@@ -195,261 +195,6 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
195195 Ok ( HrMatchResult { value : a_value } )
196196 } ) ;
197197 }
198-
199- pub fn higher_ranked_lub < T > ( & mut self , a : & Binder < T > , b : & Binder < T > , a_is_expected : bool )
200- -> RelateResult < ' tcx , Binder < T > >
201- where T : Relate < ' tcx >
202- {
203- // Start a snapshot so we can examine "all bindings that were
204- // created as part of this type comparison".
205- return self . infcx . commit_if_ok ( |snapshot| {
206- // Instantiate each bound region with a fresh region variable.
207- let span = self . trace . cause . span ;
208- let ( a_with_fresh, a_map) =
209- self . infcx . replace_late_bound_regions_with_fresh_var (
210- span, HigherRankedType , a) ;
211- let ( b_with_fresh, _) =
212- self . infcx . replace_late_bound_regions_with_fresh_var (
213- span, HigherRankedType , b) ;
214-
215- // Collect constraints.
216- let result0 =
217- self . lub ( a_is_expected) . relate ( & a_with_fresh, & b_with_fresh) ?;
218- let result0 =
219- self . infcx . resolve_type_vars_if_possible ( & result0) ;
220- debug ! ( "lub result0 = {:?}" , result0) ;
221-
222- // Generalize the regions appearing in result0 if possible
223- let new_vars = self . infcx . region_vars_confined_to_snapshot ( snapshot) ;
224- let span = self . trace . cause . span ;
225- let result1 =
226- fold_regions_in (
227- self . tcx ( ) ,
228- & result0,
229- |r, debruijn| generalize_region ( self . infcx , span, snapshot, debruijn,
230- & new_vars, & a_map, r) ) ;
231-
232- debug ! ( "lub({:?},{:?}) = {:?}" ,
233- a,
234- b,
235- result1) ;
236-
237- Ok ( ty:: Binder ( result1) )
238- } ) ;
239-
240- fn generalize_region < ' a , ' gcx , ' tcx > ( infcx : & InferCtxt < ' a , ' gcx , ' tcx > ,
241- span : Span ,
242- snapshot : & CombinedSnapshot ,
243- debruijn : ty:: DebruijnIndex ,
244- new_vars : & [ ty:: RegionVid ] ,
245- a_map : & FxHashMap < ty:: BoundRegion , ty:: Region < ' tcx > > ,
246- r0 : ty:: Region < ' tcx > )
247- -> ty:: Region < ' tcx > {
248- // Regions that pre-dated the LUB computation stay as they are.
249- if !is_var_in_set ( new_vars, r0) {
250- assert ! ( !r0. is_late_bound( ) ) ;
251- debug ! ( "generalize_region(r0={:?}): not new variable" , r0) ;
252- return r0;
253- }
254-
255- let tainted = infcx. tainted_regions ( snapshot, r0, TaintDirections :: both ( ) ) ;
256-
257- // Variables created during LUB computation which are
258- // *related* to regions that pre-date the LUB computation
259- // stay as they are.
260- if !tainted. iter ( ) . all ( |& r| is_var_in_set ( new_vars, r) ) {
261- debug ! ( "generalize_region(r0={:?}): \
262- non-new-variables found in {:?}",
263- r0, tainted) ;
264- assert ! ( !r0. is_late_bound( ) ) ;
265- return r0;
266- }
267-
268- // Otherwise, the variable must be associated with at
269- // least one of the variables representing bound regions
270- // in both A and B. Replace the variable with the "first"
271- // bound region from A that we find it to be associated
272- // with.
273- for ( a_br, a_r) in a_map {
274- if tainted. iter ( ) . any ( |x| x == a_r) {
275- debug ! ( "generalize_region(r0={:?}): \
276- replacing with {:?}, tainted={:?}",
277- r0, * a_br, tainted) ;
278- return infcx. tcx . mk_region ( ty:: ReLateBound ( debruijn, * a_br) ) ;
279- }
280- }
281-
282- span_bug ! (
283- span,
284- "region {:?} is not associated with any bound region from A!" ,
285- r0)
286- }
287- }
288-
289- pub fn higher_ranked_glb < T > ( & mut self , a : & Binder < T > , b : & Binder < T > , a_is_expected : bool )
290- -> RelateResult < ' tcx , Binder < T > >
291- where T : Relate < ' tcx >
292- {
293- debug ! ( "higher_ranked_glb({:?}, {:?})" ,
294- a, b) ;
295-
296- // Make a snapshot so we can examine "all bindings that were
297- // created as part of this type comparison".
298- return self . infcx . commit_if_ok ( |snapshot| {
299- // Instantiate each bound region with a fresh region variable.
300- let ( a_with_fresh, a_map) =
301- self . infcx . replace_late_bound_regions_with_fresh_var (
302- self . trace . cause . span , HigherRankedType , a) ;
303- let ( b_with_fresh, b_map) =
304- self . infcx . replace_late_bound_regions_with_fresh_var (
305- self . trace . cause . span , HigherRankedType , b) ;
306- let a_vars = var_ids ( self , & a_map) ;
307- let b_vars = var_ids ( self , & b_map) ;
308-
309- // Collect constraints.
310- let result0 =
311- self . glb ( a_is_expected) . relate ( & a_with_fresh, & b_with_fresh) ?;
312- let result0 =
313- self . infcx . resolve_type_vars_if_possible ( & result0) ;
314- debug ! ( "glb result0 = {:?}" , result0) ;
315-
316- // Generalize the regions appearing in result0 if possible
317- let new_vars = self . infcx . region_vars_confined_to_snapshot ( snapshot) ;
318- let span = self . trace . cause . span ;
319- let result1 =
320- fold_regions_in (
321- self . tcx ( ) ,
322- & result0,
323- |r, debruijn| generalize_region ( self . infcx , span, snapshot, debruijn,
324- & new_vars,
325- & a_map, & a_vars, & b_vars,
326- r) ) ;
327-
328- debug ! ( "glb({:?},{:?}) = {:?}" ,
329- a,
330- b,
331- result1) ;
332-
333- Ok ( ty:: Binder ( result1) )
334- } ) ;
335-
336- fn generalize_region < ' a , ' gcx , ' tcx > ( infcx : & InferCtxt < ' a , ' gcx , ' tcx > ,
337- span : Span ,
338- snapshot : & CombinedSnapshot ,
339- debruijn : ty:: DebruijnIndex ,
340- new_vars : & [ ty:: RegionVid ] ,
341- a_map : & FxHashMap < ty:: BoundRegion , ty:: Region < ' tcx > > ,
342- a_vars : & [ ty:: RegionVid ] ,
343- b_vars : & [ ty:: RegionVid ] ,
344- r0 : ty:: Region < ' tcx > )
345- -> ty:: Region < ' tcx > {
346- if !is_var_in_set ( new_vars, r0) {
347- assert ! ( !r0. is_late_bound( ) ) ;
348- return r0;
349- }
350-
351- let tainted = infcx. tainted_regions ( snapshot, r0, TaintDirections :: both ( ) ) ;
352-
353- let mut a_r = None ;
354- let mut b_r = None ;
355- let mut only_new_vars = true ;
356- for r in & tainted {
357- if is_var_in_set ( a_vars, * r) {
358- if a_r. is_some ( ) {
359- return fresh_bound_variable ( infcx, debruijn) ;
360- } else {
361- a_r = Some ( * r) ;
362- }
363- } else if is_var_in_set ( b_vars, * r) {
364- if b_r. is_some ( ) {
365- return fresh_bound_variable ( infcx, debruijn) ;
366- } else {
367- b_r = Some ( * r) ;
368- }
369- } else if !is_var_in_set ( new_vars, * r) {
370- only_new_vars = false ;
371- }
372- }
373-
374- // NB---I do not believe this algorithm computes
375- // (necessarily) the GLB. As written it can
376- // spuriously fail. In particular, if there is a case
377- // like: |fn(&a)| and fn(fn(&b)), where a and b are
378- // free, it will return fn(&c) where c = GLB(a,b). If
379- // however this GLB is not defined, then the result is
380- // an error, even though something like
381- // "fn<X>(fn(&X))" where X is bound would be a
382- // subtype of both of those.
383- //
384- // The problem is that if we were to return a bound
385- // variable, we'd be computing a lower-bound, but not
386- // necessarily the *greatest* lower-bound.
387- //
388- // Unfortunately, this problem is non-trivial to solve,
389- // because we do not know at the time of computing the GLB
390- // whether a GLB(a,b) exists or not, because we haven't
391- // run region inference (or indeed, even fully computed
392- // the region hierarchy!). The current algorithm seems to
393- // works ok in practice.
394-
395- if a_r. is_some ( ) && b_r. is_some ( ) && only_new_vars {
396- // Related to exactly one bound variable from each fn:
397- return rev_lookup ( infcx, span, a_map, a_r. unwrap ( ) ) ;
398- } else if a_r. is_none ( ) && b_r. is_none ( ) {
399- // Not related to bound variables from either fn:
400- assert ! ( !r0. is_late_bound( ) ) ;
401- return r0;
402- } else {
403- // Other:
404- return fresh_bound_variable ( infcx, debruijn) ;
405- }
406- }
407-
408- fn rev_lookup < ' a , ' gcx , ' tcx > ( infcx : & InferCtxt < ' a , ' gcx , ' tcx > ,
409- span : Span ,
410- a_map : & FxHashMap < ty:: BoundRegion , ty:: Region < ' tcx > > ,
411- r : ty:: Region < ' tcx > ) -> ty:: Region < ' tcx >
412- {
413- for ( a_br, a_r) in a_map {
414- if * a_r == r {
415- return infcx. tcx . mk_region ( ty:: ReLateBound ( ty:: DebruijnIndex :: new ( 1 ) , * a_br) ) ;
416- }
417- }
418- span_bug ! (
419- span,
420- "could not find original bound region for {:?}" ,
421- r) ;
422- }
423-
424- fn fresh_bound_variable < ' a , ' gcx , ' tcx > ( infcx : & InferCtxt < ' a , ' gcx , ' tcx > ,
425- debruijn : ty:: DebruijnIndex )
426- -> ty:: Region < ' tcx > {
427- infcx. region_vars . new_bound ( debruijn)
428- }
429- }
430- }
431-
432- fn var_ids < ' a , ' gcx , ' tcx > ( fields : & CombineFields < ' a , ' gcx , ' tcx > ,
433- map : & FxHashMap < ty:: BoundRegion , ty:: Region < ' tcx > > )
434- -> Vec < ty:: RegionVid > {
435- map. iter ( )
436- . map ( |( _, & r) | match * r {
437- ty:: ReVar ( r) => { r }
438- _ => {
439- span_bug ! (
440- fields. trace. cause. span,
441- "found non-region-vid: {:?}" ,
442- r) ;
443- }
444- } )
445- . collect ( )
446- }
447-
448- fn is_var_in_set ( new_vars : & [ ty:: RegionVid ] , r : ty:: Region ) -> bool {
449- match * r {
450- ty:: ReVar ( ref v) => new_vars. iter ( ) . any ( |x| x == v) ,
451- _ => false
452- }
453198}
454199
455200fn fold_regions_in < ' a , ' gcx , ' tcx , T , F > ( tcx : TyCtxt < ' a , ' gcx , ' tcx > ,
0 commit comments