Rollup merge of #68195 - estebank:impl-trait-2000, r=Centril

Account for common `impl Trait`/`dyn Trait` return type errors

- When all return paths have the same type, suggest `impl Trait`.
- When all return paths implement the expected `trait`, suggest `Box<dyn Trait>` and mention using an `enum`.
- When multiple different types are returned and `impl Trait` is expected, extend the explanation.
- When return type is `impl Trait` and the return paths do not implement `Trait`, point at the returned values.
- Split `src/librustc/traits/error_reporting.rs` into multiple files to keep size under control.

Fix #68110, cc #66523.
This commit is contained in:
Dylan DPC 2020-01-17 11:16:37 +05:30 committed by GitHub
commit de01a29fbe
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
38 changed files with 4067 additions and 3027 deletions

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,199 @@
use super::{
ObligationCauseCode, OnUnimplementedDirective, OnUnimplementedNote, PredicateObligation,
};
use crate::infer::InferCtxt;
use crate::ty::subst::Subst;
use crate::ty::{self, GenericParamDefKind};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_span::symbol::sym;
impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
fn impl_similar_to(
&self,
trait_ref: ty::PolyTraitRef<'tcx>,
obligation: &PredicateObligation<'tcx>,
) -> Option<DefId> {
let tcx = self.tcx;
let param_env = obligation.param_env;
let trait_ref = tcx.erase_late_bound_regions(&trait_ref);
let trait_self_ty = trait_ref.self_ty();
let mut self_match_impls = vec![];
let mut fuzzy_match_impls = vec![];
self.tcx.for_each_relevant_impl(trait_ref.def_id, trait_self_ty, |def_id| {
let impl_substs = self.fresh_substs_for_item(obligation.cause.span, def_id);
let impl_trait_ref = tcx.impl_trait_ref(def_id).unwrap().subst(tcx, impl_substs);
let impl_self_ty = impl_trait_ref.self_ty();
if let Ok(..) = self.can_eq(param_env, trait_self_ty, impl_self_ty) {
self_match_impls.push(def_id);
if trait_ref
.substs
.types()
.skip(1)
.zip(impl_trait_ref.substs.types().skip(1))
.all(|(u, v)| self.fuzzy_match_tys(u, v))
{
fuzzy_match_impls.push(def_id);
}
}
});
let impl_def_id = if self_match_impls.len() == 1 {
self_match_impls[0]
} else if fuzzy_match_impls.len() == 1 {
fuzzy_match_impls[0]
} else {
return None;
};
tcx.has_attr(impl_def_id, sym::rustc_on_unimplemented).then_some(impl_def_id)
}
/// Used to set on_unimplemented's `ItemContext`
/// to be the enclosing (async) block/function/closure
fn describe_enclosure(&self, hir_id: hir::HirId) -> Option<&'static str> {
let hir = &self.tcx.hir();
let node = hir.find(hir_id)?;
if let hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, _, body_id), .. }) = &node {
self.describe_generator(*body_id).or_else(|| {
Some(if let hir::FnHeader { asyncness: hir::IsAsync::Async, .. } = sig.header {
"an async function"
} else {
"a function"
})
})
} else if let hir::Node::Expr(hir::Expr {
kind: hir::ExprKind::Closure(_is_move, _, body_id, _, gen_movability),
..
}) = &node
{
self.describe_generator(*body_id).or_else(|| {
Some(if gen_movability.is_some() { "an async closure" } else { "a closure" })
})
} else if let hir::Node::Expr(hir::Expr { .. }) = &node {
let parent_hid = hir.get_parent_node(hir_id);
if parent_hid != hir_id {
return self.describe_enclosure(parent_hid);
} else {
None
}
} else {
None
}
}
crate fn on_unimplemented_note(
&self,
trait_ref: ty::PolyTraitRef<'tcx>,
obligation: &PredicateObligation<'tcx>,
) -> OnUnimplementedNote {
let def_id =
self.impl_similar_to(trait_ref, obligation).unwrap_or_else(|| trait_ref.def_id());
let trait_ref = *trait_ref.skip_binder();
let mut flags = vec![];
flags.push((
sym::item_context,
self.describe_enclosure(obligation.cause.body_id).map(|s| s.to_owned()),
));
match obligation.cause.code {
ObligationCauseCode::BuiltinDerivedObligation(..)
| ObligationCauseCode::ImplDerivedObligation(..) => {}
_ => {
// this is a "direct", user-specified, rather than derived,
// obligation.
flags.push((sym::direct, None));
}
}
if let ObligationCauseCode::ItemObligation(item) = obligation.cause.code {
// FIXME: maybe also have some way of handling methods
// from other traits? That would require name resolution,
// which we might want to be some sort of hygienic.
//
// Currently I'm leaving it for what I need for `try`.
if self.tcx.trait_of_item(item) == Some(trait_ref.def_id) {
let method = self.tcx.item_name(item);
flags.push((sym::from_method, None));
flags.push((sym::from_method, Some(method.to_string())));
}
}
if let Some((t, _)) = self.get_parent_trait_ref(&obligation.cause.code) {
flags.push((sym::parent_trait, Some(t)));
}
if let Some(k) = obligation.cause.span.desugaring_kind() {
flags.push((sym::from_desugaring, None));
flags.push((sym::from_desugaring, Some(format!("{:?}", k))));
}
let generics = self.tcx.generics_of(def_id);
let self_ty = trait_ref.self_ty();
// This is also included through the generics list as `Self`,
// but the parser won't allow you to use it
flags.push((sym::_Self, Some(self_ty.to_string())));
if let Some(def) = self_ty.ty_adt_def() {
// We also want to be able to select self's original
// signature with no type arguments resolved
flags.push((sym::_Self, Some(self.tcx.type_of(def.did).to_string())));
}
for param in generics.params.iter() {
let value = match param.kind {
GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => {
trait_ref.substs[param.index as usize].to_string()
}
GenericParamDefKind::Lifetime => continue,
};
let name = param.name;
flags.push((name, Some(value)));
}
if let Some(true) = self_ty.ty_adt_def().map(|def| def.did.is_local()) {
flags.push((sym::crate_local, None));
}
// Allow targeting all integers using `{integral}`, even if the exact type was resolved
if self_ty.is_integral() {
flags.push((sym::_Self, Some("{integral}".to_owned())));
}
if let ty::Array(aty, len) = self_ty.kind {
flags.push((sym::_Self, Some("[]".to_owned())));
flags.push((sym::_Self, Some(format!("[{}]", aty))));
if let Some(def) = aty.ty_adt_def() {
// We also want to be able to select the array's type's original
// signature with no type arguments resolved
flags.push((
sym::_Self,
Some(format!("[{}]", self.tcx.type_of(def.did).to_string())),
));
let tcx = self.tcx;
if let Some(len) = len.try_eval_usize(tcx, ty::ParamEnv::empty()) {
flags.push((
sym::_Self,
Some(format!("[{}; {}]", self.tcx.type_of(def.did).to_string(), len)),
));
} else {
flags.push((
sym::_Self,
Some(format!("[{}; _]", self.tcx.type_of(def.did).to_string())),
));
}
}
}
if let Ok(Some(command)) =
OnUnimplementedDirective::of_item(self.tcx, trait_ref.def_id, def_id)
{
command.evaluate(self.tcx, trait_ref, &flags[..])
} else {
OnUnimplementedNote::default()
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -155,8 +155,8 @@ pub struct ObligationCause<'tcx> {
pub code: ObligationCauseCode<'tcx>,
}
impl<'tcx> ObligationCause<'tcx> {
pub fn span(&self, tcx: TyCtxt<'tcx>) -> Span {
impl ObligationCause<'_> {
pub fn span(&self, tcx: TyCtxt<'_>) -> Span {
match self.code {
ObligationCauseCode::CompareImplMethodObligation { .. }
| ObligationCauseCode::MainFunctionType
@ -1171,6 +1171,17 @@ impl<'tcx> ObligationCause<'tcx> {
}
}
impl ObligationCauseCode<'_> {
// Return the base obligation, ignoring derived obligations.
pub fn peel_derives(&self) -> &Self {
let mut base_cause = self;
while let BuiltinDerivedObligation(cause) | ImplDerivedObligation(cause) = base_cause {
base_cause = &cause.parent_code;
}
base_cause
}
}
impl<'tcx, N> Vtable<'tcx, N> {
pub fn nested_obligations(self) -> Vec<N> {
match self {

View file

@ -244,9 +244,9 @@ impl<'tcx> ty::TyS<'tcx> {
ty::FnPtr(_) => "fn pointer".into(),
ty::Dynamic(ref inner, ..) => {
if let Some(principal) = inner.principal() {
format!("trait `{}`", tcx.def_path_str(principal.def_id())).into()
format!("trait object `dyn {}`", tcx.def_path_str(principal.def_id())).into()
} else {
"trait".into()
"trait object".into()
}
}
ty::Closure(..) => "closure".into(),

View file

@ -414,6 +414,7 @@ E0742: include_str!("./error_codes/E0742.md"),
E0743: include_str!("./error_codes/E0743.md"),
E0744: include_str!("./error_codes/E0744.md"),
E0745: include_str!("./error_codes/E0745.md"),
E0746: include_str!("./error_codes/E0746.md"),
;
// E0006, // merged with E0005
// E0008, // cannot bind by-move into a pattern guard

View file

@ -0,0 +1,138 @@
Return types cannot be `dyn Trait`s as they must be `Sized`.
Erroneous code example:
```compile_fail,E0277
# // FIXME: after E0746 is in beta, change the above
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
// unboxed trait objects 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 know that the return type implements `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

View file

@ -377,6 +377,13 @@ pub enum GenericBound<'hir> {
}
impl GenericBound<'_> {
pub fn trait_def_id(&self) -> Option<DefId> {
match self {
GenericBound::Trait(data, _) => Some(data.trait_ref.trait_def_id()),
_ => None,
}
}
pub fn span(&self) -> Span {
match self {
&GenericBound::Trait(ref t, ..) => t.span,

View file

@ -50,10 +50,12 @@
//! sort of a minor point so I've opted to leave it for later -- after all,
//! we may want to adjust precisely when coercions occur.
use crate::astconv::AstConv;
use crate::check::{FnCtxt, Needs};
use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc::infer::{Coercion, InferOk, InferResult};
use rustc::session::parse::feature_err;
use rustc::traits::object_safety_violations;
use rustc::traits::{self, ObligationCause, ObligationCauseCode};
use rustc::ty::adjustment::{
Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCast,
@ -67,8 +69,8 @@ use rustc_error_codes::*;
use rustc_errors::{struct_span_err, DiagnosticBuilder};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_span;
use rustc_span::symbol::sym;
use rustc_span::{self, Span};
use rustc_target::spec::abi::Abi;
use smallvec::{smallvec, SmallVec};
use std::ops::Deref;
@ -1222,6 +1224,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
};
let mut err;
let mut unsized_return = false;
match cause.code {
ObligationCauseCode::ReturnNoExpression => {
err = struct_span_err!(
@ -1243,6 +1246,9 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
parent_id,
expression.map(|expr| (expr, blk_id)),
);
if !fcx.tcx.features().unsized_locals {
unsized_return = self.is_return_ty_unsized(fcx, blk_id);
}
}
ObligationCauseCode::ReturnValue(id) => {
err = self.report_return_mismatched_types(
@ -1254,6 +1260,10 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
id,
None,
);
if !fcx.tcx.features().unsized_locals {
let id = fcx.tcx.hir().get_parent_node(id);
unsized_return = self.is_return_ty_unsized(fcx, id);
}
}
_ => {
err = fcx.report_mismatched_types(cause, expected, found, coercion_error);
@ -1282,7 +1292,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
.filter(|e| fcx.is_assign_to_bool(e, self.expected_ty()))
.is_some();
err.emit_unless(assign_to_bool);
err.emit_unless(assign_to_bool || unsized_return);
self.final_ty = Some(fcx.tcx.types.err);
}
@ -1302,7 +1312,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
let mut err = fcx.report_mismatched_types(cause, expected, found, ty_err);
let mut pointing_at_return_type = false;
let mut return_sp = None;
let mut fn_output = None;
// Verify that this is a tail expression of a function, otherwise the
// label pointing out the cause for the type coercion will be wrong
@ -1339,19 +1349,98 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
);
}
if !pointing_at_return_type {
return_sp = Some(fn_decl.output.span()); // `impl Trait` return type
fn_output = Some(&fn_decl.output); // `impl Trait` return type
}
}
if let (Some(sp), Some(return_sp)) = (fcx.ret_coercion_span.borrow().as_ref(), return_sp) {
err.span_label(return_sp, "expected because this return type...");
err.span_label( *sp, format!(
"...is found to be `{}` here",
fcx.resolve_vars_with_obligations(expected),
));
if let (Some(sp), Some(fn_output)) = (fcx.ret_coercion_span.borrow().as_ref(), fn_output) {
self.add_impl_trait_explanation(&mut err, fcx, expected, *sp, fn_output);
}
err
}
fn add_impl_trait_explanation<'a>(
&self,
err: &mut DiagnosticBuilder<'a>,
fcx: &FnCtxt<'a, 'tcx>,
expected: Ty<'tcx>,
sp: Span,
fn_output: &hir::FunctionRetTy<'_>,
) {
let return_sp = fn_output.span();
err.span_label(return_sp, "expected because this return type...");
err.span_label(
sp,
format!("...is found to be `{}` here", fcx.resolve_vars_with_obligations(expected)),
);
let impl_trait_msg = "for information on `impl Trait`, see \
<https://doc.rust-lang.org/book/ch10-02-traits.html\
#returning-types-that-implement-traits>";
let trait_obj_msg = "for information on trait objects, see \
<https://doc.rust-lang.org/book/ch17-02-trait-objects.html\
#using-trait-objects-that-allow-for-values-of-different-types>";
err.note("to return `impl Trait`, all returned values must be of the same type");
err.note(impl_trait_msg);
let snippet = fcx
.tcx
.sess
.source_map()
.span_to_snippet(return_sp)
.unwrap_or_else(|_| "dyn Trait".to_string());
let mut snippet_iter = snippet.split_whitespace();
let has_impl = snippet_iter.next().map_or(false, |s| s == "impl");
// Only suggest `Box<dyn Trait>` if `Trait` in `impl Trait` is object safe.
let mut is_object_safe = false;
if let hir::FunctionRetTy::Return(ty) = fn_output {
// Get the return type.
if let hir::TyKind::Def(..) = ty.kind {
let ty = AstConv::ast_ty_to_ty(fcx, ty);
// Get the `impl Trait`'s `DefId`.
if let ty::Opaque(def_id, _) = ty.kind {
let hir_id = fcx.tcx.hir().as_local_hir_id(def_id).unwrap();
// Get the `impl Trait`'s `Item` so that we can get its trait bounds and
// get the `Trait`'s `DefId`.
if let hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, .. }) =
fcx.tcx.hir().expect_item(hir_id).kind
{
// Are of this `impl Trait`'s traits object safe?
is_object_safe = bounds.iter().all(|bound| {
bound.trait_def_id().map_or(false, |def_id| {
object_safety_violations(fcx.tcx, def_id).is_empty()
})
})
}
}
}
};
if has_impl {
if is_object_safe {
err.help(&format!(
"you can instead return a boxed trait object using `Box<dyn {}>`",
&snippet[5..]
));
} else {
err.help(&format!(
"if the trait `{}` were object safe, you could return a boxed trait object",
&snippet[5..]
));
}
err.note(trait_obj_msg);
}
err.help("alternatively, create a new `enum` with a variant for each returned type");
}
fn is_return_ty_unsized(&self, fcx: &FnCtxt<'a, 'tcx>, blk_id: hir::HirId) -> bool {
if let Some((fn_decl, _)) = fcx.get_fn_decl(blk_id) {
if let hir::FunctionRetTy::Return(ty) = fn_decl.output {
let ty = AstConv::ast_ty_to_ty(fcx, ty);
if let ty::Dynamic(..) = ty.kind {
return true;
}
}
}
false
}
pub fn complete<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Ty<'tcx> {
if let Some(final_ty) = self.final_ty {
final_ty

View file

@ -1,8 +1,17 @@
error: future cannot be sent between threads safely
--> $DIR/issue-64130-4-async-move.rs:15:17
|
LL | pub fn foo() -> impl Future + Send {
| ^^^^^^^^^^^^^^^^^^ future returned by `foo` is not `Send`
LL | pub fn foo() -> impl Future + Send {
| ^^^^^^^^^^^^^^^^^^ future returned by `foo` is not `Send`
...
LL | / async move {
LL | | match client.status() {
LL | | 200 => {
LL | | let _x = get().await;
... |
LL | | }
LL | | }
| |_____- this returned value is of type `impl std::future::Future`
|
= help: the trait `std::marker::Sync` is not implemented for `(dyn std::any::Any + std::marker::Send + 'static)`
note: future is not `Send` as this value is used across an await

View file

@ -29,7 +29,7 @@ error[E0308]: mismatched types
--> $DIR/coerce-expect-unsized-ascribed.rs:13:13
|
LL | let _ = box { |x| (x as u8) }: Box<dyn Fn(i32) -> _>;
| ^^^^^^^^^^^^^^^^^^^^^ expected trait `std::ops::Fn`, found closure
| ^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn std::ops::Fn`, found closure
|
= note: expected struct `std::boxed::Box<dyn std::ops::Fn(i32) -> u8>`
found struct `std::boxed::Box<[closure@$DIR/coerce-expect-unsized-ascribed.rs:13:19: 13:32]>`
@ -38,7 +38,7 @@ error[E0308]: mismatched types
--> $DIR/coerce-expect-unsized-ascribed.rs:14:13
|
LL | let _ = box if true { false } else { true }: Box<dyn Debug>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait `std::fmt::Debug`, found `bool`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn std::fmt::Debug`, found `bool`
|
= note: expected struct `std::boxed::Box<dyn std::fmt::Debug>`
found struct `std::boxed::Box<bool>`
@ -47,7 +47,7 @@ error[E0308]: mismatched types
--> $DIR/coerce-expect-unsized-ascribed.rs:15:13
|
LL | let _ = box match true { true => 'a', false => 'b' }: Box<dyn Debug>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait `std::fmt::Debug`, found `char`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn std::fmt::Debug`, found `char`
|
= note: expected struct `std::boxed::Box<dyn std::fmt::Debug>`
found struct `std::boxed::Box<char>`
@ -83,7 +83,7 @@ error[E0308]: mismatched types
--> $DIR/coerce-expect-unsized-ascribed.rs:21:13
|
LL | let _ = &{ |x| (x as u8) }: &dyn Fn(i32) -> _;
| ^^^^^^^^^^^^^^^^^^ expected trait `std::ops::Fn`, found closure
| ^^^^^^^^^^^^^^^^^^ expected trait object `dyn std::ops::Fn`, found closure
|
= note: expected reference `&dyn std::ops::Fn(i32) -> u8`
found reference `&[closure@$DIR/coerce-expect-unsized-ascribed.rs:21:16: 21:29]`
@ -92,7 +92,7 @@ error[E0308]: mismatched types
--> $DIR/coerce-expect-unsized-ascribed.rs:22:13
|
LL | let _ = &if true { false } else { true }: &dyn Debug;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait `std::fmt::Debug`, found `bool`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn std::fmt::Debug`, found `bool`
|
= note: expected reference `&dyn std::fmt::Debug`
found reference `&bool`
@ -101,7 +101,7 @@ error[E0308]: mismatched types
--> $DIR/coerce-expect-unsized-ascribed.rs:23:13
|
LL | let _ = &match true { true => 'a', false => 'b' }: &dyn Debug;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait `std::fmt::Debug`, found `char`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn std::fmt::Debug`, found `char`
|
= note: expected reference `&dyn std::fmt::Debug`
found reference `&char`
@ -119,7 +119,7 @@ error[E0308]: mismatched types
--> $DIR/coerce-expect-unsized-ascribed.rs:26:13
|
LL | let _ = Box::new(|x| (x as u8)): Box<dyn Fn(i32) -> _>;
| ^^^^^^^^^^^^^^^^^^^^^^^ expected trait `std::ops::Fn`, found closure
| ^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn std::ops::Fn`, found closure
|
= note: expected struct `std::boxed::Box<dyn std::ops::Fn(i32) -> _>`
found struct `std::boxed::Box<[closure@$DIR/coerce-expect-unsized-ascribed.rs:26:22: 26:35]>`

View file

@ -3,6 +3,9 @@ error[E0277]: arrays only have std trait implementations for lengths 0..=32
|
LL | pub fn no_vec_partial_eq_array<A, B>() -> impl PartialEq<[B; 33]>
| ^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[B; 33]`
...
LL | Vec::<A>::new()
| --------------- this returned value is of type `std::vec::Vec<A>`
|
= note: required because of the requirements on the impl of `std::cmp::PartialEq<[B; 33]>` for `std::vec::Vec<A>`
= note: the return type of a function must have a statically known size
@ -12,6 +15,9 @@ error[E0277]: arrays only have std trait implementations for lengths 0..=32
|
LL | pub fn no_vec_partial_eq_ref_array<'a, A, B>() -> impl PartialEq<&'a [B; 33]>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[B; 33]`
...
LL | Vec::<A>::new()
| --------------- this returned value is of type `std::vec::Vec<A>`
|
= note: required because of the requirements on the impl of `std::cmp::PartialEq<&'a [B; 33]>` for `std::vec::Vec<A>`
= note: the return type of a function must have a statically known size
@ -21,6 +27,9 @@ error[E0277]: arrays only have std trait implementations for lengths 0..=32
|
LL | pub fn no_vecdeque_partial_eq_array<A, B>() -> impl PartialEq<[B; 33]>
| ^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[B; 33]`
...
LL | VecDeque::<A>::new()
| -------------------- this returned value is of type `std::collections::VecDeque<A>`
|
= note: required because of the requirements on the impl of `std::cmp::PartialEq<[B; 33]>` for `std::collections::VecDeque<A>`
= note: the return type of a function must have a statically known size
@ -30,6 +39,9 @@ error[E0277]: arrays only have std trait implementations for lengths 0..=32
|
LL | pub fn no_vecdeque_partial_eq_ref_array<'a, A, B>() -> impl PartialEq<&'a [B; 33]>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[B; 33]`
...
LL | VecDeque::<A>::new()
| -------------------- this returned value is of type `std::collections::VecDeque<A>`
|
= note: required because of the requirements on the impl of `std::cmp::PartialEq<&'a [B; 33]>` for `std::collections::VecDeque<A>`
= note: the return type of a function must have a statically known size
@ -39,6 +51,9 @@ error[E0277]: arrays only have std trait implementations for lengths 0..=32
|
LL | pub fn no_vecdeque_partial_eq_ref_mut_array<'a, A, B>() -> impl PartialEq<&'a mut [B; 33]>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[B; 33]`
...
LL | VecDeque::<A>::new()
| -------------------- this returned value is of type `std::collections::VecDeque<A>`
|
= note: required because of the requirements on the impl of `std::cmp::PartialEq<&'a mut [B; 33]>` for `std::collections::VecDeque<A>`
= note: the return type of a function must have a statically known size

View file

@ -11,6 +11,9 @@ error[E0277]: arrays only have std trait implementations for lengths 0..=32
|
LL | pub fn no_iterator() -> impl Iterator<Item = i32> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
LL |
LL | IntoIter::new([0i32; 33])
| ------------------------- this returned value is of type `std::array::IntoIter<i32, 33usize>`
|
= note: required because of the requirements on the impl of `std::iter::Iterator` for `std::array::IntoIter<i32, 33usize>`
= note: the return type of a function must have a statically known size
@ -28,6 +31,9 @@ error[E0277]: arrays only have std trait implementations for lengths 0..=32
|
LL | pub fn no_double_ended_iterator() -> impl DoubleEndedIterator {
| ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
LL |
LL | IntoIter::new([0i32; 33])
| ------------------------- this returned value is of type `std::array::IntoIter<i32, 33usize>`
|
= note: required because of the requirements on the impl of `std::iter::DoubleEndedIterator` for `std::array::IntoIter<i32, 33usize>`
= note: the return type of a function must have a statically known size
@ -45,6 +51,9 @@ error[E0277]: arrays only have std trait implementations for lengths 0..=32
|
LL | pub fn no_exact_size_iterator() -> impl ExactSizeIterator {
| ^^^^^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
LL |
LL | IntoIter::new([0i32; 33])
| ------------------------- this returned value is of type `std::array::IntoIter<i32, 33usize>`
|
= note: required because of the requirements on the impl of `std::iter::ExactSizeIterator` for `std::array::IntoIter<i32, 33usize>`
= note: the return type of a function must have a statically known size
@ -62,6 +71,9 @@ error[E0277]: arrays only have std trait implementations for lengths 0..=32
|
LL | pub fn no_fused_iterator() -> impl FusedIterator {
| ^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
LL |
LL | IntoIter::new([0i32; 33])
| ------------------------- this returned value is of type `std::array::IntoIter<i32, 33usize>`
|
= note: required because of the requirements on the impl of `std::iter::FusedIterator` for `std::array::IntoIter<i32, 33usize>`
= note: the return type of a function must have a statically known size
@ -79,6 +91,9 @@ error[E0277]: arrays only have std trait implementations for lengths 0..=32
|
LL | pub fn no_trusted_len() -> impl TrustedLen {
| ^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
LL |
LL | IntoIter::new([0i32; 33])
| ------------------------- this returned value is of type `std::array::IntoIter<i32, 33usize>`
|
= note: required because of the requirements on the impl of `std::iter::TrustedLen` for `std::array::IntoIter<i32, 33usize>`
= note: the return type of a function must have a statically known size
@ -96,6 +111,9 @@ error[E0277]: arrays only have std trait implementations for lengths 0..=32
|
LL | pub fn no_clone() -> impl Clone {
| ^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
LL |
LL | IntoIter::new([0i32; 33])
| ------------------------- this returned value is of type `std::array::IntoIter<i32, 33usize>`
|
= note: required because of the requirements on the impl of `std::clone::Clone` for `std::array::IntoIter<i32, 33usize>`
= note: the return type of a function must have a statically known size
@ -113,6 +131,9 @@ error[E0277]: arrays only have std trait implementations for lengths 0..=32
|
LL | pub fn no_debug() -> impl Debug {
| ^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
LL |
LL | IntoIter::new([0i32; 33])
| ------------------------- this returned value is of type `std::array::IntoIter<i32, 33usize>`
|
= note: required because of the requirements on the impl of `std::fmt::Debug` for `std::array::IntoIter<i32, 33usize>`
= note: the return type of a function must have a statically known size

View file

@ -33,12 +33,10 @@ fn main() {
//~^ ERROR mismatched types
//~| expected trait object `dyn T`
//~| found reference `&_`
//~| expected trait `T`, found reference
let &&&x = &(&1isize as &dyn T);
//~^ ERROR mismatched types
//~| expected trait object `dyn T`
//~| found reference `&_`
//~| expected trait `T`, found reference
let box box x = box 1isize as Box<dyn T>;
//~^ ERROR mismatched types
//~| expected trait object `dyn T`

View file

@ -22,31 +22,31 @@ error[E0308]: mismatched types
LL | let &&x = &1isize as &dyn T;
| ^^
| |
| expected trait `T`, found reference
| expected trait object `dyn T`, found reference
| help: you can probably remove the explicit borrow: `x`
|
= note: expected trait object `dyn T`
found reference `&_`
error[E0308]: mismatched types
--> $DIR/destructure-trait-ref.rs:37:11
--> $DIR/destructure-trait-ref.rs:36:11
|
LL | let &&&x = &(&1isize as &dyn T);
| ^^
| |
| expected trait `T`, found reference
| expected trait object `dyn T`, found reference
| help: you can probably remove the explicit borrow: `x`
|
= note: expected trait object `dyn T`
found reference `&_`
error[E0308]: mismatched types
--> $DIR/destructure-trait-ref.rs:42:13
--> $DIR/destructure-trait-ref.rs:40:13
|
LL | let box box x = box 1isize as Box<dyn T>;
| ^^^^^ ------------------------ this expression has type `std::boxed::Box<dyn T>`
| |
| expected trait `T`, found struct `std::boxed::Box`
| expected trait object `dyn T`, found struct `std::boxed::Box`
|
= note: expected trait object `dyn T`
found struct `std::boxed::Box<_>`

View file

@ -32,7 +32,7 @@ pub fn main() {
let z: Box<dyn ToBar> = Box::new(Bar1 {f: 36});
f5.2 = Bar1 {f: 36};
//~^ ERROR mismatched types
//~| expected trait `ToBar`, found struct `Bar1`
//~| expected trait object `dyn ToBar`, found struct `Bar1`
//~| expected trait object `dyn ToBar`
//~| found struct `Bar1`
//~| ERROR the size for values of type

View file

@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/dst-bad-assign-3.rs:33:12
|
LL | f5.2 = Bar1 {f: 36};
| ^^^^^^^^^^^^ expected trait `ToBar`, found struct `Bar1`
| ^^^^^^^^^^^^ expected trait object `dyn ToBar`, found struct `Bar1`
|
= note: expected trait object `dyn ToBar`
found struct `Bar1`

View file

@ -34,7 +34,7 @@ pub fn main() {
let z: Box<dyn ToBar> = Box::new(Bar1 {f: 36});
f5.ptr = Bar1 {f: 36};
//~^ ERROR mismatched types
//~| expected trait `ToBar`, found struct `Bar1`
//~| expected trait object `dyn ToBar`, found struct `Bar1`
//~| expected trait object `dyn ToBar`
//~| found struct `Bar1`
//~| ERROR the size for values of type

View file

@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/dst-bad-assign.rs:35:14
|
LL | f5.ptr = Bar1 {f: 36};
| ^^^^^^^^^^^^ expected trait `ToBar`, found struct `Bar1`
| ^^^^^^^^^^^^ expected trait object `dyn ToBar`, found struct `Bar1`
|
= note: expected trait object `dyn ToBar`
found struct `Bar1`

View file

@ -0,0 +1,18 @@
// run-rustfix
#![allow(dead_code)]
struct Struct;
trait Trait {}
impl Trait for Struct {}
impl Trait for u32 {}
fn foo() -> impl Trait { Struct }
//~^ ERROR E0746
fn bar() -> impl Trait { //~ ERROR E0746
if true {
return 0;
}
42
}
fn main() {}

View file

@ -0,0 +1,18 @@
// run-rustfix
#![allow(dead_code)]
struct Struct;
trait Trait {}
impl Trait for Struct {}
impl Trait for u32 {}
fn foo() -> dyn Trait { Struct }
//~^ ERROR E0746
fn bar() -> dyn Trait { //~ ERROR E0746
if true {
return 0;
}
42
}
fn main() {}

View file

@ -0,0 +1,27 @@
error[E0746]: return type cannot have an unboxed trait object
--> $DIR/E0746.rs:8:13
|
LL | fn foo() -> dyn Trait { Struct }
| ^^^^^^^^^ doesn't have a size known at compile-time
|
= note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
help: return `impl Trait` instead, as all return paths are of type `Struct`, which implements `Trait`
|
LL | fn foo() -> impl Trait { Struct }
| ^^^^^^^^^^
error[E0746]: return type cannot have an unboxed trait object
--> $DIR/E0746.rs:11:13
|
LL | fn bar() -> dyn Trait {
| ^^^^^^^^^ doesn't have a size known at compile-time
|
= note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
help: return `impl Trait` instead, as all return paths are of type `{integer}`, which implements `Trait`
|
LL | fn bar() -> impl Trait {
| ^^^^^^^^^^
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0746`.

View file

@ -38,7 +38,7 @@ LL | type C where Self: Copy = String;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
|
= note: required because of the requirements on the impl of `std::marker::Copy` for `Fooy<T>`
= note: the requirement `Fooy<T>: std::marker::Copy` appears on the associated impl typebut not on the corresponding associated trait type
= note: the requirement `Fooy<T>: std::marker::Copy` appears on the associated impl type but not on the corresponding associated trait type
error: aborting due to 3 previous errors

View file

@ -0,0 +1,34 @@
#![allow(bare_trait_objects)]
struct Struct;
trait Trait {}
impl Trait for Struct {}
impl Trait for u32 {}
fn fuz() -> (usize, Trait) { (42, Struct) }
//~^ ERROR E0277
//~| ERROR E0308
fn bar() -> (usize, dyn Trait) { (42, Struct) }
//~^ ERROR E0277
//~| ERROR E0308
fn bap() -> Trait { Struct }
//~^ ERROR E0746
fn ban() -> dyn Trait { Struct }
//~^ ERROR E0746
fn bak() -> dyn Trait { unimplemented!() } //~ ERROR E0277
// Suggest using `Box<dyn Trait>`
fn bal() -> dyn Trait { //~ ERROR E0746
if true {
return Struct;
}
42
}
// Suggest using `impl Trait`
fn bat() -> dyn Trait { //~ ERROR E0746
if true {
return 0;
}
42
}
fn main() {}

View file

@ -0,0 +1,113 @@
error[E0308]: mismatched types
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:7:35
|
LL | fn fuz() -> (usize, Trait) { (42, Struct) }
| ^^^^^^ expected trait object `dyn Trait`, found struct `Struct`
|
= note: expected trait object `(dyn Trait + 'static)`
found struct `Struct`
error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:7:13
|
LL | fn fuz() -> (usize, Trait) { (42, Struct) }
| ^^^^^^^^^^^^^^ ------------ this returned value is of type `(usize, (dyn Trait + 'static))`
| |
| doesn't have a size known at compile-time
|
= help: within `(usize, (dyn Trait + 'static))`, the trait `std::marker::Sized` is not implemented for `(dyn Trait + 'static)`
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
= note: required because it appears within the type `(usize, (dyn Trait + 'static))`
= note: the return type of a function must have a statically known size
error[E0308]: mismatched types
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:10:39
|
LL | fn bar() -> (usize, dyn Trait) { (42, Struct) }
| ^^^^^^ expected trait object `dyn Trait`, found struct `Struct`
|
= note: expected trait object `(dyn Trait + 'static)`
found struct `Struct`
error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:10:13
|
LL | fn bar() -> (usize, dyn Trait) { (42, Struct) }
| ^^^^^^^^^^^^^^^^^^ ------------ this returned value is of type `(usize, (dyn Trait + 'static))`
| |
| doesn't have a size known at compile-time
|
= help: within `(usize, (dyn Trait + 'static))`, the trait `std::marker::Sized` is not implemented for `(dyn Trait + 'static)`
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
= note: required because it appears within the type `(usize, (dyn Trait + 'static))`
= note: the return type of a function must have a statically known size
error[E0746]: return type cannot have an unboxed trait object
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:13:13
|
LL | fn bap() -> Trait { Struct }
| ^^^^^ doesn't have a size known at compile-time
|
= note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
help: return `impl Trait` instead, as all return paths are of type `Struct`, which implements `Trait`
|
LL | fn bap() -> impl Trait { Struct }
| ^^^^^^^^^^
error[E0746]: return type cannot have an unboxed trait object
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:15:13
|
LL | fn ban() -> dyn Trait { Struct }
| ^^^^^^^^^ doesn't have a size known at compile-time
|
= note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
help: return `impl Trait` instead, as all return paths are of type `Struct`, which implements `Trait`
|
LL | fn ban() -> impl Trait { Struct }
| ^^^^^^^^^^
error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:17:13
|
LL | fn bak() -> dyn Trait { unimplemented!() }
| ^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `(dyn Trait + 'static)`
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
= note: the return type of a function must have a statically known size
error[E0746]: return type cannot have an unboxed trait object
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:19:13
|
LL | fn bal() -> dyn Trait {
| ^^^^^^^^^ doesn't have a size known at compile-time
|
= note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
= note: if all the returned values were of the same type you could use `impl Trait` as the return type
= note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
= note: you can create a new `enum` with a variant for each returned type
help: return a boxed trait object instead
|
LL | fn bal() -> Box<dyn Trait> {
LL | if true {
LL | return Box::new(Struct);
LL | }
LL | Box::new(42)
|
error[E0746]: return type cannot have an unboxed trait object
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:27:13
|
LL | fn bat() -> dyn Trait {
| ^^^^^^^^^ doesn't have a size known at compile-time
|
= note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
help: return `impl Trait` instead, as all return paths are of type `{integer}`, which implements `Trait`
|
LL | fn bat() -> impl Trait {
| ^^^^^^^^^^
error: aborting due to 9 previous errors
Some errors have detailed explanations: E0277, E0308, E0746.
For more information about an error, try `rustc --explain E0277`.

View file

@ -9,6 +9,12 @@ LL | return 1_i32;
LL | }
LL | 0_u32
| ^^^^^ expected `i32`, found `u32`
|
= note: to return `impl Trait`, all returned values must be of the same type
= note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
= help: if the trait `Foo` were object safe, you could return a boxed trait object
= note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
= help: alternatively, create a new `enum` with a variant for each returned type
error[E0277]: cannot add `impl Foo` to `u32`
--> $DIR/equality.rs:24:11

View file

@ -0,0 +1,35 @@
#![allow(bare_trait_objects)]
trait NotObjectSafe {
fn foo() -> Self;
}
struct A;
struct B;
impl NotObjectSafe for A {
fn foo() -> Self {
A
}
}
impl NotObjectSafe for B {
fn foo() -> Self {
B
}
}
fn car() -> dyn NotObjectSafe { //~ ERROR the trait `NotObjectSafe` cannot be made into an object
if true {
return A;
}
B
}
fn cat() -> Box<dyn NotObjectSafe> { //~ ERROR the trait `NotObjectSafe` cannot be made into an
if true {
return Box::new(A);
}
Box::new(B)
}
fn main() {}

View file

@ -0,0 +1,21 @@
error[E0038]: the trait `NotObjectSafe` cannot be made into an object
--> $DIR/object-unsafe-trait-in-return-position-dyn-trait.rs:21:1
|
LL | fn foo() -> Self;
| --- associated function `foo` has no `self` parameter
...
LL | fn car() -> dyn NotObjectSafe {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `NotObjectSafe` cannot be made into an object
error[E0038]: the trait `NotObjectSafe` cannot be made into an object
--> $DIR/object-unsafe-trait-in-return-position-dyn-trait.rs:28:1
|
LL | fn foo() -> Self;
| --- associated function `foo` has no `self` parameter
...
LL | fn cat() -> Box<dyn NotObjectSafe> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `NotObjectSafe` cannot be made into an object
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0038`.

View file

@ -0,0 +1,46 @@
trait NotObjectSafe {
fn foo() -> Self;
}
trait ObjectSafe {
fn bar(&self);
}
struct A;
struct B;
impl NotObjectSafe for A {
fn foo() -> Self {
A
}
}
impl NotObjectSafe for B {
fn foo() -> Self {
B
}
}
impl ObjectSafe for A {
fn bar(&self) {}
}
impl ObjectSafe for B {
fn bar(&self) {}
}
fn can() -> impl NotObjectSafe {
if true {
return A;
}
B //~ ERROR mismatched types
}
fn cat() -> impl ObjectSafe {
if true {
return A;
}
B //~ ERROR mismatched types
}
fn main() {}

View file

@ -0,0 +1,39 @@
error[E0308]: mismatched types
--> $DIR/object-unsafe-trait-in-return-position-impl-trait.rs:36:5
|
LL | fn can() -> impl NotObjectSafe {
| ------------------ expected because this return type...
LL | if true {
LL | return A;
| - ...is found to be `A` here
LL | }
LL | B
| ^ expected struct `A`, found struct `B`
|
= note: to return `impl Trait`, all returned values must be of the same type
= note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
= help: if the trait `NotObjectSafe` were object safe, you could return a boxed trait object
= note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
= help: alternatively, create a new `enum` with a variant for each returned type
error[E0308]: mismatched types
--> $DIR/object-unsafe-trait-in-return-position-impl-trait.rs:43:5
|
LL | fn cat() -> impl ObjectSafe {
| --------------- expected because this return type...
LL | if true {
LL | return A;
| - ...is found to be `A` here
LL | }
LL | B
| ^ expected struct `A`, found struct `B`
|
= note: to return `impl Trait`, all returned values must be of the same type
= note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
= help: you can instead return a boxed trait object using `Box<dyn ObjectSafe>`
= note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
= help: alternatively, create a new `enum` with a variant for each returned type
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0308`.

View file

@ -3,6 +3,9 @@ error[E0277]: the trait bound `impl Trait<<u32 as std::ops::Add>::Output>: Trait
|
LL | ) -> Either<impl Trait<<u32 as Add<u32>>::Output>, impl Trait<<u32 as Add<u32>>::Output>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait<u32>` is not implemented for `impl Trait<<u32 as std::ops::Add>::Output>`
...
LL | add_generic(value, 1u32)
| ------------------------ this returned value is of type `Either<impl Trait<<u32 as std::ops::Add>::Output>, impl Trait<<u32 as std::ops::Add>::Output>>`
|
= note: the return type of a function must have a statically known size
@ -11,6 +14,9 @@ error[E0277]: the trait bound `impl Trait<<u32 as std::ops::Add>::Output>: Trait
|
LL | ) -> Either<impl Trait<<u32 as Add<u32>>::Output>, impl Trait<<u32 as Add<u32>>::Output>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait<u32>` is not implemented for `impl Trait<<u32 as std::ops::Add>::Output>`
...
LL | add_generic(value, 1u32)
| ------------------------ this returned value is of type `Either<impl Trait<<u32 as std::ops::Add>::Output>, impl Trait<<u32 as std::ops::Add>::Output>>`
|
= note: the return type of a function must have a statically known size

View file

@ -14,6 +14,9 @@ error[E0277]: the size for values of type `(dyn A + 'static)` cannot be known at
|
LL | -> Struct {
| ^^^^^^ doesn't have a size known at compile-time
LL |
LL | Struct { r: r }
| --------------- this returned value is of type `Struct`
|
= help: within `Struct`, the trait `std::marker::Sized` is not implemented for `(dyn A + 'static)`
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>

View file

@ -3,6 +3,9 @@ error[E0277]: the trait bound `std::result::Result<(), _>: Future` is not satisf
|
LL | fn foo() -> impl Future<Item=(), Error=Box<dyn Error>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Future` is not implemented for `std::result::Result<(), _>`
LL |
LL | Ok(())
| ------ this returned value is of type `std::result::Result<(), _>`
|
= note: the return type of a function must have a statically known size

View file

@ -3,8 +3,12 @@ error[E0277]: the trait bound `(): T` is not satisfied
|
LL | fn should_ret_unit() -> impl T {
| ^^^^^^ the trait `T` is not implemented for `()`
LL |
LL | panic!()
| -------- this returned value is of type `()`
|
= note: the return type of a function must have a statically known size
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
error: aborting due to previous error

View file

@ -9,6 +9,12 @@ LL | return 0i32;
LL | }
LL | 1u32
| ^^^^ expected `i32`, found `u32`
|
= note: to return `impl Trait`, all returned values must be of the same type
= note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
= help: you can instead return a boxed trait object using `Box<dyn std::fmt::Display>`
= note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
= help: alternatively, create a new `enum` with a variant for each returned type
error[E0308]: mismatched types
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:13:16
@ -21,6 +27,12 @@ LL | return 0i32;
LL | } else {
LL | return 1u32;
| ^^^^ expected `i32`, found `u32`
|
= note: to return `impl Trait`, all returned values must be of the same type
= note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
= help: you can instead return a boxed trait object using `Box<dyn std::fmt::Display>`
= note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
= help: alternatively, create a new `enum` with a variant for each returned type
error[E0308]: mismatched types
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:22:9
@ -33,6 +45,12 @@ LL | return 0i32;
LL | } else {
LL | 1u32
| ^^^^ expected `i32`, found `u32`
|
= note: to return `impl Trait`, all returned values must be of the same type
= note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
= help: you can instead return a boxed trait object using `Box<dyn std::fmt::Display>`
= note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
= help: alternatively, create a new `enum` with a variant for each returned type
error[E0308]: `if` and `else` have incompatible types
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:31:9
@ -57,6 +75,12 @@ LL | 0 => return 0i32,
| ---- ...is found to be `i32` here
LL | _ => 1u32,
| ^^^^ expected `i32`, found `u32`
|
= note: to return `impl Trait`, all returned values must be of the same type
= note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
= help: you can instead return a boxed trait object using `Box<dyn std::fmt::Display>`
= note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
= help: alternatively, create a new `enum` with a variant for each returned type
error[E0308]: mismatched types
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:45:5
@ -71,6 +95,12 @@ LL | | 1 => 1u32,
LL | | _ => 2u32,
LL | | }
| |_____^ expected `i32`, found `u32`
|
= note: to return `impl Trait`, all returned values must be of the same type
= note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
= help: you can instead return a boxed trait object using `Box<dyn std::fmt::Display>`
= note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
= help: alternatively, create a new `enum` with a variant for each returned type
error[E0308]: mismatched types
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:59:13
@ -83,6 +113,12 @@ LL | return 0i32;
...
LL | 1u32
| ^^^^ expected `i32`, found `u32`
|
= note: to return `impl Trait`, all returned values must be of the same type
= note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
= help: you can instead return a boxed trait object using `Box<dyn std::fmt::Display>`
= note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
= help: alternatively, create a new `enum` with a variant for each returned type
error: aborting due to 7 previous errors

View file

@ -18,6 +18,8 @@ LL | type Underconstrained<T: std::fmt::Debug> = impl 'static;
...
LL | fn underconstrained<U>(_: U) -> Underconstrained<U> {
| - help: consider restricting this bound: `U: std::fmt::Debug`
LL | 5u32
| ---- this returned value is of type `u32`
|
= help: the trait `std::fmt::Debug` is not implemented for `U`
= note: the return type of a function must have a statically known size
@ -30,6 +32,8 @@ LL | type Underconstrained2<T: std::fmt::Debug> = impl 'static;
...
LL | fn underconstrained2<U, V>(_: U, _: V) -> Underconstrained2<V> {
| - help: consider restricting this bound: `V: std::fmt::Debug`
LL | 5u32
| ---- this returned value is of type `u32`
|
= help: the trait `std::fmt::Debug` is not implemented for `V`
= note: the return type of a function must have a statically known size

View file

@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | fn ice(x: Box<dyn Iterator<Item=()>>) {
| - possibly return type missing here?
LL | *x
| ^^ expected `()`, found trait `std::iter::Iterator`
| ^^ expected `()`, found trait object `dyn std::iter::Iterator`
|
= note: expected unit type `()`
found trait object `(dyn std::iter::Iterator<Item = ()> + 'static)`