]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
New upstream version 1.69.0+dfsg1
[rustc.git] / compiler / rustc_trait_selection / src / traits / outlives_bounds.rs
CommitLineData
f2b60f7d
FG
1use crate::infer::InferCtxt;
2use crate::traits::query::type_op::{self, TypeOp, TypeOpOutput};
3use crate::traits::query::NoSolution;
487cf647
FG
4use crate::traits::ObligationCause;
5use rustc_data_structures::fx::FxIndexSet;
f2b60f7d 6use rustc_middle::ty::{self, ParamEnv, Ty};
9ffffee4 7use rustc_span::def_id::LocalDefId;
8faf50e0 8
ba9703b0 9pub use rustc_middle::traits::query::OutlivesBound;
8faf50e0 10
f2b60f7d
FG
11type Bounds<'a, 'tcx: 'a> = impl Iterator<Item = OutlivesBound<'tcx>> + 'a;
12pub trait InferCtxtExt<'a, 'tcx> {
ba9703b0
XL
13 fn implied_outlives_bounds(
14 &self,
15 param_env: ty::ParamEnv<'tcx>,
9ffffee4 16 body_id: LocalDefId,
ba9703b0 17 ty: Ty<'tcx>,
ba9703b0 18 ) -> Vec<OutlivesBound<'tcx>>;
f2b60f7d
FG
19
20 fn implied_bounds_tys(
21 &'a self,
22 param_env: ty::ParamEnv<'tcx>,
9ffffee4 23 body_id: LocalDefId,
487cf647 24 tys: FxIndexSet<Ty<'tcx>>,
f2b60f7d 25 ) -> Bounds<'a, 'tcx>;
ba9703b0
XL
26}
27
2b03887a 28impl<'a, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'tcx> {
8faf50e0 29 /// Implied bounds are region relationships that we deduce
9fa01778 30 /// automatically. The idea is that (e.g.) a caller must check that a
8faf50e0
XL
31 /// function's argument types are well-formed immediately before
32 /// calling that fn, and hence the *callee* can assume that its
33 /// argument types are well-formed. This may imply certain relationships
34 /// between generic parameters. For example:
04454e1e 35 /// ```
9c376795 36 /// fn foo<T>(x: &T) {}
04454e1e 37 /// ```
8faf50e0
XL
38 /// can only be called with a `'a` and `T` such that `&'a T` is WF.
39 /// For `&'a T` to be WF, `T: 'a` must hold. So we can assume `T: 'a`.
40 ///
41 /// # Parameters
42 ///
43 /// - `param_env`, the where-clauses in scope
44 /// - `body_id`, the body-id to use when normalizing assoc types.
45 /// Note that this may cause outlives obligations to be injected
46 /// into the inference context with this body-id.
47 /// - `ty`, the type that we are supposed to assume is WF.
f2b60f7d 48 #[instrument(level = "debug", skip(self, param_env, body_id), ret)]
ba9703b0 49 fn implied_outlives_bounds(
8faf50e0
XL
50 &self,
51 param_env: ty::ParamEnv<'tcx>,
9ffffee4 52 body_id: LocalDefId,
8faf50e0 53 ty: Ty<'tcx>,
8faf50e0 54 ) -> Vec<OutlivesBound<'tcx>> {
9ffffee4 55 let span = self.tcx.def_span(body_id);
923072b8
FG
56 let result = param_env
57 .and(type_op::implied_outlives_bounds::ImpliedOutlivesBounds { ty })
58 .fully_perform(self);
59 let result = match result {
8faf50e0
XL
60 Ok(r) => r,
61 Err(NoSolution) => {
62 self.tcx.sess.delay_span_bug(
63 span,
dfeec247 64 "implied_outlives_bounds failed to solve all obligations",
8faf50e0
XL
65 );
66 return vec![];
67 }
68 };
8faf50e0 69
923072b8 70 let TypeOpOutput { output, constraints, .. } = result;
8faf50e0 71
923072b8 72 if let Some(constraints) = constraints {
f2b60f7d 73 debug!(?constraints);
923072b8
FG
74 // Instantiation may have produced new inference variables and constraints on those
75 // variables. Process these constraints.
923072b8 76 let cause = ObligationCause::misc(span, body_id);
487cf647
FG
77 let errors = super::fully_solve_obligations(
78 self,
79 constraints.outlives.iter().map(|constraint| {
80 self.query_outlives_constraint_to_obligation(
81 *constraint,
82 cause.clone(),
83 param_env,
84 )
85 }),
86 );
923072b8
FG
87 if !constraints.member_constraints.is_empty() {
88 span_bug!(span, "{:#?}", constraints.member_constraints);
89 }
923072b8
FG
90 if !errors.is_empty() {
91 self.tcx.sess.delay_span_bug(
92 span,
93 "implied_outlives_bounds failed to solve obligations from instantiation",
94 );
95 }
96 };
8faf50e0 97
923072b8 98 output
8faf50e0 99 }
f2b60f7d
FG
100
101 fn implied_bounds_tys(
102 &'a self,
103 param_env: ParamEnv<'tcx>,
9ffffee4 104 body_id: LocalDefId,
487cf647 105 tys: FxIndexSet<Ty<'tcx>>,
f2b60f7d
FG
106 ) -> Bounds<'a, 'tcx> {
107 tys.into_iter()
108 .map(move |ty| {
109 let ty = self.resolve_vars_if_possible(ty);
110 self.implied_outlives_bounds(param_env, body_id, ty)
111 })
112 .flatten()
113 }
8faf50e0 114}