• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! Trait Resolution. See the [rustc dev guide] for more information on how this works.
2 //!
3 //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/resolution.html
4 
5 pub mod auto_trait;
6 pub(crate) mod coherence;
7 pub mod const_evaluatable;
8 mod engine;
9 pub mod error_reporting;
10 mod fulfill;
11 pub mod misc;
12 mod object_safety;
13 pub mod outlives_bounds;
14 pub mod project;
15 pub mod query;
16 #[cfg_attr(not(bootstrap), allow(hidden_glob_reexports))]
17 mod select;
18 mod specialize;
19 mod structural_match;
20 mod structural_normalize;
21 #[cfg_attr(not(bootstrap), allow(hidden_glob_reexports))]
22 mod util;
23 pub mod vtable;
24 pub mod wf;
25 
26 use crate::infer::outlives::env::OutlivesEnvironment;
27 use crate::infer::{InferCtxt, TyCtxtInferExt};
28 use crate::traits::error_reporting::TypeErrCtxtExt as _;
29 use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
30 use rustc_errors::ErrorGuaranteed;
31 use rustc_middle::query::Providers;
32 use rustc_middle::ty::fold::TypeFoldable;
33 use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt};
34 use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFolder, TypeSuperVisitable};
35 use rustc_middle::ty::{InternalSubsts, SubstsRef};
36 use rustc_span::def_id::DefId;
37 use rustc_span::Span;
38 
39 use std::fmt::Debug;
40 use std::ops::ControlFlow;
41 
42 pub(crate) use self::project::{needs_normalization, BoundVarReplacer, PlaceholderReplacer};
43 
44 pub use self::FulfillmentErrorCode::*;
45 pub use self::ImplSource::*;
46 pub use self::ObligationCauseCode::*;
47 pub use self::SelectionError::*;
48 
49 pub use self::coherence::{add_placeholder_note, orphan_check, overlapping_impls};
50 pub use self::coherence::{OrphanCheckErr, OverlapResult};
51 pub use self::engine::{ObligationCtxt, TraitEngineExt};
52 pub use self::fulfill::{FulfillmentContext, PendingPredicateObligation};
53 pub use self::object_safety::astconv_object_safety_violations;
54 pub use self::object_safety::is_vtable_safe_method;
55 pub use self::object_safety::MethodViolationCode;
56 pub use self::object_safety::ObjectSafetyViolation;
57 pub use self::project::NormalizeExt;
58 pub use self::project::{normalize_inherent_projection, normalize_projection_type};
59 pub use self::select::{EvaluationCache, SelectionCache, SelectionContext};
60 pub use self::select::{EvaluationResult, IntercrateAmbiguityCause, OverflowError};
61 pub use self::specialize::specialization_graph::FutureCompatOverlapError;
62 pub use self::specialize::specialization_graph::FutureCompatOverlapErrorKind;
63 pub use self::specialize::{
64     specialization_graph, translate_substs, translate_substs_with_cause, OverlapError,
65 };
66 pub use self::structural_match::search_for_structural_match_violation;
67 pub use self::structural_normalize::StructurallyNormalizeExt;
68 pub use self::util::elaborate;
69 pub use self::util::{
70     check_substs_compatible, supertrait_def_ids, supertraits, transitive_bounds,
71     transitive_bounds_that_define_assoc_item, SupertraitDefIds,
72 };
73 pub use self::util::{expand_trait_aliases, TraitAliasExpander};
74 pub use self::util::{get_vtable_index_of_object_method, impl_item_is_final, upcast_choices};
75 
76 pub use rustc_infer::traits::*;
77 
78 /// Whether to skip the leak check, as part of a future compatibility warning step.
79 ///
80 /// The "default" for skip-leak-check corresponds to the current
81 /// behavior (do not skip the leak check) -- not the behavior we are
82 /// transitioning into.
83 #[derive(Copy, Clone, PartialEq, Eq, Debug, Default)]
84 pub enum SkipLeakCheck {
85     Yes,
86     #[default]
87     No,
88 }
89 
90 impl SkipLeakCheck {
is_yes(self) -> bool91     fn is_yes(self) -> bool {
92         self == SkipLeakCheck::Yes
93     }
94 }
95 
96 /// The mode that trait queries run in.
97 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
98 pub enum TraitQueryMode {
99     /// Standard/un-canonicalized queries get accurate
100     /// spans etc. passed in and hence can do reasonable
101     /// error reporting on their own.
102     Standard,
103     /// Canonical queries get dummy spans and hence
104     /// must generally propagate errors to
105     /// pre-canonicalization callsites.
106     Canonical,
107 }
108 
109 /// Creates predicate obligations from the generic bounds.
110 #[instrument(level = "debug", skip(cause, param_env))]
predicates_for_generics<'tcx>( cause: impl Fn(usize, Span) -> ObligationCause<'tcx>, param_env: ty::ParamEnv<'tcx>, generic_bounds: ty::InstantiatedPredicates<'tcx>, ) -> impl Iterator<Item = PredicateObligation<'tcx>>111 pub fn predicates_for_generics<'tcx>(
112     cause: impl Fn(usize, Span) -> ObligationCause<'tcx>,
113     param_env: ty::ParamEnv<'tcx>,
114     generic_bounds: ty::InstantiatedPredicates<'tcx>,
115 ) -> impl Iterator<Item = PredicateObligation<'tcx>> {
116     generic_bounds.into_iter().enumerate().map(move |(idx, (clause, span))| Obligation {
117         cause: cause(idx, span),
118         recursion_depth: 0,
119         param_env,
120         predicate: clause.as_predicate(),
121     })
122 }
123 
124 /// Determines whether the type `ty` is known to meet `bound` and
125 /// returns true if so. Returns false if `ty` either does not meet
126 /// `bound` or is not known to meet bound (note that this is
127 /// conservative towards *no impl*, which is the opposite of the
128 /// `evaluate` methods).
type_known_to_meet_bound_modulo_regions<'tcx>( infcx: &InferCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>, def_id: DefId, ) -> bool129 pub fn type_known_to_meet_bound_modulo_regions<'tcx>(
130     infcx: &InferCtxt<'tcx>,
131     param_env: ty::ParamEnv<'tcx>,
132     ty: Ty<'tcx>,
133     def_id: DefId,
134 ) -> bool {
135     let trait_ref = ty::TraitRef::new(infcx.tcx, def_id, [ty]);
136     pred_known_to_hold_modulo_regions(infcx, param_env, trait_ref.without_const())
137 }
138 
139 /// FIXME(@lcnr): this function doesn't seem right and shouldn't exist?
140 ///
141 /// Ping me on zulip if you want to use this method and need help with finding
142 /// an appropriate replacement.
143 #[instrument(level = "debug", skip(infcx, param_env, pred), ret)]
pred_known_to_hold_modulo_regions<'tcx>( infcx: &InferCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, pred: impl ToPredicate<'tcx>, ) -> bool144 fn pred_known_to_hold_modulo_regions<'tcx>(
145     infcx: &InferCtxt<'tcx>,
146     param_env: ty::ParamEnv<'tcx>,
147     pred: impl ToPredicate<'tcx>,
148 ) -> bool {
149     let obligation = Obligation::new(infcx.tcx, ObligationCause::dummy(), param_env, pred);
150 
151     let result = infcx.evaluate_obligation_no_overflow(&obligation);
152     debug!(?result);
153 
154     if result.must_apply_modulo_regions() {
155         true
156     } else if result.may_apply() {
157         // Sometimes obligations are ambiguous because the recursive evaluator
158         // is not smart enough, so we fall back to fulfillment when we're not certain
159         // that an obligation holds or not. Even still, we must make sure that
160         // the we do no inference in the process of checking this obligation.
161         let goal = infcx.resolve_vars_if_possible((obligation.predicate, obligation.param_env));
162         infcx.probe(|_| {
163             let ocx = ObligationCtxt::new(infcx);
164             ocx.register_obligation(obligation);
165 
166             let errors = ocx.select_all_or_error();
167             match errors.as_slice() {
168                 // Only known to hold if we did no inference.
169                 [] => infcx.shallow_resolve(goal) == goal,
170 
171                 errors => {
172                     debug!(?errors);
173                     false
174                 }
175             }
176         })
177     } else {
178         false
179     }
180 }
181 
182 #[instrument(level = "debug", skip(tcx, elaborated_env))]
do_normalize_predicates<'tcx>( tcx: TyCtxt<'tcx>, cause: ObligationCause<'tcx>, elaborated_env: ty::ParamEnv<'tcx>, predicates: Vec<ty::Clause<'tcx>>, ) -> Result<Vec<ty::Clause<'tcx>>, ErrorGuaranteed>183 fn do_normalize_predicates<'tcx>(
184     tcx: TyCtxt<'tcx>,
185     cause: ObligationCause<'tcx>,
186     elaborated_env: ty::ParamEnv<'tcx>,
187     predicates: Vec<ty::Clause<'tcx>>,
188 ) -> Result<Vec<ty::Clause<'tcx>>, ErrorGuaranteed> {
189     let span = cause.span;
190     // FIXME. We should really... do something with these region
191     // obligations. But this call just continues the older
192     // behavior (i.e., doesn't cause any new bugs), and it would
193     // take some further refactoring to actually solve them. In
194     // particular, we would have to handle implied bounds
195     // properly, and that code is currently largely confined to
196     // regionck (though I made some efforts to extract it
197     // out). -nmatsakis
198     //
199     // @arielby: In any case, these obligations are checked
200     // by wfcheck anyway, so I'm not sure we have to check
201     // them here too, and we will remove this function when
202     // we move over to lazy normalization *anyway*.
203     let infcx = tcx.infer_ctxt().ignoring_regions().build();
204     let predicates = match fully_normalize(&infcx, cause, elaborated_env, predicates) {
205         Ok(predicates) => predicates,
206         Err(errors) => {
207             let reported = infcx.err_ctxt().report_fulfillment_errors(&errors);
208             return Err(reported);
209         }
210     };
211 
212     debug!("do_normalize_predicates: normalized predicates = {:?}", predicates);
213 
214     // We can use the `elaborated_env` here; the region code only
215     // cares about declarations like `'a: 'b`.
216     let outlives_env = OutlivesEnvironment::new(elaborated_env);
217 
218     // FIXME: It's very weird that we ignore region obligations but apparently
219     // still need to use `resolve_regions` as we need the resolved regions in
220     // the normalized predicates.
221     let errors = infcx.resolve_regions(&outlives_env);
222     if !errors.is_empty() {
223         tcx.sess.delay_span_bug(
224             span,
225             format!("failed region resolution while normalizing {elaborated_env:?}: {errors:?}"),
226         );
227     }
228 
229     match infcx.fully_resolve(predicates) {
230         Ok(predicates) => Ok(predicates),
231         Err(fixup_err) => {
232             // If we encounter a fixup error, it means that some type
233             // variable wound up unconstrained. I actually don't know
234             // if this can happen, and I certainly don't expect it to
235             // happen often, but if it did happen it probably
236             // represents a legitimate failure due to some kind of
237             // unconstrained variable.
238             //
239             // @lcnr: Let's still ICE here for now. I want a test case
240             // for that.
241             span_bug!(
242                 span,
243                 "inference variables in normalized parameter environment: {}",
244                 fixup_err
245             );
246         }
247     }
248 }
249 
250 // FIXME: this is gonna need to be removed ...
251 /// Normalizes the parameter environment, reporting errors if they occur.
252 #[instrument(level = "debug", skip(tcx))]
normalize_param_env_or_error<'tcx>( tcx: TyCtxt<'tcx>, unnormalized_env: ty::ParamEnv<'tcx>, cause: ObligationCause<'tcx>, ) -> ty::ParamEnv<'tcx>253 pub fn normalize_param_env_or_error<'tcx>(
254     tcx: TyCtxt<'tcx>,
255     unnormalized_env: ty::ParamEnv<'tcx>,
256     cause: ObligationCause<'tcx>,
257 ) -> ty::ParamEnv<'tcx> {
258     // I'm not wild about reporting errors here; I'd prefer to
259     // have the errors get reported at a defined place (e.g.,
260     // during typeck). Instead I have all parameter
261     // environments, in effect, going through this function
262     // and hence potentially reporting errors. This ensures of
263     // course that we never forget to normalize (the
264     // alternative seemed like it would involve a lot of
265     // manual invocations of this fn -- and then we'd have to
266     // deal with the errors at each of those sites).
267     //
268     // In any case, in practice, typeck constructs all the
269     // parameter environments once for every fn as it goes,
270     // and errors will get reported then; so outside of type inference we
271     // can be sure that no errors should occur.
272     let mut predicates: Vec<_> = util::elaborate(
273         tcx,
274         unnormalized_env.caller_bounds().into_iter().map(|predicate| {
275             if tcx.features().generic_const_exprs {
276                 return predicate;
277             }
278 
279             struct ConstNormalizer<'tcx>(TyCtxt<'tcx>);
280 
281             impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ConstNormalizer<'tcx> {
282                 fn interner(&self) -> TyCtxt<'tcx> {
283                     self.0
284                 }
285 
286                 fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> {
287                     // While it is pretty sus to be evaluating things with an empty param env, it
288                     // should actually be okay since without `feature(generic_const_exprs)` the only
289                     // const arguments that have a non-empty param env are array repeat counts. These
290                     // do not appear in the type system though.
291                     c.eval(self.0, ty::ParamEnv::empty())
292                 }
293             }
294 
295             // This whole normalization step is a hack to work around the fact that
296             // `normalize_param_env_or_error` is fundamentally broken from using an
297             // unnormalized param env with a trait solver that expects the param env
298             // to be normalized.
299             //
300             // When normalizing the param env we can end up evaluating obligations
301             // that have been normalized but can only be proven via a where clause
302             // which is still in its unnormalized form. example:
303             //
304             // Attempting to prove `T: Trait<<u8 as Identity>::Assoc>` in a param env
305             // with a `T: Trait<<u8 as Identity>::Assoc>` where clause will fail because
306             // we first normalize obligations before proving them so we end up proving
307             // `T: Trait<u8>`. Since lazy normalization is not implemented equating `u8`
308             // with `<u8 as Identity>::Assoc` fails outright so we incorrectly believe that
309             // we cannot prove `T: Trait<u8>`.
310             //
311             // The same thing is true for const generics- attempting to prove
312             // `T: Trait<ConstKind::Unevaluated(...)>` with the same thing as a where clauses
313             // will fail. After normalization we may be attempting to prove `T: Trait<4>` with
314             // the unnormalized where clause `T: Trait<ConstKind::Unevaluated(...)>`. In order
315             // for the obligation to hold `4` must be equal to `ConstKind::Unevaluated(...)`
316             // but as we do not have lazy norm implemented, equating the two consts fails outright.
317             //
318             // Ideally we would not normalize consts here at all but it is required for backwards
319             // compatibility. Eventually when lazy norm is implemented this can just be removed.
320             // We do not normalize types here as there is no backwards compatibility requirement
321             // for us to do so.
322             //
323             // FIXME(-Ztrait-solver=next): remove this hack since we have deferred projection equality
324             predicate.fold_with(&mut ConstNormalizer(tcx))
325         }),
326     )
327     .collect();
328 
329     debug!("normalize_param_env_or_error: elaborated-predicates={:?}", predicates);
330 
331     let elaborated_env = ty::ParamEnv::new(
332         tcx.mk_clauses(&predicates),
333         unnormalized_env.reveal(),
334         unnormalized_env.constness(),
335     );
336 
337     // HACK: we are trying to normalize the param-env inside *itself*. The problem is that
338     // normalization expects its param-env to be already normalized, which means we have
339     // a circularity.
340     //
341     // The way we handle this is by normalizing the param-env inside an unnormalized version
342     // of the param-env, which means that if the param-env contains unnormalized projections,
343     // we'll have some normalization failures. This is unfortunate.
344     //
345     // Lazy normalization would basically handle this by treating just the
346     // normalizing-a-trait-ref-requires-itself cycles as evaluation failures.
347     //
348     // Inferred outlives bounds can create a lot of `TypeOutlives` predicates for associated
349     // types, so to make the situation less bad, we normalize all the predicates *but*
350     // the `TypeOutlives` predicates first inside the unnormalized parameter environment, and
351     // then we normalize the `TypeOutlives` bounds inside the normalized parameter environment.
352     //
353     // This works fairly well because trait matching does not actually care about param-env
354     // TypeOutlives predicates - these are normally used by regionck.
355     let outlives_predicates: Vec<_> = predicates
356         .extract_if(|predicate| {
357             matches!(predicate.kind().skip_binder(), ty::ClauseKind::TypeOutlives(..))
358         })
359         .collect();
360 
361     debug!(
362         "normalize_param_env_or_error: predicates=(non-outlives={:?}, outlives={:?})",
363         predicates, outlives_predicates
364     );
365     let Ok(non_outlives_predicates) = do_normalize_predicates(
366         tcx,
367         cause.clone(),
368         elaborated_env,
369         predicates,
370     ) else {
371         // An unnormalized env is better than nothing.
372         debug!("normalize_param_env_or_error: errored resolving non-outlives predicates");
373         return elaborated_env;
374     };
375 
376     debug!("normalize_param_env_or_error: non-outlives predicates={:?}", non_outlives_predicates);
377 
378     // Not sure whether it is better to include the unnormalized TypeOutlives predicates
379     // here. I believe they should not matter, because we are ignoring TypeOutlives param-env
380     // predicates here anyway. Keeping them here anyway because it seems safer.
381     let outlives_env = non_outlives_predicates.iter().chain(&outlives_predicates).cloned();
382     let outlives_env = ty::ParamEnv::new(
383         tcx.mk_clauses_from_iter(outlives_env),
384         unnormalized_env.reveal(),
385         unnormalized_env.constness(),
386     );
387     let Ok(outlives_predicates) = do_normalize_predicates(
388         tcx,
389         cause,
390         outlives_env,
391         outlives_predicates,
392     ) else {
393         // An unnormalized env is better than nothing.
394         debug!("normalize_param_env_or_error: errored resolving outlives predicates");
395         return elaborated_env;
396     };
397     debug!("normalize_param_env_or_error: outlives predicates={:?}", outlives_predicates);
398 
399     let mut predicates = non_outlives_predicates;
400     predicates.extend(outlives_predicates);
401     debug!("normalize_param_env_or_error: final predicates={:?}", predicates);
402     ty::ParamEnv::new(
403         tcx.mk_clauses(&predicates),
404         unnormalized_env.reveal(),
405         unnormalized_env.constness(),
406     )
407 }
408 
409 /// Normalize a type and process all resulting obligations, returning any errors.
410 ///
411 /// FIXME(-Ztrait-solver=next): This should be replaced by `At::deeply_normalize`
412 /// which has the same behavior with the new solver. Because using a separate
413 /// fulfillment context worsens caching in the old solver, `At::deeply_normalize`
414 /// is still lazy with the old solver as it otherwise negatively impacts perf.
415 #[instrument(skip_all)]
fully_normalize<'tcx, T>( infcx: &InferCtxt<'tcx>, cause: ObligationCause<'tcx>, param_env: ty::ParamEnv<'tcx>, value: T, ) -> Result<T, Vec<FulfillmentError<'tcx>>> where T: TypeFoldable<TyCtxt<'tcx>>,416 pub fn fully_normalize<'tcx, T>(
417     infcx: &InferCtxt<'tcx>,
418     cause: ObligationCause<'tcx>,
419     param_env: ty::ParamEnv<'tcx>,
420     value: T,
421 ) -> Result<T, Vec<FulfillmentError<'tcx>>>
422 where
423     T: TypeFoldable<TyCtxt<'tcx>>,
424 {
425     let ocx = ObligationCtxt::new(infcx);
426     debug!(?value);
427     let normalized_value = ocx.normalize(&cause, param_env, value);
428     debug!(?normalized_value);
429     debug!("select_all_or_error start");
430     let errors = ocx.select_all_or_error();
431     if !errors.is_empty() {
432         return Err(errors);
433     }
434     debug!("select_all_or_error complete");
435     let resolved_value = infcx.resolve_vars_if_possible(normalized_value);
436     debug!(?resolved_value);
437     Ok(resolved_value)
438 }
439 
440 /// Normalizes the predicates and checks whether they hold in an empty environment. If this
441 /// returns true, then either normalize encountered an error or one of the predicates did not
442 /// hold. Used when creating vtables to check for unsatisfiable methods.
impossible_predicates<'tcx>(tcx: TyCtxt<'tcx>, predicates: Vec<ty::Clause<'tcx>>) -> bool443 pub fn impossible_predicates<'tcx>(tcx: TyCtxt<'tcx>, predicates: Vec<ty::Clause<'tcx>>) -> bool {
444     debug!("impossible_predicates(predicates={:?})", predicates);
445 
446     let infcx = tcx.infer_ctxt().build();
447     let param_env = ty::ParamEnv::reveal_all();
448     let ocx = ObligationCtxt::new(&infcx);
449     let predicates = ocx.normalize(&ObligationCause::dummy(), param_env, predicates);
450     for predicate in predicates {
451         let obligation = Obligation::new(tcx, ObligationCause::dummy(), param_env, predicate);
452         ocx.register_obligation(obligation);
453     }
454     let errors = ocx.select_all_or_error();
455 
456     let result = !errors.is_empty();
457     debug!("impossible_predicates = {:?}", result);
458     result
459 }
460 
subst_and_check_impossible_predicates<'tcx>( tcx: TyCtxt<'tcx>, key: (DefId, SubstsRef<'tcx>), ) -> bool461 fn subst_and_check_impossible_predicates<'tcx>(
462     tcx: TyCtxt<'tcx>,
463     key: (DefId, SubstsRef<'tcx>),
464 ) -> bool {
465     debug!("subst_and_check_impossible_predicates(key={:?})", key);
466 
467     let mut predicates = tcx.predicates_of(key.0).instantiate(tcx, key.1).predicates;
468 
469     // Specifically check trait fulfillment to avoid an error when trying to resolve
470     // associated items.
471     if let Some(trait_def_id) = tcx.trait_of_item(key.0) {
472         let trait_ref = ty::TraitRef::from_method(tcx, trait_def_id, key.1);
473         predicates.push(ty::Binder::dummy(trait_ref).to_predicate(tcx));
474     }
475 
476     predicates.retain(|predicate| !predicate.has_param());
477     let result = impossible_predicates(tcx, predicates);
478 
479     debug!("subst_and_check_impossible_predicates(key={:?}) = {:?}", key, result);
480     result
481 }
482 
483 /// Checks whether a trait's method is impossible to call on a given impl.
484 ///
485 /// This only considers predicates that reference the impl's generics, and not
486 /// those that reference the method's generics.
is_impossible_method(tcx: TyCtxt<'_>, (impl_def_id, trait_item_def_id): (DefId, DefId)) -> bool487 fn is_impossible_method(tcx: TyCtxt<'_>, (impl_def_id, trait_item_def_id): (DefId, DefId)) -> bool {
488     struct ReferencesOnlyParentGenerics<'tcx> {
489         tcx: TyCtxt<'tcx>,
490         generics: &'tcx ty::Generics,
491         trait_item_def_id: DefId,
492     }
493     impl<'tcx> ty::TypeVisitor<TyCtxt<'tcx>> for ReferencesOnlyParentGenerics<'tcx> {
494         type BreakTy = ();
495         fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
496             // If this is a parameter from the trait item's own generics, then bail
497             if let ty::Param(param) = t.kind()
498                 && let param_def_id = self.generics.type_param(param, self.tcx).def_id
499                 && self.tcx.parent(param_def_id) == self.trait_item_def_id
500             {
501                 return ControlFlow::Break(());
502             }
503             t.super_visit_with(self)
504         }
505         fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
506             if let ty::ReEarlyBound(param) = r.kind()
507                 && let param_def_id = self.generics.region_param(&param, self.tcx).def_id
508                 && self.tcx.parent(param_def_id) == self.trait_item_def_id
509             {
510                 return ControlFlow::Break(());
511             }
512             ControlFlow::Continue(())
513         }
514         fn visit_const(&mut self, ct: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
515             if let ty::ConstKind::Param(param) = ct.kind()
516                 && let param_def_id = self.generics.const_param(&param, self.tcx).def_id
517                 && self.tcx.parent(param_def_id) == self.trait_item_def_id
518             {
519                 return ControlFlow::Break(());
520             }
521             ct.super_visit_with(self)
522         }
523     }
524 
525     let generics = tcx.generics_of(trait_item_def_id);
526     let predicates = tcx.predicates_of(trait_item_def_id);
527     let impl_trait_ref = tcx
528         .impl_trait_ref(impl_def_id)
529         .expect("expected impl to correspond to trait")
530         .subst_identity();
531     let param_env = tcx.param_env(impl_def_id);
532 
533     let mut visitor = ReferencesOnlyParentGenerics { tcx, generics, trait_item_def_id };
534     let predicates_for_trait = predicates.predicates.iter().filter_map(|(pred, span)| {
535         pred.visit_with(&mut visitor).is_continue().then(|| {
536             Obligation::new(
537                 tcx,
538                 ObligationCause::dummy_with_span(*span),
539                 param_env,
540                 ty::EarlyBinder::bind(*pred).subst(tcx, impl_trait_ref.substs),
541             )
542         })
543     });
544 
545     let infcx = tcx.infer_ctxt().ignoring_regions().build();
546     for obligation in predicates_for_trait {
547         // Ignore overflow error, to be conservative.
548         if let Ok(result) = infcx.evaluate_obligation(&obligation)
549             && !result.may_apply()
550         {
551             return true;
552         }
553     }
554     false
555 }
556 
provide(providers: &mut Providers)557 pub fn provide(providers: &mut Providers) {
558     object_safety::provide(providers);
559     vtable::provide(providers);
560     *providers = Providers {
561         specialization_graph_of: specialize::specialization_graph_provider,
562         specializes: specialize::specializes,
563         subst_and_check_impossible_predicates,
564         check_tys_might_be_eq: misc::check_tys_might_be_eq,
565         is_impossible_method,
566         ..*providers
567     };
568 }
569