Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fiddle ParamEnv through to a place that used to use ParamEnv::empty in a buggy manner #70049

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 34 additions & 15 deletions src/librustc/ty/inhabitedness/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)),
)
}
}
Expand All @@ -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.
Expand All @@ -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)),
)
}
}
Expand All @@ -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.
Expand All @@ -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(),
},

Expand Down
7 changes: 6 additions & 1 deletion src/librustc_lint/unused.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
7 changes: 6 additions & 1 deletion src/librustc_mir_build/build/matches/simplify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_mir_build/hair/pattern/_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down Expand Up @@ -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))
Expand Down
21 changes: 16 additions & 5 deletions src/librustc_passes/liveness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand All @@ -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
Expand All @@ -681,14 +682,16 @@ 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;

Liveness {
ir,
tables,
param_env,
s: specials,
successors: vec![invalid_node(); num_live_nodes],
rwu_table: RWUTable::new(num_live_nodes * num_vars),
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down