diff options
| author | Esteban Küber <esteban@kuber.com.ar> | 2020-02-18 16:35:47 -0800 |
|---|---|---|
| committer | Esteban Küber <esteban@kuber.com.ar> | 2020-02-28 11:37:59 -0800 |
| commit | 8119d0853d6f227c5e36ab423b6e2f22604fa87d (patch) | |
| tree | 18d6127a160b0e44ed86f433f54bc488ad3eeb22 | |
| parent | ad4777dbca1d4d1b052db01b1191862c9fbbad64 (diff) | |
Track all predicates in errors, not just trait obligations
Surface associated type projection bounds that could not be fulfilled in E0599 errors. Always present the list of unfulfilled trait bounds, regardless of whether we're pointing at the ADT or trait that didn't satisfy it.
19 files changed, 134 insertions, 103 deletions
diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index b05bd26f048..77c612cf34a 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -581,6 +581,20 @@ impl<'tcx, N> Vtable<'tcx, N> { } } + pub fn borrow_nested_obligations(&self) -> &[N] { + match &self { + VtableImpl(i) => &i.nested[..], + VtableParam(n) => &n[..], + VtableBuiltin(i) => &i.nested[..], + VtableAutoImpl(d) => &d.nested[..], + VtableClosure(c) => &c.nested[..], + VtableGenerator(c) => &c.nested[..], + VtableObject(d) => &d.nested[..], + VtableFnPointer(d) => &d.nested[..], + VtableTraitAlias(d) => &d.nested[..], + } + } + pub fn map<M, F>(self, f: F) -> Vtable<'tcx, M> where F: FnMut(N) -> M, diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index de824648a25..fd85397760a 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -14,7 +14,7 @@ use crate::check::FnCtxt; use rustc::ty::subst::Subst; use rustc::ty::subst::{InternalSubsts, SubstsRef}; use rustc::ty::GenericParamDefKind; -use rustc::ty::{self, ToPolyTraitRef, ToPredicate, TraitRef, Ty, TypeFoldable, WithConstness}; +use rustc::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TypeFoldable, WithConstness}; use rustc_data_structures::sync::Lrc; use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_hir as hir; @@ -67,7 +67,7 @@ pub enum MethodError<'tcx> { // could lead to matches if satisfied, and a list of not-in-scope traits which may work. pub struct NoMatchData<'tcx> { pub static_candidates: Vec<CandidateSource>, - pub unsatisfied_predicates: Vec<TraitRef<'tcx>>, + pub unsatisfied_predicates: Vec<ty::Predicate<'tcx>>, pub out_of_scope_traits: Vec<DefId>, pub lev_candidate: Option<ty::AssocItem>, pub mode: probe::Mode, @@ -76,7 +76,7 @@ pub struct NoMatchData<'tcx> { impl<'tcx> NoMatchData<'tcx> { pub fn new( static_candidates: Vec<CandidateSource>, - unsatisfied_predicates: Vec<TraitRef<'tcx>>, + unsatisfied_predicates: Vec<ty::Predicate<'tcx>>, out_of_scope_traits: Vec<DefId>, lev_candidate: Option<ty::AssocItem>, mode: probe::Mode, diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 1bf173e3b13..4f729c593cb 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -14,8 +14,7 @@ use rustc::session::config::nightly_options; use rustc::ty::subst::{InternalSubsts, Subst, SubstsRef}; use rustc::ty::GenericParamDefKind; use rustc::ty::{ - self, ParamEnvAnd, ToPolyTraitRef, ToPredicate, TraitRef, Ty, TyCtxt, TypeFoldable, - WithConstness, + self, ParamEnvAnd, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness, }; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sync::Lrc; @@ -78,7 +77,7 @@ struct ProbeContext<'a, 'tcx> { /// Collects near misses when trait bounds for type parameters are unsatisfied and is only used /// for error reporting - unsatisfied_predicates: Vec<TraitRef<'tcx>>, + unsatisfied_predicates: Vec<ty::Predicate<'tcx>>, is_suggestion: IsSuggestion, } @@ -1224,7 +1223,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { &self, self_ty: Ty<'tcx>, probes: ProbesIter, - possibly_unsatisfied_predicates: &mut Vec<TraitRef<'tcx>>, + possibly_unsatisfied_predicates: &mut Vec<ty::Predicate<'tcx>>, unstable_candidates: Option<&mut Vec<(&'b Candidate<'tcx>, Symbol)>>, ) -> Option<PickResult<'tcx>> where @@ -1343,7 +1342,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { &self, self_ty: Ty<'tcx>, probe: &Candidate<'tcx>, - possibly_unsatisfied_predicates: &mut Vec<TraitRef<'tcx>>, + possibly_unsatisfied_predicates: &mut Vec<ty::Predicate<'tcx>>, ) -> ProbeResult { debug!("consider_probe: self_ty={:?} probe={:?}", self_ty, probe); @@ -1398,47 +1397,40 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let predicate = trait_ref.without_const().to_predicate(); let obligation = traits::Obligation::new(cause, self.param_env, predicate); if !self.predicate_may_hold(&obligation) { - if self.probe(|_| self.select_trait_candidate(trait_ref).is_err()) { + if self.probe(|_| { + match self.select_trait_candidate(trait_ref) { + Err(_) => return true, + Ok(Some(vtable)) + if !vtable.borrow_nested_obligations().is_empty() => + { + for obligation in vtable.borrow_nested_obligations() { + // Determine exactly which obligation wasn't met, so + // that we can give more context in the error. + if !self.predicate_may_hold(&obligation) { + result = ProbeResult::NoMatch; + let o = self.resolve_vars_if_possible(obligation); + possibly_unsatisfied_predicates.push(o.predicate); + } + } + } + _ => { + // Some nested subobligation of this predicate + // failed. + // + // FIXME: try to find the exact nested subobligation + // and point at it rather than reporting the entire + // trait-ref? + result = ProbeResult::NoMatch; + let predicate = self.resolve_vars_if_possible(&predicate); + possibly_unsatisfied_predicates.push(predicate); + } + } + false + }) { // This candidate's primary obligation doesn't even // select - don't bother registering anything in // `potentially_unsatisfied_predicates`. return ProbeResult::NoMatch; - } else { - self.probe(|_| { - match self.select_trait_candidate(trait_ref) { - Ok(Some(traits::VtableImpl(traits::VtableImplData { - nested, - .. - }))) if !nested.is_empty() => { - for obligation in nested { - // Determine exactly which obligation wasn't met, so - // that we can give more context in the error. - if !self.predicate_may_hold(&obligation) { - result = ProbeResult::NoMatch; - if let Some(poly_trait_ref) = - obligation.predicate.to_opt_poly_trait_ref() - { - let trait_ref = poly_trait_ref.clone(); - let trait_ref = trait_ref.skip_binder(); - possibly_unsatisfied_predicates - .push(*trait_ref); - } - } - } - } - _ => { - // Some nested subobligation of this predicate - // failed. - // - // FIXME: try to find the exact nested subobligation - // and point at it rather than reporting the entire - // trait-ref? - result = ProbeResult::NoMatch; - let trait_ref = self.resolve_vars_if_possible(&trait_ref); - possibly_unsatisfied_predicates.push(trait_ref); - } - } - }); } } vec![] @@ -1455,9 +1447,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let o = self.resolve_vars_if_possible(&o); if !self.predicate_may_hold(&o) { result = ProbeResult::NoMatch; - if let &ty::Predicate::Trait(ref pred, _) = &o.predicate { - possibly_unsatisfied_predicates.push(pred.skip_binder().trait_ref); - } + possibly_unsatisfied_predicates.push(o.predicate); } } diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 8eb42f01984..6edceeb15b3 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -535,57 +535,56 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } if !unsatisfied_predicates.is_empty() { + let def_span = + |def_id| self.tcx.sess.source_map().def_span(self.tcx.def_span(def_id)); let mut bound_spans = vec![]; let mut bound_list = unsatisfied_predicates .iter() - .filter_map(|p| { - let self_ty = p.self_ty(); - match &self_ty.kind { - ty::Adt(def, _) => { - bound_spans.push(( - self.tcx - .sess - .source_map() - .def_span(self.tcx.def_span(def.did)), - format!( - "the method `{}` exists but this type doesn't satisfy \ - the bound `{}: {}`", - item_name, - p.self_ty(), - p.print_only_trait_path() - ), - )); - None - } - ty::Dynamic(preds, _) => { - for pred in *preds.skip_binder() { - match pred { - ty::ExistentialPredicate::Trait(tr) => bound_spans - .push(( - self.tcx - .sess - .source_map() - .def_span(self.tcx.def_span(tr.def_id)), - format!( - "the method `{}` exists but this trait \ - doesn't satisfy the bound `{}: {}`", - item_name, - p.self_ty(), - p.print_only_trait_path() - ), - )), - ty::ExistentialPredicate::Projection(_) - | ty::ExistentialPredicate::AutoTrait(_) => {} + .filter_map(|pred| match pred { + ty::Predicate::Projection(pred) => { + // `<Foo as Iterator>::Item = String`. + let trait_ref = + pred.skip_binder().projection_ty.trait_ref(self.tcx); + let assoc = self + .tcx + .associated_item(pred.skip_binder().projection_ty.item_def_id); + let ty = pred.skip_binder().ty; + Some(format!("`{}::{} = {}`", trait_ref, assoc.ident, ty)) + } + ty::Predicate::Trait(poly_trait_ref, _) => { + let p = poly_trait_ref.skip_binder().trait_ref; + let self_ty = p.self_ty(); + let path = p.print_only_trait_path(); + match &self_ty.kind { + ty::Adt(def, _) => { + // Point at the type that couldn't satisfy the bound. + bound_spans.push(( + def_span(def.did), + format!("doesn't satisfy `{}: {}`", self_ty, path), + )); + } + ty::Dynamic(preds, _) => { + // Point at the trait object that couldn't satisfy the bound. + for pred in *preds.skip_binder() { + match pred { + ty::ExistentialPredicate::Trait(tr) => bound_spans + .push(( + def_span(tr.def_id), + format!( + "doesn't satisfy `{}: {}`", + self_ty, path + ), + )), + ty::ExistentialPredicate::Projection(_) + | ty::ExistentialPredicate::AutoTrait(_) => {} + } } } - None + _ => {} } - _ => Some(format!( - "`{}: {}`", - p.self_ty(), - p.print_only_trait_path() - )), + Some(format!("`{}: {}`", self_ty, path)) } + _ => None, }) .collect::<Vec<_>>(); bound_list.sort(); diff --git a/src/test/ui/derives/derive-assoc-type-not-impl.stderr b/src/test/ui/derives/derive-assoc-type-not-impl.stderr index fd74d992299..3ed726dea35 100644 --- a/src/test/ui/derives/derive-assoc-type-not-impl.stderr +++ b/src/test/ui/derives/derive-assoc-type-not-impl.stderr @@ -5,11 +5,13 @@ LL | struct Bar<T: Foo> { | ------------------ method `clone` not found for this ... LL | struct NotClone; - | ---------------- the method `clone` exists but this type doesn't satisfy the bound `NotClone: std::clone::Clone` + | ---------------- doesn't satisfy `NotClone: std::clone::Clone` ... LL | Bar::<NotClone> { x: 1 }.clone(); | ^^^^^ method not found in `Bar<NotClone>` | + = note: the method `clone` exists but the following trait bounds were not satisfied: + `NotClone: std::clone::Clone` = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `std::clone::Clone` diff --git a/src/test/ui/issues/issue-31173.stderr b/src/test/ui/issues/issue-31173.stderr index 4a5940f610e..d5e3cf48f38 100644 --- a/src/test/ui/issues/issue-31173.stderr +++ b/src/test/ui/issues/issue-31173.stderr @@ -16,7 +16,11 @@ LL | .collect(); ::: $SRC_DIR/libcore/iter/adapters/mod.rs:LL:COL | LL | pub struct Cloned<I> { - | -------------------- the method `collect` exists but this type doesn't satisfy the bound `std::iter::Cloned<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>: std::iter::Iterator` + | -------------------- doesn't satisfy `std::iter::Cloned<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>: std::iter::Iterator` + | + = note: the method `collect` exists but the following trait bounds were not satisfied: + `<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]> as std::iter::Iterator>::Item = &_` + `std::iter::Cloned<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>: std::iter::Iterator` error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr index c6d9a8415dd..63359be56bf 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr @@ -5,6 +5,7 @@ LL | let _result = &Some(42).as_deref(); | ^^^^^^^^ help: there is a method with a similar name: `as_ref` | = note: the method `as_deref` exists but the following trait bounds were not satisfied: + `<{integer} as std::ops::Deref>::Target = _` `{integer}: std::ops::Deref` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr index ae51052a22c..b01b3448e17 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr @@ -5,6 +5,7 @@ LL | let _result = &mut Some(42).as_deref_mut(); | ^^^^^^^^^^^^ method not found in `std::option::Option<{integer}>` | = note: the method `as_deref_mut` exists but the following trait bounds were not satisfied: + `<{integer} as std::ops::Deref>::Target = _` `{integer}: std::ops::DerefMut` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr index 3f7904a8521..75482841987 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr @@ -5,6 +5,7 @@ LL | let _result = &Ok(42).as_deref(); | ^^^^^^^^ help: there is a method with a similar name: `as_ref` | = note: the method `as_deref` exists but the following trait bounds were not satisfied: + `<{integer} as std::ops::Deref>::Target = _` `{integer}: std::ops::Deref` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr index eb591b419ea..cf31bc4b56b 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr @@ -5,6 +5,7 @@ LL | let _result = &Err(41).as_deref_err(); | ^^^^^^^^^^^^ help: there is a method with a similar name: `as_deref_mut` | = note: the method `as_deref_err` exists but the following trait bounds were not satisfied: + `<{integer} as std::ops::Deref>::Target = _` `{integer}: std::ops::Deref` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr index 115518dcf67..586b3555455 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr @@ -5,6 +5,7 @@ LL | let _result = &mut Ok(42).as_deref_mut(); | ^^^^^^^^^^^^ help: there is a method with a similar name: `as_deref_err` | = note: the method `as_deref_mut` exists but the following trait bounds were not satisfied: + `<{integer} as std::ops::Deref>::Target = _` `{integer}: std::ops::DerefMut` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr index 49f4a16d8ae..fd0e43d7dbc 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr @@ -5,6 +5,7 @@ LL | let _result = &mut Err(41).as_deref_mut_err(); | ^^^^^^^^^^^^^^^^ help: there is a method with a similar name: `as_deref_mut` | = note: the method `as_deref_mut_err` exists but the following trait bounds were not satisfied: + `<{integer} as std::ops::Deref>::Target = _` `{integer}: std::ops::DerefMut` error: aborting due to previous error diff --git a/src/test/ui/methods/method-call-err-msg.stderr b/src/test/ui/methods/method-call-err-msg.stderr index aa38e4da018..b0d747d201d 100644 --- a/src/test/ui/methods/method-call-err-msg.stderr +++ b/src/test/ui/methods/method-call-err-msg.stderr @@ -38,11 +38,13 @@ LL | pub struct Foo; | --------------- | | | method `take` not found for this - | the method `take` exists but this type doesn't satisfy the bound `Foo: std::iter::Iterator` + | doesn't satisfy `Foo: std::iter::Iterator` ... LL | .take() | ^^^^ method not found in `Foo` | + = note: the method `take` exists but the following trait bounds were not satisfied: + `Foo: std::iter::Iterator` = help: items from traits can only be used if the trait is implemented and in scope = note: the following traits define an item `take`, perhaps you need to implement one of them: candidate #1: `std::io::Read` diff --git a/src/test/ui/mismatched_types/issue-36053-2.stderr b/src/test/ui/mismatched_types/issue-36053-2.stderr index dc0bd310de8..5f3353c89cc 100644 --- a/src/test/ui/mismatched_types/issue-36053-2.stderr +++ b/src/test/ui/mismatched_types/issue-36053-2.stderr @@ -7,10 +7,12 @@ LL | once::<&str>("str").fuse().filter(|a: &str| true).count(); ::: $SRC_DIR/libcore/iter/adapters/mod.rs:LL:COL | LL | pub struct Filter<I, P> { - | ----------------------- the method `count` exists but this type doesn't satisfy the bound `std::iter::Filter<std::iter::Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator` + | ----------------------- doesn't satisfy `std::iter::Filter<std::iter::Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator` | = note: the method `count` exists but the following trait bounds were not satisfied: - `[closure@$DIR/issue-36053-2.rs:11:39: 11:53]: std::ops::FnMut<(&_,)>` + `<[closure@$DIR/issue-36053-2.rs:11:39: 11:53] as std::ops::FnOnce<(&&str,)>>::Output = bool` + `[closure@$DIR/issue-36053-2.rs:11:39: 11:53]: std::ops::FnMut<(&&str,)>` + `std::iter::Filter<std::iter::Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator` error[E0631]: type mismatch in closure arguments --> $DIR/issue-36053-2.rs:11:32 diff --git a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr index e95141b393a..5ab191b9270 100644 --- a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr +++ b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr @@ -2,10 +2,13 @@ error[E0599]: no method named `unwrap` found for enum `std::result::Result<(), F --> $DIR/method-help-unsatisfied-bound.rs:5:7 | LL | struct Foo; - | ----------- the method `unwrap` exists but this type doesn't satisfy the bound `Foo: std::fmt::Debug` + | ----------- doesn't satisfy `Foo: std::fmt::Debug` ... LL | a.unwrap(); | ^^^^^^ method not found in `std::result::Result<(), Foo>` + | + = note: the method `unwrap` exists but the following trait bounds were not satisfied: + `Foo: std::fmt::Debug` error: aborting due to previous error diff --git a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr index 2738bac8cc8..14f37150c80 100644 --- a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr +++ b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr @@ -8,11 +8,13 @@ LL | struct MyStruct; | ---------------- | | | method `foo_one` not found for this - | the method `foo_one` exists but this type doesn't satisfy the bound `MyStruct: Foo` + | doesn't satisfy `MyStruct: Foo` ... LL | println!("{}", MyStruct.foo_one()); | ^^^^^^^ method not found in `MyStruct` | + = note: the method `foo_one` exists but the following trait bounds were not satisfied: + `MyStruct: Foo` = help: items from traits can only be used if the trait is implemented and in scope error: aborting due to previous error diff --git a/src/test/ui/union/union-derive-clone.stderr b/src/test/ui/union/union-derive-clone.stderr index c0d99c56cc0..2051ea33391 100644 --- a/src/test/ui/union/union-derive-clone.stderr +++ b/src/test/ui/union/union-derive-clone.stderr @@ -14,11 +14,13 @@ LL | union U5<T> { | ----------- method `clone` not found for this ... LL | struct CloneNoCopy; - | ------------------- the method `clone` exists but this type doesn't satisfy the bound `CloneNoCopy: std::marker::Copy` + | ------------------- doesn't satisfy `CloneNoCopy: std::marker::Copy` ... LL | let w = u.clone(); | ^^^^^ method not found in `U5<CloneNoCopy>` | + = note: the method `clone` exists but the following trait bounds were not satisfied: + `CloneNoCopy: std::marker::Copy` = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `std::clone::Clone` diff --git a/src/test/ui/unique-object-noncopyable.stderr b/src/test/ui/unique-object-noncopyable.stderr index b786a3d6d86..f230d0d14d2 100644 --- a/src/test/ui/unique-object-noncopyable.stderr +++ b/src/test/ui/unique-object-noncopyable.stderr @@ -4,12 +4,15 @@ error[E0599]: no method named `clone` found for struct `std::boxed::Box<dyn Foo> LL | trait Foo { | --------- | | - | the method `clone` exists but this trait doesn't satisfy the bound `dyn Foo: std::clone::Clone` - | the method `clone` exists but this trait doesn't satisfy the bound `dyn Foo: std::marker::Sized` + | doesn't satisfy `dyn Foo: std::clone::Clone` + | doesn't satisfy `dyn Foo: std::marker::Sized` ... LL | let _z = y.clone(); | ^^^^^ method not found in `std::boxed::Box<dyn Foo>` | + = note: the method `clone` exists but the following trait bounds were not satisfied: + `dyn Foo: std::clone::Clone` + `dyn Foo: std::marker::Sized` = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `std::clone::Clone` diff --git a/src/test/ui/unique-pinned-nocopy.stderr b/src/test/ui/unique-pinned-nocopy.stderr index 26b82ecda48..12d719a1027 100644 --- a/src/test/ui/unique-pinned-nocopy.stderr +++ b/src/test/ui/unique-pinned-nocopy.stderr @@ -2,11 +2,13 @@ error[E0599]: no method named `clone` found for struct `std::boxed::Box<R>` in t --> $DIR/unique-pinned-nocopy.rs:12:16 | LL | struct R { - | -------- the method `clone` exists but this type doesn't satisfy the bound `R: std::clone::Clone` + | -------- doesn't satisfy `R: std::clone::Clone` ... LL | let _j = i.clone(); | ^^^^^ method not found in `std::boxed::Box<R>` | + = note: the method `clone` exists but the following trait bounds were not satisfied: + `R: std::clone::Clone` = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `std::clone::Clone` |
