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