Change to Ty::is_inhabited_from
This commit is contained in:
parent
a6d96f9fd7
commit
34cbe72780
@ -217,7 +217,7 @@ fn handle_uninhabited_return(&mut self, expr: &Expr<'tcx>) {
|
||||
let ty = self.tcx.erase_regions(ty);
|
||||
let m = self.tcx.parent_module(expr.hir_id).to_def_id();
|
||||
let param_env = self.tcx.param_env(m.expect_local());
|
||||
if self.tcx.is_ty_uninhabited_from(m, ty, param_env) {
|
||||
if !ty.is_inhabited_from(self.tcx, m, param_env) {
|
||||
// This function will not return. We model this fact as an infinite loop.
|
||||
self.drop_ranges.add_control_edge(self.expr_index + 1, self.expr_index + 1);
|
||||
}
|
||||
|
@ -542,10 +542,10 @@ fn check_must_not_suspend_ty<'tcx>(
|
||||
data: SuspendCheckData<'_, 'tcx>,
|
||||
) -> bool {
|
||||
if ty.is_unit()
|
||||
// FIXME: should this check `is_ty_uninhabited_from`. This query is not available in this stage
|
||||
// FIXME: should this check `Ty::is_inhabited_from`. This query is not available in this stage
|
||||
// of typeck (before ReVar and RePlaceholder are removed), but may remove noise, like in
|
||||
// `must_use`
|
||||
// || fcx.tcx.is_ty_uninhabited_from(fcx.tcx.parent_module(hir_id).to_def_id(), ty, fcx.param_env)
|
||||
// || !ty.is_inhabited_from(fcx.tcx, fcx.tcx.parent_module(hir_id).to_def_id(), fcx.param_env)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -201,9 +201,9 @@ fn check_must_use_ty<'tcx>(
|
||||
plural_len: usize,
|
||||
) -> bool {
|
||||
if ty.is_unit()
|
||||
|| cx.tcx.is_ty_uninhabited_from(
|
||||
|| !ty.is_inhabited_from(
|
||||
cx.tcx,
|
||||
cx.tcx.parent_module(expr.hir_id).to_def_id(),
|
||||
ty,
|
||||
cx.param_env,
|
||||
)
|
||||
{
|
||||
|
@ -57,57 +57,6 @@ pub(crate) fn provide(providers: &mut ty::query::Providers) {
|
||||
ty::query::Providers { inhabited_predicate_adt, inhabited_predicate_type, ..*providers };
|
||||
}
|
||||
|
||||
impl<'tcx> TyCtxt<'tcx> {
|
||||
/// Checks whether a type is visibly uninhabited from a particular module.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// #![feature(never_type)]
|
||||
/// # fn main() {}
|
||||
/// enum Void {}
|
||||
/// mod a {
|
||||
/// pub mod b {
|
||||
/// pub struct SecretlyUninhabited {
|
||||
/// _priv: !,
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// mod c {
|
||||
/// use super::Void;
|
||||
/// pub struct AlsoSecretlyUninhabited {
|
||||
/// _priv: Void,
|
||||
/// }
|
||||
/// mod d {
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// struct Foo {
|
||||
/// x: a::b::SecretlyUninhabited,
|
||||
/// y: c::AlsoSecretlyUninhabited,
|
||||
/// }
|
||||
/// ```
|
||||
/// In this code, the type `Foo` will only be visibly uninhabited inside the
|
||||
/// modules b, c and d. This effects pattern-matching on `Foo` or types that
|
||||
/// contain `Foo`.
|
||||
///
|
||||
/// # Example
|
||||
/// ```ignore (illustrative)
|
||||
/// let foo_result: Result<T, Foo> = ... ;
|
||||
/// let Ok(t) = foo_result;
|
||||
/// ```
|
||||
/// 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>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
) -> bool {
|
||||
!ty.inhabited_predicate(self).apply(self, param_env, module)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns an `InhabitedPredicate` that is generic over type parameters and
|
||||
/// requires calling [`InhabitedPredicate::subst`]
|
||||
fn inhabited_predicate_adt(tcx: TyCtxt<'_>, def_id: DefId) -> InhabitedPredicate<'_> {
|
||||
@ -171,6 +120,55 @@ pub fn inhabited_predicate(self, tcx: TyCtxt<'tcx>) -> InhabitedPredicate<'tcx>
|
||||
_ => InhabitedPredicate::True,
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks whether a type is visibly uninhabited from a particular module.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// #![feature(never_type)]
|
||||
/// # fn main() {}
|
||||
/// enum Void {}
|
||||
/// mod a {
|
||||
/// pub mod b {
|
||||
/// pub struct SecretlyUninhabited {
|
||||
/// _priv: !,
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// mod c {
|
||||
/// use super::Void;
|
||||
/// pub struct AlsoSecretlyUninhabited {
|
||||
/// _priv: Void,
|
||||
/// }
|
||||
/// mod d {
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// struct Foo {
|
||||
/// x: a::b::SecretlyUninhabited,
|
||||
/// y: c::AlsoSecretlyUninhabited,
|
||||
/// }
|
||||
/// ```
|
||||
/// In this code, the type `Foo` will only be visibly uninhabited inside the
|
||||
/// modules b, c and d. This effects pattern-matching on `Foo` or types that
|
||||
/// contain `Foo`.
|
||||
///
|
||||
/// # Example
|
||||
/// ```ignore (illustrative)
|
||||
/// let foo_result: Result<T, Foo> = ... ;
|
||||
/// let Ok(t) = foo_result;
|
||||
/// ```
|
||||
/// This code should only compile in modules where the uninhabitedness of Foo is
|
||||
/// visible.
|
||||
pub fn is_inhabited_from(
|
||||
self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
module: DefId,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
) -> bool {
|
||||
self.inhabited_predicate(tcx).apply(tcx, param_env, module)
|
||||
}
|
||||
}
|
||||
|
||||
/// N.B. this query should only be called through `Ty::inhabited_predicate`
|
||||
|
@ -271,15 +271,10 @@ pub(crate) fn expr_into_dest(
|
||||
// MIR checks and ultimately whether code is accepted or not. We can only
|
||||
// omit the return edge if a return type is visibly uninhabited to a module
|
||||
// that makes the call.
|
||||
target: if this.tcx.is_ty_uninhabited_from(
|
||||
this.parent_module,
|
||||
expr.ty,
|
||||
this.param_env,
|
||||
) {
|
||||
None
|
||||
} else {
|
||||
Some(success)
|
||||
},
|
||||
target: expr
|
||||
.ty
|
||||
.is_inhabited_from(this.tcx, this.parent_module, this.param_env)
|
||||
.then_some(success),
|
||||
from_hir_call,
|
||||
fn_span,
|
||||
},
|
||||
|
@ -818,7 +818,7 @@ fn non_exhaustive_match<'p, 'tcx>(
|
||||
}
|
||||
}
|
||||
if let ty::Ref(_, sub_ty, _) = scrut_ty.kind() {
|
||||
if cx.tcx.is_ty_uninhabited_from(cx.module, *sub_ty, cx.param_env) {
|
||||
if !sub_ty.is_inhabited_from(cx.tcx, cx.module, cx.param_env) {
|
||||
err.note("references are always considered inhabited");
|
||||
}
|
||||
}
|
||||
|
@ -324,7 +324,7 @@ pub(crate) struct MatchCheckCtxt<'p, 'tcx> {
|
||||
impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
|
||||
pub(super) fn is_uninhabited(&self, ty: Ty<'tcx>) -> bool {
|
||||
if self.tcx.features().exhaustive_patterns {
|
||||
self.tcx.is_ty_uninhabited_from(self.module, ty, self.param_env)
|
||||
!ty.is_inhabited_from(self.tcx, self.module, self.param_env)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
|
@ -1284,20 +1284,19 @@ fn propagate_through_loop(
|
||||
fn check_is_ty_uninhabited(&mut self, expr: &Expr<'_>, succ: LiveNode) -> LiveNode {
|
||||
let ty = self.typeck_results.expr_ty(expr);
|
||||
let m = self.ir.tcx.parent_module(expr.hir_id).to_def_id();
|
||||
if self.ir.tcx.is_ty_uninhabited_from(m, ty, self.param_env) {
|
||||
match self.ir.lnks[succ] {
|
||||
LiveNodeKind::ExprNode(succ_span, succ_id) => {
|
||||
self.warn_about_unreachable(expr.span, ty, succ_span, succ_id, "expression");
|
||||
}
|
||||
LiveNodeKind::VarDefNode(succ_span, succ_id) => {
|
||||
self.warn_about_unreachable(expr.span, ty, succ_span, succ_id, "definition");
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
self.exit_ln
|
||||
} else {
|
||||
succ
|
||||
if ty.is_inhabited_from(self.ir.tcx, m, self.param_env) {
|
||||
return succ;
|
||||
}
|
||||
match self.ir.lnks[succ] {
|
||||
LiveNodeKind::ExprNode(succ_span, succ_id) => {
|
||||
self.warn_about_unreachable(expr.span, ty, succ_span, succ_id, "expression");
|
||||
}
|
||||
LiveNodeKind::VarDefNode(succ_span, succ_id) => {
|
||||
self.warn_about_unreachable(expr.span, ty, succ_span, succ_id, "definition");
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
self.exit_ln
|
||||
}
|
||||
|
||||
fn warn_about_unreachable(
|
||||
|
@ -2,7 +2,7 @@
|
||||
// aux-build:empty.rs
|
||||
//
|
||||
// This tests plays with matching and uninhabited types. This also serves as a test for the
|
||||
// `tcx.is_ty_uninhabited_from()` function.
|
||||
// `Ty::is_inhabited_from` function.
|
||||
#![feature(never_type)]
|
||||
#![feature(never_type_fallback)]
|
||||
#![feature(exhaustive_patterns)]
|
||||
|
Loading…
Reference in New Issue
Block a user