From 1c8766761e6c2a264ed972ad70f506443184f51d Mon Sep 17 00:00:00 2001 From: ggomez Date: Mon, 15 Feb 2016 17:57:21 +0100 Subject: [PATCH] Global error explanations improvements --- src/librustc/diagnostics.rs | 247 ++++++++++++++++++--------- src/librustc_borrowck/diagnostics.rs | 20 ++- src/librustc_privacy/diagnostics.rs | 10 +- src/librustc_resolve/diagnostics.rs | 82 ++++----- 4 files changed, 223 insertions(+), 136 deletions(-) diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index 8a9ef666b83..92db527ef98 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -20,8 +20,8 @@ will never be reached as for all possible values of the expression being matched, one of the preceding patterns will match. -This means that perhaps some of the preceding patterns are too general, this one -is too specific or the ordering is incorrect. +This means that perhaps some of the preceding patterns are too general, this +one is too specific or the ordering is incorrect. For example, the following `match` block has too many arms: @@ -104,28 +104,86 @@ fn foo(x: Option) { This error indicates that the compiler cannot guarantee a matching pattern for one or more possible inputs to a match expression. Guaranteed matches are required in order to assign values to match expressions, or alternatively, -determine the flow of execution. +determine the flow of execution. Erroneous code example: + +```compile_fail +enum Terminator { + HastaLaVistaBaby, + TalkToMyHand, +} + +let x = Terminator::HastaLaVistaBaby; + +match x { // error: non-exhaustive patterns: `HastaLaVistaBaby` not covered + Terminator::TalkToMyHand => {} +} +``` If you encounter this error you must alter your patterns so that every possible value of the input type is matched. For types with a small number of variants (like enums) you should probably cover all cases explicitly. Alternatively, the underscore `_` wildcard pattern can be added after all other patterns to match -"anything else". +"anything else". Example: + +``` +enum Terminator { + HastaLaVistaBaby, + TalkToMyHand, +} + +let x = Terminator::HastaLaVistaBaby; + +match x { + Terminator::TalkToMyHand => {} + Terminator::HastaLaVistaBaby => {} +} + +// or: + +match x { + Terminator::TalkToMyHand => {} + _ => {} +} +``` "##, E0005: r##" Patterns used to bind names must be irrefutable, that is, they must guarantee -that a name will be extracted in all cases. If you encounter this error you -probably need to use a `match` or `if let` to deal with the possibility of -failure. +that a name will be extracted in all cases. Erroneous code example: + +```compile_fail +let x = Some(1); +let Some(y) = x; +// error: refutable pattern in local binding: `None` not covered +``` + +If you encounter this error you probably need to use a `match` or `if let` to +deal with the possibility of failure. Example: + +```compile_fail +let x = Some(1); + +match x { + Some(y) => { + // do something + }, + None => {} +} + +// or: + +if let Some(y) = x { + // do something +} +``` "##, E0007: r##" This error indicates that the bindings in a match arm would require a value to -be moved into more than one location, thus violating unique ownership. Code like -the following is invalid as it requires the entire `Option` to be moved -into a variable called `op_string` while simultaneously requiring the inner -String to be moved into a variable called `s`. +be moved into more than one location, thus violating unique ownership. Code +like the following is invalid as it requires the entire `Option` to be +moved 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()); @@ -180,7 +238,7 @@ fn foo(x: Option) { This limitation may be removed in a future version of Rust. -Wrong example: +Erroneous code example: ```compile_fail struct X { x: (), } @@ -264,7 +322,7 @@ trait Foo where Self: Sized { } ``` -we cannot create an object of type `Box` or `&Foo` since in this case +We cannot create an object of type `Box` or `&Foo` since in this case `Self` would not be `Sized`. Generally, `Self : Sized` is used to indicate that the trait should not be used @@ -294,7 +352,7 @@ fn foo(&self) -> Self { ``` (Note that `&self` and `&mut self` are okay, it's additional `Self` types which -cause this problem) +cause this problem.) In such a case, the compiler cannot predict the return type of `foo()` in a situation like the following: @@ -573,15 +631,15 @@ struct ListNode { "##, E0133: r##" -Using unsafe functionality, is potentially dangerous and disallowed -by safety checks. Examples: +Using unsafe functionality is potentially dangerous and disallowed by safety +checks. Examples: -- Dereferencing raw pointers -- Calling functions via FFI -- Calling functions marked unsafe +* Dereferencing raw pointers +* Calling functions via FFI +* Calling functions marked unsafe -These safety checks can be relaxed for a section of the code -by wrapping the unsafe instructions with an `unsafe` block. For instance: +These safety checks can be relaxed for a section of the code by wrapping the +unsafe instructions with an `unsafe` block. For instance: ``` unsafe fn f() { return; } @@ -1039,14 +1097,16 @@ fn foo() -> ! { println!("{}", y); ``` -In the previous example, the print statement was never reached when the wildcard -match arm was hit, so we were okay with `foo()` not returning an integer that we -could set to `y`. But in this example, `foo()` actually does return control, so -the print statement will be executed with an uninitialized value. +In the previous example, the print statement was never reached when the +wildcard match arm was hit, so we were okay with `foo()` not returning an +integer that we could set to `y`. But in this example, `foo()` actually does +return control, so the print statement will be executed with an uninitialized +value. Obviously we cannot have functions which are allowed to be used in such positions and yet can return control. So, if you are defining a function that -returns `!`, make sure that there is no way for it to actually finish executing. +returns `!`, make sure that there is no way for it to actually finish +executing. "##, E0271: r##" @@ -1206,19 +1266,19 @@ trait Index { ... } foo(true); // `bool` does not implement `Index` ``` -there will be an error about `bool` not implementing `Index`, followed by a +There will be an error about `bool` not implementing `Index`, followed by a note saying "the type `bool` cannot be indexed by `u8`". -As you can see, you can specify type parameters in curly braces for substitution -with the actual types (using the regular format string syntax) in a given -situation. Furthermore, `{Self}` will substitute to the type (in this case, -`bool`) that we tried to use. +As you can see, you can specify type parameters in curly braces for +substitution with the actual types (using the regular format string syntax) in +a given situation. Furthermore, `{Self}` will substitute to the type (in this +case, `bool`) that we tried to use. This error appears when the curly braces contain an identifier which doesn't -match with any of the type parameters or the string `Self`. This might happen if -you misspelled a type parameter, or if you intended to use literal curly braces. -If it is the latter, escape the curly braces with a second curly brace of the -same type; e.g. a literal `{` is `{{` +match with any of the type parameters or the string `Self`. This might happen +if you misspelled a type parameter, or if you intended to use literal curly +braces. If it is the latter, escape the curly braces with a second curly brace +of the same type; e.g. a literal `{` is `{{`. "##, E0273: r##" @@ -1239,10 +1299,10 @@ trait Index { ... } there will be an error about `bool` not implementing `Index`, followed by a note saying "the type `bool` cannot be indexed by `u8`". -As you can see, you can specify type parameters in curly braces for substitution -with the actual types (using the regular format string syntax) in a given -situation. Furthermore, `{Self}` will substitute to the type (in this case, -`bool`) that we tried to use. +As you can see, you can specify type parameters in curly braces for +substitution with the actual types (using the regular format string syntax) in +a given situation. Furthermore, `{Self}` will substitute to the type (in this +case, `bool`) that we tried to use. This error appears when the curly braces do not contain an identifier. Please add one of the same name as a type parameter. If you intended to use literal @@ -1274,8 +1334,8 @@ trait Index { ... } E0275: r##" This error occurs when there was a recursive trait requirement that overflowed -before it could be evaluated. Often this means that there is unbounded recursion -in resolving some type bounds. +before it could be evaluated. Often this means that there is unbounded +recursion in resolving some type bounds. For example, in the following code: @@ -1288,9 +1348,9 @@ impl Foo for T where Bar: Foo {} ``` 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. +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. Consider changing your trait bounds so that they're less self-referential. "##, @@ -1336,7 +1396,7 @@ fn main() { // we now call the method with the i32 type, which doesn't implement // the Foo trait some_func(5i32); // error: the trait `Foo` is not implemented for the - // type `i32` + // type `i32` } ``` @@ -1564,7 +1624,9 @@ fn main() { ```compile_fail match Some(()) { None => { }, - option if option.take().is_none() => { /* impossible, option is `Some` */ }, + option if option.take().is_none() => { + /* impossible, option is `Some` */ + }, Some(_) => { } // When the previous match failed, the option became `None`. } ``` @@ -1615,12 +1677,29 @@ fn main() { E0306: r##" In an array literal `[x; N]`, `N` is the number of elements in the array. This -number cannot be negative. +must be an unsigned integer. Erroneous code example: + +```compile_fail +let x = [0i32; true]; // error: expected positive integer for repeat count, + // found boolean +``` + +Working example: + +``` +let x = [0i32; 2]; +``` "##, E0307: r##" -The length of an array is part of its type. For this reason, this length must be -a compile-time constant. +The length of an array is part of its type. For this reason, this length must +be a compile-time constant. Erroneous code example: + +```compile_fail + let len = 10; + let x = [0i32; len]; // error: expected constant integer for repeat count, + // found variable +``` "##, E0308: r##" @@ -1713,24 +1792,22 @@ struct Foo { "##, E0398: r##" -In Rust 1.3, the default object lifetime bounds are expected to -change, as described in RFC #1156 [1]. You are getting a warning -because the compiler thinks it is possible that this change will cause -a compilation error in your code. It is possible, though unlikely, -that this is a false alarm. - -The heart of the change is that where `&'a Box` used to -default to `&'a Box`, it now defaults to `&'a -Box` (here, `SomeTrait` is the name of some trait -type). Note that the only types which are affected are references to -boxes, like `&Box` or `&[Box]`. More common -types like `&SomeTrait` or `Box` are unaffected. - -To silence this warning, edit your code to use an explicit bound. -Most of the time, this means that you will want to change the -signature of a function that you are calling. For example, if -the error is reported on a call like `foo(x)`, and `foo` is -defined as follows: +In Rust 1.3, the default object lifetime bounds are expected to change, as +described in RFC #1156 [1]. You are getting a warning because the compiler +thinks it is possible that this change will cause a compilation error in your +code. It is possible, though unlikely, that this is a false alarm. + +The heart of the change is that where `&'a Box` used to default to +`&'a Box`, it now defaults to `&'a Box` (here, +`SomeTrait` is the name of some trait type). Note that the only types which are +affected are references to boxes, like `&Box` or +`&[Box]`. More common types like `&SomeTrait` or `Box` +are unaffected. + +To silence this warning, edit your code to use an explicit bound. Most of the +time, this means that you will want to change the signature of a function that +you are calling. For example, if the error is reported on a call like `foo(x)`, +and `foo` is defined as follows: ```ignore fn foo(arg: &Box) { ... } @@ -1742,8 +1819,8 @@ fn foo(arg: &Box) { ... } fn foo<'a>(arg: &Box) { ... } ``` -This explicitly states that you expect the trait object `SomeTrait` to -contain references (with a maximum lifetime of `'a`). +This explicitly states that you expect the trait object `SomeTrait` to contain +references (with a maximum lifetime of `'a`). [1]: https://github.com/rust-lang/rfcs/pull/1156 "##, @@ -1812,8 +1889,8 @@ fn foo() {} "##, E0517: r##" -This error indicates that a `#[repr(..)]` attribute was placed on an unsupported -item. +This error indicates that a `#[repr(..)]` attribute was placed on an +unsupported item. Examples of erroneous code: @@ -1829,29 +1906,29 @@ struct Foo {bar: bool, baz: bool} #[repr(C)] impl Foo { - ... + // ... } ``` - - The `#[repr(C)]` attribute can only be placed on structs and enums - - The `#[repr(packed)]` and `#[repr(simd)]` attributes only work on structs - - The `#[repr(u8)]`, `#[repr(i16)]`, etc attributes only work on enums +* The `#[repr(C)]` attribute can only be placed on structs and enums. +* The `#[repr(packed)]` and `#[repr(simd)]` attributes only work on structs. +* The `#[repr(u8)]`, `#[repr(i16)]`, etc attributes only work on enums. These attributes do not work on typedefs, since typedefs are just aliases. Representations like `#[repr(u8)]`, `#[repr(i64)]` are for selecting the -discriminant size for C-like enums (when there is no associated data, e.g. `enum -Color {Red, Blue, Green}`), effectively setting the size of the enum to the size -of the provided type. Such an enum can be cast to a value of the same type as -well. In short, `#[repr(u8)]` makes the enum behave like an integer with a -constrained set of allowed values. +discriminant size for C-like enums (when there is no associated data, e.g. +`enum Color {Red, Blue, Green}`), effectively setting the size of the enum to +the size of the provided type. Such an enum can be cast to a value of the same +type as well. In short, `#[repr(u8)]` makes the enum behave like an integer +with a constrained set of allowed values. Only C-like enums can be cast to numerical primitives, so this attribute will not apply to structs. `#[repr(packed)]` reduces padding to make the struct size smaller. The -representation of enums isn't strictly defined in Rust, and this attribute won't -work on enums. +representation of enums isn't strictly defined in Rust, and this attribute +won't work on enums. `#[repr(simd)]` will give a struct consisting of a homogenous series of machine types (i.e. `u8`, `i32`, etc) a representation that permits vectorization via @@ -1860,8 +1937,8 @@ impl Foo { "##, E0518: r##" -This error indicates that an `#[inline(..)]` attribute was incorrectly placed on -something other than a function or method. +This error indicates that an `#[inline(..)]` attribute was incorrectly placed +on something other than a function or method. Examples of erroneous code: @@ -1871,7 +1948,7 @@ impl Foo { #[inline(never)] impl Foo { - ... + // ... } ``` diff --git a/src/librustc_borrowck/diagnostics.rs b/src/librustc_borrowck/diagnostics.rs index 29944aaf367..7f6fd9de3d2 100644 --- a/src/librustc_borrowck/diagnostics.rs +++ b/src/librustc_borrowck/diagnostics.rs @@ -26,7 +26,8 @@ fn foo() -> Box u32> { Notice that `x` is stack-allocated by `foo()`. By default, Rust captures closed-over data by reference. This means that once `foo()` returns, `x` no -longer exists. An attempt to access `x` within the closure would thus be unsafe. +longer exists. An attempt to access `x` within the closure would thus be +unsafe. Another situation where this might be encountered is when spawning threads: @@ -73,7 +74,14 @@ fn main() { ``` To fix this, ensure that any declared variables are initialized before being -used. +used. Example: + +``` +fn main() { + let x: i32 = 0; + let y = x; // ok! +} +``` "##, E0382: r##" @@ -210,8 +218,8 @@ fn main(){ **y = 2; ``` -It can also be fixed by using a type with interior mutability, such as `Cell` or -`RefCell`: +It can also be fixed by using a type with interior mutability, such as `Cell` +or `RefCell`: ``` use std::cell::Cell; @@ -259,8 +267,8 @@ fn foo(f: F) { } ``` Alternatively, we can consider using the `Cell` and `RefCell` types to achieve -interior mutability through a shared reference. Our example's `mutable` function -could be redefined as below: +interior mutability through a shared reference. Our example's `mutable` +function could be redefined as below: ``` use std::cell::Cell; diff --git a/src/librustc_privacy/diagnostics.rs b/src/librustc_privacy/diagnostics.rs index d124ead5091..36ba3d0ca73 100644 --- a/src/librustc_privacy/diagnostics.rs +++ b/src/librustc_privacy/diagnostics.rs @@ -27,8 +27,8 @@ 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: +can be made inaccessible if necessary by placing it into a private inner +module, but it still has to be marked with `pub`. Example: ```ignore pub trait Foo { // we set the Foo trait public @@ -55,8 +55,8 @@ pub fn bar() -> Bar { // error: private type in public interface ``` To solve this error, please ensure that the type is also public. The type -can be made inaccessible if necessary by placing it into a private inner module, -but it still has to be marked with `pub`. +can be made inaccessible if necessary by placing it into a private inner +module, but it still has to be marked with `pub`. Example: ``` @@ -165,7 +165,7 @@ mod Bar { ``` To solve this issue, please ensure that all of the fields of the tuple struct -are public. Alternatively, provide a new() method to the tuple struct to +are public. Alternatively, provide a `new()` method to the tuple struct to construct it from a given inner value. Example: ``` diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 99c29bbb8ef..dee2727c163 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -94,8 +94,8 @@ pub mod baz {} "##, E0253: r##" -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: +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 { @@ -149,10 +149,10 @@ fn main() {} "##, E0259: r##" -The name chosen for an external crate conflicts with another external crate that -has been imported into the current module. +The name chosen for an external crate conflicts with another external crate +that has been imported into the current module. -Wrong example: +Erroneous code example: ```compile_fail extern crate a; @@ -251,8 +251,8 @@ impl MyTrait for Option { "##, E0364: r##" -Private items cannot be publicly re-exported. This error indicates that -you attempted to `pub use` a type or value that was not itself public. +Private items cannot be publicly re-exported. This error indicates that you +attempted to `pub use` a type or value that was not itself public. Here is an example that demonstrates the error: @@ -275,15 +275,15 @@ mod foo { pub use foo::X; ``` -See the 'Use Declarations' section of the reference for more information -on this topic: +See the 'Use Declarations' section of the reference for more information on +this topic: https://doc.rust-lang.org/reference.html#use-declarations "##, E0365: r##" -Private modules cannot be publicly re-exported. This error indicates -that you attempted to `pub use` a module that was not itself public. +Private modules cannot be publicly re-exported. This error indicates that you +attempted to `pub use` a module that was not itself public. Here is an example that demonstrates the error: @@ -313,8 +313,8 @@ pub mod foo { "##, E0401: r##" -Inner items do not inherit type parameters from the functions they are -embedded in. For example, this will not compile: +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) { @@ -543,16 +543,15 @@ fn b() {} "##, E0411: r##" -The `Self` keyword was used outside an impl or a trait. Erroneous -code example: +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 ``` -The `Self` keyword represents the current type, which explains why it -can only be used inside an impl or a trait. It gives access to the -associated items of a type: +The `Self` keyword represents the current type, which explains why it can only +be used inside an impl or a trait. It gives access to the associated items of a +type: ``` trait Foo { @@ -564,7 +563,7 @@ trait Baz : Foo { } ``` -However, be careful when two types has a common associated type: +However, be careful when two types have a common associated type: ```compile_fail trait Foo { @@ -581,8 +580,8 @@ trait Baz : Foo + Foo2 { } ``` -This problem can be solved by specifying from which trait we want -to use the `Bar` type: +This problem can be solved by specifying from which trait we want to use the +`Bar` type: ``` trait Foo { @@ -604,16 +603,20 @@ trait Baz : Foo + Foo2 { ```compile_fail impl Something {} // error: use of undeclared type name `Something` + // or: + trait Foo { fn bar(N); // error: use of undeclared type name `N` } + // or: + fn foo(x: T) {} // error: use of undeclared type name `T` ``` -To fix this error, please verify you didn't misspell the type name, -you did declare it or imported it into the scope. Examples: +To fix this error, please verify you didn't misspell the type name, you did +declare it or imported it into the scope. Examples: ``` struct Something; @@ -635,8 +638,8 @@ fn foo(x: T) {} // ok! "##, E0413: r##" -A declaration shadows an enum variant or unit-like struct in scope. -Example of erroneous code: +A declaration shadows an enum variant or unit-like struct in scope. Example of +erroneous code: ```compile_fail struct Foo; @@ -666,8 +669,7 @@ fn foo(x: T) {} // ok! "##, E0415: r##" -More than one function parameter have the same name. Example of erroneous -code: +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 @@ -682,8 +684,7 @@ fn foo(f: i32, g: i32) {} // ok! "##, E0416: r##" -An identifier is bound more than once in a pattern. Example of erroneous -code: +An identifier is bound more than once in a pattern. Example of erroneous code: ```compile_fail match (1, 2) { @@ -739,8 +740,7 @@ fn foo(f: i32, g: i32) {} // ok! "##, E0419: r##" -An unknown enum variant, struct or const was used. Example of -erroneous code: +An unknown enum variant, struct or const was used. Example of erroneous code: ```compile_fail match 0 { @@ -766,8 +766,8 @@ enum Something { "##, E0422: r##" -You are trying to use an identifier that is either undefined or not a -struct. For instance: +You are trying to use an identifier that is either undefined or not a struct. +For instance: ``` compile_fail fn main () { @@ -785,13 +785,13 @@ fn main () { } ``` -In this case, `foo` is defined, but is not a struct, so Rust can't use -it as one. +In this case, `foo` is defined, but is not a struct, so Rust can't use it as +one. "##, E0423: r##" -A `struct` variant name was used like a function name. Example of -erroneous code: +A `struct` variant name was used like a function name. Example of erroneous +code: ```compile_fail struct Foo { a: bool}; @@ -801,8 +801,8 @@ fn main () { // it like a function name ``` -Please verify you didn't misspell the name of what you actually wanted -to use here. Example: +Please verify you didn't misspell the name of what you actually wanted to use +here. Example: ``` fn Foo() -> u32 { 0 } @@ -851,6 +851,7 @@ fn foo(self) { // error: unresolved name `something_that_doesnt_exist::foo` // or: + trait Foo { fn bar() { Self; // error: unresolved name `Self` @@ -858,6 +859,7 @@ fn bar() { } // or: + let x = unknown_variable; // error: unresolved name `unknown_variable` ``` @@ -941,7 +943,7 @@ mod something_that_does_exist { "##, E0431: r##" -`self` import was made. Erroneous code example: +An invalid `self` import was made. Erroneous code example: ```compile_fail use {self}; // error: `self` import can only appear in an import list with a -- 2.44.0