@@ -1489,14 +1489,40 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
14891489 }
14901490 }
14911491
1492- pub fn conservative_is_uninhabited ( & self ) -> bool {
1492+ pub fn conservative_is_uninhabited ( & self , tcx : TyCtxt < ' a , ' gcx , ' tcx > ) -> bool {
14931493 // Checks whether a type is definitely uninhabited. This is
14941494 // conservative: for some types that are uninhabited we return `false`,
14951495 // but we only return `true` for types that are definitely uninhabited.
14961496 match self . sty {
14971497 ty:: Never => true ,
1498- ty:: Adt ( def, _) => def. variants . is_empty ( ) ,
1499- _ => false
1498+ ty:: Adt ( def, _) => {
1499+ // Any ADT is uninhabited if:
1500+ // (a) It has no variants (i.e. an empty `enum`);
1501+ // (b) Each of its variants (a single one in the case of a `struct`) has at least
1502+ // one uninhabited field.
1503+ def. variants . iter ( ) . all ( |var| {
1504+ var. fields . iter ( ) . any ( |field| {
1505+ tcx. type_of ( field. did ) . conservative_is_uninhabited ( tcx)
1506+ } )
1507+ } )
1508+ }
1509+ ty:: Tuple ( tys) => tys. iter ( ) . any ( |ty| ty. conservative_is_uninhabited ( tcx) ) ,
1510+ ty:: Array ( ty, len) => {
1511+ match len. val . try_to_scalar ( ) {
1512+ // If the array is definitely non-empty, it's uninhabited if
1513+ // the type of its elements is uninhabited.
1514+ Some ( n) if !n. is_null ( ) => ty. conservative_is_uninhabited ( tcx) ,
1515+ _ => false
1516+ }
1517+ }
1518+ ty:: Ref ( ..) => {
1519+ // Though references to uninhabited types are trivially uninhabited
1520+ // theoretically, null references are permitted in unsafe code (as
1521+ // long as the value is not dereferenced), so we treat all references
1522+ // as inhabited.
1523+ false
1524+ }
1525+ _ => false ,
15001526 }
15011527 }
15021528
0 commit comments