Skip to content

Commit 736c675

Browse files
committed
Auto merge of #103454 - camsteffen:remove-conservatively-uninhabited, r=oli-obk
Factor out `conservative_is_privately_uninhabited` After #102660 there is no more need for `conservative_is_privately_uninhabited`. r? `@oli-obk`
2 parents ccde51a + cc8dddb commit 736c675

File tree

19 files changed

+99
-163
lines changed

19 files changed

+99
-163
lines changed

compiler/rustc_borrowck/src/type_check/mod.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -1564,10 +1564,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
15641564
}
15651565
}
15661566
None => {
1567-
if !self
1568-
.tcx()
1569-
.conservative_is_privately_uninhabited(self.param_env.and(sig.output()))
1570-
{
1567+
if !sig.output().is_privately_uninhabited(self.tcx(), self.param_env) {
15711568
span_mirbug!(self, term, "call to converging function {:?} w/o dest", sig);
15721569
}
15731570
}

compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ impl<'a, 'tcx> DropRangeVisitor<'a, 'tcx> {
217217
let ty = self.tcx.erase_regions(ty);
218218
let m = self.tcx.parent_module(expr.hir_id).to_def_id();
219219
let param_env = self.tcx.param_env(m.expect_local());
220-
if self.tcx.is_ty_uninhabited_from(m, ty, param_env) {
220+
if !ty.is_inhabited_from(self.tcx, m, param_env) {
221221
// This function will not return. We model this fact as an infinite loop.
222222
self.drop_ranges.add_control_edge(self.expr_index + 1, self.expr_index + 1);
223223
}

compiler/rustc_hir_typeck/src/generator_interior/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -542,10 +542,10 @@ fn check_must_not_suspend_ty<'tcx>(
542542
data: SuspendCheckData<'_, 'tcx>,
543543
) -> bool {
544544
if ty.is_unit()
545-
// FIXME: should this check `is_ty_uninhabited_from`. This query is not available in this stage
545+
// FIXME: should this check `Ty::is_inhabited_from`. This query is not available in this stage
546546
// of typeck (before ReVar and RePlaceholder are removed), but may remove noise, like in
547547
// `must_use`
548-
// || fcx.tcx.is_ty_uninhabited_from(fcx.tcx.parent_module(hir_id).to_def_id(), ty, fcx.param_env)
548+
// || !ty.is_inhabited_from(fcx.tcx, fcx.tcx.parent_module(hir_id).to_def_id(), fcx.param_env)
549549
{
550550
return false;
551551
}

compiler/rustc_lint/src/unused.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -201,9 +201,9 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
201201
plural_len: usize,
202202
) -> bool {
203203
if ty.is_unit()
204-
|| cx.tcx.is_ty_uninhabited_from(
204+
|| !ty.is_inhabited_from(
205+
cx.tcx,
205206
cx.tcx.parent_module(expr.hir_id).to_def_id(),
206-
ty,
207207
cx.param_env,
208208
)
209209
{

compiler/rustc_middle/src/query/mod.rs

-11
Original file line numberDiff line numberDiff line change
@@ -2078,17 +2078,6 @@ rustc_queries! {
20782078
desc { "normalizing opaque types in `{:?}`", key }
20792079
}
20802080

2081-
/// Checks whether a type is definitely uninhabited. This is
2082-
/// conservative: for some types that are uninhabited we return `false`,
2083-
/// but we only return `true` for types that are definitely uninhabited.
2084-
/// `ty.conservative_is_privately_uninhabited` implies that any value of type `ty`
2085-
/// will be `Abi::Uninhabited`. (Note that uninhabited types may have nonzero
2086-
/// size, to account for partial initialisation. See #49298 for details.)
2087-
query conservative_is_privately_uninhabited(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
2088-
desc { "conservatively checking if `{}` is privately uninhabited", key.value }
2089-
remap_env_constness
2090-
}
2091-
20922081
query limits(key: ()) -> Limits {
20932082
desc { "looking up limits" }
20942083
}

compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs

+7
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,13 @@ impl<'tcx> InhabitedPredicate<'tcx> {
4141
self.apply_inner(tcx, param_env, &|_| Err(())).ok()
4242
}
4343

44+
/// Same as `apply`, but `NotInModule(_)` predicates yield `false`. That is,
45+
/// privately uninhabited types are considered always uninhabited.
46+
pub fn apply_ignore_module(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> bool {
47+
let Ok(result) = self.apply_inner::<!>(tcx, param_env, &|_| Ok(true));
48+
result
49+
}
50+
4451
fn apply_inner<E>(
4552
self,
4653
tcx: TyCtxt<'tcx>,

compiler/rustc_middle/src/ty/inhabitedness/mod.rs

+59-52
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
//! }
3030
//! ```
3131
//! In this code, the type `Foo` will only be visibly uninhabited inside the
32-
//! modules `b`, `c` and `d`. Calling `uninhabited_predicate` on `Foo` will
32+
//! modules `b`, `c` and `d`. Calling `inhabited_predicate` on `Foo` will
3333
//! return `NotInModule(b) AND NotInModule(c)`.
3434
//!
3535
//! We need this information for pattern-matching on `Foo` or types that contain
@@ -57,57 +57,6 @@ pub(crate) fn provide(providers: &mut ty::query::Providers) {
5757
ty::query::Providers { inhabited_predicate_adt, inhabited_predicate_type, ..*providers };
5858
}
5959

60-
impl<'tcx> TyCtxt<'tcx> {
61-
/// Checks whether a type is visibly uninhabited from a particular module.
62-
///
63-
/// # Example
64-
/// ```
65-
/// #![feature(never_type)]
66-
/// # fn main() {}
67-
/// enum Void {}
68-
/// mod a {
69-
/// pub mod b {
70-
/// pub struct SecretlyUninhabited {
71-
/// _priv: !,
72-
/// }
73-
/// }
74-
/// }
75-
///
76-
/// mod c {
77-
/// use super::Void;
78-
/// pub struct AlsoSecretlyUninhabited {
79-
/// _priv: Void,
80-
/// }
81-
/// mod d {
82-
/// }
83-
/// }
84-
///
85-
/// struct Foo {
86-
/// x: a::b::SecretlyUninhabited,
87-
/// y: c::AlsoSecretlyUninhabited,
88-
/// }
89-
/// ```
90-
/// In this code, the type `Foo` will only be visibly uninhabited inside the
91-
/// modules b, c and d. This effects pattern-matching on `Foo` or types that
92-
/// contain `Foo`.
93-
///
94-
/// # Example
95-
/// ```ignore (illustrative)
96-
/// let foo_result: Result<T, Foo> = ... ;
97-
/// let Ok(t) = foo_result;
98-
/// ```
99-
/// This code should only compile in modules where the uninhabitedness of Foo is
100-
/// visible.
101-
pub fn is_ty_uninhabited_from(
102-
self,
103-
module: DefId,
104-
ty: Ty<'tcx>,
105-
param_env: ty::ParamEnv<'tcx>,
106-
) -> bool {
107-
!ty.inhabited_predicate(self).apply(self, param_env, module)
108-
}
109-
}
110-
11160
/// Returns an `InhabitedPredicate` that is generic over type parameters and
11261
/// requires calling [`InhabitedPredicate::subst`]
11362
fn inhabited_predicate_adt(tcx: TyCtxt<'_>, def_id: DefId) -> InhabitedPredicate<'_> {
@@ -171,6 +120,64 @@ impl<'tcx> Ty<'tcx> {
171120
_ => InhabitedPredicate::True,
172121
}
173122
}
123+
124+
/// Checks whether a type is visibly uninhabited from a particular module.
125+
///
126+
/// # Example
127+
/// ```
128+
/// #![feature(never_type)]
129+
/// # fn main() {}
130+
/// enum Void {}
131+
/// mod a {
132+
/// pub mod b {
133+
/// pub struct SecretlyUninhabited {
134+
/// _priv: !,
135+
/// }
136+
/// }
137+
/// }
138+
///
139+
/// mod c {
140+
/// use super::Void;
141+
/// pub struct AlsoSecretlyUninhabited {
142+
/// _priv: Void,
143+
/// }
144+
/// mod d {
145+
/// }
146+
/// }
147+
///
148+
/// struct Foo {
149+
/// x: a::b::SecretlyUninhabited,
150+
/// y: c::AlsoSecretlyUninhabited,
151+
/// }
152+
/// ```
153+
/// In this code, the type `Foo` will only be visibly uninhabited inside the
154+
/// modules b, c and d. This effects pattern-matching on `Foo` or types that
155+
/// contain `Foo`.
156+
///
157+
/// # Example
158+
/// ```ignore (illustrative)
159+
/// let foo_result: Result<T, Foo> = ... ;
160+
/// let Ok(t) = foo_result;
161+
/// ```
162+
/// This code should only compile in modules where the uninhabitedness of Foo is
163+
/// visible.
164+
pub fn is_inhabited_from(
165+
self,
166+
tcx: TyCtxt<'tcx>,
167+
module: DefId,
168+
param_env: ty::ParamEnv<'tcx>,
169+
) -> bool {
170+
self.inhabited_predicate(tcx).apply(tcx, param_env, module)
171+
}
172+
173+
/// Returns true if the type is uninhabited without regard to visibility
174+
pub fn is_privately_uninhabited(
175+
self,
176+
tcx: TyCtxt<'tcx>,
177+
param_env: ty::ParamEnv<'tcx>,
178+
) -> bool {
179+
!self.inhabited_predicate(tcx).apply_ignore_module(tcx, param_env)
180+
}
174181
}
175182

176183
/// N.B. this query should only be called through `Ty::inhabited_predicate`

compiler/rustc_mir_build/src/build/expr/into.rs

+4-9
Original file line numberDiff line numberDiff line change
@@ -271,15 +271,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
271271
// MIR checks and ultimately whether code is accepted or not. We can only
272272
// omit the return edge if a return type is visibly uninhabited to a module
273273
// that makes the call.
274-
target: if this.tcx.is_ty_uninhabited_from(
275-
this.parent_module,
276-
expr.ty,
277-
this.param_env,
278-
) {
279-
None
280-
} else {
281-
Some(success)
282-
},
274+
target: expr
275+
.ty
276+
.is_inhabited_from(this.tcx, this.parent_module, this.param_env)
277+
.then_some(success),
283278
from_hir_call,
284279
fn_span,
285280
},

compiler/rustc_mir_build/src/build/matches/simplify.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -264,10 +264,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
264264
let irrefutable = adt_def.variants().iter_enumerated().all(|(i, v)| {
265265
i == variant_index || {
266266
self.tcx.features().exhaustive_patterns
267-
&& v.inhabited_predicate(self.tcx, adt_def)
267+
&& !v
268+
.inhabited_predicate(self.tcx, adt_def)
268269
.subst(self.tcx, substs)
269-
.apply_any_module(self.tcx, self.param_env)
270-
!= Some(true)
270+
.apply_ignore_module(self.tcx, self.param_env)
271271
}
272272
}) && (adt_def.did().is_local()
273273
|| !adt_def.is_variant_list_non_exhaustive());

compiler/rustc_mir_build/src/thir/pattern/check_match.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -818,7 +818,7 @@ fn non_exhaustive_match<'p, 'tcx>(
818818
}
819819
}
820820
if let ty::Ref(_, sub_ty, _) = scrut_ty.kind() {
821-
if cx.tcx.is_ty_uninhabited_from(cx.module, *sub_ty, cx.param_env) {
821+
if !sub_ty.is_inhabited_from(cx.tcx, cx.module, cx.param_env) {
822822
err.note("references are always considered inhabited");
823823
}
824824
}

compiler/rustc_mir_build/src/thir/pattern/usefulness.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ pub(crate) struct MatchCheckCtxt<'p, 'tcx> {
324324
impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
325325
pub(super) fn is_uninhabited(&self, ty: Ty<'tcx>) -> bool {
326326
if self.tcx.features().exhaustive_patterns {
327-
self.tcx.is_ty_uninhabited_from(self.module, ty, self.param_env)
327+
!ty.is_inhabited_from(self.tcx, self.module, self.param_env)
328328
} else {
329329
false
330330
}

compiler/rustc_mir_transform/src/generator.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1015,7 +1015,7 @@ fn insert_panic_block<'tcx>(
10151015

10161016
fn can_return<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool {
10171017
// Returning from a function with an uninhabited return type is undefined behavior.
1018-
if tcx.conservative_is_privately_uninhabited(param_env.and(body.return_ty())) {
1018+
if body.return_ty().is_privately_uninhabited(tcx, param_env) {
10191019
return false;
10201020
}
10211021

compiler/rustc_passes/src/liveness.rs

+12-13
Original file line numberDiff line numberDiff line change
@@ -1284,20 +1284,19 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
12841284
fn check_is_ty_uninhabited(&mut self, expr: &Expr<'_>, succ: LiveNode) -> LiveNode {
12851285
let ty = self.typeck_results.expr_ty(expr);
12861286
let m = self.ir.tcx.parent_module(expr.hir_id).to_def_id();
1287-
if self.ir.tcx.is_ty_uninhabited_from(m, ty, self.param_env) {
1288-
match self.ir.lnks[succ] {
1289-
LiveNodeKind::ExprNode(succ_span, succ_id) => {
1290-
self.warn_about_unreachable(expr.span, ty, succ_span, succ_id, "expression");
1291-
}
1292-
LiveNodeKind::VarDefNode(succ_span, succ_id) => {
1293-
self.warn_about_unreachable(expr.span, ty, succ_span, succ_id, "definition");
1294-
}
1295-
_ => {}
1296-
};
1297-
self.exit_ln
1298-
} else {
1299-
succ
1287+
if ty.is_inhabited_from(self.ir.tcx, m, self.param_env) {
1288+
return succ;
13001289
}
1290+
match self.ir.lnks[succ] {
1291+
LiveNodeKind::ExprNode(succ_span, succ_id) => {
1292+
self.warn_about_unreachable(expr.span, ty, succ_span, succ_id, "expression");
1293+
}
1294+
LiveNodeKind::VarDefNode(succ_span, succ_id) => {
1295+
self.warn_about_unreachable(expr.span, ty, succ_span, succ_id, "definition");
1296+
}
1297+
_ => {}
1298+
};
1299+
self.exit_ln
13011300
}
13021301

13031302
fn warn_about_unreachable(

compiler/rustc_ty_utils/src/layout.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -442,8 +442,7 @@ fn layout_of_uncached<'tcx>(
442442
let element = cx.layout_of(element)?;
443443
let size = element.size.checked_mul(count, dl).ok_or(LayoutError::SizeOverflow(ty))?;
444444

445-
let abi = if count != 0 && tcx.conservative_is_privately_uninhabited(param_env.and(ty))
446-
{
445+
let abi = if count != 0 && ty.is_privately_uninhabited(tcx, param_env) {
447446
Abi::Uninhabited
448447
} else {
449448
Abi::Aggregate { sized: true }

compiler/rustc_ty_utils/src/layout_sanity_check.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ pub(super) fn sanity_check_layout<'tcx>(
1212
layout: &TyAndLayout<'tcx>,
1313
) {
1414
// Type-level uninhabitedness should always imply ABI uninhabitedness.
15-
if cx.tcx.conservative_is_privately_uninhabited(cx.param_env.and(layout.ty)) {
15+
if layout.ty.is_privately_uninhabited(cx.tcx, cx.param_env) {
1616
assert!(layout.abi.is_uninhabited());
1717
}
1818

compiler/rustc_ty_utils/src/ty.rs

-57
Original file line numberDiff line numberDiff line change
@@ -416,62 +416,6 @@ fn asyncness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::IsAsync {
416416
node.fn_sig().map_or(hir::IsAsync::NotAsync, |sig| sig.header.asyncness)
417417
}
418418

419-
/// Don't call this directly: use ``tcx.conservative_is_privately_uninhabited`` instead.
420-
pub fn conservative_is_privately_uninhabited_raw<'tcx>(
421-
tcx: TyCtxt<'tcx>,
422-
param_env_and: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
423-
) -> bool {
424-
let (param_env, ty) = param_env_and.into_parts();
425-
match ty.kind() {
426-
ty::Never => {
427-
debug!("ty::Never =>");
428-
true
429-
}
430-
ty::Adt(def, _) if def.is_union() => {
431-
debug!("ty::Adt(def, _) if def.is_union() =>");
432-
// For now, `union`s are never considered uninhabited.
433-
false
434-
}
435-
ty::Adt(def, substs) => {
436-
debug!("ty::Adt(def, _) if def.is_not_union() =>");
437-
// Any ADT is uninhabited if either:
438-
// (a) It has no variants (i.e. an empty `enum`);
439-
// (b) Each of its variants (a single one in the case of a `struct`) has at least
440-
// one uninhabited field.
441-
def.variants().iter().all(|var| {
442-
var.fields.iter().any(|field| {
443-
let ty = tcx.bound_type_of(field.did).subst(tcx, substs);
444-
tcx.conservative_is_privately_uninhabited(param_env.and(ty))
445-
})
446-
})
447-
}
448-
ty::Tuple(fields) => {
449-
debug!("ty::Tuple(..) =>");
450-
fields.iter().any(|ty| tcx.conservative_is_privately_uninhabited(param_env.and(ty)))
451-
}
452-
ty::Array(ty, len) => {
453-
debug!("ty::Array(ty, len) =>");
454-
match len.try_eval_usize(tcx, param_env) {
455-
Some(0) | None => false,
456-
// If the array is definitely non-empty, it's uninhabited if
457-
// the type of its elements is uninhabited.
458-
Some(1..) => tcx.conservative_is_privately_uninhabited(param_env.and(*ty)),
459-
}
460-
}
461-
ty::Ref(..) => {
462-
debug!("ty::Ref(..) =>");
463-
// References to uninitialised memory is valid for any type, including
464-
// uninhabited types, in unsafe code, so we treat all references as
465-
// inhabited.
466-
false
467-
}
468-
_ => {
469-
debug!("_ =>");
470-
false
471-
}
472-
}
473-
}
474-
475419
pub fn provide(providers: &mut ty::query::Providers) {
476420
*providers = ty::query::Providers {
477421
asyncness,
@@ -481,7 +425,6 @@ pub fn provide(providers: &mut ty::query::Providers) {
481425
instance_def_size_estimate,
482426
issue33140_self_ty,
483427
impl_defaultness,
484-
conservative_is_privately_uninhabited: conservative_is_privately_uninhabited_raw,
485428
..*providers
486429
};
487430
}

0 commit comments

Comments
 (0)