]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
change `ConstEvaluatable` to use `ty::Const`
[rust.git] / compiler / rustc_trait_selection / src / traits / outlives_bounds.rs
1 use crate::infer::InferCtxt;
2 use crate::traits::query::type_op::{self, TypeOp, TypeOpOutput};
3 use crate::traits::query::NoSolution;
4 use crate::traits::{ObligationCause, TraitEngine, TraitEngineExt};
5 use rustc_data_structures::fx::FxHashSet;
6 use rustc_hir as hir;
7 use rustc_hir::HirId;
8 use rustc_middle::ty::{self, ParamEnv, Ty};
9
10 pub use rustc_middle::traits::query::OutlivesBound;
11
12 type Bounds<'a, 'tcx: 'a> = impl Iterator<Item = OutlivesBound<'tcx>> + 'a;
13 pub trait InferCtxtExt<'a, 'tcx> {
14     fn implied_outlives_bounds(
15         &self,
16         param_env: ty::ParamEnv<'tcx>,
17         body_id: hir::HirId,
18         ty: Ty<'tcx>,
19     ) -> Vec<OutlivesBound<'tcx>>;
20
21     fn implied_bounds_tys(
22         &'a self,
23         param_env: ty::ParamEnv<'tcx>,
24         body_id: hir::HirId,
25         tys: FxHashSet<Ty<'tcx>>,
26     ) -> Bounds<'a, 'tcx>;
27 }
28
29 impl<'a, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'tcx> {
30     /// Implied bounds are region relationships that we deduce
31     /// automatically. The idea is that (e.g.) a caller must check that a
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:
36     /// ```
37     /// fn foo<'a,T>(x: &'a T) {}
38     /// ```
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.
49     #[instrument(level = "debug", skip(self, param_env, body_id), ret)]
50     fn implied_outlives_bounds(
51         &self,
52         param_env: ty::ParamEnv<'tcx>,
53         body_id: hir::HirId,
54         ty: Ty<'tcx>,
55     ) -> Vec<OutlivesBound<'tcx>> {
56         let span = self.tcx.hir().span(body_id);
57         let result = param_env
58             .and(type_op::implied_outlives_bounds::ImpliedOutlivesBounds { ty })
59             .fully_perform(self);
60         let result = match result {
61             Ok(r) => r,
62             Err(NoSolution) => {
63                 self.tcx.sess.delay_span_bug(
64                     span,
65                     "implied_outlives_bounds failed to solve all obligations",
66                 );
67                 return vec![];
68             }
69         };
70
71         let TypeOpOutput { output, constraints, .. } = result;
72
73         if let Some(constraints) = constraints {
74             debug!(?constraints);
75             // Instantiation may have produced new inference variables and constraints on those
76             // variables. Process these constraints.
77             let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new(self.tcx);
78             let cause = ObligationCause::misc(span, body_id);
79             for &constraint in &constraints.outlives {
80                 let obligation = self.query_outlives_constraint_to_obligation(
81                     constraint,
82                     cause.clone(),
83                     param_env,
84                 );
85                 fulfill_cx.register_predicate_obligation(self, obligation);
86             }
87             if !constraints.member_constraints.is_empty() {
88                 span_bug!(span, "{:#?}", constraints.member_constraints);
89             }
90             let errors = fulfill_cx.select_all_or_error(self);
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         };
98
99         output
100     }
101
102     fn implied_bounds_tys(
103         &'a self,
104         param_env: ParamEnv<'tcx>,
105         body_id: HirId,
106         tys: FxHashSet<Ty<'tcx>>,
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     }
115 }