Skip to content

Commit e6cbe97

Browse files
committed
Don't use identifier hygiene in HIR
1 parent 06fd246 commit e6cbe97

File tree

3 files changed

+50
-23
lines changed

3 files changed

+50
-23
lines changed

clippy_lints/src/misc.rs

+31-16
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ use rustc_const_math::ConstFloat;
1010
use syntax::codemap::{Span, Spanned, ExpnFormat};
1111
use syntax::ptr::P;
1212
use utils::{
13-
get_item_name, get_parent_expr, implements_trait, is_integer_literal, match_path, snippet,
14-
span_lint, span_lint_and_then, walk_ptrs_ty
13+
get_item_name, get_parent_expr, implements_trait, in_macro, is_integer_literal, match_path,
14+
snippet, span_lint, span_lint_and_then, walk_ptrs_ty
1515
};
1616

1717
/// **What it does:** This lint checks for function arguments and let bindings denoted as `ref`.
@@ -405,15 +405,18 @@ impl LateLintPass for UsedUnderscoreBinding {
405405
}
406406
let binding = match expr.node {
407407
ExprPath(_, ref path) => {
408-
let segment = path.segments
408+
let binding = path.segments
409409
.last()
410410
.expect("path should always have at least one segment")
411-
.name;
412-
if segment.as_str().starts_with('_') &&
413-
!segment.as_str().starts_with("__") &&
414-
segment != segment.unhygienize() && // not in bang macro
415-
is_used(cx, expr) {
416-
Some(segment.as_str())
411+
.name
412+
.as_str();
413+
if binding.starts_with('_') &&
414+
!binding.starts_with("__") &&
415+
binding != "_result" && // FIXME: #944
416+
is_used(cx, expr) &&
417+
// don't lint if the declaration is in a macro
418+
non_macro_local(cx, &cx.tcx.expect_def(expr.id)) {
419+
Some(binding)
417420
} else {
418421
None
419422
}
@@ -429,13 +432,11 @@ impl LateLintPass for UsedUnderscoreBinding {
429432
_ => None,
430433
};
431434
if let Some(binding) = binding {
432-
if binding != "_result" { // FIXME: #944
433-
span_lint(cx,
434-
USED_UNDERSCORE_BINDING,
435-
expr.span,
436-
&format!("used binding `{}` which is prefixed with an underscore. A leading \
437-
underscore signals that a binding will not be used.", binding));
438-
}
435+
span_lint(cx,
436+
USED_UNDERSCORE_BINDING,
437+
expr.span,
438+
&format!("used binding `{}` which is prefixed with an underscore. A leading \
439+
underscore signals that a binding will not be used.", binding));
439440
}
440441
}
441442
}
@@ -463,3 +464,17 @@ fn in_attributes_expansion(cx: &LateContext, expr: &Expr) -> bool {
463464
})
464465
})
465466
}
467+
468+
/// Test whether `def` is a variable defined outside a macro.
469+
fn non_macro_local(cx: &LateContext, def: &def::Def) -> bool {
470+
match *def {
471+
def::Def::Local(_, id) | def::Def::Upvar(_, id, _, _) => {
472+
if let Some(span) = cx.tcx.map.opt_span(id) {
473+
!in_macro(cx, span)
474+
} else {
475+
true
476+
}
477+
}
478+
_ => false,
479+
}
480+
}

clippy_lints/src/shadow.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ fn check_fn(cx: &LateContext, decl: &FnDecl, block: &Block) {
6666
let mut bindings = Vec::new();
6767
for arg in &decl.inputs {
6868
if let PatKind::Binding(_, ident, _) = arg.pat.node {
69-
bindings.push((ident.node.unhygienize(), ident.span))
69+
bindings.push((ident.node, ident.span))
7070
}
7171
}
7272
check_block(cx, block, &mut bindings);
@@ -120,7 +120,7 @@ fn check_pat(cx: &LateContext, pat: &Pat, init: &Option<&Expr>, span: Span, bind
120120
// TODO: match more stuff / destructuring
121121
match pat.node {
122122
PatKind::Binding(_, ref ident, ref inner) => {
123-
let name = ident.node.unhygienize();
123+
let name = ident.node;
124124
if is_binding(cx, pat) {
125125
let mut new_binding = true;
126126
for tup in bindings.iter_mut() {
@@ -139,7 +139,6 @@ fn check_pat(cx: &LateContext, pat: &Pat, init: &Option<&Expr>, span: Span, bind
139139
check_pat(cx, p, init, span, bindings);
140140
}
141141
}
142-
// PatEnum(Path, Option<Vec<P<Pat>>>),
143142
PatKind::Struct(_, ref pfields, _) => {
144143
if let Some(ref init_struct) = *init {
145144
if let ExprStruct(_, ref efields, _) = init_struct.node {
@@ -327,7 +326,7 @@ fn is_self_shadow(name: Name, expr: &Expr) -> bool {
327326
}
328327

329328
fn path_eq_name(name: Name, path: &Path) -> bool {
330-
!path.global && path.segments.len() == 1 && path.segments[0].name.unhygienize() == name
329+
!path.global && path.segments.len() == 1 && path.segments[0].name.as_str() == name.as_str()
331330
}
332331

333332
struct ContainsSelf {
@@ -337,7 +336,7 @@ struct ContainsSelf {
337336

338337
impl<'v> Visitor<'v> for ContainsSelf {
339338
fn visit_name(&mut self, _: Span, name: Name) {
340-
if self.name == name.unhygienize() {
339+
if self.name == name {
341340
self.result = true;
342341
}
343342
}

tests/compile-fail/used_underscore_binding.rs

+15-2
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,27 @@
55
#![allow(blacklisted_name)]
66
#![deny(used_underscore_binding)]
77

8+
macro_rules! test_macro {
9+
() => {{
10+
let _foo = 42;
11+
_foo + 1
12+
}}
13+
}
14+
815
/// Test that we lint if we use a binding with a single leading underscore
916
fn prefix_underscore(_foo: u32) -> u32 {
1017
_foo + 1 //~ ERROR used binding `_foo` which is prefixed with an underscore
1118
}
1219

13-
/// Test that we lint even if the use is within a macro expansion
20+
/// Test that we lint if we use a `_`-variable defined outside within a macro expansion
1421
fn in_macro(_foo: u32) {
15-
println!("{}", _foo); //~ ERROR used binding `_foo` which is prefixed with an underscore
22+
println!("{}", _foo);
23+
//~^ ERROR used binding `_foo` which is prefixed with an underscore
24+
assert_eq!(_foo, _foo);
25+
//~^ ERROR used binding `_foo` which is prefixed with an underscore
26+
//~| ERROR used binding `_foo` which is prefixed with an underscore
27+
28+
test_macro!() + 1;
1629
}
1730

1831
// Struct for testing use of fields prefixed with an underscore

0 commit comments

Comments
 (0)