@@ -12,13 +12,6 @@ pub use rustc_middle::traits::query::OutlivesBound;
1212pub type BoundsCompat < ' a , ' tcx : ' a > = impl Iterator < Item = OutlivesBound < ' tcx > > + ' a ;
1313pub type Bounds < ' a , ' tcx : ' a > = impl Iterator < Item = OutlivesBound < ' tcx > > + ' a ;
1414pub trait InferCtxtExt < ' a , ' tcx > {
15- fn implied_outlives_bounds_compat (
16- & self ,
17- param_env : ty:: ParamEnv < ' tcx > ,
18- body_id : LocalDefId ,
19- ty : Ty < ' tcx > ,
20- ) -> Vec < OutlivesBound < ' tcx > > ;
21-
2215 fn implied_bounds_tys_compat (
2316 & ' a self ,
2417 param_env : ty:: ParamEnv < ' tcx > ,
@@ -29,130 +22,127 @@ pub trait InferCtxtExt<'a, 'tcx> {
2922 fn implied_bounds_tys (
3023 & ' a self ,
3124 param_env : ty:: ParamEnv < ' tcx > ,
25+ body_id : LocalDefId ,
3226 tys : & ' a FxIndexSet < Ty < ' tcx > > ,
3327 ) -> Bounds < ' a , ' tcx > ;
3428}
3529
36- impl < ' a , ' tcx : ' a > InferCtxtExt < ' a , ' tcx > for InferCtxt < ' tcx > {
37- /// Implied bounds are region relationships that we deduce
38- /// automatically. The idea is that (e.g.) a caller must check that a
39- /// function's argument types are well-formed immediately before
40- /// calling that fn, and hence the *callee* can assume that its
41- /// argument types are well-formed. This may imply certain relationships
42- /// between generic parameters. For example:
43- /// ```
44- /// fn foo<T>(x: &T) {}
45- /// ```
46- /// can only be called with a `'a` and `T` such that `&'a T` is WF.
47- /// For `&'a T` to be WF, `T: 'a` must hold. So we can assume `T: 'a`.
48- ///
49- /// # Parameters
50- ///
51- /// - `param_env`, the where-clauses in scope
52- /// - `body_id`, the body-id to use when normalizing assoc types.
53- /// Note that this may cause outlives obligations to be injected
54- /// into the inference context with this body-id.
55- /// - `ty`, the type that we are supposed to assume is WF.
56- #[ instrument( level = "debug" , skip( self , param_env, body_id) , ret) ]
57- fn implied_outlives_bounds_compat (
58- & self ,
59- param_env : ty:: ParamEnv < ' tcx > ,
60- body_id : LocalDefId ,
61- ty : Ty < ' tcx > ,
62- ) -> Vec < OutlivesBound < ' tcx > > {
63- let ty = self . resolve_vars_if_possible ( ty) ;
64- let ty = OpportunisticRegionResolver :: new ( self ) . fold_ty ( ty) ;
65-
66- // We do not expect existential variables in implied bounds.
67- // We may however encounter unconstrained lifetime variables
68- // in very rare cases.
69- //
70- // See `ui/implied-bounds/implied-bounds-unconstrained-2.rs` for
71- // an example.
72- assert ! ( !ty. has_non_region_infer( ) ) ;
73-
74- let mut canonical_var_values = OriginalQueryValues :: default ( ) ;
75- let canonical_ty =
76- self . canonicalize_query_keep_static ( param_env. and ( ty) , & mut canonical_var_values) ;
77- let Ok ( canonical_result) = self . tcx . implied_outlives_bounds_compat ( canonical_ty) else {
78- return vec ! [ ] ;
79- } ;
80-
81- let mut constraints = QueryRegionConstraints :: default ( ) ;
82- let Ok ( InferOk { value : mut bounds, obligations } ) = self
83- . instantiate_nll_query_response_and_region_obligations (
84- & ObligationCause :: dummy ( ) ,
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<T>(x: &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( infcx, param_env, body_id) , ret) ]
50+ fn implied_outlives_bounds < ' a , ' tcx > (
51+ infcx : & ' a InferCtxt < ' tcx > ,
52+ param_env : ty:: ParamEnv < ' tcx > ,
53+ body_id : LocalDefId ,
54+ ty : Ty < ' tcx > ,
55+ compat : bool ,
56+ ) -> Vec < OutlivesBound < ' tcx > > {
57+ let ty = infcx. resolve_vars_if_possible ( ty) ;
58+ let ty = OpportunisticRegionResolver :: new ( infcx) . fold_ty ( ty) ;
59+
60+ // We do not expect existential variables in implied bounds.
61+ // We may however encounter unconstrained lifetime variables
62+ // in very rare cases.
63+ //
64+ // See `ui/implied-bounds/implied-bounds-unconstrained-2.rs` for
65+ // an example.
66+ assert ! ( !ty. has_non_region_infer( ) ) ;
67+
68+ let mut canonical_var_values = OriginalQueryValues :: default ( ) ;
69+ let canonical_ty =
70+ infcx. canonicalize_query_keep_static ( param_env. and ( ty) , & mut canonical_var_values) ;
71+ let implied_bounds_result = if compat {
72+ infcx. tcx . implied_outlives_bounds_compat ( canonical_ty)
73+ } else {
74+ infcx. tcx . implied_outlives_bounds ( canonical_ty)
75+ } ;
76+ let Ok ( canonical_result) = implied_bounds_result else {
77+ return vec ! [ ] ;
78+ } ;
79+
80+ let mut constraints = QueryRegionConstraints :: default ( ) ;
81+ let Ok ( InferOk { value : mut bounds, obligations } ) = infcx
82+ . instantiate_nll_query_response_and_region_obligations (
83+ & ObligationCause :: dummy ( ) ,
84+ param_env,
85+ & canonical_var_values,
86+ canonical_result,
87+ & mut constraints,
88+ )
89+ else {
90+ return vec ! [ ] ;
91+ } ;
92+ assert_eq ! ( & obligations, & [ ] ) ;
93+
94+ // Because of #109628, we may have unexpected placeholders. Ignore them!
95+ // FIXME(#109628): panic in this case once the issue is fixed.
96+ bounds. retain ( |bound| !bound. has_placeholders ( ) ) ;
97+
98+ if !constraints. is_empty ( ) {
99+ let span = infcx. tcx . def_span ( body_id) ;
100+
101+ debug ! ( ?constraints) ;
102+ if !constraints. member_constraints . is_empty ( ) {
103+ span_bug ! ( span, "{:#?}" , constraints. member_constraints) ;
104+ }
105+
106+ // Instantiation may have produced new inference variables and constraints on those
107+ // variables. Process these constraints.
108+ let ocx = ObligationCtxt :: new ( infcx) ;
109+ let cause = ObligationCause :: misc ( span, body_id) ;
110+ for & constraint in & constraints. outlives {
111+ ocx. register_obligation ( infcx. query_outlives_constraint_to_obligation (
112+ constraint,
113+ cause. clone ( ) ,
85114 param_env,
86- & canonical_var_values,
87- canonical_result,
88- & mut constraints,
89- )
90- else {
91- return vec ! [ ] ;
92- } ;
93- assert_eq ! ( & obligations, & [ ] ) ;
94-
95- // Because of #109628, we may have unexpected placeholders. Ignore them!
96- // FIXME(#109628): panic in this case once the issue is fixed.
97- bounds. retain ( |bound| !bound. has_placeholders ( ) ) ;
98-
99- if !constraints. is_empty ( ) {
100- let span = self . tcx . def_span ( body_id) ;
101-
102- debug ! ( ?constraints) ;
103- if !constraints. member_constraints . is_empty ( ) {
104- span_bug ! ( span, "{:#?}" , constraints. member_constraints) ;
105- }
106-
107- // Instantiation may have produced new inference variables and constraints on those
108- // variables. Process these constraints.
109- let ocx = ObligationCtxt :: new ( self ) ;
110- let cause = ObligationCause :: misc ( span, body_id) ;
111- for & constraint in & constraints. outlives {
112- ocx. register_obligation ( self . query_outlives_constraint_to_obligation (
113- constraint,
114- cause. clone ( ) ,
115- param_env,
116- ) ) ;
117- }
118-
119- let errors = ocx. select_all_or_error ( ) ;
120- if !errors. is_empty ( ) {
121- self . tcx . sess . span_delayed_bug (
122- span,
123- "implied_outlives_bounds_compat failed to solve obligations from instantiation" ,
124- ) ;
125- }
126- } ;
127-
128- bounds
129- }
115+ ) ) ;
116+ }
117+
118+ let errors = ocx. select_all_or_error ( ) ;
119+ if !errors. is_empty ( ) {
120+ infcx. tcx . sess . span_delayed_bug (
121+ span,
122+ "implied_outlives_bounds_compat failed to solve obligations from instantiation" ,
123+ ) ;
124+ }
125+ } ;
126+
127+ bounds
128+ }
130129
130+ impl < ' a , ' tcx : ' a > InferCtxtExt < ' a , ' tcx > for InferCtxt < ' tcx > {
131131 fn implied_bounds_tys_compat (
132132 & ' a self ,
133133 param_env : ParamEnv < ' tcx > ,
134134 body_id : LocalDefId ,
135135 tys : & ' a FxIndexSet < Ty < ' tcx > > ,
136136 ) -> BoundsCompat < ' a , ' tcx > {
137- tys. iter ( ) . flat_map ( move |ty| self . implied_outlives_bounds_compat ( param_env, body_id, * ty) )
137+ tys. iter ( ) . flat_map ( move |ty| implied_outlives_bounds ( self , param_env, body_id, * ty, true ) )
138138 }
139139
140140 fn implied_bounds_tys (
141141 & ' a self ,
142142 param_env : ParamEnv < ' tcx > ,
143+ body_id : LocalDefId ,
143144 tys : & ' a FxIndexSet < Ty < ' tcx > > ,
144145 ) -> Bounds < ' a , ' tcx > {
145- tys. iter ( )
146- . flat_map ( move |& ty| {
147- let ty = self . resolve_vars_if_possible ( ty) ;
148- let ty = OpportunisticRegionResolver :: new ( self ) . fold_ty ( ty) ;
149-
150- if ty. has_infer ( ) {
151- return & [ ] as & [ OutlivesBound < ' _ > ] ;
152- }
153-
154- self . tcx . implied_outlives_bounds ( param_env. and ( ty) ) . unwrap_or ( & [ ] )
155- } )
156- . copied ( )
146+ tys. iter ( ) . flat_map ( move |ty| implied_outlives_bounds ( self , param_env, body_id, * ty, false ) )
157147 }
158148}
0 commit comments