@@ -93,9 +93,10 @@ pub enum Constructor {
93
93
Slice ( uint )
94
94
}
95
95
96
- #[ deriving( Clone ) ]
96
+ #[ deriving( Clone , PartialEq ) ]
97
97
enum Usefulness {
98
- Useful ( Vec < Gc < Pat > > ) ,
98
+ Useful ,
99
+ UsefulWithWitness ( Vec < Gc < Pat > > ) ,
99
100
NotUseful
100
101
}
101
102
@@ -104,15 +105,6 @@ enum WitnessPreference {
104
105
LeaveOutWitness
105
106
}
106
107
107
- impl Usefulness {
108
- fn useful ( self ) -> Option < Vec < Gc < Pat > > > {
109
- match self {
110
- Useful ( pats) => Some ( pats) ,
111
- _ => None
112
- }
113
- }
114
- }
115
-
116
108
impl < ' a > Visitor < ( ) > for MatchCheckCtxt < ' a > {
117
109
fn visit_expr ( & mut self , ex : & Expr , _: ( ) ) {
118
110
check_expr ( self , ex) ;
@@ -203,7 +195,8 @@ fn check_arms(cx: &MatchCheckCtxt, arms: &[Arm]) {
203
195
let v = vec ! ( * pat) ;
204
196
match is_useful ( cx, & seen, v. as_slice ( ) , LeaveOutWitness ) {
205
197
NotUseful => cx. tcx . sess . span_err ( pat. span , "unreachable pattern" ) ,
206
- _ => ( )
198
+ Useful => ( ) ,
199
+ UsefulWithWitness ( _) => unreachable ! ( )
207
200
}
208
201
if arm. guard . is_none ( ) {
209
202
let Matrix ( mut rows) = seen;
@@ -223,7 +216,7 @@ fn raw_pat(p: Gc<Pat>) -> Gc<Pat> {
223
216
224
217
fn check_exhaustive ( cx : & MatchCheckCtxt , sp : Span , m : & Matrix ) {
225
218
match is_useful ( cx, m, [ wild ( ) ] , ConstructWitness ) {
226
- Useful ( pats) => {
219
+ UsefulWithWitness ( pats) => {
227
220
let witness = match pats. as_slice ( ) {
228
221
[ witness] => witness,
229
222
[ ] => wild ( ) ,
@@ -234,7 +227,8 @@ fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, m: &Matrix) {
234
227
}
235
228
NotUseful => {
236
229
// This is good, wildcard pattern isn't reachable
237
- }
230
+ } ,
231
+ _ => unreachable ! ( )
238
232
}
239
233
}
240
234
@@ -404,11 +398,14 @@ fn all_constructors(cx: &MatchCheckCtxt, left_ty: ty::t,
404
398
405
399
// Note: is_useful doesn't work on empty types, as the paper notes.
406
400
// So it assumes that v is non-empty.
407
- fn is_useful ( cx : & MatchCheckCtxt , m @ & Matrix ( ref rows) : & Matrix ,
401
+ fn is_useful ( cx : & MatchCheckCtxt , matrix @ & Matrix ( ref rows) : & Matrix ,
408
402
v : & [ Gc < Pat > ] , witness : WitnessPreference ) -> Usefulness {
409
- debug ! ( "{:}" , m ) ;
403
+ debug ! ( "{:}" , matrix ) ;
410
404
if rows. len ( ) == 0 u {
411
- return Useful ( vec ! ( ) ) ;
405
+ return match witness {
406
+ ConstructWitness => UsefulWithWitness ( vec ! ( ) ) ,
407
+ LeaveOutWitness => Useful
408
+ } ;
412
409
}
413
410
if rows. get ( 0 ) . len ( ) == 0 u {
414
411
return NotUseful ;
@@ -438,53 +435,46 @@ fn is_useful(cx: &MatchCheckCtxt, m @ &Matrix(ref rows): &Matrix,
438
435
439
436
let constructors = pat_constructors ( cx, v[ 0 ] , left_ty, max_slice_length) ;
440
437
if constructors. is_empty ( ) {
441
- match missing_constructor ( cx, m , left_ty, max_slice_length) {
438
+ match missing_constructor ( cx, matrix , left_ty, max_slice_length) {
442
439
None => {
443
- all_constructors ( cx, left_ty, max_slice_length) . move_iter ( ) . filter_map ( |c| {
444
- is_useful_specialized ( cx, m, v, c. clone ( ) ,
445
- left_ty, witness) . useful ( ) . map ( |pats| {
446
- Useful ( match witness {
447
- ConstructWitness => {
448
- let arity = constructor_arity ( cx, & c, left_ty) ;
449
- let subpats = {
450
- let pat_slice = pats. as_slice ( ) ;
451
- Vec :: from_fn ( arity, |i| {
452
- pat_slice. get ( i) . map ( |p| p. clone ( ) )
453
- . unwrap_or_else ( || wild ( ) )
454
- } )
455
- } ;
456
- let mut result = vec ! ( construct_witness( cx, & c, subpats, left_ty) ) ;
457
- result. extend ( pats. move_iter ( ) . skip ( arity) ) ;
458
- result
459
- }
460
- LeaveOutWitness => vec ! ( )
461
- } )
462
- } )
463
- } ) . nth ( 0 ) . unwrap_or ( NotUseful )
440
+ all_constructors ( cx, left_ty, max_slice_length) . move_iter ( ) . map ( |c| {
441
+ match is_useful_specialized ( cx, matrix, v, c. clone ( ) , left_ty, witness) {
442
+ UsefulWithWitness ( pats) => UsefulWithWitness ( {
443
+ let arity = constructor_arity ( cx, & c, left_ty) ;
444
+ let subpats = {
445
+ let pat_slice = pats. as_slice ( ) ;
446
+ Vec :: from_fn ( arity, |i| {
447
+ pat_slice. get ( i) . map ( |p| p. clone ( ) )
448
+ . unwrap_or_else ( || wild ( ) )
449
+ } )
450
+ } ;
451
+ let mut result = vec ! ( construct_witness( cx, & c, subpats, left_ty) ) ;
452
+ result. extend ( pats. move_iter ( ) . skip ( arity) ) ;
453
+ result
454
+ } ) ,
455
+ result => result
456
+ }
457
+ } ) . find ( |result| result != & NotUseful ) . unwrap_or ( NotUseful )
464
458
} ,
465
459
466
460
Some ( constructor) => {
467
461
let matrix = Matrix ( rows. iter ( ) . filter_map ( |r|
468
462
default ( cx, r. as_slice ( ) ) ) . collect ( ) ) ;
469
463
match is_useful ( cx, & matrix, v. tail ( ) , witness) {
470
- Useful ( pats) => Useful ( match witness {
471
- ConstructWitness => {
472
- let arity = constructor_arity ( cx, & constructor, left_ty) ;
473
- let wild_pats = Vec :: from_elem ( arity, wild ( ) ) ;
474
- let enum_pat = construct_witness ( cx, & constructor, wild_pats, left_ty) ;
475
- ( vec ! ( enum_pat) ) . append ( pats. as_slice ( ) )
476
- }
477
- LeaveOutWitness => vec ! ( )
478
- } ) ,
464
+ UsefulWithWitness ( pats) => {
465
+ let arity = constructor_arity ( cx, & constructor, left_ty) ;
466
+ let wild_pats = Vec :: from_elem ( arity, wild ( ) ) ;
467
+ let enum_pat = construct_witness ( cx, & constructor, wild_pats, left_ty) ;
468
+ UsefulWithWitness ( vec ! ( enum_pat) . append ( pats. as_slice ( ) ) )
469
+ } ,
479
470
result => result
480
471
}
481
472
}
482
473
}
483
474
} else {
484
- constructors. move_iter ( ) . filter_map ( |c| {
485
- is_useful_specialized ( cx, m, v, c. clone ( ) , left_ty, witness)
486
- . useful ( ) . map ( |pats| Useful ( pats) )
487
- } ) . nth ( 0 ) . unwrap_or ( NotUseful )
475
+ constructors. move_iter ( ) . map ( |c|
476
+ is_useful_specialized ( cx, matrix, v, c. clone ( ) , left_ty, witness)
477
+ ) . find ( |result| result != & NotUseful ) . unwrap_or ( NotUseful )
488
478
}
489
479
}
490
480
@@ -519,6 +509,7 @@ fn pat_constructors(cx: &MatchCheckCtxt, p: Gc<Pat>,
519
509
let const_expr = lookup_const_by_id ( cx. tcx , did) . unwrap ( ) ;
520
510
vec ! ( ConstantValue ( eval_const_expr( cx. tcx, & * const_expr) ) )
521
511
} ,
512
+ Some ( & DefStruct ( _) ) => vec ! ( Single ) ,
522
513
Some ( & DefVariant ( _, id, _) ) => vec ! ( Variant ( id) ) ,
523
514
_ => vec ! ( )
524
515
} ,
@@ -560,21 +551,6 @@ fn pat_constructors(cx: &MatchCheckCtxt, p: Gc<Pat>,
560
551
}
561
552
}
562
553
563
- fn is_wild ( cx : & MatchCheckCtxt , p : Gc < Pat > ) -> bool {
564
- let pat = raw_pat ( p) ;
565
- match pat. node {
566
- PatWild | PatWildMulti => true ,
567
- PatIdent ( _, _, _) =>
568
- match cx. tcx . def_map . borrow ( ) . find ( & pat. id ) {
569
- Some ( & DefVariant ( _, _, _) ) | Some ( & DefStatic ( ..) ) => false ,
570
- _ => true
571
- } ,
572
- PatVec ( ref before, Some ( _) , ref after) =>
573
- before. is_empty ( ) && after. is_empty ( ) ,
574
- _ => false
575
- }
576
- }
577
-
578
554
/// This computes the arity of a constructor. The arity of a constructor
579
555
/// is how many subpattern patterns of that constructor should be expanded to.
580
556
///
@@ -780,7 +756,7 @@ pub fn specialize(cx: &MatchCheckCtxt, r: &[Gc<Pat>],
780
756
}
781
757
782
758
fn default ( cx : & MatchCheckCtxt , r : & [ Gc < Pat > ] ) -> Option < Vec < Gc < Pat > > > {
783
- if is_wild ( cx , r[ 0 ] ) {
759
+ if pat_is_binding_or_wild ( & cx . tcx . def_map , & * raw_pat ( r[ 0 ] ) ) {
784
760
Some ( Vec :: from_slice ( r. tail ( ) ) )
785
761
} else {
786
762
None
@@ -833,12 +809,14 @@ fn check_fn(cx: &mut MatchCheckCtxt,
833
809
834
810
fn is_refutable ( cx : & MatchCheckCtxt , pat : Gc < Pat > ) -> Option < Gc < Pat > > {
835
811
let pats = Matrix ( vec ! ( vec!( pat) ) ) ;
836
- is_useful ( cx, & pats, [ wild ( ) ] , ConstructWitness )
837
- . useful ( )
838
- . map ( |pats| {
812
+ match is_useful ( cx, & pats, [ wild ( ) ] , ConstructWitness ) {
813
+ UsefulWithWitness ( pats) => {
839
814
assert_eq ! ( pats. len( ) , 1 ) ;
840
- pats. get ( 0 ) . clone ( )
841
- } )
815
+ Some ( pats. get ( 0 ) . clone ( ) )
816
+ } ,
817
+ NotUseful => None ,
818
+ Useful => unreachable ! ( )
819
+ }
842
820
}
843
821
844
822
// Legality of move bindings checking
0 commit comments