2 use rustc_infer::traits::TraitEngineExt as _;
3 use rustc_middle::ty::{self, Ty};
4 use rustc_span::source_map::Span;
5 use rustc_trait_selection::infer::canonical::OriginalQueryValues;
6 use rustc_trait_selection::infer::InferCtxt;
7 use rustc_trait_selection::traits::query::NoSolution;
8 use rustc_trait_selection::traits::{FulfillmentContext, ObligationCause, TraitEngine};
10 pub use rustc_middle::traits::query::OutlivesBound;
12 pub trait InferCtxtExt<'tcx> {
13 fn implied_outlives_bounds(
15 param_env: ty::ParamEnv<'tcx>,
19 ) -> Vec<OutlivesBound<'tcx>>;
22 impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> {
23 /// Implied bounds are region relationships that we deduce
24 /// automatically. The idea is that (e.g.) a caller must check that a
25 /// function's argument types are well-formed immediately before
26 /// calling that fn, and hence the *callee* can assume that its
27 /// argument types are well-formed. This may imply certain relationships
28 /// between generic parameters. For example:
30 /// fn foo<'a,T>(x: &'a T) {}
32 /// can only be called with a `'a` and `T` such that `&'a T` is WF.
33 /// For `&'a T` to be WF, `T: 'a` must hold. So we can assume `T: 'a`.
37 /// - `param_env`, the where-clauses in scope
38 /// - `body_id`, the body-id to use when normalizing assoc types.
39 /// Note that this may cause outlives obligations to be injected
40 /// into the inference context with this body-id.
41 /// - `ty`, the type that we are supposed to assume is WF.
42 /// - `span`, a span to use when normalizing, hopefully not important,
43 /// might be useful if a `bug!` occurs.
44 fn implied_outlives_bounds(
46 param_env: ty::ParamEnv<'tcx>,
50 ) -> Vec<OutlivesBound<'tcx>> {
51 debug!("implied_outlives_bounds(ty = {:?})", ty);
53 let mut orig_values = OriginalQueryValues::default();
54 let key = self.canonicalize_query(param_env.and(ty), &mut orig_values);
55 let result = match self.tcx.implied_outlives_bounds(key) {
58 self.tcx.sess.delay_span_bug(
60 "implied_outlives_bounds failed to solve all obligations",
65 assert!(result.value.is_proven());
67 let result = self.instantiate_query_response_and_region_obligations(
68 &ObligationCause::misc(span, body_id),
73 debug!("implied_outlives_bounds for {:?}: {:#?}", ty, result);
74 let Ok(result) = result else {
75 self.tcx.sess.delay_span_bug(span, "implied_outlives_bounds failed to instantiate");
79 // Instantiation may have produced new inference variables and constraints on those
80 // variables. Process these constraints.
81 let mut fulfill_cx = FulfillmentContext::new();
82 fulfill_cx.register_predicate_obligations(self, result.obligations);
83 let errors = fulfill_cx.select_all_or_error(self);
84 if !errors.is_empty() {
85 self.tcx.sess.delay_span_bug(
87 "implied_outlives_bounds failed to solve obligations from instantiation",