Skip to content

Rustup to *rustc 1.10.0-nightly (764ef92ae 2016-05-19)* and bump to 0.0.69 #944

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
May 23, 2016
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# Change Log
All notable changes to this project will be documented in this file.

## 0.0.69 — 2016-05-20
* Rustup to *rustc 1.10.0-nightly (476fe6eef 2016-05-21)*
* `used_underscore_binding` has been made `Allow` temporarily

## 0.0.68 — 2016-05-17
* Rustup to *rustc 1.10.0-nightly (cd6a40017 2016-05-16)*
* New lint: [`unnecessary_operation`]
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "clippy"
version = "0.0.68"
version = "0.0.69"
authors = [
"Manish Goregaokar <[email protected]>",
"Andre Bogus <[email protected]>",
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -161,7 +161,7 @@ name
[unused_label](https://github.com/Manishearth/rust-clippy/wiki#unused_label) | warn | unused label
[unused_lifetimes](https://github.com/Manishearth/rust-clippy/wiki#unused_lifetimes) | warn | unused lifetimes in function definitions
[use_debug](https://github.com/Manishearth/rust-clippy/wiki#use_debug) | allow | use `Debug`-based formatting
[used_underscore_binding](https://github.com/Manishearth/rust-clippy/wiki#used_underscore_binding) | warn | using a binding which is prefixed with an underscore
[used_underscore_binding](https://github.com/Manishearth/rust-clippy/wiki#used_underscore_binding) | allow | using a binding which is prefixed with an underscore
[useless_format](https://github.com/Manishearth/rust-clippy/wiki#useless_format) | warn | useless use of `format!`
[useless_transmute](https://github.com/Manishearth/rust-clippy/wiki#useless_transmute) | warn | transmutes that have the same to and from types
[useless_vec](https://github.com/Manishearth/rust-clippy/wiki#useless_vec) | warn | useless `vec!`
4 changes: 2 additions & 2 deletions src/blacklisted_name.rs
Original file line number Diff line number Diff line change
@@ -35,11 +35,11 @@ impl LintPass for BlackListedName {
impl LateLintPass for BlackListedName {
fn check_pat(&mut self, cx: &LateContext, pat: &Pat) {
if let PatKind::Ident(_, ref ident, _) = pat.node {
if self.blacklist.iter().any(|s| s == &*ident.node.name.as_str()) {
if self.blacklist.iter().any(|s| s == &*ident.node.as_str()) {
span_lint(cx,
BLACKLISTED_NAME,
pat.span,
&format!("use of a blacklisted/placeholder name `{}`", ident.node.name));
&format!("use of a blacklisted/placeholder name `{}`", ident.node));
}
}
}
2 changes: 1 addition & 1 deletion src/copies.rs
Original file line number Diff line number Diff line change
@@ -193,7 +193,7 @@ fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat) -> HashMap<Interned
}
}
PatKind::Ident(_, ref ident, ref as_pat) => {
if let Entry::Vacant(v) = map.entry(ident.node.name.as_str()) {
if let Entry::Vacant(v) = map.entry(ident.node.as_str()) {
v.insert(cx.tcx.pat_ty(pat));
}
if let Some(ref as_pat) = *as_pat {
2 changes: 1 addition & 1 deletion src/eta_reduction.rs
Original file line number Diff line number Diff line change
@@ -77,7 +77,7 @@ fn check_closure(cx: &LateContext, expr: &Expr) {
// If it's a proper path, it can't be a local variable
return;
}
if p.segments[0].identifier != ident.node {
if p.segments[0].name != ident.node {
// The two idents should be the same
return;
}
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
@@ -411,6 +411,7 @@ pub fn plugin_registrar(reg: &mut Registry) {
methods::OPTION_UNWRAP_USED,
methods::RESULT_UNWRAP_USED,
methods::WRONG_PUB_SELF_CONVENTION,
misc::USED_UNDERSCORE_BINDING,
mut_mut::MUT_MUT,
mutex_atomic::MUTEX_INTEGER,
non_expressive_names::SIMILAR_NAMES,
@@ -505,7 +506,6 @@ pub fn plugin_registrar(reg: &mut Registry) {
misc::MODULO_ONE,
misc::REDUNDANT_PATTERN,
misc::TOPLEVEL_REF_ARG,
misc::USED_UNDERSCORE_BINDING,
misc_early::DUPLICATE_UNDERSCORE_ARGUMENT,
misc_early::REDUNDANT_CLOSURE_CALL,
misc_early::UNNEEDED_FIELD_PATTERN,
26 changes: 13 additions & 13 deletions src/loops.rs
Original file line number Diff line number Diff line change
@@ -286,7 +286,7 @@ impl LateLintPass for LoopsPass {
if let Some(lhs_constructor) = path.segments.last() {
if method_name.node.as_str() == "next" &&
match_trait_method(cx, match_expr, &paths::ITERATOR) &&
lhs_constructor.identifier.name.as_str() == "Some" &&
lhs_constructor.name.as_str() == "Some" &&
!is_iterator_used_after_while_let(cx, iter_expr) {
let iterator = snippet(cx, method_args[0].span, "_");
let loop_var = snippet(cx, pat_args[0].span, "_");
@@ -333,7 +333,7 @@ fn check_for_loop_range(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, ex
if let PatKind::Ident(_, ref ident, _) = pat.node {
let mut visitor = VarVisitor {
cx: cx,
var: ident.node.name,
var: ident.node,
indexed: HashMap::new(),
nonindex: false,
};
@@ -378,9 +378,9 @@ fn check_for_loop_range(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, ex
expr.span,
&format!("the loop variable `{}` is used to index `{}`. Consider using `for ({}, \
item) in {}.iter().enumerate(){}{}` or similar iterators",
ident.node.name,
ident.node,
indexed,
ident.node.name,
ident.node,
indexed,
take,
skip));
@@ -396,7 +396,7 @@ fn check_for_loop_range(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, ex
expr.span,
&format!("the loop variable `{}` is only used to index `{}`. \
Consider using `for item in {}` or similar iterators",
ident.node.name,
ident.node,
indexed,
repl));
}
@@ -412,7 +412,7 @@ fn is_len_call(expr: &Expr, var: &Name) -> bool {
method.node.as_str() == "len",
let ExprPath(_, ref path) = len_args[0].node,
path.segments.len() == 1,
&path.segments[0].identifier.name == var
&path.segments[0].name == var
], {
return true;
}}
@@ -613,7 +613,7 @@ fn check_for_loop_over_map_kv(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Ex
fn pat_is_wild(pat: &PatKind, body: &Expr) -> bool {
match *pat {
PatKind::Wild => true,
PatKind::Ident(_, ident, None) if ident.node.name.as_str().starts_with('_') => {
PatKind::Ident(_, ident, None) if ident.node.as_str().starts_with('_') => {
let mut visitor = UsedVisitor {
var: ident.node,
used: false,
@@ -626,14 +626,14 @@ fn pat_is_wild(pat: &PatKind, body: &Expr) -> bool {
}

struct UsedVisitor {
var: Ident, // var to look for
var: ast::Name, // var to look for
used: bool, // has the var been used otherwise?
}

impl<'a> Visitor<'a> for UsedVisitor {
fn visit_expr(&mut self, expr: &Expr) {
if let ExprPath(None, ref path) = expr.node {
if path.segments.len() == 1 && path.segments[0].identifier == self.var {
if path.segments.len() == 1 && path.segments[0].name == self.var {
self.used = true;
return;
}
@@ -653,7 +653,7 @@ struct VarVisitor<'v, 't: 'v> {
impl<'v, 't> Visitor<'v> for VarVisitor<'v, 't> {
fn visit_expr(&mut self, expr: &'v Expr) {
if let ExprPath(None, ref path) = expr.node {
if path.segments.len() == 1 && path.segments[0].identifier.name == self.var {
if path.segments.len() == 1 && path.segments[0].name == self.var {
// we are referencing our variable! now check if it's as an index
if_let_chain! {
[
@@ -667,11 +667,11 @@ impl<'v, 't> Visitor<'v> for VarVisitor<'v, 't> {
match def.base_def {
Def::Local(..) | Def::Upvar(..) => {
let extent = self.cx.tcx.region_maps.var_scope(def.base_def.var_id());
self.indexed.insert(seqvar.segments[0].identifier.name, Some(extent));
self.indexed.insert(seqvar.segments[0].name, Some(extent));
return; // no need to walk further
}
Def::Static(..) | Def::Const(..) => {
self.indexed.insert(seqvar.segments[0].identifier.name, None);
self.indexed.insert(seqvar.segments[0].name, None);
return; // no need to walk further
}
_ => (),
@@ -885,7 +885,7 @@ impl<'v, 't> Visitor<'v> for InitializeVisitor<'v, 't> {
if let DeclLocal(ref local) = decl.node {
if local.pat.id == self.var_id {
if let PatKind::Ident(_, ref ident, _) = local.pat.node {
self.name = Some(ident.node.name);
self.name = Some(ident.node);

self.state = if let Some(ref init) = local.init {
if is_integer_literal(init, 0) {
15 changes: 8 additions & 7 deletions src/map_clone.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use rustc::lint::*;
use rustc::hir::*;
use syntax::ast;
use utils::{is_adjusted, match_path, match_trait_method, match_type, paths, snippet,
span_help_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth};

@@ -52,7 +53,7 @@ impl LateLintPass for MapClonePass {
if clone_call.node.as_str() == "clone" &&
clone_args.len() == 1 &&
match_trait_method(cx, closure_expr, &paths::CLONE_TRAIT) &&
expr_eq_ident(&clone_args[0], arg_ident)
expr_eq_name(&clone_args[0], arg_ident)
{
span_help_and_lint(cx, MAP_CLONE, expr.span, &format!(
"you seem to be using .map() to clone the contents of an {}, consider \
@@ -82,11 +83,11 @@ impl LateLintPass for MapClonePass {
}
}

fn expr_eq_ident(expr: &Expr, id: Ident) -> bool {
fn expr_eq_name(expr: &Expr, id: ast::Name) -> bool {
match expr.node {
ExprPath(None, ref path) => {
let arg_segment = [PathSegment {
identifier: id,
name: id,
parameters: PathParameters::none(),
}];
!path.global && path.segments[..] == arg_segment
@@ -105,18 +106,18 @@ fn get_type_name(cx: &LateContext, expr: &Expr, arg: &Expr) -> Option<&'static s
}
}

fn get_arg_name(pat: &Pat) -> Option<Ident> {
fn get_arg_name(pat: &Pat) -> Option<ast::Name> {
match pat.node {
PatKind::Ident(_, ident, None) => Some(ident.node),
PatKind::Ident(_, name, None) => Some(name.node),
PatKind::Ref(ref subpat, _) => get_arg_name(subpat),
_ => None,
}
}

fn only_derefs(cx: &LateContext, expr: &Expr, id: Ident) -> bool {
fn only_derefs(cx: &LateContext, expr: &Expr, id: ast::Name) -> bool {
match expr.node {
ExprUnary(UnDeref, ref subexpr) if !is_adjusted(cx, subexpr) => only_derefs(cx, subexpr, id),
_ => expr_eq_ident(expr, id),
_ => expr_eq_name(expr, id),
}
}

5 changes: 2 additions & 3 deletions src/methods.rs
Original file line number Diff line number Diff line change
@@ -473,7 +473,6 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, name: &str, args: &[P<hi
let path: &str = &path.segments
.last()
.expect("A path must have at least one segment")
.identifier
.name
.as_str();

@@ -512,7 +511,7 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, name: &str, args: &[P<hi
return;
}
}
// (path, fn_has_argument, methods)
// (path, fn_has_argument, methods, suffix)
let know_types: &[(&[_], _, &[_], _)] = &[(&paths::BTREEMAP_ENTRY, false, &["or_insert"], "with"),
(&paths::HASHMAP_ENTRY, false, &["or_insert"], "with"),
(&paths::OPTION,
@@ -811,7 +810,7 @@ fn lint_chars_next(cx: &LateContext, expr: &hir::Expr, chain: &hir::Expr, other:
let hir::ExprCall(ref fun, ref arg_char) = other.node,
arg_char.len() == 1,
let hir::ExprPath(None, ref path) = fun.node,
path.segments.len() == 1 && path.segments[0].identifier.name.as_str() == "Some"
path.segments.len() == 1 && path.segments[0].name.as_str() == "Some"
], {
let self_ty = walk_ptrs_ty(cx.tcx.expr_ty_adjusted(&args[0][0]));

63 changes: 38 additions & 25 deletions src/misc.rs
Original file line number Diff line number Diff line change
@@ -8,8 +8,10 @@ use rustc_const_eval::EvalHint::ExprTypeChecked;
use rustc_const_eval::eval_const_expr_partial;
use syntax::codemap::{Span, Spanned, ExpnFormat};
use syntax::ptr::P;
use utils::{get_item_name, match_path, snippet, get_parent_expr, span_lint};
use utils::{span_lint_and_then, walk_ptrs_ty, is_integer_literal, implements_trait};
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
};

/// **What it does:** This lint checks for function arguments and let bindings denoted as `ref`.
///
@@ -118,7 +120,7 @@ impl LateLintPass for CmpNan {

fn check_nan(cx: &LateContext, path: &Path, span: Span) {
path.segments.last().map(|seg| {
if seg.identifier.name.as_str() == "NAN" {
if seg.name.as_str() == "NAN" {
span_lint(cx,
CMP_NAN,
span,
@@ -350,8 +352,8 @@ impl LateLintPass for PatternPass {
REDUNDANT_PATTERN,
pat.span,
&format!("the `{} @ _` pattern can be written as just `{}`",
ident.node.name,
ident.node.name));
ident.node,
ident.node));
}
}
}
@@ -363,15 +365,16 @@ impl LateLintPass for PatternPass {
/// **Why is this bad?** A single leading underscore is usually used to indicate that a binding
/// will not be used. Using such a binding breaks this expectation.
///
/// **Known problems:** None
/// **Known problems:** The lint does not work properly with desugaring and macro, it has been
/// allowed in the mean time.
///
/// **Example**:
/// ```
/// let _x = 0;
/// let y = _x + 1; // Here we are using `_x`, even though it has a leading underscore.
/// // We should rename `_x` to `x`
/// ```
declare_lint!(pub USED_UNDERSCORE_BINDING, Warn,
declare_lint!(pub USED_UNDERSCORE_BINDING, Allow,
"using a binding which is prefixed with an underscore");

#[derive(Copy, Clone)]
@@ -387,32 +390,42 @@ impl LateLintPass for UsedUnderscoreBinding {
#[cfg_attr(rustfmt, rustfmt_skip)]
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
if in_attributes_expansion(cx, expr) {
// Don't lint things expanded by #[derive(...)], etc
// Don't lint things expanded by #[derive(...)], etc
return;
}
let needs_lint = match expr.node {
let binding = match expr.node {
ExprPath(_, ref path) => {
let ident = path.segments
let segment = path.segments
.last()
.expect("path should always have at least one segment")
.identifier;
ident.name.as_str().starts_with('_') &&
!ident.name.as_str().starts_with("__") &&
ident.name != ident.unhygienic_name &&
is_used(cx, expr) // not in bang macro
.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())
} else {
None
}
}
ExprField(_, spanned) => {
let name = spanned.node.as_str();
name.starts_with('_') && !name.starts_with("__")
if name.starts_with('_') && !name.starts_with("__") {
Some(name)
} else {
None
}
}
_ => false,
_ => None,
};
if needs_lint {
span_lint(cx,
USED_UNDERSCORE_BINDING,
expr.span,
"used binding which is prefixed with an underscore. A leading underscore signals that a \
binding will not be used.");
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));
}
}
}
}
@@ -431,8 +444,8 @@ fn is_used(cx: &LateContext, expr: &Expr) -> bool {
}
}

/// Test whether an expression is in a macro expansion (e.g. something generated by #[derive(...)]
/// or the like)
/// Test whether an expression is in a macro expansion (e.g. something generated by
/// `#[derive(...)`] or the like).
fn in_attributes_expansion(cx: &LateContext, expr: &Expr) -> bool {
cx.sess().codemap().with_expn_info(expr.span.expn_id, |info_opt| {
info_opt.map_or(false, |info| {
4 changes: 2 additions & 2 deletions src/overflow_check_conditional.rs
Original file line number Diff line number Diff line change
@@ -31,7 +31,7 @@ impl LateLintPass for OverflowCheckConditional {
let Expr_::ExprPath(_,ref path1) = ident1.node,
let Expr_::ExprPath(_, ref path2) = ident2.node,
let Expr_::ExprPath(_, ref path3) = second.node,
(&path1.segments[0]).identifier == (&path3.segments[0]).identifier || (&path2.segments[0]).identifier == (&path3.segments[0]).identifier,
&path1.segments[0] == &path3.segments[0] || &path2.segments[0] == &path3.segments[0],
cx.tcx.expr_ty(ident1).is_integral(),
cx.tcx.expr_ty(ident2).is_integral()
], {
@@ -53,7 +53,7 @@ impl LateLintPass for OverflowCheckConditional {
let Expr_::ExprPath(_,ref path1) = ident1.node,
let Expr_::ExprPath(_, ref path2) = ident2.node,
let Expr_::ExprPath(_, ref path3) = first.node,
(&path1.segments[0]).identifier == (&path3.segments[0]).identifier || (&path2.segments[0]).identifier == (&path3.segments[0]).identifier,
&path1.segments[0] == &path3.segments[0] || &path2.segments[0] == &path3.segments[0],
cx.tcx.expr_ty(ident1).is_integral(),
cx.tcx.expr_ty(ident2).is_integral()
], {
17 changes: 9 additions & 8 deletions src/shadow.rs
Original file line number Diff line number Diff line change
@@ -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::Ident(_, ident, _) = arg.pat.node {
bindings.push((ident.node.unhygienic_name, ident.span))
bindings.push((ident.node.unhygienize(), ident.span))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why isn't unhygienize() used in this file?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I does now, but the lint still has problems.

}
}
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::Ident(_, ref ident, ref inner) => {
let name = ident.node.unhygienic_name;
let name = ident.node.unhygienize();
if is_binding(cx, pat) {
let mut new_binding = true;
for tup in bindings.iter_mut() {
@@ -208,15 +208,16 @@ fn lint_shadow<T>(cx: &LateContext, name: Name, span: Span, pattern_span: Span,
let db = span_lint(cx,
SHADOW_SAME,
span,
&format!("{} is shadowed by itself in {}",
&format!("`{}` is shadowed by itself in `{}`",
snippet(cx, pattern_span, "_"),
snippet(cx, expr.span, "..")));

note_orig(cx, db, SHADOW_SAME, prev_span);
} else if contains_self(name, expr) {
let db = span_note_and_lint(cx,
SHADOW_REUSE,
pattern_span,
&format!("{} is shadowed by {} which reuses the original value",
&format!("`{}` is shadowed by `{}` which reuses the original value",
snippet(cx, pattern_span, "_"),
snippet(cx, expr.span, "..")),
expr.span,
@@ -226,7 +227,7 @@ fn lint_shadow<T>(cx: &LateContext, name: Name, span: Span, pattern_span: Span,
let db = span_note_and_lint(cx,
SHADOW_UNRELATED,
pattern_span,
&format!("{} is shadowed by {}",
&format!("`{}` is shadowed by `{}`",
snippet(cx, pattern_span, "_"),
snippet(cx, expr.span, "..")),
expr.span,
@@ -326,7 +327,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].identifier.unhygienic_name == name
!path.global && path.segments.len() == 1 && path.segments[0].name.unhygienize() == name
}

struct ContainsSelf {
@@ -335,8 +336,8 @@ struct ContainsSelf {
}

impl<'v> Visitor<'v> for ContainsSelf {
fn visit_ident(&mut self, _: Span, ident: Ident) {
if self.name == ident.unhygienic_name {
fn visit_name(&mut self, _: Span, name: Name) {
if self.name == name.unhygienize() {
self.result = true;
}
}
2 changes: 1 addition & 1 deletion src/swap.rs
Original file line number Diff line number Diff line change
@@ -75,7 +75,7 @@ fn check_manual_swap(cx: &LateContext, block: &Block) {
let ExprPath(None, ref rhs2) = rhs2.node,
rhs2.segments.len() == 1,

tmp_name.node.name.as_str() == rhs2.segments[0].identifier.name.as_str(),
tmp_name.node.as_str() == rhs2.segments[0].name.as_str(),
SpanlessEq::new(cx).ignore_fn().eq_expr(tmp_init, lhs1),
SpanlessEq::new(cx).ignore_fn().eq_expr(rhs1, lhs2)
], {
2 changes: 1 addition & 1 deletion src/unsafe_removed_from_name.rs
Original file line number Diff line number Diff line change
@@ -41,7 +41,7 @@ impl LateLintPass for UnsafeNameRemoval {
path.segments
.last()
.expect("use paths cannot be empty")
.identifier.name,
.name,
*name,
cx, &item.span
);
4 changes: 2 additions & 2 deletions src/unused_label.rs
Original file line number Diff line number Diff line change
@@ -65,10 +65,10 @@ impl<'v> Visitor<'v> for UnusedLabelVisitor {
fn visit_expr(&mut self, expr: &hir::Expr) {
match expr.node {
hir::ExprBreak(Some(label)) | hir::ExprAgain(Some(label)) => {
self.labels.remove(&label.node.name.as_str());
self.labels.remove(&label.node.as_str());
}
hir::ExprLoop(_, Some(label)) | hir::ExprWhile(_, _, Some(label)) => {
self.labels.insert(label.name.as_str(), expr.span);
self.labels.insert(label.as_str(), expr.span);
}
_ => (),
}
22 changes: 11 additions & 11 deletions src/utils/hir.rs
Original file line number Diff line number Diff line change
@@ -68,7 +68,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> {

match (&left.node, &right.node) {
(&ExprAddrOf(l_mut, ref le), &ExprAddrOf(r_mut, ref re)) => l_mut == r_mut && self.eq_expr(le, re),
(&ExprAgain(li), &ExprAgain(ri)) => both(&li, &ri, |l, r| l.node.name.as_str() == r.node.name.as_str()),
(&ExprAgain(li), &ExprAgain(ri)) => both(&li, &ri, |l, r| l.node.as_str() == r.node.as_str()),
(&ExprAssign(ref ll, ref lr), &ExprAssign(ref rl, ref rr)) => self.eq_expr(ll, rl) && self.eq_expr(lr, rr),
(&ExprAssignOp(ref lo, ref ll, ref lr), &ExprAssignOp(ref ro, ref rl, ref rr)) => {
lo.node == ro.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr)
@@ -80,7 +80,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> {
l_op == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr)
})
}
(&ExprBreak(li), &ExprBreak(ri)) => both(&li, &ri, |l, r| l.node.name.as_str() == r.node.name.as_str()),
(&ExprBreak(li), &ExprBreak(ri)) => both(&li, &ri, |l, r| l.node.as_str() == r.node.as_str()),
(&ExprBox(ref l), &ExprBox(ref r)) => self.eq_expr(l, r),
(&ExprCall(ref l_fun, ref l_args), &ExprCall(ref r_fun, ref r_args)) => {
!self.ignore_fn && self.eq_expr(l_fun, r_fun) && self.eq_exprs(l_args, r_args)
@@ -95,7 +95,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> {
}
(&ExprLit(ref l), &ExprLit(ref r)) => l.node == r.node,
(&ExprLoop(ref lb, ref ll), &ExprLoop(ref rb, ref rl)) => {
self.eq_block(lb, rb) && both(ll, rl, |l, r| l.name.as_str() == r.name.as_str())
self.eq_block(lb, rb) && both(ll, rl, |l, r| l.as_str() == r.as_str())
}
(&ExprMatch(ref le, ref la, ref ls), &ExprMatch(ref re, ref ra, ref rs)) => {
ls == rs && self.eq_expr(le, re) &&
@@ -124,7 +124,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> {
(&ExprUnary(l_op, ref le), &ExprUnary(r_op, ref re)) => l_op == r_op && self.eq_expr(le, re),
(&ExprVec(ref l), &ExprVec(ref r)) => self.eq_exprs(l, r),
(&ExprWhile(ref lc, ref lb, ref ll), &ExprWhile(ref rc, ref rb, ref rl)) => {
self.eq_expr(lc, rc) && self.eq_block(lb, rb) && both(ll, rl, |l, r| l.name.as_str() == r.name.as_str())
self.eq_expr(lc, rc) && self.eq_block(lb, rb) && both(ll, rl, |l, r| l.as_str() == r.as_str())
}
_ => false,
}
@@ -146,7 +146,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> {
self.eq_path(lp, rp) && both(la, ra, |l, r| over(l, r, |l, r| self.eq_pat(l, r)))
}
(&PatKind::Ident(ref lb, ref li, ref lp), &PatKind::Ident(ref rb, ref ri, ref rp)) => {
lb == rb && li.node.name.as_str() == ri.node.name.as_str() && both(lp, rp, |l, r| self.eq_pat(l, r))
lb == rb && li.node.as_str() == ri.node.as_str() && both(lp, rp, |l, r| self.eq_pat(l, r))
}
(&PatKind::Lit(ref l), &PatKind::Lit(ref r)) => self.eq_expr(l, r),
(&PatKind::QPath(ref ls, ref lp), &PatKind::QPath(ref rs, ref rp)) => {
@@ -172,7 +172,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> {
left.global == right.global &&
over(&left.segments,
&right.segments,
|l, r| l.identifier.name.as_str() == r.identifier.name.as_str() && l.parameters == r.parameters)
|l, r| l.name.as_str() == r.name.as_str() && l.parameters == r.parameters)
}

fn eq_qself(&self, left: &QSelf, right: &QSelf) -> bool {
@@ -281,7 +281,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> {
let c: fn(_) -> _ = ExprAgain;
c.hash(&mut self.s);
if let Some(i) = i {
self.hash_name(&i.node.name);
self.hash_name(&i.node);
}
}
ExprAssign(ref l, ref r) => {
@@ -313,7 +313,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> {
let c: fn(_) -> _ = ExprBreak;
c.hash(&mut self.s);
if let Some(i) = i {
self.hash_name(&i.node.name);
self.hash_name(&i.node);
}
}
ExprBox(ref e) => {
@@ -374,7 +374,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> {
c.hash(&mut self.s);
self.hash_block(b);
if let Some(i) = *i {
self.hash_name(&i.name);
self.hash_name(&i);
}
}
ExprMatch(ref e, ref arms, ref s) => {
@@ -468,7 +468,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> {
self.hash_expr(cond);
self.hash_block(b);
if let Some(l) = l {
self.hash_name(&l.name);
self.hash_name(&l);
}
}
}
@@ -487,7 +487,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> {
pub fn hash_path(&mut self, p: &Path) {
p.global.hash(&mut self.s);
for p in &p.segments {
self.hash_name(&p.identifier.name);
self.hash_name(&p.name);
}
}

2 changes: 1 addition & 1 deletion src/utils/mod.rs
Original file line number Diff line number Diff line change
@@ -200,7 +200,7 @@ pub fn match_trait_method(cx: &LateContext, expr: &Expr, path: &[&str]) -> bool
/// match_path(path, &["std", "rt", "begin_unwind"])
/// ```
pub fn match_path(path: &Path, segments: &[&str]) -> bool {
path.segments.iter().rev().zip(segments.iter().rev()).all(|(a, b)| a.identifier.name.as_str() == *b)
path.segments.iter().rev().zip(segments.iter().rev()).all(|(a, b)| a.name.as_str() == *b)
}

/// Match a `Path` against a slice of segment string literals, e.g.
12 changes: 7 additions & 5 deletions src/vec.rs
Original file line number Diff line number Diff line change
@@ -38,17 +38,19 @@ impl LateLintPass for UselessVec {
let TypeVariants::TySlice(..) = ty.ty.sty,
let ExprAddrOf(_, ref addressee) = expr.node,
], {
check_vec_macro(cx, expr, addressee);
check_vec_macro(cx, addressee, expr.span);
}}

// search for `for _ in vec![…]`
if let Some((_, arg, _)) = recover_for_loop(expr) {
check_vec_macro(cx, arg, arg);
// report the error around the `vec!` not inside `<std macros>:`
let span = cx.sess().codemap().source_callsite(arg.span);
check_vec_macro(cx, arg, span);
}
}
}

fn check_vec_macro(cx: &LateContext, expr: &Expr, vec: &Expr) {
fn check_vec_macro(cx: &LateContext, vec: &Expr, span: Span) {
if let Some(vec_args) = unexpand_vec(cx, vec) {
let snippet = match vec_args {
VecArgs::Repeat(elem, len) => {
@@ -69,8 +71,8 @@ fn check_vec_macro(cx: &LateContext, expr: &Expr, vec: &Expr) {
}
};

span_lint_and_then(cx, USELESS_VEC, expr.span, "useless use of `vec!`", |db| {
db.span_suggestion(expr.span, "you can use a slice directly", snippet);
span_lint_and_then(cx, USELESS_VEC, span, "useless use of `vec!`", |db| {
db.span_suggestion(span, "you can use a slice directly", snippet);
});
}
}
8 changes: 3 additions & 5 deletions tests/compile-fail/methods.rs
Original file line number Diff line number Diff line change
@@ -288,7 +288,7 @@ fn or_fun_call() {
with_vec.unwrap_or(vec![]);
//~^ERROR use of `unwrap_or`
//~|HELP try this
//~|SUGGESTION with_vec.unwrap_or_else(|| vec![]);
// FIXME #944: ~|SUGGESTION with_vec.unwrap_or_else(|| vec![]);

let without_default = Some(Foo);
without_default.unwrap_or(Foo::new());
@@ -493,10 +493,8 @@ fn single_char_pattern() {
fn temporary_cstring() {
use std::ffi::CString;

( // extra parenthesis to better test spans
CString::new("foo").unwrap().as_ptr();
//~^ ERROR you are getting the inner pointer of a temporary `CString`
//~| NOTE that pointer will be invalid outside this expression
CString::new("foo").unwrap()
//~^ HELP assign the `CString` to a variable to extend its lifetime
).as_ptr();
//~| HELP assign the `CString` to a variable to extend its lifetime
}
11 changes: 6 additions & 5 deletions tests/compile-fail/mut_mut.rs
Original file line number Diff line number Diff line change
@@ -18,6 +18,7 @@ fn less_fun(x : *mut *mut u32) {

macro_rules! mut_ptr {
($p:expr) => { &mut $p }
//~^ ERROR generally you want to avoid `&mut &mut
}

#[deny(mut_mut)]
@@ -30,12 +31,12 @@ fn main() {

if fun(x) {
let y : &mut &mut &mut u32 = &mut &mut &mut 2;
//~^ ERROR generally you want to avoid `&mut &mut
//~^^ ERROR generally you want to avoid `&mut &mut
//~^^^ ERROR generally you want to avoid `&mut &mut
//~^^^^ ERROR generally you want to avoid `&mut &mut
//~^ ERROR generally you want to avoid `&mut &mut
//~| ERROR generally you want to avoid `&mut &mut
//~| ERROR generally you want to avoid `&mut &mut
//~| ERROR generally you want to avoid `&mut &mut
***y + **x;
}

let mut z = mut_ptr!(&mut 3u32); //~ERROR generally you want to avoid `&mut &mut
let mut z = mut_ptr!(&mut 3u32); //~ NOTE in this expansion of mut_ptr!
}
16 changes: 8 additions & 8 deletions tests/compile-fail/shadow.rs
Original file line number Diff line number Diff line change
@@ -10,15 +10,15 @@ fn first(x: (isize, isize)) -> isize { x.0 }

fn main() {
let mut x = 1;
let x = &mut x; //~ERROR x is shadowed by itself in &mut x
let x = { x }; //~ERROR x is shadowed by itself in { x }
let x = (&*x); //~ERROR x is shadowed by itself in &*x
let x = { *x + 1 }; //~ERROR x is shadowed by { *x + 1 } which reuses
let x = id(x); //~ERROR x is shadowed by id(x) which reuses
let x = (1, x); //~ERROR x is shadowed by (1, x) which reuses
let x = first(x); //~ERROR x is shadowed by first(x) which reuses
let x = &mut x; //~ERROR `x` is shadowed by itself in `&mut x`
let x = { x }; //~ERROR `x` is shadowed by itself in `{ x }`
let x = (&*x); //~ERROR `x` is shadowed by itself in `(&*x)`
let x = { *x + 1 }; //~ERROR `x` is shadowed by `{ *x + 1 }` which reuses
let x = id(x); //~ERROR `x` is shadowed by `id(x)` which reuses
let x = (1, x); //~ERROR `x` is shadowed by `(1, x)` which reuses
let x = first(x); //~ERROR `x` is shadowed by `first(x)` which reuses
let y = 1;
let x = y; //~ERROR x is shadowed by y
let x = y; //~ERROR `x` is shadowed by `y`

let o = Some(1u8);

7 changes: 4 additions & 3 deletions tests/compile-fail/used_underscore_binding.rs
Original file line number Diff line number Diff line change
@@ -3,15 +3,16 @@
#![deny(clippy)]

#![allow(blacklisted_name)]
#![deny(used_underscore_binding)]

/// 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 which is prefixed with an underscore
_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
fn in_macro(_foo: u32) {
println!("{}", _foo); //~ ERROR used binding which is prefixed with an underscore
println!("{}", _foo); //~ ERROR used binding `_foo` which is prefixed with an underscore
}

// Struct for testing use of fields prefixed with an underscore
@@ -22,7 +23,7 @@ struct StructFieldTest {
/// Test that we lint the use of a struct field which is prefixed with an underscore
fn in_struct_field() {
let mut s = StructFieldTest { _underscore_field: 0 };
s._underscore_field += 1; //~ Error used binding which is prefixed with an underscore
s._underscore_field += 1; //~ Error used binding `_underscore_field` which is prefixed with an underscore
}

/// Test that we do not lint if the underscore is not a prefix