Skip to content

Commit 5c26509

Browse files
committed
restructure the public inhabitedness APIs and remove the cache
The cache was broken anyhow and this computation doesn't look that expensive. These public accessors could potentially become queries, but we'd have to add some more complex logic around lift. I'd prefer to have some test cases to profile with before doing that. Fixes #44402.
1 parent a5673de commit 5c26509

File tree

5 files changed

+70
-41
lines changed

5 files changed

+70
-41
lines changed

src/librustc/ty/context.rs

-4
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ use ty::RegionKind;
4343
use ty::{TyVar, TyVid, IntVar, IntVid, FloatVar, FloatVid};
4444
use ty::TypeVariants::*;
4545
use ty::layout::{Layout, TargetDataLayout};
46-
use ty::inhabitedness::DefIdForest;
4746
use ty::maps;
4847
use ty::steal::Steal;
4948
use ty::BindingMode;
@@ -896,8 +895,6 @@ pub struct GlobalCtxt<'tcx> {
896895
// FIXME dep tracking -- should be harmless enough
897896
pub normalized_cache: RefCell<FxHashMap<Ty<'tcx>, Ty<'tcx>>>,
898897

899-
pub inhabitedness_cache: RefCell<FxHashMap<Ty<'tcx>, DefIdForest>>,
900-
901898
/// Caches the results of trait selection. This cache is used
902899
/// for things that do not have to do with the parameters in scope.
903900
pub selection_cache: traits::SelectionCache<'tcx>,
@@ -1179,7 +1176,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
11791176
mir_passes,
11801177
rcache: RefCell::new(FxHashMap()),
11811178
normalized_cache: RefCell::new(FxHashMap()),
1182-
inhabitedness_cache: RefCell::new(FxHashMap()),
11831179
selection_cache: traits::SelectionCache::new(),
11841180
evaluation_cache: traits::EvaluationCache::new(),
11851181
rvalue_promotable_to_static: RefCell::new(NodeMap()),

src/librustc/ty/inhabitedness/mod.rs

+18-33
Original file line numberDiff line numberDiff line change
@@ -100,14 +100,16 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
100100
/// This code should only compile in modules where the uninhabitedness of Foo is
101101
/// visible.
102102
pub fn is_ty_uninhabited_from(self, module: DefId, ty: Ty<'tcx>) -> bool {
103-
let forest = ty.uninhabited_from(&mut FxHashMap(), self);
104-
105103
// To check whether this type is uninhabited at all (not just from the
106104
// given node) you could check whether the forest is empty.
107105
// ```
108106
// forest.is_empty()
109107
// ```
110-
forest.contains(self, module)
108+
self.ty_inhabitedness_forest(ty).contains(self, module)
109+
}
110+
111+
fn ty_inhabitedness_forest(self, ty: Ty<'tcx>) -> DefIdForest {
112+
ty.uninhabited_from(&mut FxHashMap(), self)
111113
}
112114

113115
pub fn is_enum_variant_uninhabited_from(self,
@@ -116,17 +118,25 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
116118
substs: &'tcx Substs<'tcx>)
117119
-> bool
118120
{
119-
let adt_kind = AdtKind::Enum;
120-
variant.uninhabited_from(&mut FxHashMap(), self, substs, adt_kind).contains(self, module)
121+
self.variant_inhabitedness_forest(variant, substs).contains(self, module)
121122
}
122123

123124
pub fn is_variant_uninhabited_from_all_modules(self,
124125
variant: &'tcx VariantDef,
125-
substs: &'tcx Substs<'tcx>,
126-
adt_kind: AdtKind)
126+
substs: &'tcx Substs<'tcx>)
127127
-> bool
128128
{
129-
!variant.uninhabited_from(&mut FxHashMap(), self, substs, adt_kind).is_empty()
129+
!self.variant_inhabitedness_forest(variant, substs).is_empty()
130+
}
131+
132+
fn variant_inhabitedness_forest(self, variant: &'tcx VariantDef, substs: &'tcx Substs<'tcx>)
133+
-> DefIdForest {
134+
// Determine the ADT kind:
135+
let adt_def_id = self.adt_def_id_of_variant(variant);
136+
let adt_kind = self.adt_def(adt_def_id).adt_kind();
137+
138+
// Compute inhabitedness forest:
139+
variant.uninhabited_from(&mut FxHashMap(), self, substs, adt_kind)
130140
}
131141
}
132142

@@ -210,31 +220,6 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
210220
&self,
211221
visited: &mut FxHashMap<DefId, FxHashSet<&'tcx Substs<'tcx>>>,
212222
tcx: TyCtxt<'a, 'gcx, 'tcx>) -> DefIdForest
213-
{
214-
match tcx.lift_to_global(&self) {
215-
Some(global_ty) => {
216-
{
217-
let cache = tcx.inhabitedness_cache.borrow();
218-
if let Some(forest) = cache.get(&global_ty) {
219-
return forest.clone();
220-
}
221-
}
222-
let forest = global_ty.uninhabited_from_inner(visited, tcx);
223-
let mut cache = tcx.inhabitedness_cache.borrow_mut();
224-
cache.insert(global_ty, forest.clone());
225-
forest
226-
},
227-
None => {
228-
let forest = self.uninhabited_from_inner(visited, tcx);
229-
forest
230-
},
231-
}
232-
}
233-
234-
fn uninhabited_from_inner(
235-
&self,
236-
visited: &mut FxHashMap<DefId, FxHashSet<&'tcx Substs<'tcx>>>,
237-
tcx: TyCtxt<'a, 'gcx, 'tcx>) -> DefIdForest
238223
{
239224
match self.sty {
240225
TyAdt(def, substs) => {

src/librustc/ty/mod.rs

+15
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ pub use self::fold::TypeFoldable;
1818
use hir::{map as hir_map, FreevarMap, TraitMap};
1919
use hir::def::{Def, CtorKind, ExportMap};
2020
use hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
21+
use hir::map::DefPathData;
2122
use ich::StableHashingContext;
2223
use middle::const_val::ConstVal;
2324
use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem};
@@ -2232,6 +2233,20 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
22322233
}
22332234
}
22342235

2236+
/// Given a `VariantDef`, returns the def-id of the `AdtDef` of which it is a part.
2237+
pub fn adt_def_id_of_variant(self, variant_def: &'tcx VariantDef) -> DefId {
2238+
let def_key = self.def_key(variant_def.did);
2239+
match def_key.disambiguated_data.data {
2240+
// for enum variants and tuple structs, the def-id of the ADT itself
2241+
// is the *parent* of the variant
2242+
DefPathData::EnumVariant(..) | DefPathData::StructCtor =>
2243+
DefId { krate: variant_def.did.krate, index: def_key.parent.unwrap() },
2244+
2245+
// otherwise, for structs and unions, they share a def-id
2246+
_ => variant_def.did,
2247+
}
2248+
}
2249+
22352250
pub fn item_name(self, id: DefId) -> InternedString {
22362251
if let Some(id) = self.hir.as_local_node_id(id) {
22372252
self.hir.name(id).as_str()

src/librustc_mir/build/matches/simplify.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -101,10 +101,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
101101
if self.hir.tcx().sess.features.borrow().never_type {
102102
let irrefutable = adt_def.variants.iter().enumerate().all(|(i, v)| {
103103
i == variant_index || {
104-
let adt_kind = adt_def.adt_kind();
105-
self.hir.tcx().is_variant_uninhabited_from_all_modules(v,
106-
substs,
107-
adt_kind)
104+
self.hir.tcx().is_variant_uninhabited_from_all_modules(v, substs)
108105
}
109106
});
110107
if irrefutable {

src/test/run-pass/issue-44402.rs

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(never_type)]
12+
13+
// Regression test for inhabitedness check. The old
14+
// cache used to cause us to incorrectly decide
15+
// that `test_b` was invalid.
16+
17+
struct Foo {
18+
field1: !,
19+
field2: Option<&'static Bar>,
20+
}
21+
22+
struct Bar {
23+
field1: &'static Foo
24+
}
25+
26+
fn test_a() {
27+
let x: Option<Foo> = None;
28+
match x { None => () }
29+
}
30+
31+
fn test_b() {
32+
let x: Option<Bar> = None;
33+
match x { None => () }
34+
}
35+
36+
fn main() { }

0 commit comments

Comments
 (0)