@@ -129,7 +129,7 @@ pub enum Constructor {
129
129
SliceWithSubslice ( usize , usize )
130
130
}
131
131
132
- #[ derive( Clone , PartialEq ) ]
132
+ #[ derive( Clone , PartialEq , Debug ) ]
133
133
enum Usefulness {
134
134
Useful ,
135
135
UsefulWithWitness ( Vec < P < Pat > > ) ,
@@ -569,18 +569,31 @@ impl<'a, 'tcx> StaticInliner<'a, 'tcx> {
569
569
/// left_ty: struct X { a: (bool, &'static str), b: usize}
570
570
/// pats: [(false, "foo"), 42] => X { a: (false, "foo"), b: 42 }
571
571
fn 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 ;
573
574
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 ( ) ) ) ;
575
576
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) => {
579
586
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
+ } ;
580
593
match v. ctor_kind {
581
594
CtorKind :: Fictive => {
582
595
let field_pats: hir:: HirVec < _ > = v. fields . iter ( )
583
- . zip ( pats )
596
+ . zip ( pats_owned )
584
597
. filter ( |& ( _, ref pat) | pat. node != PatKind :: Wild )
585
598
. map ( |( field, pat) | Spanned {
586
599
span : DUMMY_SP ,
@@ -594,30 +607,40 @@ fn construct_witness<'a,'tcx>(cx: &MatchCheckCtxt<'a,'tcx>, ctor: &Constructor,
594
607
PatKind :: Struct ( def_to_path ( cx. tcx , v. did ) , field_pats, has_more_fields)
595
608
}
596
609
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 )
598
611
}
599
612
CtorKind :: Const => {
600
613
PatKind :: Path ( None , def_to_path ( cx. tcx , v. did ) )
601
614
}
602
615
}
603
616
}
604
617
605
- ty:: TyRef ( _, ty:: TypeAndMut { mutbl, .. } ) => {
618
+ ty:: TyRef ( _, ty:: TypeAndMut { mutbl, ty : inner_ty } ) => {
606
619
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)
608
625
}
609
626
610
- ty:: TySlice ( _ ) => match ctor {
627
+ ty:: TySlice ( ref inner_ty ) => match ctor {
611
628
& Slice ( n) => {
612
629
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 ( ) )
614
634
} ,
615
635
_ => unreachable ! ( )
616
636
} ,
617
637
618
- ty:: TyArray ( _ , len) => {
638
+ ty:: TyArray ( ref inner_ty , len) => {
619
639
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 ( ) )
621
644
}
622
645
623
646
_ => {
@@ -628,11 +651,11 @@ fn construct_witness<'a,'tcx>(cx: &MatchCheckCtxt<'a,'tcx>, ctor: &Constructor,
628
651
}
629
652
} ;
630
653
631
- P ( hir:: Pat {
654
+ Some ( P ( hir:: Pat {
632
655
id : DUMMY_NODE_ID ,
633
656
node : pat,
634
657
span : DUMMY_SP
635
- } )
658
+ } ) )
636
659
}
637
660
638
661
impl Constructor {
@@ -724,20 +747,26 @@ fn is_useful<'a, 'tcx>(cx: &MatchCheckCtxt<'a, 'tcx>,
724
747
let constructors = missing_constructors ( cx, matrix, left_ty, max_slice_length) ;
725
748
debug ! ( "is_useful - missing_constructors = {:?}" , constructors) ;
726
749
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) => {
730
755
let arity = constructor_arity ( cx, & c, left_ty) ;
731
- let mut result = {
756
+ let mut result: Vec < _ > = {
732
757
let pat_slice = & pats[ ..] ;
733
758
let subpats: Vec < _ > = ( 0 ..arity) . map ( |i| {
734
759
pat_slice. get ( i) . map_or ( DUMMY_WILD_PAT , |p| & * * p)
735
760
} ) . collect ( ) ;
736
- vec ! [ construct_witness( cx, & c, subpats, left_ty) ]
761
+ construct_witness ( cx, & c, subpats, left_ty) . into_iter ( ) . collect ( )
737
762
} ;
738
763
result. extend ( pats. into_iter ( ) . skip ( arity) ) ;
739
- result
740
- } ) ,
764
+ if result. is_empty ( ) {
765
+ NotUseful
766
+ } else {
767
+ UsefulWithWitness ( result)
768
+ }
769
+ } ,
741
770
result => result
742
771
}
743
772
} ) . find ( |result| result != & NotUseful ) . unwrap_or ( NotUseful )
@@ -750,13 +779,17 @@ fn is_useful<'a, 'tcx>(cx: &MatchCheckCtxt<'a, 'tcx>,
750
779
} ) . collect ( ) ;
751
780
match is_useful ( cx, & matrix, & v[ 1 ..] , witness) {
752
781
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| {
754
783
let arity = constructor_arity ( cx, & constructor, left_ty) ;
755
784
let wild_pats = vec ! [ DUMMY_WILD_PAT ; arity] ;
756
785
construct_witness ( cx, & constructor, wild_pats, left_ty)
757
786
} ) . collect ( ) ;
758
787
new_pats. extend ( pats) ;
759
- UsefulWithWitness ( new_pats)
788
+ if new_pats. is_empty ( ) {
789
+ NotUseful
790
+ } else {
791
+ UsefulWithWitness ( new_pats)
792
+ }
760
793
} ,
761
794
result => result
762
795
}
@@ -780,7 +813,8 @@ fn is_useful_specialized<'a, 'tcx>(
780
813
let matrix = Matrix ( m. iter ( ) . filter_map ( |r| {
781
814
specialize ( cx, & r[ ..] , & ctor, 0 , arity)
782
815
} ) . collect ( ) ) ;
783
- match specialize ( cx, v, & ctor, 0 , arity) {
816
+ let spec = specialize ( cx, v, & ctor, 0 , arity) ;
817
+ match spec {
784
818
Some ( v) => is_useful ( cx, & matrix, & v[ ..] , witness) ,
785
819
None => NotUseful
786
820
}
0 commit comments