]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_typeck/src/outlives/outlives_bounds.rs
New upstream version 1.64.0+dfsg1
[rustc.git] / compiler / rustc_typeck / src / outlives / outlives_bounds.rs
CommitLineData
dfeec247 1use rustc_hir as hir;
ba9703b0 2use rustc_middle::ty::{self, Ty};
c295e0f8 3use rustc_trait_selection::infer::InferCtxt;
923072b8 4use rustc_trait_selection::traits::query::type_op::{self, TypeOp, TypeOpOutput};
c295e0f8 5use rustc_trait_selection::traits::query::NoSolution;
064997fb 6use rustc_trait_selection::traits::{ObligationCause, TraitEngine, TraitEngineExt};
8faf50e0 7
ba9703b0 8pub use rustc_middle::traits::query::OutlivesBound;
8faf50e0 9
ba9703b0
XL
10pub trait InferCtxtExt<'tcx> {
11 fn implied_outlives_bounds(
12 &self,
13 param_env: ty::ParamEnv<'tcx>,
14 body_id: hir::HirId,
15 ty: Ty<'tcx>,
ba9703b0
XL
16 ) -> Vec<OutlivesBound<'tcx>>;
17}
18
19impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> {
8faf50e0 20 /// Implied bounds are region relationships that we deduce
9fa01778 21 /// automatically. The idea is that (e.g.) a caller must check that a
8faf50e0
XL
22 /// function's argument types are well-formed immediately before
23 /// calling that fn, and hence the *callee* can assume that its
24 /// argument types are well-formed. This may imply certain relationships
25 /// between generic parameters. For example:
04454e1e
FG
26 /// ```
27 /// fn foo<'a,T>(x: &'a T) {}
28 /// ```
8faf50e0
XL
29 /// can only be called with a `'a` and `T` such that `&'a T` is WF.
30 /// For `&'a T` to be WF, `T: 'a` must hold. So we can assume `T: 'a`.
31 ///
32 /// # Parameters
33 ///
34 /// - `param_env`, the where-clauses in scope
35 /// - `body_id`, the body-id to use when normalizing assoc types.
36 /// Note that this may cause outlives obligations to be injected
37 /// into the inference context with this body-id.
38 /// - `ty`, the type that we are supposed to assume is WF.
064997fb 39 #[instrument(level = "debug", skip(self, param_env, body_id))]
ba9703b0 40 fn implied_outlives_bounds(
8faf50e0
XL
41 &self,
42 param_env: ty::ParamEnv<'tcx>,
9fa01778 43 body_id: hir::HirId,
8faf50e0 44 ty: Ty<'tcx>,
8faf50e0 45 ) -> Vec<OutlivesBound<'tcx>> {
064997fb 46 let span = self.tcx.hir().span(body_id);
923072b8
FG
47 let result = param_env
48 .and(type_op::implied_outlives_bounds::ImpliedOutlivesBounds { ty })
49 .fully_perform(self);
50 let result = match result {
8faf50e0
XL
51 Ok(r) => r,
52 Err(NoSolution) => {
53 self.tcx.sess.delay_span_bug(
54 span,
dfeec247 55 "implied_outlives_bounds failed to solve all obligations",
8faf50e0
XL
56 );
57 return vec![];
58 }
59 };
8faf50e0 60
923072b8 61 let TypeOpOutput { output, constraints, .. } = result;
8faf50e0 62
923072b8
FG
63 if let Some(constraints) = constraints {
64 // Instantiation may have produced new inference variables and constraints on those
65 // variables. Process these constraints.
064997fb 66 let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new(self.tcx);
923072b8
FG
67 let cause = ObligationCause::misc(span, body_id);
68 for &constraint in &constraints.outlives {
69 let obligation = self.query_outlives_constraint_to_obligation(
70 constraint,
71 cause.clone(),
72 param_env,
73 );
74 fulfill_cx.register_predicate_obligation(self, obligation);
75 }
76 if !constraints.member_constraints.is_empty() {
77 span_bug!(span, "{:#?}", constraints.member_constraints);
78 }
79 let errors = fulfill_cx.select_all_or_error(self);
80 if !errors.is_empty() {
81 self.tcx.sess.delay_span_bug(
82 span,
83 "implied_outlives_bounds failed to solve obligations from instantiation",
84 );
85 }
86 };
8faf50e0 87
923072b8 88 output
8faf50e0
XL
89 }
90}