@@ -196,6 +196,28 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
196
196
}
197
197
} ) . clone ( )
198
198
}
199
+
200
+ fn is_uninhabited ( & self , ty : Ty < ' tcx > ) -> bool {
201
+ if self . tcx . sess . features . borrow ( ) . never_type {
202
+ ty. is_uninhabited_from ( self . module , self . tcx )
203
+ } else {
204
+ false
205
+ }
206
+ }
207
+
208
+ fn is_variant_uninhabited ( & self ,
209
+ variant : & ' tcx ty:: VariantDef ,
210
+ substs : & ' tcx ty:: subst:: Substs < ' tcx > ) -> bool
211
+ {
212
+ if self . tcx . sess . features . borrow ( ) . never_type {
213
+ let forest = variant. uninhabited_from (
214
+ & mut FxHashMap :: default ( ) , self . tcx , substs, AdtKind :: Enum
215
+ ) ;
216
+ forest. contains ( self . tcx , self . module )
217
+ } else {
218
+ false
219
+ }
220
+ }
199
221
}
200
222
201
223
#[ derive( Clone , Debug , PartialEq ) ]
@@ -379,48 +401,32 @@ impl<'tcx> Witness<'tcx> {
379
401
fn all_constructors < ' a , ' tcx : ' a > ( cx : & mut MatchCheckCtxt < ' a , ' tcx > ,
380
402
pcx : PatternContext < ' tcx > ) -> Vec < Constructor >
381
403
{
382
- let check_inhabited = cx. tcx . sess . features . borrow ( ) . never_type ;
383
404
debug ! ( "all_constructors({:?})" , pcx. ty) ;
384
405
match pcx. ty . sty {
385
406
ty:: TyBool =>
386
407
[ true , false ] . iter ( ) . map ( |b| ConstantValue ( ConstVal :: Bool ( * b) ) ) . collect ( ) ,
387
408
ty:: TySlice ( ref sub_ty) => {
388
- if sub_ty. is_uninhabited_from ( cx. module , cx. tcx )
389
- && check_inhabited
390
- {
409
+ if cx. is_uninhabited ( sub_ty) {
391
410
vec ! [ Slice ( 0 ) ]
392
411
} else {
393
412
( 0 ..pcx. max_slice_length +1 ) . map ( |length| Slice ( length) ) . collect ( )
394
413
}
395
414
}
396
415
ty:: TyArray ( ref sub_ty, length) => {
397
- if length == 0 || !( sub_ty. is_uninhabited_from ( cx. module , cx. tcx )
398
- && check_inhabited)
399
- {
400
- vec ! [ Slice ( length) ]
401
- } else {
416
+ if length > 0 && cx. is_uninhabited ( sub_ty) {
402
417
vec ! [ ]
418
+ } else {
419
+ vec ! [ Slice ( length) ]
403
420
}
404
421
}
405
422
ty:: TyAdt ( def, substs) if def. is_enum ( ) && def. variants . len ( ) != 1 => {
406
- def. variants . iter ( ) . filter_map ( |v| {
407
- let mut visited = FxHashMap :: default ( ) ;
408
- let forest = v. uninhabited_from ( & mut visited,
409
- cx. tcx , substs,
410
- AdtKind :: Enum ) ;
411
- if forest. contains ( cx. tcx , cx. module )
412
- && check_inhabited
413
- {
414
- None
415
- } else {
416
- Some ( Variant ( v. did ) )
417
- }
418
- } ) . collect ( )
423
+ def. variants . iter ( )
424
+ . filter ( |v| !cx. is_variant_uninhabited ( v, substs) )
425
+ . map ( |v| Variant ( v. did ) )
426
+ . collect ( )
419
427
}
420
428
_ => {
421
- if pcx. ty . is_uninhabited_from ( cx. module , cx. tcx )
422
- && check_inhabited
423
- {
429
+ if cx. is_uninhabited ( pcx. ty ) {
424
430
vec ! [ ]
425
431
} else {
426
432
vec ! [ Single ]
@@ -564,7 +570,6 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
564
570
565
571
assert ! ( rows. iter( ) . all( |r| r. len( ) == v. len( ) ) ) ;
566
572
567
-
568
573
let pcx = PatternContext {
569
574
ty : rows. iter ( ) . map ( |r| r[ 0 ] . ty ) . find ( |ty| !ty. references_error ( ) )
570
575
. unwrap_or ( v[ 0 ] . ty ) ,
@@ -590,7 +595,6 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
590
595
let missing_ctors: Vec < Constructor > = all_ctors. iter ( ) . filter ( |c| {
591
596
!used_ctors. contains ( * c)
592
597
} ) . cloned ( ) . collect ( ) ;
593
- debug ! ( "missing_ctors = {:?}" , missing_ctors) ;
594
598
595
599
// `missing_ctors` is the set of constructors from the same type as the
596
600
// first column of `matrix` that are matched only by wildcard patterns
@@ -599,8 +603,23 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
599
603
// Therefore, if there is some pattern that is unmatched by `matrix`,
600
604
// it will still be unmatched if the first constructor is replaced by
601
605
// any of the constructors in `missing_ctors`
602
-
603
- if missing_ctors. is_empty ( ) {
606
+ //
607
+ // However, if our scrutinee is *privately* an empty enum, we
608
+ // must treat it as though it had an "unknown" constructor (in
609
+ // that case, all other patterns obviously can't be variants)
610
+ // to avoid exposing its emptyness. See the `match_privately_empty`
611
+ // test for details.
612
+ //
613
+ // FIXME: currently the only way I know of something can
614
+ // be a privately-empty enum is when the never_type
615
+ // feature flag is not present, so this is only
616
+ // needed for that case.
617
+
618
+ let is_privately_empty =
619
+ all_ctors. is_empty ( ) && !cx. is_uninhabited ( pcx. ty ) ;
620
+ debug ! ( "missing_ctors={:?} is_privately_empty={:?}" , missing_ctors,
621
+ is_privately_empty) ;
622
+ if missing_ctors. is_empty ( ) && !is_privately_empty {
604
623
all_ctors. into_iter ( ) . map ( |c| {
605
624
is_useful_specialized ( cx, matrix, v, c. clone ( ) , pcx. ty , witness)
606
625
} ) . find ( |result| result. is_useful ( ) ) . unwrap_or ( NotUseful )
@@ -649,6 +668,7 @@ fn is_useful_specialized<'p, 'a:'p, 'tcx: 'a>(
649
668
lty : Ty < ' tcx > ,
650
669
witness : WitnessPreference ) -> Usefulness < ' tcx >
651
670
{
671
+ debug ! ( "is_useful_specialized({:?}, {:?}, {:?})" , v, ctor, lty) ;
652
672
let sub_pat_tys = constructor_sub_pattern_tys ( cx, & ctor, lty) ;
653
673
let wild_patterns_owned: Vec < _ > = sub_pat_tys. iter ( ) . map ( |ty| {
654
674
Pattern {
@@ -754,7 +774,19 @@ fn constructor_sub_pattern_tys<'a, 'tcx: 'a>(cx: &MatchCheckCtxt<'a, 'tcx>,
754
774
ty:: TyRef ( _, ref ty_and_mut) => vec ! [ ty_and_mut. ty] ,
755
775
ty:: TyAdt ( adt, substs) => {
756
776
adt. variants [ ctor. variant_index_for_adt ( adt) ] . fields . iter ( ) . map ( |field| {
757
- field. ty ( cx. tcx , substs)
777
+ let is_visible = adt. is_enum ( )
778
+ || field. vis . is_accessible_from ( cx. module , cx. tcx ) ;
779
+ if is_visible {
780
+ field. ty ( cx. tcx , substs)
781
+ } else {
782
+ // Treat all non-visible fields as nil. They
783
+ // can't appear in any other pattern from
784
+ // this match (because they are private),
785
+ // so their type does not matter - but
786
+ // we don't want to know they are
787
+ // uninhabited.
788
+ cx. tcx . mk_nil ( )
789
+ }
758
790
} ) . collect ( )
759
791
}
760
792
_ => vec ! [ ] ,
0 commit comments