Skip to content

Commit 2dd5ad0

Browse files
committed
Auto merge of #25501 - nham:E0072_E0073, r=alexcrichton
cc #24407
2 parents 84b1e08 + c69a152 commit 2dd5ad0

File tree

2 files changed

+123
-8
lines changed

2 files changed

+123
-8
lines changed

src/librustc_typeck/diagnostics.rs

+121-6
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,63 @@ Since `return;` is just like `return ();`, there is a mismatch between the
170170
function's return type and the value being returned.
171171
"##,
172172

173+
E0072: r##"
174+
When defining a recursive struct or enum, any use of the type being defined
175+
from inside the definition must occur behind a pointer (like `Box` or `&`).
176+
This is because structs and enums must have a well-defined size, and without
177+
the pointer the size of the type would need to be unbounded.
178+
179+
Consider the following erroneous definition of a type for a list of bytes:
180+
181+
```
182+
// error, illegal recursive struct type
183+
struct ListNode {
184+
head: u8,
185+
tail: Option<ListNode>,
186+
}
187+
```
188+
189+
This type cannot have a well-defined size, because it needs to be arbitrarily
190+
large (since we would be able to nest `ListNode`s to any depth). Specifically,
191+
192+
```
193+
size of ListNode = 1 byte for head
194+
+ 1 byte for the discriminant of the Option
195+
+ size of ListNode
196+
```
197+
198+
One way to fix this is by wrapping `ListNode` in a `Box`, like so:
199+
200+
```
201+
struct ListNode {
202+
head: u8,
203+
tail: Option<Box<ListNode>>,
204+
}
205+
```
206+
207+
This works because `Box` is a pointer, so its size is well-known.
208+
"##,
209+
210+
E0073: r##"
211+
You cannot define a struct (or enum) `Foo` that requires an instance of `Foo`
212+
in order to make a new `Foo` value. This is because there would be no way a
213+
first instance of `Foo` could be made to initialize another instance!
214+
215+
Here's an example of a struct that has this problem:
216+
217+
```
218+
struct Foo { x: Box<Foo> } // error
219+
```
220+
221+
One fix is to use `Option`, like so:
222+
223+
```
224+
struct Foo { x: Option<Box<Foo>> }
225+
```
226+
227+
Now it's possible to create at least one instance of `Foo`: `Foo { x: None }`.
228+
"##,
229+
173230
E0081: r##"
174231
Enum discriminants are used to differentiate enum variants stored in memory.
175232
This error indicates that the same value was used for two or more variants,
@@ -327,6 +384,19 @@ RFC. It is, however, [currently unimplemented][iss15872].
327384
[iss15872]: https://github.com/rust-lang/rust/issues/15872
328385
"##,
329386

387+
E0121: r##"
388+
In order to be consistent with Rust's lack of global type inference, type
389+
placeholders are disallowed by de# item signatures.
390+
391+
Examples of this error include:
392+
393+
```
394+
fn foo() -> _ { 5 } // error, explicitly write out the return type instead
395+
396+
static BAR: _ = "test"; // error, explicitly write out the type instead
397+
```
398+
"##,
399+
330400
E0131: r##"
331401
It is not possible to define `main` with type parameters, or even with function
332402
parameters. When `main` is present, it must take no arguments and return `()`.
@@ -355,6 +425,28 @@ return, for example with a `loop` that never breaks or a call to another
355425
diverging function (such as `panic!()`).
356426
"##,
357427

