-
Notifications
You must be signed in to change notification settings - Fork 13.4k
Add some more error explanations #25328
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 5 commits
4b52059
4fee8d3
c3dc769
71f6ed8
cbeda68
33a30f2
5c77f0d
a6d1e98
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,6 +19,51 @@ methods that do not have default implementations), as well as any required | |
trait items like associated types or constants. | ||
"##, | ||
|
||
E0049: r##" | ||
This error indicates that an attempted implementation of a trait method | ||
has the wrong number of type parameters. | ||
|
||
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: | ||
|
||
``` | ||
trait Foo { | ||
fn foo<T: Default>(T) -> Self; | ||
} | ||
|
||
struct Bar; | ||
|
||
// error: method `foo` has 0 type parameters but its trait declaration has 1 | ||
// type parameter | ||
impl Foo for Bar { | ||
fn foo(x: bool) -> Self { Bar } | ||
} | ||
``` | ||
"##, | ||
|
||
E0050: r##" | ||
This error indicates that an attempted implementation of a trait method | ||
has the wrong number of function parameters. | ||
|
||
For example, the trait below has a method `foo` with two function parameters | ||
(`&self` and `u8`), but the implementation of `foo` for the type `Bar` omits | ||
the `u8` parameter: | ||
|
||
``` | ||
trait Foo { | ||
fn foo(&self, u8) -> bool; | ||
} | ||
|
||
struct Bar; | ||
|
||
// error: method `foo` has 1 parameter but the declaration in trait `Foo::foo` | ||
// has 2 | ||
impl Foo for Bar { | ||
fn foo(&self) -> bool { true } | ||
} | ||
``` | ||
"##, | ||
|
||
E0054: r##" | ||
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: | ||
|
@@ -46,6 +91,16 @@ enum variant, one of the fields was not provided. Each field should be specified | |
exactly once. | ||
"##, | ||
|
||
E0066: r##" | ||
Box placement expressions (like C++'s "placement new") do not support any | ||
place expression except the exchange heap (i.e. `std::boxed::HEAP`). | ||
Furthermore, the syntax is changing to use `in` instead of `box`. See [RFC | ||
470][rfc470] and [RFC 809][rfc809] for more details. | ||
|
||
[rfc470]: https://github.com/rust-lang/rfcs/pull/470 | ||
[rfc809]: https://github.com/rust-lang/rfcs/pull/809 | ||
"##, | ||
|
||
E0067: r##" | ||
The left-hand side of an assignment operator must be an lvalue expression. An | ||
lvalue expression represents a memory location and includes item paths (ie, | ||
|
@@ -63,6 +118,22 @@ LinkedList::new() += 1; | |
``` | ||
"##, | ||
|
||
E0069: r##" | ||
This error means that the compiler found a function whose body contains a | ||
`return;` statement but whose return type is not `()`. For example: | ||
|
||
``` | ||
// error | ||
fn foo() -> u8 { | ||
return; | ||
} | ||
``` | ||
|
||
When you omit the value from a `return` expression (that is, when you use | ||
`return;` instead of `return x;`), the value `()` gets returned. So `return;` | ||
is always incorrect for a function whose return type is not `()`. | ||
"##, | ||
|
||
E0081: r##" | ||
Enum discriminants are used to differentiate enum variants stored in memory. | ||
This error indicates that the same value was used for two or more variants, | ||
|
@@ -138,6 +209,110 @@ enum Empty {} | |
``` | ||
"##, | ||
|
||
E0106: r##" | ||
This error indicates that a lifetime is missing from a type. If it is an error | ||
inside a function signature, the problem may be with failing to adhere to the | ||
lifetime elision rules (see below). | ||
|
||
Here are some simple examples of where you'll run into this error: | ||
|
||
``` | ||
struct Foo { x: &bool } // error | ||
struct Foo<'a> { x: &'a bool } // correct | ||
|
||
enum Bar { A(u8), B(&bool), } // error | ||
enum Bar<'a> { A(u8), B(&'a bool), } // correct | ||
|
||
type MyStr = &str; // error | ||
type MyStr<'a> = &'a str; //correct | ||
|
||
``` | ||
|
||
Lifetime elision is a special, limited kind of inference for lifetimes in | ||
function signatures which allows you to leave out lifetimes in certain cases. | ||
For example, the lifetimes on parameter in the following function signatures | ||
have been left out, but they still compile successfully: | ||
|
||
``` | ||
fn foo(x: &str) { } | ||
|
||
fn bar(x: &str, y: &str) { } | ||
|
||
fn baz(x: &str) -> &str { x } | ||
``` | ||
|
||
To explain the lifetime elision rules, we need to first discuss some background. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wonder if this may not be the best place to talk about lifetime elision? These are definitely great docs, but perhaps they could be placed in a lifetime elision chapter of the book instead? (and then this would link to that chapter) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. After reading it again, I agree. I've removed a good chunk of the explanation of lifetime elision and added a link to the lifetime elision section of the book. Let me know if you think this is still too much explanation. |
||
The lifetime elision rules consider each lifetime in a function signature, | ||
whether it's elided or not, to be in a certain position, either *input | ||
position*, for function parameters, or *output position*, for the return type. | ||
For example, the function: | ||
|
||
``` | ||
fn hello<'a>(name: &'a str) -> (&'static str, &str) { | ||
("hello", name) | ||
} | ||
``` | ||
|
||
has a signature with one lifetime in input position and two lifetimes in output | ||
position. | ||
|
||
The lifetime elision rules require that any function signature with an elided | ||
output lifetime must either have | ||
|
||
- exactly one input lifetime | ||
- or, multiple input lifetimes, but the function must also be a method with a | ||
`&self` or `&mut self` receiver | ||
|
||
In the first case, the output lifetime is inferred to be the same as the unique | ||
input lifetime. In the second case, the lifetime is instead inferred to be the | ||
same as the lifetime on `&self` or `&mut self`. | ||
|
||
Here are some examples of elision errors: | ||
|
||
``` | ||
// error, no input lifetimes | ||
fn foo() -> &str { ... } | ||
|
||
// error, `x` and `y` have distinct lifetimes inferred | ||
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 { ... } | ||
``` | ||
"##, | ||
|
||
E0107: r##" | ||
This error means that an incorrect number of lifetime parameters were provided | ||
for a type (like a struct or enum) or trait. | ||
|
||
Some basic examples include: | ||
|
||
``` | ||
struct Foo<'a>(&'a str); | ||
enum Bar { A, B, C } | ||
|
||
struct Baz<'a> { | ||
foo: Foo, // error: expected 1, found 0 | ||
bar: Bar<'a>, // error: expected 0, found 1 | ||
} | ||
``` | ||
|
||
Here's an example that is currently an error, but may work in a future version | ||
of Rust: | ||
|
||
``` | ||
struct Foo<'a>(&'a str); | ||
|
||
trait Quux { } | ||
impl Quux for Foo { } // error: expected 1, found 0 | ||
``` | ||
|
||
Lifetime elision in implementation headers was part of the lifetime elision | ||
RFC. It is, however, [currently unimplemented][iss15872]. | ||
|
||
[iss15872]: https://github.com/rust-lang/rust/issues/15872 | ||
"##, | ||
|
||
E0131: r##" | ||
It is not possible to define `main` with type parameters, or even with function | ||
parameters. When `main` is present, it must take no arguments and return `()`. | ||
|
@@ -152,6 +327,20 @@ fn(isize, *const *const u8) -> isize | |
``` | ||
"##, | ||
|
||
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: | ||
|
||
``` | ||
fn foo() -> ! { return; } // error | ||
``` | ||
|
||
For a function that diverges, every control path in the function must end | ||
with a call to `panic!()` or another diverging function. Attempting to return | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps this could be re-worded to something like:
Specifically a call to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ahh, I didn't realize the thing with loops. (Also that sentence was paraphrased from the Reference, so I should probably update too). Fixed. |
||
from a diverging function is an error. | ||
"##, | ||
|
||
E0184: r##" | ||
Explicitly implementing both Drop and Copy for a type is currently disallowed. | ||
This feature can make some sense in theory, but the current implementation is | ||
|
@@ -161,6 +350,24 @@ it has been disabled for now. | |
[iss20126]: https://github.com/rust-lang/rust/issues/20126 | ||
"##, | ||
|
||
E0201: r##" | ||
It is an error to define a method--a trait method or an inherent method--more | ||
than once. | ||
|
||
For example, | ||
|
||
``` | ||
struct Foo(u8); | ||
|
||
impl Foo { | ||
fn bar() {} | ||
|
||
// error: duplicate method | ||
fn bar(&self) -> bool { self.0 > 5 } | ||
} | ||
``` | ||
"##, | ||
|
||
E0204: r##" | ||
An attempt to implement the `Copy` trait for a struct failed because one of the | ||
fields does not implement `Copy`. To fix this, you must implement `Copy` for the | ||
|
@@ -292,6 +499,13 @@ const B: [u32; foo()] = []; | |
use std::{f64, u8}; | ||
const C: [u32; u8::MAX + f64::EPSILON] = []; | ||
``` | ||
"##, | ||
|
||
E0322: r##" | ||
The `Sized` trait is a special trait built-in to the compiler for types with a | ||
constant size known at compile-time. This trait is automatically implemented | ||
for types as needed by the compiler, and it is currently disallowed to | ||
explicitly implement it for a type. | ||
"## | ||
|
||
} | ||
|
@@ -313,17 +527,13 @@ register_diagnostics! { | |
E0040, // explicit use of destructor method | ||
E0044, // foreign items may not have type parameters | ||
E0045, // variadic function must have C calling convention | ||
E0049, | ||
E0050, | ||
E0053, | ||
E0055, // method has an incompatible type for trait | ||
E0057, // method has an incompatible type for trait | ||
E0059, | ||
E0060, | ||
E0061, | ||
E0066, | ||
E0068, | ||
E0069, | ||
E0070, | ||
E0071, | ||
E0072, | ||
|
@@ -346,8 +556,6 @@ register_diagnostics! { | |
E0102, | ||
E0103, | ||
E0104, | ||
E0106, | ||
E0107, | ||
E0116, | ||
E0117, | ||
E0118, | ||
|
@@ -365,7 +573,6 @@ register_diagnostics! { | |
E0159, | ||
E0163, | ||
E0164, | ||
E0166, | ||
E0167, | ||
E0168, | ||
E0172, | ||
|
@@ -391,7 +598,6 @@ register_diagnostics! { | |
E0198, // negative implementations are not unsafe | ||
E0199, // implementing trait is not unsafe | ||
E0200, // trait requires an `unsafe impl` declaration | ||
E0201, // duplicate method in trait impl | ||
E0202, // associated items are not allowed in inherent impls | ||
E0203, // type parameter has more than one relaxed default bound, | ||
// and only one is supported | ||
|
@@ -422,7 +628,7 @@ register_diagnostics! { | |
E0231, // only named substitution parameters are allowed | ||
E0232, // this attribute must have a value | ||
E0233, | ||
E0234, // `for` loop expression has type which does not implement the `Iterator` trait | ||
E0234, | ||
E0235, // structure constructor specifies a structure of type but | ||
E0236, // no lang item for range syntax | ||
E0237, // no lang item for range syntax | ||
|
@@ -439,7 +645,6 @@ register_diagnostics! { | |
E0319, // trait impls for defaulted traits allowed just for structs/enums | ||
E0320, // recursive overflow during dropck | ||
E0321, // extended coherence rules for defaulted traits violated | ||
E0322, // cannot implement Sized explicitly | ||
E0323, // implemented an associated const when another trait item expected | ||
E0324, // implemented a method when another trait item expected | ||
E0325, // implemented an associated type when another trait item expected | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think not naming the parameter here is somewhat rare, could this be given a name?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(ah same for the above
fn foo
as well)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.