@@ -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