Skip to content

Commit 62b3590

Browse files
committed
Check for uninhabitedness instead of never
1 parent 1137d29 commit 62b3590

File tree

7 files changed

+26
-60
lines changed

7 files changed

+26
-60
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
@@ -1197,8 +1197,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
11971197
}
11981198

11991199
hir::ExprKind::Call(ref f, ref args) => {
1200-
// FIXME(canndrew): This is_never should really be an is_uninhabited
1201-
let succ = if self.tables.expr_ty(expr).is_never() {
1200+
let succ = if self.tables.expr_ty(expr).conservative_is_uninhabited() {
12021201
self.s.exit_ln
12031202
} else {
12041203
succ
@@ -1208,8 +1207,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
12081207
}
12091208

12101209
hir::ExprKind::MethodCall(.., ref args) => {
1211-
// FIXME(canndrew): This is_never should really be an is_uninhabited
1212-
let succ = if self.tables.expr_ty(expr).is_never() {
1210+
let succ = if self.tables.expr_ty(expr).conservative_is_uninhabited() {
12131211
self.s.exit_ln
12141212
} else {
12151213
succ

src/librustc/ty/sty.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1543,6 +1543,17 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
15431543
}
15441544
}
15451545

1546+
pub fn conservative_is_uninhabited(&self) -> bool {
1547+
// Checks whether a type is definitely uninhabited. This is
1548+
// conservative: for some types that are uninhabited we return `false`,
1549+
// but we only return `true` for types that are definitely uninhabited.
1550+
match self.sty {
1551+
ty::Never => true,
1552+
ty::Adt(def, _) => def.variants.is_empty(),
1553+
_ => false
1554+
}
1555+
}
1556+
15461557
pub fn is_primitive(&self) -> bool {
15471558
match self.sty {
15481559
Bool | Char | Int(_) | Uint(_) | Float(_) => true,

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1546,8 +1546,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
15461546
}
15471547
}
15481548
None => {
1549-
// FIXME(canndrew): This is_never should probably be an is_uninhabited
1550-
if !sig.output().is_never() {
1549+
if !sig.output().conservative_is_uninhabited() {
15511550
span_mirbug!(self, term, "call to converging function {:?} w/o dest", sig);
15521551
}
15531552
}

src/librustc_mir/build/expr/into.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -275,8 +275,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
275275
exit_block.unit()
276276
}
277277
ExprKind::Call { ty, fun, args, from_hir_call } => {
278-
// FIXME(canndrew): This is_never should probably be an is_uninhabited
279-
let diverges = expr.ty.is_never();
278+
let diverges = expr.ty.conservative_is_uninhabited();
280279
let intrinsic = match ty.sty {
281280
ty::FnDef(def_id, _) => {
282281
let f = ty.fn_sig(this.hir.tcx());
@@ -332,7 +331,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
332331
func: fun,
333332
args,
334333
cleanup: Some(cleanup),
335-
destination: if diverges {
334+
destination: if expr.ty.conservative_is_uninhabited() {
336335
None
337336
} else {
338337
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
@@ -230,7 +230,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
230230
let scrutinee_is_uninhabited = if self.tcx.features().exhaustive_patterns {
231231
self.tcx.is_ty_uninhabited_from(module, pat_ty)
232232
} else {
233-
self.conservative_is_uninhabited(pat_ty)
233+
pat_ty.conservative_is_uninhabited()
234234
};
235235
if !scrutinee_is_uninhabited {
236236
// We know the type is inhabited, so this must be wrong
@@ -258,15 +258,6 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
258258
})
259259
}
260260

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

src/test/debuginfo/nil-enum.rs

Lines changed: 8 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,24 @@
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-
11-
// NOTE Instantiating an empty enum is UB. This test may break in the future.
12-
13-
// LLDB can't handle zero-sized values
1+
// LLDB can't handle zero-sized values.
142
// ignore-lldb
153

16-
17-
// Require LLVM with DW_TAG_variant_part and a gdb that can read it.
18-
// gdb 8.2.0 crashes on this test case, see
19-
// https://sourceware.org/bugzilla/show_bug.cgi?id=23626
20-
// This will be fixed in the next release, which will be >= 8.2.1.
21-
// min-system-llvm-version: 7.0
22-
// min-gdb-version: 8.2.1
23-
244
// compile-flags:-g
255
// gdb-command:run
266

27-
// gdb-command:print first
28-
// gdbr-check:$1 = nil_enum::ANilEnum {<No data fields>}
29-
30-
// gdb-command:print second
31-
// gdbr-check:$2 = nil_enum::AnotherNilEnum {<No data fields>}
7+
// gdb-command:print *first
8+
// gdbg-check:$1 = {<No data fields>}
9+
// gdbr-check:$1 = <error reading variable>
3210

3311
#![allow(unused_variables)]
3412
#![feature(omit_gdb_pretty_printer_section)]
3513
#![feature(maybe_uninit)]
3614
#![omit_gdb_pretty_printer_section]
3715

38-
use std::mem::MaybeUninit;
39-
40-
enum ANilEnum {}
41-
enum AnotherNilEnum {}
16+
enum Void {}
4217

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

51-
zzz(); // #break
52-
}
21+
zzz(); // #break
5322
}
5423

55-
fn zzz() {()}
24+
fn zzz() {}

0 commit comments

Comments
 (0)