]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_typeck/src/outlives/outlives_bounds.rs
Rollup merge of #89507 - lopopolo:lopopolo/ordering-repr-i8, r=joshtriplett
[rust.git] / compiler / rustc_typeck / src / outlives / outlives_bounds.rs
1 use rustc_hir as hir;
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};
9
10 pub use rustc_middle::traits::query::OutlivesBound;
11
12 pub trait InferCtxtExt<'tcx> {
13     fn implied_outlives_bounds(
14         &self,
15         param_env: ty::ParamEnv<'tcx>,
16         body_id: hir::HirId,
17         ty: Ty<'tcx>,
18         span: Span,
19     ) -> Vec<OutlivesBound<'tcx>>;
20 }
21
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:
29     ///
30     ///     fn foo<'a,T>(x: &'a T)
31     ///
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`.
34     ///
35     /// # Parameters
36     ///
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(
45         &self,
46         param_env: ty::ParamEnv<'tcx>,
47         body_id: hir::HirId,
48         ty: Ty<'tcx>,
49         span: Span,
50     ) -> Vec<OutlivesBound<'tcx>> {
51         debug!("implied_outlives_bounds(ty = {:?})", ty);
52
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) {
56             Ok(r) => r,
57             Err(NoSolution) => {
58                 self.tcx.sess.delay_span_bug(
59                     span,
60                     "implied_outlives_bounds failed to solve all obligations",
61                 );
62                 return vec![];
63             }
64         };
65         assert!(result.value.is_proven());
66
67         let result = self.instantiate_query_response_and_region_obligations(
68             &ObligationCause::misc(span, body_id),
69             param_env,
70             &orig_values,
71             result,
72         );
73         debug!("implied_outlives_bounds for {:?}: {:#?}", ty, result);
74         let result = match result {
75             Ok(v) => v,
76             Err(_) => {
77                 self.tcx.sess.delay_span_bug(span, "implied_outlives_bounds failed to instantiate");
78                 return vec![];
79             }
80         };
81
82         // Instantiation may have produced new inference variables and constraints on those
83         // variables. Process these constraints.
84         let mut fulfill_cx = FulfillmentContext::new();
85         fulfill_cx.register_predicate_obligations(self, result.obligations);
86         if fulfill_cx.select_all_or_error(self).is_err() {
87             self.tcx.sess.delay_span_bug(
88                 span,
89                 "implied_outlives_bounds failed to solve obligations from instantiation",
90             );
91         }
92
93         result.value
94     }
95 }