diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index d6d22a43fe0b8..618d90a07ec29 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 2876e0b49db22..8a7ebd6478b13 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -21,7 +21,7 @@ use rustc_middle::ty::fast_reject::{simplify_type, TreatParams}; use rustc_middle::ty::AssocItem; use rustc_middle::ty::GenericParamDefKind; use rustc_middle::ty::ToPredicate; -use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt, TypeFoldable, TypeVisitableExt}; +use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt}; use rustc_middle::ty::{GenericArgs, GenericArgsRef}; use rustc_session::lint; use rustc_span::def_id::DefId; @@ -37,7 +37,7 @@ 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 +99,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 +106,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,42 +703,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); - let impl_ty = impl_ty.instantiate(self.tcx, impl_args); - - 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, @@ -810,26 +738,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.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, ); }); @@ -860,19 +770,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![], @@ -929,27 +828,12 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } } - fn matches_return_type( - &self, - method: ty::AssocItem, - self_ty: Option>, - expected: Ty<'tcx>, - ) -> bool { + fn matches_return_type(&self, method: ty::AssocItem, expected: Ty<'tcx>) -> bool { match method.kind { ty::AssocKind::Fn => self.probe(|_| { let args = self.fresh_args_for_item(self.span, method.def_id); let fty = self.tcx.fn_sig(method.def_id).instantiate(self.tcx, args); let fty = self.instantiate_binder_with_fresh_vars(self.span, infer::FnCall, fty); - - if let Some(self_ty) = self_ty { - if self - .at(&ObligationCause::dummy(), self.param_env) - .sup(DefineOpaqueTypes::No, fty.inputs()[0], self_ty) - .is_err() - { - return false; - } - } self.can_sub(self.param_env, fty.output(), expected) }), _ => false, @@ -978,21 +862,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, ); @@ -1011,16 +885,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, ); @@ -1040,7 +909,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { .filter(|candidate| candidate_filter(&candidate.item)) .filter(|candidate| { if let Some(return_ty) = self.return_type { - self.matches_return_type(candidate.item, None, return_ty) + self.matches_return_type(candidate.item, return_ty) } else { true } @@ -1450,16 +1319,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) { @@ -1486,54 +1359,46 @@ 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 = traits::ObligationCause::misc(self.span, self.body_id); + let cause = &self.misc(self.span); + let ocx = ObligationCtxt::new(self); - let mut parent_pred = None; + let mut trait_predicate = None; + let (mut xform_self_ty, mut xform_ret_ty); - // 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: Make this `ocx.sup` once we define opaques more eagerly. + match self.at(cause, self.param_env).sup( + DefineOpaqueTypes::No, + xform_self_ty, + self_ty, + ) { + Ok(infer_ok) => { + ocx.register_infer_ok_obligations(infer_ok); + } + Err(err) => { + debug!("--> cannot relate self-types {:?}", err); + return ProbeResult::NoMatch; + } + } + // 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); // 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) @@ -1549,106 +1414,92 @@ 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) { + + let trait_ref = self.instantiate_binder_with_fresh_vars( + self.span, + infer::FnCall, + poly_trait_ref, + ); + let trait_ref = ocx.normalize(cause, self.param_env, 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); + // FIXME: Make this `ocx.sup` once we define opaques more eagerly. + match self.at(cause, self.param_env).sup( + DefineOpaqueTypes::No, + xform_self_ty, + self_ty, + ) { + Ok(infer_ok) => { + ocx.register_infer_ok_obligations(infer_ok); + } + Err(err) => { + debug!("--> cannot relate self-types {:?}", err); + return ProbeResult::NoMatch; + } + } + let obligation = traits::Obligation::new( + self.tcx, + cause.clone(), + self.param_env, + ty::Binder::dummy(trait_ref), + ); + + // FIXME(-Znext-solver): We only need this hack to deal with fatal + // overflow in the old solver. + if self.infcx.next_trait_solver() || self.infcx.predicate_may_hold(&obligation) + { + ocx.register_obligation(obligation); + } else { 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)); + if let Ok(Some(candidate)) = self.select_trait_candidate(trait_ref) { + for nested_obligation in candidate.nested_obligations() { + if !self.infcx.predicate_may_hold(&nested_obligation) { + possibly_unsatisfied_predicates.push(( + self.resolve_vars_if_possible(nested_obligation.predicate), + Some(self.resolve_vars_if_possible(obligation.predicate)), + Some(nested_obligation.cause), + )); } } - false - }) { - // This candidate's primary obligation doesn't even - // select - don't bother registering anything in - // `potentially_unsatisfied_predicates`. + } + } + + 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); + // FIXME: Make this `ocx.sup` once we define opaques more eagerly. + match self.at(cause, self.param_env).sup( + DefineOpaqueTypes::No, + xform_self_ty, + self_ty, + ) { + Ok(infer_ok) => { + ocx.register_infer_ok_obligations(infer_ok); + } + Err(err) => { + debug!("--> cannot relate self-types {:?}", err); return ProbeResult::NoMatch; } } @@ -1656,11 +1507,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), + )); } } @@ -1672,38 +1534,39 @@ 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 }) } @@ -1894,40 +1757,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { fn_sig.instantiate(self.tcx, args) }; - self.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::EarlyBinder>, GenericArgsRef<'tcx>) { - (self.tcx.type_of(impl_def_id), self.fresh_args_for_item(self.span, impl_def_id)) - } - - /// Replaces late-bound-regions bound by `value` with `'static` using - /// `ty::instantiate_bound_regions_with_erased`. - /// - /// This is only a reasonable thing to do during the *probe* phase, not the *confirm* phase, of - /// method matching. It is reasonable during the probe phase because we don't consider region - /// relationships at all. Therefore, we can just replace all the region variables with 'static - /// rather than creating fresh region variables. This is nice for two reasons: - /// - /// 1. Because the numbers of the region variables would otherwise be fairly unique to this - /// particular method call, it winds up creating fewer types overall, which helps for memory - /// usage. (Admittedly, this is a rather small effect, though measurable.) - /// - /// 2. It makes it easier to deal with higher-ranked trait bounds, because we can replace any - /// late-bound regions with 'static. Otherwise, if we were going to replace late-bound - /// regions with actual region variables as is proper, we'd have to ensure that the same - /// region got replaced with the same variable, which requires a bit more coordination - /// and/or tracking the instantiations and - /// so forth. - fn instantiate_bound_regions_with_erased(&self, value: ty::Binder<'tcx, T>) -> T - where - T: TypeFoldable>, - { - self.tcx.instantiate_bound_regions_with_erased(value) + self.tcx.instantiate_bound_regions_with_erased(xform_fn_sig) } /// Determine if the given associated item type is relevant in the current context. @@ -2051,10 +1881,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 @@ -2065,7 +1895,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/tests/ui/derives/issue-91550.stderr b/tests/ui/derives/issue-91550.stderr index 9e17189671827..4d637c9728385 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/generic-associated-types/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.rs b/tests/ui/generic-associated-types/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.rs index 86da6ebfaaa42..d7dff329df1e6 100644 --- a/tests/ui/generic-associated-types/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.rs +++ b/tests/ui/generic-associated-types/issue-119942-unsatisified-gat-bound-during-assoc-ty-selection.rs @@ -29,5 +29,5 @@ where fn main() { let mut list = RcNode::::new(); - //~^ ERROR trait bounds were not satisfied + //~^ ERROR the variant or associated item `new` exists for enum `Node`, but its trait bounds were not satisfied } diff --git a/tests/ui/impl-trait/issues/issue-62742.rs b/tests/ui/impl-trait/issues/issue-62742.rs index 11a75737e5545..56c63a1daa867 100644 --- a/tests/ui/impl-trait/issues/issue-62742.rs +++ b/tests/ui/impl-trait/issues/issue-62742.rs @@ -1,12 +1,17 @@ use std::marker::PhantomData; -fn _alias_check() { +fn a() { WrongImpl::foo(0i32); - //~^ ERROR the trait bound `RawImpl<_>: Raw<_>` is not satisfied - //~| ERROR the trait bound `RawImpl<_>: Raw<_>` is not satisfied + //~^ ERROR overflow assigning `_` to `[_]` +} + +fn b() { WrongImpl::<()>::foo(0i32); //~^ ERROR the trait bound `RawImpl<()>: Raw<()>` is not satisfied //~| ERROR trait bounds were not satisfied +} + +fn c() { CorrectImpl::foo(0i32); } diff --git a/tests/ui/impl-trait/issues/issue-62742.stderr b/tests/ui/impl-trait/issues/issue-62742.stderr index 9ec581c231b7b..7a1bcfc70d54f 100644 --- a/tests/ui/impl-trait/issues/issue-62742.stderr +++ b/tests/ui/impl-trait/issues/issue-62742.stderr @@ -1,33 +1,11 @@ -error[E0277]: the trait bound `RawImpl<_>: Raw<_>` is not satisfied - --> $DIR/issue-62742.rs:4:5 +error[E0275]: overflow assigning `_` to `[_]` + --> $DIR/issue-62742.rs:4:16 | 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::::foo` - --> $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 - | -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[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 + --> $DIR/issue-62742.rs:9:22 | LL | WrongImpl::<()>::foo(0i32); | ^^^ function or associated item cannot be called on `SafeImpl<(), RawImpl<()>>` due to unsatisfied trait bounds @@ -39,20 +17,20 @@ LL | pub struct SafeImpl>(PhantomData<(A, T)>); | ----------------------------------------- function or associated item `foo` not found for this struct | note: trait bound `RawImpl<()>: Raw<()>` was not satisfied - --> $DIR/issue-62742.rs:29:20 + --> $DIR/issue-62742.rs:34:20 | LL | impl> SafeImpl { | ^^^^^^ -------------- | | | unsatisfied trait bound introduced here note: the trait `Raw` must be implemented - --> $DIR/issue-62742.rs:13:1 + --> $DIR/issue-62742.rs:18:1 | LL | pub trait Raw { | ^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `RawImpl<()>: Raw<()>` is not satisfied - --> $DIR/issue-62742.rs:7:5 + --> $DIR/issue-62742.rs:9:5 | LL | WrongImpl::<()>::foo(0i32); | ^^^^^^^^^^^^^^^ the trait `Raw<()>` is not implemented for `RawImpl<()>` @@ -60,12 +38,12 @@ LL | WrongImpl::<()>::foo(0i32); = help: the trait `Raw<[()]>` is implemented for `RawImpl<()>` = help: for that trait implementation, expected `[()]`, found `()` note: required by a bound in `SafeImpl` - --> $DIR/issue-62742.rs:27:35 + --> $DIR/issue-62742.rs:32:35 | LL | pub struct SafeImpl>(PhantomData<(A, T)>); | ^^^^^^ required by this bound in `SafeImpl` -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0277, E0599. -For more information about an error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0275, E0277, E0599. +For more information about an error, try `rustc --explain E0275`. diff --git a/tests/ui/impl-trait/issues/issue-84073.rs b/tests/ui/impl-trait/issues/issue-84073.rs index 85d9d461fd9ad..7acee44a722a4 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 overflow assigning `_` to `Option<_>` } diff --git a/tests/ui/impl-trait/issues/issue-84073.stderr b/tests/ui/impl-trait/issues/issue-84073.stderr index ab119a8a4f456..0f4c6e83fbe70 100644 --- a/tests/ui/impl-trait/issues/issue-84073.stderr +++ b/tests/ui/impl-trait/issues/issue-84073.stderr @@ -1,8 +1,8 @@ error[E0275]: overflow assigning `_` to `Option<_>` - --> $DIR/issue-84073.rs:32:22 + --> $DIR/issue-84073.rs:32:27 | LL | Race::new(|race| race.when()); - | ^^^^ + | ^^^^ 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 0000000000000..639e1c7fc5c02 --- /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 0000000000000..d3b7dd4b80719 --- /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/methods/self-type-is-sup-no-eq.rs b/tests/ui/methods/self-type-is-sup-no-eq.rs new file mode 100644 index 0000000000000..ec28b964a0518 --- /dev/null +++ b/tests/ui/methods/self-type-is-sup-no-eq.rs @@ -0,0 +1,24 @@ +//@ check-pass + +// Test that we use `sup` not `eq` during method probe, since this has an effect +// on the leak check. This is (conceptually) minimized from a crater run for +// `wrend 0.3.6`. + +use std::ops::Deref; + +struct A; + +impl Deref for A { + type Target = B; + + fn deref(&self) -> &::Target { todo!() } +} + +struct B(T); +impl B { + fn method(&self) {} +} + +fn main() { + A.method(); +} diff --git a/tests/ui/missing-trait-bounds/issue-35677.stderr b/tests/ui/missing-trait-bounds/issue-35677.stderr index f73bff51e7ad1..3bfdd4da6dac8 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 a0b0ea1d03893..664cdf89a3886 100644 --- a/tests/ui/nll/issue-57362-2.rs +++ b/tests/ui/nll/issue-57362-2.rs @@ -18,8 +18,10 @@ impl<'a> X for fn(&'a ()) { } } +// FIXME(@compiler-errors): This error message is less than helpful. 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 57477f5341ede..24787b990e312 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 - --> $DIR/issue-57362-2.rs:22:25 +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:23: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 eba859cde2206..69187cab34227 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 d1e94bc702cae..998d06b77065f 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/suggestions/derive-trait-for-method-call.stderr b/tests/ui/suggestions/derive-trait-for-method-call.stderr index 9d6d29ec74eec..ae3a0391eea24 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 74526b4dbc182..49a4db7491ed8 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/track-obligations.stderr b/tests/ui/traits/track-obligations.stderr index 822fc91e43fea..141f565077a5b 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 - | -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 +note: trait bound `>::Response = Res` was not satisfied + --> $DIR/track-obligations.rs:24:21 | -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