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}
;
7 use rustc_span
::source_map
::Span
;
9 pub use rustc
::traits
::query
::OutlivesBound
;
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:
19 /// fn foo<'a,T>(x: &'a T)
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`.
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(
35 param_env
: ty
::ParamEnv
<'tcx
>,
39 ) -> Vec
<OutlivesBound
<'tcx
>> {
40 debug
!("implied_outlives_bounds(ty = {:?})", ty
);
42 let mut orig_values
= OriginalQueryValues
::default();
43 let key
= self.canonicalize_query(¶m_env
.and(ty
), &mut orig_values
);
44 let result
= match self.tcx
.implied_outlives_bounds(key
) {
47 self.tcx
.sess
.delay_span_bug(
49 "implied_outlives_bounds failed to solve all obligations",
54 assert
!(result
.value
.is_proven());
56 let result
= self.instantiate_query_response_and_region_obligations(
57 &ObligationCause
::misc(span
, body_id
),
62 debug
!("implied_outlives_bounds for {:?}: {:#?}", ty
, result
);
63 let result
= match result
{
66 self.tcx
.sess
.delay_span_bug(span
, "implied_outlives_bounds failed to instantiate");
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(
78 "implied_outlives_bounds failed to solve obligations from instantiation",
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
101 .map(|ty
::OutlivesPredicate(r_a
, r_b
)| OutlivesBound
::RegionSubRegion(r_b
, r_a
)),