Merge pull request #1012 from Manishearth/nohyg

Don't use identifier hygiene in HIR
This commit is contained in:
Martin Carton 2016-06-21 21:23:39 +02:00 committed by GitHub
commit 294aeaf4b3
6 changed files with 58 additions and 27 deletions

View file

@ -1,7 +1,11 @@
# Change Log
All notable changes to this project will be documented in this file.
## 0.0.76 — TBD
## 0.0.77 — 2016-06-21
* Rustup to *rustc 1.11.0-nightly (5522e678b 2016-06-20)*
* New lints: [`stutter`] and [`iter_nth`]
## 0.0.76 — 2016-06-10
* Rustup to *rustc 1.11.0-nightly (7d2f75a95 2016-06-09)*
* `cargo clippy` now automatically defines the `clippy` feature

View file

@ -1,6 +1,6 @@
[package]
name = "clippy"
version = "0.0.76"
version = "0.0.77"
authors = [
"Manish Goregaokar <manishsmail@gmail.com>",
"Andre Bogus <bogusandre@gmail.com>",
@ -25,7 +25,7 @@ test = false
[dependencies]
regex_macros = { version = "0.1.33", optional = true }
# begin automatic update
clippy_lints = { version = "0.0.76", path = "clippy_lints" }
clippy_lints = { version = "0.0.77", path = "clippy_lints" }
# end automatic update
[dev-dependencies]

View file

@ -1,7 +1,7 @@
[package]
name = "clippy_lints"
# begin automatic update
version = "0.0.76"
version = "0.0.77"
# end automatic update
authors = [
"Manish Goregaokar <manishsmail@gmail.com>",

View file

@ -10,8 +10,8 @@ use rustc_const_math::ConstFloat;
use syntax::codemap::{Span, Spanned, ExpnFormat};
use syntax::ptr::P;
use utils::{
get_item_name, get_parent_expr, implements_trait, is_integer_literal, match_path, snippet,
span_lint, span_lint_and_then, walk_ptrs_ty
get_item_name, get_parent_expr, implements_trait, in_macro, is_integer_literal, match_path,
snippet, span_lint, span_lint_and_then, walk_ptrs_ty
};
/// **What it does:** This lint checks for function arguments and let bindings denoted as `ref`.
@ -405,15 +405,18 @@ impl LateLintPass for UsedUnderscoreBinding {
}
let binding = match expr.node {
ExprPath(_, ref path) => {
let segment = path.segments
let binding = path.segments
.last()
.expect("path should always have at least one segment")
.name;
if segment.as_str().starts_with('_') &&
!segment.as_str().starts_with("__") &&
segment != segment.unhygienize() && // not in bang macro
is_used(cx, expr) {
Some(segment.as_str())
.name
.as_str();
if binding.starts_with('_') &&
!binding.starts_with("__") &&
binding != "_result" && // FIXME: #944
is_used(cx, expr) &&
// don't lint if the declaration is in a macro
non_macro_local(cx, &cx.tcx.expect_def(expr.id)) {
Some(binding)
} else {
None
}
@ -429,13 +432,11 @@ impl LateLintPass for UsedUnderscoreBinding {
_ => None,
};
if let Some(binding) = binding {
if binding != "_result" { // FIXME: #944
span_lint(cx,
USED_UNDERSCORE_BINDING,
expr.span,
&format!("used binding `{}` which is prefixed with an underscore. A leading \
underscore signals that a binding will not be used.", binding));
}
span_lint(cx,
USED_UNDERSCORE_BINDING,
expr.span,
&format!("used binding `{}` which is prefixed with an underscore. A leading \
underscore signals that a binding will not be used.", binding));
}
}
}
@ -463,3 +464,17 @@ fn in_attributes_expansion(cx: &LateContext, expr: &Expr) -> bool {
})
})
}
/// Test whether `def` is a variable defined outside a macro.
fn non_macro_local(cx: &LateContext, def: &def::Def) -> bool {
match *def {
def::Def::Local(_, id) | def::Def::Upvar(_, id, _, _) => {
if let Some(span) = cx.tcx.map.opt_span(id) {
!in_macro(cx, span)
} else {
true
}
}
_ => false,
}
}

View file

@ -66,7 +66,7 @@ fn check_fn(cx: &LateContext, decl: &FnDecl, block: &Block) {
let mut bindings = Vec::new();
for arg in &decl.inputs {
if let PatKind::Binding(_, ident, _) = arg.pat.node {
bindings.push((ident.node.unhygienize(), ident.span))
bindings.push((ident.node, ident.span))
}
}
check_block(cx, block, &mut bindings);
@ -120,7 +120,7 @@ fn check_pat(cx: &LateContext, pat: &Pat, init: &Option<&Expr>, span: Span, bind
// TODO: match more stuff / destructuring
match pat.node {
PatKind::Binding(_, ref ident, ref inner) => {
let name = ident.node.unhygienize();
let name = ident.node;
if is_binding(cx, pat) {
let mut new_binding = true;
for tup in bindings.iter_mut() {
@ -139,7 +139,6 @@ fn check_pat(cx: &LateContext, pat: &Pat, init: &Option<&Expr>, span: Span, bind
check_pat(cx, p, init, span, bindings);
}
}
// PatEnum(Path, Option<Vec<P<Pat>>>),
PatKind::Struct(_, ref pfields, _) => {
if let Some(ref init_struct) = *init {
if let ExprStruct(_, ref efields, _) = init_struct.node {
@ -327,7 +326,7 @@ fn is_self_shadow(name: Name, expr: &Expr) -> bool {
}
fn path_eq_name(name: Name, path: &Path) -> bool {
!path.global && path.segments.len() == 1 && path.segments[0].name.unhygienize() == name
!path.global && path.segments.len() == 1 && path.segments[0].name.as_str() == name.as_str()
}
struct ContainsSelf {
@ -337,7 +336,7 @@ struct ContainsSelf {
impl<'v> Visitor<'v> for ContainsSelf {
fn visit_name(&mut self, _: Span, name: Name) {
if self.name == name.unhygienize() {
if self.name == name {
self.result = true;
}
}

View file

@ -5,14 +5,27 @@
#![allow(blacklisted_name)]
#![deny(used_underscore_binding)]
macro_rules! test_macro {
() => {{
let _foo = 42;
_foo + 1
}}
}
/// Test that we lint if we use a binding with a single leading underscore
fn prefix_underscore(_foo: u32) -> u32 {
_foo + 1 //~ ERROR used binding `_foo` which is prefixed with an underscore
}
/// Test that we lint even if the use is within a macro expansion
/// Test that we lint if we use a `_`-variable defined outside within a macro expansion
fn in_macro(_foo: u32) {
println!("{}", _foo); //~ ERROR used binding `_foo` which is prefixed with an underscore
println!("{}", _foo);
//~^ ERROR used binding `_foo` which is prefixed with an underscore
assert_eq!(_foo, _foo);
//~^ ERROR used binding `_foo` which is prefixed with an underscore
//~| ERROR used binding `_foo` which is prefixed with an underscore
test_macro!() + 1;
}
// Struct for testing use of fields prefixed with an underscore