Skip to content

Commit a885411

Browse files
committed
Check for uninhabitedness instead of never
1 parent e7416d5 commit a885411

File tree

9 files changed

+27
-54
lines changed

9 files changed

+27
-54
lines changed

src/librustc/cfg/construct.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -415,8 +415,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
415415
args: I) -> CFGIndex {
416416
let func_or_rcvr_exit = self.expr(func_or_rcvr, pred);
417417
let ret = self.straightline(call_expr, func_or_rcvr_exit, args);
418-
// FIXME(canndrew): This is_never should probably be an is_uninhabited.
419-
if self.tables.expr_ty(call_expr).is_never() {
418+
if self.tables.expr_ty(call_expr).conservative_is_uninhabited() {
420419
self.add_unreachable_node()
421420
} else {
422421
ret

src/librustc/middle/liveness.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1209,8 +1209,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
12091209
}
12101210

12111211
hir::ExprKind::Call(ref f, ref args) => {
1212-
// FIXME(canndrew): This is_never should really be an is_uninhabited
1213-
let succ = if self.tables.expr_ty(expr).is_never() {
1212+
let succ = if self.tables.expr_ty(expr).conservative_is_uninhabited() {
12141213
self.s.exit_ln
12151214
} else {
12161215
succ
@@ -1220,8 +1219,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
12201219
}
12211220

12221221
hir::ExprKind::MethodCall(.., ref args) => {
1223-
// FIXME(canndrew): This is_never should really be an is_uninhabited
1224-
let succ = if self.tables.expr_ty(expr).is_never() {
1222+
let succ = if self.tables.expr_ty(expr).conservative_is_uninhabited() {
12251223
self.s.exit_ln
12261224
} else {
12271225
succ

src/librustc/ty/sty.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1489,6 +1489,17 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
14891489
}
14901490
}
14911491

1492+
pub fn conservative_is_uninhabited(&self) -> bool {
1493+
// Checks whether a type is definitely uninhabited. This is
1494+
// conservative: for some types that are uninhabited we return `false`,
1495+
// but we only return `true` for types that are definitely uninhabited.
1496+
match self.sty {
1497+
ty::Never => true,
1498+
ty::Adt(def, _) => def.variants.is_empty(),
1499+
_ => false
1500+
}
1501+
}
1502+
14921503
pub fn is_primitive(&self) -> bool {
14931504
match self.sty {
14941505
Bool | Char | Int(_) | Uint(_) | Float(_) => true,

src/librustc_codegen_llvm/debuginfo/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,8 @@ pub fn create_function_debug_context(
279279
}
280280
None => {}
281281
};
282+
283+
// Tell LLVM that functions that return uninhabited types will not return.
282284
if cx.layout_of(sig.output()).abi.is_uninhabited() {
283285
flags = flags | DIFlags::FlagNoReturn;
284286
}

src/librustc_codegen_llvm/mir/block.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,7 @@ impl FunctionCx<'a, 'll, 'tcx> {
457457
// we can do what we like. Here, we declare that transmuting
458458
// into an uninhabited type is impossible, so anything following
459459
// it must be unreachable.
460-
assert_eq!(bx.cx.layout_of(sig.output()).abi, layout::Abi::Uninhabited);
460+
assert!(sig.output().conservative_is_uninhabited());
461461
bx.unreachable();
462462
}
463463
return;

src/librustc_mir/borrow_check/nll/type_check/mod.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1259,8 +1259,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
12591259
}
12601260
}
12611261
None => {
1262-
// FIXME(canndrew): This is_never should probably be an is_uninhabited
1263-
if !sig.output().is_never() {
1262+
if !sig.output().conservative_is_uninhabited() {
12641263
span_mirbug!(self, term, "call to converging function {:?} w/o dest", sig);
12651264
}
12661265
}

src/librustc_mir/build/expr/into.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -265,8 +265,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
265265
exit_block.unit()
266266
}
267267
ExprKind::Call { ty, fun, args } => {
268-
// FIXME(canndrew): This is_never should probably be an is_uninhabited
269-
let diverges = expr.ty.is_never();
270268
let intrinsic = match ty.sty {
271269
ty::FnDef(def_id, _) => {
272270
let f = ty.fn_sig(this.hir.tcx());
@@ -321,7 +319,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
321319
func: fun,
322320
args,
323321
cleanup: Some(cleanup),
324-
destination: if diverges {
322+
destination: if expr.ty.conservative_is_uninhabited() {
325323
None
326324
} else {
327325
Some((destination.clone(), success))

src/librustc_mir/hair/pattern/check_match.rs

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
229229
let scrutinee_is_uninhabited = if self.tcx.features().exhaustive_patterns {
230230
self.tcx.is_ty_uninhabited_from(module, pat_ty)
231231
} else {
232-
self.conservative_is_uninhabited(pat_ty)
232+
pat_ty.conservative_is_uninhabited()
233233
};
234234
if !scrutinee_is_uninhabited {
235235
// We know the type is inhabited, so this must be wrong
@@ -257,15 +257,6 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
257257
})
258258
}
259259

260-
fn conservative_is_uninhabited(&self, scrutinee_ty: Ty<'tcx>) -> bool {
261-
// "rustc-1.0-style" uncontentious uninhabitableness check
262-
match scrutinee_ty.sty {
263-
ty::Never => true,
264-
ty::Adt(def, _) => def.variants.is_empty(),
265-
_ => false
266-
}
267-
}
268-
269260
fn check_irrefutable(&self, pat: &'tcx Pat, origin: &str) {
270261
let module = self.tcx.hir.get_module_parent(pat.id);
271262
MatchCheckCtxt::create_and_enter(self.tcx, module, |ref mut cx| {

src/test/debuginfo/nil-enum.rs

Lines changed: 7 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,25 @@
1-
// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
2-
// file at the top-level directory of this distribution and at
3-
// http://rust-lang.org/COPYRIGHT.
4-
//
5-
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6-
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7-
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8-
// option. This file may not be copied, modified, or distributed
9-
// except according to those terms.
10-
111
// NOTE Instantiating an empty enum is UB. This test may break in the future.
12-
13-
// LLDB can't handle zero-sized values
2+
//
3+
// LLDB can't handle zero-sized values.
144
// ignore-lldb
155

16-
176
// compile-flags:-g
187
// gdb-command:run
198

20-
// gdb-command:print first
9+
// gdb-command:print *first
2110
// gdbg-check:$1 = {<No data fields>}
2211
// gdbr-check:$1 = <error reading variable>
2312

24-
// gdb-command:print second
25-
// gdbg-check:$2 = {<No data fields>}
26-
// gdbr-check:$2 = <error reading variable>
27-
2813
#![allow(unused_variables)]
2914
#![feature(omit_gdb_pretty_printer_section)]
30-
#![feature(maybe_uninit)]
3115
#![omit_gdb_pretty_printer_section]
3216

33-
use std::mem::MaybeUninit;
34-
35-
enum ANilEnum {}
36-
enum AnotherNilEnum {}
17+
enum Void {}
3718

38-
// This test relies on gdbg printing the string "{<No data fields>}" for empty
39-
// structs (which may change some time)
40-
// The error from gdbr is expected since nil enums are not supposed to exist.
4119
fn main() {
42-
unsafe {
43-
let first: ANilEnum = MaybeUninit::uninitialized().into_inner();
44-
let second: AnotherNilEnum = MaybeUninit::uninitialized().into_inner();
20+
let first: *const Void = 1 as *const _;
4521

46-
zzz(); // #break
47-
}
22+
zzz(); // #break
4823
}
4924

50-
fn zzz() {()}
25+
fn zzz() {}

0 commit comments

Comments
 (0)