428+
E0178: r##"
429+
In types, the `+` type operator has low precedence, so it is often necessary
430+
to use parentheses.
431+
432+
For example:
433+
434+
```
435+
trait Foo {}
436+
437+
struct Bar<'a> {
438+
w: &'a Foo + Copy, // error, use &'a (Foo + Copy)
439+
x: &'a Foo + 'a, // error, use &'a (Foo + 'a)
440+
y: &'a mut Foo + 'a, // error, use &'a mut (Foo + 'a)
441+
z: fn() -> Foo + 'a, // error, use fn() -> (Foo + 'a)
442+
}
443+
```
444+
445+
More details can be found in [RFC 438].
446+
447+
[RFC 438]: https://github.com/rust-lang/rfcs/pull/438
448+
"##,
449+
358450
E0184: r##"
359451
Explicitly implementing both Drop and Copy for a type is currently disallowed.
360452
This feature can make some sense in theory, but the current implementation is
@@ -632,6 +724,35 @@ traits, so it is not possible to overload them. See [RFC 953] for a proposal
632724
to change this.
633725
634726
[RFC 953]: https://github.com/rust-lang/rfcs/pull/953
727+
"##,
728+
729+
E0371: r##"
730+
When `Trait2` is a subtrait of `Trait1` (for example, when `Trait2` has a
731+
definition like `trait Trait2: Trait1 { ... }`), it is not allowed to implement
732+
`Trait1` for `Trait2`. This is because `Trait2` already implements `Trait1` by
733+
definition, so it is not useful to do this.
734+
735+
Example:
736+
737+
```
738+
trait Foo { fn foo(&self) { } }
739+
trait Bar: Foo { }
740+
trait Baz: Bar { }
741+
742+
impl Bar for Baz { } // error, `Baz` implements `Bar` by definition
743+
impl Foo for Baz { } // error, `Baz` implements `Bar` which implements `Foo`
744+
impl Baz for Baz { } // error, `Baz` (trivially) implements `Baz`
745+
impl Baz for Bar { } // Note: This is OK
746+
```
747+
"##,
748+
749+
E0372: r##"
750+
Trying to implement a trait for a trait object (as in `impl Trait1 for
751+
Trait2 { ... }`) does not work if the trait is not object-safe. Please see the
752+
[RFC 255] for more details on object safety rules.
753+
754+
[RFC 255]:https://github.com/rust-lang/rfcs/blob/master/text/0255-object-\
755+
safety.md
635756
"##
636757

637758
}
@@ -660,8 +781,6 @@ register_diagnostics! {
660781
E0068,
661782
E0070,
662783
E0071,
663-
E0072,
664-
E0073,
665784
E0074,
666785
E0075,
667786
E0076,
@@ -685,7 +804,6 @@ register_diagnostics! {
685804
E0118,
686805
E0119,
687806
E0120,
688-
E0121,
689807
E0122,
690808
E0123,
691809
E0124,
@@ -702,7 +820,6 @@ register_diagnostics! {
702820
E0172,
703821
E0173, // manual implementations of unboxed closure traits are experimental
704822
E0174, // explicit use of unboxed closure methods are experimental
705-
E0178,
706823
E0182,
707824
E0183,
708825
E0185,
@@ -774,8 +891,6 @@ register_diagnostics! {
774891
E0366, // dropck forbid specialization to concrete type or region
775892
E0367, // dropck forbid specialization to predicate not in struct/enum
776893
E0369, // binary operation `<op>` cannot be applied to types
777-
E0371, // impl Trait for Trait is illegal
778-
E0372, // impl Trait for Trait where Trait is not object safe
779894
E0374, // the trait `CoerceUnsized` may only be implemented for a coercion
780895
// between structures with one field being coerced, none found
781896
E0375, // the trait `CoerceUnsized` may only be implemented for a coercion

src/test/compile-fail/coherence-impl-trait-for-trait.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,14 @@ trait Foo { fn dummy(&self) { } }
1515
trait Bar: Foo { }
1616
trait Baz: Bar { }
1717

18-
// Subtraits of Baz are not legal:
18+
// Supertraits of Baz are not legal:
1919
impl Foo for Baz { } //~ ERROR E0371
2020
impl Bar for Baz { } //~ ERROR E0371
2121
impl Baz for Baz { } //~ ERROR E0371
2222

2323
// But other random traits are:
2424
trait Other { }
25-
impl Other for Baz { } // OK, Bar not a subtrait of Baz
25+
impl Other for Baz { } // OK, Other not a supertrait of Baz
2626

2727
// If the trait is not object-safe, we give a more tailored message
2828
// because we're such schnuckels:

0 commit comments

Comments
 (0)