Skip to content

Commit cf1fa94

Browse files
committed
down to for-loops not comparing as equal
1 parent 16aab71 commit cf1fa94

File tree

2 files changed

+41
-60
lines changed

2 files changed

+41
-60
lines changed

clippy_lints/src/utils/hir.rs

+37-58
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use consts::constant;
22
use rustc::lint::*;
33
use rustc::hir::*;
4+
use rustc::hir::def::Def;
45
use std::hash::{Hash, Hasher};
56
use std::collections::hash_map::DefaultHasher;
67
use syntax::ast::{Name, NodeId};
@@ -103,8 +104,8 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> {
103104
(&ExprLoop(ref lb, ref ll, ref lls), &ExprLoop(ref rb, ref rl, ref rls)) => {
104105
self.eq_block(lb, rb) && both(ll, rl, |l, r| l.node.as_str() == r.node.as_str()) && lls == rls
105106
}
106-
(&ExprMatch(ref le, ref la, ref ls), &ExprMatch(ref re, ref ra, ref rs)) => {
107-
ls == rs && self.eq_expr(le, re) &&
107+
(&ExprMatch(ref le, ref la, _), &ExprMatch(ref re, ref ra, _)) => {
108+
self.eq_expr(le, re) &&
108109
over(la, ra, |l, r| {
109110
self.eq_expr(&l.body, &r.body) && both(&l.guard, &r.guard, |l, r| self.eq_expr(l, r)) &&
110111
over(&l.pats, &r.pats, |l, r| self.eq_pat(l, r))
@@ -118,9 +119,10 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> {
118119
}
119120
(&ExprRepeat(ref le, ref ll), &ExprRepeat(ref re, ref rl)) => self.eq_expr(le, re) && self.eq_expr(ll, rl),
120121
(&ExprRet(ref l), &ExprRet(ref r)) => both(l, r, |l, r| self.eq_expr(l, r)),
121-
(&ExprPath(ref l), &ExprPath(ref r)) => self.eq_qpath(l, r),
122+
(&ExprPath(ref l), &ExprPath(ref r)) => self.eq_qpath(l, left.id, r, right.id),
122123
(&ExprStruct(ref l_path, ref lf, ref lo), &ExprStruct(ref r_path, ref rf, ref ro)) => {
123-
self.eq_qpath(l_path, r_path) && both(lo, ro, |l, r| self.eq_expr(l, r)) &&
124+
self.eq_qpath(l_path, left.id, r_path, right.id) &&
125+
both(lo, ro, |l, r| self.eq_expr(l, r)) &&
124126
over(lf, rf, |l, r| self.eq_field(l, r))
125127
}
126128
(&ExprTup(ref l_tup), &ExprTup(ref r_tup)) => self.eq_exprs(l_tup, r_tup),
@@ -142,21 +144,17 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> {
142144
left.name.node == right.name.node && self.eq_expr(&left.expr, &right.expr)
143145
}
144146

145-
fn eq_lifetime(&self, left: &Lifetime, right: &Lifetime) -> bool {
146-
left.name == right.name
147-
}
148-
149147
/// Check whether two patterns are the same.
150148
pub fn eq_pat(&self, left: &Pat, right: &Pat) -> bool {
151149
match (&left.node, &right.node) {
152150
(&PatKind::Box(ref l), &PatKind::Box(ref r)) => self.eq_pat(l, r),
153151
(&PatKind::TupleStruct(ref lp, ref la, ls), &PatKind::TupleStruct(ref rp, ref ra, rs)) => {
154-
self.eq_qpath(lp, rp) && over(la, ra, |l, r| self.eq_pat(l, r)) && ls == rs
152+
self.eq_qpath(lp, left.id, rp, right.id) && over(la, ra, |l, r| self.eq_pat(l, r)) && ls == rs
155153
}
156-
(&PatKind::Binding(ref lb, ref ld, ref li, ref lp), &PatKind::Binding(ref rb, ref rd, ref ri, ref rp)) => {
157-
lb == rb && ld == rd && li.node.as_str() == ri.node.as_str() && both(lp, rp, |l, r| self.eq_pat(l, r))
154+
(&PatKind::Binding(ref lb, _, ref li, ref lp), &PatKind::Binding(ref rb, _, ref ri, ref rp)) => {
155+
lb == rb && li.node.as_str() == ri.node.as_str() && both(lp, rp, |l, r| self.eq_pat(l, r))
158156
}
159-
(&PatKind::Path(ref l), &PatKind::Path(ref r)) => self.eq_qpath(l, r),
157+
(&PatKind::Path(ref l), &PatKind::Path(ref r)) => self.eq_qpath(l, left.id, r, right.id),
160158
(&PatKind::Lit(ref l), &PatKind::Lit(ref r)) => self.eq_expr(l, r),
161159
(&PatKind::Tuple(ref l, ls), &PatKind::Tuple(ref r, rs)) => {
162160
ls == rs && over(l, r, |l, r| self.eq_pat(l, r))
@@ -174,48 +172,23 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> {
174172
}
175173
}
176174

177-
fn eq_qpath(&self, left: &QPath, right: &QPath) -> bool {
178-
match (left, right) {
179-
(&QPath::Resolved(ref lty, ref lpath), &QPath::Resolved(ref rty, ref rpath)) => {
180-
both(lty, rty, |l, r| self.eq_ty(l, r)) && self.eq_path(lpath, rpath)
181-
},
182-
(&QPath::TypeRelative(ref lty, ref lseg), &QPath::TypeRelative(ref rty, ref rseg)) => {
183-
self.eq_ty(lty, rty) && self.eq_path_segment(lseg, rseg)
184-
},
185-
_ => false,
186-
}
187-
}
188-
189-
fn eq_path(&self, left: &Path, right: &Path) -> bool {
190-
left.global == right.global &&
191-
over(&left.segments, &right.segments, |l, r| self.eq_path_segment(l, r))
192-
}
175+
fn eq_qpath(&self, left: &QPath, lid: NodeId, right: &QPath, rid: NodeId) -> bool {
176+
let l = self.cx.tcx.tables().qpath_def(left, lid);
177+
let r = self.cx.tcx.tables().qpath_def(right, rid);
193178

194-
fn eq_path_parameters(&self, left: &PathParameters, right: &PathParameters) -> bool {
195-
match (left, right) {
196-
(&AngleBracketedParameters(ref left), &AngleBracketedParameters(ref right)) => {
197-
over(&left.lifetimes, &right.lifetimes, |l, r| self.eq_lifetime(l, r)) &&
198-
over(&left.types, &right.types, |l, r| self.eq_ty(l, r)) &&
199-
over(&left.bindings, &right.bindings, |l, r| self.eq_type_binding(l, r))
200-
}
201-
(&ParenthesizedParameters(ref left), &ParenthesizedParameters(ref right)) => {
202-
over(&left.inputs, &right.inputs, |l, r| self.eq_ty(l, r)) &&
203-
both(&left.output, &right.output, |l, r| self.eq_ty(l, r))
204-
}
205-
(&AngleBracketedParameters(_), &ParenthesizedParameters(_)) |
206-
(&ParenthesizedParameters(_), &AngleBracketedParameters(_)) => {
207-
false
179+
if let (Def::Local(_), Def::Local(_)) = (l, r) {
180+
if let (&QPath::Resolved(None, ref l), &QPath::Resolved(None, ref r)) = (left, right) {
181+
assert_eq!(l.segments.len(), 1);
182+
assert_eq!(r.segments.len(), 1);
183+
l.segments[0].name == r.segments[0].name
184+
} else {
185+
unreachable!();
208186
}
187+
} else {
188+
l == r
209189
}
210190
}
211191

212-
fn eq_path_segment(&self, left: &PathSegment, right: &PathSegment) -> bool {
213-
// The == of idents doesn't work with different contexts,
214-
// we have to be explicit about hygiene
215-
left.name.as_str() == right.name.as_str() &&
216-
self.eq_path_parameters(&left.parameters, &right.parameters)
217-
}
218-
219192
fn eq_ty(&self, left: &Ty, right: &Ty) -> bool {
220193
match (&left.node, &right.node) {
221194
(&TySlice(ref l_vec), &TySlice(ref r_vec)) => self.eq_ty(l_vec, r_vec),
@@ -226,16 +199,12 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> {
226199
(&TyRptr(_, ref l_rmut), &TyRptr(_, ref r_rmut)) => {
227200
l_rmut.mutbl == r_rmut.mutbl && self.eq_ty(&*l_rmut.ty, &*r_rmut.ty)
228201
}
229-
(&TyPath(ref l), &TyPath(ref r)) => self.eq_qpath(l, r),
202+
(&TyPath(ref l), &TyPath(ref r)) => self.eq_qpath(l, left.id, r, right.id),
230203
(&TyTup(ref l), &TyTup(ref r)) => over(l, r, |l, r| self.eq_ty(l, r)),
231204
(&TyInfer, &TyInfer) => true,
232205
_ => false,
233206
}
234207
}
235-
236-
fn eq_type_binding(&self, left: &TypeBinding, right: &TypeBinding) -> bool {
237-
left.name == right.name && self.eq_ty(&left.ty, &right.ty)
238-
}
239208
}
240209

241210
fn swap_binop<'a>(binop: BinOp_, lhs: &'a Expr, rhs: &'a Expr) -> Option<(BinOp_, &'a Expr, &'a Expr)> {
@@ -420,7 +389,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> {
420389
}
421390
j.hash(&mut self.s);
422391
}
423-
ExprMatch(ref e, ref arms, ref s) => {
392+
ExprMatch(ref e, ref arms, _) => {
424393
let c: fn(_, _, _) -> _ = ExprMatch;
425394
c.hash(&mut self.s);
426395
self.hash_expr(e);
@@ -432,8 +401,6 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> {
432401
}
433402
self.hash_expr(&arm.body);
434403
}
435-
436-
s.hash(&mut self.s);
437404
}
438405
ExprMethodCall(ref name, ref _tys, ref args) => {
439406
let c: fn(_, _, _) -> _ = ExprMethodCall;
@@ -529,7 +496,19 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> {
529496
}
530497

531498
pub fn hash_qpath(&mut self, p: &QPath, id: NodeId) {
532-
self.cx.tcx.tables().qpath_def(p, id).hash(&mut self.s);
499+
let def = self.cx.tcx.tables().qpath_def(p, id);
500+
if let Def::Local(_) = def {
501+
true.hash(&mut self.s);
502+
if let QPath::Resolved(None, ref seq) = *p {
503+
assert_eq!(seq.segments.len(), 1);
504+
self.hash_name(&seq.segments[0].name);
505+
} else {
506+
unreachable!();
507+
}
508+
} else {
509+
false.hash(&mut self.s);
510+
def.hash(&mut self.s);
511+
}
533512
}
534513

535514
pub fn hash_path(&mut self, p: &Path) {

tests/compile-fail/copies.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -224,16 +224,18 @@ fn if_same_then_else() -> Result<&'static str, ()> {
224224
}
225225

226226
if true {
227+
//~^NOTE same as this
227228
if let Some(42) = None {}
228229
}
229-
else {
230+
else { //~ERROR this `if` has identical blocks
230231
if let Option::Some(42) = None {}
231232
}
232233

233234
if true {
235+
//~^NOTE same as this
234236
if let Some(42) = None::<u8> {}
235237
}
236-
else {
238+
else { //~ERROR this `if` has identical blocks
237239
if let Some(42) = None {}
238240
}
239241

0 commit comments

Comments
 (0)