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:
commit
de01a29fbe
38 changed files with 4067 additions and 3027 deletions
File diff suppressed because it is too large
Load diff
1412
src/librustc/traits/error_reporting/mod.rs
Normal file
1412
src/librustc/traits/error_reporting/mod.rs
Normal file
File diff suppressed because it is too large
Load diff
199
src/librustc/traits/error_reporting/on_unimplemented.rs
Normal file
199
src/librustc/traits/error_reporting/on_unimplemented.rs
Normal 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()
|
||||
}
|
||||
}
|
||||
}
|
||||
1718
src/librustc/traits/error_reporting/suggestions.rs
Normal file
1718
src/librustc/traits/error_reporting/suggestions.rs
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
138
src/librustc_error_codes/error_codes/E0746.md
Normal file
138
src/librustc_error_codes/error_codes/E0746.md
Normal 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
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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]>`
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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`
|
||||
|
|
|
|||
|
|
@ -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<_>`
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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`
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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`
|
||||
|
|
|
|||
18
src/test/ui/error-codes/E0746.fixed
Normal file
18
src/test/ui/error-codes/E0746.fixed
Normal 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() {}
|
||||
18
src/test/ui/error-codes/E0746.rs
Normal file
18
src/test/ui/error-codes/E0746.rs
Normal 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() {}
|
||||
27
src/test/ui/error-codes/E0746.stderr
Normal file
27
src/test/ui/error-codes/E0746.stderr
Normal 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`.
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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() {}
|
||||
|
|
@ -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`.
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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() {}
|
||||
|
|
@ -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`.
|
||||
|
|
@ -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() {}
|
||||
|
|
@ -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`.
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)`
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue