Skip to content

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

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions src/librustc_typeck/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3033,8 +3033,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
let mut checked = false;
opt_place.as_ref().map(|place| match place.node {
ast::ExprPath(None, ref path) => {
// FIXME(pcwalton): For now we hardcode the two permissible
// places: the exchange heap and the managed heap.
// FIXME(pcwalton): For now we hardcode the only permissible
// place: the exchange heap.
let definition = lookup_full_def(tcx, path.span, place.id);
let def_id = definition.def_id();
let referent_ty = fcx.expr_ty(&**subexpr);
Expand All @@ -3048,7 +3048,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,

if !checked {
span_err!(tcx.sess, expr.span, E0066,
"only the managed heap and exchange heap are currently supported");
"only the exchange heap is currently supported");
fcx.write_ty(id, tcx.types.err);
}
}
Expand Down Expand Up @@ -3268,7 +3268,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
if let Err(_) = fcx.mk_eqty(false, infer::Misc(expr.span),
result_type, ty::mk_nil(fcx.tcx())) {
span_err!(tcx.sess, expr.span, E0069,
"`return;` in function returning non-nil");
"`return;` in a function whose return type is \
not `()`");
},
Some(ref e) => {
check_expr_coercable_to_type(fcx, &**e, result_type);
Expand Down
203 changes: 193 additions & 10 deletions src/librustc_typeck/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>(x: 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, x: 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:
Expand Down Expand Up @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -138,6 +209,88 @@ 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 more background on lifetime elision see [the book][book-le].

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 { ... }
```

[book-le]: http://doc.rust-lang.org/nightly/book/lifetimes.html#lifetime-elision
"##,

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 `()`.
Expand All @@ -152,6 +305,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 never
return, for example with a `loop` that never breaks or a call to another
diverging function (such as `panic!()`).
"##,

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
Expand All @@ -161,6 +328,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
Expand Down Expand Up @@ -292,6 +477,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.
"##

}
Expand All @@ -313,17 +505,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,
Expand All @@ -346,8 +534,6 @@ register_diagnostics! {
E0102,
E0103,
E0104,
E0106,
E0107,
E0116,
E0117,
E0118,
Expand All @@ -365,7 +551,6 @@ register_diagnostics! {
E0159,
E0163,
E0164,
E0166,
E0167,
E0168,
E0172,
Expand All @@ -391,7 +576,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
Expand Down Expand Up @@ -422,7 +606,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
Expand All @@ -439,7 +623,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
Expand Down
2 changes: 1 addition & 1 deletion src/test/compile-fail/issue-14084.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@

fn main() {
box ( () ) 0;
//~^ ERROR: only the managed heap and exchange heap are currently supported
//~^ ERROR: only the exchange heap is currently supported
}
2 changes: 1 addition & 1 deletion src/test/compile-fail/ret-non-nil.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// error-pattern: `return;` in function returning non-nil
// error-pattern: `return;` in a function whose return type is not `()`

fn f() { return; }

Expand Down