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:
commit
5e720f0e54
6 changed files with 122 additions and 23 deletions
|
|
@ -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)*)
|
||||
});
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)*)
|
||||
});
|
||||
)
|
||||
|
||||
|
|
|
|||
29
src/test/compile-fail/fail-no-dead-code-core.rs
Normal file
29
src/test/compile-fail/fail-no-dead-code-core.rs
Normal 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() {}
|
||||
25
src/test/compile-fail/fail-no-dead-code.rs
Normal file
25
src/test/compile-fail/fail-no-dead-code.rs
Normal 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() {}
|
||||
38
src/test/run-pass/dead-code-leading-underscore.rs
Normal file
38
src/test/run-pass/dead-code-leading-underscore.rs
Normal 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() {}
|
||||
Loading…
Add table
Add a link
Reference in a new issue