From 6461532afa8ec554e1d40d5887a2de60aa658199 Mon Sep 17 00:00:00 2001 From: varkor Date: Thu, 25 Jan 2018 18:03:48 +0000 Subject: [PATCH] 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 b2b615d29a5b..f8718c36ede9 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 3e0ccc7d0726..68b23d1ae17e 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 000000000000..9bf003ee1dd3 --- /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() { }