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