Skip to content

Commit

Permalink
Auto merge of #4149 - flip1995:rollup-6knpdqb, r=flip1995
Browse files Browse the repository at this point in the history
Rollup of 2 pull requests

Successful merges:

 - #4102 (Fix match_same_arms to fail late)
 - #4119 (Improve non ascii literal)

Failed merges:

r? @ghost
  • Loading branch information
bors committed May 27, 2019
2 parents cf81a3b + dce670c commit eb0a288
Show file tree
Hide file tree
Showing 8 changed files with 241 additions and 82 deletions.
37 changes: 26 additions & 11 deletions clippy_lints/src/copies.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ fn lint_same_cond(cx: &LateContext<'_, '_>, conds: &[&Expr]) {
let eq: &dyn Fn(&&Expr, &&Expr) -> bool =
&|&lhs, &rhs| -> bool { SpanlessEq::new(cx).ignore_fn().eq_expr(lhs, rhs) };

if let Some((i, j)) = search_same(conds, hash, eq) {
for (i, j) in search_same(conds, hash, eq) {
span_note_and_lint(
cx,
IFS_SAME_COND,
Expand Down Expand Up @@ -185,7 +185,7 @@ fn lint_match_arms(cx: &LateContext<'_, '_>, expr: &Expr) {
};

let indexed_arms: Vec<(usize, &Arm)> = arms.iter().enumerate().collect();
if let Some((&(_, i), &(_, j))) = search_same(&indexed_arms, hash, eq) {
for (&(_, i), &(_, j)) in search_same(&indexed_arms, hash, eq) {
span_lint_and_then(
cx,
MATCH_SAME_ARMS,
Expand Down Expand Up @@ -217,7 +217,10 @@ fn lint_match_arms(cx: &LateContext<'_, '_>, expr: &Expr) {
),
);
} else {
db.span_note(i.body.span, &format!("consider refactoring into `{} | {}`", lhs, rhs));
db.span_help(
i.pats[0].span,
&format!("consider refactoring into `{} | {}`", lhs, rhs),
);
}
}
},
Expand Down Expand Up @@ -323,21 +326,33 @@ where
None
}

fn search_same<T, Hash, Eq>(exprs: &[T], hash: Hash, eq: Eq) -> Option<(&T, &T)>
fn search_common_cases<'a, T, Eq>(exprs: &'a [T], eq: &Eq) -> Option<(&'a T, &'a T)>
where
Hash: Fn(&T) -> u64,
Eq: Fn(&T, &T) -> bool,
{
// common cases
if exprs.len() < 2 {
return None;
None
} else if exprs.len() == 2 {
return if eq(&exprs[0], &exprs[1]) {
if eq(&exprs[0], &exprs[1]) {
Some((&exprs[0], &exprs[1]))
} else {
None
};
}
} else {
None
}
}

fn search_same<T, Hash, Eq>(exprs: &[T], hash: Hash, eq: Eq) -> Vec<(&T, &T)>
where
Hash: Fn(&T) -> u64,
Eq: Fn(&T, &T) -> bool,
{
if let Some(expr) = search_common_cases(&exprs, &eq) {
return vec![expr];
}

let mut match_expr_list: Vec<(&T, &T)> = Vec::new();

let mut map: FxHashMap<_, Vec<&_>> =
FxHashMap::with_capacity_and_hasher(exprs.len(), BuildHasherDefault::default());
Expand All @@ -347,7 +362,7 @@ where
Entry::Occupied(mut o) => {
for o in o.get() {
if eq(o, expr) {
return Some((o, expr));
match_expr_list.push((o, expr));
}
}
o.get_mut().push(expr);
Expand All @@ -358,5 +373,5 @@ where
}
}

None
match_expr_list
}
44 changes: 23 additions & 21 deletions clippy_lints/src/unicode.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use crate::utils::{is_allowed, snippet, span_help_and_lint};
use crate::utils::{is_allowed, snippet, span_lint_and_sugg};
use rustc::hir::*;
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::{declare_lint_pass, declare_tool_lint};
use rustc_errors::Applicability;
use syntax::ast::LitKind;
use syntax::source_map::Span;
use unicode_normalization::UnicodeNormalization;
Expand Down Expand Up @@ -34,7 +35,11 @@ declare_clippy_lint! {
///
/// **Example:**
/// ```rust
/// let x = "Hä?"
/// let x = String::from("€");
/// ```
/// Could be written as:
/// ```rust
/// let x = String::from("\u{20ac}");
/// ```
pub NON_ASCII_LITERAL,
pedantic,
Expand Down Expand Up @@ -87,43 +92,40 @@ fn escape<T: Iterator<Item = char>>(s: T) -> String {
fn check_str(cx: &LateContext<'_, '_>, span: Span, id: HirId) {
let string = snippet(cx, span, "");
if string.contains('\u{200B}') {
span_help_and_lint(
span_lint_and_sugg(
cx,
ZERO_WIDTH_SPACE,
span,
"zero-width space detected",
&format!(
"Consider replacing the string with:\n\"{}\"",
string.replace("\u{200B}", "\\u{200B}")
),
"consider replacing the string with",
string.replace("\u{200B}", "\\u{200B}"),
Applicability::MachineApplicable,
);
}
if string.chars().any(|c| c as u32 > 0x7F) {
span_help_and_lint(
span_lint_and_sugg(
cx,
NON_ASCII_LITERAL,
span,
"literal non-ASCII character detected",
&format!(
"Consider replacing the string with:\n\"{}\"",
if is_allowed(cx, UNICODE_NOT_NFC, id) {
escape(string.chars())
} else {
escape(string.nfc())
}
),
"consider replacing the string with",
if is_allowed(cx, UNICODE_NOT_NFC, id) {
escape(string.chars())
} else {
escape(string.nfc())
},
Applicability::MachineApplicable,
);
}
if is_allowed(cx, NON_ASCII_LITERAL, id) && string.chars().zip(string.nfc()).any(|(a, b)| a != b) {
span_help_and_lint(
span_lint_and_sugg(
cx,
UNICODE_NOT_NFC,
span,
"non-nfc unicode sequence detected",
&format!(
"Consider replacing the string with:\n\"{}\"",
string.nfc().collect::<String>()
),
"consider replacing the string with",
string.nfc().collect::<String>(),
Applicability::MachineApplicable,
);
}
}
14 changes: 14 additions & 0 deletions tests/ui/if_same_then_else.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,20 @@ fn if_same_then_else() -> Result<&'static str, ()> {
return Ok(&foo[0..]);
}

if true {
let foo = "";
return Ok(&foo[0..]);
} else if false {
let foo = "bar";
return Ok(&foo[0..]);
} else if true {
let foo = "";
return Ok(&foo[0..]);
} else {
let foo = "";
return Ok(&foo[0..]);
}

// False positive `if_same_then_else`: `let (x, y)` vs. `let (y, x)`; see issue #3559.
if true {
let foo = "";
Expand Down
35 changes: 34 additions & 1 deletion tests/ui/if_same_then_else.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -210,5 +210,38 @@ LL | | try!(Ok("foo"));
LL | | } else {
| |_____^

error: aborting due to 10 previous errors
error: this `if` has identical blocks
--> $DIR/if_same_then_else.rs:244:12
|
LL | } else {
| ____________^
LL | | let foo = "";
LL | | return Ok(&foo[0..]);
LL | | }
| |_____^
|
note: same as this
--> $DIR/if_same_then_else.rs:241:20
|
LL | } else if true {
| ____________________^
LL | | let foo = "";
LL | | return Ok(&foo[0..]);
LL | | } else {
| |_____^

error: this `if` has the same condition as a previous if
--> $DIR/if_same_then_else.rs:241:15
|
LL | } else if true {
| ^^^^
|
= note: #[deny(clippy::ifs_same_cond)] on by default
note: same as this
--> $DIR/if_same_then_else.rs:235:8
|
LL | if true {
| ^^^^

error: aborting due to 12 previous errors

16 changes: 16 additions & 0 deletions tests/ui/match_same_arms.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,22 @@ fn match_same_arms() {
(None, Some(a)) => bar(a), // bindings have different types
_ => (),
}

let _ = match 42 {
42 => 1,
51 => 1, //~ ERROR match arms have same body
41 => 2,
52 => 2, //~ ERROR match arms have same body
_ => 0,
};

let _ = match 42 {
1 => 2,
2 => 2, //~ ERROR 2nd matched arms have same body
3 => 2, //~ ERROR 3rd matched arms have same body
4 => 3,
_ => 0,
};
}

fn main() {}
Loading

0 comments on commit eb0a288

Please sign in to comment.