From 2eca64de71d1c7ab58a5f8c38d424193f01e5d89 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Mon, 23 Nov 2015 19:25:57 +0530 Subject: [PATCH 1/2] Make unreachable_code lint warn on diverging call arguments as well Fixes #1889 --- src/librustc_typeck/check/mod.rs | 28 +++++++++++++++ src/test/compile-fail/unreachable-in-call.rs | 37 ++++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 src/test/compile-fail/unreachable-in-call.rs diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index a635c1b047d..bac85e4b700 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -2490,6 +2490,8 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, // of arguments when we typecheck the functions. This isn't really the // right way to do this. let xs = [false, true]; + let mut any_diverges = false; // has any of the arguments diverged? + let mut warned = false; // have we already warned about unreachable code? for check_blocks in &xs { let check_blocks = *check_blocks; debug!("check_blocks={}", check_blocks); @@ -2512,6 +2514,16 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, supplied_arg_count }; for (i, arg) in args.iter().take(t).enumerate() { + if any_diverges && !warned { + fcx.ccx + .tcx + .sess + .add_lint(lint::builtin::UNREACHABLE_CODE, + arg.id, + arg.span, + "unreachable expression".to_string()); + warned = true; + } let is_block = match arg.node { hir::ExprClosure(..) => true, _ => false @@ -2542,7 +2554,23 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, coerce_ty.map(|ty| demand::suptype(fcx, arg.span, formal_ty, ty)); }); } + + if let Some(&arg_ty) = fcx.inh.tables.borrow().node_types.get(&arg.id) { + any_diverges = any_diverges || fcx.infcx().type_var_diverges(arg_ty); + } } + if any_diverges && !warned { + let parent = fcx.ccx.tcx.map.get_parent_node(args[0].id); + fcx.ccx + .tcx + .sess + .add_lint(lint::builtin::UNREACHABLE_CODE, + parent, + sp, + "unreachable call".to_string()); + warned = true; + } + } // We also need to make sure we at least write the ty of the other diff --git a/src/test/compile-fail/unreachable-in-call.rs b/src/test/compile-fail/unreachable-in-call.rs new file mode 100644 index 00000000000..61c89e3a4b4 --- /dev/null +++ b/src/test/compile-fail/unreachable-in-call.rs @@ -0,0 +1,37 @@ +// Copyright 2014 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. + +// Test that the unboxed closure sugar can be used with an arbitrary +// struct type and that it is equivalent to the same syntax using +// angle brackets. This test covers only simple types and in +// particular doesn't test bound regions. + +#![allow(dead_code)] +#![deny(unreachable_code)] + +fn diverge() -> ! { panic!() } + +fn get_u8() -> u8 { + 1 +} +fn call(_: u8, _: u8) { + +} +fn diverge_first() { + call(diverge(), + get_u8()); //~ ERROR unreachable expression +} +fn diverge_second() { + call( //~ ERROR unreachable call + get_u8(), + diverge()); +} + +fn main() {} From 7fbcb51589a9d10a2b3ec227611b31b7384b5370 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Tue, 24 Nov 2015 07:23:53 +0530 Subject: [PATCH 2/2] Fix unreachable code in libsyntax --- src/libsyntax/ext/base.rs | 4 ++-- src/libsyntax/ext/tt/macro_rules.rs | 4 ++-- src/test/compile-fail/unreachable-in-call.rs | 5 ----- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 0dba15760cd..08888b3073d 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -678,9 +678,9 @@ impl<'a> ExtCtxt<'a> { pub fn bt_push(&mut self, ei: ExpnInfo) { self.recursion_count += 1; if self.recursion_count > self.ecfg.recursion_limit { - panic!(self.span_fatal(ei.call_site, + self.span_fatal(ei.call_site, &format!("recursion limit reached while expanding the macro `{}`", - ei.callee.name()))); + ei.callee.name())); } let mut call_site = ei.call_site; diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 43647ea4a2e..23d6b794a72 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -209,12 +209,12 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt, best_fail_msg = (*msg).clone(); }, Error(err_sp, ref msg) => { - panic!(cx.span_fatal(err_sp.substitute_dummy(sp), &msg[..])) + cx.span_fatal(err_sp.substitute_dummy(sp), &msg[..]) } } } - panic!(cx.span_fatal(best_fail_spot.substitute_dummy(sp), &best_fail_msg[..])); + cx.span_fatal(best_fail_spot.substitute_dummy(sp), &best_fail_msg[..]); } // Note that macro-by-example's input is also matched against a token tree: diff --git a/src/test/compile-fail/unreachable-in-call.rs b/src/test/compile-fail/unreachable-in-call.rs index 61c89e3a4b4..5a3257d54db 100644 --- a/src/test/compile-fail/unreachable-in-call.rs +++ b/src/test/compile-fail/unreachable-in-call.rs @@ -8,11 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Test that the unboxed closure sugar can be used with an arbitrary -// struct type and that it is equivalent to the same syntax using -// angle brackets. This test covers only simple types and in -// particular doesn't test bound regions. - #![allow(dead_code)] #![deny(unreachable_code)]