@@ -93,9 +93,10 @@ pub enum Constructor {
9393 Slice ( uint )
9494}
9595
96- #[ deriving( Clone ) ]
96+ #[ deriving( Clone , PartialEq ) ]
9797enum Usefulness {
98- Useful ( Vec < Gc < Pat > > ) ,
98+ Useful ,
99+ UsefulWithWitness ( Vec < Gc < Pat > > ) ,
99100 NotUseful
100101}
101102
@@ -104,15 +105,6 @@ enum WitnessPreference {
104105 LeaveOutWitness
105106}
106107
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-
116108impl < ' a > Visitor < ( ) > for MatchCheckCtxt < ' a > {
117109 fn visit_expr ( & mut self , ex : & Expr , _: ( ) ) {
118110 check_expr ( self , ex) ;
@@ -203,7 +195,8 @@ fn check_arms(cx: &MatchCheckCtxt, arms: &[Arm]) {
203195 let v = vec ! ( * pat) ;
204196 match is_useful ( cx, & seen, v. as_slice ( ) , LeaveOutWitness ) {
205197 NotUseful => cx. tcx . sess . span_err ( pat. span , "unreachable pattern" ) ,
206- _ => ( )
198+ Useful => ( ) ,
199+ UsefulWithWitness ( _) => unreachable ! ( )
207200 }
208201 if arm. guard . is_none ( ) {
209202 let Matrix ( mut rows) = seen;
@@ -223,7 +216,7 @@ fn raw_pat(p: Gc<Pat>) -> Gc<Pat> {
223216
224217fn check_exhaustive ( cx : & MatchCheckCtxt , sp : Span , m : & Matrix ) {
225218 match is_useful ( cx, m, [ wild ( ) ] , ConstructWitness ) {
226- Useful ( pats) => {
219+ UsefulWithWitness ( pats) => {
227220 let witness = match pats. as_slice ( ) {
228221 [ witness] => witness,
229222 [ ] => wild ( ) ,
@@ -234,7 +227,8 @@ fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, m: &Matrix) {
234227 }
235228 NotUseful => {
236229 // This is good, wildcard pattern isn't reachable
237- }
230+ } ,
231+ _ => unreachable ! ( )
238232 }
239233}
240234
@@ -404,11 +398,14 @@ fn all_constructors(cx: &MatchCheckCtxt, left_ty: ty::t,
404398
405399// Note: is_useful doesn't work on empty types, as the paper notes.
406400// 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 ,
408402 v : & [ Gc < Pat > ] , witness : WitnessPreference ) -> Usefulness {
409- debug ! ( "{:}" , m ) ;
403+ debug ! ( "{:}" , matrix ) ;
410404 if rows. len ( ) == 0 u {
411- return Useful ( vec ! ( ) ) ;
405+ return match witness {
406+ ConstructWitness => UsefulWithWitness ( vec ! ( ) ) ,
407+ LeaveOutWitness => Useful
408+ } ;
412409 }
413410 if rows. get ( 0 ) . len ( ) == 0 u {
414411 return NotUseful ;
@@ -438,53 +435,46 @@ fn is_useful(cx: &MatchCheckCtxt, m @ &Matrix(ref rows): &Matrix,
438435
439436 let constructors = pat_constructors ( cx, v[ 0 ] , left_ty, max_slice_length) ;
440437 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) {
442439 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 )
464458 } ,
465459
466460 Some ( constructor) => {
467461 let matrix = Matrix ( rows. iter ( ) . filter_map ( |r|
468462 default ( cx, r. as_slice ( ) ) ) . collect ( ) ) ;
469463 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+ } ,
479470 result => result
480471 }
481472 }
482473 }
483474 } 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 )
488478 }
489479}
490480
@@ -519,6 +509,7 @@ fn pat_constructors(cx: &MatchCheckCtxt, p: Gc<Pat>,
519509 let const_expr = lookup_const_by_id ( cx. tcx , did) . unwrap ( ) ;
520510 vec ! ( ConstantValue ( eval_const_expr( cx. tcx, & * const_expr) ) )
521511 } ,
512+ Some ( & DefStruct ( _) ) => vec ! ( Single ) ,
522513 Some ( & DefVariant ( _, id, _) ) => vec ! ( Variant ( id) ) ,
523514 _ => vec ! ( )
524515 } ,
@@ -560,21 +551,6 @@ fn pat_constructors(cx: &MatchCheckCtxt, p: Gc<Pat>,
560551 }
561552}
562553
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-
578554/// This computes the arity of a constructor. The arity of a constructor
579555/// is how many subpattern patterns of that constructor should be expanded to.
580556///
@@ -780,7 +756,7 @@ pub fn specialize(cx: &MatchCheckCtxt, r: &[Gc<Pat>],
780756}
781757
782758fn 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 ] ) ) {
784760 Some ( Vec :: from_slice ( r. tail ( ) ) )
785761 } else {
786762 None
@@ -833,12 +809,14 @@ fn check_fn(cx: &mut MatchCheckCtxt,
833809
834810fn is_refutable ( cx : & MatchCheckCtxt , pat : Gc < Pat > ) -> Option < Gc < Pat > > {
835811 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) => {
839814 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+ }
842820}
843821
844822// Legality of move bindings checking
0 commit comments