From 4b520592eac6b43c72016145855d5616fb16910e Mon Sep 17 00:00:00 2001 From: Nick Hamann Date: Mon, 11 May 2015 14:28:31 -0500 Subject: [PATCH 1/8] Add error explanations for E0049, E0050, E0069, E0106, E0107, E0166. --- src/librustc_typeck/check/mod.rs | 3 +- src/librustc_typeck/diagnostics.rs | 185 ++++++++++++++++++++++++++++- 2 files changed, 181 insertions(+), 7 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 3769e9fa0f36a..fd44f6c7678e6 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -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); diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index ea872d1014425..99932cdf23b6b 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -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) -> 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: @@ -63,6 +108,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 +199,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. +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 +317,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 +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 @@ -313,8 +492,6 @@ 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 @@ -323,7 +500,6 @@ register_diagnostics! { E0061, E0066, E0068, - E0069, E0070, E0071, E0072, @@ -346,8 +522,6 @@ register_diagnostics! { E0102, E0103, E0104, - E0106, - E0107, E0116, E0117, E0118, @@ -365,7 +539,6 @@ register_diagnostics! { E0159, E0163, E0164, - E0166, E0167, E0168, E0172, From 4fee8d3d89edab42efa7d7d4291e23af827e6bdf Mon Sep 17 00:00:00 2001 From: Nick Hamann Date: Mon, 11 May 2015 23:36:54 -0500 Subject: [PATCH 2/8] Add error explanation for E0066. This also updates the error message to remove mention of "managed heap", which was removed in 8a91d33. --- src/librustc_typeck/check/mod.rs | 6 +++--- src/librustc_typeck/diagnostics.rs | 11 ++++++++++- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index fd44f6c7678e6..169c4f6649739 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -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); @@ -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); } } diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 99932cdf23b6b..ecfab0d2c192e 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -91,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, @@ -498,7 +508,6 @@ register_diagnostics! { E0059, E0060, E0061, - E0066, E0068, E0070, E0071, From c3dc769f76e38cdb64453c4acdf945c10ca14400 Mon Sep 17 00:00:00 2001 From: Nick Hamann Date: Tue, 12 May 2015 03:05:16 -0500 Subject: [PATCH 3/8] Add error explanation for E0322. --- src/librustc_typeck/diagnostics.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index ecfab0d2c192e..3f8b1a0ee196e 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -481,6 +481,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. "## } @@ -621,7 +628,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 From 71f6ed8464d3fe910d905ac8ed38ec83e5bd58aa Mon Sep 17 00:00:00 2001 From: Nick Hamann Date: Tue, 12 May 2015 03:06:30 -0500 Subject: [PATCH 4/8] Remove comment description of E0234. This error code has been removed. --- src/librustc_typeck/diagnostics.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 3f8b1a0ee196e..e27ae857cf80a 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -611,7 +611,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 From cbeda68028c7c641c08bb74cac540dfd97433213 Mon Sep 17 00:00:00 2001 From: Nick Hamann Date: Tue, 12 May 2015 04:05:57 -0500 Subject: [PATCH 5/8] Add error explanation for E0201. --- src/librustc_typeck/diagnostics.rs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index e27ae857cf80a..7c4edc1648059 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -350,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 @@ -580,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 From 33a30f272f019f3490800b189aee2307053ab403 Mon Sep 17 00:00:00 2001 From: Nick Hamann Date: Tue, 12 May 2015 13:44:50 -0500 Subject: [PATCH 6/8] Improve error explanations for E0049, E0050, E0166. --- src/librustc_typeck/diagnostics.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 7c4edc1648059..d8c92b9746930 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -28,7 +28,7 @@ but the implementation of `foo` for the type `Bar` is missing this parameter: ``` trait Foo { - fn foo(T) -> Self; + fn foo(x: T) -> Self; } struct Bar; @@ -51,7 +51,7 @@ the `u8` parameter: ``` trait Foo { - fn foo(&self, u8) -> bool; + fn foo(&self, x: u8) -> bool; } struct Bar; @@ -336,9 +336,9 @@ 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 -from a diverging function is an 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##" From 5c77f0d98fbc36ed3982e1f000d9290f31f05bfa Mon Sep 17 00:00:00 2001 From: Nick Hamann Date: Tue, 12 May 2015 13:53:40 -0500 Subject: [PATCH 7/8] Remove extended explanation of lifetime elision from E0106. I've just added a link instead to the lifetime elision section of the book. --- src/librustc_typeck/diagnostics.rs | 28 +++------------------------- 1 file changed, 3 insertions(+), 25 deletions(-) diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index d8c92b9746930..abe91c51e15d3 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -230,31 +230,7 @@ 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. -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. +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 @@ -279,6 +255,8 @@ 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##" From a6d1e98f515a798f888d56d4624011f050efce4e Mon Sep 17 00:00:00 2001 From: Nick Hamann Date: Tue, 12 May 2015 22:02:42 -0500 Subject: [PATCH 8/8] Update error messages for tests in compile-fail for E0066 and E0069. --- src/test/compile-fail/issue-14084.rs | 2 +- src/test/compile-fail/ret-non-nil.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/compile-fail/issue-14084.rs b/src/test/compile-fail/issue-14084.rs index 92e0dd3ad0e52..003c6644f7f02 100644 --- a/src/test/compile-fail/issue-14084.rs +++ b/src/test/compile-fail/issue-14084.rs @@ -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 } diff --git a/src/test/compile-fail/ret-non-nil.rs b/src/test/compile-fail/ret-non-nil.rs index 4ee3cf4abac4e..6be98fbd82773 100644 --- a/src/test/compile-fail/ret-non-nil.rs +++ b/src/test/compile-fail/ret-non-nil.rs @@ -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; }