@@ -51,13 +51,13 @@ impl Usefulness {
51
51
}
52
52
53
53
fn def_to_path ( tcx : & ty:: ctxt , id : DefId ) -> Path {
54
- ty:: with_path ( tcx, id, |path| Path {
54
+ ty:: with_path ( tcx, id, |mut path| Path {
55
55
global : false ,
56
- segments : path. map ( |elem| PathSegment {
56
+ segments : path. last ( ) . map ( |elem| PathSegment {
57
57
identifier : Ident :: new ( elem. name ( ) ) ,
58
58
lifetimes : vec ! ( ) ,
59
59
types : OwnedSlice :: empty ( )
60
- } ) . collect ( ) ,
60
+ } ) . move_iter ( ) . collect ( ) ,
61
61
span : DUMMY_SP ,
62
62
} )
63
63
}
@@ -100,10 +100,11 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &Expr) {
100
100
arm. pats . as_slice ( ) ) ;
101
101
}
102
102
103
+ // Second, check for unreachable arms.
103
104
check_arms ( cx, arms. as_slice ( ) ) ;
104
- /* Check for exhaustiveness */
105
- // Check for empty enum, because is_useful only works on inhabited
106
- // types.
105
+
106
+ // Finally, check if the whole match expression is exhaustive.
107
+ // Check for empty enum, because is_useful only works on inhabited types.
107
108
let pat_ty = node_id_to_type ( cx. tcx , scrut. id ) ;
108
109
if ( * arms) . is_empty ( ) {
109
110
if !type_is_empty ( cx. tcx , pat_ty) {
@@ -180,11 +181,11 @@ fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, m: &Matrix) {
180
181
}
181
182
Useful ( pats) => {
182
183
let witness = match pats. as_slice ( ) {
183
- [ ref witness] => witness. clone ( ) ,
184
+ [ witness] => witness,
184
185
[ ] => wild ( ) ,
185
186
_ => unreachable ! ( )
186
187
} ;
187
- let msg = format ! ( "non-exhaustive patterns: {0} not covered" , pat_to_str( & * witness) ) ;
188
+ let msg = format ! ( "non-exhaustive patterns: ` {0}` not covered" , pat_to_str( & * witness) ) ;
188
189
cx. tcx . sess . span_err ( sp, msg. as_slice ( ) ) ;
189
190
}
190
191
}
@@ -193,7 +194,7 @@ fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, m: &Matrix) {
193
194
#[ deriving( Clone , PartialEq ) ]
194
195
enum ctor {
195
196
single,
196
- variant( DefId ) ,
197
+ variant( DefId /* variant */ , bool /* is_structure */ ) ,
197
198
val( const_val ) ,
198
199
range( const_val , const_val ) ,
199
200
vec( uint )
@@ -215,23 +216,23 @@ fn construct_witness(cx: &MatchCheckCtxt, ctor: &ctor, pats: Vec<Gc<Pat>>, lty:
215
216
let pat = match ty:: get ( lty) . sty {
216
217
ty:: ty_tup( _) => PatTup ( pats) ,
217
218
218
- ty:: ty_enum( _ , _) => {
219
- let vid = match ctor {
220
- & variant( vid) => vid,
221
- _ => unreachable ! ( )
219
+ ty:: ty_enum( cid , _ ) | ty :: ty_struct ( cid , _) => {
220
+ let ( vid, is_structure ) = match ctor {
221
+ & variant( vid, is_structure ) => ( vid, is_structure ) ,
222
+ _ => ( cid , true )
222
223
} ;
223
- PatEnum ( def_to_path ( cx . tcx , vid ) , Some ( pats ) )
224
- } ,
225
-
226
- ty :: ty_struct ( cid , _ ) => {
227
- let fields = ty :: lookup_struct_fields ( cx . tcx , cid ) ;
228
- let field_pats = fields . move_iter ( )
229
- . zip ( pats . iter ( ) )
230
- . map ( | ( field , pat ) | FieldPat {
231
- ident : Ident :: new ( field . name ) ,
232
- pat : pat . clone ( )
233
- } ) . collect ( ) ;
234
- PatStruct ( def_to_path ( cx . tcx , cid ) , field_pats , false )
224
+ if is_structure {
225
+ let fields = ty :: lookup_struct_fields ( cx . tcx , vid ) ;
226
+ let field_pats = fields . move_iter ( )
227
+ . zip ( pats . iter ( ) )
228
+ . map ( | ( field , pat ) | FieldPat {
229
+ ident : Ident :: new ( field . name ) ,
230
+ pat : pat . clone ( )
231
+ } ) . collect ( ) ;
232
+ PatStruct ( def_to_path ( cx . tcx , vid ) , field_pats , false )
233
+ } else {
234
+ PatEnum ( def_to_path ( cx . tcx , vid ) , Some ( pats ) )
235
+ }
235
236
} ,
236
237
237
238
ty:: ty_rptr( _, ty:: mt { ty : ty, .. } ) => {
@@ -307,7 +308,10 @@ fn all_constructors(cx: &MatchCheckCtxt, m: &Matrix, left_ty: ty::t) -> Vec<ctor
307
308
} ,
308
309
309
310
ty:: ty_enum( eid, _) =>
310
- ty:: enum_variants ( cx. tcx , eid) . iter ( ) . map ( |va| variant ( va. id ) ) . collect ( ) ,
311
+ ty:: enum_variants ( cx. tcx , eid)
312
+ . iter ( )
313
+ . map ( |va| variant ( va. id , va. arg_names . is_some ( ) ) )
314
+ . collect ( ) ,
311
315
312
316
ty:: ty_vec( _, None ) =>
313
317
vec_constructors ( m) ,
@@ -389,8 +393,8 @@ fn is_useful(cx: &MatchCheckCtxt, m: &Matrix, v: &[Gc<Pat>],
389
393
} ,
390
394
391
395
Some ( ctor) => {
392
- let matrix = & m. iter ( ) . filter_map ( |r| default ( cx, r. as_slice ( ) ) ) . collect ( ) ;
393
- match is_useful ( cx, matrix, v. tail ( ) , witness) {
396
+ let matrix = m. iter ( ) . filter_map ( |r| default ( cx, r. as_slice ( ) ) ) . collect ( ) ;
397
+ match is_useful ( cx, & matrix, v. tail ( ) , witness) {
394
398
Useful ( pats) => Useful ( match witness {
395
399
ConstructWitness => {
396
400
let arity = constructor_arity ( cx, & ctor, left_ty) ;
@@ -424,19 +428,28 @@ fn is_useful_specialized(cx: &MatchCheckCtxt, m: &Matrix, v: &[Gc<Pat>],
424
428
fn pat_ctor_id ( cx : & MatchCheckCtxt , left_ty : ty:: t , p : Gc < Pat > ) -> Option < ctor > {
425
429
let pat = raw_pat ( p) ;
426
430
match pat. node {
427
- PatIdent ( ..) | PatEnum ( .. ) | PatStruct ( .. ) =>
431
+ PatIdent ( ..) =>
428
432
match cx. tcx . def_map . borrow ( ) . find ( & pat. id ) {
429
433
Some ( & DefStatic ( did, false ) ) => {
430
434
let const_expr = lookup_const_by_id ( cx. tcx , did) . unwrap ( ) ;
431
435
Some ( val ( eval_const_expr ( cx. tcx , & * const_expr) ) )
432
436
} ,
433
- Some ( & DefVariant ( _, id, _) ) =>
434
- Some ( variant ( id) ) ,
435
- _ => match pat. node {
436
- PatEnum ( ..) | PatStruct ( ..) => Some ( single) ,
437
- PatIdent ( ..) => None ,
438
- _ => unreachable ! ( )
439
- }
437
+ Some ( & DefVariant ( _, id, is_structure) ) => Some ( variant ( id, is_structure) ) ,
438
+ _ => None
439
+ } ,
440
+ PatEnum ( ..) =>
441
+ match cx. tcx . def_map . borrow ( ) . find ( & pat. id ) {
442
+ Some ( & DefStatic ( did, false ) ) => {
443
+ let const_expr = lookup_const_by_id ( cx. tcx , did) . unwrap ( ) ;
444
+ Some ( val ( eval_const_expr ( cx. tcx , & * const_expr) ) )
445
+ } ,
446
+ Some ( & DefVariant ( _, id, is_structure) ) => Some ( variant ( id, is_structure) ) ,
447
+ _ => Some ( single)
448
+ } ,
449
+ PatStruct ( ..) =>
450
+ match cx. tcx . def_map . borrow ( ) . find ( & pat. id ) {
451
+ Some ( & DefVariant ( _, id, is_structure) ) => Some ( variant ( id, is_structure) ) ,
452
+ _ => Some ( single)
440
453
} ,
441
454
PatLit ( expr) =>
442
455
Some ( val ( eval_const_expr ( cx. tcx , & * expr) ) ) ,
@@ -485,7 +498,7 @@ fn constructor_arity(cx: &MatchCheckCtxt, ctor: &ctor, ty: ty::t) -> uint {
485
498
} ,
486
499
ty:: ty_enum( eid, _) => {
487
500
match * ctor {
488
- variant( id) => enum_variant_with_id ( cx. tcx , eid, id) . args . len ( ) ,
501
+ variant( id, _ ) => enum_variant_with_id ( cx. tcx , eid, id) . args . len ( ) ,
489
502
_ => unreachable ! ( )
490
503
}
491
504
}
@@ -532,13 +545,10 @@ fn specialize(cx: &MatchCheckCtxt, r: &[Gc<Pat>],
532
545
& PatIdent ( _, _, _) => {
533
546
let opt_def = cx. tcx . def_map . borrow ( ) . find_copy ( pat_id) ;
534
547
match opt_def {
535
- Some ( DefVariant ( _, id, _) ) => {
536
- if variant ( id) == * ctor_id {
537
- Some ( vec ! ( ) )
538
- } else {
539
- None
540
- }
541
- }
548
+ Some ( DefVariant ( _, id, _) ) => match * ctor_id {
549
+ variant( vid, _) if vid == id => Some ( vec ! ( ) ) ,
550
+ _ => None
551
+ } ,
542
552
Some ( DefStatic ( did, _) ) => {
543
553
let const_expr = lookup_const_by_id ( cx. tcx , did) . unwrap ( ) ;
544
554
let e_v = eval_const_expr ( cx. tcx , & * const_expr) ;
@@ -571,7 +581,7 @@ fn specialize(cx: &MatchCheckCtxt, r: &[Gc<Pat>],
571
581
}
572
582
}
573
583
}
574
- DefVariant ( _, id, _) if variant ( id) != * ctor_id => None ,
584
+ DefVariant ( _, id, _) if variant ( id, false ) != * ctor_id => None ,
575
585
DefVariant ( ..) | DefFn ( ..) | DefStruct ( ..) => {
576
586
Some ( match args {
577
587
& Some ( ref args) => args. clone ( ) ,
@@ -586,7 +596,7 @@ fn specialize(cx: &MatchCheckCtxt, r: &[Gc<Pat>],
586
596
// Is this a struct or an enum variant?
587
597
let def = cx. tcx . def_map . borrow ( ) . get_copy ( pat_id) ;
588
598
let class_id = match def {
589
- DefVariant ( _, variant_id, _) => if variant ( variant_id ) == * ctor_id {
599
+ DefVariant ( _, variant_id, _) => if * ctor_id == variant ( variant_id , true ) {
590
600
Some ( variant_id)
591
601
} else {
592
602
None
@@ -687,7 +697,7 @@ fn check_local(cx: &mut MatchCheckCtxt, loc: &Local) {
687
697
match is_refutable ( cx, loc. pat ) {
688
698
Some ( pat) => {
689
699
let msg = format ! (
690
- "refutable pattern in {} binding: {} not covered" ,
700
+ "refutable pattern in {} binding: `{}` not covered" ,
691
701
name, pat_to_str( & * pat)
692
702
) ;
693
703
cx. tcx . sess . span_err ( loc. pat . span , msg. as_slice ( ) ) ;
@@ -709,7 +719,7 @@ fn check_fn(cx: &mut MatchCheckCtxt,
709
719
match is_refutable ( cx, input. pat ) {
710
720
Some ( pat) => {
711
721
let msg = format ! (
712
- "refutable pattern in function argument: {} not covered" ,
722
+ "refutable pattern in function argument: `{}` not covered" ,
713
723
pat_to_str( & * pat)
714
724
) ;
715
725
cx. tcx . sess . span_err ( input. pat . span , msg. as_slice ( ) ) ;
0 commit comments