@@ -32,17 +32,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
32
32
33
33
debug ! ( "check_pat(pat={:?},expected={:?})" , pat, expected) ;
34
34
35
- match pat. node {
35
+ let ty = match pat. node {
36
36
PatKind :: Wild => {
37
- self . write_ty ( pat . id , expected) ;
37
+ expected
38
38
}
39
39
PatKind :: Lit ( ref lt) => {
40
- self . check_expr ( & lt) ;
41
- let expr_ty = self . expr_ty ( & lt) ;
40
+ let ty = self . check_expr ( & lt) ;
42
41
43
42
// Byte string patterns behave the same way as array patterns
44
43
// They can denote both statically and dynamically sized byte arrays
45
- let mut pat_ty = expr_ty ;
44
+ let mut pat_ty = ty ;
46
45
if let hir:: ExprLit ( ref lt) = lt. node {
47
46
if let ast:: LitKind :: ByteStr ( _) = lt. node {
48
47
let expected_ty = self . structurally_resolved_type ( pat. span , expected) ;
@@ -55,28 +54,24 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
55
54
}
56
55
}
57
56
58
- self . write_ty ( pat. id , pat_ty) ;
59
-
60
57
// somewhat surprising: in this case, the subtyping
61
58
// relation goes the opposite way as the other
62
59
// cases. Actually what we really want is not a subtyping
63
60
// relation at all but rather that there exists a LUB (so
64
61
// that they can be compared). However, in practice,
65
62
// constants are always scalars or strings. For scalars
66
- // subtyping is irrelevant, and for strings `expr_ty ` is
63
+ // subtyping is irrelevant, and for strings `ty ` is
67
64
// type is `&'static str`, so if we say that
68
65
//
69
66
// &'static str <: expected
70
67
//
71
68
// that's equivalent to there existing a LUB.
72
69
self . demand_suptype ( pat. span , expected, pat_ty) ;
70
+ pat_ty
73
71
}
74
72
PatKind :: Range ( ref begin, ref end) => {
75
- self . check_expr ( begin) ;
76
- self . check_expr ( end) ;
77
-
78
- let lhs_ty = self . expr_ty ( begin) ;
79
- let rhs_ty = self . expr_ty ( end) ;
73
+ let lhs_ty = self . check_expr ( begin) ;
74
+ let rhs_ty = self . check_expr ( end) ;
80
75
81
76
// Check that both end-points are of numeric or char type.
82
77
let numeric_or_char = |ty : Ty | ty. is_numeric ( ) || ty. is_char ( ) ;
@@ -105,11 +100,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
105
100
// it to type the entire expression.
106
101
let common_type = self . resolve_type_vars_if_possible ( & lhs_ty) ;
107
102
108
- self . write_ty ( pat. id , common_type) ;
109
-
110
103
// subtyping doesn't matter here, as the value is some kind of scalar
111
104
self . demand_eqtype ( pat. span , expected, lhs_ty) ;
112
105
self . demand_eqtype ( pat. span , expected, rhs_ty) ;
106
+ common_type
113
107
}
114
108
PatKind :: Binding ( bm, _, ref sub) => {
115
109
let typ = self . local_ty ( pat. span , pat. id ) ;
@@ -136,8 +130,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
136
130
}
137
131
}
138
132
139
- self . write_ty ( pat. id , typ) ;
140
-
141
133
// if there are multiple arms, make sure they all agree on
142
134
// what the type of the binding `x` ought to be
143
135
match tcx. expect_def ( pat. id ) {
@@ -154,16 +146,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
154
146
if let Some ( ref p) = * sub {
155
147
self . check_pat ( & p, expected) ;
156
148
}
149
+
150
+ typ
157
151
}
158
152
PatKind :: TupleStruct ( ref path, ref subpats, ddpos) => {
159
- self . check_pat_tuple_struct ( pat, path, & subpats, ddpos, expected) ;
153
+ self . check_pat_tuple_struct ( pat, path, & subpats, ddpos, expected)
160
154
}
161
155
PatKind :: Path ( ref opt_qself, ref path) => {
162
156
let opt_qself_ty = opt_qself. as_ref ( ) . map ( |qself| self . to_ty ( & qself. ty ) ) ;
163
- self . check_pat_path ( pat, opt_qself_ty, path, expected) ;
157
+ self . check_pat_path ( pat, opt_qself_ty, path, expected)
164
158
}
165
159
PatKind :: Struct ( ref path, ref fields, etc) => {
166
- self . check_pat_struct ( pat, path, fields, etc, expected) ;
160
+ self . check_pat_struct ( pat, path, fields, etc, expected)
167
161
}
168
162
PatKind :: Tuple ( ref elements, ddpos) => {
169
163
let mut expected_len = elements. len ( ) ;
@@ -178,11 +172,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
178
172
179
173
let element_tys: Vec < _ > = ( 0 .. max_len) . map ( |_| self . next_ty_var ( ) ) . collect ( ) ;
180
174
let pat_ty = tcx. mk_tup ( element_tys. clone ( ) ) ;
181
- self . write_ty ( pat. id , pat_ty) ;
182
175
self . demand_eqtype ( pat. span , expected, pat_ty) ;
183
176
for ( i, elem) in elements. iter ( ) . enumerate_and_adjust ( max_len, ddpos) {
184
177
self . check_pat ( elem, & element_tys[ i] ) ;
185
178
}
179
+ pat_ty
186
180
}
187
181
PatKind :: Box ( ref inner) => {
188
182
let inner_ty = self . next_ty_var ( ) ;
@@ -193,11 +187,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
193
187
// think any errors can be introduced by using
194
188
// `demand::eqtype`.
195
189
self . demand_eqtype ( pat. span , expected, uniq_ty) ;
196
- self . write_ty ( pat. id , uniq_ty) ;
197
190
self . check_pat ( & inner, inner_ty) ;
191
+ uniq_ty
198
192
} else {
199
- self . write_error ( pat. id ) ;
200
193
self . check_pat ( & inner, tcx. types . err ) ;
194
+ tcx. types . err
201
195
}
202
196
}
203
197
PatKind :: Ref ( ref inner, mutbl) => {
@@ -225,11 +219,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
225
219
}
226
220
} ;
227
221
228
- self . write_ty ( pat. id , rptr_ty) ;
229
222
self . check_pat ( & inner, inner_ty) ;
223
+ rptr_ty
230
224
} else {
231
- self . write_error ( pat. id ) ;
232
225
self . check_pat ( & inner, tcx. types . err ) ;
226
+ tcx. types . err
233
227
}
234
228
}
235
229
PatKind :: Vec ( ref before, ref slice, ref after) => {
@@ -281,8 +275,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
281
275
}
282
276
} ;
283
277
284
- self . write_ty ( pat. id , expected_ty) ;
285
-
286
278
for elt in before {
287
279
self . check_pat ( & elt, inner_ty) ;
288
280
}
@@ -292,8 +284,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
292
284
for elt in after {
293
285
self . check_pat ( & elt, inner_ty) ;
294
286
}
287
+ expected_ty
295
288
}
296
- }
289
+ } ;
290
+
291
+ self . write_ty ( pat. id , ty) ;
297
292
298
293
// (*) In most of the cases above (literals and constants being
299
294
// the exception), we relate types using strict equality, evewn
@@ -371,7 +366,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
371
366
discrim : & ' gcx hir:: Expr ,
372
367
arms : & ' gcx [ hir:: Arm ] ,
373
368
expected : Expectation < ' tcx > ,
374
- match_src : hir:: MatchSource ) {
369
+ match_src : hir:: MatchSource ) -> Ty < ' tcx > {
375
370
let tcx = self . tcx ;
376
371
377
372
// Not entirely obvious: if matches may create ref bindings, we
@@ -385,8 +380,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
385
380
} ) ;
386
381
let discrim_ty;
387
382
if let Some ( m) = contains_ref_bindings {
388
- self . check_expr_with_lvalue_pref ( discrim, LvaluePreference :: from_mutbl ( m) ) ;
389
- discrim_ty = self . expr_ty ( discrim) ;
383
+ discrim_ty = self . check_expr_with_lvalue_pref ( discrim, LvaluePreference :: from_mutbl ( m) ) ;
390
384
} else {
391
385
// ...but otherwise we want to use any supertype of the
392
386
// discriminant. This is sort of a workaround, see note (*) in
@@ -425,12 +419,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
425
419
}
426
420
_ => result_ty
427
421
} ;
422
+
428
423
for ( i, arm) in arms. iter ( ) . enumerate ( ) {
429
424
if let Some ( ref e) = arm. guard {
430
425
self . check_expr_has_type ( e, tcx. types . bool ) ;
431
426
}
432
- self . check_expr_with_expectation ( & arm. body , expected) ;
433
- let arm_ty = self . expr_ty ( & arm. body ) ;
427
+ let arm_ty = self . check_expr_with_expectation ( & arm. body , expected) ;
434
428
435
429
if result_ty. references_error ( ) || arm_ty. references_error ( ) {
436
430
result_ty = tcx. types . err ;
@@ -460,10 +454,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
460
454
} )
461
455
} else if i == 0 {
462
456
// Special-case the first arm, as it has no "previous expressions".
463
- self . try_coerce ( & arm. body , coerce_first)
457
+ self . try_coerce ( & arm. body , arm_ty , coerce_first)
464
458
} else {
465
459
let prev_arms = || arms[ ..i] . iter ( ) . map ( |arm| & * arm. body ) ;
466
- self . try_find_coercion_lub ( origin, prev_arms, result_ty, & arm. body )
460
+ self . try_find_coercion_lub ( origin, prev_arms, result_ty, & arm. body , arm_ty )
467
461
} ;
468
462
469
463
result_ty = match result {
@@ -480,7 +474,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
480
474
} ;
481
475
}
482
476
483
- self . write_ty ( expr . id , result_ty) ;
477
+ result_ty
484
478
}
485
479
}
486
480
@@ -490,39 +484,38 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
490
484
path : & hir:: Path ,
491
485
fields : & ' gcx [ Spanned < hir:: FieldPat > ] ,
492
486
etc : bool ,
493
- expected : Ty < ' tcx > )
487
+ expected : Ty < ' tcx > ) -> Ty < ' tcx >
494
488
{
495
489
// Resolve the path and check the definition for errors.
496
490
let ( variant, pat_ty) = if let Some ( variant_ty) = self . check_struct_path ( path, pat. id ,
497
491
pat. span ) {
498
492
variant_ty
499
493
} else {
500
- self . write_error ( pat. id ) ;
501
494
for field in fields {
502
495
self . check_pat ( & field. node . pat , self . tcx . types . err ) ;
503
496
}
504
- return ;
497
+ return self . tcx . types . err ;
505
498
} ;
506
499
507
500
// Type check the path.
508
501
self . demand_eqtype ( pat. span , expected, pat_ty) ;
509
502
510
503
// Type check subpatterns.
511
504
self . check_struct_pat_fields ( pat_ty, pat. span , variant, fields, etc) ;
505
+ pat_ty
512
506
}
513
507
514
508
fn check_pat_path ( & self ,
515
509
pat : & hir:: Pat ,
516
510
opt_self_ty : Option < Ty < ' tcx > > ,
517
511
path : & hir:: Path ,
518
- expected : Ty < ' tcx > )
512
+ expected : Ty < ' tcx > ) -> Ty < ' tcx >
519
513
{
520
514
let tcx = self . tcx ;
521
515
let report_unexpected_def = || {
522
516
span_err ! ( tcx. sess, pat. span, E0533 ,
523
517
"`{}` does not name a unit variant, unit struct or a constant" ,
524
518
pprust:: path_to_string( path) ) ;
525
- self . write_error ( pat. id ) ;
526
519
} ;
527
520
528
521
// Resolve the path and check the definition for errors.
@@ -531,18 +524,17 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
531
524
match def {
532
525
Def :: Err => {
533
526
self . set_tainted_by_errors ( ) ;
534
- self . write_error ( pat. id ) ;
535
- return ;
527
+ return tcx. types . err ;
536
528
}
537
529
Def :: Method ( ..) => {
538
530
report_unexpected_def ( ) ;
539
- return ;
531
+ return tcx . types . err ;
540
532
}
541
533
Def :: Variant ( ..) | Def :: Struct ( ..) => {
542
534
let variant = tcx. expect_variant_def ( def) ;
543
535
if variant. kind != VariantKind :: Unit {
544
536
report_unexpected_def ( ) ;
545
- return ;
537
+ return tcx . types . err ;
546
538
}
547
539
}
548
540
Def :: Const ( ..) | Def :: AssociatedConst ( ..) => { } // OK
@@ -552,18 +544,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
552
544
// Type check the path.
553
545
let pat_ty = self . instantiate_value_path ( segments, opt_ty, def, pat. span , pat. id ) ;
554
546
self . demand_suptype ( pat. span , expected, pat_ty) ;
547
+ pat_ty
555
548
}
556
549
557
550
fn check_pat_tuple_struct ( & self ,
558
551
pat : & hir:: Pat ,
559
552
path : & hir:: Path ,
560
553
subpats : & ' gcx [ P < hir:: Pat > ] ,
561
554
ddpos : Option < usize > ,
562
- expected : Ty < ' tcx > )
555
+ expected : Ty < ' tcx > ) -> Ty < ' tcx >
563
556
{
564
557
let tcx = self . tcx ;
565
558
let on_error = || {
566
- self . write_error ( pat. id ) ;
567
559
for pat in subpats {
568
560
self . check_pat ( & pat, tcx. types . err ) ;
569
561
}
@@ -587,11 +579,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
587
579
Def :: Err => {
588
580
self . set_tainted_by_errors ( ) ;
589
581
on_error ( ) ;
590
- return ;
582
+ return tcx . types . err ;
591
583
}
592
584
Def :: Const ( ..) | Def :: AssociatedConst ( ..) | Def :: Method ( ..) => {
593
585
report_unexpected_def ( false ) ;
594
- return ;
586
+ return tcx . types . err ;
595
587
}
596
588
Def :: Variant ( ..) | Def :: Struct ( ..) => {
597
589
tcx. expect_variant_def ( def)
@@ -604,20 +596,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
604
596
report_unexpected_def ( true ) ;
605
597
} else if variant. kind != VariantKind :: Tuple {
606
598
report_unexpected_def ( false ) ;
607
- return ;
599
+ return tcx . types . err ;
608
600
}
609
601
610
602
// Type check the path.
611
603
let pat_ty = self . instantiate_value_path ( segments, opt_ty, def, pat. span , pat. id ) ;
612
-
613
604
let pat_ty = if pat_ty. is_fn ( ) {
614
605
// Replace constructor type with constructed type for tuple struct patterns.
615
606
tcx. no_late_bound_regions ( & pat_ty. fn_ret ( ) ) . unwrap ( )
616
607
} else {
617
608
// Leave the type as is for unit structs (backward compatibility).
618
609
pat_ty
619
610
} ;
620
- self . write_ty ( pat. id , pat_ty) ;
621
611
self . demand_eqtype ( pat. span , expected, pat_ty) ;
622
612
623
613
// Type check subpatterns.
@@ -650,7 +640,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
650
640
variant. fields. len( ) , fields_ending, subpats. len( ) ) )
651
641
. emit ( ) ;
652
642
on_error ( ) ;
643
+ return tcx. types . err ;
653
644
}
645
+ pat_ty
654
646
}
655
647
656
648
fn check_struct_pat_fields ( & self ,
0 commit comments