Consider references and unions potentially inhabited during privacy-respecting inhabitedness checks

This commit is contained in:
varkor 2018-11-20 19:20:14 +00:00
parent 3dde9e1322
commit 682f0f8d80

View file

@ -167,23 +167,15 @@ impl<'a, 'gcx, 'tcx> VariantDef {
substs: &'tcx Substs<'tcx>, substs: &'tcx Substs<'tcx>,
adt_kind: AdtKind) -> DefIdForest adt_kind: AdtKind) -> DefIdForest
{ {
match adt_kind { let is_enum = match adt_kind {
AdtKind::Union => { // For now, `union`s are never considered uninhabited.
DefIdForest::intersection(tcx, self.fields.iter().map(|f| { AdtKind::Union => return DefIdForest::empty(),
f.uninhabited_from(visited, tcx, substs, false) AdtKind::Enum => true,
})) AdtKind::Struct => false,
}, };
AdtKind::Struct => { DefIdForest::union(tcx, self.fields.iter().map(|f| {
DefIdForest::union(tcx, self.fields.iter().map(|f| { f.uninhabited_from(visited, tcx, substs, is_enum)
f.uninhabited_from(visited, tcx, substs, false) }))
}))
},
AdtKind::Enum => {
DefIdForest::union(tcx, self.fields.iter().map(|f| {
f.uninhabited_from(visited, tcx, substs, true)
}))
},
}
} }
} }
@ -194,8 +186,8 @@ impl<'a, 'gcx, 'tcx> FieldDef {
visited: &mut FxHashMap<DefId, FxHashSet<&'tcx Substs<'tcx>>>, visited: &mut FxHashMap<DefId, FxHashSet<&'tcx Substs<'tcx>>>,
tcx: TyCtxt<'a, 'gcx, 'tcx>, tcx: TyCtxt<'a, 'gcx, 'tcx>,
substs: &'tcx Substs<'tcx>, substs: &'tcx Substs<'tcx>,
is_enum: bool) -> DefIdForest is_enum: bool,
{ ) -> DefIdForest {
let mut data_uninhabitedness = move || { let mut data_uninhabitedness = move || {
self.ty(tcx, substs).uninhabited_from(visited, tcx) self.ty(tcx, substs).uninhabited_from(visited, tcx)
}; };
@ -253,14 +245,16 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
let substs_set = visited.get_mut(&def.did).unwrap(); let substs_set = visited.get_mut(&def.did).unwrap();
substs_set.remove(substs); substs_set.remove(substs);
ret ret
}, }
Never => DefIdForest::full(tcx), Never => DefIdForest::full(tcx),
Tuple(ref tys) => { Tuple(ref tys) => {
DefIdForest::union(tcx, tys.iter().map(|ty| { DefIdForest::union(tcx, tys.iter().map(|ty| {
ty.uninhabited_from(visited, tcx) ty.uninhabited_from(visited, tcx)
})) }))
}, }
Array(ty, len) => { Array(ty, len) => {
match len.assert_usize(tcx) { match len.assert_usize(tcx) {
// If the array is definitely non-empty, it's uninhabited if // If the array is definitely non-empty, it's uninhabited if
@ -269,9 +263,11 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
_ => DefIdForest::empty() _ => DefIdForest::empty()
} }
} }
Ref(_, ty, _) => {
ty.uninhabited_from(visited, tcx) // References to uninitialised memory is valid for any type, including
} // uninhabited types, in unsafe code, so we treat all references as
// inhabited.
Ref(..) => DefIdForest::empty(),
_ => DefIdForest::empty(), _ => DefIdForest::empty(),
} }