From ff4653a08f0c9dad1db927727e102c51f0ea39b2 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 10 Mar 2024 19:43:20 -0400 Subject: [PATCH] Use fulfillment, not evaluate, during method probe --- compiler/rustc_hir_typeck/src/demand.rs | 2 +- compiler/rustc_hir_typeck/src/method/probe.rs | 431 ++++++------------ .../src/traits/engine.rs | 13 + tests/ui/derives/issue-91550.stderr | 27 +- tests/ui/impl-trait/issues/issue-62742.rs | 2 +- tests/ui/impl-trait/issues/issue-62742.stderr | 50 +- tests/ui/impl-trait/issues/issue-84073.rs | 3 +- tests/ui/impl-trait/issues/issue-84073.stderr | 28 +- .../option-as_deref.stderr | 1 + .../option-as_deref_mut.stderr | 1 + .../result-as_deref.stderr | 1 + .../result-as_deref_mut.stderr | 1 + .../fulfillment-disqualifies-method.rs | 32 ++ tests/ui/methods/leak-check-disquality.rs | 26 ++ .../ui/mismatched_types/issue-36053-2.stderr | 10 +- .../missing-trait-bounds/issue-35677.stderr | 2 - tests/ui/nll/issue-57362-2.rs | 3 +- tests/ui/nll/issue-57362-2.stderr | 6 +- .../nll/issue-57642-higher-ranked-subtype.rs | 3 +- .../issue-57642-higher-ranked-subtype.stderr | 8 +- tests/ui/resolve/issue-85671.rs | 3 +- tests/ui/resolve/issue-85671.stderr | 17 + .../derive-trait-for-method-call.stderr | 24 +- ...t-trait-alias-bound-on-generic-impl.stderr | 7 - .../method-on-unbounded-type-param.stderr | 2 +- tests/ui/traits/track-obligations.stderr | 30 +- tests/ui/typeck/issue-31173.stderr | 2 +- 27 files changed, 328 insertions(+), 407 deletions(-) create mode 100644 tests/ui/methods/fulfillment-disqualifies-method.rs create mode 100644 tests/ui/methods/leak-check-disquality.rs create mode 100644 tests/ui/resolve/issue-85671.stderr diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index d6d22a43fe0..618d90a07ec 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -889,7 +889,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { [candidate] => format!( "the method of the same name on {} `{}`", match candidate.kind { - probe::CandidateKind::InherentImplCandidate(..) => "the inherent impl for", + probe::CandidateKind::InherentImplCandidate(_) => "the inherent impl for", _ => "trait", }, self.tcx.def_path_str(candidate.item.container_id(self.tcx)) diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 7e480d66695..c31b54c642d 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -31,13 +31,12 @@ use rustc_span::edit_distance::{ }; use rustc_span::symbol::sym; use rustc_span::{symbol::Ident, Span, Symbol, DUMMY_SP}; -use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; use rustc_trait_selection::traits::query::method_autoderef::MethodAutoderefBadTy; use rustc_trait_selection::traits::query::method_autoderef::{ CandidateStep, MethodAutoderefStepsResult, }; use rustc_trait_selection::traits::query::CanonicalTyGoal; -use rustc_trait_selection::traits::NormalizeExt; +use rustc_trait_selection::traits::ObligationCtxt; use rustc_trait_selection::traits::{self, ObligationCause}; use std::cell::RefCell; use std::cmp::max; @@ -99,39 +98,6 @@ impl<'a, 'tcx> Deref for ProbeContext<'a, 'tcx> { #[derive(Debug, Clone)] pub(crate) struct Candidate<'tcx> { - // Candidates are (I'm not quite sure, but they are mostly) basically - // some metadata on top of a `ty::AssocItem` (without args). - // - // However, method probing wants to be able to evaluate the predicates - // for a function with the args applied - for example, if a function - // has `where Self: Sized`, we don't want to consider it unless `Self` - // is actually `Sized`, and similarly, return-type suggestions want - // to consider the "actual" return type. - // - // The way this is handled is through `xform_self_ty`. It contains - // the receiver type of this candidate, but `xform_self_ty`, - // `xform_ret_ty` and `kind` (which contains the predicates) have the - // generic parameters of this candidate instantiated with the *same set* - // of inference variables, which acts as some weird sort of "query". - // - // When we check out a candidate, we require `xform_self_ty` to be - // a subtype of the passed-in self-type, and this equates the type - // variables in the rest of the fields. - // - // For example, if we have this candidate: - // ``` - // trait Foo { - // fn foo(&self) where Self: Sized; - // } - // ``` - // - // Then `xform_self_ty` will be `&'erased ?X` and `kind` will contain - // the predicate `?X: Sized`, so if we are evaluating `Foo` for a - // the receiver `&T`, we'll do the subtyping which will make `?X` - // get the right value, then when we evaluate the predicate we'll check - // if `T: Sized`. - xform_self_ty: Ty<'tcx>, - xform_ret_ty: Option>, pub(crate) item: ty::AssocItem, pub(crate) kind: CandidateKind<'tcx>, pub(crate) import_ids: SmallVec<[LocalDefId; 1]>, @@ -139,17 +105,10 @@ pub(crate) struct Candidate<'tcx> { #[derive(Debug, Clone)] pub(crate) enum CandidateKind<'tcx> { - InherentImplCandidate( - GenericArgsRef<'tcx>, - // Normalize obligations - Vec>, - ), - ObjectCandidate, - TraitCandidate(ty::TraitRef<'tcx>), - WhereClauseCandidate( - // Trait - ty::PolyTraitRef<'tcx>, - ), + InherentImplCandidate(DefId), + ObjectCandidate(ty::PolyTraitRef<'tcx>), + TraitCandidate(ty::PolyTraitRef<'tcx>), + WhereClauseCandidate(ty::PolyTraitRef<'tcx>), } #[derive(Debug, PartialEq, Eq, Copy, Clone)] @@ -743,41 +702,10 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { self.record_static_candidate(CandidateSource::Impl(impl_def_id)); continue; } - - let (impl_ty, impl_args) = self.impl_ty_and_args(impl_def_id); - - debug!("impl_ty: {:?}", impl_ty); - - // Determine the receiver type that the method itself expects. - let (xform_self_ty, xform_ret_ty) = self.xform_self_ty(item, impl_ty, impl_args); - debug!("xform_self_ty: {:?}, xform_ret_ty: {:?}", xform_self_ty, xform_ret_ty); - - // We can't use `FnCtxt::normalize` as it will pollute the - // fcx's fulfillment context after this probe is over. - // - // Note: we only normalize `xform_self_ty` here since the normalization - // of the return type can lead to inference results that prohibit - // valid candidates from being found, see issue #85671 - // - // FIXME Postponing the normalization of the return type likely only hides a deeper bug, - // which might be caused by the `param_env` itself. The clauses of the `param_env` - // maybe shouldn't include `Param`s, but rather fresh variables or be canonicalized, - // see issue #89650 - let cause = traits::ObligationCause::misc(self.span, self.body_id); - let InferOk { value: xform_self_ty, obligations } = - self.fcx.at(&cause, self.param_env).normalize(xform_self_ty); - - debug!( - "assemble_inherent_impl_probe after normalization: xform_self_ty = {:?}/{:?}", - xform_self_ty, xform_ret_ty - ); - self.push_candidate( Candidate { - xform_self_ty, - xform_ret_ty, item, - kind: InherentImplCandidate(impl_args, obligations), + kind: InherentImplCandidate(impl_def_id), import_ids: smallvec![], }, true, @@ -809,26 +737,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { // a `&self` method will wind up with an argument type like `&dyn Trait`. let trait_ref = principal.with_self_ty(self.tcx, self_ty); self.elaborate_bounds(iter::once(trait_ref), |this, new_trait_ref, item| { - if new_trait_ref.has_non_region_bound_vars() { - this.dcx().span_delayed_bug( - this.span, - "tried to select method from HRTB with non-lifetime bound vars", - ); - return; - } - - let new_trait_ref = this.tcx.instantiate_bound_regions_with_erased(new_trait_ref); - - let (xform_self_ty, xform_ret_ty) = - this.xform_self_ty(item, new_trait_ref.self_ty(), new_trait_ref.args); this.push_candidate( - Candidate { - xform_self_ty, - xform_ret_ty, - item, - kind: ObjectCandidate, - import_ids: smallvec![], - }, + Candidate { item, kind: ObjectCandidate(new_trait_ref), import_ids: smallvec![] }, true, ); }); @@ -859,19 +769,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { }); self.elaborate_bounds(bounds, |this, poly_trait_ref, item| { - let trait_ref = this.instantiate_binder_with_fresh_vars( - this.span, - infer::BoundRegionConversionTime::FnCall, - poly_trait_ref, - ); - - let (xform_self_ty, xform_ret_ty) = - this.xform_self_ty(item, trait_ref.self_ty(), trait_ref.args); - this.push_candidate( Candidate { - xform_self_ty, - xform_ret_ty, item, kind: WhereClauseCandidate(poly_trait_ref), import_ids: smallvec![], @@ -962,21 +861,11 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { bound_trait_ref.def_id(), )); } else { - let new_trait_ref = self.instantiate_binder_with_fresh_vars( - self.span, - infer::BoundRegionConversionTime::FnCall, - bound_trait_ref, - ); - - let (xform_self_ty, xform_ret_ty) = - self.xform_self_ty(item, new_trait_ref.self_ty(), new_trait_ref.args); self.push_candidate( Candidate { - xform_self_ty, - xform_ret_ty, item, import_ids: import_ids.clone(), - kind: TraitCandidate(new_trait_ref), + kind: TraitCandidate(bound_trait_ref), }, false, ); @@ -995,16 +884,11 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { self.record_static_candidate(CandidateSource::Trait(trait_def_id)); continue; } - - let (xform_self_ty, xform_ret_ty) = - self.xform_self_ty(item, trait_ref.self_ty(), trait_args); self.push_candidate( Candidate { - xform_self_ty, - xform_ret_ty, item, import_ids: import_ids.clone(), - kind: TraitCandidate(trait_ref), + kind: TraitCandidate(ty::Binder::dummy(trait_ref)), }, false, ); @@ -1434,16 +1318,20 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { fn candidate_source(&self, candidate: &Candidate<'tcx>, self_ty: Ty<'tcx>) -> CandidateSource { match candidate.kind { - InherentImplCandidate(..) => { + InherentImplCandidate(_) => { CandidateSource::Impl(candidate.item.container_id(self.tcx)) } - ObjectCandidate | WhereClauseCandidate(_) => { + ObjectCandidate(_) | WhereClauseCandidate(_) => { CandidateSource::Trait(candidate.item.container_id(self.tcx)) } TraitCandidate(trait_ref) => self.probe(|_| { + let trait_ref = + self.instantiate_binder_with_fresh_vars(self.span, infer::FnCall, trait_ref); + let (xform_self_ty, _) = + self.xform_self_ty(candidate.item, trait_ref.self_ty(), trait_ref.args); let _ = self.at(&ObligationCause::dummy(), self.param_env).sup( DefineOpaqueTypes::No, - candidate.xform_self_ty, + xform_self_ty, self_ty, ); match self.select_trait_candidate(trait_ref) { @@ -1470,54 +1358,39 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { ) -> ProbeResult { debug!("consider_probe: self_ty={:?} probe={:?}", self_ty, probe); - self.probe(|_| { - // First check that the self type can be related. - let sub_obligations = match self.at(&ObligationCause::dummy(), self.param_env).sup( - DefineOpaqueTypes::No, - probe.xform_self_ty, - self_ty, - ) { - Ok(InferOk { obligations, value: () }) => obligations, - Err(err) => { - debug!("--> cannot relate self-types {:?}", err); - return ProbeResult::NoMatch; - } - }; + self.probe(|snapshot| { + let outer_universe = self.universe(); let mut result = ProbeResult::Match; - let mut xform_ret_ty = probe.xform_ret_ty; - debug!(?xform_ret_ty); + let cause = &self.misc(self.span); + let ocx = ObligationCtxt::new(self); - let cause = traits::ObligationCause::misc(self.span, self.body_id); + let mut trait_predicate = None; + let (mut xform_self_ty, mut xform_ret_ty); - 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 - // don't have enough information to fully evaluate). match probe.kind { - InherentImplCandidate(args, ref ref_obligations) => { - // `xform_ret_ty` hasn't been normalized yet, only `xform_self_ty`, - // see the reasons mentioned in the comments in `assemble_inherent_impl_probe` - // for why this is necessary - let InferOk { - value: normalized_xform_ret_ty, - obligations: normalization_obligations, - } = self.fcx.at(&cause, self.param_env).normalize(xform_ret_ty); - xform_ret_ty = normalized_xform_ret_ty; - debug!("xform_ret_ty after normalization: {:?}", xform_ret_ty); - + InherentImplCandidate(impl_def_id) => { + let impl_args = self.fresh_args_for_item(self.span, impl_def_id); + let impl_ty = self.tcx.type_of(impl_def_id).instantiate(self.tcx, impl_args); + (xform_self_ty, xform_ret_ty) = + self.xform_self_ty(probe.item, impl_ty, impl_args); + xform_self_ty = ocx.normalize(cause, self.param_env, xform_self_ty); + // FIXME: Weirdly, we normalize the ret ty in this candidate, but no other candidates. + xform_ret_ty = ocx.normalize(cause, self.param_env, xform_ret_ty); + match ocx.eq_no_opaques(cause, self.param_env, xform_self_ty, self_ty) { + Ok(()) => {} + Err(err) => { + debug!("--> cannot relate self-types {:?}", err); + return ProbeResult::NoMatch; + } + } // Check whether the impl imposes obligations we have to worry about. let impl_def_id = probe.item.container_id(self.tcx); - let impl_bounds = self.tcx.predicates_of(impl_def_id); - let impl_bounds = impl_bounds.instantiate(self.tcx, args); - - let InferOk { value: impl_bounds, obligations: norm_obligations } = - self.fcx.at(&cause, self.param_env).normalize(impl_bounds); - + let impl_bounds = + self.tcx.predicates_of(impl_def_id).instantiate(self.tcx, impl_args); + let impl_bounds = ocx.normalize(cause, self.param_env, impl_bounds); // Convert the bounds into obligations. - let impl_obligations = traits::predicates_for_generics( + ocx.register_obligations(traits::predicates_for_generics( |idx, span| { let code = if span.is_dummy() { traits::ExprItemObligation(impl_def_id, self.scope_expr_id, idx) @@ -1533,106 +1406,56 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { }, self.param_env, impl_bounds, - ); - - let candidate_obligations = impl_obligations - .chain(norm_obligations) - .chain(ref_obligations.iter().cloned()) - .chain(normalization_obligations); - - // Evaluate those obligations to see if they might possibly hold. - for o in candidate_obligations { - let o = self.resolve_vars_if_possible(o); - if !self.predicate_may_hold(&o) { - result = ProbeResult::NoMatch; - let parent_o = o.clone(); - let implied_obligations = traits::elaborate(self.tcx, vec![o]); - for o in implied_obligations { - let parent = if o == parent_o { - None - } else { - if o.predicate.to_opt_poly_trait_pred().map(|p| p.def_id()) - == self.tcx.lang_items().sized_trait() - { - // We don't care to talk about implicit `Sized` bounds. - continue; - } - Some(parent_o.predicate) - }; - if !self.predicate_may_hold(&o) { - possibly_unsatisfied_predicates.push(( - o.predicate, - parent, - Some(o.cause), - )); - } - } - } - } + )); } - - ObjectCandidate | WhereClauseCandidate(..) => { - // These have no additional conditions to check. - } - - TraitCandidate(trait_ref) => { + TraitCandidate(poly_trait_ref) => { + // Some trait methods are excluded for arrays before 2021. + // (`array.into_iter()` wants a slice iterator for compatibility.) if let Some(method_name) = self.method_name { - // Some trait methods are excluded for arrays before 2021. - // (`array.into_iter()` wants a slice iterator for compatibility.) if self_ty.is_array() && !method_name.span.at_least_rust_2021() { - let trait_def = self.tcx.trait_def(trait_ref.def_id); + let trait_def = self.tcx.trait_def(poly_trait_ref.def_id()); if trait_def.skip_array_during_method_dispatch { return ProbeResult::NoMatch; } } } - let predicate = ty::Binder::dummy(trait_ref).to_predicate(self.tcx); - parent_pred = Some(predicate); - let obligation = - traits::Obligation::new(self.tcx, cause.clone(), self.param_env, predicate); - if !self.predicate_may_hold(&obligation) { - result = ProbeResult::NoMatch; - if self.probe(|_| { - match self.select_trait_candidate(trait_ref) { - Err(_) => return true, - Ok(Some(impl_source)) - if !impl_source.borrow_nested_obligations().is_empty() => - { - for obligation in impl_source.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) { - let nested_predicate = - self.resolve_vars_if_possible(obligation.predicate); - let predicate = - self.resolve_vars_if_possible(predicate); - let p = if predicate == nested_predicate { - // Avoid "`MyStruct: Foo` which is required by - // `MyStruct: Foo`" in E0599. - None - } else { - Some(predicate) - }; - possibly_unsatisfied_predicates.push(( - nested_predicate, - p, - Some(obligation.cause.clone()), - )); - } - } - } - _ => { - // Some nested subobligation of this predicate - // failed. - let predicate = self.resolve_vars_if_possible(predicate); - possibly_unsatisfied_predicates.push((predicate, None, None)); - } - } - false - }) { - // This candidate's primary obligation doesn't even - // select - don't bother registering anything in - // `potentially_unsatisfied_predicates`. + + let trait_ref = self.instantiate_binder_with_fresh_vars( + self.span, + infer::FnCall, + poly_trait_ref, + ); + (xform_self_ty, xform_ret_ty) = + self.xform_self_ty(probe.item, trait_ref.self_ty(), trait_ref.args); + xform_self_ty = ocx.normalize(cause, self.param_env, xform_self_ty); + match ocx.eq_no_opaques(cause, self.param_env, xform_self_ty, self_ty) { + Ok(()) => {} + Err(err) => { + debug!("--> cannot relate self-types {:?}", err); + return ProbeResult::NoMatch; + } + } + ocx.register_obligation(traits::Obligation::new( + self.tcx, + cause.clone(), + self.param_env, + ty::Binder::dummy(trait_ref), + )); + trait_predicate = Some(ty::Binder::dummy(trait_ref).to_predicate(self.tcx)); + } + ObjectCandidate(poly_trait_ref) | WhereClauseCandidate(poly_trait_ref) => { + let trait_ref = self.instantiate_binder_with_fresh_vars( + self.span, + infer::FnCall, + poly_trait_ref, + ); + (xform_self_ty, xform_ret_ty) = + self.xform_self_ty(probe.item, trait_ref.self_ty(), trait_ref.args); + xform_self_ty = ocx.normalize(cause, self.param_env, xform_self_ty); + match ocx.eq_no_opaques(cause, self.param_env, xform_self_ty, self_ty) { + Ok(()) => {} + Err(err) => { + debug!("--> cannot relate self-types {:?}", err); return ProbeResult::NoMatch; } } @@ -1640,11 +1463,22 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } // Evaluate those obligations to see if they might possibly hold. - for o in sub_obligations { - let o = self.resolve_vars_if_possible(o); - if !self.predicate_may_hold(&o) { - result = ProbeResult::NoMatch; - possibly_unsatisfied_predicates.push((o.predicate, parent_pred, Some(o.cause))); + for error in ocx.select_where_possible() { + result = ProbeResult::NoMatch; + let nested_predicate = self.resolve_vars_if_possible(error.obligation.predicate); + if let Some(trait_predicate) = trait_predicate + && nested_predicate == self.resolve_vars_if_possible(trait_predicate) + { + // Don't report possibly unsatisfied predicates if the root + // trait obligation from a `TraitCandidate` is unsatisfied. + // That just means the candidate doesn't hold. + } else { + possibly_unsatisfied_predicates.push(( + nested_predicate, + Some(self.resolve_vars_if_possible(error.root_obligation.predicate)) + .filter(|root_predicate| *root_predicate != nested_predicate), + Some(error.obligation.cause), + )); } } @@ -1656,36 +1490,37 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { // We don't normalize the other candidates for perf/backwards-compat reasons... // but `self.return_type` is only set on the diagnostic-path, so we // should be okay doing it here. - if !matches!(probe.kind, InherentImplCandidate(..)) { - let InferOk { - value: normalized_xform_ret_ty, - obligations: normalization_obligations, - } = self.fcx.at(&cause, self.param_env).normalize(xform_ret_ty); - xform_ret_ty = normalized_xform_ret_ty; - debug!("xform_ret_ty after normalization: {:?}", xform_ret_ty); - // Evaluate those obligations to see if they might possibly hold. - for o in normalization_obligations { - 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), - )); - } - } + if !matches!(probe.kind, InherentImplCandidate(_)) { + xform_ret_ty = ocx.normalize(&cause, self.param_env, xform_ret_ty); } debug!("comparing return_ty {:?} with xform ret ty {:?}", return_ty, xform_ret_ty); - if let ProbeResult::Match = result - && self - .at(&ObligationCause::dummy(), self.param_env) - .sup(DefineOpaqueTypes::Yes, return_ty, xform_ret_ty) - .is_err() - { - result = ProbeResult::BadReturnType; + match ocx.sup(cause, self.param_env, return_ty, xform_ret_ty) { + Ok(()) => {} + Err(_) => { + result = ProbeResult::BadReturnType; + } } + + // Evaluate those obligations to see if they might possibly hold. + for error in ocx.select_where_possible() { + result = ProbeResult::NoMatch; + possibly_unsatisfied_predicates.push(( + error.obligation.predicate, + Some(error.root_obligation.predicate) + .filter(|predicate| *predicate != error.obligation.predicate), + Some(error.root_obligation.cause), + )); + } + } + + // Previously, method probe used `evaluate_predicate` to determine if a predicate + // was impossible to satisfy. This did a leak check, so we must also do a leak + // check here to prevent backwards-incompatible ambiguity being introduced. See + // `tests/ui/methods/leak-check-disquality.rs` for a simple example of when this + // may happen. + if let Err(_) = self.leak_check(outer_universe, Some(snapshot)) { + result = ProbeResult::NoMatch; } result @@ -1881,12 +1716,6 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { self.tcx.instantiate_bound_regions_with_erased(xform_fn_sig) } - /// Gets the type of an impl and generate generic parameters with inference vars. - fn impl_ty_and_args(&self, impl_def_id: DefId) -> (Ty<'tcx>, GenericArgsRef<'tcx>) { - let args = self.fresh_args_for_item(self.span, impl_def_id); - (self.tcx.type_of(impl_def_id).instantiate(self.tcx, args), args) - } - /// Determine if the given associated item type is relevant in the current context. fn is_relevant_kind_for_mode(&self, kind: ty::AssocKind) -> bool { match (self.mode, kind) { @@ -2008,10 +1837,10 @@ impl<'tcx> Candidate<'tcx> { Pick { item: self.item, kind: match self.kind { - InherentImplCandidate(..) => InherentImplPick, - ObjectCandidate => ObjectPick, + InherentImplCandidate(_) => InherentImplPick, + ObjectCandidate(_) => ObjectPick, TraitCandidate(_) => TraitPick, - WhereClauseCandidate(ref trait_ref) => { + WhereClauseCandidate(trait_ref) => { // Only trait derived from where-clauses should // appear here, so they should not contain any // inference variables or other artifacts. This @@ -2022,7 +1851,7 @@ impl<'tcx> Candidate<'tcx> { && !trait_ref.skip_binder().args.has_placeholders() ); - WhereClausePick(*trait_ref) + WhereClausePick(trait_ref) } }, import_ids: self.import_ids.clone(), diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs index 9fbec174ce8..68c76dcf297 100644 --- a/compiler/rustc_trait_selection/src/traits/engine.rs +++ b/compiler/rustc_trait_selection/src/traits/engine.rs @@ -129,6 +129,19 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { .map(|infer_ok| self.register_infer_ok_obligations(infer_ok)) } + pub fn eq_no_opaques>( + &self, + cause: &ObligationCause<'tcx>, + param_env: ty::ParamEnv<'tcx>, + expected: T, + actual: T, + ) -> Result<(), TypeError<'tcx>> { + self.infcx + .at(cause, param_env) + .eq(DefineOpaqueTypes::No, expected, actual) + .map(|infer_ok| self.register_infer_ok_obligations(infer_ok)) + } + /// Checks whether `expected` is a subtype of `actual`: `expected <: actual`. pub fn sub>( &self, diff --git a/tests/ui/derives/issue-91550.stderr b/tests/ui/derives/issue-91550.stderr index 9e171896718..4d637c97283 100644 --- a/tests/ui/derives/issue-91550.stderr +++ b/tests/ui/derives/issue-91550.stderr @@ -2,15 +2,13 @@ error[E0599]: the method `insert` exists for struct `HashSet`, but its tr --> $DIR/issue-91550.rs:8:8 | LL | struct Value(u32); - | ------------ doesn't satisfy `Value: Eq`, `Value: Hash` or `Value: PartialEq` + | ------------ doesn't satisfy `Value: Eq` or `Value: Hash` ... LL | hs.insert(Value(0)); | ^^^^^^ | = note: the following trait bounds were not satisfied: `Value: Eq` - `Value: PartialEq` - which is required by `Value: Eq` `Value: Hash` help: consider annotating `Value` with `#[derive(Eq, Hash, PartialEq)]` | @@ -22,7 +20,7 @@ error[E0599]: the method `use_eq` exists for struct `Object`, but its --> $DIR/issue-91550.rs:26:9 | LL | pub struct NoDerives; - | -------------------- doesn't satisfy `NoDerives: Eq` or `NoDerives: PartialEq` + | -------------------- doesn't satisfy `NoDerives: Eq` LL | LL | struct Object(T); | ---------------- method `use_eq` not found for this struct @@ -37,9 +35,6 @@ LL | impl Object { | ^^ --------- | | | unsatisfied trait bound introduced here - = note: the following trait bounds were not satisfied: - `NoDerives: PartialEq` - which is required by `NoDerives: Eq` help: consider annotating `NoDerives` with `#[derive(Eq, PartialEq)]` | LL + #[derive(Eq, PartialEq)] @@ -50,7 +45,7 @@ error[E0599]: the method `use_ord` exists for struct `Object`, but it --> $DIR/issue-91550.rs:27:9 | LL | pub struct NoDerives; - | -------------------- doesn't satisfy `NoDerives: Eq`, `NoDerives: Ord`, `NoDerives: PartialEq` or `NoDerives: PartialOrd` + | -------------------- doesn't satisfy `NoDerives: Ord` LL | LL | struct Object(T); | ---------------- method `use_ord` not found for this struct @@ -65,13 +60,6 @@ LL | impl Object { | ^^^ --------- | | | unsatisfied trait bound introduced here - = note: the following trait bounds were not satisfied: - `NoDerives: PartialOrd` - which is required by `NoDerives: Ord` - `NoDerives: PartialEq` - which is required by `NoDerives: Ord` - `NoDerives: Eq` - which is required by `NoDerives: Ord` help: consider annotating `NoDerives` with `#[derive(Eq, Ord, PartialEq, PartialOrd)]` | LL + #[derive(Eq, Ord, PartialEq, PartialOrd)] @@ -82,7 +70,7 @@ error[E0599]: the method `use_ord_and_partial_ord` exists for struct `Object $DIR/issue-91550.rs:28:9 | LL | pub struct NoDerives; - | -------------------- doesn't satisfy `NoDerives: Eq`, `NoDerives: Ord`, `NoDerives: PartialEq` or `NoDerives: PartialOrd` + | -------------------- doesn't satisfy `NoDerives: Ord` or `NoDerives: PartialOrd` LL | LL | struct Object(T); | ---------------- method `use_ord_and_partial_ord` not found for this struct @@ -100,13 +88,6 @@ LL | impl Object { | | | | | unsatisfied trait bound introduced here | unsatisfied trait bound introduced here - = note: the following trait bounds were not satisfied: - `NoDerives: PartialEq` - which is required by `NoDerives: Ord` - `NoDerives: Eq` - which is required by `NoDerives: Ord` - `NoDerives: PartialEq` - which is required by `NoDerives: PartialOrd` help: consider annotating `NoDerives` with `#[derive(Eq, Ord, PartialEq, PartialOrd)]` | LL + #[derive(Eq, Ord, PartialEq, PartialOrd)] diff --git a/tests/ui/impl-trait/issues/issue-62742.rs b/tests/ui/impl-trait/issues/issue-62742.rs index 11a75737e55..bd48c51c065 100644 --- a/tests/ui/impl-trait/issues/issue-62742.rs +++ b/tests/ui/impl-trait/issues/issue-62742.rs @@ -3,7 +3,7 @@ use std::marker::PhantomData; fn _alias_check() { WrongImpl::foo(0i32); //~^ ERROR the trait bound `RawImpl<_>: Raw<_>` is not satisfied - //~| ERROR the trait bound `RawImpl<_>: Raw<_>` is not satisfied + //~| ERROR the function or associated item `foo` exists for struct `SafeImpl<_, RawImpl<_>>`, but its trait bounds were not satisfied WrongImpl::<()>::foo(0i32); //~^ ERROR the trait bound `RawImpl<()>: Raw<()>` is not satisfied //~| ERROR trait bounds were not satisfied diff --git a/tests/ui/impl-trait/issues/issue-62742.stderr b/tests/ui/impl-trait/issues/issue-62742.stderr index 9ec581c231b..f6798f55a47 100644 --- a/tests/ui/impl-trait/issues/issue-62742.stderr +++ b/tests/ui/impl-trait/issues/issue-62742.stderr @@ -1,30 +1,27 @@ -error[E0277]: the trait bound `RawImpl<_>: Raw<_>` is not satisfied - --> $DIR/issue-62742.rs:4:5 +error[E0599]: the function or associated item `foo` exists for struct `SafeImpl<_, RawImpl<_>>`, but its trait bounds were not satisfied + --> $DIR/issue-62742.rs:4:16 | LL | WrongImpl::foo(0i32); - | ^^^^^^^^^^^^^^^^^^^^ the trait `Raw<_>` is not implemented for `RawImpl<_>` + | ^^^ function or associated item cannot be called on `SafeImpl<_, RawImpl<_>>` due to unsatisfied trait bounds +... +LL | pub struct RawImpl(PhantomData); + | --------------------- doesn't satisfy `RawImpl<_>: Raw<_>` +... +LL | pub struct SafeImpl>(PhantomData<(A, T)>); + | ----------------------------------------- function or associated item `foo` not found for this struct | - = help: the trait `Raw<[_]>` is implemented for `RawImpl<_>` -note: required by a bound in `SafeImpl::::foo` +note: trait bound `RawImpl<_>: Raw<_>` was not satisfied --> $DIR/issue-62742.rs:29:20 | LL | impl> SafeImpl { - | ^^^^^^ required by this bound in `SafeImpl::::foo` -LL | pub fn foo(value: A::Value) {} - | --- required by a bound in this associated function - -error[E0277]: the trait bound `RawImpl<_>: Raw<_>` is not satisfied - --> $DIR/issue-62742.rs:4:5 + | ^^^^^^ -------------- + | | + | unsatisfied trait bound introduced here +note: the trait `Raw` must be implemented + --> $DIR/issue-62742.rs:13:1 | -LL | WrongImpl::foo(0i32); - | ^^^^^^^^^ the trait `Raw<_>` is not implemented for `RawImpl<_>` - | - = help: the trait `Raw<[_]>` is implemented for `RawImpl<_>` -note: required by a bound in `SafeImpl` - --> $DIR/issue-62742.rs:27:35 - | -LL | pub struct SafeImpl>(PhantomData<(A, T)>); - | ^^^^^^ required by this bound in `SafeImpl` +LL | pub trait Raw { + | ^^^^^^^^^^^^^^^^^^^^^^^^ error[E0599]: the function or associated item `foo` exists for struct `SafeImpl<(), RawImpl<()>>`, but its trait bounds were not satisfied --> $DIR/issue-62742.rs:7:22 @@ -51,6 +48,19 @@ note: the trait `Raw` must be implemented LL | pub trait Raw { | ^^^^^^^^^^^^^^^^^^^^^^^^ +error[E0277]: the trait bound `RawImpl<_>: Raw<_>` is not satisfied + --> $DIR/issue-62742.rs:4:5 + | +LL | WrongImpl::foo(0i32); + | ^^^^^^^^^ the trait `Raw<_>` is not implemented for `RawImpl<_>` + | + = help: the trait `Raw<[_]>` is implemented for `RawImpl<_>` +note: required by a bound in `SafeImpl` + --> $DIR/issue-62742.rs:27:35 + | +LL | pub struct SafeImpl>(PhantomData<(A, T)>); + | ^^^^^^ required by this bound in `SafeImpl` + error[E0277]: the trait bound `RawImpl<()>: Raw<()>` is not satisfied --> $DIR/issue-62742.rs:7:5 | diff --git a/tests/ui/impl-trait/issues/issue-84073.rs b/tests/ui/impl-trait/issues/issue-84073.rs index 85d9d461fd9..f2f1835dc34 100644 --- a/tests/ui/impl-trait/issues/issue-84073.rs +++ b/tests/ui/impl-trait/issues/issue-84073.rs @@ -29,5 +29,6 @@ where } fn main() { - Race::new(|race| race.when()); //~ ERROR overflow assigning `_` to `Option<_>` + Race::new(|race| race.when()); + //~^ ERROR the method `when` exists for struct `RaceBuilder<_, Never<_>>`, but its trait bounds were not satisfied } diff --git a/tests/ui/impl-trait/issues/issue-84073.stderr b/tests/ui/impl-trait/issues/issue-84073.stderr index ab119a8a4f4..eeb23b13081 100644 --- a/tests/ui/impl-trait/issues/issue-84073.stderr +++ b/tests/ui/impl-trait/issues/issue-84073.stderr @@ -1,9 +1,29 @@ -error[E0275]: overflow assigning `_` to `Option<_>` - --> $DIR/issue-84073.rs:32:22 +error[E0599]: the method `when` exists for struct `RaceBuilder<_, Never<_>>`, but its trait bounds were not satisfied + --> $DIR/issue-84073.rs:32:27 | +LL | pub struct Never(PhantomData); + | ------------------- doesn't satisfy `Never<_>: StatefulFuture>` +... +LL | pub struct RaceBuilder { + | ---------------------------- method `when` not found for this struct +... LL | Race::new(|race| race.when()); - | ^^^^ + | ^^^^ method cannot be called on `RaceBuilder<_, Never<_>>` due to unsatisfied trait bounds + | +note: trait bound `Never<_>: StatefulFuture>` was not satisfied + --> $DIR/issue-84073.rs:14:8 + | +LL | impl RaceBuilder + | ----------------- +LL | where +LL | F: StatefulFuture>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound introduced here +note: the trait `StatefulFuture` must be implemented + --> $DIR/issue-84073.rs:3:1 + | +LL | pub trait StatefulFuture {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0275`. +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr b/tests/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr index 84247a42704..0468e0522d1 100644 --- a/tests/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr +++ b/tests/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr @@ -6,6 +6,7 @@ LL | let _result = &Some(42).as_deref(); | = note: the following trait bounds were not satisfied: `{integer}: Deref` + which is required by `<{integer} as Deref>::Target = _` error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr b/tests/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr index bf05ab5665c..cf4e866901c 100644 --- a/tests/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr +++ b/tests/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr @@ -6,6 +6,7 @@ LL | let _result = &mut Some(42).as_deref_mut(); | = note: the following trait bounds were not satisfied: `{integer}: Deref` + which is required by `<{integer} as Deref>::Target = _` error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr b/tests/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr index ac744a6d3b6..0e3e7999044 100644 --- a/tests/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr +++ b/tests/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr @@ -6,6 +6,7 @@ LL | let _result = &Ok(42).as_deref(); | = note: the following trait bounds were not satisfied: `{integer}: Deref` + which is required by `<{integer} as Deref>::Target = _` error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr b/tests/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr index 688d2cf3486..43143db0da7 100644 --- a/tests/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr +++ b/tests/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr @@ -6,6 +6,7 @@ LL | let _result = &mut Ok(42).as_deref_mut(); | = note: the following trait bounds were not satisfied: `{integer}: Deref` + which is required by `<{integer} as Deref>::Target = _` error: aborting due to 1 previous error diff --git a/tests/ui/methods/fulfillment-disqualifies-method.rs b/tests/ui/methods/fulfillment-disqualifies-method.rs new file mode 100644 index 00000000000..639e1c7fc5c --- /dev/null +++ b/tests/ui/methods/fulfillment-disqualifies-method.rs @@ -0,0 +1,32 @@ +// Tests that using fulfillment in the trait solver means that we detect that a +// method is impossible, leading to no ambiguity. +//@ check-pass +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +#[derive(Default)] +struct W(A, B); + +trait Constrain { + type Output; +} + +impl Constrain for i32 { + type Output = u32; +} + +trait Impossible {} + +impl W where A: Constrain, B: Impossible { + fn method(&self) {} +} + +impl W { + fn method(&self) {} +} + +fn main() { + let w: W = W::default(); + w.method(); +} diff --git a/tests/ui/methods/leak-check-disquality.rs b/tests/ui/methods/leak-check-disquality.rs new file mode 100644 index 00000000000..d3b7dd4b807 --- /dev/null +++ b/tests/ui/methods/leak-check-disquality.rs @@ -0,0 +1,26 @@ +// Tests that using fulfillment in the trait solver means that we detect that a +// method is impossible, leading to no ambiguity. +//@ check-pass +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +struct W(Option, Option); + +impl<'a> W { + fn method(&self) {} +} + +trait Leak {} +impl Leak for T {} + +impl W { + fn method(&self) {} +} + +fn test<'a>() { + let x: W = W(None, None); + x.method(); +} + +fn main() {} diff --git a/tests/ui/mismatched_types/issue-36053-2.stderr b/tests/ui/mismatched_types/issue-36053-2.stderr index ffaa276b62e..5b8332016de 100644 --- a/tests/ui/mismatched_types/issue-36053-2.stderr +++ b/tests/ui/mismatched_types/issue-36053-2.stderr @@ -21,14 +21,16 @@ error[E0599]: the method `count` exists for struct `Filter>, {cl LL | once::<&str>("str").fuse().filter(|a: &str| true).count(); | --------- ^^^^^ method cannot be called due to unsatisfied trait bounds | | - | doesn't satisfy `<_ as FnOnce<(&&str,)>>::Output = bool` or `_: FnMut<(&&str,)>` + | doesn't satisfy `_: FnMut<(&&str,)>` or `_: FnOnce<(&&str,)>` | = note: the following trait bounds were not satisfied: - `<{closure@$DIR/issue-36053-2.rs:7:39: 7:48} as FnOnce<(&&str,)>>::Output = bool` - which is required by `Filter>, {closure@$DIR/issue-36053-2.rs:7:39: 7:48}>: Iterator` `{closure@$DIR/issue-36053-2.rs:7:39: 7:48}: FnMut<(&&str,)>` which is required by `Filter>, {closure@$DIR/issue-36053-2.rs:7:39: 7:48}>: Iterator` - `Filter>, {closure@$DIR/issue-36053-2.rs:7:39: 7:48}>: Iterator` + `{closure@$DIR/issue-36053-2.rs:7:39: 7:48}: FnOnce<(&&str,)>` + which is required by `Filter>, {closure@$DIR/issue-36053-2.rs:7:39: 7:48}>: Iterator` + `{closure@$DIR/issue-36053-2.rs:7:39: 7:48}: FnMut<(&&str,)>` + which is required by `&mut Filter>, {closure@$DIR/issue-36053-2.rs:7:39: 7:48}>: Iterator` + `{closure@$DIR/issue-36053-2.rs:7:39: 7:48}: FnOnce<(&&str,)>` which is required by `&mut Filter>, {closure@$DIR/issue-36053-2.rs:7:39: 7:48}>: Iterator` error: aborting due to 2 previous errors diff --git a/tests/ui/missing-trait-bounds/issue-35677.stderr b/tests/ui/missing-trait-bounds/issue-35677.stderr index f73bff51e7a..3bfdd4da6da 100644 --- a/tests/ui/missing-trait-bounds/issue-35677.stderr +++ b/tests/ui/missing-trait-bounds/issue-35677.stderr @@ -6,8 +6,6 @@ LL | this.is_subset(other) | = note: the following trait bounds were not satisfied: `T: Eq` - `T: PartialEq` - which is required by `T: Eq` `T: Hash` help: consider restricting the type parameters to satisfy the trait bounds | diff --git a/tests/ui/nll/issue-57362-2.rs b/tests/ui/nll/issue-57362-2.rs index a0b0ea1d038..bc0d0f5291f 100644 --- a/tests/ui/nll/issue-57362-2.rs +++ b/tests/ui/nll/issue-57362-2.rs @@ -19,7 +19,8 @@ impl<'a> X for fn(&'a ()) { } fn g() { - let x = ::make_g(); //~ ERROR the function + let x = ::make_g(); + //~^ ERROR no function or associated item named `make_g` found for fn pointer `for<'a> fn(&'a ())` in the current scope } fn main() {} diff --git a/tests/ui/nll/issue-57362-2.stderr b/tests/ui/nll/issue-57362-2.stderr index 57477f5341e..a78c96dbd0d 100644 --- a/tests/ui/nll/issue-57362-2.stderr +++ b/tests/ui/nll/issue-57362-2.stderr @@ -1,11 +1,9 @@ -error[E0599]: the function or associated item `make_g` exists for fn pointer `fn(&())`, but its trait bounds were not satisfied +error[E0599]: no function or associated item named `make_g` found for fn pointer `for<'a> fn(&'a ())` in the current scope --> $DIR/issue-57362-2.rs:22:25 | LL | let x = ::make_g(); - | ^^^^^^ function or associated item cannot be called on `fn(&())` due to unsatisfied trait bounds + | ^^^^^^ function or associated item not found in `fn(&())` | - = note: the following trait bounds were not satisfied: - `for<'a> fn(&'a ()): X` = help: items from traits can only be used if the trait is implemented and in scope note: `X` defines an item `make_g`, perhaps you need to implement it --> $DIR/issue-57362-2.rs:8:1 diff --git a/tests/ui/nll/issue-57642-higher-ranked-subtype.rs b/tests/ui/nll/issue-57642-higher-ranked-subtype.rs index eba859cde22..69187cab342 100644 --- a/tests/ui/nll/issue-57642-higher-ranked-subtype.rs +++ b/tests/ui/nll/issue-57642-higher-ranked-subtype.rs @@ -28,7 +28,8 @@ impl Y for fn(T) { } fn higher_ranked_region_has_lost_its_binder() { - let x = ::make_g(); //~ ERROR the function + let x = ::make_g(); + //~^ ERROR no function or associated item named `make_g` found for fn pointer `for<'a> fn(&'a ())` in the current scope } fn magical() { diff --git a/tests/ui/nll/issue-57642-higher-ranked-subtype.stderr b/tests/ui/nll/issue-57642-higher-ranked-subtype.stderr index d1e94bc702c..998d06b7706 100644 --- a/tests/ui/nll/issue-57642-higher-ranked-subtype.stderr +++ b/tests/ui/nll/issue-57642-higher-ranked-subtype.stderr @@ -1,11 +1,9 @@ -error[E0599]: the function or associated item `make_g` exists for fn pointer `fn(&())`, but its trait bounds were not satisfied +error[E0599]: no function or associated item named `make_g` found for fn pointer `for<'a> fn(&'a ())` in the current scope --> $DIR/issue-57642-higher-ranked-subtype.rs:31:25 | LL | let x = ::make_g(); - | ^^^^^^ function or associated item cannot be called on `fn(&())` due to unsatisfied trait bounds + | ^^^^^^ function or associated item not found in `fn(&())` | - = note: the following trait bounds were not satisfied: - `for<'a> fn(&'a ()): X` = help: items from traits can only be used if the trait is implemented and in scope note: `X` defines an item `make_g`, perhaps you need to implement it --> $DIR/issue-57642-higher-ranked-subtype.rs:4:1 @@ -14,7 +12,7 @@ LL | trait X { | ^^^^^^^ error[E0599]: no function or associated item named `make_f` found for fn pointer `for<'a> fn(&'a ())` in the current scope - --> $DIR/issue-57642-higher-ranked-subtype.rs:35:25 + --> $DIR/issue-57642-higher-ranked-subtype.rs:36:25 | LL | let x = ::make_f(); | ^^^^^^ function or associated item not found in `fn(&())` diff --git a/tests/ui/resolve/issue-85671.rs b/tests/ui/resolve/issue-85671.rs index 54db03f774e..ac001cebda7 100644 --- a/tests/ui/resolve/issue-85671.rs +++ b/tests/ui/resolve/issue-85671.rs @@ -1,5 +1,3 @@ -//@ check-pass - // Some trait with a function that returns a slice: pub trait AsSlice { type Element; @@ -24,6 +22,7 @@ impl A { Self: AsSlice, { self.as_ref_a().as_ref_a(); + //~^ ERROR no method named `as_ref_a` found for struct `A<&[Coef]>` in the current scope } pub fn as_ref_a(&self) -> A<&[::Element]> diff --git a/tests/ui/resolve/issue-85671.stderr b/tests/ui/resolve/issue-85671.stderr new file mode 100644 index 00000000000..0571e600197 --- /dev/null +++ b/tests/ui/resolve/issue-85671.stderr @@ -0,0 +1,17 @@ +error[E0599]: no method named `as_ref_a` found for struct `A<&[Coef]>` in the current scope + --> $DIR/issue-85671.rs:24:25 + | +LL | pub struct A(Cont); + | ------------------ method `as_ref_a` not found for this struct +... +LL | self.as_ref_a().as_ref_a(); + | ---- ^^^^^^^^ method not found in `A<&[Coef]>` + | | + | method `as_ref_a` is available on `&A` + | + = note: the method was found for + - `A` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/suggestions/derive-trait-for-method-call.stderr b/tests/ui/suggestions/derive-trait-for-method-call.stderr index 9d6d29ec74e..ae3a0391eea 100644 --- a/tests/ui/suggestions/derive-trait-for-method-call.stderr +++ b/tests/ui/suggestions/derive-trait-for-method-call.stderr @@ -74,22 +74,30 @@ LL | struct Struct { error[E0599]: the method `test` exists for struct `Foo, Instant>`, but its trait bounds were not satisfied --> $DIR/derive-trait-for-method-call.rs:40:15 | +LL | enum Enum { + | --------- doesn't satisfy `Enum: Clone` +... LL | struct Foo (X, Y); | ---------------- method `test` not found for this struct ... LL | let y = x.test(); | ^^^^ method cannot be called on `Foo, Instant>` due to unsatisfied trait bounds | -note: the following trait bounds were not satisfied: - `Instant: Default` - `Vec: Clone` - --> $DIR/derive-trait-for-method-call.rs:20:9 +note: trait bound `Instant: Default` was not satisfied + --> $DIR/derive-trait-for-method-call.rs:20:40 | LL | impl Foo { - | ^^^^^ ^^^^^^^ --------- - | | | - | | unsatisfied trait bound introduced here - | unsatisfied trait bound introduced here + | ^^^^^^^ --------- + | | + | unsatisfied trait bound introduced here + = note: the following trait bounds were not satisfied: + `Enum: Clone` + which is required by `Vec: Clone` +help: consider annotating `Enum` with `#[derive(Clone)]` + | +LL + #[derive(Clone)] +LL | enum Enum { + | error: aborting due to 3 previous errors diff --git a/tests/ui/traits/alias/issue-108132-unmet-trait-alias-bound-on-generic-impl.stderr b/tests/ui/traits/alias/issue-108132-unmet-trait-alias-bound-on-generic-impl.stderr index 74526b4dbc1..49a4db7491e 100644 --- a/tests/ui/traits/alias/issue-108132-unmet-trait-alias-bound-on-generic-impl.stderr +++ b/tests/ui/traits/alias/issue-108132-unmet-trait-alias-bound-on-generic-impl.stderr @@ -12,13 +12,6 @@ note: trait bound `(): Iterator` was not satisfied | LL | trait IteratorAlias = Iterator; | ------------- ^^^^^^^^ unsatisfied trait bound introduced here -note: trait bound `(): IteratorAlias` was not satisfied - --> $DIR/issue-108132-unmet-trait-alias-bound-on-generic-impl.rs:9:9 - | -LL | impl Foo { - | ^^^^^^^^^^^^^ ------ - | | - | unsatisfied trait bound introduced here error: aborting due to 1 previous error diff --git a/tests/ui/traits/method-on-unbounded-type-param.stderr b/tests/ui/traits/method-on-unbounded-type-param.stderr index 4d968e7bee1..38537619365 100644 --- a/tests/ui/traits/method-on-unbounded-type-param.stderr +++ b/tests/ui/traits/method-on-unbounded-type-param.stderr @@ -70,7 +70,7 @@ LL | x.cmp(&x); which is required by `Box: Iterator` `dyn T: Ord` which is required by `Box: Ord` - `Box: Iterator` + `dyn T: Iterator` which is required by `&mut Box: Iterator` `dyn T: Iterator` which is required by `&mut dyn T: Iterator` diff --git a/tests/ui/traits/track-obligations.stderr b/tests/ui/traits/track-obligations.stderr index 822fc91e43f..141f565077a 100644 --- a/tests/ui/traits/track-obligations.stderr +++ b/tests/ui/traits/track-obligations.stderr @@ -2,7 +2,10 @@ error[E0599]: the method `check` exists for struct `Client<()>`, but its trait b --> $DIR/track-obligations.rs:83:16 | LL | struct ALayer(C); - | ---------------- doesn't satisfy `<_ as Layer<()>>::Service = as ParticularServiceLayer<()>>::Service` or `ALayer<()>: ParticularServiceLayer<()>` + | ---------------- doesn't satisfy `ALayer<()>: ParticularServiceLayer<()>` +... +LL | struct AService; + | --------------- doesn't satisfy `>::Response = Res` ... LL | struct Client(C); | ---------------- method `check` not found for this struct @@ -10,27 +13,14 @@ LL | struct Client(C); LL | Client(()).check(); | ^^^^^ method cannot be called on `Client<()>` due to unsatisfied trait bounds | -note: trait bound ` as Layer<()>>::Service = as ParticularServiceLayer<()>>::Service` was not satisfied - --> $DIR/track-obligations.rs:35:14 +note: trait bound `>::Response = Res` was not satisfied + --> $DIR/track-obligations.rs:24:21 | -LL | pub trait ParticularServiceLayer: - | ---------------------- -LL | Layer>::Service> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound introduced here -note: trait bound `ALayer<()>: ParticularServiceLayer<()>` was not satisfied - --> $DIR/track-obligations.rs:71:16 - | -LL | impl Client - | --------- +LL | impl ParticularService for T + | ----------------- - LL | where -LL | ALayer: ParticularServiceLayer, - | ^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound introduced here -note: the trait `ParticularServiceLayer` must be implemented - --> $DIR/track-obligations.rs:34:1 - | -LL | / pub trait ParticularServiceLayer: -LL | | Layer>::Service> - | |____________________________________________________________________^ +LL | T: Service, + | ^^^^^^^^^^^^^^ unsatisfied trait bound introduced here error[E0271]: type mismatch resolving `>::Response == Res` --> $DIR/track-obligations.rs:87:11 diff --git a/tests/ui/typeck/issue-31173.stderr b/tests/ui/typeck/issue-31173.stderr index 0983147a5f0..5fee16b5e89 100644 --- a/tests/ui/typeck/issue-31173.stderr +++ b/tests/ui/typeck/issue-31173.stderr @@ -39,7 +39,7 @@ LL | | .collect(); = note: the following trait bounds were not satisfied: `, {closure@$DIR/issue-31173.rs:7:21: 7:25}> as Iterator>::Item = &_` which is required by `Cloned, {closure@$DIR/issue-31173.rs:7:21: 7:25}>>: Iterator` - `Cloned, {closure@$DIR/issue-31173.rs:7:21: 7:25}>>: Iterator` + `, {closure@$DIR/issue-31173.rs:7:21: 7:25}> as Iterator>::Item = &_` which is required by `&mut Cloned, {closure@$DIR/issue-31173.rs:7:21: 7:25}>>: Iterator` error: aborting due to 2 previous errors