@@ -129,7 +129,7 @@ pub enum Constructor {
129129 SliceWithSubslice ( usize , usize )
130130}
131131
132- #[ derive( Clone , PartialEq ) ]
132+ #[ derive( Clone , PartialEq , Debug ) ]
133133enum Usefulness {
134134 Useful ,
135135 UsefulWithWitness ( Vec < P < Pat > > ) ,
@@ -569,18 +569,31 @@ impl<'a, 'tcx> StaticInliner<'a, 'tcx> {
569569/// left_ty: struct X { a: (bool, &'static str), b: usize}
570570/// pats: [(false, "foo"), 42] => X { a: (false, "foo"), b: 42 }
571571fn construct_witness < ' a , ' tcx > ( cx : & MatchCheckCtxt < ' a , ' tcx > , ctor : & Constructor ,
572- pats : Vec < & Pat > , left_ty : Ty < ' tcx > ) -> P < Pat > {
572+ pats : Vec < & Pat > , left_ty : Ty < ' tcx > ) -> Option < P < Pat > > {
573+ let tcx = cx. tcx ;
573574 let pats_len = pats. len ( ) ;
574- let mut pats = pats. into_iter ( ) . map ( |p| P ( ( * p) . clone ( ) ) ) ;
575+ let mut pats_owned = pats. iter ( ) . map ( |p| P ( ( * * p) . clone ( ) ) ) ;
575576 let pat = match left_ty. sty {
576- ty:: TyTuple ( ..) => PatKind :: Tuple ( pats. collect ( ) , None ) ,
577-
578- ty:: TyAdt ( adt, _) => {
577+ ty:: TyTuple ( ref inner_tys) => {
578+ if pats. iter ( ) . zip ( inner_tys. iter ( ) ) . any ( |( p, t) | {
579+ * p == DUMMY_WILD_PAT && t. is_uninhabited ( tcx)
580+ } ) {
581+ return None ;
582+ }
583+ PatKind :: Tuple ( pats_owned. collect ( ) , None )
584+ } ,
585+ ty:: TyAdt ( adt, substs) => {
579586 let v = ctor. variant_for_adt ( adt) ;
587+ if pats. iter ( ) . zip ( v. fields . iter ( ) ) . any ( |( p, f) | {
588+ * p == DUMMY_WILD_PAT &&
589+ f. ty ( tcx, substs) . is_uninhabited ( tcx)
590+ } ) {
591+ return None ;
592+ } ;
580593 match v. ctor_kind {
581594 CtorKind :: Fictive => {
582595 let field_pats: hir:: HirVec < _ > = v. fields . iter ( )
583- . zip ( pats )
596+ . zip ( pats_owned )
584597 . filter ( |& ( _, ref pat) | pat. node != PatKind :: Wild )
585598 . map ( |( field, pat) | Spanned {
586599 span : DUMMY_SP ,
@@ -594,30 +607,40 @@ fn construct_witness<'a,'tcx>(cx: &MatchCheckCtxt<'a,'tcx>, ctor: &Constructor,
594607 PatKind :: Struct ( def_to_path ( cx. tcx , v. did ) , field_pats, has_more_fields)
595608 }
596609 CtorKind :: Fn => {
597- PatKind :: TupleStruct ( def_to_path ( cx. tcx , v. did ) , pats . collect ( ) , None )
610+ PatKind :: TupleStruct ( def_to_path ( cx. tcx , v. did ) , pats_owned . collect ( ) , None )
598611 }
599612 CtorKind :: Const => {
600613 PatKind :: Path ( None , def_to_path ( cx. tcx , v. did ) )
601614 }
602615 }
603616 }
604617
605- ty:: TyRef ( _, ty:: TypeAndMut { mutbl, .. } ) => {
618+ ty:: TyRef ( _, ty:: TypeAndMut { mutbl, ty : inner_ty } ) => {
606619 assert_eq ! ( pats_len, 1 ) ;
607- PatKind :: Ref ( pats. nth ( 0 ) . unwrap ( ) , mutbl)
620+ let pat = pats_owned. nth ( 0 ) . unwrap ( ) ;
621+ if * pat == * DUMMY_WILD_PAT && inner_ty. is_uninhabited ( tcx) {
622+ return None ;
623+ }
624+ PatKind :: Ref ( pat, mutbl)
608625 }
609626
610- ty:: TySlice ( _ ) => match ctor {
627+ ty:: TySlice ( ref inner_ty ) => match ctor {
611628 & Slice ( n) => {
612629 assert_eq ! ( pats_len, n) ;
613- PatKind :: Slice ( pats. collect ( ) , None , hir:: HirVec :: new ( ) )
630+ if inner_ty. is_uninhabited ( tcx) && pats. iter ( ) . any ( |p| * p == DUMMY_WILD_PAT ) {
631+ return None ;
632+ }
633+ PatKind :: Slice ( pats_owned. collect ( ) , None , hir:: HirVec :: new ( ) )
614634 } ,
615635 _ => unreachable ! ( )
616636 } ,
617637
618- ty:: TyArray ( _ , len) => {
638+ ty:: TyArray ( ref inner_ty , len) => {
619639 assert_eq ! ( pats_len, len) ;
620- PatKind :: Slice ( pats. collect ( ) , None , hir:: HirVec :: new ( ) )
640+ if inner_ty. is_uninhabited ( tcx) && pats. iter ( ) . any ( |p| * p == DUMMY_WILD_PAT ) {
641+ return None ;
642+ }
643+ PatKind :: Slice ( pats_owned. collect ( ) , None , hir:: HirVec :: new ( ) )
621644 }
622645
623646 _ => {
@@ -628,11 +651,11 @@ fn construct_witness<'a,'tcx>(cx: &MatchCheckCtxt<'a,'tcx>, ctor: &Constructor,
628651 }
629652 } ;
630653
631- P ( hir:: Pat {
654+ Some ( P ( hir:: Pat {
632655 id : DUMMY_NODE_ID ,
633656 node : pat,
634657 span : DUMMY_SP
635- } )
658+ } ) )
636659}
637660
638661impl Constructor {
@@ -724,20 +747,26 @@ fn is_useful<'a, 'tcx>(cx: &MatchCheckCtxt<'a, 'tcx>,
724747 let constructors = missing_constructors ( cx, matrix, left_ty, max_slice_length) ;
725748 debug ! ( "is_useful - missing_constructors = {:?}" , constructors) ;
726749 if constructors. is_empty ( ) {
727- all_constructors ( cx, left_ty, max_slice_length) . into_iter ( ) . map ( |c| {
728- match is_useful_specialized ( cx, matrix, v, c. clone ( ) , left_ty, witness) {
729- UsefulWithWitness ( pats) => UsefulWithWitness ( {
750+ let all_cons = all_constructors ( cx, left_ty, max_slice_length) ;
751+ all_cons. into_iter ( ) . map ( |c| {
752+ let spec = is_useful_specialized ( cx, matrix, v, c. clone ( ) , left_ty, witness) ;
753+ match spec {
754+ UsefulWithWitness ( pats) => {
730755 let arity = constructor_arity ( cx, & c, left_ty) ;
731- let mut result = {
756+ let mut result: Vec < _ > = {
732757 let pat_slice = & pats[ ..] ;
733758 let subpats: Vec < _ > = ( 0 ..arity) . map ( |i| {
734759 pat_slice. get ( i) . map_or ( DUMMY_WILD_PAT , |p| & * * p)
735760 } ) . collect ( ) ;
736- vec ! [ construct_witness( cx, & c, subpats, left_ty) ]
761+ construct_witness ( cx, & c, subpats, left_ty) . into_iter ( ) . collect ( )
737762 } ;
738763 result. extend ( pats. into_iter ( ) . skip ( arity) ) ;
739- result
740- } ) ,
764+ if result. is_empty ( ) {
765+ NotUseful
766+ } else {
767+ UsefulWithWitness ( result)
768+ }
769+ } ,
741770 result => result
742771 }
743772 } ) . find ( |result| result != & NotUseful ) . unwrap_or ( NotUseful )
@@ -750,13 +779,17 @@ fn is_useful<'a, 'tcx>(cx: &MatchCheckCtxt<'a, 'tcx>,
750779 } ) . collect ( ) ;
751780 match is_useful ( cx, & matrix, & v[ 1 ..] , witness) {
752781 UsefulWithWitness ( pats) => {
753- let mut new_pats: Vec < _ > = constructors. into_iter ( ) . map ( |constructor| {
782+ let mut new_pats: Vec < _ > = constructors. into_iter ( ) . filter_map ( |constructor| {
754783 let arity = constructor_arity ( cx, & constructor, left_ty) ;
755784 let wild_pats = vec ! [ DUMMY_WILD_PAT ; arity] ;
756785 construct_witness ( cx, & constructor, wild_pats, left_ty)
757786 } ) . collect ( ) ;
758787 new_pats. extend ( pats) ;
759- UsefulWithWitness ( new_pats)
788+ if new_pats. is_empty ( ) {
789+ NotUseful
790+ } else {
791+ UsefulWithWitness ( new_pats)
792+ }
760793 } ,
761794 result => result
762795 }
@@ -780,7 +813,8 @@ fn is_useful_specialized<'a, 'tcx>(
780813 let matrix = Matrix ( m. iter ( ) . filter_map ( |r| {
781814 specialize ( cx, & r[ ..] , & ctor, 0 , arity)
782815 } ) . collect ( ) ) ;
783- match specialize ( cx, v, & ctor, 0 , arity) {
816+ let spec = specialize ( cx, v, & ctor, 0 , arity) ;
817+ match spec {
784818 Some ( v) => is_useful ( cx, & matrix, & v[ ..] , witness) ,
785819 None => NotUseful
786820 }
0 commit comments