]> git.proxmox.com Git - rustc.git/blob - src/librustc_infer/traits/query/outlives_bounds.rs
New upstream version 1.43.0+dfsg1
[rustc.git] / src / librustc_infer / traits / query / outlives_bounds.rs
1 use crate::infer::canonical::OriginalQueryValues;
2 use crate::infer::InferCtxt;
3 use crate::traits::query::NoSolution;
4 use crate::traits::{FulfillmentContext, ObligationCause, TraitEngine, TraitEngineExt};
5 use rustc::ty::{self, Ty};
6 use rustc_hir as hir;
7 use rustc_span::source_map::Span;
8
9 pub use rustc::traits::query::OutlivesBound;
10
11 impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
12 /// Implied bounds are region relationships that we deduce
13 /// automatically. The idea is that (e.g.) a caller must check that a
14 /// function's argument types are well-formed immediately before
15 /// calling that fn, and hence the *callee* can assume that its
16 /// argument types are well-formed. This may imply certain relationships
17 /// between generic parameters. For example:
18 ///
19 /// fn foo<'a,T>(x: &'a T)
20 ///
21 /// can only be called with a `'a` and `T` such that `&'a T` is WF.
22 /// For `&'a T` to be WF, `T: 'a` must hold. So we can assume `T: 'a`.
23 ///
24 /// # Parameters
25 ///
26 /// - `param_env`, the where-clauses in scope
27 /// - `body_id`, the body-id to use when normalizing assoc types.
28 /// Note that this may cause outlives obligations to be injected
29 /// into the inference context with this body-id.
30 /// - `ty`, the type that we are supposed to assume is WF.
31 /// - `span`, a span to use when normalizing, hopefully not important,
32 /// might be useful if a `bug!` occurs.
33 pub fn implied_outlives_bounds(
34 &self,
35 param_env: ty::ParamEnv<'tcx>,
36 body_id: hir::HirId,
37 ty: Ty<'tcx>,
38 span: Span,
39 ) -> Vec<OutlivesBound<'tcx>> {
40 debug!("implied_outlives_bounds(ty = {:?})", ty);
41
42 let mut orig_values = OriginalQueryValues::default();
43 let key = self.canonicalize_query(&param_env.and(ty), &mut orig_values);
44 let result = match self.tcx.implied_outlives_bounds(key) {
45 Ok(r) => r,
46 Err(NoSolution) => {
47 self.tcx.sess.delay_span_bug(
48 span,
49 "implied_outlives_bounds failed to solve all obligations",
50 );
51 return vec![];
52 }
53 };
54 assert!(result.value.is_proven());
55
56 let result = self.instantiate_query_response_and_region_obligations(
57 &ObligationCause::misc(span, body_id),
58 param_env,
59 &orig_values,
60 &result,
61 );
62 debug!("implied_outlives_bounds for {:?}: {:#?}", ty, result);
63 let result = match result {
64 Ok(v) => v,
65 Err(_) => {
66 self.tcx.sess.delay_span_bug(span, "implied_outlives_bounds failed to instantiate");
67 return vec![];
68 }
69 };
70
71 // Instantiation may have produced new inference variables and constraints on those
72 // variables. Process these constraints.
73 let mut fulfill_cx = FulfillmentContext::new();
74 fulfill_cx.register_predicate_obligations(self, result.obligations);
75 if fulfill_cx.select_all_or_error(self).is_err() {
76 self.tcx.sess.delay_span_bug(
77 span,
78 "implied_outlives_bounds failed to solve obligations from instantiation",
79 );
80 }
81
82 result.value
83 }
84 }
85
86 pub fn explicit_outlives_bounds<'tcx>(
87 param_env: ty::ParamEnv<'tcx>,
88 ) -> impl Iterator<Item = OutlivesBound<'tcx>> + 'tcx {
89 debug!("explicit_outlives_bounds()");
90 param_env.caller_bounds.into_iter().filter_map(move |predicate| match predicate {
91 ty::Predicate::Projection(..)
92 | ty::Predicate::Trait(..)
93 | ty::Predicate::Subtype(..)
94 | ty::Predicate::WellFormed(..)
95 | ty::Predicate::ObjectSafe(..)
96 | ty::Predicate::ClosureKind(..)
97 | ty::Predicate::TypeOutlives(..)
98 | ty::Predicate::ConstEvaluatable(..) => None,
99 ty::Predicate::RegionOutlives(ref data) => data
100 .no_bound_vars()
101 .map(|ty::OutlivesPredicate(r_a, r_b)| OutlivesBound::RegionSubRegion(r_b, r_a)),
102 })
103 }