8
8
// option. This file may not be copied, modified, or distributed
9
9
// except according to those terms.
10
10
11
- // ______________________________________________________________________
12
- // Type combining
11
+ ///////////////////////////////////////////////////////////////////////////
12
+ // # Type combining
13
13
//
14
- // There are three type combiners: sub, lub, and glb. Each implements
15
- // the trait `Combine` and contains methods for combining two
16
- // instances of various things and yielding a new instance. These
17
- // combiner methods always yield a `result<T>`---failure is propagated
18
- // upward using `and_then()` methods. There is a lot of common code for
19
- // these operations, implemented as default methods on the `Combine`
20
- // trait.
14
+ // There are four type combiners: equate, sub, lub, and glb. Each
15
+ // implements the trait `Combine` and contains methods for combining
16
+ // two instances of various things and yielding a new instance. These
17
+ // combiner methods always yield a `Result<T>`. There is a lot of
18
+ // common code for these operations, implemented as default methods on
19
+ // the `Combine` trait.
21
20
//
22
- // In reality, the sub operation is rather different from lub/glb, but
23
- // they are combined into one trait to avoid duplication (they used to
24
- // be separate but there were many bugs because there were two copies
25
- // of most routines) .
21
+ // Each operation may have side-effects on the inference context,
22
+ // though these can be unrolled using snapshots. On success, the
23
+ // LUB/GLB operations return the appropriate bound. The Eq and Sub
24
+ // operations generally return the first operand .
26
25
//
27
- // The differences are:
28
- //
29
- // - when making two things have a sub relationship, the order of the
30
- // arguments is significant (a <: b) and the return value of the
31
- // combine functions is largely irrelevant. The important thing is
32
- // whether the action succeeds or fails. If it succeeds, then side
33
- // effects have been committed into the type variables.
34
- //
35
- // - for GLB/LUB, the order of arguments is not significant (GLB(a,b) ==
36
- // GLB(b,a)) and the return value is important (it is the GLB). Of
37
- // course GLB/LUB may also have side effects.
38
- //
39
- // Contravariance
26
+ // ## Contravariance
40
27
//
41
28
// When you are relating two things which have a contravariant
42
29
// relationship, you should use `contratys()` or `contraregions()`,
43
30
// rather than inversing the order of arguments! This is necessary
44
31
// because the order of arguments is not relevant for LUB and GLB. It
45
32
// is also useful to track which value is the "expected" value in
46
- // terms of error reporting, although we do not do that properly right
47
- // now.
33
+ // terms of error reporting.
48
34
49
35
50
36
use middle:: subst;
@@ -53,14 +39,16 @@ use middle::ty::{FloatVar, FnSig, IntVar, TyVar};
53
39
use middle:: ty:: { IntType , UintType } ;
54
40
use middle:: ty:: { BuiltinBounds } ;
55
41
use middle:: ty;
56
- use middle:: typeck:: infer:: { ToUres } ;
42
+ use middle:: typeck:: infer:: equate :: Equate ;
57
43
use middle:: typeck:: infer:: glb:: Glb ;
58
44
use middle:: typeck:: infer:: lub:: Lub ;
59
45
use middle:: typeck:: infer:: sub:: Sub ;
60
46
use middle:: typeck:: infer:: unify:: InferCtxtMethodsForSimplyUnifiableTypes ;
61
- use middle:: typeck:: infer:: { InferCtxt , cres, ures} ;
62
- use middle:: typeck:: infer:: { TypeTrace } ;
63
- use util:: common:: indent;
47
+ use middle:: typeck:: infer:: { InferCtxt , cres} ;
48
+ use middle:: typeck:: infer:: { MiscVariable , TypeTrace } ;
49
+ use middle:: typeck:: infer:: type_variable:: { RelationDir , EqTo ,
50
+ SubtypeOf , SupertypeOf } ;
51
+ use middle:: ty_fold:: { RegionFolder , TypeFoldable } ;
64
52
use util:: ppaux:: Repr ;
65
53
66
54
use std:: result;
@@ -75,6 +63,7 @@ pub trait Combine {
75
63
fn a_is_expected ( & self ) -> bool ;
76
64
fn trace ( & self ) -> TypeTrace ;
77
65
66
+ fn equate < ' a > ( & ' a self ) -> Equate < ' a > ;
78
67
fn sub < ' a > ( & ' a self ) -> Sub < ' a > ;
79
68
fn lub < ' a > ( & ' a self ) -> Lub < ' a > ;
80
69
fn glb < ' a > ( & ' a self ) -> Glb < ' a > ;
@@ -101,7 +90,7 @@ pub trait Combine {
101
90
try!( result:: fold_ ( as_
102
91
. iter ( )
103
92
. zip ( bs. iter ( ) )
104
- . map ( |( a, b) | eq_tys ( self , * a, * b) ) ) ) ;
93
+ . map ( |( a, b) | self . equate ( ) . tys ( * a, * b) ) ) ) ;
105
94
Ok ( Vec :: from_slice ( as_) )
106
95
}
107
96
@@ -177,10 +166,7 @@ pub trait Combine {
177
166
let b_r = b_rs[ i] ;
178
167
let variance = variances[ i] ;
179
168
let r = match variance {
180
- ty:: Invariant => {
181
- eq_regions ( this, a_r, b_r)
182
- . and_then ( |( ) | Ok ( a_r) )
183
- }
169
+ ty:: Invariant => this. equate ( ) . regions ( a_r, b_r) ,
184
170
ty:: Covariant => this. regions ( a_r, b_r) ,
185
171
ty:: Contravariant => this. contraregions ( a_r, b_r) ,
186
172
ty:: Bivariant => Ok ( a_r) ,
@@ -334,34 +320,6 @@ pub fn expected_found<C:Combine,T>(
334
320
}
335
321
}
336
322
337
- pub fn eq_tys < C : Combine > ( this : & C , a : ty:: t , b : ty:: t ) -> ures {
338
- let suber = this. sub ( ) ;
339
- this. infcx ( ) . try ( || {
340
- suber. tys ( a, b) . and_then ( |_ok| suber. contratys ( a, b) ) . to_ures ( )
341
- } )
342
- }
343
-
344
- pub fn eq_regions < C : Combine > ( this : & C , a : ty:: Region , b : ty:: Region )
345
- -> ures {
346
- debug ! ( "eq_regions({}, {})" ,
347
- a. repr( this. infcx( ) . tcx) ,
348
- b. repr( this. infcx( ) . tcx) ) ;
349
- let sub = this. sub ( ) ;
350
- indent ( || {
351
- this. infcx ( ) . try ( || {
352
- sub. regions ( a, b) . and_then ( |_r| sub. contraregions ( a, b) )
353
- } ) . or_else ( |e| {
354
- // substitute a better error, but use the regions
355
- // found in the original error
356
- match e {
357
- ty:: terr_regions_does_not_outlive( a1, b1) =>
358
- Err ( ty:: terr_regions_not_same ( a1, b1) ) ,
359
- _ => Err ( e)
360
- }
361
- } ) . to_ures ( )
362
- } )
363
- }
364
-
365
323
pub fn super_fn_sigs < C : Combine > ( this : & C , a : & ty:: FnSig , b : & ty:: FnSig ) -> cres < ty:: FnSig > {
366
324
367
325
fn argvecs < C : Combine > ( this : & C , a_args : & [ ty:: t ] , b_args : & [ ty:: t ] ) -> cres < Vec < ty:: t > > {
@@ -453,8 +411,7 @@ pub fn super_tys<C:Combine>(this: &C, a: ty::t, b: ty::t) -> cres<ty::t> {
453
411
454
412
// Relate floating-point variables to other types
455
413
( & ty:: ty_infer( FloatVar ( a_id) ) , & ty:: ty_infer( FloatVar ( b_id) ) ) => {
456
- try!( this. infcx ( ) . simple_vars ( this. a_is_expected ( ) ,
457
- a_id, b_id) ) ;
414
+ try!( this. infcx ( ) . simple_vars ( this. a_is_expected ( ) , a_id, b_id) ) ;
458
415
Ok ( a)
459
416
}
460
417
( & ty:: ty_infer( FloatVar ( v_id) ) , & ty:: ty_float( v) ) => {
@@ -469,7 +426,8 @@ pub fn super_tys<C:Combine>(this: &C, a: ty::t, b: ty::t) -> cres<ty::t> {
469
426
( & ty:: ty_bool, _) |
470
427
( & ty:: ty_int( _) , _) |
471
428
( & ty:: ty_uint( _) , _) |
472
- ( & ty:: ty_float( _) , _) => {
429
+ ( & ty:: ty_float( _) , _) |
430
+ ( & ty:: ty_err, _) => {
473
431
if ty:: get ( a) . sty == ty:: get ( b) . sty {
474
432
Ok ( a)
475
433
} else {
@@ -512,7 +470,10 @@ pub fn super_tys<C:Combine>(this: &C, a: ty::t, b: ty::t) -> cres<ty::t> {
512
470
( & ty:: ty_unboxed_closure( a_id, a_region) ,
513
471
& ty:: ty_unboxed_closure( b_id, b_region) )
514
472
if a_id == b_id => {
515
- let region = if_ok ! ( this. regions( a_region, b_region) ) ;
473
+ // All ty_unboxed_closure types with the same id represent
474
+ // the (anonymous) type of the same closure expression. So
475
+ // all of their regions should be equated.
476
+ let region = try!( this. equate ( ) . regions ( a_region, b_region) ) ;
516
477
Ok ( ty:: mk_unboxed_closure ( tcx, a_id, region) )
517
478
}
518
479
@@ -609,3 +570,118 @@ pub fn super_tys<C:Combine>(this: &C, a: ty::t, b: ty::t) -> cres<ty::t> {
609
570
Ok ( ty:: mk_mach_float ( val) )
610
571
}
611
572
}
573
+
574
+ impl < ' f > CombineFields < ' f > {
575
+ pub fn switch_expected ( & self ) -> CombineFields < ' f > {
576
+ CombineFields {
577
+ a_is_expected : !self . a_is_expected ,
578
+ ..( * self ) . clone ( )
579
+ }
580
+ }
581
+
582
+ fn equate ( & self ) -> Equate < ' f > {
583
+ Equate ( ( * self ) . clone ( ) )
584
+ }
585
+
586
+ fn sub ( & self ) -> Sub < ' f > {
587
+ Sub ( ( * self ) . clone ( ) )
588
+ }
589
+
590
+ pub fn instantiate ( & self ,
591
+ a_ty : ty:: t ,
592
+ dir : RelationDir ,
593
+ b_vid : ty:: TyVid )
594
+ -> cres < ( ) >
595
+ {
596
+ let tcx = self . infcx . tcx ;
597
+ let mut stack = Vec :: new ( ) ;
598
+ stack. push ( ( a_ty, dir, b_vid) ) ;
599
+ loop {
600
+ // For each turn of the loop, we extract a tuple
601
+ //
602
+ // (a_ty, dir, b_vid)
603
+ //
604
+ // to relate. Here dir is either SubtypeOf or
605
+ // SupertypeOf. The idea is that we should ensure that
606
+ // the type `a_ty` is a subtype or supertype (respectively) of the
607
+ // type to which `b_vid` is bound.
608
+ //
609
+ // If `b_vid` has not yet been instantiated with a type
610
+ // (which is always true on the first iteration, but not
611
+ // necessarily true on later iterations), we will first
612
+ // instantiate `b_vid` with a *generalized* version of
613
+ // `a_ty`. Generalization introduces other inference
614
+ // variables whereever subtyping could occur (at time of
615
+ // this writing, this means replacing free regions with
616
+ // region variables).
617
+ let ( a_ty, dir, b_vid) = match stack. pop ( ) {
618
+ None => break ,
619
+ Some ( e) => e,
620
+ } ;
621
+
622
+ debug ! ( "instantiate(a_ty={} dir={} b_vid={})" ,
623
+ a_ty. repr( tcx) ,
624
+ dir,
625
+ b_vid. repr( tcx) ) ;
626
+
627
+ // Check whether `vid` has been instantiated yet. If not,
628
+ // make a generalized form of `ty` and instantiate with
629
+ // that.
630
+ let b_ty = self . infcx . type_variables . borrow ( ) . probe ( b_vid) ;
631
+ let b_ty = match b_ty {
632
+ Some ( t) => t, // ...already instantiated.
633
+ None => { // ...not yet instantiated:
634
+ // Generalize type if necessary.
635
+ let generalized_ty = match dir {
636
+ EqTo => a_ty,
637
+ SupertypeOf | SubtypeOf => self . generalize ( a_ty)
638
+ } ;
639
+ debug ! ( "instantiate(a_ty={}, dir={}, \
640
+ b_vid={}, generalized_ty={})",
641
+ a_ty. repr( tcx) , dir, b_vid. repr( tcx) ,
642
+ generalized_ty. repr( tcx) ) ;
643
+ self . infcx . type_variables
644
+ . borrow_mut ( )
645
+ . instantiate_and_push (
646
+ b_vid, generalized_ty, & mut stack) ;
647
+ generalized_ty
648
+ }
649
+ } ;
650
+
651
+ // The original triple was `(a_ty, dir, b_vid)` -- now we have
652
+ // resolved `b_vid` to `b_ty`, so apply `(a_ty, dir, b_ty)`:
653
+ //
654
+ // FIXME: This code is non-ideal because all these subtype
655
+ // relations wind up attributed to the same spans. We need
656
+ // to associate causes/spans with each of the relations in
657
+ // the stack to get this right.
658
+ match dir {
659
+ EqTo => {
660
+ try!( self . equate ( ) . tys ( a_ty, b_ty) ) ;
661
+ }
662
+
663
+ SubtypeOf => {
664
+ try!( self . sub ( ) . tys ( a_ty, b_ty) ) ;
665
+ }
666
+
667
+ SupertypeOf => {
668
+ try!( self . sub ( ) . contratys ( a_ty, b_ty) ) ;
669
+ }
670
+ }
671
+ }
672
+
673
+ Ok ( ( ) )
674
+ }
675
+
676
+ fn generalize ( & self , t : ty:: t ) -> ty:: t {
677
+ // FIXME: This is non-ideal because we don't give a very descriptive
678
+ // origin for this region variable.
679
+
680
+ let infcx = self . infcx ;
681
+ let span = self . trace . origin . span ( ) ;
682
+ t. fold_with (
683
+ & mut RegionFolder :: regions (
684
+ self . infcx . tcx ,
685
+ |_| infcx. next_region_var ( MiscVariable ( span) ) ) )
686
+ }
687
+ }
0 commit comments