@@ -31,6 +31,70 @@ pub trait RelateExt: InferCtxtLike {
3131 Vec < Goal < Self :: Interner , <Self :: Interner as Interner >:: Predicate > > ,
3232 TypeError < Self :: Interner > ,
3333 > ;
34+
35+ fn eq_structurally_relating_aliases_with_region_constraints < T : Relate < Self :: Interner > > (
36+ & self ,
37+ param_env : <Self :: Interner as Interner >:: ParamEnv ,
38+ lhs : T ,
39+ rhs : T ,
40+ span : <Self :: Interner as Interner >:: Span ,
41+ ) -> Result <
42+ (
43+ Vec < Goal < Self :: Interner , <Self :: Interner as Interner >:: Predicate > > ,
44+ RegionConstraint < Self :: Interner > ,
45+ ) ,
46+ TypeError < Self :: Interner > ,
47+ > ;
48+
49+ fn relate_with_region_constraints < T : Relate < Self :: Interner > > (
50+ & self ,
51+ param_env : <Self :: Interner as Interner >:: ParamEnv ,
52+ lhs : T ,
53+ variance : ty:: Variance ,
54+ rhs : T ,
55+ span : <Self :: Interner as Interner >:: Span ,
56+ ) -> Result <
57+ (
58+ Vec < Goal < Self :: Interner , <Self :: Interner as Interner >:: Predicate > > ,
59+ RegionConstraint < Self :: Interner > ,
60+ ) ,
61+ TypeError < Self :: Interner > ,
62+ > ;
63+ }
64+
65+ fn relate_with_options < Infcx , T > (
66+ infcx : & Infcx ,
67+ structurally_relate_aliases : StructurallyRelateAliases ,
68+ param_env : <Infcx :: Interner as Interner >:: ParamEnv ,
69+ lhs : T ,
70+ variance : ty:: Variance ,
71+ rhs : T ,
72+ span : <Infcx :: Interner as Interner >:: Span ,
73+ collect_region_constraints : bool ,
74+ ) -> Result <
75+ (
76+ Vec < Goal < Infcx :: Interner , <Infcx :: Interner as Interner >:: Predicate > > ,
77+ Option < RegionConstraint < Infcx :: Interner > > ,
78+ ) ,
79+ TypeError < Infcx :: Interner > ,
80+ >
81+ where
82+ Infcx : InferCtxtLike ,
83+ T : Relate < Infcx :: Interner > ,
84+ {
85+ let mut relate = SolverRelating :: build (
86+ infcx,
87+ structurally_relate_aliases,
88+ variance,
89+ param_env,
90+ span,
91+ collect_region_constraints. then ( Vec :: new) ,
92+ ) ;
93+ relate. relate ( lhs, rhs) ?;
94+ Ok ( (
95+ relate. goals ,
96+ relate. region_constraints . map ( |c| RegionConstraint :: And ( c. into_boxed_slice ( ) ) ) ,
97+ ) )
3498}
3599
36100impl < Infcx : InferCtxtLike > RelateExt for Infcx {
@@ -45,10 +109,17 @@ impl<Infcx: InferCtxtLike> RelateExt for Infcx {
45109 Vec < Goal < Self :: Interner , <Self :: Interner as Interner >:: Predicate > > ,
46110 TypeError < Self :: Interner > ,
47111 > {
48- let mut relate =
49- SolverRelating :: new ( self , StructurallyRelateAliases :: No , variance, param_env, span) ;
50- relate. relate ( lhs, rhs) ?;
51- Ok ( relate. goals )
112+ let ( goals, _) = relate_with_options (
113+ self ,
114+ StructurallyRelateAliases :: No ,
115+ param_env,
116+ lhs,
117+ variance,
118+ rhs,
119+ span,
120+ false ,
121+ ) ?;
122+ Ok ( goals)
52123 }
53124
54125 fn eq_structurally_relating_aliases < T : Relate < Self :: Interner > > (
@@ -61,15 +132,70 @@ impl<Infcx: InferCtxtLike> RelateExt for Infcx {
61132 Vec < Goal < Self :: Interner , <Self :: Interner as Interner >:: Predicate > > ,
62133 TypeError < Self :: Interner > ,
63134 > {
64- let mut relate = SolverRelating :: new (
135+ let ( goals , _ ) = relate_with_options (
65136 self ,
66137 StructurallyRelateAliases :: Yes ,
138+ param_env,
139+ lhs,
67140 ty:: Invariant ,
141+ rhs,
142+ span,
143+ false ,
144+ ) ?;
145+ Ok ( goals)
146+ }
147+
148+ fn eq_structurally_relating_aliases_with_region_constraints < T : Relate < Self :: Interner > > (
149+ & self ,
150+ param_env : <Self :: Interner as Interner >:: ParamEnv ,
151+ lhs : T ,
152+ rhs : T ,
153+ span : <Self :: Interner as Interner >:: Span ,
154+ ) -> Result <
155+ (
156+ Vec < Goal < Self :: Interner , <Self :: Interner as Interner >:: Predicate > > ,
157+ RegionConstraint < Self :: Interner > ,
158+ ) ,
159+ TypeError < Self :: Interner > ,
160+ > {
161+ let ( goals, region_constraints) = relate_with_options (
162+ self ,
163+ StructurallyRelateAliases :: Yes ,
68164 param_env,
165+ lhs,
166+ ty:: Invariant ,
167+ rhs,
69168 span,
70- ) ;
71- relate. relate ( lhs, rhs) ?;
72- Ok ( relate. goals )
169+ true ,
170+ ) ?;
171+ Ok ( ( goals, region_constraints. unwrap ( ) ) )
172+ }
173+
174+ fn relate_with_region_constraints < T : Relate < Self :: Interner > > (
175+ & self ,
176+ param_env : <Self :: Interner as Interner >:: ParamEnv ,
177+ lhs : T ,
178+ variance : ty:: Variance ,
179+ rhs : T ,
180+ span : <Self :: Interner as Interner >:: Span ,
181+ ) -> Result <
182+ (
183+ Vec < Goal < Self :: Interner , <Self :: Interner as Interner >:: Predicate > > ,
184+ RegionConstraint < Self :: Interner > ,
185+ ) ,
186+ TypeError < Self :: Interner > ,
187+ > {
188+ let ( goals, region_constraints) = relate_with_options (
189+ self ,
190+ StructurallyRelateAliases :: No ,
191+ param_env,
192+ lhs,
193+ variance,
194+ rhs,
195+ span,
196+ true ,
197+ ) ?;
198+ Ok ( ( goals, region_constraints. unwrap ( ) ) )
73199 }
74200}
75201
@@ -83,6 +209,7 @@ pub struct SolverRelating<'infcx, Infcx, I: Interner> {
83209 // Mutable fields.
84210 ambient_variance : ty:: Variance ,
85211 goals : Vec < Goal < I , I :: Predicate > > ,
212+ region_constraints : Option < Vec < RegionConstraint < I > > > ,
86213 /// The cache only tracks the `ambient_variance` as it's the
87214 /// only field which is mutable and which meaningfully changes
88215 /// the result when relating types.
@@ -119,6 +246,17 @@ where
119246 ambient_variance : ty:: Variance ,
120247 param_env : I :: ParamEnv ,
121248 span : I :: Span ,
249+ ) -> Self {
250+ Self :: build ( infcx, structurally_relate_aliases, ambient_variance, param_env, span, None )
251+ }
252+
253+ fn build (
254+ infcx : & ' infcx Infcx ,
255+ structurally_relate_aliases : StructurallyRelateAliases ,
256+ ambient_variance : ty:: Variance ,
257+ param_env : I :: ParamEnv ,
258+ span : I :: Span ,
259+ region_constraints : Option < Vec < RegionConstraint < I > > > ,
122260 ) -> Self {
123261 SolverRelating {
124262 infcx,
@@ -127,6 +265,7 @@ where
127265 ambient_variance,
128266 param_env,
129267 goals : vec ! [ ] ,
268+ region_constraints,
130269 cache : Default :: default ( ) ,
131270 }
132271 }
@@ -255,43 +394,42 @@ where
255394
256395 #[ instrument( skip( self ) , level = "trace" ) ]
257396 fn regions ( & mut self , a : I :: Region , b : I :: Region ) -> RelateResult < I , I :: Region > {
258- if self . cx ( ) . assumptions_on_binders ( ) {
259- if a == b {
260- return Ok ( a) ;
397+ match self . ambient_variance {
398+ // Subtype(&'a u8, &'b u8) => Outlives('a: 'b) => SubRegion('b, 'a)
399+ ty:: Covariant => self . infcx . sub_regions ( b, a, VisibleForLeakCheck :: Yes , self . span ) ,
400+ // Suptype(&'a u8, &'b u8) => Outlives('b: 'a) => SubRegion('a, 'b)
401+ ty:: Contravariant => self . infcx . sub_regions ( a, b, VisibleForLeakCheck :: Yes , self . span ) ,
402+ ty:: Invariant => self . infcx . equate_regions ( a, b, VisibleForLeakCheck :: Yes , self . span ) ,
403+ ty:: Bivariant => {
404+ unreachable ! ( "Expected bivariance to be handled in relate_with_variance" )
261405 }
406+ }
262407
263- match self . ambient_variance {
264- ty:: Covariant => {
265- self . infcx
266- . register_solver_region_constraint ( RegionConstraint :: RegionOutlives ( a, b) ) ;
267- }
268- ty:: Contravariant => {
269- self . infcx
270- . register_solver_region_constraint ( RegionConstraint :: RegionOutlives ( b, a) ) ;
271- }
272- ty:: Invariant => {
273- self . infcx
274- . register_solver_region_constraint ( RegionConstraint :: RegionOutlives ( a, b) ) ;
275- self . infcx
276- . register_solver_region_constraint ( RegionConstraint :: RegionOutlives ( b, a) ) ;
277- }
278- ty:: Bivariant => {
279- unreachable ! ( "Expected bivariance to be handled in relate_with_variance" )
280- }
281- }
282- } else {
283- match self . ambient_variance {
284- // Subtype(&'a u8, &'b u8) => Outlives('a: 'b) => SubRegion('b, 'a)
285- ty:: Covariant => self . infcx . sub_regions ( b, a, VisibleForLeakCheck :: Yes , self . span ) ,
286- // Suptype(&'a u8, &'b u8) => Outlives('b: 'a) => SubRegion('a, 'b)
287- ty:: Contravariant => {
288- self . infcx . sub_regions ( a, b, VisibleForLeakCheck :: Yes , self . span )
289- }
290- ty:: Invariant => {
291- self . infcx . equate_regions ( a, b, VisibleForLeakCheck :: Yes , self . span )
292- }
293- ty:: Bivariant => {
294- unreachable ! ( "Expected bivariance to be handled in relate_with_variance" )
408+ let resolve_region = |r : I :: Region | match r. kind ( ) {
409+ ty:: ReVar ( vid) => self . infcx . opportunistic_resolve_lt_var ( vid) ,
410+ _ => r,
411+ } ;
412+ let a = resolve_region ( a) ;
413+ let b = resolve_region ( b) ;
414+
415+ if let Some ( region_constraints) = & mut self . region_constraints {
416+ if a == b {
417+ return Ok ( a) ;
418+ } else {
419+ match self . ambient_variance {
420+ ty:: Covariant => {
421+ region_constraints. push ( RegionConstraint :: RegionOutlives ( a, b) ) ;
422+ }
423+ ty:: Contravariant => {
424+ region_constraints. push ( RegionConstraint :: RegionOutlives ( b, a) ) ;
425+ }
426+ ty:: Invariant => {
427+ region_constraints. push ( RegionConstraint :: RegionOutlives ( a, b) ) ;
428+ region_constraints. push ( RegionConstraint :: RegionOutlives ( b, a) ) ;
429+ }
430+ ty:: Bivariant => {
431+ unreachable ! ( "Expected bivariance to be handled in relate_with_variance" )
432+ }
295433 }
296434 }
297435 }
0 commit comments