mirror of
https://github.com/rust-lang/rust.git
synced 2026-06-02 15:56:09 +03:00
Auto merge of #30726 - GuillaumeGomez:compile-fail, r=brson
r? @brson cc @alexcrichton I still need to add error code explanation test with this, but I can't figure out a way to generate the `.md` files in order to test example source codes. Will fix #27328.
This commit is contained in:
+8
-1
@@ -62,6 +62,7 @@ RUSTBOOK = $(RPATH_VAR2_T_$(CFG_BUILD)_H_$(CFG_BUILD)) $(RUSTBOOK_EXE)
|
||||
# The error-index-generator executable...
|
||||
ERR_IDX_GEN_EXE = $(HBIN2_H_$(CFG_BUILD))/error-index-generator$(X_$(CFG_BUILD))
|
||||
ERR_IDX_GEN = $(RPATH_VAR2_T_$(CFG_BUILD)_H_$(CFG_BUILD)) $(ERR_IDX_GEN_EXE)
|
||||
ERR_IDX_GEN_MD = $(RPATH_VAR2_T_$(CFG_BUILD)_H_$(CFG_BUILD)) $(ERR_IDX_GEN_EXE) markdown
|
||||
|
||||
D := $(S)src/doc
|
||||
|
||||
@@ -217,6 +218,12 @@ doc/style/index.html: $(RUSTBOOK_EXE) $(wildcard $(S)/src/doc/style/*.md) | doc/
|
||||
|
||||
error-index: doc/error-index.html
|
||||
|
||||
doc/error-index.html: $(ERR_IDX_GEN_EXE) | doc/
|
||||
# Metadata used to generate the index is created as a side effect of
|
||||
# the build so this depends on every crate being up to date.
|
||||
doc/error-index.html: $(ERR_IDX_GEN_EXE) $(CSREQ$(2)_T_$(CFG_BUILD)_H_$(CFG_BUILD)) | doc/
|
||||
$(Q)$(call E, error-index-generator: $@)
|
||||
$(Q)$(ERR_IDX_GEN)
|
||||
|
||||
doc/error-index.md: $(ERR_IDX_GEN_EXE) $(CSREQ$(2)_T_$(CFG_BUILD)_H_$(CFG_BUILD)) | doc/
|
||||
$(Q)$(call E, error-index-generator: $@)
|
||||
$(Q)$(ERR_IDX_GEN_MD)
|
||||
|
||||
+33
-10
@@ -298,14 +298,14 @@ check-stage$(1)-T-$(2)-H-$(3)-exec: \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-rfail-exec \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-cfail-exec \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-pfail-exec \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-rpass-valgrind-exec \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-rpass-full-exec \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-rfail-full-exec \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-rpass-valgrind-exec \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-rpass-full-exec \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-rfail-full-exec \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-cfail-full-exec \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-rmake-exec \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-rustdocck-exec \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-crates-exec \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-doc-crates-exec \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-crates-exec \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-doc-crates-exec \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-debuginfo-gdb-exec \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-debuginfo-lldb-exec \
|
||||
check-stage$(1)-T-$(2)-H-$(3)-codegen-exec \
|
||||
@@ -673,8 +673,8 @@ CTEST_DEPS_debuginfo-lldb_$(1)-T-$(2)-H-$(3) = $$(DEBUGINFO_LLDB_TESTS) \
|
||||
CTEST_DEPS_codegen_$(1)-T-$(2)-H-$(3) = $$(CODEGEN_TESTS)
|
||||
CTEST_DEPS_codegen-units_$(1)-T-$(2)-H-$(3) = $$(CODEGEN_UNITS_TESTS)
|
||||
CTEST_DEPS_rustdocck_$(1)-T-$(2)-H-$(3) = $$(RUSTDOCCK_TESTS) \
|
||||
$$(HBIN$(1)_H_$(3))/rustdoc$$(X_$(3)) \
|
||||
$(S)src/etc/htmldocck.py
|
||||
$$(HBIN$(1)_H_$(3))/rustdoc$$(X_$(3)) \
|
||||
$(S)src/etc/htmldocck.py
|
||||
|
||||
endef
|
||||
|
||||
@@ -892,6 +892,28 @@ $(foreach host,$(CFG_HOST), \
|
||||
$(foreach crate,$(TEST_DOC_CRATES), \
|
||||
$(eval $(call DEF_CRATE_DOC_TEST,$(stage),$(target),$(host),$(crate)))))))
|
||||
|
||||
define DEF_DOC_TEST_ERROR_INDEX
|
||||
|
||||
check-stage$(1)-T-$(2)-H-$(3)-doc-error-index-exec: $$(call TEST_OK_FILE,$(1),$(2),$(3),doc-error-index)
|
||||
|
||||
ifeq ($(2),$$(CFG_BUILD))
|
||||
$$(call TEST_OK_FILE,$(1),$(2),$(3),doc-error-index): \
|
||||
$$(TEST_SREQ$(1)_T_$(2)_H_$(3)) \
|
||||
doc/error-index.md
|
||||
$$(Q)touch $$@.start_time
|
||||
$$(RUSTDOC_$(1)_T_$(2)_H_$(3)) --test doc/error-index.md
|
||||
$$(Q)touch -r $$@.start_time $$@ && rm $$@.start_time
|
||||
else
|
||||
$$(call TEST_OK_FILE,$(1),$(2),$(3),doc-error-index):
|
||||
$$(Q)touch $$@
|
||||
endif
|
||||
endef
|
||||
|
||||
$(foreach host,$(CFG_HOST), \
|
||||
$(foreach target,$(CFG_TARGET), \
|
||||
$(foreach stage,$(STAGES), \
|
||||
$(eval $(call DEF_DOC_TEST_ERROR_INDEX,$(stage),$(target),$(host))))))
|
||||
|
||||
######################################################################
|
||||
# Shortcut rules
|
||||
######################################################################
|
||||
@@ -901,7 +923,7 @@ TEST_GROUPS = \
|
||||
$(foreach crate,$(TEST_CRATES),$(crate)) \
|
||||
$(foreach crate,$(TEST_DOC_CRATES),doc-crate-$(crate)) \
|
||||
rpass \
|
||||
rpass-valgrind \
|
||||
rpass-valgrind \
|
||||
rpass-full \
|
||||
rfail-full \
|
||||
cfail-full \
|
||||
@@ -918,7 +940,7 @@ TEST_GROUPS = \
|
||||
$(foreach docname,$(DOC_NAMES),doc-$(docname)) \
|
||||
pretty \
|
||||
pretty-rpass \
|
||||
pretty-rpass-valgrind \
|
||||
pretty-rpass-valgrind \
|
||||
pretty-rpass-full \
|
||||
pretty-rfail-full \
|
||||
pretty-rfail \
|
||||
@@ -987,7 +1009,8 @@ define DEF_CHECK_DOC_FOR_STAGE
|
||||
check-stage$(1)-docs: $$(foreach docname,$$(DOC_NAMES), \
|
||||
check-stage$(1)-T-$$(CFG_BUILD)-H-$$(CFG_BUILD)-doc-$$(docname)) \
|
||||
$$(foreach crate,$$(TEST_DOC_CRATES), \
|
||||
check-stage$(1)-T-$$(CFG_BUILD)-H-$$(CFG_BUILD)-doc-crate-$$(crate))
|
||||
check-stage$(1)-T-$$(CFG_BUILD)-H-$$(CFG_BUILD)-doc-crate-$$(crate)) \
|
||||
check-stage$(1)-T-$$(CFG_BUILD)-H-$$(CFG_BUILD)-doc-error-index-exec
|
||||
endef
|
||||
|
||||
$(foreach stage,$(STAGES), \
|
||||
|
||||
@@ -21,11 +21,123 @@
|
||||
use std::path::Path;
|
||||
use std::error::Error;
|
||||
|
||||
use syntax::diagnostics::metadata::{get_metadata_dir, ErrorMetadataMap};
|
||||
use syntax::diagnostics::metadata::{get_metadata_dir, ErrorMetadataMap, ErrorMetadata};
|
||||
|
||||
use rustdoc::html::markdown::Markdown;
|
||||
use rustc_serialize::json;
|
||||
|
||||
enum OutputFormat {
|
||||
HTML(HTMLFormatter),
|
||||
Markdown(MarkdownFormatter),
|
||||
Unknown(String),
|
||||
}
|
||||
|
||||
impl OutputFormat {
|
||||
fn from(format: &str) -> OutputFormat {
|
||||
match &*format.to_lowercase() {
|
||||
"html" => OutputFormat::HTML(HTMLFormatter),
|
||||
"markdown" => OutputFormat::Markdown(MarkdownFormatter),
|
||||
s => OutputFormat::Unknown(s.to_owned()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trait Formatter {
|
||||
fn header(&self, output: &mut Write) -> Result<(), Box<Error>>;
|
||||
fn title(&self, output: &mut Write) -> Result<(), Box<Error>>;
|
||||
fn error_code_block(&self, output: &mut Write, info: &ErrorMetadata,
|
||||
err_code: &str) -> Result<(), Box<Error>>;
|
||||
fn footer(&self, output: &mut Write) -> Result<(), Box<Error>>;
|
||||
}
|
||||
|
||||
struct HTMLFormatter;
|
||||
struct MarkdownFormatter;
|
||||
|
||||
impl Formatter for HTMLFormatter {
|
||||
fn header(&self, output: &mut Write) -> Result<(), Box<Error>> {
|
||||
try!(write!(output, r##"<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Rust Compiler Error Index</title>
|
||||
<meta charset="utf-8">
|
||||
<!-- Include rust.css after main.css so its rules take priority. -->
|
||||
<link rel="stylesheet" type="text/css" href="main.css"/>
|
||||
<link rel="stylesheet" type="text/css" href="rust.css"/>
|
||||
<style>
|
||||
.error-undescribed {{
|
||||
display: none;
|
||||
}}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
"##));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn title(&self, output: &mut Write) -> Result<(), Box<Error>> {
|
||||
try!(write!(output, "<h1>Rust Compiler Error Index</h1>\n"));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn error_code_block(&self, output: &mut Write, info: &ErrorMetadata,
|
||||
err_code: &str) -> Result<(), Box<Error>> {
|
||||
// Enclose each error in a div so they can be shown/hidden en masse.
|
||||
let desc_desc = match info.description {
|
||||
Some(_) => "error-described",
|
||||
None => "error-undescribed",
|
||||
};
|
||||
let use_desc = match info.use_site {
|
||||
Some(_) => "error-used",
|
||||
None => "error-unused",
|
||||
};
|
||||
try!(write!(output, "<div class=\"{} {}\">", desc_desc, use_desc));
|
||||
|
||||
// Error title (with self-link).
|
||||
try!(write!(output,
|
||||
"<h2 id=\"{0}\" class=\"section-header\"><a href=\"#{0}\">{0}</a></h2>\n",
|
||||
err_code));
|
||||
|
||||
// Description rendered as markdown.
|
||||
match info.description {
|
||||
Some(ref desc) => try!(write!(output, "{}", Markdown(desc))),
|
||||
None => try!(write!(output, "<p>No description.</p>\n")),
|
||||
}
|
||||
|
||||
try!(write!(output, "</div>\n"));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn footer(&self, output: &mut Write) -> Result<(), Box<Error>> {
|
||||
try!(write!(output, "</body>\n</html>"));
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Formatter for MarkdownFormatter {
|
||||
#[allow(unused_variables)]
|
||||
fn header(&self, output: &mut Write) -> Result<(), Box<Error>> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn title(&self, output: &mut Write) -> Result<(), Box<Error>> {
|
||||
try!(write!(output, "# Rust Compiler Error Index\n"));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn error_code_block(&self, output: &mut Write, info: &ErrorMetadata,
|
||||
err_code: &str) -> Result<(), Box<Error>> {
|
||||
Ok(match info.description {
|
||||
Some(ref desc) => try!(write!(output, "## {}\n{}\n", err_code, desc)),
|
||||
None => (),
|
||||
})
|
||||
}
|
||||
|
||||
#[allow(unused_variables)]
|
||||
fn footer(&self, output: &mut Write) -> Result<(), Box<Error>> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Load all the metadata files from `metadata_dir` into an in-memory map.
|
||||
fn load_all_errors(metadata_dir: &Path) -> Result<ErrorMetadataMap, Box<Error>> {
|
||||
let mut all_errors = BTreeMap::new();
|
||||
@@ -47,71 +159,45 @@ fn load_all_errors(metadata_dir: &Path) -> Result<ErrorMetadataMap, Box<Error>>
|
||||
}
|
||||
|
||||
/// Output an HTML page for the errors in `err_map` to `output_path`.
|
||||
fn render_error_page(err_map: &ErrorMetadataMap, output_path: &Path) -> Result<(), Box<Error>> {
|
||||
fn render_error_page<T: Formatter>(err_map: &ErrorMetadataMap, output_path: &Path,
|
||||
formatter: T) -> Result<(), Box<Error>> {
|
||||
let mut output_file = try!(File::create(output_path));
|
||||
|
||||
try!(write!(&mut output_file,
|
||||
r##"<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Rust Compiler Error Index</title>
|
||||
<meta charset="utf-8">
|
||||
<!-- Include rust.css after main.css so its rules take priority. -->
|
||||
<link rel="stylesheet" type="text/css" href="main.css"/>
|
||||
<link rel="stylesheet" type="text/css" href="rust.css"/>
|
||||
<style>
|
||||
.error-undescribed {{
|
||||
display: none;
|
||||
}}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
"##
|
||||
));
|
||||
|
||||
try!(write!(&mut output_file, "<h1>Rust Compiler Error Index</h1>\n"));
|
||||
try!(formatter.header(&mut output_file));
|
||||
try!(formatter.title(&mut output_file));
|
||||
|
||||
for (err_code, info) in err_map {
|
||||
// Enclose each error in a div so they can be shown/hidden en masse.
|
||||
let desc_desc = match info.description {
|
||||
Some(_) => "error-described",
|
||||
None => "error-undescribed",
|
||||
};
|
||||
let use_desc = match info.use_site {
|
||||
Some(_) => "error-used",
|
||||
None => "error-unused",
|
||||
};
|
||||
try!(write!(&mut output_file, "<div class=\"{} {}\">", desc_desc, use_desc));
|
||||
|
||||
// Error title (with self-link).
|
||||
try!(write!(&mut output_file,
|
||||
"<h2 id=\"{0}\" class=\"section-header\"><a href=\"#{0}\">{0}</a></h2>\n",
|
||||
err_code));
|
||||
|
||||
// Description rendered as markdown.
|
||||
match info.description {
|
||||
Some(ref desc) => try!(write!(&mut output_file, "{}", Markdown(desc))),
|
||||
None => try!(write!(&mut output_file, "<p>No description.</p>\n")),
|
||||
}
|
||||
|
||||
try!(write!(&mut output_file, "</div>\n"));
|
||||
try!(formatter.error_code_block(&mut output_file, info, err_code));
|
||||
}
|
||||
|
||||
try!(write!(&mut output_file, "</body>\n</html>"));
|
||||
|
||||
Ok(())
|
||||
formatter.footer(&mut output_file)
|
||||
}
|
||||
|
||||
fn main_with_result() -> Result<(), Box<Error>> {
|
||||
fn main_with_result(format: OutputFormat) -> Result<(), Box<Error>> {
|
||||
let build_arch = try!(env::var("CFG_BUILD"));
|
||||
let metadata_dir = get_metadata_dir(&build_arch);
|
||||
let err_map = try!(load_all_errors(&metadata_dir));
|
||||
try!(render_error_page(&err_map, Path::new("doc/error-index.html")));
|
||||
match format {
|
||||
OutputFormat::Unknown(s) => panic!("Unknown output format: {}", s),
|
||||
OutputFormat::HTML(h) => try!(render_error_page(&err_map,
|
||||
Path::new("doc/error-index.html"),
|
||||
h)),
|
||||
OutputFormat::Markdown(m) => try!(render_error_page(&err_map,
|
||||
Path::new("doc/error-index.md"),
|
||||
m)),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn parse_args() -> OutputFormat {
|
||||
for arg in env::args().skip(1) {
|
||||
return OutputFormat::from(&arg);
|
||||
}
|
||||
OutputFormat::from("html")
|
||||
}
|
||||
|
||||
fn main() {
|
||||
if let Err(e) = main_with_result() {
|
||||
if let Err(e) = main_with_result(parse_args()) {
|
||||
panic!("{}", e.description());
|
||||
}
|
||||
}
|
||||
|
||||
+208
-120
@@ -25,7 +25,7 @@
|
||||
|
||||
For example, the following `match` block has too many arms:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
match foo {
|
||||
Some(bar) => {/* ... */}
|
||||
None => {/* ... */}
|
||||
@@ -50,6 +50,8 @@
|
||||
An example of an empty type is `enum Empty { }`. So, the following will work:
|
||||
|
||||
```
|
||||
enum Empty {}
|
||||
|
||||
fn foo(x: Empty) {
|
||||
match x {
|
||||
// empty
|
||||
@@ -59,7 +61,9 @@ fn foo(x: Empty) {
|
||||
|
||||
However, this won't:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
enum Empty {}
|
||||
|
||||
fn foo(x: Option<String>) {
|
||||
match x {
|
||||
// empty
|
||||
@@ -72,12 +76,14 @@ fn foo(x: Option<String>) {
|
||||
Not-a-Number (NaN) values cannot be compared for equality and hence can never
|
||||
match the input to a match expression. So, the following will not compile:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
const NAN: f32 = 0.0 / 0.0;
|
||||
|
||||
let number = 0.1f32;
|
||||
|
||||
match number {
|
||||
NAN => { /* ... */ },
|
||||
// ...
|
||||
_ => {}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -85,10 +91,11 @@ fn foo(x: Option<String>) {
|
||||
guard, like so:
|
||||
|
||||
```
|
||||
let number = 0.1f32;
|
||||
|
||||
match number {
|
||||
// ...
|
||||
x if x.is_nan() => { /* ... */ }
|
||||
// ...
|
||||
_ => {}
|
||||
}
|
||||
```
|
||||
"##,
|
||||
@@ -120,15 +127,16 @@ fn foo(x: Option<String>) {
|
||||
into a variable called `op_string` while simultaneously requiring the inner
|
||||
String to be moved into a variable called `s`.
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
let x = Some("s".to_string());
|
||||
|
||||
match x {
|
||||
op_string @ Some(s) => ...
|
||||
None => ...
|
||||
op_string @ Some(s) => {},
|
||||
None => {},
|
||||
}
|
||||
```
|
||||
|
||||
See also Error 303.
|
||||
See also the error E0303.
|
||||
"##,
|
||||
|
||||
E0008: r##"
|
||||
@@ -137,10 +145,10 @@ fn foo(x: Option<String>) {
|
||||
referenced in the pattern guard code. Doing so however would prevent the name
|
||||
from being available in the body of the match arm. Consider the following:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
match Some("hi".to_string()) {
|
||||
Some(s) if s.len() == 0 => // use s.
|
||||
...
|
||||
Some(s) if s.len() == 0 => {}, // use s.
|
||||
_ => {},
|
||||
}
|
||||
```
|
||||
|
||||
@@ -151,11 +159,11 @@ fn foo(x: Option<String>) {
|
||||
innocuous, the problem is most clear when considering functions that take their
|
||||
argument by value.
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
match Some("hi".to_string()) {
|
||||
Some(s) if { drop(s); false } => (),
|
||||
Some(s) => // use s.
|
||||
...
|
||||
Some(s) => {}, // use s.
|
||||
_ => {},
|
||||
}
|
||||
```
|
||||
|
||||
@@ -174,7 +182,7 @@ fn foo(x: Option<String>) {
|
||||
|
||||
Wrong example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
struct X { x: (), }
|
||||
|
||||
let x = Some((X { x: () }, X { x: () }));
|
||||
@@ -220,7 +228,7 @@ struct X { x: (), }
|
||||
remainder of a zero divisor) in a static or constant expression. Erroneous
|
||||
code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
const X: i32 = 42 / 0;
|
||||
// error: attempted to divide by zero in a constant expression
|
||||
```
|
||||
@@ -267,7 +275,7 @@ trait Foo where Self: Sized {
|
||||
|
||||
This happens when a trait has a method like the following:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
trait Trait {
|
||||
fn foo(&self) -> Self;
|
||||
}
|
||||
@@ -291,7 +299,11 @@ fn foo(&self) -> Self {
|
||||
In such a case, the compiler cannot predict the return type of `foo()` in a
|
||||
situation like the following:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
trait Trait {
|
||||
fn foo(&self) -> Self;
|
||||
}
|
||||
|
||||
fn call_foo(x: Box<Trait>) {
|
||||
let y = x.foo(); // What type is y?
|
||||
// ...
|
||||
@@ -324,11 +336,13 @@ trait Trait {
|
||||
trait Trait {
|
||||
fn foo(&self);
|
||||
}
|
||||
|
||||
impl Trait for String {
|
||||
fn foo(&self) {
|
||||
// implementation 1
|
||||
}
|
||||
}
|
||||
|
||||
impl Trait for u8 {
|
||||
fn foo(&self) {
|
||||
// implementation 2
|
||||
@@ -351,7 +365,7 @@ fn foo<T>(x: T) {
|
||||
}
|
||||
```
|
||||
|
||||
the machine code for `foo::<u8>()`, `foo::<bool>()`, `foo::<String>()`, or any
|
||||
The machine code for `foo::<u8>()`, `foo::<bool>()`, `foo::<String>()`, or any
|
||||
other type substitution is different. Hence the compiler generates the
|
||||
implementation on-demand. If you call `foo()` with a `bool` parameter, the
|
||||
compiler will only generate code for `foo::<bool>()`. When we have additional
|
||||
@@ -373,22 +387,25 @@ trait Trait {
|
||||
fn foo<T>(&self, on: T);
|
||||
// more methods
|
||||
}
|
||||
|
||||
impl Trait for String {
|
||||
fn foo<T>(&self, on: T) {
|
||||
// implementation 1
|
||||
}
|
||||
}
|
||||
|
||||
impl Trait for u8 {
|
||||
fn foo<T>(&self, on: T) {
|
||||
// implementation 2
|
||||
}
|
||||
}
|
||||
|
||||
// 8 more implementations
|
||||
```
|
||||
|
||||
Now, if we have the following code:
|
||||
|
||||
```
|
||||
```ignore
|
||||
fn call_foo(thing: Box<Trait>) {
|
||||
thing.foo(true); // this could be any one of the 8 types above
|
||||
thing.foo(1);
|
||||
@@ -396,7 +413,7 @@ fn call_foo(thing: Box<Trait>) {
|
||||
}
|
||||
```
|
||||
|
||||
we don't just need to create a table of all implementations of all methods of
|
||||
We don't just need to create a table of all implementations of all methods of
|
||||
`Trait`, we need to create such a table, for each different type fed to
|
||||
`foo()`. In this case this turns out to be (10 types implementing `Trait`)*(3
|
||||
types being fed to `foo()`) = 30 implementations!
|
||||
@@ -422,7 +439,7 @@ trait object (e.g. if `T: OtherTrait`, use `on: Box<OtherTrait>`). If the number
|
||||
### Method has no receiver
|
||||
|
||||
Methods that do not take a `self` parameter can't be called since there won't be
|
||||
a way to get a pointer to the method table for them
|
||||
a way to get a pointer to the method table for them.
|
||||
|
||||
```
|
||||
trait Foo {
|
||||
@@ -446,7 +463,7 @@ trait Foo {
|
||||
This is similar to the second sub-error, but subtler. It happens in situations
|
||||
like the following:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
trait Super<A> {}
|
||||
|
||||
trait Trait: Super<Self> {
|
||||
@@ -488,7 +505,7 @@ trait Super<A> {
|
||||
|
||||
Consider the following erroneous definition of a type for a list of bytes:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
// error, invalid recursive struct type
|
||||
struct ListNode {
|
||||
head: u8,
|
||||
@@ -521,7 +538,7 @@ struct ListNode {
|
||||
You tried to give a type parameter to a type which doesn't need it. Erroneous
|
||||
code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
type X = u32<i32>; // error: type parameters are not allowed on this type
|
||||
```
|
||||
|
||||
@@ -542,7 +559,7 @@ struct ListNode {
|
||||
You tried to give a lifetime parameter to a type which doesn't need it.
|
||||
Erroneous code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
type X = u32<'static>; // error: lifetime parameters are not allowed on
|
||||
// this type
|
||||
```
|
||||
@@ -605,8 +622,8 @@ fn main() {
|
||||
|
||||
So, for example, the following is not allowed:
|
||||
|
||||
```
|
||||
struct Foo<T>(Vec<T>)
|
||||
```compile_fail
|
||||
struct Foo<T>(Vec<T>);
|
||||
|
||||
fn foo<T>(x: Vec<T>) {
|
||||
// we are transmuting between Vec<T> and Foo<T> here
|
||||
@@ -631,9 +648,11 @@ fn foo<T>(x: Vec<T>) {
|
||||
possible type substitution. It's possible to use traits to do this cleanly,
|
||||
for example:
|
||||
|
||||
```
|
||||
```ignore
|
||||
struct Foo<T>(Vec<T>);
|
||||
|
||||
trait MyTransmutableType {
|
||||
fn transmute(Vec<Self>) -> Foo<Self>
|
||||
fn transmute(Vec<Self>) -> Foo<Self>;
|
||||
}
|
||||
|
||||
impl MyTransmutableType for u8 {
|
||||
@@ -641,11 +660,13 @@ fn transmute(x: Foo<u8>) -> Vec<u8> {
|
||||
transmute(x)
|
||||
}
|
||||
}
|
||||
|
||||
impl MyTransmutableType for String {
|
||||
fn transmute(x: Foo<String>) -> Vec<String> {
|
||||
transmute(x)
|
||||
}
|
||||
}
|
||||
|
||||
// ... more impls for the types you intend to transmute
|
||||
|
||||
fn foo<T: MyTransmutableType>(x: Vec<T>) {
|
||||
@@ -660,7 +681,7 @@ fn foo<T: MyTransmutableType>(x: Vec<T>) {
|
||||
|
||||
It is also possible to manually transmute:
|
||||
|
||||
```
|
||||
```ignore
|
||||
ptr::read(&v as *const _ as *const SomeType) // `v` transmuted to `SomeType`
|
||||
```
|
||||
|
||||
@@ -696,9 +717,10 @@ fn foo<T: MyTransmutableType>(x: Vec<T>) {
|
||||
|
||||
```
|
||||
static FORTY_TWO: i32 = 42;
|
||||
|
||||
match Some(42) {
|
||||
Some(x) if x == FORTY_TWO => ...
|
||||
...
|
||||
Some(x) if x == FORTY_TWO => {}
|
||||
_ => {}
|
||||
}
|
||||
```
|
||||
"##,
|
||||
@@ -708,7 +730,7 @@ fn foo<T: MyTransmutableType>(x: Vec<T>) {
|
||||
match was successful. If the match is irrefutable (when it cannot fail to
|
||||
match), use a regular `let`-binding instead. For instance:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
struct Irrefutable(i32);
|
||||
let irr = Irrefutable(0);
|
||||
|
||||
@@ -717,8 +739,14 @@ fn foo<T: MyTransmutableType>(x: Vec<T>) {
|
||||
// This body will always be executed.
|
||||
foo(x);
|
||||
}
|
||||
```
|
||||
|
||||
Try this instead:
|
||||
|
||||
```ignore
|
||||
struct Irrefutable(i32);
|
||||
let irr = Irrefutable(0);
|
||||
|
||||
// Try this instead:
|
||||
let Irrefutable(x) = irr;
|
||||
foo(x);
|
||||
```
|
||||
@@ -729,7 +757,7 @@ fn foo<T: MyTransmutableType>(x: Vec<T>) {
|
||||
match was successful. If the match is irrefutable (when it cannot fail to
|
||||
match), use a regular `let`-binding inside a `loop` instead. For instance:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
struct Irrefutable(i32);
|
||||
let irr = Irrefutable(0);
|
||||
|
||||
@@ -738,7 +766,12 @@ fn foo<T: MyTransmutableType>(x: Vec<T>) {
|
||||
...
|
||||
}
|
||||
|
||||
// Try this instead:
|
||||
Try this instead:
|
||||
|
||||
```
|
||||
struct Irrefutable(i32);
|
||||
let irr = Irrefutable(0);
|
||||
|
||||
loop {
|
||||
let Irrefutable(x) = irr;
|
||||
...
|
||||
@@ -752,16 +785,23 @@ fn foo<T: MyTransmutableType>(x: Vec<T>) {
|
||||
```
|
||||
enum Method {
|
||||
GET,
|
||||
POST
|
||||
POST,
|
||||
}
|
||||
```
|
||||
|
||||
you would match it using:
|
||||
You would match it using:
|
||||
|
||||
```
|
||||
enum Method {
|
||||
GET,
|
||||
POST,
|
||||
}
|
||||
|
||||
let m = Method::GET;
|
||||
|
||||
match m {
|
||||
Method::GET => ...
|
||||
Method::POST => ...
|
||||
Method::GET => {},
|
||||
Method::POST => {},
|
||||
}
|
||||
```
|
||||
|
||||
@@ -772,7 +812,7 @@ enum Method {
|
||||
Qualified names are good practice, and most code works well with them. But if
|
||||
you prefer them unqualified, you can import the variants into scope:
|
||||
|
||||
```
|
||||
```ignore
|
||||
use Method::*;
|
||||
enum Method { GET, POST }
|
||||
```
|
||||
@@ -780,7 +820,7 @@ enum Method { GET, POST }
|
||||
If you want others to be able to import variants from your module directly, use
|
||||
`pub use`:
|
||||
|
||||
```
|
||||
```ignore
|
||||
pub use Method::*;
|
||||
enum Method { GET, POST }
|
||||
```
|
||||
@@ -790,7 +830,7 @@ enum Method { GET, POST }
|
||||
An associated type binding was done outside of the type parameter declaration
|
||||
and `where` clause. Erroneous code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
pub trait Foo {
|
||||
type A;
|
||||
fn boo(&self) -> <Self as Foo>::A;
|
||||
@@ -810,13 +850,13 @@ fn baz<I>(x: &<I as Foo<A=Bar>>::A) {}
|
||||
To solve this error, please move the type bindings in the type parameter
|
||||
declaration:
|
||||
|
||||
```
|
||||
```ignore
|
||||
fn baz<I: Foo<A=Bar>>(x: &<I as Foo>::A) {} // ok!
|
||||
```
|
||||
|
||||
or in the `where` clause:
|
||||
Or in the `where` clause:
|
||||
|
||||
```
|
||||
```ignore
|
||||
fn baz<I>(x: &<I as Foo>::A) where I: Foo<A=Bar> {}
|
||||
```
|
||||
"##,
|
||||
@@ -827,7 +867,7 @@ fn baz<I>(x: &<I as Foo>::A) where I: Foo<A=Bar> {}
|
||||
|
||||
These two examples illustrate the problem:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
// error, use of undeclared lifetime name `'a`
|
||||
fn foo(x: &'a str) { }
|
||||
|
||||
@@ -840,7 +880,7 @@ struct Foo {
|
||||
These can be fixed by declaring lifetime parameters:
|
||||
|
||||
```
|
||||
fn foo<'a>(x: &'a str) { }
|
||||
fn foo<'a>(x: &'a str) {}
|
||||
|
||||
struct Foo<'a> {
|
||||
x: &'a str,
|
||||
@@ -853,7 +893,7 @@ struct Foo<'a> {
|
||||
because the `'static` lifetime is a special built-in lifetime name denoting
|
||||
the lifetime of the entire program, this is an error:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
// error, invalid lifetime parameter name `'static`
|
||||
fn foo<'static>(x: &'static str) { }
|
||||
```
|
||||
@@ -863,7 +903,7 @@ fn foo<'static>(x: &'static str) { }
|
||||
A lifetime name cannot be declared more than once in the same scope. For
|
||||
example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
// error, lifetime name `'a` declared twice in the same scope
|
||||
fn foo<'a, 'b, 'a>(x: &'a str, y: &'b str) { }
|
||||
```
|
||||
@@ -872,7 +912,7 @@ fn foo<'a, 'b, 'a>(x: &'a str, y: &'b str) { }
|
||||
E0264: r##"
|
||||
An unknown external lang item was used. Erroneous code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
#![feature(lang_items)]
|
||||
|
||||
extern "C" {
|
||||
@@ -896,9 +936,9 @@ fn foo<'a, 'b, 'a>(x: &'a str, y: &'b str) { }
|
||||
|
||||
E0269: r##"
|
||||
Functions must eventually return a value of their return type. For example, in
|
||||
the following function
|
||||
the following function:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
fn foo(x: u8) -> u8 {
|
||||
if x > 0 {
|
||||
x // alternatively, `return x`
|
||||
@@ -907,7 +947,7 @@ fn foo(x: u8) -> u8 {
|
||||
}
|
||||
```
|
||||
|
||||
if the condition is true, the value `x` is returned, but if the condition is
|
||||
If the condition is true, the value `x` is returned, but if the condition is
|
||||
false, control exits the `if` block and reaches a place where nothing is being
|
||||
returned. All possible control paths must eventually return a `u8`, which is not
|
||||
happening here.
|
||||
@@ -915,7 +955,7 @@ fn foo(x: u8) -> u8 {
|
||||
An easy fix for this in a complicated function is to specify a default return
|
||||
value, if possible:
|
||||
|
||||
```
|
||||
```ignore
|
||||
fn foo(x: u8) -> u8 {
|
||||
if x > 0 {
|
||||
x // alternatively, `return x`
|
||||
@@ -935,7 +975,7 @@ fn foo(x: u8) -> u8 {
|
||||
|
||||
For example, the following functions never return:
|
||||
|
||||
```
|
||||
```no_run
|
||||
fn foo() -> ! {
|
||||
loop {}
|
||||
}
|
||||
@@ -947,18 +987,24 @@ fn bar() -> ! {
|
||||
fn baz() -> ! {
|
||||
panic!(); // this macro internally expands to a call to a diverging function
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Such functions can be used in a place where a value is expected without
|
||||
returning a value of that type, for instance:
|
||||
returning a value of that type, for instance:
|
||||
|
||||
```no_run
|
||||
fn foo() -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
||||
let x = 3;
|
||||
|
||||
```
|
||||
let y = match x {
|
||||
1 => 1,
|
||||
2 => 4,
|
||||
_ => foo() // diverging function called here
|
||||
};
|
||||
|
||||
println!("{}", y)
|
||||
```
|
||||
|
||||
@@ -967,22 +1013,29 @@ fn baz() -> ! {
|
||||
integer was expected. The `match` block will never finish executing, and any
|
||||
point where `y` (like the print statement) is needed will not be reached.
|
||||
|
||||
However, if we had a diverging function that actually does finish execution
|
||||
However, if we had a diverging function that actually does finish execution:
|
||||
|
||||
```
|
||||
fn foo() -> {
|
||||
```ignore
|
||||
fn foo() -> ! {
|
||||
loop {break;}
|
||||
}
|
||||
```
|
||||
|
||||
then we would have an unknown value for `y` in the following code:
|
||||
Then we would have an unknown value for `y` in the following code:
|
||||
|
||||
```no_run
|
||||
fn foo() -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
||||
let x = 3;
|
||||
|
||||
```
|
||||
let y = match x {
|
||||
1 => 1,
|
||||
2 => 4,
|
||||
_ => foo()
|
||||
};
|
||||
|
||||
println!("{}", y);
|
||||
```
|
||||
|
||||
@@ -1004,18 +1057,21 @@ fn foo() -> {
|
||||
|
||||
Here is a basic example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
trait Trait { type AssociatedType; }
|
||||
|
||||
fn foo<T>(t: T) where T: Trait<AssociatedType=u32> {
|
||||
println!("in foo");
|
||||
}
|
||||
|
||||
impl Trait for i8 { type AssociatedType = &'static str; }
|
||||
|
||||
foo(3_i8);
|
||||
```
|
||||
|
||||
Here is that same example again, with some explanatory comments:
|
||||
|
||||
```
|
||||
```ignore
|
||||
trait Trait { type AssociatedType; }
|
||||
|
||||
fn foo<T>(t: T) where T: Trait<AssociatedType=u32> {
|
||||
@@ -1053,12 +1109,12 @@ fn foo<T>(t: T) where T: Trait<AssociatedType=u32> {
|
||||
Here is a more subtle instance of the same problem, that can
|
||||
arise with for-loops in Rust:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
let vs: Vec<i32> = vec![1, 2, 3, 4];
|
||||
for v in &vs {
|
||||
match v {
|
||||
1 => {}
|
||||
_ => {}
|
||||
1 => {},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -1067,7 +1123,7 @@ fn foo<T>(t: T) where T: Trait<AssociatedType=u32> {
|
||||
though may be harder to see. Again, here are some
|
||||
explanatory comments for the same example:
|
||||
|
||||
```
|
||||
```ignore
|
||||
{
|
||||
let vs = vec![1, 2, 3, 4];
|
||||
|
||||
@@ -1115,10 +1171,13 @@ fn foo<T>(t: T) where T: Trait<AssociatedType=u32> {
|
||||
```
|
||||
// Basic Example:
|
||||
trait Trait { type AssociatedType; }
|
||||
|
||||
fn foo<T>(t: T) where T: Trait<AssociatedType = &'static str> {
|
||||
println!("in foo");
|
||||
}
|
||||
|
||||
impl Trait for i8 { type AssociatedType = &'static str; }
|
||||
|
||||
foo(3_i8);
|
||||
|
||||
// For-Loop Example:
|
||||
@@ -1138,7 +1197,7 @@ fn foo<T>(t: T) where T: Trait<AssociatedType = &'static str> {
|
||||
position that needs that trait. For example, when the following code is
|
||||
compiled:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
fn foo<T: Index<u8>>(x: T){}
|
||||
|
||||
#[rustc_on_unimplemented = "the type `{Self}` cannot be indexed by `{Idx}`"]
|
||||
@@ -1168,7 +1227,7 @@ trait Index<Idx> { ... }
|
||||
position that needs that trait. For example, when the following code is
|
||||
compiled:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
fn foo<T: Index<u8>>(x: T){}
|
||||
|
||||
#[rustc_on_unimplemented = "the type `{Self}` cannot be indexed by `{Idx}`"]
|
||||
@@ -1196,7 +1255,7 @@ trait Index<Idx> { ... }
|
||||
position that needs that trait. For example, when the following code is
|
||||
compiled:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
fn foo<T: Index<u8>>(x: T){}
|
||||
|
||||
#[rustc_on_unimplemented = "the type `{Self}` cannot be indexed by `{Idx}`"]
|
||||
@@ -1218,9 +1277,9 @@ trait Index<Idx> { ... }
|
||||
before it could be evaluated. Often this means that there is unbounded recursion
|
||||
in resolving some type bounds.
|
||||
|
||||
For example, in the following code
|
||||
For example, in the following code:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
trait Foo {}
|
||||
|
||||
struct Bar<T>(T);
|
||||
@@ -1228,7 +1287,7 @@ trait Foo {}
|
||||
impl<T> Foo for T where Bar<T>: Foo {}
|
||||
```
|
||||
|
||||
to determine if a `T` is `Foo`, we need to check if `Bar<T>` is `Foo`. However,
|
||||
To determine if a `T` is `Foo`, we need to check if `Bar<T>` is `Foo`. However,
|
||||
to do this check, we need to determine that `Bar<Bar<T>>` is `Foo`. To determine
|
||||
this, we check if `Bar<Bar<Bar<T>>>` is `Foo`, and so on. This is clearly a
|
||||
recursive requirement that can't be resolved directly.
|
||||
@@ -1240,13 +1299,13 @@ impl<T> Foo for T where Bar<T>: Foo {}
|
||||
This error occurs when a bound in an implementation of a trait does not match
|
||||
the bounds specified in the original trait. For example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
trait Foo {
|
||||
fn foo<T>(x: T);
|
||||
fn foo<T>(x: T);
|
||||
}
|
||||
|
||||
impl Foo for bool {
|
||||
fn foo<T>(x: T) where T: Copy {}
|
||||
fn foo<T>(x: T) where T: Copy {}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1262,7 +1321,7 @@ fn foo<T>(x: T) where T: Copy {}
|
||||
You tried to use a type which doesn't implement some trait in a place which
|
||||
expected that trait. Erroneous code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
// here we declare the Foo trait with a bar method
|
||||
trait Foo {
|
||||
fn bar(&self);
|
||||
@@ -1310,7 +1369,7 @@ fn main() {
|
||||
which expected that trait. This error typically occurs when working with
|
||||
`Fn`-based types. Erroneous code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
fn foo<F: Fn()>(x: F) { }
|
||||
|
||||
fn main() {
|
||||
@@ -1336,7 +1395,7 @@ fn main() {
|
||||
implemented by `Vec` and `String` among others. Consider the following snippet
|
||||
that reverses the characters of a string:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
let x = "hello".chars().rev().collect();
|
||||
```
|
||||
|
||||
@@ -1373,9 +1432,9 @@ fn main() {
|
||||
case it is not always possible to use a type annotation, because all candidates
|
||||
have the same return type. For instance:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
struct Foo<T> {
|
||||
// Some fields omitted.
|
||||
num: T,
|
||||
}
|
||||
|
||||
impl<T> Foo<T> {
|
||||
@@ -1399,17 +1458,19 @@ fn baz() {
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
trait Generator {
|
||||
fn create() -> u32;
|
||||
}
|
||||
|
||||
struct Impl;
|
||||
|
||||
impl Generator for Impl {
|
||||
fn create() -> u32 { 1 }
|
||||
}
|
||||
|
||||
struct AnotherImpl;
|
||||
|
||||
impl Generator for AnotherImpl {
|
||||
fn create() -> u32 { 2 }
|
||||
}
|
||||
@@ -1424,6 +1485,16 @@ fn main() {
|
||||
To resolve this error use the concrete type:
|
||||
|
||||
```
|
||||
trait Generator {
|
||||
fn create() -> u32;
|
||||
}
|
||||
|
||||
struct AnotherImpl;
|
||||
|
||||
impl Generator for AnotherImpl {
|
||||
fn create() -> u32 { 2 }
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let gen1 = AnotherImpl::create();
|
||||
|
||||
@@ -1448,24 +1519,36 @@ fn main() {
|
||||
loop variable, consider using a `match` or `if let` inside the loop body. For
|
||||
instance:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
let xs : Vec<Option<i32>> = vec!(Some(1), None);
|
||||
|
||||
// This fails because `None` is not covered.
|
||||
for Some(x) in xs {
|
||||
...
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
Match inside the loop instead:
|
||||
|
||||
```
|
||||
let xs : Vec<Option<i32>> = vec!(Some(1), None);
|
||||
|
||||
// Match inside the loop instead:
|
||||
for item in xs {
|
||||
match item {
|
||||
Some(x) => ...
|
||||
None => ...
|
||||
Some(x) => {},
|
||||
None => {},
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Or use `if let`:
|
||||
|
||||
```
|
||||
let xs : Vec<Option<i32>> = vec!(Some(1), None);
|
||||
|
||||
// Or use `if let`:
|
||||
for item in xs {
|
||||
if let Some(x) = item {
|
||||
...
|
||||
// ...
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -1478,7 +1561,7 @@ fn main() {
|
||||
exhaustive. For instance, the following would not match any arm if mutable
|
||||
borrows were allowed:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
match Some(()) {
|
||||
None => { },
|
||||
option if option.take().is_none() => { /* impossible, option is `Some` */ },
|
||||
@@ -1494,7 +1577,7 @@ fn main() {
|
||||
exhaustive. For instance, the following would not match any arm if assignments
|
||||
were allowed:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
match Some(()) {
|
||||
None => { },
|
||||
option if { option = None; false } { },
|
||||
@@ -1508,20 +1591,20 @@ fn main() {
|
||||
Updates to the borrow checker in a future version of Rust may remove this
|
||||
restriction, but for now patterns must be rewritten without sub-bindings.
|
||||
|
||||
```
|
||||
```ignore
|
||||
// Before.
|
||||
match Some("hi".to_string()) {
|
||||
ref op_string_ref @ Some(ref s) => ...
|
||||
None => ...
|
||||
ref op_string_ref @ Some(s) => {},
|
||||
None => {},
|
||||
}
|
||||
|
||||
// After.
|
||||
match Some("hi".to_string()) {
|
||||
Some(ref s) => {
|
||||
let op_string_ref = &Some(s);
|
||||
...
|
||||
}
|
||||
None => ...
|
||||
// ...
|
||||
},
|
||||
None => {},
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1549,7 +1632,7 @@ fn main() {
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
let x: i32 = "I am not a number!";
|
||||
// ~~~ ~~~~~~~~~~~~~~~~~~~~
|
||||
// | |
|
||||
@@ -1562,7 +1645,7 @@ fn main() {
|
||||
Another situation in which this occurs is when you attempt to use the `try!`
|
||||
macro inside a function that does not return a `Result<T, E>`:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
use std::fs::File;
|
||||
|
||||
fn main() {
|
||||
@@ -1590,14 +1673,17 @@ fn main() {
|
||||
must be as long as the data needs to be alive, and missing the constraint that
|
||||
denotes this will cause this error.
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
// This won't compile because T is not constrained, meaning the data
|
||||
// stored in it is not guaranteed to last as long as the reference
|
||||
struct Foo<'a, T> {
|
||||
foo: &'a T
|
||||
}
|
||||
```
|
||||
|
||||
// This will compile, because it has the constraint on the type parameter
|
||||
This will compile, because it has the constraint on the type parameter:
|
||||
|
||||
```
|
||||
struct Foo<'a, T: 'a> {
|
||||
foo: &'a T
|
||||
}
|
||||
@@ -1610,14 +1696,16 @@ struct Foo<'a, T: 'a> {
|
||||
must be as long as the data needs to be alive, and missing the constraint that
|
||||
denotes this will cause this error.
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
// This won't compile because T is not constrained to the static lifetime
|
||||
// the reference needs
|
||||
struct Foo<T> {
|
||||
foo: &'static T
|
||||
}
|
||||
|
||||
// This will compile, because it has the constraint on the type parameter
|
||||
This will compile, because it has the constraint on the type parameter:
|
||||
|
||||
```
|
||||
struct Foo<T: 'static> {
|
||||
foo: &'static T
|
||||
}
|
||||
@@ -1644,13 +1732,13 @@ struct Foo<T: 'static> {
|
||||
the error is reported on a call like `foo(x)`, and `foo` is
|
||||
defined as follows:
|
||||
|
||||
```
|
||||
```ignore
|
||||
fn foo(arg: &Box<SomeTrait>) { ... }
|
||||
```
|
||||
|
||||
you might change it to:
|
||||
You might change it to:
|
||||
|
||||
```
|
||||
```ignore
|
||||
fn foo<'a>(arg: &Box<SomeTrait+'a>) { ... }
|
||||
```
|
||||
|
||||
@@ -1663,7 +1751,7 @@ fn foo<'a>(arg: &Box<SomeTrait+'a>) { ... }
|
||||
E0452: r##"
|
||||
An invalid lint attribute has been given. Erroneous code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
#![allow(foo = "")] // error: malformed lint attribute
|
||||
```
|
||||
|
||||
@@ -1680,7 +1768,7 @@ fn foo<'a>(arg: &Box<SomeTrait+'a>) { ... }
|
||||
E0496: r##"
|
||||
A lifetime name is shadowing another lifetime name. Erroneous code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
struct Foo<'a> {
|
||||
a: &'a i32,
|
||||
}
|
||||
@@ -1713,7 +1801,7 @@ fn main() {
|
||||
A stability attribute was used outside of the standard library. Erroneous code
|
||||
example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
#[stable] // error: stability attributes may not be used outside of the
|
||||
// standard library
|
||||
fn foo() {}
|
||||
@@ -1729,7 +1817,7 @@ fn foo() {}
|
||||
|
||||
Examples of erroneous code:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
#[repr(C)]
|
||||
type Foo = u8;
|
||||
|
||||
@@ -1777,7 +1865,7 @@ impl Foo {
|
||||
|
||||
Examples of erroneous code:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
#[inline(always)]
|
||||
struct Foo;
|
||||
|
||||
@@ -1811,9 +1899,9 @@ impl Foo {
|
||||
// E0285, // overflow evaluation builtin bounds
|
||||
E0298, // mismatched types between arms
|
||||
E0299, // mismatched types between arms
|
||||
// E0300, // unexpanded macro
|
||||
// E0304, // expected signed integer constant
|
||||
// E0305, // expected constant
|
||||
// E0300, // unexpanded macro
|
||||
// E0304, // expected signed integer constant
|
||||
// E0305, // expected constant
|
||||
E0311, // thing may not live long enough
|
||||
E0312, // lifetime of reference outlives lifetime of borrowed content
|
||||
E0313, // lifetime of borrowed pointer outlives lifetime of captured variable
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
when that data may no longer exist. It's most commonly seen when attempting to
|
||||
return a closure:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
fn foo() -> Box<Fn(u32) -> u32> {
|
||||
let x = 0u32;
|
||||
Box::new(|y| x + y)
|
||||
@@ -30,7 +30,7 @@ fn foo() -> Box<Fn(u32) -> u32> {
|
||||
|
||||
Another situation where this might be encountered is when spawning threads:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
fn foo() {
|
||||
let x = 0u32;
|
||||
let y = 1u32;
|
||||
@@ -65,10 +65,11 @@ fn foo() -> Box<Fn(u32) -> u32> {
|
||||
E0381: r##"
|
||||
It is not allowed to use or capture an uninitialized variable. For example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
fn main() {
|
||||
let x: i32;
|
||||
let y = x; // error, use of possibly uninitialized variable
|
||||
}
|
||||
```
|
||||
|
||||
To fix this, ensure that any declared variables are initialized before being
|
||||
@@ -79,7 +80,7 @@ fn main() {
|
||||
This error occurs when an attempt is made to use a variable after its contents
|
||||
have been moved elsewhere. For example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
struct MyStruct { s: u32 }
|
||||
|
||||
fn main() {
|
||||
@@ -144,7 +145,11 @@ fn main() {
|
||||
|
||||
For example, this can happen when a drop has taken place:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
struct Foo {
|
||||
a: u32,
|
||||
}
|
||||
|
||||
let mut x = Foo { a: 1 };
|
||||
drop(x); // `x` is now uninitialized
|
||||
x.a = 2; // error, partial reinitialization of uninitialized structure `t`
|
||||
@@ -153,6 +158,10 @@ fn main() {
|
||||
This error can be fixed by fully reinitializing the structure in question:
|
||||
|
||||
```
|
||||
struct Foo {
|
||||
a: u32,
|
||||
}
|
||||
|
||||
let mut x = Foo { a: 1 };
|
||||
drop(x);
|
||||
x = Foo { a: 2 };
|
||||
@@ -163,7 +172,7 @@ fn main() {
|
||||
This error occurs when an attempt is made to reassign an immutable variable.
|
||||
For example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
fn main(){
|
||||
let x = 3;
|
||||
x = 5; // error, reassignment of immutable variable
|
||||
@@ -187,7 +196,7 @@ fn main(){
|
||||
|
||||
For example, this can happen when storing a `&mut` inside an immutable `Box`:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
let mut x: i64 = 1;
|
||||
let y: Box<_> = Box::new(&mut x);
|
||||
**y = 2; // error, cannot assign to data in an immutable container
|
||||
@@ -205,6 +214,8 @@ fn main(){
|
||||
`RefCell`:
|
||||
|
||||
```
|
||||
use std::cell::Cell;
|
||||
|
||||
let x: i64 = 1;
|
||||
let y: Box<Cell<_>> = Box::new(Cell::new(x));
|
||||
y.set(2);
|
||||
@@ -215,12 +226,12 @@ fn main(){
|
||||
This error occurs when an attempt is made to mutate or mutably reference data
|
||||
that a closure has captured immutably. Examples of this error are shown below:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
// Accepts a function or a closure that captures its environment immutably.
|
||||
// Closures passed to foo will not be able to mutate their closed-over state.
|
||||
fn foo<F: Fn()>(f: F) { }
|
||||
|
||||
// Attempts to mutate closed-over data. Error message reads:
|
||||
// Attempts to mutate closed-over data. Error message reads:
|
||||
// `cannot assign to data in a captured outer variable...`
|
||||
fn mutable() {
|
||||
let mut x = 0u32;
|
||||
@@ -254,6 +265,8 @@ fn foo<F: FnMut()>(f: F) { }
|
||||
```
|
||||
use std::cell::Cell;
|
||||
|
||||
fn foo<F: Fn()>(f: F) { }
|
||||
|
||||
fn mutable() {
|
||||
let x = Cell::new(0u32);
|
||||
foo(|| x.set(2));
|
||||
@@ -268,7 +281,7 @@ fn mutable() {
|
||||
E0499: r##"
|
||||
A variable was borrowed as mutable more than once. Erroneous code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
let mut i = 0;
|
||||
let mut x = &mut i;
|
||||
let mut a = &mut i;
|
||||
@@ -296,7 +309,7 @@ fn mutable() {
|
||||
E0507: r##"
|
||||
You tried to move out of a value which was borrowed. Erroneous code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
use std::cell::RefCell;
|
||||
|
||||
struct TheDarkKnight;
|
||||
@@ -380,7 +393,7 @@ fn main() {
|
||||
Moving out of a member of a mutably borrowed struct is fine if you put something
|
||||
back. `mem::replace` can be used for that:
|
||||
|
||||
```
|
||||
```ignore
|
||||
struct TheDarkKnight;
|
||||
|
||||
impl TheDarkKnight {
|
||||
|
||||
@@ -66,7 +66,7 @@ pub fn compile_input(sess: &Session,
|
||||
outdir: &Option<PathBuf>,
|
||||
output: &Option<PathBuf>,
|
||||
addl_plugins: Option<Vec<String>>,
|
||||
control: CompileController) -> CompileResult {
|
||||
control: &CompileController) -> CompileResult {
|
||||
macro_rules! controller_entry_point {
|
||||
($point: ident, $tsess: expr, $make_state: expr, $phase_result: expr) => {{
|
||||
let state = $make_state;
|
||||
|
||||
@@ -203,7 +203,7 @@ macro_rules! do_or_return {($expr: expr, $sess: expr) => {
|
||||
let plugins = sess.opts.debugging_opts.extra_plugins.clone();
|
||||
let control = callbacks.build_controller(&sess);
|
||||
(driver::compile_input(&sess, &cstore, cfg, &input, &odir, &ofile,
|
||||
Some(plugins), control),
|
||||
Some(plugins), &control),
|
||||
Some(sess))
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
the heap at runtime, and therefore cannot be done at compile time. Erroneous
|
||||
code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
#![feature(box_syntax)]
|
||||
|
||||
const CON : Box<i32> = box 0;
|
||||
@@ -30,9 +30,9 @@
|
||||
User-defined operators rely on user-defined functions, which cannot be evaluated
|
||||
at compile time.
|
||||
|
||||
Bad example:
|
||||
Erroneous code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
use std::ops::Index;
|
||||
|
||||
struct Foo { a: u8 }
|
||||
@@ -53,16 +53,16 @@ fn index<'a>(&'a self, idx: u8) -> &'a u8 { &self.a }
|
||||
|
||||
```
|
||||
const a: &'static [i32] = &[1, 2, 3];
|
||||
const b: i32 = a[0]; // Good!
|
||||
const b: i32 = a[0]; // Ok!
|
||||
```
|
||||
"##,
|
||||
|
||||
E0013: r##"
|
||||
Static and const variables can refer to other const variables. But a const
|
||||
variable cannot refer to a static variable. For example, `Y` cannot refer to `X`
|
||||
here:
|
||||
variable cannot refer to a static variable. For example, `Y` cannot refer to
|
||||
`X` here:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
static X: i32 = 42;
|
||||
const Y: i32 = X;
|
||||
```
|
||||
@@ -80,9 +80,9 @@ fn index<'a>(&'a self, idx: u8) -> &'a u8 { &self.a }
|
||||
Constants can only be initialized by a constant value or, in a future
|
||||
version of Rust, a call to a const function. This error indicates the use
|
||||
of a path (like a::b, or x) denoting something other than one of these
|
||||
allowed items. Example:
|
||||
allowed items. Erroneous code xample:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
const FOO: i32 = { let x = 0; x }; // 'x' isn't a constant nor a function!
|
||||
```
|
||||
|
||||
@@ -91,7 +91,7 @@ fn index<'a>(&'a self, idx: u8) -> &'a u8 { &self.a }
|
||||
```
|
||||
const FOO: i32 = { const X : i32 = 0; X };
|
||||
// or even:
|
||||
const FOO: i32 = { 0 }; // but brackets are useless here
|
||||
const FOO2: i32 = { 0 }; // but brackets are useless here
|
||||
```
|
||||
"##,
|
||||
|
||||
@@ -115,9 +115,9 @@ struct Bar {x: u8}
|
||||
|
||||
E0016: r##"
|
||||
Blocks in constants may only contain items (such as constant, function
|
||||
definition, etc...) and a tail expression. Example:
|
||||
definition, etc...) and a tail expression. Erroneous code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
const FOO: i32 = { let x = 0; x }; // 'x' isn't an item!
|
||||
```
|
||||
|
||||
@@ -129,9 +129,10 @@ struct Bar {x: u8}
|
||||
"##,
|
||||
|
||||
E0017: r##"
|
||||
References in statics and constants may only refer to immutable values. Example:
|
||||
References in statics and constants may only refer to immutable values.
|
||||
Erroneous code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
static X: i32 = 1;
|
||||
const C: i32 = 2;
|
||||
|
||||
@@ -156,7 +157,8 @@ struct Bar {x: u8}
|
||||
vary.
|
||||
|
||||
For example, if you write:
|
||||
```
|
||||
|
||||
```compile_fail
|
||||
static MY_STATIC: u32 = 42;
|
||||
static MY_STATIC_ADDR: usize = &MY_STATIC as *const _ as usize;
|
||||
static WHAT: usize = (MY_STATIC_ADDR^17) + MY_STATIC_ADDR;
|
||||
@@ -184,10 +186,10 @@ struct Bar {x: u8}
|
||||
|
||||
E0019: r##"
|
||||
A function call isn't allowed in the const's initialization expression
|
||||
because the expression's value must be known at compile-time. Example of
|
||||
erroneous code:
|
||||
because the expression's value must be known at compile-time. Erroneous code
|
||||
example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
enum Test {
|
||||
V1
|
||||
}
|
||||
@@ -222,13 +224,13 @@ fn main() {
|
||||
Constant functions are not allowed to mutate anything. Thus, binding to an
|
||||
argument with a mutable pattern is not allowed. For example,
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
const fn foo(mut x: u8) {
|
||||
// do stuff
|
||||
}
|
||||
```
|
||||
|
||||
is bad because the function body may not mutate `x`.
|
||||
Is incorrect because the function body may not mutate `x`.
|
||||
|
||||
Remove any mutable bindings from the argument list to fix this error. In case
|
||||
you need to mutate the argument, try lazily initializing a global variable
|
||||
@@ -244,12 +246,12 @@ const fn foo(mut x: u8) {
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
match 5u32 {
|
||||
// This range is ok, albeit pointless.
|
||||
1 ... 1 => ...
|
||||
1 ... 1 => {}
|
||||
// This range is empty, and the compiler can tell.
|
||||
1000 ... 5 => ...
|
||||
1000 ... 5 => {}
|
||||
}
|
||||
```
|
||||
"##,
|
||||
@@ -268,11 +270,11 @@ const fn foo(mut x: u8) {
|
||||
|
||||
For example, neither of the following can be sensibly compiled:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
const X: u32 = X;
|
||||
```
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
const X: u32 = Y;
|
||||
const Y: u32 = X;
|
||||
```
|
||||
@@ -282,7 +284,7 @@ const fn foo(mut x: u8) {
|
||||
This error indicates the use of a loop keyword (`break` or `continue`) inside a
|
||||
closure but outside of any loop. Erroneous code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
let w = || { break; }; // error: `break` inside of a closure
|
||||
```
|
||||
|
||||
@@ -306,7 +308,7 @@ const fn foo(mut x: u8) {
|
||||
of a loop. Without a loop to break out of or continue in, no sensible action can
|
||||
be taken. Erroneous code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
fn some_func() {
|
||||
break; // error: `break` outside of loop
|
||||
}
|
||||
@@ -329,7 +331,7 @@ fn some_func() {
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
const BAZ: i32 = Foo(25).bar(); // error, `bar` isn't `const`
|
||||
|
||||
struct Foo(i32);
|
||||
@@ -362,9 +364,9 @@ fn bar(&self) -> i32 { self.0 }
|
||||
The value assigned to a constant scalar must be known at compile time,
|
||||
which is not the case when comparing raw pointers.
|
||||
|
||||
|
||||
Erroneous code example:
|
||||
```
|
||||
|
||||
```compile_fail
|
||||
static FOO: i32 = 42;
|
||||
static BAR: i32 = 42;
|
||||
|
||||
@@ -391,10 +393,9 @@ fn bar(&self) -> i32 { self.0 }
|
||||
E0396: r##"
|
||||
The value behind a raw pointer can't be determined at compile-time
|
||||
(or even link-time), which means it can't be used in a constant
|
||||
expression.
|
||||
expression. Erroneous code example:
|
||||
|
||||
For example:
|
||||
```
|
||||
```compile_fail
|
||||
const REG_ADDR: *const u8 = 0x5f3759df as *const u8;
|
||||
|
||||
const VALUE: u8 = unsafe { *REG_ADDR };
|
||||
@@ -416,7 +417,7 @@ fn bar(&self) -> i32 { self.0 }
|
||||
It is not allowed for a mutable static to allocate or have destructors. For
|
||||
example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
// error: mutable statics are not allowed to have boxes
|
||||
static mut FOO: Option<Box<usize>> = None;
|
||||
|
||||
@@ -429,7 +430,7 @@ fn bar(&self) -> i32 { self.0 }
|
||||
A user-defined dereference was attempted in an invalid context. Erroneous
|
||||
code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
use std::ops::Deref;
|
||||
|
||||
struct A;
|
||||
@@ -473,7 +474,7 @@ fn main() {
|
||||
A borrow of a constant containing interior mutability was attempted. Erroneous
|
||||
code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT};
|
||||
|
||||
const A: AtomicUsize = ATOMIC_USIZE_INIT;
|
||||
@@ -500,7 +501,7 @@ fn main() {
|
||||
|
||||
You can also have this error while using a cell type:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
#![feature(const_fn)]
|
||||
|
||||
use std::cell::Cell;
|
||||
@@ -552,7 +553,7 @@ unsafe impl<T> Sync for NotThreadSafe<T> {}
|
||||
A type with a destructor was assigned to an invalid type of variable. Erroneous
|
||||
code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
struct Foo {
|
||||
a: u32
|
||||
}
|
||||
@@ -575,7 +576,7 @@ fn drop(&mut self) {}
|
||||
A reference of an interior static was assigned to another const/static.
|
||||
Erroneous code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
struct Foo {
|
||||
a: u32
|
||||
}
|
||||
|
||||
@@ -16,28 +16,27 @@
|
||||
A private trait was used on a public type parameter bound. Erroneous code
|
||||
examples:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
trait Foo {
|
||||
fn dummy(&self) { }
|
||||
}
|
||||
|
||||
pub trait Bar : Foo {} // error: private trait in public interface
|
||||
pub struct Bar<T: Foo>(pub T); // same error
|
||||
pub struct Bar2<T: Foo>(pub T); // same error
|
||||
pub fn foo<T: Foo> (t: T) {} // same error
|
||||
```
|
||||
|
||||
To solve this error, please ensure that the trait is also public. The trait
|
||||
can be made inaccessible if necessary by placing it into a private inner module,
|
||||
but it still has to be marked with `pub`.
|
||||
Example:
|
||||
but it still has to be marked with `pub`. Example:
|
||||
|
||||
```
|
||||
```ignore
|
||||
pub trait Foo { // we set the Foo trait public
|
||||
fn dummy(&self) { }
|
||||
}
|
||||
|
||||
pub trait Bar : Foo {} // ok!
|
||||
pub struct Bar<T: Foo>(pub T); // ok!
|
||||
pub struct Bar2<T: Foo>(pub T); // ok!
|
||||
pub fn foo<T: Foo> (t: T) {} // ok!
|
||||
```
|
||||
"##,
|
||||
@@ -45,7 +44,7 @@ pub fn foo<T: Foo> (t: T) {} // ok!
|
||||
E0446: r##"
|
||||
A private type was used in a public type signature. Erroneous code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
mod Foo {
|
||||
struct Bar(u32);
|
||||
|
||||
@@ -74,7 +73,7 @@ pub fn bar() -> Bar { // ok!
|
||||
E0447: r##"
|
||||
The `pub` keyword was used inside a function. Erroneous code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
fn foo() {
|
||||
pub struct Bar; // error: visibility has no effect inside functions
|
||||
}
|
||||
@@ -88,7 +87,7 @@ fn foo() {
|
||||
E0448: r##"
|
||||
The `pub` keyword was used inside a public enum. Erroneous code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
pub enum Foo {
|
||||
pub Bar, // error: unnecessary `pub` visibility
|
||||
}
|
||||
@@ -97,13 +96,15 @@ pub enum Foo {
|
||||
Since the enum is already public, adding `pub` on one its elements is
|
||||
unnecessary. Example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
enum Foo {
|
||||
pub Bar, // ok!
|
||||
pub Bar, // not ok!
|
||||
}
|
||||
```
|
||||
|
||||
// or:
|
||||
This is the correct syntax:
|
||||
|
||||
```ignore
|
||||
pub enum Foo {
|
||||
Bar, // ok!
|
||||
}
|
||||
@@ -114,7 +115,7 @@ pub enum Foo {
|
||||
A visibility qualifier was used when it was unnecessary. Erroneous code
|
||||
examples:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
struct Bar;
|
||||
|
||||
trait Foo {
|
||||
@@ -131,7 +132,7 @@ pub fn foo() {} // error: unnecessary visibility qualifier
|
||||
To fix this error, please remove the visibility qualifier when it is not
|
||||
required. Example:
|
||||
|
||||
```
|
||||
```ignore
|
||||
struct Bar;
|
||||
|
||||
trait Foo {
|
||||
@@ -154,7 +155,7 @@ pub fn foo() {}
|
||||
A tuple constructor was invoked while some of its fields are private. Erroneous
|
||||
code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
mod Bar {
|
||||
pub struct Foo(isize);
|
||||
}
|
||||
@@ -179,7 +180,7 @@ mod bar {
|
||||
pub struct Foo(isize);
|
||||
|
||||
impl Foo {
|
||||
pub fn new(x: isize) {
|
||||
pub fn new(x: isize) -> Foo {
|
||||
Foo(x)
|
||||
}
|
||||
}
|
||||
@@ -192,7 +193,7 @@ pub fn new(x: isize) {
|
||||
E0451: r##"
|
||||
A struct constructor with private fields was invoked. Erroneous code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
mod Bar {
|
||||
pub struct Foo {
|
||||
pub a: isize,
|
||||
@@ -216,8 +217,11 @@ pub struct Foo {
|
||||
}
|
||||
|
||||
let f = Bar::Foo{ a: 0, b: 0 }; // ok!
|
||||
```
|
||||
|
||||
// or:
|
||||
Or:
|
||||
|
||||
```
|
||||
mod Bar {
|
||||
pub struct Foo {
|
||||
pub a: isize,
|
||||
|
||||
@@ -21,12 +21,12 @@
|
||||
|
||||
Here is an example that demonstrates the error:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
fn f() {
|
||||
// Variable declaration before import
|
||||
let x = 0;
|
||||
use std::io::Read;
|
||||
...
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
@@ -39,7 +39,7 @@ fn f() {
|
||||
fn f() {
|
||||
use std::io::Read;
|
||||
let x = 0;
|
||||
...
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
@@ -55,7 +55,7 @@ fn f() {
|
||||
|
||||
An example of this error:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
use foo::baz;
|
||||
use bar::*; // error, do `use foo::baz as quux` instead on the previous line
|
||||
|
||||
@@ -77,7 +77,7 @@ pub mod baz {}
|
||||
|
||||
An example of this error:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
use foo::baz;
|
||||
use bar::baz; // error, do `use bar::baz as quux` instead
|
||||
|
||||
@@ -97,12 +97,13 @@ pub mod baz {}
|
||||
Attempt was made to import an unimportable value. This can happen when
|
||||
trying to import a method from a trait. An example of this error:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
mod foo {
|
||||
pub trait MyTrait {
|
||||
fn do_something();
|
||||
}
|
||||
}
|
||||
|
||||
use foo::MyTrait::do_something;
|
||||
```
|
||||
|
||||
@@ -115,7 +116,7 @@ pub trait MyTrait {
|
||||
|
||||
An example of this error:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
use bar::foo; // error, do `use bar::foo as baz` instead
|
||||
|
||||
fn foo() {}
|
||||
@@ -134,7 +135,7 @@ fn main() {}
|
||||
|
||||
An example of this error:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
use foo::Bar; // error
|
||||
|
||||
type Bar = u32;
|
||||
@@ -153,7 +154,7 @@ fn main() {}
|
||||
|
||||
Wrong example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
extern crate a;
|
||||
extern crate crate_a as a;
|
||||
```
|
||||
@@ -163,7 +164,7 @@ fn main() {}
|
||||
|
||||
Correct example:
|
||||
|
||||
```
|
||||
```ignore
|
||||
extern crate a;
|
||||
extern crate crate_a as other_name;
|
||||
```
|
||||
@@ -172,9 +173,9 @@ fn main() {}
|
||||
E0260: r##"
|
||||
The name for an item declaration conflicts with an external crate's name.
|
||||
|
||||
For instance,
|
||||
For instance:
|
||||
|
||||
```
|
||||
```ignore
|
||||
extern crate abc;
|
||||
|
||||
struct abc;
|
||||
@@ -184,7 +185,7 @@ fn main() {}
|
||||
|
||||
Solution #1: Rename the item.
|
||||
|
||||
```
|
||||
```ignore
|
||||
extern crate abc;
|
||||
|
||||
struct xyz;
|
||||
@@ -192,7 +193,7 @@ fn main() {}
|
||||
|
||||
Solution #2: Import the crate with a different name.
|
||||
|
||||
```
|
||||
```ignore
|
||||
extern crate abc as xyz;
|
||||
|
||||
struct abc;
|
||||
@@ -209,7 +210,7 @@ fn main() {}
|
||||
This error indicates you tried to define a type, struct or enum with the same
|
||||
name as an existing primitive type:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
struct u8 {
|
||||
// ...
|
||||
}
|
||||
@@ -220,7 +221,7 @@ struct u8 {
|
||||
Such an error may also occur if you define a type parameter which shadows a
|
||||
primitive type. An example would be something like:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
impl<u8> MyTrait for Option<u8> {
|
||||
// ...
|
||||
}
|
||||
@@ -229,7 +230,7 @@ impl<u8> MyTrait for Option<u8> {
|
||||
In such a case, if you meant for `u8` to be a generic type parameter (i.e. any
|
||||
type can be used in its place), use something like `T` instead:
|
||||
|
||||
```
|
||||
```ignore
|
||||
impl<T> MyTrait for Option<T> {
|
||||
// ...
|
||||
}
|
||||
@@ -238,7 +239,7 @@ impl<T> MyTrait for Option<T> {
|
||||
On the other hand, if you wished to refer to the specific type `u8`, remove it
|
||||
from the type parameter list:
|
||||
|
||||
```
|
||||
```ignore
|
||||
impl MyTrait for Option<u8> {
|
||||
// ...
|
||||
}
|
||||
@@ -255,20 +256,22 @@ impl MyTrait for Option<u8> {
|
||||
|
||||
Here is an example that demonstrates the error:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
mod foo {
|
||||
const X: u32 = 1;
|
||||
}
|
||||
|
||||
pub use foo::X;
|
||||
```
|
||||
|
||||
The solution to this problem is to ensure that the items that you are
|
||||
re-exporting are themselves marked with `pub`:
|
||||
|
||||
```
|
||||
```ignore
|
||||
mod foo {
|
||||
pub const X: u32 = 1;
|
||||
}
|
||||
|
||||
pub use foo::X;
|
||||
```
|
||||
|
||||
@@ -284,20 +287,22 @@ mod foo {
|
||||
|
||||
Here is an example that demonstrates the error:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
mod foo {
|
||||
pub const X: u32 = 1;
|
||||
}
|
||||
pub use foo as foo2;
|
||||
|
||||
pub use foo as foo2;
|
||||
```
|
||||
|
||||
The solution to this problem is to ensure that the module that you are
|
||||
re-exporting is itself marked with `pub`:
|
||||
|
||||
```
|
||||
```ignore
|
||||
pub mod foo {
|
||||
pub const X: u32 = 1;
|
||||
}
|
||||
|
||||
pub use foo as foo2;
|
||||
```
|
||||
|
||||
@@ -311,7 +316,7 @@ pub mod foo {
|
||||
Inner items do not inherit type parameters from the functions they are
|
||||
embedded in. For example, this will not compile:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
fn foo<T>(x: T) {
|
||||
fn bar(y: T) { // T is defined in the "outer" function
|
||||
// ..
|
||||
@@ -320,18 +325,18 @@ fn bar(y: T) { // T is defined in the "outer" function
|
||||
}
|
||||
```
|
||||
|
||||
nor will this:
|
||||
Nor will this:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
fn foo<T>(x: T) {
|
||||
type MaybeT = Option<T>;
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
or this:
|
||||
Or this:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
fn foo<T>(x: T) {
|
||||
struct Foo {
|
||||
x: T,
|
||||
@@ -351,7 +356,7 @@ struct Foo {
|
||||
fn foo<T>(x: T) {
|
||||
let bar = |y: T| { // explicit type annotation may not be necessary
|
||||
// ..
|
||||
}
|
||||
};
|
||||
bar(x);
|
||||
}
|
||||
```
|
||||
@@ -397,11 +402,12 @@ struct Foo<T: Copy> {
|
||||
In case the item is a function inside an `impl`, defining a private helper
|
||||
function might be easier:
|
||||
|
||||
```
|
||||
```ignore
|
||||
impl<T> Foo<T> {
|
||||
pub fn foo(&self, x: T) {
|
||||
self.bar(x);
|
||||
}
|
||||
|
||||
fn bar(&self, y: T) {
|
||||
// ..
|
||||
}
|
||||
@@ -415,7 +421,7 @@ fn bar(&self, y: T) {
|
||||
E0403: r##"
|
||||
Some type parameters have the same name. Example of erroneous code:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
fn foo<T, T>(s: T, u: T) {} // error: the name `T` is already used for a type
|
||||
// parameter in this type parameter list
|
||||
```
|
||||
@@ -432,7 +438,7 @@ fn foo<T, Y>(s: T, u: Y) {} // ok!
|
||||
You tried to implement something which was not a trait on an object. Example of
|
||||
erroneous code:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
struct Foo;
|
||||
struct Bar;
|
||||
|
||||
@@ -457,7 +463,7 @@ impl Foo for Bar { // ok!
|
||||
E0405: r##"
|
||||
An unknown trait was implemented. Example of erroneous code:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
struct Foo;
|
||||
|
||||
impl SomeTrait for Foo {} // error: use of undeclared trait name `SomeTrait`
|
||||
@@ -466,7 +472,7 @@ impl SomeTrait for Foo {} // error: use of undeclared trait name `SomeTrait`
|
||||
Please verify that the name of the trait wasn't misspelled and ensure that it
|
||||
was imported. Example:
|
||||
|
||||
```
|
||||
```ignore
|
||||
// solution 1:
|
||||
use some_file::SomeTrait;
|
||||
|
||||
@@ -487,7 +493,7 @@ impl SomeTrait for Foo { // ok!
|
||||
A definition of a method not in the implemented trait was given in a trait
|
||||
implementation. Example of erroneous code:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
trait Foo {
|
||||
fn a();
|
||||
}
|
||||
@@ -540,7 +546,7 @@ fn b() {}
|
||||
The `Self` keyword was used outside an impl or a trait. Erroneous
|
||||
code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
<Self>::foo; // error: use of `Self` outside of an impl or trait
|
||||
```
|
||||
|
||||
@@ -560,7 +566,7 @@ trait Baz : Foo {
|
||||
|
||||
However, be careful when two types has a common associated type:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
trait Foo {
|
||||
type Bar;
|
||||
}
|
||||
@@ -579,6 +585,14 @@ trait Baz : Foo + Foo2 {
|
||||
to use the `Bar` type:
|
||||
|
||||
```
|
||||
trait Foo {
|
||||
type Bar;
|
||||
}
|
||||
|
||||
trait Foo2 {
|
||||
type Bar;
|
||||
}
|
||||
|
||||
trait Baz : Foo + Foo2 {
|
||||
fn bar() -> <Self as Foo>::Bar; // ok!
|
||||
}
|
||||
@@ -588,7 +602,7 @@ trait Baz : Foo + Foo2 {
|
||||
E0412: r##"
|
||||
An undeclared type name was used. Example of erroneous codes:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
impl Something {} // error: use of undeclared type name `Something`
|
||||
// or:
|
||||
trait Foo {
|
||||
@@ -605,13 +619,17 @@ fn foo(x: T) {} // error: use of undeclared type name `T`
|
||||
struct Something;
|
||||
|
||||
impl Something {} // ok!
|
||||
|
||||
// or:
|
||||
|
||||
trait Foo {
|
||||
type N;
|
||||
|
||||
fn bar(Self::N); // ok!
|
||||
}
|
||||
//or:
|
||||
|
||||
// or:
|
||||
|
||||
fn foo<T>(x: T) {} // ok!
|
||||
```
|
||||
"##,
|
||||
@@ -620,14 +638,13 @@ fn foo<T>(x: T) {} // ok!
|
||||
A declaration shadows an enum variant or unit-like struct in scope.
|
||||
Example of erroneous code:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
struct Foo;
|
||||
|
||||
let Foo = 12i32; // error: declaration of `Foo` shadows an enum variant or
|
||||
// unit-like struct in scope
|
||||
```
|
||||
|
||||
|
||||
To fix this error, rename the variable such that it doesn't shadow any enum
|
||||
variable or structure in scope. Example:
|
||||
|
||||
@@ -652,7 +669,7 @@ fn foo<T>(x: T) {} // ok!
|
||||
More than one function parameter have the same name. Example of erroneous
|
||||
code:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
fn foo(f: i32, f: i32) {} // error: identifier `f` is bound more than
|
||||
// once in this parameter list
|
||||
```
|
||||
@@ -668,7 +685,7 @@ fn foo(f: i32, g: i32) {} // ok!
|
||||
An identifier is bound more than once in a pattern. Example of erroneous
|
||||
code:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
match (1, 2) {
|
||||
(x, x) => {} // error: identifier `x` is bound more than once in the
|
||||
// same pattern
|
||||
@@ -685,7 +702,7 @@ fn foo(f: i32, g: i32) {} // ok!
|
||||
|
||||
Or maybe did you mean to unify? Consider using a guard:
|
||||
|
||||
```
|
||||
```ignore
|
||||
match (A, B, C) {
|
||||
(x, x2, see) if x == x2 => { /* A and B are equal, do one thing */ }
|
||||
(y, z, see) => { /* A and B unequal; do another thing */ }
|
||||
@@ -696,7 +713,7 @@ fn foo(f: i32, g: i32) {} // ok!
|
||||
E0417: r##"
|
||||
A static variable was referenced in a pattern. Example of erroneous code:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
static FOO : i32 = 0;
|
||||
|
||||
match 0 {
|
||||
@@ -725,7 +742,7 @@ fn foo(f: i32, g: i32) {} // ok!
|
||||
An unknown enum variant, struct or const was used. Example of
|
||||
erroneous code:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
match 0 {
|
||||
Something::Foo => {} // error: unresolved enum variant, struct
|
||||
// or const `Foo`
|
||||
@@ -751,7 +768,8 @@ enum Something {
|
||||
E0422: r##"
|
||||
You are trying to use an identifier that is either undefined or not a
|
||||
struct. For instance:
|
||||
```
|
||||
|
||||
``` compile_fail
|
||||
fn main () {
|
||||
let x = Foo { x: 1, y: 2 };
|
||||
}
|
||||
@@ -760,7 +778,7 @@ fn main () {
|
||||
In this case, `Foo` is undefined, so it inherently isn't anything, and
|
||||
definitely not a struct.
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
fn main () {
|
||||
let foo = 1;
|
||||
let x = foo { x: 1, y: 2 };
|
||||
@@ -775,7 +793,7 @@ fn main () {
|
||||
A `struct` variant name was used like a function name. Example of
|
||||
erroneous code:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
struct Foo { a: bool};
|
||||
|
||||
let f = Foo();
|
||||
@@ -796,7 +814,7 @@ fn Foo() -> u32 { 0 }
|
||||
E0424: r##"
|
||||
The `self` keyword was used in a static method. Example of erroneous code:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
struct Foo;
|
||||
|
||||
impl Foo {
|
||||
@@ -828,7 +846,7 @@ fn foo(self) {
|
||||
E0425: r##"
|
||||
An unresolved name was used. Example of erroneous codes:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
something_that_doesnt_exist::foo;
|
||||
// error: unresolved name `something_that_doesnt_exist::foo`
|
||||
|
||||
@@ -848,17 +866,23 @@ fn bar() {
|
||||
|
||||
```
|
||||
enum something_that_does_exist {
|
||||
foo
|
||||
Foo,
|
||||
}
|
||||
```
|
||||
|
||||
// or:
|
||||
Or:
|
||||
|
||||
```
|
||||
mod something_that_does_exist {
|
||||
pub static foo : i32 = 0i32;
|
||||
}
|
||||
|
||||
something_that_does_exist::foo; // ok!
|
||||
```
|
||||
|
||||
// or:
|
||||
Or:
|
||||
|
||||
```
|
||||
let unknown_variable = 12u32;
|
||||
let x = unknown_variable; // ok!
|
||||
```
|
||||
@@ -867,7 +891,7 @@ mod something_that_does_exist {
|
||||
E0426: r##"
|
||||
An undeclared label was used. Example of erroneous code:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
loop {
|
||||
break 'a; // error: use of undeclared label `'a`
|
||||
}
|
||||
@@ -886,7 +910,7 @@ mod something_that_does_exist {
|
||||
A type or module has been defined more than once. Example of erroneous
|
||||
code:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
struct Bar;
|
||||
struct Bar; // error: duplicate definition of value `Bar`
|
||||
```
|
||||
@@ -903,7 +927,7 @@ mod something_that_does_exist {
|
||||
E0430: r##"
|
||||
The `self` import appears more than once in the list. Erroneous code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
use something::{self, self}; // error: `self` import can only appear once in
|
||||
// the list
|
||||
```
|
||||
@@ -911,7 +935,7 @@ mod something_that_does_exist {
|
||||
Please verify you didn't misspell the import name or remove the duplicated
|
||||
`self` import. Example:
|
||||
|
||||
```
|
||||
```ignore
|
||||
use something::self; // ok!
|
||||
```
|
||||
"##,
|
||||
@@ -919,7 +943,7 @@ mod something_that_does_exist {
|
||||
E0431: r##"
|
||||
`self` import was made. Erroneous code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
use {self}; // error: `self` import can only appear in an import list with a
|
||||
// non-empty prefix
|
||||
```
|
||||
@@ -931,14 +955,14 @@ mod something_that_does_exist {
|
||||
E0432: r##"
|
||||
An import was unresolved. Erroneous code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
use something::Foo; // error: unresolved import `something::Foo`.
|
||||
```
|
||||
|
||||
Please verify you didn't misspell the import name or the import does exist
|
||||
in the module from where you tried to import it. Example:
|
||||
|
||||
```
|
||||
```ignore
|
||||
use something::Foo; // ok!
|
||||
|
||||
mod something {
|
||||
@@ -949,7 +973,7 @@ mod something {
|
||||
Or, if you tried to use a module from an external crate, you may have missed
|
||||
the `extern crate` declaration:
|
||||
|
||||
```
|
||||
```ignore
|
||||
extern crate homura; // Required to use the `homura` crate
|
||||
|
||||
use homura::Madoka;
|
||||
@@ -959,7 +983,7 @@ mod something {
|
||||
E0433: r##"
|
||||
Invalid import. Example of erroneous code:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
use something_which_doesnt_exist;
|
||||
// error: unresolved import `something_which_doesnt_exist`
|
||||
```
|
||||
@@ -971,7 +995,7 @@ mod something {
|
||||
A non-constant value was used to initialise a constant. Example of erroneous
|
||||
code:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
let foo = 42u32;
|
||||
const FOO : u32 = foo; // error: attempt to use a non-constant value in a
|
||||
// constant
|
||||
@@ -981,8 +1005,11 @@ mod something {
|
||||
|
||||
```
|
||||
const FOO : u32 = 42u32; // ok!
|
||||
```
|
||||
|
||||
// or:
|
||||
Or:
|
||||
|
||||
```
|
||||
const OTHER_FOO : u32 = 42u32;
|
||||
const FOO : u32 = OTHER_FOO; // ok!
|
||||
```
|
||||
@@ -996,7 +1023,7 @@ mod something {
|
||||
|
||||
Here is an example that demonstrates the error:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
trait Foo {}
|
||||
|
||||
impl Foo for i32 {
|
||||
@@ -1021,7 +1048,7 @@ impl Foo for i32 {}
|
||||
|
||||
Here is an example that demonstrates the error:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
#![feature(associated_consts)]
|
||||
|
||||
trait Foo {}
|
||||
|
||||
@@ -15,12 +15,14 @@
|
||||
E0510: r##"
|
||||
`return_address` was used in an invalid context. Erroneous code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
#![feature(intrinsics)]
|
||||
|
||||
extern "rust-intrinsic" {
|
||||
fn return_address() -> *const u8;
|
||||
}
|
||||
|
||||
pub unsafe fn by_value() -> i32 {
|
||||
unsafe fn by_value() -> i32 {
|
||||
let _ = return_address();
|
||||
// error: invalid use of `return_address` intrinsic: function does
|
||||
// not use out pointer
|
||||
@@ -35,11 +37,13 @@ pub unsafe fn by_value() -> i32 {
|
||||
space allocated in the caller's stack frame. Example:
|
||||
|
||||
```
|
||||
#![feature(intrinsics)]
|
||||
|
||||
extern "rust-intrinsic" {
|
||||
fn return_address() -> *const u8;
|
||||
}
|
||||
|
||||
pub unsafe fn by_pointer() -> String {
|
||||
unsafe fn by_pointer() -> String {
|
||||
let _ = return_address();
|
||||
String::new() // ok!
|
||||
}
|
||||
@@ -50,7 +54,9 @@ pub unsafe fn by_pointer() -> String {
|
||||
Invalid monomorphization of an intrinsic function was used. Erroneous code
|
||||
example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
#![feature(platform_intrinsics)]
|
||||
|
||||
extern "platform-intrinsic" {
|
||||
fn simd_add<T>(a: T, b: T) -> T;
|
||||
}
|
||||
@@ -62,6 +68,9 @@ pub unsafe fn by_pointer() -> String {
|
||||
The generic type has to be a SIMD type. Example:
|
||||
|
||||
```
|
||||
#![feature(repr_simd)]
|
||||
#![feature(platform_intrinsics)]
|
||||
|
||||
#[repr(simd)]
|
||||
#[derive(Copy, Clone)]
|
||||
struct i32x1(i32);
|
||||
@@ -78,7 +87,7 @@ pub unsafe fn by_pointer() -> String {
|
||||
Transmute with two differently sized types was attempted. Erroneous code
|
||||
example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
fn takes_u8(_: u8) {}
|
||||
|
||||
fn main() {
|
||||
@@ -103,7 +112,7 @@ fn main() {
|
||||
E0515: r##"
|
||||
A constant index expression was out of bounds. Erroneous code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
let x = &[0, 1, 2][7]; // error: const index-expr is out of bounds
|
||||
```
|
||||
|
||||
|
||||
+443
-230
@@ -19,27 +19,42 @@
|
||||
|
||||
```
|
||||
enum Fruit {
|
||||
Apple(String, String)
|
||||
Pear(u32)
|
||||
Apple(String, String),
|
||||
Pear(u32),
|
||||
}
|
||||
```
|
||||
|
||||
Here the `Apple` variant has two fields, and should be matched against like so:
|
||||
|
||||
```
|
||||
enum Fruit {
|
||||
Apple(String, String),
|
||||
Pear(u32),
|
||||
}
|
||||
|
||||
let x = Fruit::Apple(String::new(), String::new());
|
||||
|
||||
// Correct.
|
||||
match x {
|
||||
Apple(a, b) => ...
|
||||
Fruit::Apple(a, b) => {},
|
||||
_ => {}
|
||||
}
|
||||
```
|
||||
|
||||
Matching with the wrong number of fields has no sensible interpretation:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
enum Fruit {
|
||||
Apple(String, String),
|
||||
Pear(u32),
|
||||
}
|
||||
|
||||
let x = Fruit::Apple(String::new(), String::new());
|
||||
|
||||
// Incorrect.
|
||||
match x {
|
||||
Apple(a) => ...,
|
||||
Apple(a, b, c) => ...
|
||||
Apple(a) => {},
|
||||
Apple(a, b, c) => {},
|
||||
}
|
||||
```
|
||||
|
||||
@@ -51,7 +66,7 @@ enum Fruit {
|
||||
This error indicates that a pattern attempted to extract the fields of an enum
|
||||
variant with no fields. Here's a tiny example of this error:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
// This enum has two variants.
|
||||
enum Number {
|
||||
// This variant has no fields.
|
||||
@@ -62,8 +77,8 @@ enum Number {
|
||||
|
||||
// Assuming x is a Number we can pattern match on its contents.
|
||||
match x {
|
||||
Zero(inside) => ...,
|
||||
One(inside) => ...
|
||||
Zero(inside) => {},
|
||||
One(inside) => {},
|
||||
}
|
||||
```
|
||||
|
||||
@@ -76,7 +91,7 @@ enum Number {
|
||||
Each field of a struct can only be bound once in a pattern. Erroneous code
|
||||
example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
struct Foo {
|
||||
a: u8,
|
||||
b: u8,
|
||||
@@ -122,23 +137,42 @@ struct Thing {
|
||||
}
|
||||
|
||||
let thing = Thing { x: 1, y: 2 };
|
||||
|
||||
match thing {
|
||||
Thing { x: xfield, y: yfield } => ...
|
||||
Thing { x: xfield, y: yfield } => {}
|
||||
}
|
||||
```
|
||||
|
||||
If you are using shorthand field patterns but want to refer to the struct field
|
||||
by a different name, you should rename it explicitly.
|
||||
|
||||
```
|
||||
// Change this:
|
||||
match thing {
|
||||
Thing { x, z } => ...
|
||||
Change this:
|
||||
|
||||
```compile_fail
|
||||
struct Thing {
|
||||
x: u32,
|
||||
y: u32
|
||||
}
|
||||
|
||||
// To this:
|
||||
let thing = Thing { x: 0, y: 0 };
|
||||
|
||||
match thing {
|
||||
Thing { x, y: z } => ...
|
||||
Thing { x, z } => {}
|
||||
}
|
||||
```
|
||||
|
||||
To this:
|
||||
|
||||
```
|
||||
struct Thing {
|
||||
x: u32,
|
||||
y: u32
|
||||
}
|
||||
|
||||
let thing = Thing { x: 0, y: 0 };
|
||||
|
||||
match thing {
|
||||
Thing { x, y: z } => {}
|
||||
}
|
||||
```
|
||||
"##,
|
||||
@@ -150,27 +184,37 @@ struct Thing {
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
struct Dog {
|
||||
name: String,
|
||||
age: u32
|
||||
age: u32,
|
||||
}
|
||||
|
||||
let d = Dog { name: "Rusty".to_string(), age: 8 };
|
||||
|
||||
// This is incorrect.
|
||||
match d {
|
||||
Dog { age: x } => ...
|
||||
Dog { age: x } => {}
|
||||
}
|
||||
```
|
||||
|
||||
This is correct (explicit):
|
||||
|
||||
```
|
||||
struct Dog {
|
||||
name: String,
|
||||
age: u32,
|
||||
}
|
||||
|
||||
// This is correct (explicit).
|
||||
let d = Dog { name: "Rusty".to_string(), age: 8 };
|
||||
|
||||
match d {
|
||||
Dog { name: n, age: x } => ...
|
||||
Dog { name: ref n, age: x } => {}
|
||||
}
|
||||
|
||||
// This is also correct (ignore unused fields).
|
||||
match d {
|
||||
Dog { age: x, .. } => ...
|
||||
Dog { age: x, .. } => {}
|
||||
}
|
||||
```
|
||||
"##,
|
||||
@@ -182,18 +226,18 @@ struct Dog {
|
||||
want to capture values of an orderable type between two end-points, you can use
|
||||
a guard.
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
// The ordering relation for strings can't be evaluated at compile time,
|
||||
// so this doesn't work:
|
||||
match string {
|
||||
"hello" ... "world" => ...
|
||||
_ => ...
|
||||
"hello" ... "world" => {}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
// This is a more general version, using a guard:
|
||||
match string {
|
||||
s if s >= "hello" && s <= "world" => ...
|
||||
_ => ...
|
||||
s if s >= "hello" && s <= "world" => {}
|
||||
_ => {}
|
||||
}
|
||||
```
|
||||
"##,
|
||||
@@ -205,7 +249,7 @@ struct Dog {
|
||||
Therefore, all accesses to trait types must be through pointers. If you
|
||||
encounter this error you should try to avoid dereferencing the pointer.
|
||||
|
||||
```
|
||||
```ignore
|
||||
let trait_obj: &SomeTrait = ...;
|
||||
|
||||
// This tries to implicitly dereference to create an unsized local variable.
|
||||
@@ -224,9 +268,9 @@ struct Dog {
|
||||
|
||||
E0034: r##"
|
||||
The compiler doesn't know what method to call because more than one method
|
||||
has the same prototype. Example:
|
||||
has the same prototype. Erroneous code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
struct Test;
|
||||
|
||||
trait Trait1 {
|
||||
@@ -286,9 +330,10 @@ fn main() {
|
||||
"##,
|
||||
|
||||
E0035: r##"
|
||||
You tried to give a type parameter where it wasn't needed. Bad example:
|
||||
You tried to give a type parameter where it wasn't needed. Erroneous code
|
||||
example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
struct Test;
|
||||
|
||||
impl Test {
|
||||
@@ -321,9 +366,9 @@ fn main() {
|
||||
|
||||
E0036: r##"
|
||||
This error occurrs when you pass too many or not enough type parameters to
|
||||
a method. Example:
|
||||
a method. Erroneous code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
struct Test;
|
||||
|
||||
impl Test {
|
||||
@@ -361,7 +406,7 @@ fn main() {
|
||||
|
||||
Please note on the last example that we could have called `method` like this:
|
||||
|
||||
```
|
||||
```ignore
|
||||
x.method(v);
|
||||
```
|
||||
"##,
|
||||
@@ -373,7 +418,7 @@ fn main() {
|
||||
|
||||
Here's an example of this error:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
struct Foo {
|
||||
x: i32,
|
||||
}
|
||||
@@ -394,7 +439,7 @@ fn main() {
|
||||
E0044: r##"
|
||||
You can't use type parameters on foreign items. Example of erroneous code:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
extern { fn some_func<T>(x: T); }
|
||||
```
|
||||
|
||||
@@ -412,17 +457,23 @@ fn main() {
|
||||
FFI. As such, variadic parameters can only be used with functions which are
|
||||
using the C ABI. Examples of erroneous code:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
extern "rust-call" { fn foo(x: u8, ...); }
|
||||
|
||||
// or
|
||||
|
||||
fn foo(x: u8, ...) {}
|
||||
```
|
||||
|
||||
To fix such code, put them in an extern "C" block:
|
||||
|
||||
```ignore
|
||||
extern "C" fn foo(x: u8, ...);
|
||||
```
|
||||
|
||||
Or:
|
||||
|
||||
```
|
||||
extern "C" fn foo (x: u8, ...);
|
||||
// or:
|
||||
extern "C" {
|
||||
fn foo (x: u8, ...);
|
||||
}
|
||||
@@ -432,7 +483,7 @@ fn foo(x: u8, ...) {}
|
||||
E0046: r##"
|
||||
Items are missing in a trait implementation. Erroneous code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
trait Foo {
|
||||
fn foo();
|
||||
}
|
||||
@@ -468,7 +519,7 @@ fn foo() {} // ok!
|
||||
For example, the trait below has a method `foo` with a type parameter `T`,
|
||||
but the implementation of `foo` for the type `Bar` is missing this parameter:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
trait Foo {
|
||||
fn foo<T: Default>(x: T) -> Self;
|
||||
}
|
||||
@@ -491,7 +542,7 @@ fn foo(x: bool) -> Self { Bar }
|
||||
(`&self` and `u8`), but the implementation of `foo` for the type `Bar` omits
|
||||
the `u8` parameter:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
trait Foo {
|
||||
fn foo(&self, x: u8) -> bool;
|
||||
}
|
||||
@@ -512,7 +563,7 @@ fn foo(&self) -> bool { true }
|
||||
|
||||
Here are a couple examples of this error:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
trait Foo {
|
||||
fn foo(x: u16);
|
||||
fn bar(&self);
|
||||
@@ -534,14 +585,18 @@ fn bar(&mut self) { }
|
||||
It is not allowed to cast to a bool. If you are trying to cast a numeric type
|
||||
to a bool, you can compare it with zero instead:
|
||||
|
||||
```compile_fail
|
||||
let x = 5;
|
||||
|
||||
// Not allowed, won't compile
|
||||
let x_is_nonzero = x as bool;
|
||||
```
|
||||
|
||||
```
|
||||
let x = 5;
|
||||
|
||||
// Ok
|
||||
let x_is_nonzero = x != 0;
|
||||
|
||||
// Not allowed, won't compile
|
||||
let x_is_nonzero = x as bool;
|
||||
```
|
||||
"##,
|
||||
|
||||
@@ -553,7 +608,7 @@ fn bar(&mut self) { }
|
||||
|
||||
For a somewhat artificial example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
#![recursion_limit="2"]
|
||||
|
||||
struct Foo;
|
||||
@@ -583,7 +638,7 @@ fn main() {
|
||||
|
||||
An example using a closure:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
let f = |x| x * 3;
|
||||
let a = f(); // invalid, too few parameters
|
||||
let b = f(4); // this works!
|
||||
@@ -609,13 +664,13 @@ fn foo<F: Fn()>(f: F) {
|
||||
The most likely source of this error is using angle-bracket notation without
|
||||
wrapping the function argument type into a tuple, for example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
fn foo<F: Fn<i32>>(f: F) -> F::Output { f(3) }
|
||||
```
|
||||
|
||||
It can be fixed by adjusting the trait bound like this:
|
||||
|
||||
```
|
||||
```ignore
|
||||
fn foo<F: Fn<(i32,)>>(f: F) -> F::Output { f(3) }
|
||||
```
|
||||
|
||||
@@ -628,7 +683,7 @@ fn foo<F: Fn<(i32,)>>(f: F) -> F::Output { f(3) }
|
||||
takes a minimum number of arguments. For example, consider C's variadic `printf`
|
||||
function:
|
||||
|
||||
```
|
||||
```ignore
|
||||
extern crate libc;
|
||||
use libc::{ c_char, c_int };
|
||||
|
||||
@@ -640,7 +695,7 @@ fn foo<F: Fn<(i32,)>>(f: F) -> F::Output { f(3) }
|
||||
Using this declaration, it must be called with at least one argument, so
|
||||
simply calling `printf()` is invalid. But the following uses are allowed:
|
||||
|
||||
```
|
||||
```ignore
|
||||
unsafe {
|
||||
use std::ffi::CString;
|
||||
|
||||
@@ -655,13 +710,13 @@ fn foo<F: Fn<(i32,)>>(f: F) -> F::Output { f(3) }
|
||||
The number of arguments passed to a function must match the number of arguments
|
||||
specified in the function signature.
|
||||
|
||||
For example, a function like
|
||||
For example, a function like:
|
||||
|
||||
```
|
||||
fn f(a: u16, b: &str) {}
|
||||
```
|
||||
|
||||
must always be called with exactly two arguments, e.g. `f(2, "test")`.
|
||||
Must always be called with exactly two arguments, e.g. `f(2, "test")`.
|
||||
|
||||
Note, that Rust does not have a notion of optional function arguments or
|
||||
variadic functions (except for its C-FFI).
|
||||
@@ -672,7 +727,7 @@ fn f(a: u16, b: &str) {}
|
||||
enum variant, one of the fields was specified more than once. Erroneous code
|
||||
example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
struct Foo {
|
||||
x: i32
|
||||
}
|
||||
@@ -702,7 +757,7 @@ fn main() {
|
||||
This error indicates that during an attempt to build a struct or struct-like
|
||||
enum variant, one of the fields was not provided. Erroneous code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
struct Foo {
|
||||
x: i32,
|
||||
y: i32
|
||||
@@ -743,9 +798,9 @@ fn main() {
|
||||
item paths (ie, namespaced variables), dereferences, indexing expressions,
|
||||
and field references.
|
||||
|
||||
Let's start with some bad examples:
|
||||
Let's start with some erroneous code examples:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
use std::collections::LinkedList;
|
||||
|
||||
// Bad: assignment to non-lvalue expression
|
||||
@@ -758,7 +813,7 @@ fn some_func(i: &mut i32) {
|
||||
}
|
||||
```
|
||||
|
||||
And now some good examples:
|
||||
And now some working examples:
|
||||
|
||||
```
|
||||
let mut i : i32 = 0;
|
||||
@@ -777,7 +832,7 @@ fn some_func(i: &mut i32) {
|
||||
The compiler found a function whose body contains a `return;` statement but
|
||||
whose return type is not `()`. An example of this is:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
// error
|
||||
fn foo() -> u8 {
|
||||
return;
|
||||
@@ -797,13 +852,14 @@ fn foo() -> u8 {
|
||||
More details can be found here:
|
||||
https://doc.rust-lang.org/reference.html#lvalues-rvalues-and-temporaries
|
||||
|
||||
Now, we can go further. Here are some bad examples:
|
||||
Now, we can go further. Here are some erroneous code examples:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
struct SomeStruct {
|
||||
x: i32,
|
||||
y: i32
|
||||
}
|
||||
|
||||
const SOME_CONST : i32 = 12;
|
||||
|
||||
fn some_other_func() {}
|
||||
@@ -817,7 +873,7 @@ fn some_function() {
|
||||
}
|
||||
```
|
||||
|
||||
And now let's give good examples:
|
||||
And now let's give working examples:
|
||||
|
||||
```
|
||||
struct SomeStruct {
|
||||
@@ -842,7 +898,7 @@ fn some_func(x: &mut i32) {
|
||||
|
||||
Example of erroneous code:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
enum Foo { FirstValue(i32) };
|
||||
|
||||
let u = Foo::FirstValue { value: 0i32 }; // error: Foo::FirstValue
|
||||
@@ -876,7 +932,7 @@ fn main() {
|
||||
|
||||
Here's an example of a struct that has this problem:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
struct Foo { x: Box<Foo> } // error
|
||||
```
|
||||
|
||||
@@ -895,12 +951,22 @@ struct Foo { x: Option<Box<Foo>> }
|
||||
reason about how to use SIMD with them. This error will occur if the types
|
||||
are generic.
|
||||
|
||||
```
|
||||
#[simd]
|
||||
struct Bad<T>(T, T, T); // This will cause an error
|
||||
This will cause an error:
|
||||
|
||||
```compile_fail
|
||||
#![feature(simd)]
|
||||
|
||||
#[simd]
|
||||
struct Good(u32, u32, u32); // This will not
|
||||
struct Bad<T>(T, T, T);
|
||||
```
|
||||
|
||||
This will not:
|
||||
|
||||
```
|
||||
#![feature(simd)]
|
||||
|
||||
#[simd]
|
||||
struct Good(u32, u32, u32);
|
||||
```
|
||||
"##,
|
||||
|
||||
@@ -909,12 +975,22 @@ struct Foo { x: Option<Box<Foo>> }
|
||||
it doesn't make sense to try to use SIMD operations when there are no values to
|
||||
operate on.
|
||||
|
||||
```
|
||||
#[simd]
|
||||
struct Bad; // This will cause an error
|
||||
This will cause an error:
|
||||
|
||||
```compile_fail
|
||||
#![feature(simd)]
|
||||
|
||||
#[simd]
|
||||
struct Good(u32); // This will not
|
||||
struct Bad;
|
||||
```
|
||||
|
||||
This will not:
|
||||
|
||||
```
|
||||
#![feature(simd)]
|
||||
|
||||
#[simd]
|
||||
struct Good(u32);
|
||||
```
|
||||
"##,
|
||||
|
||||
@@ -923,26 +999,45 @@ struct Foo { x: Option<Box<Foo>> }
|
||||
struct, the types in the struct must all be of the same type, or the compiler
|
||||
will trigger this error.
|
||||
|
||||
```
|
||||
#[simd]
|
||||
struct Bad(u16, u32, u32); // This will cause an error
|
||||
This will cause an error:
|
||||
|
||||
```compile_fail
|
||||
#![feature(simd)]
|
||||
|
||||
#[simd]
|
||||
struct Good(u32, u32, u32); // This will not
|
||||
struct Bad(u16, u32, u32);
|
||||
```
|
||||
|
||||
This will not:
|
||||
|
||||
```
|
||||
#![feature(simd)]
|
||||
|
||||
#[simd]
|
||||
struct Good(u32, u32, u32);
|
||||
```
|
||||
"##,
|
||||
|
||||
E0077: r##"
|
||||
When using the `#[simd]` attribute on a tuple struct, the elements in the tuple
|
||||
must be machine types so SIMD operations can be applied to them.
|
||||
|
||||
```
|
||||
#[simd]
|
||||
struct Bad(String); // This will cause an error
|
||||
This will cause an error:
|
||||
|
||||
```compile_fail
|
||||
#![feature(simd)]
|
||||
|
||||
#[simd]
|
||||
struct Good(u32, u32, u32); // This will not
|
||||
struct Bad(String);
|
||||
```
|
||||
|
||||
This will not:
|
||||
|
||||
```
|
||||
#![feature(simd)]
|
||||
|
||||
#[simd]
|
||||
struct Good(u32, u32, u32);
|
||||
```
|
||||
"##,
|
||||
|
||||
@@ -951,15 +1046,15 @@ struct Foo { x: Option<Box<Foo>> }
|
||||
representation. This error indicates that the value provided is not an integer
|
||||
literal and is therefore invalid.
|
||||
|
||||
For example, in the following code,
|
||||
For example, in the following code:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
enum Foo {
|
||||
Q = "32"
|
||||
}
|
||||
```
|
||||
|
||||
we try to set the representation to a string.
|
||||
We try to set the representation to a string.
|
||||
|
||||
There's no general fix for this; if you can work with an integer then just set
|
||||
it to one:
|
||||
@@ -970,7 +1065,7 @@ enum Foo {
|
||||
}
|
||||
```
|
||||
|
||||
however if you actually wanted a mapping between variants and non-integer
|
||||
However if you actually wanted a mapping between variants and non-integer
|
||||
objects, it may be preferable to use a method with a match instead:
|
||||
|
||||
```
|
||||
@@ -990,7 +1085,7 @@ fn get_str(&self) -> &'static str {
|
||||
integer expression provided as an enum discriminant. Attempting to divide by 0
|
||||
or causing integer overflow are two ways to induce this error. For example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
enum Enum {
|
||||
X = (1 << 500),
|
||||
Y = (1 / 0)
|
||||
@@ -1009,6 +1104,15 @@ enum Enum {
|
||||
This error indicates that the same value was used for two or more variants,
|
||||
making them impossible to tell apart.
|
||||
|
||||
```compile_fail
|
||||
// Bad.
|
||||
enum Enum {
|
||||
P = 3,
|
||||
X = 3,
|
||||
Y = 5
|
||||
}
|
||||
```
|
||||
|
||||
```
|
||||
// Good.
|
||||
enum Enum {
|
||||
@@ -1016,20 +1120,13 @@ enum Enum {
|
||||
X = 3,
|
||||
Y = 5
|
||||
}
|
||||
|
||||
// Bad.
|
||||
enum Enum {
|
||||
P = 3,
|
||||
X = 3,
|
||||
Y = 5
|
||||
}
|
||||
```
|
||||
|
||||
Note that variants without a manually specified discriminant are numbered from
|
||||
top to bottom starting from 0, so clashes can occur with seemingly unrelated
|
||||
variants.
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
enum Bad {
|
||||
X,
|
||||
Y = 0
|
||||
@@ -1046,7 +1143,7 @@ enum Bad {
|
||||
an integer literal given as a discriminant is not a member of the discriminant
|
||||
type. For example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
#[repr(u8)]
|
||||
enum Thing {
|
||||
A = 1024,
|
||||
@@ -1075,7 +1172,7 @@ enum Empty {}
|
||||
E0087: r##"
|
||||
Too many type parameters were supplied for a function. For example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
fn foo<T>() {}
|
||||
|
||||
fn main() {
|
||||
@@ -1090,7 +1187,7 @@ fn main() {
|
||||
E0088: r##"
|
||||
You gave too many lifetime parameters. Erroneous code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
fn f() {}
|
||||
|
||||
fn main() {
|
||||
@@ -1135,7 +1232,7 @@ fn main() {
|
||||
E0089: r##"
|
||||
Not enough type parameters were supplied for a function. For example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
fn foo<T, U>() {}
|
||||
|
||||
fn main() {
|
||||
@@ -1146,7 +1243,7 @@ fn main() {
|
||||
Note that if a function takes multiple type parameters but you want the compiler
|
||||
to infer some of them, you can use type placeholders:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
fn foo<T, U>(x: T) {}
|
||||
|
||||
fn main() {
|
||||
@@ -1161,7 +1258,7 @@ fn main() {
|
||||
You gave an unnecessary type parameter in a type alias. Erroneous code
|
||||
example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
type Foo<T> = u32; // error: type parameter `T` is unused
|
||||
// or:
|
||||
type Foo<A,B> = Box<A>; // error: type parameter `B` is unused
|
||||
@@ -1171,7 +1268,7 @@ fn main() {
|
||||
|
||||
```
|
||||
type Foo = u32; // ok!
|
||||
type Foo<A> = Box<A>; // ok!
|
||||
type Foo2<A> = Box<A>; // ok!
|
||||
```
|
||||
"##,
|
||||
|
||||
@@ -1179,7 +1276,7 @@ fn main() {
|
||||
You tried to declare an undefined atomic operation function.
|
||||
Erroneous code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
#![feature(intrinsics)]
|
||||
|
||||
extern "rust-intrinsic" {
|
||||
@@ -1204,7 +1301,7 @@ fn main() {
|
||||
E0093: r##"
|
||||
You declared an unknown intrinsic function. Erroneous code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
#![feature(intrinsics)]
|
||||
|
||||
extern "rust-intrinsic" {
|
||||
@@ -1241,7 +1338,7 @@ fn main() {
|
||||
You gave an invalid number of type parameters to an intrinsic function.
|
||||
Erroneous code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
#![feature(intrinsics)]
|
||||
|
||||
extern "rust-intrinsic" {
|
||||
@@ -1267,7 +1364,7 @@ fn main() {
|
||||
You hit this error because the compiler lacks the information to
|
||||
determine a type for this expression. Erroneous code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
fn main() {
|
||||
let x = |_| {}; // error: cannot determine a type for this expression
|
||||
}
|
||||
@@ -1293,7 +1390,7 @@ fn main() {
|
||||
You hit this error because the compiler lacks information to
|
||||
determine a type for this variable. Erroneous code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
fn demo(devil: fn () -> !) {
|
||||
let x: &_ = devil();
|
||||
// error: cannot determine a type for this local variable
|
||||
@@ -1309,7 +1406,9 @@ fn main() {
|
||||
To solve this situation, constrain the type of the variable.
|
||||
Examples:
|
||||
|
||||
```
|
||||
```no_run
|
||||
#![allow(unused_variables)]
|
||||
|
||||
fn some_func(x: &u32) {
|
||||
// some code
|
||||
}
|
||||
@@ -1338,7 +1437,7 @@ fn main() {
|
||||
|
||||
Here are some simple examples of where you'll run into this error:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
struct Foo { x: &bool } // error
|
||||
struct Foo<'a> { x: &'a bool } // correct
|
||||
|
||||
@@ -1366,15 +1465,15 @@ enum Bar<'a> { A(u8), B(&'a bool), } // correct
|
||||
|
||||
Here are some examples of elision errors:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
// error, no input lifetimes
|
||||
fn foo() -> &str { ... }
|
||||
fn foo() -> &str { }
|
||||
|
||||
// error, `x` and `y` have distinct lifetimes inferred
|
||||
fn bar(x: &str, y: &str) -> &str { ... }
|
||||
fn bar(x: &str, y: &str) -> &str { }
|
||||
|
||||
// error, `y`'s lifetime is inferred to be distinct from `x`'s
|
||||
fn baz<'a>(x: &'a str, y: &str) -> &str { ... }
|
||||
fn baz<'a>(x: &'a str, y: &str) -> &str { }
|
||||
```
|
||||
|
||||
[book-le]: https://doc.rust-lang.org/nightly/book/lifetimes.html#lifetime-elision
|
||||
@@ -1386,7 +1485,7 @@ fn baz<'a>(x: &'a str, y: &str) -> &str { ... }
|
||||
|
||||
Some basic examples include:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
struct Foo<'a>(&'a str);
|
||||
enum Bar { A, B, C }
|
||||
|
||||
@@ -1399,7 +1498,7 @@ struct Baz<'a> {
|
||||
Here's an example that is currently an error, but may work in a future version
|
||||
of Rust:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
struct Foo<'a>(&'a str);
|
||||
|
||||
trait Quux { }
|
||||
@@ -1417,8 +1516,8 @@ impl Quux for Foo { } // error: expected 1, found 0
|
||||
where the type was defined. For example, an `impl` block as below is not allowed
|
||||
since `Vec` is defined in the standard library:
|
||||
|
||||
```
|
||||
impl Vec<u8> { ... } // error
|
||||
```compile_fail
|
||||
impl Vec<u8> { } // error
|
||||
```
|
||||
|
||||
To fix this problem, you can do either of these things:
|
||||
@@ -1431,10 +1530,10 @@ impl Vec<u8> { ... } // error
|
||||
Note that using the `type` keyword does not work here because `type` only
|
||||
introduces a type alias:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
type Bytes = Vec<u8>;
|
||||
|
||||
impl Bytes { ... } // error, same as above
|
||||
impl Bytes { } // error, same as above
|
||||
```
|
||||
"##,
|
||||
|
||||
@@ -1449,14 +1548,14 @@ trait defined in another crate) where
|
||||
|
||||
Here's one example of this error:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
impl Drop for u32 {}
|
||||
```
|
||||
|
||||
To avoid this kind of error, ensure that at least one local type is referenced
|
||||
by the `impl`:
|
||||
|
||||
```
|
||||
```ignore
|
||||
pub struct Foo; // you define your type in your crate
|
||||
|
||||
impl Drop for Foo { // and you can implement the trait on it!
|
||||
@@ -1492,7 +1591,7 @@ fn get(&self) -> usize { 0 }
|
||||
You're trying to write an inherent implementation for something which isn't a
|
||||
struct nor an enum. Erroneous code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
impl (u8, u8) { // error: no base type found for inherent implementation
|
||||
fn get_state(&self) -> String {
|
||||
// ...
|
||||
@@ -1536,7 +1635,7 @@ fn get_state(&self) -> String {
|
||||
There are conflicting trait implementations for the same type.
|
||||
Example of erroneous code:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
trait MyTrait {
|
||||
fn get(&self) -> usize;
|
||||
}
|
||||
@@ -1561,6 +1660,10 @@ fn get(&self) -> usize { self.value }
|
||||
this is an error. So, when you write:
|
||||
|
||||
```
|
||||
trait MyTrait {
|
||||
fn get(&self) -> usize;
|
||||
}
|
||||
|
||||
impl<T> MyTrait for T {
|
||||
fn get(&self) -> usize { 0 }
|
||||
}
|
||||
@@ -1593,7 +1696,7 @@ fn main() {
|
||||
An attempt was made to implement Drop on a trait, which is not allowed: only
|
||||
structs and enums can implement Drop. An example causing this error:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
trait MyTrait {}
|
||||
|
||||
impl Drop for MyTrait {
|
||||
@@ -1634,7 +1737,7 @@ fn drop(&mut self) {}
|
||||
|
||||
Examples of this error include:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
fn foo() -> _ { 5 } // error, explicitly write out the return type instead
|
||||
|
||||
static BAR: _ = "test"; // error, explicitly write out the type instead
|
||||
@@ -1665,10 +1768,10 @@ fn main() {
|
||||
You declared two fields of a struct with the same name. Erroneous code
|
||||
example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
struct Foo {
|
||||
field1: i32,
|
||||
field1: i32 // error: field is already declared
|
||||
field1: i32, // error: field is already declared
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1677,7 +1780,7 @@ struct Foo {
|
||||
```
|
||||
struct Foo {
|
||||
field1: i32,
|
||||
field2: i32 // ok!
|
||||
field2: i32, // ok!
|
||||
}
|
||||
```
|
||||
"##,
|
||||
@@ -1686,8 +1789,8 @@ struct Foo {
|
||||
Type parameter defaults can only use parameters that occur before them.
|
||||
Erroneous code example:
|
||||
|
||||
```
|
||||
pub struct Foo<T=U, U=()> {
|
||||
```compile_fail
|
||||
struct Foo<T=U, U=()> {
|
||||
field1: T,
|
||||
filed2: U,
|
||||
}
|
||||
@@ -1699,7 +1802,7 @@ pub struct Foo<T=U, U=()> {
|
||||
by doing:
|
||||
|
||||
```
|
||||
pub struct Foo<U=(), T=U> {
|
||||
struct Foo<U=(), T=U> {
|
||||
field1: T,
|
||||
filed2: U,
|
||||
}
|
||||
@@ -1713,7 +1816,7 @@ pub struct Foo<U=(), T=U> {
|
||||
You declared a pattern as an argument in a foreign function declaration.
|
||||
Erroneous code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
extern {
|
||||
fn foo((a, b): (u32, u32)); // error: patterns aren't allowed in foreign
|
||||
// function declarations
|
||||
@@ -1731,7 +1834,11 @@ struct SomeStruct {
|
||||
extern {
|
||||
fn foo(s: SomeStruct); // ok!
|
||||
}
|
||||
// or
|
||||
```
|
||||
|
||||
Or:
|
||||
|
||||
```
|
||||
extern {
|
||||
fn foo(a: (u32, u32)); // ok!
|
||||
}
|
||||
@@ -1743,7 +1850,7 @@ struct SomeStruct {
|
||||
parameters. When `main` is present, it must take no arguments and return `()`.
|
||||
Erroneous code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
fn main<T>() { // error: main function is not allowed to have type parameters
|
||||
}
|
||||
```
|
||||
@@ -1753,7 +1860,7 @@ fn main<T>() { // error: main function is not allowed to have type parameters
|
||||
It is not possible to declare type parameters on a function that has the `start`
|
||||
attribute. Such a function must have the following type signature:
|
||||
|
||||
```
|
||||
```ignore
|
||||
fn(isize, *const *const u8) -> isize;
|
||||
```
|
||||
"##,
|
||||
@@ -1762,12 +1869,12 @@ fn main<T>() { // error: main function is not allowed to have type parameters
|
||||
This error means that an attempt was made to match an enum variant as a
|
||||
struct type when the variant isn't a struct type:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
enum Foo { B(u32) }
|
||||
|
||||
fn bar(foo: Foo) -> u32 {
|
||||
match foo {
|
||||
Foo::B{i} => i // error 0163
|
||||
B{i} => i, // error E0163
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -1775,25 +1882,26 @@ fn bar(foo: Foo) -> u32 {
|
||||
Try using `()` instead:
|
||||
|
||||
```
|
||||
enum Foo { B(u32) }
|
||||
|
||||
fn bar(foo: Foo) -> u32 {
|
||||
match foo {
|
||||
Foo::B(i) => i
|
||||
Foo::B(i) => i,
|
||||
}
|
||||
}
|
||||
```
|
||||
"##,
|
||||
|
||||
E0164: r##"
|
||||
|
||||
This error means that an attempt was made to match a struct type enum
|
||||
variant as a non-struct type:
|
||||
|
||||
```
|
||||
enum Foo { B{ i: u32 } }
|
||||
```compile_fail
|
||||
enum Foo { B { i: u32 } }
|
||||
|
||||
fn bar(foo: Foo) -> u32 {
|
||||
match foo {
|
||||
Foo::B(i) => i // error 0164
|
||||
Foo::B(i) => i, // error E0164
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -1801,21 +1909,22 @@ fn bar(foo: Foo) -> u32 {
|
||||
Try using `{}` instead:
|
||||
|
||||
```
|
||||
enum Foo { B { i: u32 } }
|
||||
|
||||
fn bar(foo: Foo) -> u32 {
|
||||
match foo {
|
||||
Foo::B{i} => i
|
||||
Foo::B{i} => i,
|
||||
}
|
||||
}
|
||||
```
|
||||
"##,
|
||||
|
||||
|
||||
E0166: r##"
|
||||
This error means that the compiler found a return expression in a function
|
||||
marked as diverging. A function diverges if it has `!` in the place of the
|
||||
return type in its signature. For example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
fn foo() -> ! { return; } // error
|
||||
```
|
||||
|
||||
@@ -1828,7 +1937,7 @@ fn bar(foo: Foo) -> u32 {
|
||||
This error means that an attempt was made to specify the type of a variable with
|
||||
a combination of a concrete type and a trait. Consider the following example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
fn foo(bar: i32+std::fmt::Display) {}
|
||||
```
|
||||
|
||||
@@ -1857,7 +1966,7 @@ fn foo(bar: i32) {}
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
trait Foo {}
|
||||
|
||||
struct Bar<'a> {
|
||||
@@ -1889,7 +1998,7 @@ struct Bar<'a> {
|
||||
|
||||
Here's an example of this error:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
trait Foo {
|
||||
fn foo();
|
||||
}
|
||||
@@ -1910,7 +2019,7 @@ fn foo(&self) {}
|
||||
|
||||
Here's an example of this error:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
trait Foo {
|
||||
fn foo(&self);
|
||||
}
|
||||
@@ -1929,7 +2038,7 @@ fn foo() {}
|
||||
Trait objects need to have all associated types specified. Erroneous code
|
||||
example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
trait Trait {
|
||||
type Bar;
|
||||
}
|
||||
@@ -1960,7 +2069,7 @@ trait Trait {
|
||||
`where` clauses must use generic type parameters: it does not make sense to use
|
||||
them otherwise. An example causing this error:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
trait Foo {
|
||||
fn bar(&self);
|
||||
}
|
||||
@@ -1979,6 +2088,14 @@ fn bar(&self) { }
|
||||
something like the following:
|
||||
|
||||
```
|
||||
trait Foo {
|
||||
fn bar(&self);
|
||||
}
|
||||
|
||||
#[derive(Copy,Clone)]
|
||||
struct Wrapper<T> {
|
||||
Wrapped: T
|
||||
}
|
||||
impl <T> Foo for Wrapper<T> where Wrapper<T>: Clone {
|
||||
fn bar(&self) { }
|
||||
}
|
||||
@@ -1997,7 +2114,7 @@ fn bar(&self) { }
|
||||
A type parameter was declared which shadows an existing one. An example of this
|
||||
error:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
trait Foo<T> {
|
||||
fn do_something(&self) -> T;
|
||||
fn do_something_else<T: Clone>(&self, bar: T);
|
||||
@@ -2013,7 +2130,7 @@ trait Foo<T> {
|
||||
Your method's lifetime parameters do not match the trait declaration.
|
||||
Erroneous code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
trait Trait {
|
||||
fn bar<'a,'b:'a>(x: &'a str, y: &'b str);
|
||||
}
|
||||
@@ -2052,7 +2169,7 @@ fn t<'a,'b:'a>(x: &'a str, y: &'b str) { // ok!
|
||||
implementing an unsafe trait. Removing the `unsafe` keyword from the inherent
|
||||
implementation will resolve this error.
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
struct Foo;
|
||||
|
||||
// this will cause this error
|
||||
@@ -2068,22 +2185,38 @@ impl Foo { }
|
||||
so negative implementations are always safe and never need to be marked as
|
||||
unsafe.
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
#![feature(optin_builtin_traits)]
|
||||
|
||||
struct Foo;
|
||||
|
||||
// unsafe is unnecessary
|
||||
unsafe impl !Clone for Foo { }
|
||||
// this will compile
|
||||
impl !Clone for Foo { }
|
||||
```
|
||||
|
||||
This will compile:
|
||||
|
||||
```
|
||||
#![feature(optin_builtin_traits)]
|
||||
|
||||
struct Foo;
|
||||
|
||||
trait Enterprise {}
|
||||
|
||||
impl Enterprise for .. { }
|
||||
|
||||
impl !Enterprise for Foo { }
|
||||
```
|
||||
|
||||
Please note that negative impls are only allowed for traits with default impls.
|
||||
"##,
|
||||
|
||||
E0199: r##"
|
||||
Safe traits should not have unsafe implementations, therefore marking an
|
||||
implementation for a safe trait unsafe will cause a compiler error. Removing the
|
||||
unsafe marker on the trait noted in the error will resolve this problem.
|
||||
implementation for a safe trait unsafe will cause a compiler error. Removing
|
||||
the unsafe marker on the trait noted in the error will resolve this problem.
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
struct Foo;
|
||||
|
||||
trait Bar { }
|
||||
@@ -2100,7 +2233,7 @@ impl Bar for Foo { }
|
||||
implementation for an unsafe trait isn't marked as unsafe. This may be resolved
|
||||
by marking the unsafe implementation as unsafe.
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
struct Foo;
|
||||
|
||||
unsafe trait Bar { }
|
||||
@@ -2118,7 +2251,7 @@ unsafe impl Bar for Foo { }
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
struct Foo(u8);
|
||||
|
||||
impl Foo {
|
||||
@@ -2158,7 +2291,7 @@ fn baz(&self) -> bool { self.0 > 5 }
|
||||
fields does not implement `Copy`. To fix this, you must implement `Copy` for the
|
||||
mentioned field. Note that this may not be possible, as in the example of
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
struct Foo {
|
||||
foo : Vec<u32>,
|
||||
}
|
||||
@@ -2170,7 +2303,7 @@ impl Copy for Foo { }
|
||||
|
||||
Here's another example that will fail:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
#[derive(Copy)]
|
||||
struct Foo<'a> {
|
||||
ty: &'a mut bool,
|
||||
@@ -2186,7 +2319,7 @@ struct Foo<'a> {
|
||||
variants does not implement `Copy`. To fix this, you must implement `Copy` for
|
||||
the mentioned variant. Note that this may not be possible, as in the example of
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
enum Foo {
|
||||
Bar(Vec<u32>),
|
||||
Baz,
|
||||
@@ -2199,7 +2332,7 @@ impl Copy for Foo { }
|
||||
|
||||
Here's another example that will fail:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
#[derive(Copy)]
|
||||
enum Foo<'a> {
|
||||
Bar(&'a mut bool),
|
||||
@@ -2216,7 +2349,7 @@ enum Foo<'a> {
|
||||
examples will fail, because neither `i32` (primitive type) nor `&'static Bar`
|
||||
(reference to `Bar`) is a struct or enum:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
type Foo = i32;
|
||||
impl Copy for Foo { } // error
|
||||
|
||||
@@ -2230,7 +2363,7 @@ impl Copy for &'static Bar { } // error
|
||||
You declared an unused type parameter when implementing a trait on an object.
|
||||
Erroneous code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
trait MyTrait {
|
||||
fn get(&self) -> usize;
|
||||
}
|
||||
@@ -2272,18 +2405,18 @@ fn get(&self) -> usize {
|
||||
If `ForeignTrait` is a trait defined in some external crate `foo`, then the
|
||||
following trait `impl` is an error:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
extern crate foo;
|
||||
use foo::ForeignTrait;
|
||||
|
||||
impl<T> ForeignTrait for T { ... } // error
|
||||
impl<T> ForeignTrait for T { } // error
|
||||
```
|
||||
|
||||
To work around this, it can be covered with a local type, `MyType`:
|
||||
|
||||
```
|
||||
```ignore
|
||||
struct MyType<T>(T);
|
||||
impl<T> ForeignTrait for MyType<T> { ... } // Ok
|
||||
impl<T> ForeignTrait for MyType<T> { } // Ok
|
||||
```
|
||||
|
||||
Please note that a type alias is not sufficient.
|
||||
@@ -2292,9 +2425,9 @@ impl<T> ForeignTrait for MyType<T> { ... } // Ok
|
||||
named `ForeignTrait2` that takes two type parameters. Then this `impl` results
|
||||
in the same rule violation:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
struct MyType2;
|
||||
impl<T> ForeignTrait2<T, MyType<T>> for MyType2 { ... } // error
|
||||
impl<T> ForeignTrait2<T, MyType<T>> for MyType2 { } // error
|
||||
```
|
||||
|
||||
The reason for this is that there are two appearances of type parameter `T` in
|
||||
@@ -2303,8 +2436,8 @@ impl<T> ForeignTrait2<T, MyType<T>> for MyType2 { ... } // error
|
||||
|
||||
Consider one more example:
|
||||
|
||||
```
|
||||
impl<T> ForeignTrait2<MyType<T>, T> for MyType2 { ... } // Ok
|
||||
```ignore
|
||||
impl<T> ForeignTrait2<MyType<T>, T> for MyType2 { } // Ok
|
||||
```
|
||||
|
||||
This only differs from the previous `impl` in that the parameters `T` and
|
||||
@@ -2314,7 +2447,7 @@ impl<T> ForeignTrait2<MyType<T>, T> for MyType2 { ... } // Ok
|
||||
To see why that last example was allowed, you need to understand the general
|
||||
rule. Unfortunately this rule is a bit tricky to state. Consider an `impl`:
|
||||
|
||||
```
|
||||
```ignore
|
||||
impl<P1, ..., Pm> ForeignTrait<T1, ..., Tn> for T0 { ... }
|
||||
```
|
||||
|
||||
@@ -2333,7 +2466,7 @@ impl<P1, ..., Pm> ForeignTrait<T1, ..., Tn> for T0 { ... }
|
||||
You used a function or type which doesn't fit the requirements for where it was
|
||||
used. Erroneous code examples:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
#![feature(intrinsics)]
|
||||
|
||||
extern "rust-intrinsic" {
|
||||
@@ -2379,7 +2512,7 @@ fn x(self: Rc<Foo>) {}
|
||||
The second case example is a bit particular : the main function must always
|
||||
have this definition:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
fn main();
|
||||
```
|
||||
|
||||
@@ -2390,6 +2523,7 @@ fn x(self: Rc<Foo>) {}
|
||||
|
||||
```
|
||||
let x = 1u8;
|
||||
|
||||
match x {
|
||||
0u8...3u8 => (), // ok!
|
||||
_ => ()
|
||||
@@ -2412,7 +2546,7 @@ fn x(self: Box<Foo>) {} // ok!
|
||||
A generic type was described using parentheses rather than angle brackets. For
|
||||
example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
fn main() {
|
||||
let v: Vec(&str) = vec!["foo"];
|
||||
}
|
||||
@@ -2427,7 +2561,7 @@ fn main() {
|
||||
You used an associated type which isn't defined in the trait.
|
||||
Erroneous code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
trait Trait {
|
||||
type Bar;
|
||||
}
|
||||
@@ -2452,7 +2586,7 @@ trait Trait {
|
||||
An attempt was made to retrieve an associated type, but the type was ambiguous.
|
||||
For example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
trait T1 {}
|
||||
trait T2 {}
|
||||
|
||||
@@ -2478,8 +2612,18 @@ fn do_something() {
|
||||
following syntax:
|
||||
|
||||
```
|
||||
fn do_something() {
|
||||
let _: <Self as Bar>::A;
|
||||
trait T1 {}
|
||||
trait T2 {}
|
||||
|
||||
trait Foo {
|
||||
type A: T1;
|
||||
}
|
||||
|
||||
trait Bar : Foo {
|
||||
type A: T2;
|
||||
fn do_something() {
|
||||
let _: <Self as Bar>::A;
|
||||
}
|
||||
}
|
||||
```
|
||||
"##,
|
||||
@@ -2488,7 +2632,7 @@ fn do_something() {
|
||||
An attempt was made to retrieve an associated type, but the type was ambiguous.
|
||||
For example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
trait MyTrait {type X; }
|
||||
|
||||
fn main() {
|
||||
@@ -2523,7 +2667,7 @@ fn main() {
|
||||
You attempted to use multiple types as bounds for a closure or trait object.
|
||||
Rust does not currently support this. A simple example that causes this error:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
fn main() {
|
||||
let _: Box<std::io::Read+std::io::Write>;
|
||||
}
|
||||
@@ -2543,7 +2687,9 @@ fn main() {
|
||||
E0232: r##"
|
||||
The attribute must have a value. Erroneous code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
#![feature(on_unimplemented)]
|
||||
|
||||
#[rustc_on_unimplemented] // error: this attribute must have a value
|
||||
trait Bar {}
|
||||
```
|
||||
@@ -2551,6 +2697,8 @@ trait Bar {}
|
||||
Please supply the missing value of the attribute. Example:
|
||||
|
||||
```
|
||||
#![feature(on_unimplemented)]
|
||||
|
||||
#[rustc_on_unimplemented = "foo"] // ok!
|
||||
trait Bar {}
|
||||
```
|
||||
@@ -2563,7 +2711,7 @@ trait Bar {}
|
||||
For example, the `Foo` struct below is defined to be generic in `T`, but the
|
||||
type parameter is missing in the definition of `Bar`:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
struct Foo<T> { x: T }
|
||||
|
||||
struct Bar { x: Foo }
|
||||
@@ -2577,7 +2725,7 @@ struct Bar { x: Foo }
|
||||
For example, the `Foo` struct below has no type parameters, but is supplied
|
||||
with two in the definition of `Bar`:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
struct Foo { x: bool }
|
||||
|
||||
struct Bar<S, T> { x: Foo<S, T> }
|
||||
@@ -2588,7 +2736,7 @@ struct Bar<S, T> { x: Foo<S, T> }
|
||||
This error indicates an attempt to use a value where a type is expected. For
|
||||
example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
enum Foo {
|
||||
Bar(u32)
|
||||
}
|
||||
@@ -2609,7 +2757,7 @@ fn do_something(x: Foo::Bar) { }
|
||||
|
||||
Some examples of code that produces this error are:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
const A: [u32; "hello"] = []; // error
|
||||
const B: [u32; true] = []; // error
|
||||
const C: [u32; 0.0] = []; // error
|
||||
@@ -2621,7 +2769,7 @@ fn do_something(x: Foo::Bar) { }
|
||||
|
||||
Some examples of this error are:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
// divide by zero in the length expression
|
||||
const A: [u32; 1/0] = [];
|
||||
|
||||
@@ -2645,7 +2793,7 @@ fn foo() -> usize { 12 }
|
||||
A cross-crate opt-out trait was implemented on something which wasn't a struct
|
||||
or enum type. Erroneous code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
#![feature(optin_builtin_traits)]
|
||||
|
||||
struct Foo;
|
||||
@@ -2674,7 +2822,9 @@ unsafe impl Send for &'static Foo {
|
||||
An associated const was implemented when another trait item was expected.
|
||||
Erroneous code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
#![feature(associated_consts)]
|
||||
|
||||
trait Foo {
|
||||
type N;
|
||||
}
|
||||
@@ -2701,8 +2851,15 @@ trait Foo {
|
||||
impl Foo for Bar {
|
||||
type N = u32; // ok!
|
||||
}
|
||||
```
|
||||
|
||||
Or:
|
||||
|
||||
```
|
||||
#![feature(associated_consts)]
|
||||
|
||||
struct Bar;
|
||||
|
||||
// or:
|
||||
trait Foo {
|
||||
const N : u32;
|
||||
}
|
||||
@@ -2717,7 +2874,7 @@ impl Foo for Bar {
|
||||
A method was implemented when another trait item was expected. Erroneous
|
||||
code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
struct Bar;
|
||||
|
||||
trait Foo {
|
||||
@@ -2737,6 +2894,8 @@ fn N() {}
|
||||
verify that you are indeed implementing the correct trait items. Example:
|
||||
|
||||
```
|
||||
#![feature(associated_consts)]
|
||||
|
||||
struct Bar;
|
||||
|
||||
trait Foo {
|
||||
@@ -2757,7 +2916,7 @@ fn M() {} // ok!
|
||||
An associated type was implemented when another trait item was expected.
|
||||
Erroneous code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
struct Bar;
|
||||
|
||||
trait Foo {
|
||||
@@ -2784,8 +2943,15 @@ trait Foo {
|
||||
impl Foo for Bar {
|
||||
type N = u32; // ok!
|
||||
}
|
||||
```
|
||||
|
||||
Or:
|
||||
|
||||
```
|
||||
#![feature(associated_consts)]
|
||||
|
||||
struct Bar;
|
||||
|
||||
//or:
|
||||
trait Foo {
|
||||
const N : u32;
|
||||
}
|
||||
@@ -2802,7 +2968,7 @@ impl Foo for Bar {
|
||||
|
||||
Here's an example of this error:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
trait Foo {
|
||||
const BAR: bool;
|
||||
}
|
||||
@@ -2819,7 +2985,7 @@ impl Foo for Bar {
|
||||
You cannot use associated items other than constant items as patterns. This
|
||||
includes method items. Example of erroneous code:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
enum B {}
|
||||
|
||||
impl B {
|
||||
@@ -2856,7 +3022,9 @@ fn main() {
|
||||
type parameter or `Self`. This is not supported yet. An example causing this
|
||||
error is shown below:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
#![feature(associated_consts)]
|
||||
|
||||
trait Foo {
|
||||
const BAR: f64;
|
||||
}
|
||||
@@ -2872,10 +3040,18 @@ fn get_bar_bad<F: Foo>(t: F) -> f64 {
|
||||
}
|
||||
```
|
||||
|
||||
Currently, the value of `BAR` for a particular type can only be accessed through
|
||||
a concrete type, as shown below:
|
||||
Currently, the value of `BAR` for a particular type can only be accessed
|
||||
through a concrete type, as shown below:
|
||||
|
||||
```ignore
|
||||
#![feature(associated_consts)]
|
||||
|
||||
trait Foo {
|
||||
const BAR: f64;
|
||||
}
|
||||
|
||||
struct MyStruct;
|
||||
|
||||
```
|
||||
fn get_bar_good() -> f64 {
|
||||
<MyStruct as Foo>::BAR
|
||||
}
|
||||
@@ -2886,7 +3062,7 @@ fn get_bar_good() -> f64 {
|
||||
An attempt was made to implement `Drop` on a concrete specialization of a
|
||||
generic type. An example is shown below:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
struct Foo<T> {
|
||||
t: T
|
||||
}
|
||||
@@ -2919,7 +3095,7 @@ fn drop(&mut self) {}
|
||||
An attempt was made to implement `Drop` on a specialization of a generic type.
|
||||
An example is shown below:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
trait Foo{}
|
||||
|
||||
struct MyStruct<T> {
|
||||
@@ -2957,9 +3133,9 @@ fn drop(&mut self) {}
|
||||
This error indicates that a binary assignment operator like `+=` or `^=` was
|
||||
applied to a type that doesn't support it. For example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
let mut x = 12f32; // error: binary operation `<<` cannot be applied to
|
||||
// type `f32`
|
||||
// type `f32`
|
||||
|
||||
x <<= 2;
|
||||
```
|
||||
@@ -2967,7 +3143,7 @@ fn drop(&mut self) {}
|
||||
To fix this error, please check that this type implements this binary
|
||||
operation. Example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
let x = 12u32; // the `u32` type does implement the `ShlAssign` trait
|
||||
|
||||
x <<= 2; // ok!
|
||||
@@ -2980,7 +3156,7 @@ fn drop(&mut self) {}
|
||||
operator for some type `Foo` by implementing the `std::ops::Add` trait for
|
||||
`Foo`, but you find that using `+=` does not work, as in this example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
use std::ops::Add;
|
||||
|
||||
struct Foo(u32);
|
||||
@@ -3007,7 +3183,7 @@ fn main() {
|
||||
A binary operation was attempted on a type which doesn't support it.
|
||||
Erroneous code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
let x = 12f32; // error: binary operation `<<` cannot be applied to
|
||||
// type `f32`
|
||||
|
||||
@@ -3032,12 +3208,12 @@ fn main() {
|
||||
The maximum value of an enum was reached, so it cannot be automatically
|
||||
set in the next enum value. Erroneous code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
enum Foo {
|
||||
X = 0x7fffffffffffffff,
|
||||
Y // error: enum discriminant overflowed on value after
|
||||
// 9223372036854775807: i64; set explicitly via
|
||||
// Y = -9223372036854775808 if that is desired outcome
|
||||
Y, // error: enum discriminant overflowed on value after
|
||||
// 9223372036854775807: i64; set explicitly via
|
||||
// Y = -9223372036854775808 if that is desired outcome
|
||||
}
|
||||
```
|
||||
|
||||
@@ -3049,8 +3225,11 @@ enum Foo {
|
||||
X = 0x7fffffffffffffff,
|
||||
Y = 0, // ok!
|
||||
}
|
||||
```
|
||||
|
||||
// or:
|
||||
Or:
|
||||
|
||||
```
|
||||
enum Foo {
|
||||
Y = 0, // ok!
|
||||
X = 0x7fffffffffffffff,
|
||||
@@ -3066,7 +3245,7 @@ enum Foo {
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
trait Foo { fn foo(&self) { } }
|
||||
trait Bar: Foo { }
|
||||
trait Baz: Bar { }
|
||||
@@ -3094,7 +3273,7 @@ impl Baz for Bar { } // Note: This is OK
|
||||
E0390: r##"
|
||||
You tried to implement methods for a primitive type. Erroneous code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
struct Foo {
|
||||
x: i32
|
||||
}
|
||||
@@ -3128,7 +3307,7 @@ fn bar() {} // ok!
|
||||
|
||||
The following example contains a circular dependency between two traits:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
trait FirstTrait : SecondTrait {
|
||||
|
||||
}
|
||||
@@ -3141,9 +3320,9 @@ trait SecondTrait : FirstTrait {
|
||||
|
||||
E0392: r##"
|
||||
This error indicates that a type or lifetime parameter has been declared
|
||||
but not actually used. Here is an example that demonstrates the error:
|
||||
but not actually used. Here is an example that demonstrates the error:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
enum Foo<T> {
|
||||
Bar
|
||||
}
|
||||
@@ -3172,7 +3351,7 @@ enum Foo<T> {
|
||||
which the pointed-at data is valid. An initial attempt (below) causes this
|
||||
error:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
struct Foo<'a, T> {
|
||||
x: *const T
|
||||
}
|
||||
@@ -3203,7 +3382,9 @@ struct Foo<'a, T: 'a> {
|
||||
The length of the platform-intrinsic function `simd_shuffle`
|
||||
wasn't specified. Erroneous code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
#![feature(platform_intrinsics)]
|
||||
|
||||
extern "platform-intrinsic" {
|
||||
fn simd_shuffle<A,B>(a: A, b: A, c: [u32; 8]) -> B;
|
||||
// error: invalid `simd_shuffle`, needs length: `simd_shuffle`
|
||||
@@ -3214,6 +3395,8 @@ struct Foo<'a, T: 'a> {
|
||||
last parameter in its name. Example:
|
||||
|
||||
```
|
||||
#![feature(platform_intrinsics)]
|
||||
|
||||
extern "platform-intrinsic" {
|
||||
fn simd_shuffle8<A,B>(a: A, b: A, c: [u32; 8]) -> B;
|
||||
}
|
||||
@@ -3224,7 +3407,10 @@ struct Foo<'a, T: 'a> {
|
||||
A platform-specific intrinsic function has the wrong number of type
|
||||
parameters. Erroneous code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
#![feature(repr_simd)]
|
||||
#![feature(platform_intrinsics)]
|
||||
|
||||
#[repr(simd)]
|
||||
struct f64x2(f64, f64);
|
||||
|
||||
@@ -3239,6 +3425,9 @@ struct Foo<'a, T: 'a> {
|
||||
with yours. Example:
|
||||
|
||||
```
|
||||
#![feature(repr_simd)]
|
||||
#![feature(platform_intrinsics)]
|
||||
|
||||
#[repr(simd)]
|
||||
struct f64x2(f64, f64);
|
||||
|
||||
@@ -3252,7 +3441,10 @@ struct Foo<'a, T: 'a> {
|
||||
An unknown platform-specific intrinsic function was used. Erroneous
|
||||
code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
#![feature(repr_simd)]
|
||||
#![feature(platform_intrinsics)]
|
||||
|
||||
#[repr(simd)]
|
||||
struct i16x8(i16, i16, i16, i16, i16, i16, i16, i16);
|
||||
|
||||
@@ -3267,6 +3459,9 @@ struct Foo<'a, T: 'a> {
|
||||
src/librustc_platform_intrinsics/x86.rs). Example:
|
||||
|
||||
```
|
||||
#![feature(repr_simd)]
|
||||
#![feature(platform_intrinsics)]
|
||||
|
||||
#[repr(simd)]
|
||||
struct i16x8(i16, i16, i16, i16, i16, i16, i16, i16);
|
||||
|
||||
@@ -3280,7 +3475,10 @@ struct Foo<'a, T: 'a> {
|
||||
Intrinsic argument(s) and/or return value have the wrong type.
|
||||
Erroneous code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
#![feature(repr_simd)]
|
||||
#![feature(platform_intrinsics)]
|
||||
|
||||
#[repr(simd)]
|
||||
struct i8x16(i8, i8, i8, i8, i8, i8, i8, i8,
|
||||
i8, i8, i8, i8, i8, i8, i8, i8);
|
||||
@@ -3299,6 +3497,9 @@ struct i8x16(i8, i8, i8, i8, i8, i8, i8, i8,
|
||||
it the awaited types. Example:
|
||||
|
||||
```
|
||||
#![feature(repr_simd)]
|
||||
#![feature(platform_intrinsics)]
|
||||
|
||||
#[repr(simd)]
|
||||
struct i16x8(i16, i16, i16, i16, i16, i16, i16, i16);
|
||||
|
||||
@@ -3312,7 +3513,10 @@ struct i8x16(i8, i8, i8, i8, i8, i8, i8, i8,
|
||||
Intrinsic argument(s) and/or return value have the wrong type.
|
||||
Erroneous code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
#![feature(repr_simd)]
|
||||
#![feature(platform_intrinsics)]
|
||||
|
||||
#[repr(simd)]
|
||||
struct i16x8(i16, i16, i16, i16, i16, i16, i16, i16);
|
||||
#[repr(simd)]
|
||||
@@ -3328,6 +3532,9 @@ struct i8x16(i8, i8, i8, i8, i8, i8, i8, i8,
|
||||
it the awaited types. Example:
|
||||
|
||||
```
|
||||
#![feature(repr_simd)]
|
||||
#![feature(platform_intrinsics)]
|
||||
|
||||
#[repr(simd)]
|
||||
struct i16x8(i16, i16, i16, i16, i16, i16, i16, i16);
|
||||
|
||||
@@ -3341,7 +3548,10 @@ struct i8x16(i8, i8, i8, i8, i8, i8, i8, i8,
|
||||
A platform-specific intrinsic function has wrong number of arguments.
|
||||
Erroneous code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
#![feature(repr_simd)]
|
||||
#![feature(platform_intrinsics)]
|
||||
|
||||
#[repr(simd)]
|
||||
struct f64x2(f64, f64);
|
||||
|
||||
@@ -3355,6 +3565,9 @@ struct i8x16(i8, i8, i8, i8, i8, i8, i8, i8,
|
||||
with yours. Example:
|
||||
|
||||
```
|
||||
#![feature(repr_simd)]
|
||||
#![feature(platform_intrinsics)]
|
||||
|
||||
#[repr(simd)]
|
||||
struct f64x2(f64, f64);
|
||||
|
||||
@@ -3368,7 +3581,7 @@ struct i8x16(i8, i8, i8, i8, i8, i8, i8, i8,
|
||||
The `typeof` keyword is currently reserved but unimplemented.
|
||||
Erroneous code example:
|
||||
|
||||
```
|
||||
```compile_fail
|
||||
fn main() {
|
||||
let x: typeof(92) = 92;
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
use libc;
|
||||
use rustc::session::config::get_unstable_features_setting;
|
||||
use std::ascii::AsciiExt;
|
||||
use std::cell::RefCell;
|
||||
use std::default::Default;
|
||||
@@ -34,6 +35,7 @@
|
||||
use std::fmt;
|
||||
use std::slice;
|
||||
use std::str;
|
||||
use syntax::feature_gate::UnstableFeatures;
|
||||
|
||||
use html::render::derive_id;
|
||||
use html::toc::TocBuilder;
|
||||
@@ -403,7 +405,8 @@ pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector) {
|
||||
let text = lines.collect::<Vec<&str>>().join("\n");
|
||||
tests.add_test(text.to_owned(),
|
||||
block_info.should_panic, block_info.no_run,
|
||||
block_info.ignore, block_info.test_harness);
|
||||
block_info.ignore, block_info.test_harness,
|
||||
block_info.compile_fail);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -448,6 +451,7 @@ struct LangString {
|
||||
ignore: bool,
|
||||
rust: bool,
|
||||
test_harness: bool,
|
||||
compile_fail: bool,
|
||||
}
|
||||
|
||||
impl LangString {
|
||||
@@ -458,6 +462,7 @@ fn all_false() -> LangString {
|
||||
ignore: false,
|
||||
rust: true, // NB This used to be `notrust = false`
|
||||
test_harness: false,
|
||||
compile_fail: false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -465,6 +470,10 @@ fn parse(string: &str) -> LangString {
|
||||
let mut seen_rust_tags = false;
|
||||
let mut seen_other_tags = false;
|
||||
let mut data = LangString::all_false();
|
||||
let allow_compile_fail = match get_unstable_features_setting() {
|
||||
UnstableFeatures::Allow | UnstableFeatures::Cheat=> true,
|
||||
_ => false,
|
||||
};
|
||||
|
||||
let tokens = string.split(|c: char|
|
||||
!(c == '_' || c == '-' || c.is_alphanumeric())
|
||||
@@ -477,7 +486,12 @@ fn parse(string: &str) -> LangString {
|
||||
"no_run" => { data.no_run = true; seen_rust_tags = true; },
|
||||
"ignore" => { data.ignore = true; seen_rust_tags = true; },
|
||||
"rust" => { data.rust = true; seen_rust_tags = true; },
|
||||
"test_harness" => { data.test_harness = true; seen_rust_tags = true; }
|
||||
"test_harness" => { data.test_harness = true; seen_rust_tags = true; },
|
||||
"compile_fail" if allow_compile_fail => {
|
||||
data.compile_fail = true;
|
||||
seen_rust_tags = true;
|
||||
data.no_run = true;
|
||||
},
|
||||
_ => { seen_other_tags = true }
|
||||
}
|
||||
}
|
||||
@@ -560,28 +574,31 @@ mod tests {
|
||||
#[test]
|
||||
fn test_lang_string_parse() {
|
||||
fn t(s: &str,
|
||||
should_panic: bool, no_run: bool, ignore: bool, rust: bool, test_harness: bool) {
|
||||
should_panic: bool, no_run: bool, ignore: bool, rust: bool, test_harness: bool,
|
||||
compile_fail: bool) {
|
||||
assert_eq!(LangString::parse(s), LangString {
|
||||
should_panic: should_panic,
|
||||
no_run: no_run,
|
||||
ignore: ignore,
|
||||
rust: rust,
|
||||
test_harness: test_harness,
|
||||
compile_fail: compile_fail,
|
||||
})
|
||||
}
|
||||
|
||||
// marker | should_panic| no_run | ignore | rust | test_harness
|
||||
t("", false, false, false, true, false);
|
||||
t("rust", false, false, false, true, false);
|
||||
t("sh", false, false, false, false, false);
|
||||
t("ignore", false, false, true, true, false);
|
||||
t("should_panic", true, false, false, true, false);
|
||||
t("no_run", false, true, false, true, false);
|
||||
t("test_harness", false, false, false, true, true);
|
||||
t("{.no_run .example}", false, true, false, true, false);
|
||||
t("{.sh .should_panic}", true, false, false, true, false);
|
||||
t("{.example .rust}", false, false, false, true, false);
|
||||
t("{.test_harness .rust}", false, false, false, true, true);
|
||||
// marker | should_panic| no_run| ignore| rust | test_harness| compile_fail
|
||||
t("", false, false, false, true, false, false);
|
||||
t("rust", false, false, false, true, false, false);
|
||||
t("sh", false, false, false, false, false, false);
|
||||
t("ignore", false, false, true, true, false, false);
|
||||
t("should_panic", true, false, false, true, false, false);
|
||||
t("no_run", false, true, false, true, false, false);
|
||||
t("test_harness", false, false, false, true, true, false);
|
||||
t("compile_fail", false, true, false, true, false, true);
|
||||
t("{.no_run .example}", false, true, false, true, false, false);
|
||||
t("{.sh .should_panic}", true, false, false, true, false, false);
|
||||
t("{.example .rust}", false, false, false, true, false, false);
|
||||
t("{.test_harness .rust}", false, false, false, true, true, false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -22,10 +22,12 @@
|
||||
#![feature(box_syntax)]
|
||||
#![feature(dynamic_lib)]
|
||||
#![feature(libc)]
|
||||
#![feature(recover)]
|
||||
#![feature(rustc_private)]
|
||||
#![feature(set_stdio)]
|
||||
#![feature(slice_patterns)]
|
||||
#![feature(staged_api)]
|
||||
#![feature(std_panic)]
|
||||
#![feature(test)]
|
||||
#![feature(unicode)]
|
||||
|
||||
|
||||
+33
-11
@@ -18,6 +18,7 @@
|
||||
use std::io::prelude::*;
|
||||
use std::io;
|
||||
use std::path::PathBuf;
|
||||
use std::panic::{self, AssertRecoverSafe};
|
||||
use std::process::Command;
|
||||
use std::rc::Rc;
|
||||
use std::str;
|
||||
@@ -178,7 +179,7 @@ fn scrape_test_config(krate: &::rustc_front::hir::Crate) -> TestOptions {
|
||||
fn runtest(test: &str, cratename: &str, cfgs: Vec<String>, libs: SearchPaths,
|
||||
externs: core::Externs,
|
||||
should_panic: bool, no_run: bool, as_test_harness: bool,
|
||||
opts: &TestOptions) {
|
||||
compile_fail: bool, opts: &TestOptions) {
|
||||
// the test harness wants its own `main` & top level functions, so
|
||||
// never wrap the test in `fn main() { ... }`
|
||||
let test = maketest(test, Some(cratename), as_test_harness, opts);
|
||||
@@ -244,19 +245,39 @@ fn drop(&mut self) {
|
||||
cstore.clone());
|
||||
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
|
||||
|
||||
let outdir = TempDir::new("rustdoctest").ok().expect("rustdoc needs a tempdir");
|
||||
let out = Some(outdir.path().to_path_buf());
|
||||
let mut cfg = config::build_configuration(&sess);
|
||||
cfg.extend(config::parse_cfgspecs(cfgs));
|
||||
let outdir = Mutex::new(TempDir::new("rustdoctest").ok().expect("rustdoc needs a tempdir"));
|
||||
let libdir = sess.target_filesearch(PathKind::All).get_lib_path();
|
||||
let mut control = driver::CompileController::basic();
|
||||
let mut cfg = config::build_configuration(&sess);
|
||||
cfg.extend(config::parse_cfgspecs(cfgs.clone()));
|
||||
let out = Some(outdir.lock().unwrap().path().to_path_buf());
|
||||
|
||||
if no_run {
|
||||
control.after_analysis.stop = Compilation::Stop;
|
||||
}
|
||||
let result = driver::compile_input(&sess, &cstore, cfg, &input,
|
||||
&out, &None, None, control);
|
||||
match result {
|
||||
Err(count) if count > 0 => sess.fatal("aborting due to previous error(s)"),
|
||||
|
||||
match {
|
||||
let b_sess = AssertRecoverSafe::new(&sess);
|
||||
let b_cstore = AssertRecoverSafe::new(&cstore);
|
||||
let b_cfg = AssertRecoverSafe::new(cfg.clone());
|
||||
let b_control = AssertRecoverSafe::new(&control);
|
||||
|
||||
panic::recover(|| {
|
||||
driver::compile_input(&b_sess, &b_cstore, (*b_cfg).clone(),
|
||||
&input, &out,
|
||||
&None, None, &b_control)
|
||||
})
|
||||
} {
|
||||
Ok(r) => {
|
||||
match r {
|
||||
Err(count) if count > 0 && compile_fail == false => {
|
||||
sess.fatal("aborting due to previous error(s)")
|
||||
}
|
||||
Ok(()) if compile_fail => panic!("test compiled while it wasn't supposed to"),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
Err(_) if compile_fail == false => panic!("couldn't compile the test"),
|
||||
_ => {}
|
||||
}
|
||||
|
||||
@@ -268,7 +289,7 @@ fn drop(&mut self) {
|
||||
// environment to ensure that the target loads the right libraries at
|
||||
// runtime. It would be a sad day if the *host* libraries were loaded as a
|
||||
// mistake.
|
||||
let mut cmd = Command::new(&outdir.path().join("rust_out"));
|
||||
let mut cmd = Command::new(&outdir.lock().unwrap().path().join("rust_out"));
|
||||
let var = DynamicLibrary::envvar();
|
||||
let newpath = {
|
||||
let path = env::var_os(var).unwrap_or(OsString::new());
|
||||
@@ -392,7 +413,7 @@ pub fn new(cratename: String, cfgs: Vec<String>, libs: SearchPaths, externs: cor
|
||||
|
||||
pub fn add_test(&mut self, test: String,
|
||||
should_panic: bool, no_run: bool, should_ignore: bool,
|
||||
as_test_harness: bool) {
|
||||
as_test_harness: bool, compile_fail: bool) {
|
||||
let name = if self.use_headers {
|
||||
let s = self.current_header.as_ref().map(|s| &**s).unwrap_or("");
|
||||
format!("{}_{}", s, self.cnt)
|
||||
@@ -422,6 +443,7 @@ pub fn add_test(&mut self, test: String,
|
||||
should_panic,
|
||||
no_run,
|
||||
as_test_harness,
|
||||
compile_fail,
|
||||
&opts);
|
||||
}))
|
||||
});
|
||||
|
||||
@@ -71,5 +71,5 @@ fn compile(code: String, output: PathBuf, sysroot: PathBuf) {
|
||||
&None,
|
||||
&Some(output),
|
||||
None,
|
||||
control);
|
||||
&control);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user