Skip to content

Commit d7a32b0

Browse files
author
Nick Hamann
committed
Add error explanations for E0072, E0073, E0121, E0178, E0371, E0372.
1 parent af52207 commit d7a32b0

File tree

2 files changed

+134
-8
lines changed

2 files changed

+134
-8
lines changed

src/librustc_typeck/diagnostics.rs

Lines changed: 132 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,64 @@ LinkedList::new() += 1;
108108
```
109109
"##,
110110

111+
E0072: r##"
112+
When defining a recursive struct or enum, any use of the type being defined
113+
from inside the definition must occur behind a pointer (like `Box` or `&`).
114+
This is because structs and enums must have a well-defined size, and without
115+
the pointer the size of the type would need to be unbounded.
116+
117+
Consider the following erroneous definition of a type for a list of bytes:
118+
119+
```
120+
// error, illegal recursive struct type
121+
struct ListNode {
122+
head: u8,
123+
tail: Option<ListNode>,
124+
}
125+
```
126+
127+
This type cannot have a well-defined size, because it needs to be arbitrarily
128+
large (since we would be able to nest `ListNode`s to any depth). Specifically,
129+
130+
```
131+
size of ListNode = 1 byte for head
132+
+ 1 byte for the discriminant of the Option
133+
+ size of ListNode
134+
```
135+
136+
One way to fix this is by wrapping `ByteList` in a `Box`, like so:
137+
138+
```
139+
struct ByteList {
140+
head: u8,
141+
tail: Option<Box<ByteList>>,
142+
}
143+
```
144+
145+
This works because `Box` is a pointer, so its size is well-known.
146+
"##,
147+
148+
E0073: r##"
149+
You cannot define a struct (or enum) `Foo` that requires an instance of `Foo`
150+
in order to make a new `Foo` value (think about it: if making an instance of
151+
`Foo` requires an already-existing instance of `Foo`, how does the first
152+
instance get made?).
153+
154+
Here's an example of a struct that has this problem:
155+
156+
```
157+
struct Foo { x: Box<Foo> } // error
158+
```
159+
160+
One fix is to use `Option`, like so:
161+
162+
```
163+
struct Foo { x: Option<Box<Foo>> }
164+
```
165+
166+
Now it's possible to create at least one instance of Foo: `Foo { x: None }`.
167+
"##,
168+
111169
E0081: r##"
112170
Enum discriminants are used to differentiate enum variants stored in memory.
113171
This error indicates that the same value was used for two or more variants,
@@ -265,6 +323,28 @@ RFC. It is, however, [currently unimplemented][iss15872].
265323
[iss15872]: https://github.com/rust-lang/rust/issues/15872
266324
"##,
267325

326+
E0121: r##"
327+
When `_` is in a type, it can act as a placeholder for another type. The
328+
compiler interprets it as a request to infer the type. This enables partial
329+
type hints, as in the following example:
330+
331+
```
332+
// x is a Vec<T> for some T. The compiler infers T.
333+
let x: Vec<_> = (0..4).collect();
334+
```
335+
336+
However, in order to be consistent with Rust's lack of global type inference,
337+
type placeholders are disallowed by design in item signatures.
338+
339+
Examples of this error include:
340+
341+
```
342+
fn foo() -> _ { 5 } // error, explicitly write out the return type instead
343+
344+
static BAR: _ = "test"; // error, explicitly write out the type instead
345+
```
346+
"##,
347+
268348
E0131: r##"
269349
It is not possible to define `main` with type parameters, or even with function
270350
parameters. When `main` is present, it must take no arguments and return `()`.
@@ -293,6 +373,29 @@ return, for example with a `loop` that never breaks or a call to another
293373
diverging function (such as `panic!()`).
294374
"##,
295375

376+
E0178: r##"
377+
In types, the `+` type operator has low precedence, so it is often necessary
378+
to use parentheses.
379+
380+
For example:
381+
382+
```
383+
trait Foo {}
384+
385+
struct Bar<'a> {
386+
w: &'a Foo + Copy, // error, use &'a (Foo + Copy)
387+
x: &'a Foo + 'a, // error, use &'a (Foo + 'a)
388+
y: &'a mut Foo + 'a, // error, use &'a mut (Foo + 'a)
389+
z: fn() -> Foo + 'a, // error, use fn() -> (Foo + 'a)
390+
}
391+
```
392+
393+
More details can be found in [RFC 438].
394+
395+
[RFC 438]: https://github.com/rust-lang/rfcs/blob/master/text/0438-precedence-\
396+
of-plus.md
397+
"##,
398+
296399
E0184: r##"
297400
Explicitly implementing both Drop and Copy for a type is currently disallowed.
298401
This feature can make some sense in theory, but the current implementation is
@@ -458,6 +561,35 @@ The `Sized` trait is a special trait built-in to the compiler for types with a
458561
constant size known at compile-time. This trait is automatically implemented
459562
for types as needed by the compiler, and it is currently disallowed to
460563
explicitly implement it for a type.
564+
"##,
565+
566+
E0371: r##"
567+
When `Trait2` is a subtrait of `Trait1` (for example, when `Trait2` has a
568+
definition like `trait Trait2: Trait1 { ... }`), it is not allowed to implement
569+
`Trait1` for `Trait2`. This is because `Trait2` already implements `Trait1` by
570+
definition, so it is not useful to do this.
571+
572+
Example:
573+
574+
```
575+
trait Foo { fn foo(&self) { } }
576+
trait Bar: Foo { }
577+
trait Baz: Bar { }
578+
579+
impl Bar for Baz { } // error, `Baz` implements `Bar` by definition
580+
impl Foo for Baz { } // error, `Baz` implements `Bar` which implements `Foo`
581+
impl Baz for Baz { } // error, `Baz` (trivially) implements `Baz`
582+
impl Baz for Bar { } // Note: This is OK
583+
```
584+
"##,
585+
586+
E0372: r##"
587+
Trying to implement a trait for a trait object (as in `impl Trait1 for
588+
Trait2 { ... }`) does not work if the trait is not object-safe. Please see the
589+
[RFC 255] for more details on object safety rules.
590+
591+
[RFC 255]:https://github.com/rust-lang/rfcs/blob/master/text/0255-object-\
592+
safety.md
461593
"##
462594

463595
}
@@ -489,8 +621,6 @@ register_diagnostics! {
489621
E0069,
490622
E0070,
491623
E0071,
492-
E0072,
493-
E0073,
494624
E0074,
495625
E0075,
496626
E0076,
@@ -514,7 +644,6 @@ register_diagnostics! {
514644
E0118,
515645
E0119,
516646
E0120,
517-
E0121,
518647
E0122,
519648
E0123,
520649
E0124,
@@ -531,7 +660,6 @@ register_diagnostics! {
531660
E0172,
532661
E0173, // manual implementations of unboxed closure traits are experimental
533662
E0174, // explicit use of unboxed closure methods are experimental
534-
E0178,
535663
E0182,
536664
E0183,
537665
E0185,
@@ -608,8 +736,6 @@ register_diagnostics! {
608736
E0367, // dropck forbid specialization to predicate not in struct/enum
609737
E0368, // binary operation `<op>=` cannot be applied to types
610738
E0369, // binary operation `<op>` cannot be applied to types
611-
E0371, // impl Trait for Trait is illegal
612-
E0372, // impl Trait for Trait where Trait is not object safe
613739
E0374, // the trait `CoerceUnsized` may only be implemented for a coercion
614740
// between structures with one field being coerced, none found
615741
E0375, // the trait `CoerceUnsized` may only be implemented for a coercion

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

Lines changed: 2 additions & 2 deletions
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)