diff --git a/mk/docs.mk b/mk/docs.mk index f76368e3d0b8..7f73b99863f0 100644 --- a/mk/docs.mk +++ b/mk/docs.mk @@ -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) diff --git a/mk/tests.mk b/mk/tests.mk index 19587a28d559..2e530095cbe1 100644 --- a/mk/tests.mk +++ b/mk/tests.mk @@ -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), \ diff --git a/src/error-index-generator/main.rs b/src/error-index-generator/main.rs index 4b10b02f2d40..db9dd006f3c8 100644 --- a/src/error-index-generator/main.rs +++ b/src/error-index-generator/main.rs @@ -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>; + fn title(&self, output: &mut Write) -> Result<(), Box>; + fn error_code_block(&self, output: &mut Write, info: &ErrorMetadata, + err_code: &str) -> Result<(), Box>; + fn footer(&self, output: &mut Write) -> Result<(), Box>; +} + +struct HTMLFormatter; +struct MarkdownFormatter; + +impl Formatter for HTMLFormatter { + fn header(&self, output: &mut Write) -> Result<(), Box> { + try!(write!(output, r##" + + +Rust Compiler Error Index + + + + + + + +"##)); + Ok(()) + } + + fn title(&self, output: &mut Write) -> Result<(), Box> { + try!(write!(output, "

Rust Compiler Error Index

\n")); + Ok(()) + } + + fn error_code_block(&self, output: &mut Write, info: &ErrorMetadata, + err_code: &str) -> Result<(), Box> { + // 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, "
", desc_desc, use_desc)); + + // Error title (with self-link). + try!(write!(output, + "

{0}

\n", + err_code)); + + // Description rendered as markdown. + match info.description { + Some(ref desc) => try!(write!(output, "{}", Markdown(desc))), + None => try!(write!(output, "

No description.

\n")), + } + + try!(write!(output, "
\n")); + Ok(()) + } + + fn footer(&self, output: &mut Write) -> Result<(), Box> { + try!(write!(output, "\n")); + Ok(()) + } +} + +impl Formatter for MarkdownFormatter { + #[allow(unused_variables)] + fn header(&self, output: &mut Write) -> Result<(), Box> { + Ok(()) + } + + fn title(&self, output: &mut Write) -> Result<(), Box> { + try!(write!(output, "# Rust Compiler Error Index\n")); + Ok(()) + } + + fn error_code_block(&self, output: &mut Write, info: &ErrorMetadata, + err_code: &str) -> Result<(), Box> { + 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> { + Ok(()) + } +} + /// Load all the metadata files from `metadata_dir` into an in-memory map. fn load_all_errors(metadata_dir: &Path) -> Result> { let mut all_errors = BTreeMap::new(); @@ -47,71 +159,45 @@ fn load_all_errors(metadata_dir: &Path) -> Result> } /// 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> { +fn render_error_page(err_map: &ErrorMetadataMap, output_path: &Path, + formatter: T) -> Result<(), Box> { let mut output_file = try!(File::create(output_path)); - try!(write!(&mut output_file, -r##" - - -Rust Compiler Error Index - - - - - - - -"## - )); - - try!(write!(&mut output_file, "

Rust Compiler Error Index

\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, "
", desc_desc, use_desc)); - - // Error title (with self-link). - try!(write!(&mut output_file, - "

{0}

\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, "

No description.

\n")), - } - - try!(write!(&mut output_file, "
\n")); + try!(formatter.error_code_block(&mut output_file, info, err_code)); } - try!(write!(&mut output_file, "\n")); - - Ok(()) + formatter.footer(&mut output_file) } -fn main_with_result() -> Result<(), Box> { +fn main_with_result(format: OutputFormat) -> Result<(), Box> { 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()); } } diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index 9dbc75b960ef..8a9ef666b838 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -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) { match x { // empty @@ -72,12 +76,14 @@ fn foo(x: Option) { 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) { guard, like so: ``` +let number = 0.1f32; + match number { - // ... x if x.is_nan() => { /* ... */ } - // ... + _ => {} } ``` "##, @@ -120,15 +127,16 @@ fn foo(x: Option) { 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) { 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) { 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) { 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) { 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(x: T) { } ``` -the machine code for `foo::()`, `foo::()`, `foo::()`, or any +The machine code for `foo::()`, `foo::()`, `foo::()`, 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::()`. When we have additional @@ -373,22 +387,25 @@ trait Trait { fn foo(&self, on: T); // more methods } + impl Trait for String { fn foo(&self, on: T) { // implementation 1 } } + impl Trait for u8 { fn foo(&self, on: T) { // implementation 2 } } + // 8 more implementations ``` Now, if we have the following code: -``` +```ignore fn call_foo(thing: Box) { 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) { } ``` -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`). 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 {} trait Trait: Super { @@ -488,7 +505,7 @@ trait Super { 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; // 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(Vec) +```compile_fail +struct Foo(Vec); fn foo(x: Vec) { // we are transmuting between Vec and Foo here @@ -631,9 +648,11 @@ fn foo(x: Vec) { possible type substitution. It's possible to use traits to do this cleanly, for example: -``` +```ignore +struct Foo(Vec); + trait MyTransmutableType { - fn transmute(Vec) -> Foo + fn transmute(Vec) -> Foo; } impl MyTransmutableType for u8 { @@ -641,11 +660,13 @@ fn transmute(x: Foo) -> Vec { transmute(x) } } + impl MyTransmutableType for String { fn transmute(x: Foo) -> Vec { transmute(x) } } + // ... more impls for the types you intend to transmute fn foo(x: Vec) { @@ -660,7 +681,7 @@ fn foo(x: Vec) { 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(x: Vec) { ``` 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(x: Vec) { 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(x: Vec) { // 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(x: Vec) { 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(x: Vec) { ... } -// Try this instead: +Try this instead: + +``` +struct Irrefutable(i32); +let irr = Irrefutable(0); + loop { let Irrefutable(x) = irr; ... @@ -752,16 +785,23 @@ fn foo(x: Vec) { ``` 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) -> ::A; @@ -810,13 +850,13 @@ fn baz(x: &>::A) {} To solve this error, please move the type bindings in the type parameter declaration: -``` +```ignore fn baz>(x: &::A) {} // ok! ``` -or in the `where` clause: +Or in the `where` clause: -``` +```ignore fn baz(x: &::A) where I: Foo {} ``` "##, @@ -827,7 +867,7 @@ fn baz(x: &::A) where I: Foo {} 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) where T: Trait { 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) where T: Trait { @@ -1053,12 +1109,12 @@ fn foo(t: T) where T: Trait { Here is a more subtle instance of the same problem, that can arise with for-loops in Rust: -``` +```compile_fail let vs: Vec = vec![1, 2, 3, 4]; for v in &vs { match v { - 1 => {} - _ => {} + 1 => {}, + _ => {}, } } ``` @@ -1067,7 +1123,7 @@ fn foo(t: T) where T: Trait { 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) where T: Trait { ``` // Basic Example: trait Trait { type AssociatedType; } + fn foo(t: T) where T: Trait { 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) where T: Trait { position that needs that trait. For example, when the following code is compiled: -``` +```compile_fail fn foo>(x: T){} #[rustc_on_unimplemented = "the type `{Self}` cannot be indexed by `{Idx}`"] @@ -1168,7 +1227,7 @@ trait Index { ... } position that needs that trait. For example, when the following code is compiled: -``` +```compile_fail fn foo>(x: T){} #[rustc_on_unimplemented = "the type `{Self}` cannot be indexed by `{Idx}`"] @@ -1196,7 +1255,7 @@ trait Index { ... } position that needs that trait. For example, when the following code is compiled: -``` +```compile_fail fn foo>(x: T){} #[rustc_on_unimplemented = "the type `{Self}` cannot be indexed by `{Idx}`"] @@ -1218,9 +1277,9 @@ trait Index { ... } 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); @@ -1228,7 +1287,7 @@ trait Foo {} impl Foo for T where Bar: Foo {} ``` -to determine if a `T` is `Foo`, we need to check if `Bar` is `Foo`. However, +To determine if a `T` is `Foo`, we need to check if `Bar` is `Foo`. However, to do this check, we need to determine that `Bar>` is `Foo`. To determine this, we check if `Bar>>` is `Foo`, and so on. This is clearly a recursive requirement that can't be resolved directly. @@ -1240,13 +1299,13 @@ impl Foo for T where Bar: 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(x: T); + fn foo(x: T); } impl Foo for bool { - fn foo(x: T) where T: Copy {} + fn foo(x: T) where T: Copy {} } ``` @@ -1262,7 +1321,7 @@ fn foo(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(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 { - // Some fields omitted. + num: T, } impl Foo { @@ -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> = vec!(Some(1), None); + // This fails because `None` is not covered. for Some(x) in xs { - ... + // ... } +``` + +Match inside the loop instead: + +``` +let xs : Vec> = 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> = 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`: -``` +```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 { 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 { foo: &'static T } @@ -1644,13 +1732,13 @@ struct Foo { the error is reported on a call like `foo(x)`, and `foo` is defined as follows: -``` +```ignore fn foo(arg: &Box) { ... } ``` -you might change it to: +You might change it to: -``` +```ignore fn foo<'a>(arg: &Box) { ... } ``` @@ -1663,7 +1751,7 @@ fn foo<'a>(arg: &Box) { ... } 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) { ... } 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 diff --git a/src/librustc_borrowck/diagnostics.rs b/src/librustc_borrowck/diagnostics.rs index 6cbea1abbb5b..29944aaf3673 100644 --- a/src/librustc_borrowck/diagnostics.rs +++ b/src/librustc_borrowck/diagnostics.rs @@ -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 u32> { let x = 0u32; Box::new(|y| x + y) @@ -30,7 +30,7 @@ fn foo() -> Box 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 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> = 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: 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: F) { } ``` use std::cell::Cell; +fn foo(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 { diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 6c5b577e0d1a..bd7f094364ad 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -66,7 +66,7 @@ pub fn compile_input(sess: &Session, outdir: &Option, output: &Option, addl_plugins: Option>, - 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; diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 25cef24c50d5..f6eb99f5589c 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -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)) } diff --git a/src/librustc_passes/diagnostics.rs b/src/librustc_passes/diagnostics.rs index 27354c28d85e..c89e9bb19595 100644 --- a/src/librustc_passes/diagnostics.rs +++ b/src/librustc_passes/diagnostics.rs @@ -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 = 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> = 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 Sync for NotThreadSafe {} 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 } diff --git a/src/librustc_privacy/diagnostics.rs b/src/librustc_privacy/diagnostics.rs index 3fbe3bc20053..d124ead5091d 100644 --- a/src/librustc_privacy/diagnostics.rs +++ b/src/librustc_privacy/diagnostics.rs @@ -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(pub T); // same error +pub struct Bar2(pub T); // same error pub fn 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(pub T); // ok! +pub struct Bar2(pub T); // ok! pub fn foo (t: T) {} // ok! ``` "##, @@ -45,7 +44,7 @@ pub fn 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, diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 16bcf84b7950..99c29bbb8ef7 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -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 MyTrait for Option { // ... } @@ -229,7 +230,7 @@ impl MyTrait for Option { 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 MyTrait for Option { // ... } @@ -238,7 +239,7 @@ impl MyTrait for Option { 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 { // ... } @@ -255,20 +256,22 @@ impl MyTrait for Option { 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(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(x: T) { type MaybeT = Option; // ... } ``` -or this: +Or this: -``` +```compile_fail fn foo(x: T) { struct Foo { x: T, @@ -351,7 +356,7 @@ struct Foo { fn foo(x: T) { let bar = |y: T| { // explicit type annotation may not be necessary // .. - } + }; bar(x); } ``` @@ -397,11 +402,12 @@ struct Foo { In case the item is a function inside an `impl`, defining a private helper function might be easier: -``` +```ignore impl Foo { 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(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(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 ::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() -> ::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(x: T) {} // ok! ``` "##, @@ -620,14 +638,13 @@ fn foo(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(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 {} diff --git a/src/librustc_trans/diagnostics.rs b/src/librustc_trans/diagnostics.rs index 539b9a4171f9..5ae60d182407 100644 --- a/src/librustc_trans/diagnostics.rs +++ b/src/librustc_trans/diagnostics.rs @@ -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(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 ``` diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index f138b997f4cc..0ff6dcccde69 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -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(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(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: 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: F) -> F::Output { f(3) } ``` It can be fixed by adjusting the trait bound like this: -``` +```ignore fn foo>(f: F) -> F::Output { f(3) } ``` @@ -628,7 +683,7 @@ fn foo>(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: 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: 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 } // error ``` @@ -895,12 +951,22 @@ struct Foo { x: Option> } reason about how to use SIMD with them. This error will occur if the types are generic. -``` -#[simd] -struct Bad(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); +``` + +This will not: + +``` +#![feature(simd)] + +#[simd] +struct Good(u32, u32, u32); ``` "##, @@ -909,12 +975,22 @@ struct Foo { x: Option> } 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> } 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> } 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() {} 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() {} 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(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 = u32; // error: type parameter `T` is unused // or: type Foo = Box; // error: type parameter `B` is unused @@ -1171,7 +1268,7 @@ fn main() { ``` type Foo = u32; // ok! -type Foo = Box; // ok! +type Foo2 = Box; // 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 { ... } // error +```compile_fail +impl Vec { } // error ``` To fix this problem, you can do either of these things: @@ -1431,10 +1530,10 @@ impl Vec { ... } // error Note that using the `type` keyword does not work here because `type` only introduces a type alias: -``` +```compile_fail type Bytes = Vec; -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 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 { +```compile_fail +struct Foo { field1: T, filed2: U, } @@ -1699,7 +1802,7 @@ pub struct Foo { by doing: ``` -pub struct Foo { +struct Foo { field1: T, filed2: U, } @@ -1713,7 +1816,7 @@ pub struct Foo { 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() { // error: main function is not allowed to have type parameters } ``` @@ -1753,7 +1860,7 @@ fn main() { // 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() { // 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 { + Wrapped: T +} impl Foo for Wrapper where Wrapper: 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 { fn do_something(&self) -> T; fn do_something_else(&self, bar: T); @@ -2013,7 +2130,7 @@ trait Foo { 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, } @@ -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), 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 ForeignTrait for T { ... } // error +impl ForeignTrait for T { } // error ``` To work around this, it can be covered with a local type, `MyType`: -``` +```ignore struct MyType(T); -impl ForeignTrait for MyType { ... } // Ok +impl ForeignTrait for MyType { } // Ok ``` Please note that a type alias is not sufficient. @@ -2292,9 +2425,9 @@ impl ForeignTrait for MyType { ... } // Ok named `ForeignTrait2` that takes two type parameters. Then this `impl` results in the same rule violation: -``` +```compile_fail struct MyType2; -impl ForeignTrait2> for MyType2 { ... } // error +impl ForeignTrait2> for MyType2 { } // error ``` The reason for this is that there are two appearances of type parameter `T` in @@ -2303,8 +2436,8 @@ impl ForeignTrait2> for MyType2 { ... } // error Consider one more example: -``` -impl ForeignTrait2, T> for MyType2 { ... } // Ok +```ignore +impl ForeignTrait2, T> for MyType2 { } // Ok ``` This only differs from the previous `impl` in that the parameters `T` and @@ -2314,7 +2447,7 @@ impl ForeignTrait2, 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 ForeignTrait for T0 { ... } ``` @@ -2333,7 +2466,7 @@ impl ForeignTrait 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) {} 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) {} ``` let x = 1u8; + match x { 0u8...3u8 => (), // ok! _ => () @@ -2412,7 +2546,7 @@ fn x(self: Box) {} // 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 _: ::A; +trait T1 {} +trait T2 {} + +trait Foo { + type A: T1; +} + +trait Bar : Foo { + type A: T2; + fn do_something() { + let _: ::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; } @@ -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 { 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 { x: Foo } @@ -2588,7 +2736,7 @@ struct Bar { x: Foo } 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(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 { ::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 } @@ -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 { @@ -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 { Bar } @@ -3172,7 +3351,7 @@ enum Foo { 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: 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: 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; } diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index c0846cae6870..8633d2a1c2e6 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -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::>().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] diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index c52459f6c105..6cad0d7d940d 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -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)] diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 490e54f4e3df..39550488a9e8 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -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, 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, 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); })) }); diff --git a/src/test/run-make/issue-19371/foo.rs b/src/test/run-make/issue-19371/foo.rs index b2aed9154584..43ae356feede 100644 --- a/src/test/run-make/issue-19371/foo.rs +++ b/src/test/run-make/issue-19371/foo.rs @@ -71,5 +71,5 @@ fn compile(code: String, output: PathBuf, sysroot: PathBuf) { &None, &Some(output), None, - control); + &control); }