From c69a152018de3c70e949f758d59e6aa86e19e9d4 Mon Sep 17 00:00:00 2001 From: Nick Hamann Date: Thu, 14 May 2015 15:42:35 -0500 Subject: [PATCH] Add error explanations for E0072, E0073, E0121, E0178, E0371, E0372. --- src/librustc_typeck/diagnostics.rs | 127 +++++++++++++++++- .../coherence-impl-trait-for-trait.rs | 4 +- 2 files changed, 123 insertions(+), 8 deletions(-) diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 58d09632741..bb60de955f0 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -170,6 +170,63 @@ fn foo() -> u8 { function's return type and the value being returned. "##, +E0072: r##" +When defining a recursive struct or enum, any use of the type being defined +from inside the definition must occur behind a pointer (like `Box` or `&`). +This is because structs and enums must have a well-defined size, and without +the pointer the size of the type would need to be unbounded. + +Consider the following erroneous definition of a type for a list of bytes: + +``` +// error, illegal recursive struct type +struct ListNode { + head: u8, + tail: Option, +} +``` + +This type cannot have a well-defined size, because it needs to be arbitrarily +large (since we would be able to nest `ListNode`s to any depth). Specifically, + +``` +size of ListNode = 1 byte for head + + 1 byte for the discriminant of the Option + + size of ListNode +``` + +One way to fix this is by wrapping `ListNode` in a `Box`, like so: + +``` +struct ListNode { + head: u8, + tail: Option>, +} +``` + +This works because `Box` is a pointer, so its size is well-known. +"##, + +E0073: r##" +You cannot define a struct (or enum) `Foo` that requires an instance of `Foo` +in order to make a new `Foo` value. This is because there would be no way a +first instance of `Foo` could be made to initialize another instance! + +Here's an example of a struct that has this problem: + +``` +struct Foo { x: Box } // error +``` + +One fix is to use `Option`, like so: + +``` +struct Foo { x: Option> } +``` + +Now it's possible to create at least one instance of `Foo`: `Foo { x: None }`. +"##, + 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, @@ -327,6 +384,19 @@ impl Quux for Foo { } // error: expected 1, found 0 [iss15872]: https://github.com/rust-lang/rust/issues/15872 "##, +E0121: r##" +In order to be consistent with Rust's lack of global type inference, type +placeholders are disallowed by design in item signatures. + +Examples of this error include: + +``` +fn foo() -> _ { 5 } // error, explicitly write out the return type instead + +static BAR: _ = "test"; // error, explicitly write out the type instead +``` +"##, + 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 `()`. @@ -355,6 +425,28 @@ impl Quux for Foo { } // error: expected 1, found 0 diverging function (such as `panic!()`). "##, +E0178: r##" +In types, the `+` type operator has low precedence, so it is often necessary +to use parentheses. + +For example: + +``` +trait Foo {} + +struct Bar<'a> { + w: &'a Foo + Copy, // error, use &'a (Foo + Copy) + x: &'a Foo + 'a, // error, use &'a (Foo + 'a) + y: &'a mut Foo + 'a, // error, use &'a mut (Foo + 'a) + z: fn() -> Foo + 'a, // error, use fn() -> (Foo + 'a) +} +``` + +More details can be found in [RFC 438]. + +[RFC 438]: https://github.com/rust-lang/rfcs/pull/438 +"##, + 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 @@ -632,6 +724,35 @@ fn main() { to change this. [RFC 953]: https://github.com/rust-lang/rfcs/pull/953 +"##, + +E0371: r##" +When `Trait2` is a subtrait of `Trait1` (for example, when `Trait2` has a +definition like `trait Trait2: Trait1 { ... }`), it is not allowed to implement +`Trait1` for `Trait2`. This is because `Trait2` already implements `Trait1` by +definition, so it is not useful to do this. + +Example: + +``` +trait Foo { fn foo(&self) { } } +trait Bar: Foo { } +trait Baz: Bar { } + +impl Bar for Baz { } // error, `Baz` implements `Bar` by definition +impl Foo for Baz { } // error, `Baz` implements `Bar` which implements `Foo` +impl Baz for Baz { } // error, `Baz` (trivially) implements `Baz` +impl Baz for Bar { } // Note: This is OK +``` +"##, + +E0372: r##" +Trying to implement a trait for a trait object (as in `impl Trait1 for +Trait2 { ... }`) does not work if the trait is not object-safe. Please see the +[RFC 255] for more details on object safety rules. + +[RFC 255]:https://github.com/rust-lang/rfcs/blob/master/text/0255-object-\ +safety.md "## } @@ -660,8 +781,6 @@ fn main() { E0068, E0070, E0071, - E0072, - E0073, E0074, E0075, E0076, @@ -685,7 +804,6 @@ fn main() { E0118, E0119, E0120, - E0121, E0122, E0123, E0124, @@ -702,7 +820,6 @@ fn main() { E0172, E0173, // manual implementations of unboxed closure traits are experimental E0174, // explicit use of unboxed closure methods are experimental - E0178, E0182, E0183, E0185, @@ -774,8 +891,6 @@ fn main() { E0366, // dropck forbid specialization to concrete type or region E0367, // dropck forbid specialization to predicate not in struct/enum E0369, // binary operation `` cannot be applied to types - E0371, // impl Trait for Trait is illegal - E0372, // impl Trait for Trait where Trait is not object safe E0374, // the trait `CoerceUnsized` may only be implemented for a coercion // between structures with one field being coerced, none found E0375, // the trait `CoerceUnsized` may only be implemented for a coercion diff --git a/src/test/compile-fail/coherence-impl-trait-for-trait.rs b/src/test/compile-fail/coherence-impl-trait-for-trait.rs index 23f4218fc1e..332965cc940 100644 --- a/src/test/compile-fail/coherence-impl-trait-for-trait.rs +++ b/src/test/compile-fail/coherence-impl-trait-for-trait.rs @@ -15,14 +15,14 @@ trait Foo { fn dummy(&self) { } } trait Bar: Foo { } trait Baz: Bar { } -// Subtraits of Baz are not legal: +// Supertraits of Baz are not legal: impl Foo for Baz { } //~ ERROR E0371 impl Bar for Baz { } //~ ERROR E0371 impl Baz for Baz { } //~ ERROR E0371 // But other random traits are: trait Other { } -impl Other for Baz { } // OK, Bar not a subtrait of Baz +impl Other for Baz { } // OK, Other not a supertrait of Baz // If the trait is not object-safe, we give a more tailored message // because we're such schnuckels: