Fiddle ParamEnv
through to a place that used to use ParamEnv::empty
in a buggy manner
This commit is contained in:
parent
59f4ba9504
commit
7894509b00
@ -90,30 +90,46 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||||||
/// ```
|
/// ```
|
||||||
/// This code should only compile in modules where the uninhabitedness of Foo is
|
/// This code should only compile in modules where the uninhabitedness of Foo is
|
||||||
/// visible.
|
/// visible.
|
||||||
pub fn is_ty_uninhabited_from(self, module: DefId, ty: Ty<'tcx>) -> bool {
|
pub fn is_ty_uninhabited_from(
|
||||||
|
self,
|
||||||
|
module: DefId,
|
||||||
|
ty: Ty<'tcx>,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
|
) -> bool {
|
||||||
// To check whether this type is uninhabited at all (not just from the
|
// To check whether this type is uninhabited at all (not just from the
|
||||||
// given node), you could check whether the forest is empty.
|
// given node), you could check whether the forest is empty.
|
||||||
// ```
|
// ```
|
||||||
// forest.is_empty()
|
// forest.is_empty()
|
||||||
// ```
|
// ```
|
||||||
ty.uninhabited_from(self).contains(self, module)
|
ty.uninhabited_from(self, param_env).contains(self, module)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_ty_uninhabited_from_any_module(self, ty: Ty<'tcx>) -> bool {
|
pub fn is_ty_uninhabited_from_any_module(
|
||||||
!ty.uninhabited_from(self).is_empty()
|
self,
|
||||||
|
ty: Ty<'tcx>,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
|
) -> bool {
|
||||||
|
!ty.uninhabited_from(self, param_env).is_empty()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> AdtDef {
|
impl<'tcx> AdtDef {
|
||||||
/// Calculates the forest of `DefId`s from which this ADT is visibly uninhabited.
|
/// Calculates the forest of `DefId`s from which this ADT is visibly uninhabited.
|
||||||
fn uninhabited_from(&self, tcx: TyCtxt<'tcx>, substs: SubstsRef<'tcx>) -> DefIdForest {
|
fn uninhabited_from(
|
||||||
|
&self,
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
substs: SubstsRef<'tcx>,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
|
) -> DefIdForest {
|
||||||
// Non-exhaustive ADTs from other crates are always considered inhabited.
|
// Non-exhaustive ADTs from other crates are always considered inhabited.
|
||||||
if self.is_variant_list_non_exhaustive() && !self.did.is_local() {
|
if self.is_variant_list_non_exhaustive() && !self.did.is_local() {
|
||||||
DefIdForest::empty()
|
DefIdForest::empty()
|
||||||
} else {
|
} else {
|
||||||
DefIdForest::intersection(
|
DefIdForest::intersection(
|
||||||
tcx,
|
tcx,
|
||||||
self.variants.iter().map(|v| v.uninhabited_from(tcx, substs, self.adt_kind())),
|
self.variants
|
||||||
|
.iter()
|
||||||
|
.map(|v| v.uninhabited_from(tcx, substs, self.adt_kind(), param_env)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -126,6 +142,7 @@ impl<'tcx> VariantDef {
|
|||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
substs: SubstsRef<'tcx>,
|
substs: SubstsRef<'tcx>,
|
||||||
adt_kind: AdtKind,
|
adt_kind: AdtKind,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
) -> DefIdForest {
|
) -> DefIdForest {
|
||||||
let is_enum = match adt_kind {
|
let is_enum = match adt_kind {
|
||||||
// For now, `union`s are never considered uninhabited.
|
// For now, `union`s are never considered uninhabited.
|
||||||
@ -140,7 +157,7 @@ impl<'tcx> VariantDef {
|
|||||||
} else {
|
} else {
|
||||||
DefIdForest::union(
|
DefIdForest::union(
|
||||||
tcx,
|
tcx,
|
||||||
self.fields.iter().map(|f| f.uninhabited_from(tcx, substs, is_enum)),
|
self.fields.iter().map(|f| f.uninhabited_from(tcx, substs, is_enum, param_env)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -153,8 +170,9 @@ impl<'tcx> FieldDef {
|
|||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
substs: SubstsRef<'tcx>,
|
substs: SubstsRef<'tcx>,
|
||||||
is_enum: bool,
|
is_enum: bool,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
) -> DefIdForest {
|
) -> DefIdForest {
|
||||||
let data_uninhabitedness = move || self.ty(tcx, substs).uninhabited_from(tcx);
|
let data_uninhabitedness = move || self.ty(tcx, substs).uninhabited_from(tcx, param_env);
|
||||||
// FIXME(canndrew): Currently enum fields are (incorrectly) stored with
|
// FIXME(canndrew): Currently enum fields are (incorrectly) stored with
|
||||||
// `Visibility::Invisible` so we need to override `self.vis` if we're
|
// `Visibility::Invisible` so we need to override `self.vis` if we're
|
||||||
// dealing with an enum.
|
// dealing with an enum.
|
||||||
@ -176,20 +194,21 @@ impl<'tcx> FieldDef {
|
|||||||
|
|
||||||
impl<'tcx> TyS<'tcx> {
|
impl<'tcx> TyS<'tcx> {
|
||||||
/// Calculates the forest of `DefId`s from which this type is visibly uninhabited.
|
/// Calculates the forest of `DefId`s from which this type is visibly uninhabited.
|
||||||
fn uninhabited_from(&self, tcx: TyCtxt<'tcx>) -> DefIdForest {
|
fn uninhabited_from(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> DefIdForest {
|
||||||
match self.kind {
|
match self.kind {
|
||||||
Adt(def, substs) => def.uninhabited_from(tcx, substs),
|
Adt(def, substs) => def.uninhabited_from(tcx, substs, param_env),
|
||||||
|
|
||||||
Never => DefIdForest::full(tcx),
|
Never => DefIdForest::full(tcx),
|
||||||
|
|
||||||
Tuple(ref tys) => {
|
Tuple(ref tys) => DefIdForest::union(
|
||||||
DefIdForest::union(tcx, tys.iter().map(|ty| ty.expect_ty().uninhabited_from(tcx)))
|
tcx,
|
||||||
}
|
tys.iter().map(|ty| ty.expect_ty().uninhabited_from(tcx, param_env)),
|
||||||
|
),
|
||||||
|
|
||||||
Array(ty, len) => match len.try_eval_usize(tcx, ty::ParamEnv::empty()) {
|
Array(ty, len) => match len.try_eval_usize(tcx, param_env) {
|
||||||
// If the array is definitely non-empty, it's uninhabited if
|
// If the array is definitely non-empty, it's uninhabited if
|
||||||
// the type of its elements is uninhabited.
|
// the type of its elements is uninhabited.
|
||||||
Some(n) if n != 0 => ty.uninhabited_from(tcx),
|
Some(n) if n != 0 => ty.uninhabited_from(tcx, param_env),
|
||||||
_ => DefIdForest::empty(),
|
_ => DefIdForest::empty(),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -124,7 +124,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults {
|
|||||||
descr_post: &str,
|
descr_post: &str,
|
||||||
plural_len: usize,
|
plural_len: usize,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
if ty.is_unit() || cx.tcx.is_ty_uninhabited_from(cx.tcx.parent_module(expr.hir_id), ty)
|
if ty.is_unit()
|
||||||
|
|| cx.tcx.is_ty_uninhabited_from(
|
||||||
|
cx.tcx.parent_module(expr.hir_id),
|
||||||
|
ty,
|
||||||
|
cx.param_env,
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -209,7 +209,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
i == variant_index || {
|
i == variant_index || {
|
||||||
self.hir.tcx().features().exhaustive_patterns
|
self.hir.tcx().features().exhaustive_patterns
|
||||||
&& !v
|
&& !v
|
||||||
.uninhabited_from(self.hir.tcx(), substs, adt_def.adt_kind())
|
.uninhabited_from(
|
||||||
|
self.hir.tcx(),
|
||||||
|
substs,
|
||||||
|
adt_def.adt_kind(),
|
||||||
|
self.hir.param_env,
|
||||||
|
)
|
||||||
.is_empty()
|
.is_empty()
|
||||||
}
|
}
|
||||||
}) && (adt_def.did.is_local()
|
}) && (adt_def.did.is_local()
|
||||||
|
@ -598,7 +598,7 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
|
|||||||
|
|
||||||
fn is_uninhabited(&self, ty: Ty<'tcx>) -> bool {
|
fn is_uninhabited(&self, ty: Ty<'tcx>) -> bool {
|
||||||
if self.tcx.features().exhaustive_patterns {
|
if self.tcx.features().exhaustive_patterns {
|
||||||
self.tcx.is_ty_uninhabited_from(self.module, ty)
|
self.tcx.is_ty_uninhabited_from(self.module, ty, self.param_env)
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
@ -1267,7 +1267,7 @@ fn all_constructors<'a, 'tcx>(
|
|||||||
def.variants
|
def.variants
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|v| {
|
.filter(|v| {
|
||||||
!v.uninhabited_from(cx.tcx, substs, def.adt_kind())
|
!v.uninhabited_from(cx.tcx, substs, def.adt_kind(), cx.param_env)
|
||||||
.contains(cx.tcx, cx.module)
|
.contains(cx.tcx, cx.module)
|
||||||
})
|
})
|
||||||
.map(|v| Variant(v.def_id))
|
.map(|v| Variant(v.def_id))
|
||||||
|
@ -398,7 +398,7 @@ fn visit_fn<'tcx>(
|
|||||||
intravisit::walk_fn(&mut fn_maps, fk, decl, body_id, sp, id);
|
intravisit::walk_fn(&mut fn_maps, fk, decl, body_id, sp, id);
|
||||||
|
|
||||||
// compute liveness
|
// compute liveness
|
||||||
let mut lsets = Liveness::new(&mut fn_maps, body_id);
|
let mut lsets = Liveness::new(&mut fn_maps, def_id);
|
||||||
let entry_ln = lsets.compute(&body.value);
|
let entry_ln = lsets.compute(&body.value);
|
||||||
|
|
||||||
// check for various error conditions
|
// check for various error conditions
|
||||||
@ -658,6 +658,7 @@ const ACC_USE: u32 = 4;
|
|||||||
struct Liveness<'a, 'tcx> {
|
struct Liveness<'a, 'tcx> {
|
||||||
ir: &'a mut IrMaps<'tcx>,
|
ir: &'a mut IrMaps<'tcx>,
|
||||||
tables: &'a ty::TypeckTables<'tcx>,
|
tables: &'a ty::TypeckTables<'tcx>,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
s: Specials,
|
s: Specials,
|
||||||
successors: Vec<LiveNode>,
|
successors: Vec<LiveNode>,
|
||||||
rwu_table: RWUTable,
|
rwu_table: RWUTable,
|
||||||
@ -670,7 +671,7 @@ struct Liveness<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
||||||
fn new(ir: &'a mut IrMaps<'tcx>, body: hir::BodyId) -> Liveness<'a, 'tcx> {
|
fn new(ir: &'a mut IrMaps<'tcx>, def_id: DefId) -> Liveness<'a, 'tcx> {
|
||||||
// Special nodes and variables:
|
// Special nodes and variables:
|
||||||
// - exit_ln represents the end of the fn, either by return or panic
|
// - exit_ln represents the end of the fn, either by return or panic
|
||||||
// - implicit_ret_var is a pseudo-variable that represents
|
// - implicit_ret_var is a pseudo-variable that represents
|
||||||
@ -681,7 +682,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
|||||||
clean_exit_var: ir.add_variable(CleanExit),
|
clean_exit_var: ir.add_variable(CleanExit),
|
||||||
};
|
};
|
||||||
|
|
||||||
let tables = ir.tcx.body_tables(body);
|
let tables = ir.tcx.typeck_tables_of(def_id);
|
||||||
|
let param_env = ir.tcx.param_env(def_id);
|
||||||
|
|
||||||
let num_live_nodes = ir.num_live_nodes;
|
let num_live_nodes = ir.num_live_nodes;
|
||||||
let num_vars = ir.num_vars;
|
let num_vars = ir.num_vars;
|
||||||
@ -689,6 +691,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
|||||||
Liveness {
|
Liveness {
|
||||||
ir,
|
ir,
|
||||||
tables,
|
tables,
|
||||||
|
param_env,
|
||||||
s: specials,
|
s: specials,
|
||||||
successors: vec![invalid_node(); num_live_nodes],
|
successors: vec![invalid_node(); num_live_nodes],
|
||||||
rwu_table: RWUTable::new(num_live_nodes * num_vars),
|
rwu_table: RWUTable::new(num_live_nodes * num_vars),
|
||||||
@ -1126,7 +1129,11 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
|||||||
|
|
||||||
hir::ExprKind::Call(ref f, ref args) => {
|
hir::ExprKind::Call(ref f, ref args) => {
|
||||||
let m = self.ir.tcx.parent_module(expr.hir_id);
|
let m = self.ir.tcx.parent_module(expr.hir_id);
|
||||||
let succ = if self.ir.tcx.is_ty_uninhabited_from(m, self.tables.expr_ty(expr)) {
|
let succ = if self.ir.tcx.is_ty_uninhabited_from(
|
||||||
|
m,
|
||||||
|
self.tables.expr_ty(expr),
|
||||||
|
self.param_env,
|
||||||
|
) {
|
||||||
self.s.exit_ln
|
self.s.exit_ln
|
||||||
} else {
|
} else {
|
||||||
succ
|
succ
|
||||||
@ -1137,7 +1144,11 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
|||||||
|
|
||||||
hir::ExprKind::MethodCall(.., ref args) => {
|
hir::ExprKind::MethodCall(.., ref args) => {
|
||||||
let m = self.ir.tcx.parent_module(expr.hir_id);
|
let m = self.ir.tcx.parent_module(expr.hir_id);
|
||||||
let succ = if self.ir.tcx.is_ty_uninhabited_from(m, self.tables.expr_ty(expr)) {
|
let succ = if self.ir.tcx.is_ty_uninhabited_from(
|
||||||
|
m,
|
||||||
|
self.tables.expr_ty(expr),
|
||||||
|
self.param_env,
|
||||||
|
) {
|
||||||
self.s.exit_ln
|
self.s.exit_ln
|
||||||
} else {
|
} else {
|
||||||
succ
|
succ
|
||||||
|
Loading…
Reference in New Issue
Block a user