From 6461532afa8ec554e1d40d5887a2de60aa658199 Mon Sep 17 00:00:00 2001 From: varkor Date: Thu, 25 Jan 2018 18:03:48 +0000 Subject: [PATCH 1/2] Fix never-type rvalue ICE --- src/librustc_mir/build/block.rs | 8 ++++- src/librustc_mir/build/expr/into.rs | 2 +- src/test/run-pass/never-type-rvalues.rs | 46 +++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 src/test/run-pass/never-type-rvalues.rs diff --git a/src/librustc_mir/build/block.rs b/src/librustc_mir/build/block.rs index b2b615d29a5b8..f8718c36ede98 100644 --- a/src/librustc_mir/build/block.rs +++ b/src/librustc_mir/build/block.rs @@ -143,7 +143,13 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { if let Some(expr) = expr { unpack!(block = this.into(destination, block, expr)); } else { - this.cfg.push_assign_unit(block, source_info, destination); + let tcx = this.hir.tcx(); + let ty = destination.ty(&this.local_decls, tcx).to_ty(tcx); + if ty.is_nil() { + // We only want to assign an implicit `()` as the return value of the block if the + // block does not diverge. (Otherwise, we may try to assign a unit to a `!`-type.) + this.cfg.push_assign_unit(block, source_info, destination); + } } // Finally, we pop all the let scopes before exiting out from the scope of block // itself. diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index 3e0ccc7d07260..68b23d1ae17e8 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -272,7 +272,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { ExprKind::Continue { .. } | ExprKind::Break { .. } | ExprKind::InlineAsm { .. } | - ExprKind::Return {.. } => { + ExprKind::Return { .. } => { unpack!(block = this.stmt_expr(block, expr)); this.cfg.push_assign_unit(block, source_info, destination); block.unit() diff --git a/src/test/run-pass/never-type-rvalues.rs b/src/test/run-pass/never-type-rvalues.rs new file mode 100644 index 0000000000000..9bf003ee1dd3b --- /dev/null +++ b/src/test/run-pass/never-type-rvalues.rs @@ -0,0 +1,46 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(never_type)] +#![allow(dead_code)] +#![allow(path_statements)] +#![allow(unreachable_patterns)] + +fn never_direct(x: !) { + x; +} + +fn never_ref_pat(ref x: !) { + *x; +} + +fn never_ref(x: &!) { + let &y = x; + y; +} + +fn never_pointer(x: *const !) { + unsafe { + *x; + } +} + +fn never_slice(x: &[!]) { + x[0]; +} + +fn never_match(x: Result<(), !>) { + match x { + Ok(_) => {}, + Err(_) => {}, + } +} + +pub fn main() { } From adcb37e275ee9b06114d4debdfe453cbc89b7716 Mon Sep 17 00:00:00 2001 From: varkor Date: Fri, 26 Jan 2018 15:39:19 +0000 Subject: [PATCH 2/2] Add clarifying comment regarding the trailing type of a block --- src/librustc_mir/build/block.rs | 4 ++++ src/test/run-pass/never-type-rvalues.rs | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/librustc_mir/build/block.rs b/src/librustc_mir/build/block.rs index f8718c36ede98..ef30b1e452230 100644 --- a/src/librustc_mir/build/block.rs +++ b/src/librustc_mir/build/block.rs @@ -143,6 +143,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { if let Some(expr) = expr { unpack!(block = this.into(destination, block, expr)); } else { + // If a block has no trailing expression, then it is given an implicit return type. + // This return type is usually `()`, unless the block is diverging, in which case the + // return type is `!`. For the unit type, we need to actually return the unit, but in + // the case of `!`, no return value is required, as the block will never return. let tcx = this.hir.tcx(); let ty = destination.ty(&this.local_decls, tcx).to_ty(tcx); if ty.is_nil() { diff --git a/src/test/run-pass/never-type-rvalues.rs b/src/test/run-pass/never-type-rvalues.rs index 9bf003ee1dd3b..bda288f40869b 100644 --- a/src/test/run-pass/never-type-rvalues.rs +++ b/src/test/run-pass/never-type-rvalues.rs @@ -1,4 +1,4 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. //