2 use rustc_middle
::ty
::{self, Ty}
;
3 use rustc_span
::source_map
::Span
;
4 use rustc_trait_selection
::infer
::InferCtxt
;
5 use rustc_trait_selection
::traits
::query
::type_op
::{self, TypeOp, TypeOpOutput}
;
6 use rustc_trait_selection
::traits
::query
::NoSolution
;
7 use rustc_trait_selection
::traits
::{FulfillmentContext, ObligationCause, TraitEngine}
;
9 pub use rustc_middle
::traits
::query
::OutlivesBound
;
11 pub trait InferCtxtExt
<'tcx
> {
12 fn implied_outlives_bounds(
14 param_env
: ty
::ParamEnv
<'tcx
>,
18 ) -> Vec
<OutlivesBound
<'tcx
>>;
21 impl<'cx
, 'tcx
> InferCtxtExt
<'tcx
> for InferCtxt
<'cx
, 'tcx
> {
22 /// Implied bounds are region relationships that we deduce
23 /// automatically. The idea is that (e.g.) a caller must check that a
24 /// function's argument types are well-formed immediately before
25 /// calling that fn, and hence the *callee* can assume that its
26 /// argument types are well-formed. This may imply certain relationships
27 /// between generic parameters. For example:
29 /// fn foo<'a,T>(x: &'a T) {}
31 /// can only be called with a `'a` and `T` such that `&'a T` is WF.
32 /// For `&'a T` to be WF, `T: 'a` must hold. So we can assume `T: 'a`.
36 /// - `param_env`, the where-clauses in scope
37 /// - `body_id`, the body-id to use when normalizing assoc types.
38 /// Note that this may cause outlives obligations to be injected
39 /// into the inference context with this body-id.
40 /// - `ty`, the type that we are supposed to assume is WF.
41 /// - `span`, a span to use when normalizing, hopefully not important,
42 /// might be useful if a `bug!` occurs.
43 #[instrument(level = "debug", skip(self, param_env, body_id, span))]
44 fn implied_outlives_bounds(
46 param_env
: ty
::ParamEnv
<'tcx
>,
50 ) -> Vec
<OutlivesBound
<'tcx
>> {
51 let result
= param_env
52 .and(type_op
::implied_outlives_bounds
::ImpliedOutlivesBounds { ty }
)
54 let result
= match result
{
57 self.tcx
.sess
.delay_span_bug(
59 "implied_outlives_bounds failed to solve all obligations",
65 let TypeOpOutput { output, constraints, .. }
= result
;
67 if let Some(constraints
) = constraints
{
68 // Instantiation may have produced new inference variables and constraints on those
69 // variables. Process these constraints.
70 let mut fulfill_cx
= FulfillmentContext
::new();
71 let cause
= ObligationCause
::misc(span
, body_id
);
72 for &constraint
in &constraints
.outlives
{
73 let obligation
= self.query_outlives_constraint_to_obligation(
78 fulfill_cx
.register_predicate_obligation(self, obligation
);
80 if !constraints
.member_constraints
.is_empty() {
81 span_bug
!(span
, "{:#?}", constraints
.member_constraints
);
83 let errors
= fulfill_cx
.select_all_or_error(self);
84 if !errors
.is_empty() {
85 self.tcx
.sess
.delay_span_bug(
87 "implied_outlives_bounds failed to solve obligations from instantiation",