@@ -15,6 +15,7 @@ use middle::typeck::check::demand;
15
15
use middle:: typeck:: check:: { check_block, check_expr_has_type, FnCtxt } ;
16
16
use middle:: typeck:: check:: { instantiate_path, lookup_def} ;
17
17
use middle:: typeck:: check:: { structure_of, valid_range_bounds} ;
18
+ use middle:: typeck:: infer;
18
19
use middle:: typeck:: require_same_types;
19
20
20
21
use std:: hashmap:: { HashMap , HashSet } ;
@@ -29,26 +30,31 @@ pub fn check_match(fcx: @mut FnCtxt,
29
30
arms : & [ ast:: arm ] ) {
30
31
let tcx = fcx. ccx . tcx ;
31
32
32
- let pattern_ty = fcx. infcx ( ) . next_ty_var ( ) ;
33
- check_expr_has_type ( fcx, discrim, pattern_ty ) ;
33
+ let discrim_ty = fcx. infcx ( ) . next_ty_var ( ) ;
34
+ check_expr_has_type ( fcx, discrim, discrim_ty ) ;
34
35
35
36
// Typecheck the patterns first, so that we get types for all the
36
37
// bindings.
37
38
for arms . iter( ) . advance |arm| {
38
39
let pcx = pat_ctxt {
39
40
fcx : fcx,
40
41
map : pat_id_map( tcx. def_map, arm. pats[ 0 ] ) ,
41
- match_region : ty:: re_scope( expr. id) ,
42
- block_region : ty:: re_scope( arm. body. node. id)
43
42
} ;
44
43
45
- for arm. pats. iter( ) . advance |p| { check_pat( & pcx, * p, pattern_ty ) ; }
44
+ for arm. pats. iter( ) . advance |p| { check_pat( & pcx, * p, discrim_ty ) ; }
46
45
}
47
46
47
+ // The result of the match is the common supertype of all the
48
+ // arms. Start out the value as bottom, since it's the, well,
49
+ // bottom the type lattice, and we'll be moving up the lattice as
50
+ // we process each arm. (Note that any match with 0 arms is matching
51
+ // on any empty type and is therefore unreachable; should the flow
52
+ // of execution reach it, we will fail, so bottom is an appropriate
53
+ // type in that case)
54
+ let mut result_ty = ty:: mk_bot ( ) ;
55
+
48
56
// Now typecheck the blocks.
49
- let mut result_ty = fcx. infcx ( ) . next_ty_var ( ) ;
50
- let mut arm_non_bot = false ;
51
- let mut saw_err = false ;
57
+ let mut saw_err = ty:: type_is_error ( discrim_ty) ;
52
58
for arms. iter( ) . advance |arm| {
53
59
let mut guard_err = false;
54
60
let mut guard_bot = false;
@@ -75,26 +81,28 @@ pub fn check_match(fcx: @mut FnCtxt,
75
81
else if guard_bot {
76
82
fcx. write_bot ( arm. body . node . id ) ;
77
83
}
78
- else if !ty:: type_is_bot ( bty) {
79
- arm_non_bot = true ; // If the match *may* evaluate to a non-_|_
80
- // expr, the whole thing is non-_|_
81
- }
82
- demand:: suptype ( fcx, arm. body . span , result_ty, bty) ;
84
+
85
+ result_ty =
86
+ infer:: common_supertype (
87
+ fcx. infcx ( ) ,
88
+ infer:: MatchExpression ( expr. span ) ,
89
+ true , // result_ty is "expected" here
90
+ result_ty,
91
+ bty) ;
83
92
}
93
+
84
94
if saw_err {
85
95
result_ty = ty:: mk_err ( ) ;
86
- }
87
- else if !arm_non_bot {
96
+ } else if ty:: type_is_bot ( discrim_ty) {
88
97
result_ty = ty:: mk_bot ( ) ;
89
98
}
99
+
90
100
fcx. write_ty ( expr. id , result_ty) ;
91
101
}
92
102
93
103
pub struct pat_ctxt {
94
104
fcx : @mut FnCtxt ,
95
105
map : PatIdMap ,
96
- match_region : ty:: Region , // Region for the match as a whole
97
- block_region : ty:: Region , // Region for the block of the arm
98
106
}
99
107
100
108
pub fn check_pat_variant( pcx : & pat_ctxt , pat : @ast:: pat , path : @ast:: Path ,
@@ -442,8 +450,8 @@ pub fn check_pat(pcx: &pat_ctxt, pat: @ast::pat, expected: ty::t) {
442
450
// then the type of x is &M T where M is the mutability
443
451
// and T is the expected type
444
452
let region_var =
445
- fcx.infcx().next_region_var_with_lb (
446
- pat.span, pcx.block_region );
453
+ fcx.infcx().next_region_var (
454
+ infer::PatternRegion( pat.span) );
447
455
let mt = ty::mt {ty: expected, mutbl: mutbl};
448
456
let region_ty = ty::mk_rptr(tcx, region_var, mt);
449
457
demand::eqtype(fcx, pat.span, region_ty, typ);
@@ -544,9 +552,8 @@ pub fn check_pat(pcx: &pat_ctxt, pat: @ast::pat, expected: ty::t) {
544
552
}
545
553
ast::pat_vec(ref before, slice, ref after) => {
546
554
let default_region_var =
547
- fcx.infcx().next_region_var_with_lb(
548
- pat.span, pcx.block_region
549
- );
555
+ fcx.infcx().next_region_var(
556
+ infer::PatternRegion(pat.span));
550
557
551
558
let (elt_type, region_var) = match structure_of(
552
559
fcx, pat.span, expected
@@ -651,3 +658,4 @@ pub fn check_pointer_pat(pcx: &pat_ctxt,
651
658
652
659
#[ deriving( Eq ) ]
653
660
enum PointerKind { Managed , Send , Borrowed }
661
+
0 commit comments