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
|
||||
/// 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
|
||||
// given node), you could check whether the 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 {
|
||||
!ty.uninhabited_from(self).is_empty()
|
||||
pub fn is_ty_uninhabited_from_any_module(
|
||||
self,
|
||||
ty: Ty<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
) -> bool {
|
||||
!ty.uninhabited_from(self, param_env).is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> AdtDef {
|
||||
/// 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.
|
||||
if self.is_variant_list_non_exhaustive() && !self.did.is_local() {
|
||||
DefIdForest::empty()
|
||||
} else {
|
||||
DefIdForest::intersection(
|
||||
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>,
|
||||
substs: SubstsRef<'tcx>,
|
||||
adt_kind: AdtKind,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
) -> DefIdForest {
|
||||
let is_enum = match adt_kind {
|
||||
// For now, `union`s are never considered uninhabited.
|
||||
@ -140,7 +157,7 @@ impl<'tcx> VariantDef {
|
||||
} else {
|
||||
DefIdForest::union(
|
||||
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>,
|
||||
substs: SubstsRef<'tcx>,
|
||||
is_enum: bool,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
) -> 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
|
||||
// `Visibility::Invisible` so we need to override `self.vis` if we're
|
||||
// dealing with an enum.
|
||||
@ -176,20 +194,21 @@ impl<'tcx> FieldDef {
|
||||
|
||||
impl<'tcx> TyS<'tcx> {
|
||||
/// 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 {
|
||||
Adt(def, substs) => def.uninhabited_from(tcx, substs),
|
||||
Adt(def, substs) => def.uninhabited_from(tcx, substs, param_env),
|
||||
|
||||
Never => DefIdForest::full(tcx),
|
||||
|
||||
Tuple(ref tys) => {
|
||||
DefIdForest::union(tcx, tys.iter().map(|ty| ty.expect_ty().uninhabited_from(tcx)))
|
||||
}
|
||||
Tuple(ref tys) => DefIdForest::union(
|
||||
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
|
||||
// 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(),
|
||||
},
|
||||
|
||||
|
@ -124,7 +124,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults {
|
||||
descr_post: &str,
|
||||
plural_len: usize,
|
||||
) -> 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;
|
||||
}
|
||||
|
@ -209,7 +209,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
i == variant_index || {
|
||||
self.hir.tcx().features().exhaustive_patterns
|
||||
&& !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()
|
||||
}
|
||||
}) && (adt_def.did.is_local()
|
||||
|
@ -598,7 +598,7 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
|
||||
|
||||
fn is_uninhabited(&self, ty: Ty<'tcx>) -> bool {
|
||||
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 {
|
||||
false
|
||||
}
|
||||
@ -1267,7 +1267,7 @@ fn all_constructors<'a, 'tcx>(
|
||||
def.variants
|
||||
.iter()
|
||||
.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)
|
||||
})
|
||||
.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);
|
||||
|
||||
// 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);
|
||||
|
||||
// check for various error conditions
|
||||
@ -658,6 +658,7 @@ const ACC_USE: u32 = 4;
|
||||
struct Liveness<'a, 'tcx> {
|
||||
ir: &'a mut IrMaps<'tcx>,
|
||||
tables: &'a ty::TypeckTables<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
s: Specials,
|
||||
successors: Vec<LiveNode>,
|
||||
rwu_table: RWUTable,
|
||||
@ -670,7 +671,7 @@ struct 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:
|
||||
// - exit_ln represents the end of the fn, either by return or panic
|
||||
// - 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),
|
||||
};
|
||||
|
||||
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_vars = ir.num_vars;
|
||||
@ -689,6 +691,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
||||
Liveness {
|
||||
ir,
|
||||
tables,
|
||||
param_env,
|
||||
s: specials,
|
||||
successors: vec![invalid_node(); num_live_nodes],
|
||||
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) => {
|
||||
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
|
||||
} else {
|
||||
succ
|
||||
@ -1137,7 +1144,11 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
||||
|
||||
hir::ExprKind::MethodCall(.., ref args) => {
|
||||
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
|
||||
} else {
|
||||
succ
|
||||
|
Loading…
Reference in New Issue
Block a user