@@ -17,9 +17,9 @@ export new_infer_ctxt;
17
17
export mk_subty;
18
18
export mk_eqty;
19
19
export mk_assignty;
20
- export resolve_type_structure ;
21
- export fixup_vars ;
22
- export resolve_var ;
20
+ export resolve_shallow ;
21
+ export resolve_deep ;
22
+ export resolve_deep_var ;
23
23
export compare_tys;
24
24
export fixup_err, fixup_err_to_str;
25
25
@@ -92,16 +92,23 @@ fn compare_tys(tcx: ty::ctxt, a: ty::t, b: ty::t) -> ures {
92
92
mk_eqty ( infcx, a, b)
93
93
}
94
94
95
- fn resolve_type_structure ( cx : infer_ctxt , a : ty:: t ) -> fres < ty:: t > {
96
- cx. resolve_ty ( a)
95
+ // Resolves one level of type structure but not any type variables
96
+ // that may be nested within.
97
+ fn resolve_shallow ( cx : infer_ctxt , a : ty:: t ) -> fres < ty:: t > {
98
+ resolver ( cx, false , false ) . resolve ( a)
97
99
}
98
100
99
- fn resolve_var ( cx : infer_ctxt , vid : ty_vid ) -> fres < ty:: t > {
100
- cx. fixup_ty ( ty:: mk_var ( cx. tcx , vid) )
101
+ // see resolve_deep()
102
+ fn resolve_deep_var ( cx : infer_ctxt , vid : ty_vid ,
103
+ force_vars : bool ) -> fres < ty:: t > {
104
+ resolver ( cx, true , force_vars) . resolve ( ty:: mk_var ( cx. tcx , vid) )
101
105
}
102
106
103
- fn fixup_vars ( cx : infer_ctxt , a : ty:: t ) -> fres < ty:: t > {
104
- cx. fixup_ty ( a)
107
+ // Resolves all levels of type structure. If `force_vars` is true,
108
+ // then we will resolve unconstrained type/region variables to
109
+ // something arbitrary. Otherwise, we preserve them as variables.
110
+ fn resolve_deep ( cx : infer_ctxt , a : ty:: t , force_vars : bool ) -> fres < ty:: t > {
111
+ resolver ( cx, true , force_vars) . resolve ( a)
105
112
}
106
113
107
114
impl methods for ures {
@@ -555,141 +562,149 @@ impl unify_methods for infer_ctxt {
555
562
}
556
563
}
557
564
558
- impl resolve_methods for infer_ctxt {
559
- fn rok( t: ty:: t) -> fres < ty:: t > {
560
- #debug[ "Resolve OK: %s" , t. to_str( self ) ] ;
561
- ok( t)
562
- }
563
-
564
- fn rerr < T > ( v: fixup_err) -> fres < T > {
565
- #debug[ "Resolve error: %?" , v] ;
566
- err( v)
567
- }
565
+ // Resolution is the process of removing type variables and replacing
566
+ // them with their inferred values. There are several "modes" for
567
+ // resolution. The first is a shallow resolution: this only resolves
568
+ // one layer, but does not resolve any nested variables. So, for
569
+ // example, if we have two variables A and B, and the constraint that
570
+ // A <: [B] and B <: int, then shallow resolution on A would yield
571
+ // [B]. Deep resolution, on the other hand, would yield [int].
572
+ //
573
+ // But there is one more knob: the force_vars variable controls the
574
+ // behavior in the face of unconstrained variables. If we have A, B
575
+ // and only the constraint that A <: B, then the result is [_|_] if
576
+ // force_vars is true and [B] otherwise. We use force_vars == true
577
+ // when resolving types after typeck, but false otherwise (for
578
+ // example, when pretty-printing them for errors).
579
+
580
+ type resolve_state = @{
581
+ infcx: infer_ctxt,
582
+ deep: bool,
583
+ force_vars: bool,
584
+ mut err: option < fixup_err > ,
585
+ mut r_seen: [ region_vid] ,
586
+ mut v_seen: [ ty_vid]
587
+ } ;
568
588
569
- fn resolve_var < V : copy vid, T : copy to_str > (
570
- vb: vals_and_bindings < V , T > , bot_guard: fn ( T ) ->bool,
571
- vid: V , unbound: fn ( ) -> fres < T > ) -> fres < T > {
589
+ fn resolver( infcx: infer_ctxt, deep: bool, fvars: bool ) -> resolve_state {
590
+ @{ infcx : infcx,
591
+ deep : deep,
592
+ force_vars : fvars,
593
+ mut err : none,
594
+ mut r_seen : [ ] ,
595
+ mut v_seen : [ ] }
596
+ }
572
597
573
- let { root: _, bounds} = self . get( vb, vid) ;
598
+ impl methods for resolve_state {
599
+ fn resolve( typ : ty:: t) -> fres < ty:: t > {
600
+ self . err = none;
574
601
575
- #debug [ "resolve_var(%s) bounds=%s" ,
576
- vid . to_str ( ) , bounds . to_str ( self ) ] ;
602
+ // n.b. This is a hokey mess because the current fold doesn't
603
+ // allow us to pass back errors in any useful way.
577
604
578
- // Nonobvious: prefer the most specific type
579
- // (i.e., the lower bound) to the more general
580
- // one. More general types in Rust (e.g., fn())
581
- // tend to carry more restrictions or higher
582
- // perf. penalties, so it pays to know more.
583
-
584
- alt bounds {
585
- { ub : _, lb : some( t) } if !bot_guard( t) { ok( t) }
586
- { ub: some( t) , lb: _ } { ok( t) }
587
- { ub: _, lb: some( t) } { ok( t) }
588
- { ub: none, lb: none } { unbound( ) }
605
+ assert vec:: is_empty( self . v_seen) && vec:: is_empty( self . r_seen) ;
606
+ let rty = self . resolve1( typ) ;
607
+ assert vec:: is_empty( self . v_seen) && vec:: is_empty( self . r_seen) ;
608
+ alt self. err {
609
+ none {
610
+ #debug[ "Resolved %s to %s (deep=%b, force_vars=%b)" ,
611
+ ty_to_str( self . infcx. tcx, typ) ,
612
+ ty_to_str( self . infcx. tcx, rty) ,
613
+ self . deep,
614
+ self . force_vars] ;
615
+ ret ok( rty) ;
616
+ }
617
+ some( e) { ret err( e) ; }
589
618
}
590
619
}
591
620
592
- fn resolve_ty_var( vid: ty_vid) -> fres < ty:: t > {
593
- ret self. resolve_var(
594
- self . vb,
595
- { |t| type_is_bot( t) } ,
596
- vid,
597
- { || ok( ty:: mk_bot( self . tcx) ) } ) ;
598
- }
599
-
600
- fn resolve_region_var( rid: region_vid) -> fres < ty:: region > {
601
- ret self. resolve_var(
602
- self . rb,
603
- { |_t| false } ,
604
- rid,
605
- { || ok( ty:: re_static) } ) ;
606
- }
607
-
608
- fn resolve_ty( typ: ty:: t) -> fres < ty:: t > {
609
- alt ty:: get( typ) . struct {
621
+ fn resolve1( typ: ty:: t) -> ty:: t {
622
+ let tb = ty:: get( typ) ;
623
+ alt tb. struct {
610
624
ty:: ty_var( vid) { self . resolve_ty_var( vid) }
611
- ty :: ty_rptr ( ty :: re_var ( rid ) , base_ty ) {
612
- alt self . resolve_region_var ( rid ) {
613
- err ( terr ) { err ( terr ) }
614
- ok ( region ) {
615
- self . rok ( ty :: mk_rptr ( self . tcx , region , base_ty ) )
616
- }
617
- }
625
+ _ if !tb . has_regions && ! self . deep { typ }
626
+ _ {
627
+ ty :: fold_regions_and_ty (
628
+ self . infcx . tcx , typ ,
629
+ { |r| self . resolve_region ( r ) } ,
630
+ { |t| self . resolve_if_deep ( t ) } ,
631
+ { |t| self . resolve_if_deep ( t ) } )
618
632
}
619
- _ { self . rok( typ) }
620
633
}
621
634
}
622
635
623
- fn fixup_region( r: ty:: region,
624
- & r_seen: [ region_vid] ,
625
- err: @mut option < fixup_err > ) -> ty:: region {
626
- alt r {
627
- ty : : re_var( rid) if vec:: contains( r_seen, rid) {
628
- * err = some( cyclic_region( rid) ) ; r
629
- }
636
+ fn resolve_if_deep( typ: ty:: t) -> ty:: t {
637
+ if !self . deep { typ} else { self . resolve1( typ) }
638
+ }
630
639
631
- ty:: re_var( rid) {
632
- alt self. resolve_region_var( rid) {
633
- result:: ok( r1) {
634
- vec:: push( r_seen, rid) ;
635
- let r2 = self . fixup_region( r1, r_seen, err) ;
636
- vec:: pop( r_seen) ;
637
- ret r2;
638
- }
639
- result:: err( e) { * err = some( e) ; r }
640
- }
641
- }
640
+ fn resolve_region( orig: ty:: region) -> ty:: region {
641
+ alt orig {
642
+ ty:: re_var( rid) { self . resolve_region_var( rid) }
643
+ _ { orig }
644
+ }
645
+ }
642
646
643
- _ { r }
647
+ fn resolve_region_var( rid: region_vid) -> ty:: region {
648
+ if vec:: contains( self . r_seen, rid) {
649
+ self . err = some( cyclic_region( rid) ) ;
650
+ ret ty:: re_var( rid) ;
651
+ } else {
652
+ vec:: push( self . r_seen, rid) ;
653
+ let r = self . resolve_var(
654
+ self . infcx. rb,
655
+ { |_t| false } ,
656
+ rid,
657
+ { ||
658
+ if self . force_vars { ty:: re_static}
659
+ else { ty:: re_var( rid) }
660
+ } ) ;
661
+ vec:: pop( self . r_seen) ;
662
+ ret r;
663
+ }
664
+ }
665
+
666
+ fn resolve_ty_var( vid: ty_vid) -> ty:: t {
667
+ if vec:: contains( self . v_seen, vid) {
668
+ self . err = some( cyclic_ty( vid) ) ;
669
+ ret ty:: mk_var( self . infcx. tcx, vid) ;
670
+ } else {
671
+ vec:: push( self . v_seen, vid) ;
672
+ let tcx = self . infcx. tcx;
673
+ let t0 = self . resolve_var(
674
+ self . infcx. vb,
675
+ { |t| type_is_bot( t) } ,
676
+ vid,
677
+ { ||
678
+ if self . force_vars { ty:: mk_bot( tcx) }
679
+ else { ty:: mk_var( tcx, vid) }
680
+ } ) ;
681
+ let t1 = self . resolve1( t0) ;
682
+ vec:: pop( self . v_seen) ;
683
+ ret t1;
644
684
}
645
685
}
646
686
647
- fn fixup_ty1( ty: ty:: t,
648
- & ty_seen: [ ty_vid] ,
649
- & r_seen: [ region_vid] ,
650
- err: @mut option < fixup_err > ) -> ty:: t {
651
- let tb = ty:: get( ty) ;
652
- if !tb. has_vars { ret ty; }
653
- alt tb . struct {
654
- ty : : ty_var( vid) if vec:: contains( ty_seen, vid) {
655
- * err = some( cyclic_ty( vid) ) ; ty
656
- }
687
+ fn resolve_var<V : copy vid, T : copy to_str>(
688
+ vb: vals_and_bindings<V , T >, bot_guard: fn ( T ) ->bool ,
689
+ vid: V , unbound: fn ( ) -> T ) -> T {
657
690
658
- ty:: ty_var( vid) {
659
- alt self. resolve_ty_var( vid) {
660
- result:: err( e) { * err = some( e) ; ty }
661
- result:: ok( ty1) {
662
- vec:: push( ty_seen, vid) ;
663
- let ty2 = self . fixup_ty1( ty1, ty_seen, r_seen, err) ;
664
- vec:: pop( ty_seen) ;
665
- ret ty2;
666
- }
667
- }
668
- }
691
+ let { root: _, bounds} = self . infcx. get( vb, vid) ;
669
692
670
- ty:: ty_rptr( r, { ty: base_ty, mutbl: m} ) {
671
- let base_ty1 = self . fixup_ty1( base_ty, ty_seen, r_seen, err) ;
672
- let r1 = self . fixup_region( r, r_seen, err) ;
673
- ret ty:: mk_rptr( self . tcx, r1, { ty: base_ty1, mutbl: m} ) ;
674
- }
693
+ #debug[ "resolve_var( %s) bounds=%s",
694
+ vid. to_str( ) ,
695
+ bounds. to_str( self . infcx) ] ;
675
696
676
- sty {
677
- ty : : fold_sty_to_ty( self . tcx, sty) { |t|
678
- self . fixup_ty1( t, ty_seen, r_seen, err)
679
- }
680
- }
681
- }
682
- }
697
+ // Nonobvious: prefer the most specific type
698
+ // (i.e., the lower bound) to the more general
699
+ // one. More general types in Rust (e.g., fn())
700
+ // tend to carry more restrictions or higher
701
+ // perf. penalties, so it pays to know more.
683
702
684
- fn fixup_ty( typ: ty:: t) -> fres < ty:: t > {
685
- #debug[ "fixup_ty(%s)" , ty_to_str( self . tcx, typ) ] ;
686
- let mut ty_seen = [ ] ;
687
- let mut r_seen = [ ] ;
688
- let unresolved = @mut none;
689
- let rty = self . fixup_ty1( typ, ty_seen, r_seen, unresolved) ;
690
- alt * unresolved {
691
- none { ret self . rok( rty) ; }
692
- some( e) { ret self . rerr( e) ; }
703
+ alt bounds {
704
+ { ub: _, lb: some( t) } if !bot_guard( t) { t }
705
+ { ub: some( t) , lb: _ } { t }
706
+ { ub: _, lb: some( t) } { t }
707
+ { ub: none, lb: none } { unbound( ) }
693
708
}
694
709
}
695
710
}
0 commit comments