@@ -1543,14 +1543,40 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
15431543 }
15441544 }
15451545
1546- pub fn conservative_is_uninhabited ( & self ) -> bool {
1546+ pub fn conservative_is_uninhabited ( & self , tcx : TyCtxt < ' a , ' gcx , ' tcx > ) -> bool {
15471547 // Checks whether a type is definitely uninhabited. This is
15481548 // conservative: for some types that are uninhabited we return `false`,
15491549 // but we only return `true` for types that are definitely uninhabited.
15501550 match self . sty {
15511551 ty:: Never => true ,
1552- ty:: Adt ( def, _) => def. variants . is_empty ( ) ,
1553- _ => false
1552+ ty:: Adt ( def, _) => {
1553+ // Any ADT is uninhabited if:
1554+ // (a) It has no variants (i.e. an empty `enum`);
1555+ // (b) Each of its variants (a single one in the case of a `struct`) has at least
1556+ // one uninhabited field.
1557+ def. variants . iter ( ) . all ( |var| {
1558+ var. fields . iter ( ) . any ( |field| {
1559+ tcx. type_of ( field. did ) . conservative_is_uninhabited ( tcx)
1560+ } )
1561+ } )
1562+ }
1563+ ty:: Tuple ( tys) => tys. iter ( ) . any ( |ty| ty. conservative_is_uninhabited ( tcx) ) ,
1564+ ty:: Array ( ty, len) => {
1565+ match len. val . try_to_scalar ( ) {
1566+ // If the array is definitely non-empty, it's uninhabited if
1567+ // the type of its elements is uninhabited.
1568+ Some ( n) if !n. is_null ( ) => ty. conservative_is_uninhabited ( tcx) ,
1569+ _ => false
1570+ }
1571+ }
1572+ ty:: Ref ( ..) => {
1573+ // Though references to uninhabited types are trivially uninhabited
1574+ // theoretically, null references are permitted in unsafe code (as
1575+ // long as the value is not dereferenced), so we treat all references
1576+ // as inhabited.
1577+ false
1578+ }
1579+ _ => false ,
15541580 }
15551581 }
15561582
0 commit comments