mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-09 16:37:36 +00:00
Add E0746 explanation to the index
This commit is contained in:
parent
93293c56e8
commit
4c13d2555c
@ -414,6 +414,7 @@ E0742: include_str!("./error_codes/E0742.md"),
|
|||||||
E0743: include_str!("./error_codes/E0743.md"),
|
E0743: include_str!("./error_codes/E0743.md"),
|
||||||
E0744: include_str!("./error_codes/E0744.md"),
|
E0744: include_str!("./error_codes/E0744.md"),
|
||||||
E0745: include_str!("./error_codes/E0745.md"),
|
E0745: include_str!("./error_codes/E0745.md"),
|
||||||
|
E0746: include_str!("./error_codes/E0746.md"),
|
||||||
;
|
;
|
||||||
// E0006, // merged with E0005
|
// E0006, // merged with E0005
|
||||||
// E0008, // cannot bind by-move into a pattern guard
|
// E0008, // cannot bind by-move into a pattern guard
|
||||||
@ -608,5 +609,4 @@ E0745: include_str!("./error_codes/E0745.md"),
|
|||||||
E0726, // non-explicit (not `'_`) elided lifetime in unsupported position
|
E0726, // non-explicit (not `'_`) elided lifetime in unsupported position
|
||||||
E0727, // `async` generators are not yet supported
|
E0727, // `async` generators are not yet supported
|
||||||
E0739, // invalid track_caller application/syntax
|
E0739, // invalid track_caller application/syntax
|
||||||
E0746, // `dyn Trait` return type
|
|
||||||
}
|
}
|
||||||
|
137
src/librustc_error_codes/error_codes/E0746.md
Normal file
137
src/librustc_error_codes/error_codes/E0746.md
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
Return types cannot be `dyn Trait`s as they must be `Sized`.
|
||||||
|
|
||||||
|
Erroneous code example:
|
||||||
|
|
||||||
|
```compile_fail,E0746
|
||||||
|
trait T {
|
||||||
|
fn bar(&self);
|
||||||
|
}
|
||||||
|
struct S(usize);
|
||||||
|
impl T for S {
|
||||||
|
fn bar(&self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Having the trait `T` as return type is invalid because bare traits do not
|
||||||
|
have a statically known size:
|
||||||
|
fn foo() -> dyn T {
|
||||||
|
S(42)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
To avoid the error there are a couple of options.
|
||||||
|
|
||||||
|
If there is a single type involved, you can use [`impl Trait`]:
|
||||||
|
|
||||||
|
```
|
||||||
|
# trait T {
|
||||||
|
# fn bar(&self);
|
||||||
|
# }
|
||||||
|
# struct S(usize);
|
||||||
|
# impl T for S {
|
||||||
|
# fn bar(&self) {}
|
||||||
|
# }
|
||||||
|
// The compiler will select `S(usize)` as the materialized return type of this
|
||||||
|
// function, but callers will only be able to access associated items from `T`.
|
||||||
|
fn foo() -> impl T {
|
||||||
|
S(42)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
If there are multiple types involved, the only way you care to interact with
|
||||||
|
them is through the trait's interface and having to rely on dynamic dispatch is
|
||||||
|
acceptable, then you can use [trait objects] with `Box`, or other container
|
||||||
|
types like `Rc` or `Arc`:
|
||||||
|
|
||||||
|
```
|
||||||
|
# trait T {
|
||||||
|
# fn bar(&self);
|
||||||
|
# }
|
||||||
|
# struct S(usize);
|
||||||
|
# impl T for S {
|
||||||
|
# fn bar(&self) {}
|
||||||
|
# }
|
||||||
|
struct O(&'static str);
|
||||||
|
impl T for O {
|
||||||
|
fn bar(&self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This now returns a "trait object" and callers are only be able to access
|
||||||
|
// associated items from `T`.
|
||||||
|
fn foo(x: bool) -> Box<dyn T> {
|
||||||
|
if x {
|
||||||
|
Box::new(S(42))
|
||||||
|
} else {
|
||||||
|
Box::new(O("val"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Finally, if you wish to still be able to access the original type, you can
|
||||||
|
create a new `enum` with a variant for each type:
|
||||||
|
|
||||||
|
```
|
||||||
|
# trait T {
|
||||||
|
# fn bar(&self);
|
||||||
|
# }
|
||||||
|
# struct S(usize);
|
||||||
|
# impl T for S {
|
||||||
|
# fn bar(&self) {}
|
||||||
|
# }
|
||||||
|
# struct O(&'static str);
|
||||||
|
# impl T for O {
|
||||||
|
# fn bar(&self) {}
|
||||||
|
# }
|
||||||
|
enum E {
|
||||||
|
S(S),
|
||||||
|
O(O),
|
||||||
|
}
|
||||||
|
|
||||||
|
// The caller can access the original types directly, but it needs to match on
|
||||||
|
// the returned `enum E`.
|
||||||
|
fn foo(x: bool) -> E {
|
||||||
|
if x {
|
||||||
|
E::S(S(42))
|
||||||
|
} else {
|
||||||
|
E::O(O("val"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
You can even implement the `trait` on the returned `enum` so the callers
|
||||||
|
*don't* have to match on the returned value to invoke the associated items:
|
||||||
|
|
||||||
|
```
|
||||||
|
# trait T {
|
||||||
|
# fn bar(&self);
|
||||||
|
# }
|
||||||
|
# struct S(usize);
|
||||||
|
# impl T for S {
|
||||||
|
# fn bar(&self) {}
|
||||||
|
# }
|
||||||
|
# struct O(&'static str);
|
||||||
|
# impl T for O {
|
||||||
|
# fn bar(&self) {}
|
||||||
|
# }
|
||||||
|
# enum E {
|
||||||
|
# S(S),
|
||||||
|
# O(O),
|
||||||
|
# }
|
||||||
|
impl T for E {
|
||||||
|
fn bar(&self) {
|
||||||
|
match self {
|
||||||
|
E::S(s) => s.bar(),
|
||||||
|
E::O(o) => o.bar(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
If you decide to use trait objects, be aware that these rely on
|
||||||
|
[dynamic dispatch], which has performance implications, as the compiler needs
|
||||||
|
to emit code that will figure out which method to call *at runtime* instead of
|
||||||
|
during compilation. Using trait objects we are trading flexibility for
|
||||||
|
performance.
|
||||||
|
|
||||||
|
[`impl Trait`]: https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits
|
||||||
|
[trait objects]: https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types
|
||||||
|
[dynamic dispatch]: https://doc.rust-lang.org/book/ch17-02-trait-objects.html#trait-objects-perform-dynamic-dispatch
|
@ -24,3 +24,4 @@ LL | fn bar() -> impl Trait {
|
|||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0746`.
|
||||||
|
@ -116,5 +116,5 @@ LL | fn bat() -> impl Trait {
|
|||||||
|
|
||||||
error: aborting due to 9 previous errors
|
error: aborting due to 9 previous errors
|
||||||
|
|
||||||
Some errors have detailed explanations: E0277, E0308.
|
Some errors have detailed explanations: E0277, E0308, E0746.
|
||||||
For more information about an error, try `rustc --explain E0277`.
|
For more information about an error, try `rustc --explain E0277`.
|
||||||
|
Loading…
Reference in New Issue
Block a user