@@ -51,13 +51,13 @@ impl Usefulness {
5151}
5252
5353fn 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 {
5555 global : false ,
56- segments : path. map ( |elem| PathSegment {
56+ segments : path. last ( ) . map ( |elem| PathSegment {
5757 identifier : Ident :: new ( elem. name ( ) ) ,
5858 lifetimes : vec ! ( ) ,
5959 types : OwnedSlice :: empty ( )
60- } ) . collect ( ) ,
60+ } ) . move_iter ( ) . collect ( ) ,
6161 span : DUMMY_SP ,
6262 } )
6363}
@@ -100,10 +100,11 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &Expr) {
100100 arm. pats . as_slice ( ) ) ;
101101 }
102102
103+ // Second, check for unreachable arms.
103104 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.
107108 let pat_ty = node_id_to_type ( cx. tcx , scrut. id ) ;
108109 if ( * arms) . is_empty ( ) {
109110 if !type_is_empty ( cx. tcx , pat_ty) {
@@ -180,11 +181,11 @@ fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, m: &Matrix) {
180181 }
181182 Useful ( pats) => {
182183 let witness = match pats. as_slice ( ) {
183- [ ref witness] => witness. clone ( ) ,
184+ [ witness] => witness,
184185 [ ] => wild ( ) ,
185186 _ => unreachable ! ( )
186187 } ;
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) ) ;
188189 cx. tcx . sess . span_err ( sp, msg. as_slice ( ) ) ;
189190 }
190191 }
@@ -193,7 +194,7 @@ fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, m: &Matrix) {
193194#[ deriving( Clone , PartialEq ) ]
194195enum ctor {
195196 single,
196- variant( DefId ) ,
197+ variant( DefId /* variant */ , bool /* is_structure */ ) ,
197198 val( const_val ) ,
198199 range( const_val , const_val ) ,
199200 vec( uint )
@@ -215,23 +216,23 @@ fn construct_witness(cx: &MatchCheckCtxt, ctor: &ctor, pats: Vec<Gc<Pat>>, lty:
215216 let pat = match ty:: get ( lty) . sty {
216217 ty:: ty_tup( _) => PatTup ( pats) ,
217218
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 )
222223 } ;
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+ }
235236 } ,
236237
237238 ty:: ty_rptr( _, ty:: mt { ty : ty, .. } ) => {
@@ -307,7 +308,10 @@ fn all_constructors(cx: &MatchCheckCtxt, m: &Matrix, left_ty: ty::t) -> Vec<ctor
307308 } ,
308309
309310 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 ( ) ,
311315
312316 ty:: ty_vec( _, None ) =>
313317 vec_constructors ( m) ,
@@ -389,8 +393,8 @@ fn is_useful(cx: &MatchCheckCtxt, m: &Matrix, v: &[Gc<Pat>],
389393 } ,
390394
391395 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) {
394398 Useful ( pats) => Useful ( match witness {
395399 ConstructWitness => {
396400 let arity = constructor_arity ( cx, & ctor, left_ty) ;
@@ -424,19 +428,28 @@ fn is_useful_specialized(cx: &MatchCheckCtxt, m: &Matrix, v: &[Gc<Pat>],
424428fn pat_ctor_id ( cx : & MatchCheckCtxt , left_ty : ty:: t , p : Gc < Pat > ) -> Option < ctor > {
425429 let pat = raw_pat ( p) ;
426430 match pat. node {
427- PatIdent ( ..) | PatEnum ( .. ) | PatStruct ( .. ) =>
431+ PatIdent ( ..) =>
428432 match cx. tcx . def_map . borrow ( ) . find ( & pat. id ) {
429433 Some ( & DefStatic ( did, false ) ) => {
430434 let const_expr = lookup_const_by_id ( cx. tcx , did) . unwrap ( ) ;
431435 Some ( val ( eval_const_expr ( cx. tcx , & * const_expr) ) )
432436 } ,
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)
440453 } ,
441454 PatLit ( expr) =>
442455 Some ( val ( eval_const_expr ( cx. tcx , & * expr) ) ) ,
@@ -485,7 +498,7 @@ fn constructor_arity(cx: &MatchCheckCtxt, ctor: &ctor, ty: ty::t) -> uint {
485498 } ,
486499 ty:: ty_enum( eid, _) => {
487500 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 ( ) ,
489502 _ => unreachable ! ( )
490503 }
491504 }
@@ -532,13 +545,10 @@ fn specialize(cx: &MatchCheckCtxt, r: &[Gc<Pat>],
532545 & PatIdent ( _, _, _) => {
533546 let opt_def = cx. tcx . def_map . borrow ( ) . find_copy ( pat_id) ;
534547 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+ } ,
542552 Some ( DefStatic ( did, _) ) => {
543553 let const_expr = lookup_const_by_id ( cx. tcx , did) . unwrap ( ) ;
544554 let e_v = eval_const_expr ( cx. tcx , & * const_expr) ;
@@ -571,7 +581,7 @@ fn specialize(cx: &MatchCheckCtxt, r: &[Gc<Pat>],
571581 }
572582 }
573583 }
574- DefVariant ( _, id, _) if variant ( id) != * ctor_id => None ,
584+ DefVariant ( _, id, _) if variant ( id, false ) != * ctor_id => None ,
575585 DefVariant ( ..) | DefFn ( ..) | DefStruct ( ..) => {
576586 Some ( match args {
577587 & Some ( ref args) => args. clone ( ) ,
@@ -586,7 +596,7 @@ fn specialize(cx: &MatchCheckCtxt, r: &[Gc<Pat>],
586596 // Is this a struct or an enum variant?
587597 let def = cx. tcx . def_map . borrow ( ) . get_copy ( pat_id) ;
588598 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 ) {
590600 Some ( variant_id)
591601 } else {
592602 None
@@ -687,7 +697,7 @@ fn check_local(cx: &mut MatchCheckCtxt, loc: &Local) {
687697 match is_refutable ( cx, loc. pat ) {
688698 Some ( pat) => {
689699 let msg = format ! (
690- "refutable pattern in {} binding: {} not covered" ,
700+ "refutable pattern in {} binding: `{}` not covered" ,
691701 name, pat_to_str( & * pat)
692702 ) ;
693703 cx. tcx . sess . span_err ( loc. pat . span , msg. as_slice ( ) ) ;
@@ -709,7 +719,7 @@ fn check_fn(cx: &mut MatchCheckCtxt,
709719 match is_refutable ( cx, input. pat ) {
710720 Some ( pat) => {
711721 let msg = format ! (
712- "refutable pattern in function argument: {} not covered" ,
722+ "refutable pattern in function argument: `{}` not covered" ,
713723 pat_to_str( & * pat)
714724 ) ;
715725 cx. tcx . sess . span_err ( input. pat . span , msg. as_slice ( ) ) ;
0 commit comments