auto merge of #16196 : huonw/rust/fail-dead-code, r=alexcrichton

The fail macro defines some function/static items internally, which got
a dead_code warning when `fail!()` is used inside a dead function. This
is ugly and unnecessarily reveals implementation details, so the
warnings can be squashed.

Fixes #16192.
This commit is contained in:
bors 2014-08-11 09:01:06 +00:00
commit 5e720f0e54
6 changed files with 122 additions and 23 deletions

View file

@ -31,12 +31,17 @@ macro_rules! fail(
// because it's just a tiny wrapper. Small wins (156K to 149K in size)
// were seen when forcing this to be inlined, and that number just goes
// up with the number of calls to fail!()
//
// The leading _'s are to avoid dead code warnings if this is
// used inside a dead function. Just `#[allow(dead_code)]` is
// insufficient, since the user may have
// `#[forbid(dead_code)]` and which cannot be overridden.
#[inline(always)]
fn run_fmt(fmt: &::std::fmt::Arguments) -> ! {
static FILE_LINE: (&'static str, uint) = (file!(), line!());
::core::failure::begin_unwind(fmt, &FILE_LINE)
fn _run_fmt(fmt: &::std::fmt::Arguments) -> ! {
static _FILE_LINE: (&'static str, uint) = (file!(), line!());
::core::failure::begin_unwind(fmt, &_FILE_LINE)
}
format_args!(run_fmt, $fmt, $($arg)*)
format_args!(_run_fmt, $fmt, $($arg)*)
});
)

View file

@ -26,7 +26,6 @@ use syntax::ast_util::{local_def, is_local, PostExpansionMethod};
use syntax::attr::AttrMetaMethods;
use syntax::attr;
use syntax::codemap;
use syntax::parse::token;
use syntax::visit::Visitor;
use syntax::visit;
@ -412,10 +411,7 @@ struct DeadVisitor<'a> {
impl<'a> DeadVisitor<'a> {
fn should_warn_about_field(&mut self, node: &ast::StructField_) -> bool {
let (is_named, has_leading_underscore) = match node.ident() {
Some(ref ident) => (true, token::get_ident(*ident).get().as_bytes()[0] == ('_' as u8)),
_ => (false, false)
};
let is_named = node.ident().is_some();
let field_type = ty::node_id_to_type(self.tcx, node.id);
let is_marker_field = match ty::ty_to_def_id(field_type) {
Some(def_id) => self.tcx.lang_items.items().any(|(_, item)| *item == Some(def_id)),
@ -423,7 +419,6 @@ impl<'a> DeadVisitor<'a> {
};
is_named
&& !self.symbol_is_live(node.id, None)
&& !has_leading_underscore
&& !is_marker_field
&& !has_allow_dead_code_or_lang_attr(node.attrs.as_slice())
}
@ -468,13 +463,15 @@ impl<'a> DeadVisitor<'a> {
id: ast::NodeId,
span: codemap::Span,
ident: ast::Ident) {
self.tcx
.sess
.add_lint(lint::builtin::DEAD_CODE,
id,
span,
format!("code is never used: `{}`",
token::get_ident(ident)));
let name = ident.as_str();
if !name.starts_with("_") {
self.tcx
.sess
.add_lint(lint::builtin::DEAD_CODE,
id,
span,
format!("code is never used: `{}`", name));
}
}
}

View file

@ -43,8 +43,8 @@ macro_rules! fail(
});
($msg:expr) => ({
// static requires less code at runtime, more constant data
static FILE_LINE: (&'static str, uint) = (file!(), line!());
::std::rt::begin_unwind($msg, &FILE_LINE)
static _FILE_LINE: (&'static str, uint) = (file!(), line!());
::std::rt::begin_unwind($msg, &_FILE_LINE)
});
($fmt:expr, $($arg:tt)*) => ({
// a closure can't have return type !, so we need a full
@ -58,12 +58,17 @@ macro_rules! fail(
// because it's just a tiny wrapper. Small wins (156K to 149K in size)
// were seen when forcing this to be inlined, and that number just goes
// up with the number of calls to fail!()
//
// The leading _'s are to avoid dead code warnings if this is
// used inside a dead function. Just `#[allow(dead_code)]` is
// insufficient, since the user may have
// `#[forbid(dead_code)]` and which cannot be overridden.
#[inline(always)]
fn run_fmt(fmt: &::std::fmt::Arguments) -> ! {
static FILE_LINE: (&'static str, uint) = (file!(), line!());
::std::rt::begin_unwind_fmt(fmt, &FILE_LINE)
fn _run_fmt(fmt: &::std::fmt::Arguments) -> ! {
static _FILE_LINE: (&'static str, uint) = (file!(), line!());
::std::rt::begin_unwind_fmt(fmt, &_FILE_LINE)
}
format_args!(run_fmt, $fmt, $($arg)*)
format_args!(_run_fmt, $fmt, $($arg)*)
});
)

View file

@ -0,0 +1,29 @@
// 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(phase)]
#![deny(dead_code)]
#![allow(unreachable_code)]
#[phase(link, plugin)] extern crate core;
fn foo() { //~ ERROR code is never used
// none of these should have any dead_code exposed to the user
fail!();
fail!("foo");
fail!("bar {}", "baz")
}
fn main() {}

View file

@ -0,0 +1,25 @@
// 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![deny(dead_code)]
#![allow(unreachable_code)]
fn foo() { //~ ERROR code is never used
// none of these should have any dead_code exposed to the user
fail!();
fail!("foo");
fail!("bar {}", "baz")
}
fn main() {}

View file

@ -0,0 +1,38 @@
// 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![deny(dead_code)]
static _X: uint = 0;
fn _foo() {}
struct _Y {
_z: uint
}
enum _Z {}
impl _Y {
fn _bar() {}
}
type _A = int;
mod _bar {
fn _qux() {}
}
extern {
#[link_name = "abort"]
fn _abort() -> !;
}
pub fn main() {}