Skip to content

Commit 379c934

Browse files
committed
Auto merge of #3535 - sinkuu:fixes, r=phansch
Fix some problems Fixes #2892, #3199, #2841, #3476
2 parents 777c909 + eba44e1 commit 379c934

10 files changed

+123
-22
lines changed

clippy_lints/src/new_without_default.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use crate::rustc_errors::Applicability;
1717
use crate::syntax::source_map::Span;
1818
use crate::utils::paths;
1919
use crate::utils::sugg::DiagnosticBuilderExt;
20-
use crate::utils::{get_trait_def_id, implements_trait, return_ty, same_tys, span_lint_and_then};
20+
use crate::utils::{get_trait_def_id, implements_trait, return_ty, same_tys, span_lint_node_and_then};
2121
use if_chain::if_chain;
2222

2323
/// **What it does:** Checks for types with a `fn new() -> Self` method and no
@@ -165,9 +165,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault {
165165
}
166166

167167
if let Some(sp) = can_derive_default(self_ty, cx, default_trait_id) {
168-
span_lint_and_then(
168+
span_lint_node_and_then(
169169
cx,
170170
NEW_WITHOUT_DEFAULT_DERIVE,
171+
id,
171172
impl_item.span,
172173
&format!(
173174
"you should consider deriving a `Default` implementation for `{}`",
@@ -183,9 +184,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault {
183184
);
184185
});
185186
} else {
186-
span_lint_and_then(
187+
span_lint_node_and_then(
187188
cx,
188189
NEW_WITHOUT_DEFAULT,
190+
id,
189191
impl_item.span,
190192
&format!(
191193
"you should consider adding a `Default` implementation for `{}`",

clippy_lints/src/partialeq_ne_impl.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
use crate::rustc::hir::*;
1111
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
1212
use crate::rustc::{declare_tool_lint, lint_array};
13-
use crate::utils::{is_automatically_derived, span_lint};
13+
use crate::utils::{is_automatically_derived, span_lint_node};
1414
use if_chain::if_chain;
1515

1616
/// **What it does:** Checks for manual re-implementations of `PartialEq::ne`.
@@ -56,10 +56,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
5656
then {
5757
for impl_item in impl_items {
5858
if impl_item.ident.name == "ne" {
59-
span_lint(cx,
60-
PARTIALEQ_NE_IMPL,
61-
impl_item.span,
62-
"re-implementing `PartialEq::ne` is unnecessary")
59+
span_lint_node(
60+
cx,
61+
PARTIALEQ_NE_IMPL,
62+
impl_item.id.node_id,
63+
impl_item.span,
64+
"re-implementing `PartialEq::ne` is unnecessary",
65+
);
6366
}
6467
}
6568
}

clippy_lints/src/question_mark.rs

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use if_chain::if_chain;
1717

1818
use crate::rustc_errors::Applicability;
1919
use crate::utils::paths::*;
20-
use crate::utils::{match_def_path, match_type, span_lint_and_then};
20+
use crate::utils::{match_def_path, match_type, span_lint_and_then, SpanlessEq};
2121

2222
/// **What it does:** Checks for expressions that could be replaced by the question mark operator
2323
///
@@ -64,14 +64,40 @@ impl Pass {
6464
/// If it matches, it will suggest to use the question mark operator instead
6565
fn check_is_none_and_early_return_none(cx: &LateContext<'_, '_>, expr: &Expr) {
6666
if_chain! {
67-
if let ExprKind::If(ref if_expr, ref body, _) = expr.node;
68-
if let ExprKind::MethodCall(ref segment, _, ref args) = if_expr.node;
67+
if let ExprKind::If(if_expr, body, else_) = &expr.node;
68+
if let ExprKind::MethodCall(segment, _, args) = &if_expr.node;
6969
if segment.ident.name == "is_none";
7070
if Self::expression_returns_none(cx, body);
7171
if let Some(subject) = args.get(0);
7272
if Self::is_option(cx, subject);
7373

7474
then {
75+
if let Some(else_) = else_ {
76+
if_chain! {
77+
if let ExprKind::Block(block, None) = &else_.node;
78+
if block.stmts.len() == 0;
79+
if let Some(block_expr) = &block.expr;
80+
if SpanlessEq::new(cx).ignore_fn().eq_expr(subject, block_expr);
81+
then {
82+
span_lint_and_then(
83+
cx,
84+
QUESTION_MARK,
85+
expr.span,
86+
"this block may be rewritten with the `?` operator",
87+
|db| {
88+
db.span_suggestion_with_applicability(
89+
expr.span,
90+
"replace_it_with",
91+
format!("Some({}?)", Sugg::hir(cx, subject, "..")),
92+
Applicability::MaybeIncorrect, // snippet
93+
);
94+
}
95+
)
96+
}
97+
}
98+
return;
99+
}
100+
75101
span_lint_and_then(
76102
cx,
77103
QUESTION_MARK,
@@ -84,7 +110,7 @@ impl Pass {
84110
expr.span,
85111
"replace_it_with",
86112
format!("{}?;", receiver_str),
87-
Applicability::MachineApplicable, // snippet
113+
Applicability::MaybeIncorrect, // snippet
88114
);
89115
}
90116
)
@@ -133,9 +159,13 @@ impl Pass {
133159
}
134160
}
135161

136-
// Check if the block has an implicit return expression
137-
if let Some(ref ret_expr) = block.expr {
138-
return Some(ret_expr.clone());
162+
// Check for `return` without a semicolon.
163+
if_chain! {
164+
if block.stmts.len() == 0;
165+
if let Some(ExprKind::Ret(Some(ret_expr))) = block.expr.as_ref().map(|e| &e.node);
166+
then {
167+
return Some(ret_expr.clone());
168+
}
139169
}
140170

141171
None

clippy_lints/src/redundant_field_names.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,10 @@ impl EarlyLintPass for RedundantFieldNames {
5757
continue;
5858
}
5959
if let ExprKind::Path(None, path) = &field.expr.node {
60-
if path.segments.len() == 1 && path.segments[0].ident == field.ident {
60+
if path.segments.len() == 1
61+
&& path.segments[0].ident == field.ident
62+
&& path.segments[0].args.is_none()
63+
{
6164
span_lint_and_sugg(
6265
cx,
6366
REDUNDANT_FIELD_NAMES,

tests/ui/new_without_default.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,4 +139,18 @@ impl<'a, T: 'a> OptionRefWrapper<'a, T> {
139139
}
140140
}
141141

142+
pub struct Allow(Foo);
143+
144+
impl Allow {
145+
#[allow(clippy::new_without_default)]
146+
pub fn new() -> Self { unimplemented!() }
147+
}
148+
149+
pub struct AllowDerive;
150+
151+
impl AllowDerive {
152+
#[allow(clippy::new_without_default_derive)]
153+
pub fn new() -> Self { unimplemented!() }
154+
}
155+
142156
fn main() {}

tests/ui/partialeq_ne_impl.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,12 @@ impl PartialEq for Foo {
2020
}
2121
}
2222

23+
struct Bar;
24+
25+
impl PartialEq for Bar {
26+
fn eq(&self, _: &Bar) -> bool { true }
27+
#[allow(clippy::partialeq_ne_impl)]
28+
fn ne(&self, _: &Bar) -> bool { false }
29+
}
30+
2331
fn main() {}

tests/ui/question_mark.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,22 @@ pub struct SomeStruct {
4242
}
4343

4444
impl SomeStruct {
45+
#[rustfmt::skip]
4546
pub fn func(&self) -> Option<u32> {
4647
if (self.opt).is_none() {
4748
return None;
4849
}
4950

51+
if self.opt.is_none() {
52+
return None
53+
}
54+
55+
let _ = if self.opt.is_none() {
56+
return None;
57+
} else {
58+
self.opt
59+
};
60+
5061
self.opt
5162
}
5263
}

tests/ui/question_mark.stderr

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,31 @@ error: this block may be rewritten with the `?` operator
99
= note: `-D clippy::question-mark` implied by `-D warnings`
1010

1111
error: this block may be rewritten with the `?` operator
12-
--> $DIR/question_mark.rs:46:9
12+
--> $DIR/question_mark.rs:47:9
1313
|
14-
46 | / if (self.opt).is_none() {
15-
47 | | return None;
16-
48 | | }
14+
47 | / if (self.opt).is_none() {
15+
48 | | return None;
16+
49 | | }
1717
| |_________^ help: replace_it_with: `(self.opt)?;`
1818

19-
error: aborting due to 2 previous errors
19+
error: this block may be rewritten with the `?` operator
20+
--> $DIR/question_mark.rs:51:9
21+
|
22+
51 | / if self.opt.is_none() {
23+
52 | | return None
24+
53 | | }
25+
| |_________^ help: replace_it_with: `self.opt?;`
26+
27+
error: this block may be rewritten with the `?` operator
28+
--> $DIR/question_mark.rs:55:17
29+
|
30+
55 | let _ = if self.opt.is_none() {
31+
| _________________^
32+
56 | | return None;
33+
57 | | } else {
34+
58 | | self.opt
35+
59 | | };
36+
| |_________^ help: replace_it_with: `Some(self.opt?)`
37+
38+
error: aborting due to 4 previous errors
2039

tests/ui/redundant_field_names.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,14 @@ fn main() {
6868
let _ = RangeInclusive::new(start, end);
6969
let _ = RangeToInclusive { end: end };
7070
}
71+
72+
fn issue_3476() {
73+
fn foo<T>() {
74+
}
75+
76+
struct S {
77+
foo: fn(),
78+
}
79+
80+
S { foo: foo::<i32> };
81+
}

tests/ui/unused_io_amount.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
use std::io;
1414

15-
// FIXME: compiletest doesn't understand errors from macro invocation span
15+
1616
fn try_macro<T: io::Read + io::Write>(s: &mut T) -> io::Result<()> {
1717
try!(s.write(b"test"));
1818
let mut buf = [0u8; 4];

0 commit comments

Comments
 (0)