From 5fd37862d95a7fd898342e49ae5273edc8886b83 Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Wed, 13 Oct 2021 13:58:41 +0000 Subject: [PATCH] Properly track `ImplObligation`s Instead of probing for all possible impls that could have caused an `ImplObligation`, keep track of its `DefId` and obligation spans for accurate error reporting. Follow up to #89580. Addresses #89418. Remove some unnecessary clones. Tweak output for auto trait impl obligations. --- .../mismatched_static_lifetime.rs | 2 +- compiler/rustc_middle/src/traits/mod.rs | 27 ++- .../src/traits/error_reporting/suggestions.rs | 121 ++++++---- .../src/traits/select/confirmation.rs | 75 +++--- .../src/traits/select/mod.rs | 37 +-- .../rustc_typeck/src/check/compare_method.rs | 10 +- .../rustc_typeck/src/check/fn_ctxt/checks.rs | 8 +- .../rustc_typeck/src/check/method/probe.rs | 5 +- .../rustc_typeck/src/check/method/suggest.rs | 217 ++++++++++++------ compiler/rustc_typeck/src/lib.rs | 1 + .../derives/derive-assoc-type-not-impl.stderr | 9 +- .../method-unsatified-assoc-type-predicate.rs | 5 +- ...hod-unsatified-assoc-type-predicate.stderr | 11 +- src/test/ui/hrtb/issue-30786.migrate.stderr | 16 +- src/test/ui/hrtb/issue-30786.nll.stderr | 16 +- ...issing-trait-bounds-for-method-call.stderr | 29 ++- .../const-drop-fail.precise.stderr | 6 + .../const-drop-fail.stock.stderr | 6 + ...pecialization-trait-not-implemented.stderr | 3 +- src/test/ui/traits/alias/cross-crate.stderr | 2 + .../supertrait-auto-trait.stderr | 6 +- .../union-derive-clone.mirunsafeck.stderr | 5 + .../union-derive-clone.thirunsafeck.stderr | 5 + .../ui/wf/hir-wf-check-erase-regions.stderr | 12 +- 24 files changed, 421 insertions(+), 213 deletions(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs index 467054e318be5..61e3334862bc0 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs @@ -31,7 +31,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { // about the original obligation only. let code = match cause.code() { ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } => &*parent_code, - _ => cause.code(), + code => code, }; let ObligationCauseCode::MatchImpl(parent, impl_def_id) = code else { return None; diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 36bbccf0a8038..3ed7836074b25 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -257,7 +257,7 @@ pub enum ObligationCauseCode<'tcx> { BuiltinDerivedObligation(DerivedObligationCause<'tcx>), - ImplDerivedObligation(DerivedObligationCause<'tcx>), + ImplDerivedObligation(Box>), DerivedObligation(DerivedObligationCause<'tcx>), @@ -396,16 +396,29 @@ pub enum WellFormedLoc { }, } +#[derive(Clone, Debug, PartialEq, Eq, Hash, Lift)] +pub struct ImplDerivedObligationCause<'tcx> { + pub derived: DerivedObligationCause<'tcx>, + pub impl_def_id: DefId, + pub span: Span, +} + impl ObligationCauseCode<'_> { // Return the base obligation, ignoring derived obligations. pub fn peel_derives(&self) -> &Self { let mut base_cause = self; - while let BuiltinDerivedObligation(DerivedObligationCause { parent_code, .. }) - | ImplDerivedObligation(DerivedObligationCause { parent_code, .. }) - | DerivedObligation(DerivedObligationCause { parent_code, .. }) - | FunctionArgumentObligation { parent_code, .. } = base_cause - { - base_cause = &parent_code; + loop { + match base_cause { + BuiltinDerivedObligation(DerivedObligationCause { parent_code, .. }) + | DerivedObligation(DerivedObligationCause { parent_code, .. }) + | FunctionArgumentObligation { parent_code, .. } => { + base_cause = &parent_code; + } + ImplDerivedObligation(obligation_cause) => { + base_cause = &*obligation_cause.derived.parent_code; + } + _ => break, + } } base_cause } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index b617067e66ddd..d65b390af3460 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -507,8 +507,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { let body_id = obligation.cause.body_id; let span = obligation.cause.span; let real_trait_pred = match &*code { - ObligationCauseCode::ImplDerivedObligation(cause) - | ObligationCauseCode::DerivedObligation(cause) + ObligationCauseCode::ImplDerivedObligation(cause) => cause.derived.parent_trait_pred, + ObligationCauseCode::DerivedObligation(cause) | ObligationCauseCode::BuiltinDerivedObligation(cause) => cause.parent_trait_pred, _ => trait_pred, }; @@ -790,8 +790,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { return false; }; - if let ObligationCauseCode::ImplDerivedObligation(obligation) = code { - try_borrowing(obligation.parent_trait_pred, &[]) + if let ObligationCauseCode::ImplDerivedObligation(cause) = &*code { + try_borrowing(cause.derived.parent_trait_pred, &[]) } else if let ObligationCauseCode::BindingObligation(_, _) | ObligationCauseCode::ItemObligation(_) = code { @@ -1433,13 +1433,43 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } => { next_code = Some(parent_code.as_ref()); } + ObligationCauseCode::ImplDerivedObligation(cause) => { + let ty = cause.derived.parent_trait_pred.skip_binder().self_ty(); + debug!( + "maybe_note_obligation_cause_for_async_await: ImplDerived \ + parent_trait_ref={:?} self_ty.kind={:?}", + cause.derived.parent_trait_pred, + ty.kind() + ); + + match *ty.kind() { + ty::Generator(did, ..) => { + generator = generator.or(Some(did)); + outer_generator = Some(did); + } + ty::GeneratorWitness(..) => {} + ty::Tuple(_) if !seen_upvar_tys_infer_tuple => { + // By introducing a tuple of upvar types into the chain of obligations + // of a generator, the first non-generator item is now the tuple itself, + // we shall ignore this. + + seen_upvar_tys_infer_tuple = true; + } + _ if generator.is_none() => { + trait_ref = Some(cause.derived.parent_trait_pred.skip_binder()); + target_ty = Some(ty); + } + _ => {} + } + + next_code = Some(cause.derived.parent_code.as_ref()); + } ObligationCauseCode::DerivedObligation(derived_obligation) - | ObligationCauseCode::BuiltinDerivedObligation(derived_obligation) - | ObligationCauseCode::ImplDerivedObligation(derived_obligation) => { + | ObligationCauseCode::BuiltinDerivedObligation(derived_obligation) => { let ty = derived_obligation.parent_trait_pred.skip_binder().self_ty(); debug!( "maybe_note_obligation_cause_for_async_await: \ - parent_trait_ref={:?} self_ty.kind={:?}", + parent_trait_ref={:?} self_ty.kind={:?}", derived_obligation.parent_trait_pred, ty.kind() ); @@ -2166,7 +2196,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { } } ObligationCauseCode::ImplDerivedObligation(ref data) => { - let mut parent_trait_pred = self.resolve_vars_if_possible(data.parent_trait_pred); + let mut parent_trait_pred = + self.resolve_vars_if_possible(data.derived.parent_trait_pred); parent_trait_pred.remap_constness_diag(param_env); let parent_def_id = parent_trait_pred.def_id(); let msg = format!( @@ -2174,51 +2205,63 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { parent_trait_pred.print_modifiers_and_trait_path(), parent_trait_pred.skip_binder().self_ty() ); - let mut candidates = vec![]; - self.tcx.for_each_relevant_impl( - parent_def_id, - parent_trait_pred.self_ty().skip_binder(), - |impl_def_id| match self.tcx.hir().get_if_local(impl_def_id) { - Some(Node::Item(hir::Item { - kind: hir::ItemKind::Impl(hir::Impl { .. }), - .. - })) => { - candidates.push(impl_def_id); - } - _ => {} - }, - ); - match &candidates[..] { - [def_id] => match self.tcx.hir().get_if_local(*def_id) { - Some(Node::Item(hir::Item { - kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, .. }), - .. - })) => { - let mut spans = Vec::with_capacity(2); - if let Some(trait_ref) = of_trait { - spans.push(trait_ref.path.span); - } - spans.push(self_ty.span); - err.span_note(spans, &msg) + let mut is_auto_trait = false; + match self.tcx.hir().get_if_local(data.impl_def_id) { + Some(Node::Item(hir::Item { + kind: hir::ItemKind::Trait(is_auto, ..), + ident, + .. + })) => { + // FIXME: we should do something else so that it works even on crate foreign + // auto traits. + is_auto_trait = matches!(is_auto, hir::IsAuto::Yes); + err.span_note(ident.span, &msg) + } + Some(Node::Item(hir::Item { + kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, .. }), + .. + })) => { + let mut spans = Vec::with_capacity(2); + if let Some(trait_ref) = of_trait { + spans.push(trait_ref.path.span); } - _ => err.note(&msg), - }, + spans.push(self_ty.span); + err.span_note(spans, &msg) + } _ => err.note(&msg), }; let mut parent_predicate = parent_trait_pred.to_predicate(tcx); - let mut data = data; + let mut data = &data.derived; let mut count = 0; seen_requirements.insert(parent_def_id); + if is_auto_trait { + // We don't want to point at the ADT saying "required because it appears within + // the type `X`", like we would otherwise do in test `supertrait-auto-trait.rs`. + while let ObligationCauseCode::BuiltinDerivedObligation(derived) = + &*data.parent_code + { + let child_trait_ref = + self.resolve_vars_if_possible(derived.parent_trait_pred); + let child_def_id = child_trait_ref.def_id(); + if seen_requirements.insert(child_def_id) { + break; + } + data = derived; + parent_predicate = child_trait_ref.to_predicate(tcx); + parent_trait_pred = child_trait_ref; + } + } while let ObligationCauseCode::ImplDerivedObligation(child) = &*data.parent_code { // Skip redundant recursive obligation notes. See `ui/issue-20413.rs`. - let child_trait_pred = self.resolve_vars_if_possible(child.parent_trait_pred); + let child_trait_pred = + self.resolve_vars_if_possible(child.derived.parent_trait_pred); let child_def_id = child_trait_pred.def_id(); if seen_requirements.insert(child_def_id) { break; } count += 1; - data = child; + data = &child.derived; parent_predicate = child_trait_pred.to_predicate(tcx); parent_trait_pred = child_trait_pred; } diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index df760a166e82c..9c871eea1cdda 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -18,24 +18,17 @@ use rustc_span::def_id::DefId; use crate::traits::project::{normalize_with_depth, normalize_with_depth_to}; use crate::traits::select::TraitObligationExt; -use crate::traits::util; -use crate::traits::util::{closure_trait_ref_and_return_type, predicate_for_trait_def}; -use crate::traits::ImplSource; -use crate::traits::Normalized; -use crate::traits::OutputTypeParameterMismatch; -use crate::traits::Selection; -use crate::traits::TraitNotObjectSafe; -use crate::traits::VtblSegment; -use crate::traits::{BuiltinDerivedObligation, ImplDerivedObligation}; +use crate::traits::util::{self, closure_trait_ref_and_return_type, predicate_for_trait_def}; use crate::traits::{ - ImplSourceAutoImplData, ImplSourceBuiltinData, ImplSourceClosureData, - ImplSourceConstDestructData, ImplSourceDiscriminantKindData, ImplSourceFnPointerData, - ImplSourceGeneratorData, ImplSourceObjectData, ImplSourcePointeeData, ImplSourceTraitAliasData, - ImplSourceTraitUpcastingData, ImplSourceUserDefinedData, + BuiltinDerivedObligation, DerivedObligationCause, ImplDerivedObligation, + ImplDerivedObligationCause, ImplSource, ImplSourceAutoImplData, ImplSourceBuiltinData, + ImplSourceClosureData, ImplSourceConstDestructData, ImplSourceDiscriminantKindData, + ImplSourceFnPointerData, ImplSourceGeneratorData, ImplSourceObjectData, ImplSourcePointeeData, + ImplSourceTraitAliasData, ImplSourceTraitUpcastingData, ImplSourceUserDefinedData, Normalized, + ObjectCastObligation, Obligation, ObligationCause, OutputTypeParameterMismatch, + PredicateObligation, Selection, SelectionError, TraitNotObjectSafe, TraitObligation, + Unimplemented, VtblSegment, }; -use crate::traits::{ObjectCastObligation, PredicateObligation, TraitObligation}; -use crate::traits::{Obligation, ObligationCause}; -use crate::traits::{SelectionError, Unimplemented}; use super::BuiltinImplConditions; use super::SelectionCandidate::{self, *}; @@ -321,28 +314,29 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { debug!(?nested, "vtable_auto_impl"); ensure_sufficient_stack(|| { let cause = obligation.derived_cause(BuiltinDerivedObligation); - let mut obligations = self.collect_predicates_for_types( - obligation.param_env, - cause, - obligation.recursion_depth + 1, - trait_def_id, - nested, - ); let trait_obligations: Vec> = self.infcx.commit_unconditionally(|_| { let poly_trait_ref = obligation.predicate.to_poly_trait_ref(); let trait_ref = self.infcx.replace_bound_vars_with_placeholders(poly_trait_ref); - let cause = obligation.derived_cause(ImplDerivedObligation); self.impl_or_trait_obligations( - cause, + &cause, obligation.recursion_depth + 1, obligation.param_env, trait_def_id, &trait_ref.substs, + obligation.predicate, ) }); + let mut obligations = self.collect_predicates_for_types( + obligation.param_env, + cause, + obligation.recursion_depth + 1, + trait_def_id, + nested, + ); + // Adds the predicates from the trait. Note that this contains a `Self: Trait` // predicate as usual. It won't have any effect since auto traits are coinductive. obligations.extend(trait_obligations); @@ -365,14 +359,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.infcx.commit_unconditionally(|_| { let substs = self.rematch_impl(impl_def_id, obligation); debug!(?substs, "impl substs"); - let cause = obligation.derived_cause(ImplDerivedObligation); ensure_sufficient_stack(|| { self.vtable_impl( impl_def_id, substs, - cause, + &obligation.cause, obligation.recursion_depth + 1, obligation.param_env, + obligation.predicate, ) }) }) @@ -382,9 +376,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, impl_def_id: DefId, substs: Normalized<'tcx, SubstsRef<'tcx>>, - cause: ObligationCause<'tcx>, + cause: &ObligationCause<'tcx>, recursion_depth: usize, param_env: ty::ParamEnv<'tcx>, + parent_trait_pred: ty::Binder<'tcx, ty::TraitPredicate<'tcx>>, ) -> ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>> { debug!(?impl_def_id, ?substs, ?recursion_depth, "vtable_impl"); @@ -394,6 +389,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { param_env, impl_def_id, &substs.value, + parent_trait_pred, ); debug!(?impl_obligations, "vtable_impl"); @@ -566,11 +562,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let substs = trait_ref.substs; let trait_obligations = self.impl_or_trait_obligations( - obligation.cause.clone(), + &obligation.cause, obligation.recursion_depth, obligation.param_env, trait_def_id, &substs, + obligation.predicate, ); debug!(?trait_def_id, ?trait_obligations, "trait alias obligations"); @@ -1073,14 +1070,30 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { }); let substs = self.rematch_impl(impl_def_id, &new_obligation); debug!(?substs, "impl substs"); - let cause = obligation.derived_cause(ImplDerivedObligation); + + let derived = DerivedObligationCause { + parent_trait_pred: obligation.predicate, + parent_code: obligation.cause.clone_code(), + }; + let derived_code = ImplDerivedObligation(Box::new(ImplDerivedObligationCause { + derived, + impl_def_id, + span: obligation.cause.span, + })); + + let cause = ObligationCause::new( + obligation.cause.span, + obligation.cause.body_id, + derived_code, + ); ensure_sufficient_stack(|| { self.vtable_impl( impl_def_id, substs, - cause, + &cause, new_obligation.recursion_depth + 1, new_obligation.param_env, + obligation.predicate, ) }) }); diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 5d07139e87bf0..c15afa33d2b98 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -13,15 +13,11 @@ use super::project::ProjectionTyObligation; use super::util; use super::util::{closure_trait_ref_and_return_type, predicate_for_trait_def}; use super::wf; -use super::DerivedObligationCause; -use super::Normalized; -use super::Obligation; -use super::ObligationCauseCode; -use super::Selection; -use super::SelectionResult; -use super::TraitQueryMode; -use super::{ErrorReporting, Overflow, SelectionError}; -use super::{ObligationCause, PredicateObligation, TraitObligation}; +use super::{ + DerivedObligationCause, ErrorReporting, ImplDerivedObligation, ImplDerivedObligationCause, + Normalized, Obligation, ObligationCause, ObligationCauseCode, Overflow, PredicateObligation, + Selection, SelectionError, SelectionResult, TraitObligation, TraitQueryMode, +}; use crate::infer::{InferCtxt, InferOk, TypeFreshener}; use crate::traits::error_reporting::InferCtxtExt; @@ -2333,11 +2329,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { #[tracing::instrument(level = "debug", skip(self, cause, param_env))] fn impl_or_trait_obligations( &mut self, - cause: ObligationCause<'tcx>, + cause: &ObligationCause<'tcx>, recursion_depth: usize, param_env: ty::ParamEnv<'tcx>, def_id: DefId, // of impl or trait substs: SubstsRef<'tcx>, // for impl or trait + parent_trait_pred: ty::Binder<'tcx, ty::TraitPredicate<'tcx>>, ) -> Vec> { let tcx = self.tcx(); @@ -2359,8 +2356,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { debug!(?predicates); assert_eq!(predicates.parent, None); let mut obligations = Vec::with_capacity(predicates.predicates.len()); - for (predicate, _) in predicates.predicates { - debug!(?predicate); + let parent_code = cause.clone_code(); + for (predicate, span) in predicates.predicates { + let span = *span; + let derived = + DerivedObligationCause { parent_trait_pred, parent_code: parent_code.clone() }; + let code = ImplDerivedObligation(Box::new(ImplDerivedObligationCause { + derived, + impl_def_id: def_id, + span, + })); + let cause = ObligationCause::new(cause.span, cause.body_id, code); let predicate = normalize_with_depth_to( self, param_env, @@ -2369,12 +2375,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { predicate.subst(tcx, substs), &mut obligations, ); - obligations.push(Obligation { - cause: cause.clone(), - recursion_depth, - param_env, - predicate, - }); + obligations.push(Obligation { cause, recursion_depth, param_env, predicate }); } obligations diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index f5477f7103cb3..a22c9210a9c22 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -227,8 +227,14 @@ fn compare_predicate_entailment<'tcx>( traits::normalize(&mut selcx, param_env, normalize_cause, predicate); inh.register_predicates(obligations); - let mut cause = cause.clone(); - cause.span = span; + let cause = ObligationCause::new( + span, + impl_m_hir_id, + ObligationCauseCode::CompareImplMethodObligation { + impl_item_def_id: impl_m.def_id, + trait_item_def_id: trait_m.def_id, + }, + ); inh.register_predicate(traits::Obligation::new(cause, param_env, predicate)); } diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs index d336573c254f8..b7b45929e1463 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs @@ -1087,8 +1087,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut result_code = code.clone(); loop { let parent = match &*code { + ObligationCauseCode::ImplDerivedObligation(c) => { + c.derived.parent_code.clone() + } ObligationCauseCode::BuiltinDerivedObligation(c) - | ObligationCauseCode::ImplDerivedObligation(c) | ObligationCauseCode::DerivedObligation(c) => c.parent_code.clone(), _ => break, }; @@ -1098,10 +1100,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } let self_: ty::subst::GenericArg<'_> = match &*unpeel_to_top(error.obligation.cause.clone_code()) { ObligationCauseCode::BuiltinDerivedObligation(code) | - ObligationCauseCode::ImplDerivedObligation(code) | ObligationCauseCode::DerivedObligation(code) => { code.parent_trait_pred.self_ty().skip_binder().into() } + ObligationCauseCode::ImplDerivedObligation(code) => { + code.derived.parent_trait_pred.self_ty().skip_binder().into() + } _ if let ty::PredicateKind::Trait(predicate) = error.obligation.predicate.kind().skip_binder() => { predicate.self_ty().into() diff --git a/compiler/rustc_typeck/src/check/method/probe.rs b/compiler/rustc_typeck/src/check/method/probe.rs index 4e1645adca5d3..704866c2cc2ac 100644 --- a/compiler/rustc_typeck/src/check/method/probe.rs +++ b/compiler/rustc_typeck/src/check/method/probe.rs @@ -1521,6 +1521,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let selcx = &mut traits::SelectionContext::new(self); let cause = traits::ObligationCause::misc(self.span, self.body_id); + let mut parent_pred = None; + // If so, impls may carry other conditions (e.g., where // clauses) that must be considered. Make sure that those // match as well (or at least may match, sometimes we @@ -1584,6 +1586,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } let predicate = ty::Binder::dummy(trait_ref).without_const().to_predicate(self.tcx); + parent_pred = Some(predicate); let obligation = traits::Obligation::new(cause, self.param_env, predicate); if !self.predicate_may_hold(&obligation) { result = ProbeResult::NoMatch; @@ -1639,7 +1642,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let o = self.resolve_vars_if_possible(o); if !self.predicate_may_hold(&o) { result = ProbeResult::NoMatch; - possibly_unsatisfied_predicates.push((o.predicate, None, Some(o.cause))); + possibly_unsatisfied_predicates.push((o.predicate, parent_pred, Some(o.cause))); } } diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index bf7db8221a26f..9c3f2da56442f 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -16,9 +16,8 @@ use rustc_middle::ty::fast_reject::{simplify_type, TreatParams}; use rustc_middle::ty::print::with_crate_prefix; use rustc_middle::ty::ToPolyTraitRef; use rustc_middle::ty::{self, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable}; -use rustc_span::lev_distance; use rustc_span::symbol::{kw, sym, Ident}; -use rustc_span::{source_map, FileName, MultiSpan, Span}; +use rustc_span::{lev_distance, source_map, ExpnKind, FileName, MacroKind, MultiSpan, Span}; use rustc_trait_selection::traits::error_reporting::on_unimplemented::InferCtxtExt as _; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _; use rustc_trait_selection::traits::{ @@ -723,102 +722,190 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Find all the requirements that come from a local `impl` block. let mut skip_list: FxHashSet<_> = Default::default(); let mut spanned_predicates: FxHashMap = Default::default(); - for (data, p, parent_p) in unsatisfied_predicates + for (data, p, parent_p, impl_def_id, cause_span) in unsatisfied_predicates .iter() .filter_map(|(p, parent, c)| c.as_ref().map(|c| (p, parent, c))) .filter_map(|(p, parent, c)| match c.code() { ObligationCauseCode::ImplDerivedObligation(ref data) => { - Some((data, p, parent)) + Some((&data.derived, p, parent, data.impl_def_id, data.span)) } _ => None, }) { let parent_trait_ref = data.parent_trait_pred; - let parent_def_id = parent_trait_ref.def_id(); let path = parent_trait_ref.print_modifiers_and_trait_path(); let tr_self_ty = parent_trait_ref.skip_binder().self_ty(); - let mut candidates = vec![]; - self.tcx.for_each_relevant_impl( - parent_def_id, - parent_trait_ref.self_ty().skip_binder(), - |impl_def_id| match self.tcx.hir().get_if_local(impl_def_id) { - Some(Node::Item(hir::Item { - kind: hir::ItemKind::Impl(hir::Impl { .. }), - .. - })) => { - candidates.push(impl_def_id); + let unsatisfied_msg = "unsatisfied trait bound introduced here".to_string(); + let derive_msg = + "unsatisfied trait bound introduced in this `derive` macro"; + match self.tcx.hir().get_if_local(impl_def_id) { + // Unmet obligation comes from a `derive` macro, point at it once to + // avoid multiple span labels pointing at the same place. + Some(Node::Item(hir::Item { + kind: hir::ItemKind::Trait(..), + ident, + .. + })) if matches!( + ident.span.ctxt().outer_expn_data().kind, + ExpnKind::Macro(MacroKind::Derive, _) + ) => + { + let span = ident.span.ctxt().outer_expn_data().call_site; + let mut spans: MultiSpan = span.into(); + spans.push_span_label(span, derive_msg.to_string()); + let entry = spanned_predicates.entry(spans); + entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p); + } + + Some(Node::Item(hir::Item { + kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, .. }), + .. + })) if matches!( + self_ty.span.ctxt().outer_expn_data().kind, + ExpnKind::Macro(MacroKind::Derive, _) + ) || matches!( + of_trait.as_ref().map(|t| t + .path + .span + .ctxt() + .outer_expn_data() + .kind), + Some(ExpnKind::Macro(MacroKind::Derive, _)) + ) => + { + let span = self_ty.span.ctxt().outer_expn_data().call_site; + let mut spans: MultiSpan = span.into(); + spans.push_span_label(span, derive_msg.to_string()); + let entry = spanned_predicates.entry(spans.into()); + entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p); + } + + // Unmet obligation coming from a `trait`. + Some(Node::Item(hir::Item { + kind: hir::ItemKind::Trait(..), + ident, + span: item_span, + .. + })) if !matches!( + ident.span.ctxt().outer_expn_data().kind, + ExpnKind::Macro(MacroKind::Derive, _) + ) => + { + if let Some(pred) = parent_p { + // Done to add the "doesn't satisfy" `span_label`. + let _ = format_pred(*pred); } - _ => {} - }, - ); - if let [def_id] = &candidates[..] { - match self.tcx.hir().get_if_local(*def_id) { - Some(Node::Item(hir::Item { - kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, .. }), - .. - })) => { - if let Some(pred) = parent_p { - // Done to add the "doesn't satisfy" `span_label`. - let _ = format_pred(*pred); - } - skip_list.insert(p); + skip_list.insert(p); + let mut spans = if cause_span != *item_span { + let mut spans: MultiSpan = cause_span.into(); + spans.push_span_label(cause_span, unsatisfied_msg); + spans + } else { + ident.span.into() + }; + spans.push_span_label(ident.span, "in this trait".to_string()); + let entry = spanned_predicates.entry(spans.into()); + entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p); + } + + // Unmet obligation coming from an `impl`. + Some(Node::Item(hir::Item { + kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, .. }), + span: item_span, + .. + })) if !matches!( + self_ty.span.ctxt().outer_expn_data().kind, + ExpnKind::Macro(MacroKind::Derive, _) + ) && !matches!( + of_trait.as_ref().map(|t| t + .path + .span + .ctxt() + .outer_expn_data() + .kind), + Some(ExpnKind::Macro(MacroKind::Derive, _)) + ) => + { + if let Some(pred) = parent_p { + // Done to add the "doesn't satisfy" `span_label`. + let _ = format_pred(*pred); + } + skip_list.insert(p); + let mut spans = if cause_span != *item_span { + let mut spans: MultiSpan = cause_span.into(); + spans.push_span_label(cause_span, unsatisfied_msg); + spans + } else { let mut spans = Vec::with_capacity(2); if let Some(trait_ref) = of_trait { spans.push(trait_ref.path.span); } spans.push(self_ty.span); - let entry = spanned_predicates.entry(spans.into()); - entry - .or_insert_with(|| (path, tr_self_ty, Vec::new())) - .2 - .push(p); + spans.into() + }; + if let Some(trait_ref) = of_trait { + spans.push_span_label(trait_ref.path.span, String::new()); } - _ => {} + spans.push_span_label(self_ty.span, String::new()); + + let entry = spanned_predicates.entry(spans.into()); + entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p); } + _ => {} } } - for (span, (path, self_ty, preds)) in spanned_predicates { - err.span_note( - span, - &format!( - "the following trait bounds were not satisfied because of the \ - requirements of the implementation of `{}` for `{}`:\n{}", - path, - self_ty, - preds - .into_iter() - // .map(|pred| format!("{:?}", pred)) - .filter_map(|pred| format_pred(*pred)) - .map(|(p, _)| format!("`{}`", p)) - .collect::>() - .join("\n"), - ), - ); + let mut spanned_predicates: Vec<_> = spanned_predicates.into_iter().collect(); + spanned_predicates.sort_by_key(|(span, (_, _, _))| span.primary_span()); + for (span, (_path, _self_ty, preds)) in spanned_predicates { + let mut preds: Vec<_> = preds + .into_iter() + .filter_map(|pred| format_pred(*pred)) + .map(|(p, _)| format!("`{}`", p)) + .collect(); + preds.sort(); + preds.dedup(); + let msg = if let [pred] = &preds[..] { + format!("trait bound {} was not satisfied", pred) + } else { + format!( + "the following trait bounds were not satisfied:\n{}", + preds.join("\n"), + ) + }; + err.span_note(span, &msg); + unsatisfied_bounds = true; } // The requirements that didn't have an `impl` span to show. let mut bound_list = unsatisfied_predicates .iter() - .filter(|(pred, _, _parent_pred)| !skip_list.contains(&pred)) .filter_map(|(pred, parent_pred, _cause)| { format_pred(*pred).map(|(p, self_ty)| { collect_type_param_suggestions(self_ty, *pred, &p); - match parent_pred { - None => format!("`{}`", &p), - Some(parent_pred) => match format_pred(*parent_pred) { + ( + match parent_pred { None => format!("`{}`", &p), - Some((parent_p, _)) => { - collect_type_param_suggestions( - self_ty, - *parent_pred, - &p, - ); - format!("`{}`\nwhich is required by `{}`", p, parent_p) - } + Some(parent_pred) => match format_pred(*parent_pred) { + None => format!("`{}`", &p), + Some((parent_p, _)) => { + collect_type_param_suggestions( + self_ty, + *parent_pred, + &p, + ); + format!( + "`{}`\nwhich is required by `{}`", + p, parent_p + ) + } + }, }, - } + *pred, + ) }) }) + .filter(|(_, pred)| !skip_list.contains(&pred)) + .map(|(t, _)| t) .enumerate() .collect::>(); diff --git a/compiler/rustc_typeck/src/lib.rs b/compiler/rustc_typeck/src/lib.rs index 5d4dfd3caefcc..d0c4726bb0a8c 100644 --- a/compiler/rustc_typeck/src/lib.rs +++ b/compiler/rustc_typeck/src/lib.rs @@ -58,6 +58,7 @@ This API is completely unstable and subject to change. #![allow(rustc::potential_query_instability)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(bool_to_option)] +#![feature(box_patterns)] #![feature(control_flow_enum)] #![feature(crate_visibility_modifier)] #![feature(hash_drain_filter)] 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 45a906a39475b..72dd9c153ab0d 100644 --- a/src/test/ui/derives/derive-assoc-type-not-impl.stderr +++ b/src/test/ui/derives/derive-assoc-type-not-impl.stderr @@ -13,16 +13,17 @@ LL | struct NotClone; LL | Bar:: { x: 1 }.clone(); | ^^^^^ method cannot be called on `Bar` due to unsatisfied trait bounds | -note: the following trait bounds were not satisfied because of the requirements of the implementation of `Clone` for `_`: - `NotClone: Clone` +note: trait bound `NotClone: Clone` was not satisfied --> $DIR/derive-assoc-type-not-impl.rs:6:10 | LL | #[derive(Clone)] - | ^^^^^ + | ^^^^^ unsatisfied trait bound introduced in this `derive` macro + = note: the following trait bounds were not satisfied: + `NotClone: Clone` + which is required by `Bar: 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: `Clone` - = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `NotClone` with `#[derive(Clone)]` | LL | #[derive(Clone)] diff --git a/src/test/ui/generic-associated-types/method-unsatified-assoc-type-predicate.rs b/src/test/ui/generic-associated-types/method-unsatified-assoc-type-predicate.rs index 8b6f7c41a7c66..655abd18da1cb 100644 --- a/src/test/ui/generic-associated-types/method-unsatified-assoc-type-predicate.rs +++ b/src/test/ui/generic-associated-types/method-unsatified-assoc-type-predicate.rs @@ -12,7 +12,10 @@ trait M { } impl = i32>> M for T {} -//~^ NOTE the following trait bounds were not satisfied +//~^ NOTE trait bound `::Y = i32` was not satisfied +//~| NOTE unsatisfied trait bound introduced here +//~| NOTE +//~| NOTE struct S; //~^ NOTE method `f` not found for this diff --git a/src/test/ui/generic-associated-types/method-unsatified-assoc-type-predicate.stderr b/src/test/ui/generic-associated-types/method-unsatified-assoc-type-predicate.stderr index 3eeb9540e7351..9eeebd80afecb 100644 --- a/src/test/ui/generic-associated-types/method-unsatified-assoc-type-predicate.stderr +++ b/src/test/ui/generic-associated-types/method-unsatified-assoc-type-predicate.stderr @@ -1,5 +1,5 @@ error[E0599]: the method `f` exists for struct `S`, but its trait bounds were not satisfied - --> $DIR/method-unsatified-assoc-type-predicate.rs:27:7 + --> $DIR/method-unsatified-assoc-type-predicate.rs:30:7 | LL | struct S; | --------- @@ -11,12 +11,13 @@ LL | struct S; LL | a.f(); | ^ method cannot be called on `S` due to unsatisfied trait bounds | -note: the following trait bounds were not satisfied because of the requirements of the implementation of `M` for `_`: - `::Y = i32` - --> $DIR/method-unsatified-assoc-type-predicate.rs:14:26 +note: trait bound `::Y = i32` was not satisfied + --> $DIR/method-unsatified-assoc-type-predicate.rs:14:11 | LL | impl = i32>> M for T {} - | ^ ^ + | ^^^^^^^^^^^^ - - + | | + | unsatisfied trait bound introduced here error: aborting due to previous error diff --git a/src/test/ui/hrtb/issue-30786.migrate.stderr b/src/test/ui/hrtb/issue-30786.migrate.stderr index a2ab1f1856d3e..7ffe2f4cd7e1c 100644 --- a/src/test/ui/hrtb/issue-30786.migrate.stderr +++ b/src/test/ui/hrtb/issue-30786.migrate.stderr @@ -10,14 +10,14 @@ LL | pub struct Map { LL | let filter = map.filterx(|x: &_| true); | ^^^^^^^ method cannot be called on `Map` due to unsatisfied trait bounds | -note: the following trait bounds were not satisfied because of the requirements of the implementation of `StreamExt` for `_`: - `&'a mut Map: Stream` +note: the following trait bounds were not satisfied: `&'a mut &Map: Stream` `&'a mut &mut Map: Stream` - --> $DIR/issue-30786.rs:105:9 + `&'a mut Map: Stream` + --> $DIR/issue-30786.rs:105:50 | LL | impl StreamExt for T where for<'a> &'a mut T: Stream {} - | ^^^^^^^^^ ^ + | --------- - ^^^^^^ unsatisfied trait bound introduced here error[E0599]: the method `countx` exists for struct `Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:139:30: 139:42]>`, but its trait bounds were not satisfied --> $DIR/issue-30786.rs:140:24 @@ -31,14 +31,14 @@ LL | pub struct Filter { LL | let count = filter.countx(); | ^^^^^^ method cannot be called on `Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:139:30: 139:42]>` due to unsatisfied trait bounds | -note: the following trait bounds were not satisfied because of the requirements of the implementation of `StreamExt` for `_`: - `&'a mut Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:139:30: 139:42]>: Stream` +note: the following trait bounds were not satisfied: `&'a mut &Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:139:30: 139:42]>: Stream` `&'a mut &mut Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:139:30: 139:42]>: Stream` - --> $DIR/issue-30786.rs:105:9 + `&'a mut Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:139:30: 139:42]>: Stream` + --> $DIR/issue-30786.rs:105:50 | LL | impl StreamExt for T where for<'a> &'a mut T: Stream {} - | ^^^^^^^^^ ^ + | --------- - ^^^^^^ unsatisfied trait bound introduced here error: aborting due to 2 previous errors diff --git a/src/test/ui/hrtb/issue-30786.nll.stderr b/src/test/ui/hrtb/issue-30786.nll.stderr index a2ab1f1856d3e..7ffe2f4cd7e1c 100644 --- a/src/test/ui/hrtb/issue-30786.nll.stderr +++ b/src/test/ui/hrtb/issue-30786.nll.stderr @@ -10,14 +10,14 @@ LL | pub struct Map { LL | let filter = map.filterx(|x: &_| true); | ^^^^^^^ method cannot be called on `Map` due to unsatisfied trait bounds | -note: the following trait bounds were not satisfied because of the requirements of the implementation of `StreamExt` for `_`: - `&'a mut Map: Stream` +note: the following trait bounds were not satisfied: `&'a mut &Map: Stream` `&'a mut &mut Map: Stream` - --> $DIR/issue-30786.rs:105:9 + `&'a mut Map: Stream` + --> $DIR/issue-30786.rs:105:50 | LL | impl StreamExt for T where for<'a> &'a mut T: Stream {} - | ^^^^^^^^^ ^ + | --------- - ^^^^^^ unsatisfied trait bound introduced here error[E0599]: the method `countx` exists for struct `Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:139:30: 139:42]>`, but its trait bounds were not satisfied --> $DIR/issue-30786.rs:140:24 @@ -31,14 +31,14 @@ LL | pub struct Filter { LL | let count = filter.countx(); | ^^^^^^ method cannot be called on `Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:139:30: 139:42]>` due to unsatisfied trait bounds | -note: the following trait bounds were not satisfied because of the requirements of the implementation of `StreamExt` for `_`: - `&'a mut Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:139:30: 139:42]>: Stream` +note: the following trait bounds were not satisfied: `&'a mut &Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:139:30: 139:42]>: Stream` `&'a mut &mut Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:139:30: 139:42]>: Stream` - --> $DIR/issue-30786.rs:105:9 + `&'a mut Filter fn(&'r u64) -> &'r u64 {identity::}>, [closure@$DIR/issue-30786.rs:139:30: 139:42]>: Stream` + --> $DIR/issue-30786.rs:105:50 | LL | impl StreamExt for T where for<'a> &'a mut T: Stream {} - | ^^^^^^^^^ ^ + | --------- - ^^^^^^ unsatisfied trait bound introduced here error: aborting due to 2 previous errors diff --git a/src/test/ui/missing-trait-bounds/missing-trait-bounds-for-method-call.stderr b/src/test/ui/missing-trait-bounds/missing-trait-bounds-for-method-call.stderr index 2f0fd692a444a..f3c6b39e62ed0 100644 --- a/src/test/ui/missing-trait-bounds/missing-trait-bounds-for-method-call.stderr +++ b/src/test/ui/missing-trait-bounds/missing-trait-bounds-for-method-call.stderr @@ -7,11 +7,20 @@ LL | struct Foo { LL | self.foo(); | ^^^ method cannot be called on `&Foo` due to unsatisfied trait bounds | - = note: the following trait bounds were not satisfied: - `T: Default` - which is required by `Foo: Bar` - `T: Bar` - which is required by `Foo: Bar` +note: trait bound `T: Default` was not satisfied + --> $DIR/missing-trait-bounds-for-method-call.rs:10:9 + | +LL | impl Bar for Foo {} + | ^^^^^^^ --- ------ + | | + | unsatisfied trait bound introduced here +note: trait bound `T: Bar` was not satisfied + --> $DIR/missing-trait-bounds-for-method-call.rs:10:19 + | +LL | impl Bar for Foo {} + | ^^^ --- ------ + | | + | unsatisfied trait bound introduced here help: consider restricting the type parameters to satisfy the trait bounds | LL | struct Foo where T: Bar, T: Default { @@ -26,9 +35,13 @@ LL | struct Fin where T: Bar { LL | self.foo(); | ^^^ method cannot be called on `&Fin` due to unsatisfied trait bounds | - = note: the following trait bounds were not satisfied: - `T: Default` - which is required by `Fin: Bar` +note: trait bound `T: Default` was not satisfied + --> $DIR/missing-trait-bounds-for-method-call.rs:23:9 + | +LL | impl Bar for Fin {} + | ^^^^^^^ --- ------ + | | + | unsatisfied trait bound introduced here help: consider restricting the type parameter to satisfy the trait bound | LL | struct Fin where T: Bar, T: Default { diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr index fedb1ffdea97a..9dbaffd4c1565 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr @@ -54,6 +54,12 @@ LL | const _: () = check($exp); LL | ConstDropImplWithBounds::(PhantomData), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an implementor of trait `~const Destruct` | +note: required because of the requirements on the impl of `~const Destruct` for `ConstDropImplWithBounds` + --> $DIR/const-drop-fail.rs:28:25 + | +LL | impl const Drop for ConstDropImplWithBounds { + | ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: 1 redundant requirement hidden = note: required because of the requirements on the impl of `~const Destruct` for `ConstDropImplWithBounds` note: required by a bound in `check` --> $DIR/const-drop-fail.rs:34:19 diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr index fedb1ffdea97a..9dbaffd4c1565 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr @@ -54,6 +54,12 @@ LL | const _: () = check($exp); LL | ConstDropImplWithBounds::(PhantomData), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an implementor of trait `~const Destruct` | +note: required because of the requirements on the impl of `~const Destruct` for `ConstDropImplWithBounds` + --> $DIR/const-drop-fail.rs:28:25 + | +LL | impl const Drop for ConstDropImplWithBounds { + | ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: 1 redundant requirement hidden = note: required because of the requirements on the impl of `~const Destruct` for `ConstDropImplWithBounds` note: required by a bound in `check` --> $DIR/const-drop-fail.rs:34:19 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 81e2a9a1ffcc7..9894ecc64b518 100644 --- a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr +++ b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr @@ -20,8 +20,7 @@ LL | struct MyStruct; LL | println!("{}", MyStruct.foo_one()); | ^^^^^^^ method cannot be called on `MyStruct` due to unsatisfied trait bounds | -note: the following trait bounds were not satisfied because of the requirements of the implementation of `Foo` for `_`: - `MyStruct: Foo` +note: trait bound `MyStruct: Foo` was not satisfied --> $DIR/specialization-trait-not-implemented.rs:14:17 | LL | default impl Foo for T { diff --git a/src/test/ui/traits/alias/cross-crate.stderr b/src/test/ui/traits/alias/cross-crate.stderr index 3c3b6e566908a..d0d00c97e8305 100644 --- a/src/test/ui/traits/alias/cross-crate.stderr +++ b/src/test/ui/traits/alias/cross-crate.stderr @@ -5,6 +5,7 @@ LL | use_alias::>(); | ^^^^^^^ `Rc` cannot be sent between threads safely | = help: the trait `Send` is not implemented for `Rc` + = note: required because of the requirements on the impl of `SendSync` for `Rc` note: required by a bound in `use_alias` --> $DIR/cross-crate.rs:10:17 | @@ -18,6 +19,7 @@ LL | use_alias::>(); | ^^^^^^^ `Rc` cannot be shared between threads safely | = help: the trait `Sync` is not implemented for `Rc` + = note: required because of the requirements on the impl of `SendSync` for `Rc` note: required by a bound in `use_alias` --> $DIR/cross-crate.rs:10:17 | diff --git a/src/test/ui/traits/inductive-overflow/supertrait-auto-trait.stderr b/src/test/ui/traits/inductive-overflow/supertrait-auto-trait.stderr index 8405d7ddc7aa5..9ceeea4872fbb 100644 --- a/src/test/ui/traits/inductive-overflow/supertrait-auto-trait.stderr +++ b/src/test/ui/traits/inductive-overflow/supertrait-auto-trait.stderr @@ -14,7 +14,11 @@ LL | let (a, b) = copy(NoClone); | | | required by a bound introduced by this call | - = note: required because of the requirements on the impl of `Magic` for `NoClone` +note: required because of the requirements on the impl of `Magic` for `NoClone` + --> $DIR/supertrait-auto-trait.rs:8:12 + | +LL | auto trait Magic: Copy {} + | ^^^^^ note: required by a bound in `copy` --> $DIR/supertrait-auto-trait.rs:10:12 | diff --git a/src/test/ui/union/union-derive-clone.mirunsafeck.stderr b/src/test/ui/union/union-derive-clone.mirunsafeck.stderr index e8e65fe5d1d1d..de0bc7830b73a 100644 --- a/src/test/ui/union/union-derive-clone.mirunsafeck.stderr +++ b/src/test/ui/union/union-derive-clone.mirunsafeck.stderr @@ -13,6 +13,11 @@ LL | struct CloneNoCopy; LL | let w = u.clone(); | ^^^^^ method cannot be called on `U5` due to unsatisfied trait bounds | +note: trait bound `CloneNoCopy: Copy` was not satisfied + --> $DIR/union-derive-clone.rs:28:10 + | +LL | #[derive(Clone, Copy)] + | ^^^^^ unsatisfied trait bound introduced in this `derive` macro = note: the following trait bounds were not satisfied: `CloneNoCopy: Copy` which is required by `U5: Clone` diff --git a/src/test/ui/union/union-derive-clone.thirunsafeck.stderr b/src/test/ui/union/union-derive-clone.thirunsafeck.stderr index e8e65fe5d1d1d..de0bc7830b73a 100644 --- a/src/test/ui/union/union-derive-clone.thirunsafeck.stderr +++ b/src/test/ui/union/union-derive-clone.thirunsafeck.stderr @@ -13,6 +13,11 @@ LL | struct CloneNoCopy; LL | let w = u.clone(); | ^^^^^ method cannot be called on `U5` due to unsatisfied trait bounds | +note: trait bound `CloneNoCopy: Copy` was not satisfied + --> $DIR/union-derive-clone.rs:28:10 + | +LL | #[derive(Clone, Copy)] + | ^^^^^ unsatisfied trait bound introduced in this `derive` macro = note: the following trait bounds were not satisfied: `CloneNoCopy: Copy` which is required by `U5: Clone` diff --git a/src/test/ui/wf/hir-wf-check-erase-regions.stderr b/src/test/ui/wf/hir-wf-check-erase-regions.stderr index aef6db0a40b75..0d9b9627562f9 100644 --- a/src/test/ui/wf/hir-wf-check-erase-regions.stderr +++ b/src/test/ui/wf/hir-wf-check-erase-regions.stderr @@ -5,11 +5,7 @@ LL | type IntoIter = std::iter::Flatten>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&T` is not an iterator | = help: the trait `Iterator` is not implemented for `&T` -note: required because of the requirements on the impl of `IntoIterator` for `&T` - --> $DIR/hir-wf-check-erase-regions.rs:6:29 - | -LL | impl<'a, T, const N: usize> IntoIterator for &'a Table { - | ^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ + = note: required because of the requirements on the impl of `IntoIterator` for `&T` note: required by a bound in `Flatten` --> $SRC_DIR/core/src/iter/adapters/flatten.rs:LL:COL | @@ -23,11 +19,7 @@ LL | fn into_iter(self) -> Self::IntoIter { | ^^^^^^^^^^^^^^ `&T` is not an iterator | = help: the trait `Iterator` is not implemented for `&T` -note: required because of the requirements on the impl of `IntoIterator` for `&T` - --> $DIR/hir-wf-check-erase-regions.rs:6:29 - | -LL | impl<'a, T, const N: usize> IntoIterator for &'a Table { - | ^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ + = note: required because of the requirements on the impl of `IntoIterator` for `&T` note: required by a bound in `Flatten` --> $SRC_DIR/core/src/iter/adapters/flatten.rs:LL:COL |