mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 00:03:43 +00:00
Do not underline suggestions for code that is already there
When a suggestion part is for already present code, do not highlight it. If after that there are no highlights left, do not show the suggestion at all. Fix clippy lint suggestion incorrectly treated as `span_help`.
This commit is contained in:
parent
e60ebb2f2c
commit
8ce8c42e0b
@ -1767,7 +1767,10 @@ impl HumanEmitter {
|
||||
debug!(?suggestions);
|
||||
|
||||
if suggestions.is_empty() {
|
||||
// Suggestions coming from macros can have malformed spans. This is a heavy handed
|
||||
// Here we check if there are suggestions that have actual code changes. We sometimes
|
||||
// suggest the same code that is already there, instead of changing how we produce the
|
||||
// suggestions and filtering there, we just don't emit the suggestion.
|
||||
// Suggestions coming from macros can also have malformed spans. This is a heavy handed
|
||||
// approach to avoid ICEs by ignoring the suggestion outright.
|
||||
return Ok(());
|
||||
}
|
||||
@ -2046,7 +2049,9 @@ impl HumanEmitter {
|
||||
assert!(underline_start >= 0 && underline_end >= 0);
|
||||
let padding: usize = max_line_num_len + 3;
|
||||
for p in underline_start..underline_end {
|
||||
if let DisplaySuggestion::Underline = show_code_change {
|
||||
if let DisplaySuggestion::Underline = show_code_change
|
||||
&& is_different(sm, &part.snippet, part.span)
|
||||
{
|
||||
// If this is a replacement, underline with `~`, if this is an addition
|
||||
// underline with `+`.
|
||||
buffer.putc(
|
||||
@ -2824,6 +2829,18 @@ impl Style {
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether the original and suggested code are the same.
|
||||
pub fn is_different(sm: &SourceMap, suggested: &str, sp: Span) -> bool {
|
||||
let found = match sm.span_to_snippet(sp) {
|
||||
Ok(snippet) => snippet,
|
||||
Err(e) => {
|
||||
warn!(error = ?e, "Invalid span {:?}", sp);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
found != suggested
|
||||
}
|
||||
|
||||
/// Whether the original and suggested code are visually similar enough to warrant extra wording.
|
||||
pub fn is_case_difference(sm: &SourceMap, suggested: &str, sp: Span) -> bool {
|
||||
// FIXME: this should probably be extended to also account for `FO0` → `FOO` and unicode.
|
||||
|
@ -50,7 +50,7 @@ pub use diagnostic_impls::{
|
||||
IndicateAnonymousLifetime, SingleLabelManySpans,
|
||||
};
|
||||
pub use emitter::ColorConfig;
|
||||
use emitter::{is_case_difference, DynEmitter, Emitter};
|
||||
use emitter::{is_case_difference, is_different, DynEmitter, Emitter};
|
||||
use registry::Registry;
|
||||
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
|
||||
use rustc_data_structures::stable_hasher::{Hash128, StableHasher};
|
||||
@ -357,10 +357,16 @@ impl CodeSuggestion {
|
||||
_ => 1,
|
||||
})
|
||||
.sum();
|
||||
line_highlight.push(SubstitutionHighlight {
|
||||
start: (cur_lo.col.0 as isize + acc) as usize,
|
||||
end: (cur_lo.col.0 as isize + acc + len) as usize,
|
||||
});
|
||||
if !is_different(sm, &part.snippet, part.span) {
|
||||
// Account for cases where we are suggesting the same code that's already
|
||||
// there. This shouldn't happen often, but in some cases for multipart
|
||||
// suggestions it's much easier to handle it here than in the origin.
|
||||
} else {
|
||||
line_highlight.push(SubstitutionHighlight {
|
||||
start: (cur_lo.col.0 as isize + acc) as usize,
|
||||
end: (cur_lo.col.0 as isize + acc + len) as usize,
|
||||
});
|
||||
}
|
||||
buf.push_str(&part.snippet);
|
||||
let cur_hi = sm.lookup_char_pos(part.span.hi());
|
||||
// Account for the difference between the width of the current code and the
|
||||
@ -392,7 +398,11 @@ impl CodeSuggestion {
|
||||
while buf.ends_with('\n') {
|
||||
buf.pop();
|
||||
}
|
||||
Some((buf, substitution.parts, highlights, only_capitalization))
|
||||
if highlights.iter().all(|parts| parts.is_empty()) {
|
||||
None
|
||||
} else {
|
||||
Some((buf, substitution.parts, highlights, only_capitalization))
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
@ -145,7 +145,9 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryWraps {
|
||||
(
|
||||
"this function's return value is unnecessary".to_string(),
|
||||
"remove the return type...".to_string(),
|
||||
snippet(cx, fn_decl.output.span(), "..").to_string(),
|
||||
// FIXME: we should instead get the span including the `->` and suggest an
|
||||
// empty string for this case.
|
||||
"()".to_string(),
|
||||
"...and then remove returned values",
|
||||
)
|
||||
} else {
|
||||
|
@ -63,7 +63,7 @@ LL | let _val = None::<()>.expect("this always happens");
|
||||
help: remove the `None` and `expect()`
|
||||
|
|
||||
LL | let _val = panic!("this always happens");
|
||||
| ~~~~~~~ ~
|
||||
| ~~~~~~~
|
||||
|
||||
error: used `unwrap_or_default()` on `None` value
|
||||
--> tests/ui/unnecessary_literal_unwrap.rs:22:24
|
||||
@ -134,7 +134,7 @@ LL | None::<()>.expect("this always happens");
|
||||
help: remove the `None` and `expect()`
|
||||
|
|
||||
LL | panic!("this always happens");
|
||||
| ~~~~~~~ ~
|
||||
| ~~~~~~~
|
||||
|
||||
error: used `unwrap_or_default()` on `None` value
|
||||
--> tests/ui/unnecessary_literal_unwrap.rs:30:5
|
||||
|
@ -118,8 +118,8 @@ LL | | }
|
||||
|
|
||||
help: remove the return type...
|
||||
|
|
||||
LL | fn issue_6640_1(a: bool, b: bool) -> Option<()> {
|
||||
| ~~~~~~~~~~
|
||||
LL | fn issue_6640_1(a: bool, b: bool) -> () {
|
||||
| ~~
|
||||
help: ...and then remove returned values
|
||||
|
|
||||
LL ~ return ;
|
||||
@ -145,8 +145,8 @@ LL | | }
|
||||
|
|
||||
help: remove the return type...
|
||||
|
|
||||
LL | fn issue_6640_2(a: bool, b: bool) -> Result<(), i32> {
|
||||
| ~~~~~~~~~~~~~~~
|
||||
LL | fn issue_6640_2(a: bool, b: bool) -> () {
|
||||
| ~~
|
||||
help: ...and then remove returned values
|
||||
|
|
||||
LL ~ return ;
|
||||
|
@ -4,10 +4,6 @@ error[E0282]: type annotations needed
|
||||
LL | Combination::<0>.and::<_>().and::<_>();
|
||||
| ^^^ cannot infer type of the type parameter `M` declared on the method `and`
|
||||
|
|
||||
help: consider specifying the generic argument
|
||||
|
|
||||
LL | Combination::<0>.and::<_>().and::<_>();
|
||||
| ~~~~~
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
@ -24,10 +24,6 @@ note: ...and refers to the struct `ParseOptions` which is defined here
|
||||
|
|
||||
LL | pub struct ParseOptions {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ you could import this directly
|
||||
help: import `ParseOptions` through the re-export
|
||||
|
|
||||
LL | pub use parser::ParseOptions;
|
||||
| ~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
@ -74,7 +74,7 @@ LL | let _ = PartialEq::eq(&a, &b);
|
||||
help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
|
||||
|
|
||||
LL | let _ = std::ptr::addr_eq(a, b);
|
||||
| ~~~~~~~~~~~~~~~~~~ ~ ~
|
||||
| ~~~~~~~~~~~~~~~~~~ ~
|
||||
|
||||
warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
|
||||
--> $DIR/wide_pointer_comparisons.rs:35:13
|
||||
@ -85,7 +85,7 @@ LL | let _ = PartialEq::ne(&a, &b);
|
||||
help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
|
||||
|
|
||||
LL | let _ = !std::ptr::addr_eq(a, b);
|
||||
| ~~~~~~~~~~~~~~~~~~~ ~ ~
|
||||
| ~~~~~~~~~~~~~~~~~~~ ~
|
||||
|
||||
warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
|
||||
--> $DIR/wide_pointer_comparisons.rs:37:13
|
||||
@ -96,7 +96,7 @@ LL | let _ = a.eq(&b);
|
||||
help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
|
||||
|
|
||||
LL | let _ = std::ptr::addr_eq(a, b);
|
||||
| ++++++++++++++++++ ~ ~
|
||||
| ++++++++++++++++++ ~
|
||||
|
||||
warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
|
||||
--> $DIR/wide_pointer_comparisons.rs:39:13
|
||||
@ -107,7 +107,7 @@ LL | let _ = a.ne(&b);
|
||||
help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
|
||||
|
|
||||
LL | let _ = !std::ptr::addr_eq(a, b);
|
||||
| +++++++++++++++++++ ~ ~
|
||||
| +++++++++++++++++++ ~
|
||||
|
||||
warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
|
||||
--> $DIR/wide_pointer_comparisons.rs:41:13
|
||||
@ -283,7 +283,7 @@ LL | let _ = PartialEq::eq(a, b);
|
||||
help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
|
||||
|
|
||||
LL | let _ = std::ptr::addr_eq(*a, *b);
|
||||
| ~~~~~~~~~~~~~~~~~~~ ~~~ ~
|
||||
| ~~~~~~~~~~~~~~~~~~~ ~~~
|
||||
|
||||
warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
|
||||
--> $DIR/wide_pointer_comparisons.rs:85:17
|
||||
@ -294,7 +294,7 @@ LL | let _ = PartialEq::ne(a, b);
|
||||
help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
|
||||
|
|
||||
LL | let _ = !std::ptr::addr_eq(*a, *b);
|
||||
| ~~~~~~~~~~~~~~~~~~~~ ~~~ ~
|
||||
| ~~~~~~~~~~~~~~~~~~~~ ~~~
|
||||
|
||||
warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
|
||||
--> $DIR/wide_pointer_comparisons.rs:87:17
|
||||
@ -305,7 +305,7 @@ LL | let _ = PartialEq::eq(&a, &b);
|
||||
help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
|
||||
|
|
||||
LL | let _ = std::ptr::addr_eq(*a, *b);
|
||||
| ~~~~~~~~~~~~~~~~~~~ ~~~ ~
|
||||
| ~~~~~~~~~~~~~~~~~~~ ~~~
|
||||
|
||||
warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
|
||||
--> $DIR/wide_pointer_comparisons.rs:89:17
|
||||
@ -316,7 +316,7 @@ LL | let _ = PartialEq::ne(&a, &b);
|
||||
help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
|
||||
|
|
||||
LL | let _ = !std::ptr::addr_eq(*a, *b);
|
||||
| ~~~~~~~~~~~~~~~~~~~~ ~~~ ~
|
||||
| ~~~~~~~~~~~~~~~~~~~~ ~~~
|
||||
|
||||
warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
|
||||
--> $DIR/wide_pointer_comparisons.rs:91:17
|
||||
@ -327,7 +327,7 @@ LL | let _ = a.eq(b);
|
||||
help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
|
||||
|
|
||||
LL | let _ = std::ptr::addr_eq(*a, *b);
|
||||
| +++++++++++++++++++ ~~~ ~
|
||||
| +++++++++++++++++++ ~~~
|
||||
|
||||
warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
|
||||
--> $DIR/wide_pointer_comparisons.rs:93:17
|
||||
@ -338,7 +338,7 @@ LL | let _ = a.ne(b);
|
||||
help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
|
||||
|
|
||||
LL | let _ = !std::ptr::addr_eq(*a, *b);
|
||||
| ++++++++++++++++++++ ~~~ ~
|
||||
| ++++++++++++++++++++ ~~~
|
||||
|
||||
warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
|
||||
--> $DIR/wide_pointer_comparisons.rs:95:17
|
||||
@ -519,11 +519,11 @@ LL | let _ = PartialEq::eq(&a, &b);
|
||||
help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
|
||||
|
|
||||
LL | let _ = std::ptr::addr_eq(a, b);
|
||||
| ~~~~~~~~~~~~~~~~~~ ~ ~
|
||||
| ~~~~~~~~~~~~~~~~~~ ~
|
||||
help: use explicit `std::ptr::eq` method to compare metadata and addresses
|
||||
|
|
||||
LL | let _ = std::ptr::eq(a, b);
|
||||
| ~~~~~~~~~~~~~ ~ ~
|
||||
| ~~~~~~~~~~~~~ ~
|
||||
|
||||
warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
|
||||
--> $DIR/wide_pointer_comparisons.rs:133:17
|
||||
@ -534,11 +534,11 @@ LL | let _ = PartialEq::ne(&a, &b);
|
||||
help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
|
||||
|
|
||||
LL | let _ = !std::ptr::addr_eq(a, b);
|
||||
| ~~~~~~~~~~~~~~~~~~~ ~ ~
|
||||
| ~~~~~~~~~~~~~~~~~~~ ~
|
||||
help: use explicit `std::ptr::eq` method to compare metadata and addresses
|
||||
|
|
||||
LL | let _ = !std::ptr::eq(a, b);
|
||||
| ~~~~~~~~~~~~~~ ~ ~
|
||||
| ~~~~~~~~~~~~~~ ~
|
||||
|
||||
warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
|
||||
--> $DIR/wide_pointer_comparisons.rs:135:17
|
||||
@ -549,11 +549,11 @@ LL | let _ = a.eq(&b);
|
||||
help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
|
||||
|
|
||||
LL | let _ = std::ptr::addr_eq(a, b);
|
||||
| ++++++++++++++++++ ~ ~
|
||||
| ++++++++++++++++++ ~
|
||||
help: use explicit `std::ptr::eq` method to compare metadata and addresses
|
||||
|
|
||||
LL | let _ = std::ptr::eq(a, b);
|
||||
| +++++++++++++ ~ ~
|
||||
| +++++++++++++ ~
|
||||
|
||||
warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
|
||||
--> $DIR/wide_pointer_comparisons.rs:137:17
|
||||
@ -564,11 +564,11 @@ LL | let _ = a.ne(&b);
|
||||
help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
|
||||
|
|
||||
LL | let _ = !std::ptr::addr_eq(a, b);
|
||||
| +++++++++++++++++++ ~ ~
|
||||
| +++++++++++++++++++ ~
|
||||
help: use explicit `std::ptr::eq` method to compare metadata and addresses
|
||||
|
|
||||
LL | let _ = !std::ptr::eq(a, b);
|
||||
| ++++++++++++++ ~ ~
|
||||
| ++++++++++++++ ~
|
||||
|
||||
warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
|
||||
--> $DIR/wide_pointer_comparisons.rs:142:9
|
||||
@ -594,7 +594,7 @@ LL | cmp!(a, b);
|
||||
help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
|
||||
|
|
||||
LL | cmp!(std::ptr::addr_eq(a, b));
|
||||
| ++++++++++++++++++ ~ +
|
||||
| ++++++++++++++++++ +
|
||||
|
||||
warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
|
||||
--> $DIR/wide_pointer_comparisons.rs:159:39
|
||||
|
@ -14,7 +14,7 @@ LL | let Bar(x, y, Foo(z)) = make_bar();
|
||||
help: consider making the fields publicly accessible
|
||||
|
|
||||
LL | pub(crate) struct Bar(pub u8, pub u8, pub Foo);
|
||||
| ~~~ ~~~ +++
|
||||
| ~~~ +++
|
||||
|
||||
error[E0532]: cannot match against a tuple struct which contains private fields
|
||||
--> $DIR/issue-75907.rs:15:19
|
||||
|
@ -53,7 +53,7 @@ LL | pub struct C(pub isize, isize);
|
||||
help: consider making the fields publicly accessible
|
||||
|
|
||||
LL | pub struct C(pub isize, pub isize);
|
||||
| ~~~ +++
|
||||
| +++
|
||||
|
||||
error[E0603]: tuple struct constructor `A` is private
|
||||
--> $DIR/privacy5.rs:56:12
|
||||
@ -262,7 +262,7 @@ LL | pub struct C(pub isize, isize);
|
||||
help: consider making the fields publicly accessible
|
||||
|
|
||||
LL | pub struct C(pub isize, pub isize);
|
||||
| ~~~ +++
|
||||
| +++
|
||||
|
||||
error[E0603]: tuple struct constructor `C` is private
|
||||
--> $DIR/privacy5.rs:69:12
|
||||
@ -281,7 +281,7 @@ LL | pub struct C(pub isize, isize);
|
||||
help: consider making the fields publicly accessible
|
||||
|
|
||||
LL | pub struct C(pub isize, pub isize);
|
||||
| ~~~ +++
|
||||
| +++
|
||||
|
||||
error[E0603]: tuple struct constructor `C` is private
|
||||
--> $DIR/privacy5.rs:70:12
|
||||
@ -300,7 +300,7 @@ LL | pub struct C(pub isize, isize);
|
||||
help: consider making the fields publicly accessible
|
||||
|
|
||||
LL | pub struct C(pub isize, pub isize);
|
||||
| ~~~ +++
|
||||
| +++
|
||||
|
||||
error[E0603]: tuple struct constructor `C` is private
|
||||
--> $DIR/privacy5.rs:71:12
|
||||
@ -319,7 +319,7 @@ LL | pub struct C(pub isize, isize);
|
||||
help: consider making the fields publicly accessible
|
||||
|
|
||||
LL | pub struct C(pub isize, pub isize);
|
||||
| ~~~ +++
|
||||
| +++
|
||||
|
||||
error[E0603]: tuple struct constructor `C` is private
|
||||
--> $DIR/privacy5.rs:72:18
|
||||
@ -338,7 +338,7 @@ LL | pub struct C(pub isize, isize);
|
||||
help: consider making the fields publicly accessible
|
||||
|
|
||||
LL | pub struct C(pub isize, pub isize);
|
||||
| ~~~ +++
|
||||
| +++
|
||||
|
||||
error[E0603]: tuple struct constructor `C` is private
|
||||
--> $DIR/privacy5.rs:73:18
|
||||
@ -357,7 +357,7 @@ LL | pub struct C(pub isize, isize);
|
||||
help: consider making the fields publicly accessible
|
||||
|
|
||||
LL | pub struct C(pub isize, pub isize);
|
||||
| ~~~ +++
|
||||
| +++
|
||||
|
||||
error[E0603]: tuple struct constructor `C` is private
|
||||
--> $DIR/privacy5.rs:74:18
|
||||
@ -376,7 +376,7 @@ LL | pub struct C(pub isize, isize);
|
||||
help: consider making the fields publicly accessible
|
||||
|
|
||||
LL | pub struct C(pub isize, pub isize);
|
||||
| ~~~ +++
|
||||
| +++
|
||||
|
||||
error[E0603]: tuple struct constructor `C` is private
|
||||
--> $DIR/privacy5.rs:75:18
|
||||
@ -395,7 +395,7 @@ LL | pub struct C(pub isize, isize);
|
||||
help: consider making the fields publicly accessible
|
||||
|
|
||||
LL | pub struct C(pub isize, pub isize);
|
||||
| ~~~ +++
|
||||
| +++
|
||||
|
||||
error[E0603]: tuple struct constructor `A` is private
|
||||
--> $DIR/privacy5.rs:83:17
|
||||
@ -452,7 +452,7 @@ LL | pub struct C(pub isize, isize);
|
||||
help: consider making the fields publicly accessible
|
||||
|
|
||||
LL | pub struct C(pub isize, pub isize);
|
||||
| ~~~ +++
|
||||
| +++
|
||||
|
||||
error[E0603]: tuple struct constructor `A` is private
|
||||
--> $DIR/privacy5.rs:90:20
|
||||
|
@ -17,10 +17,6 @@ error[E0282]: type annotations needed
|
||||
LL | .sum::<_>()
|
||||
| ^^^ cannot infer type of the type parameter `S` declared on the method `sum`
|
||||
|
|
||||
help: consider specifying the generic argument
|
||||
|
|
||||
LL | .sum::<_>()
|
||||
| ~~~~~
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -40,7 +40,7 @@ LL | let _ = vec![1, 2, 3].into_iter().collect::Vec<_>>();
|
||||
help: surround the type parameters with angle brackets
|
||||
|
|
||||
LL | let _ = vec![1, 2, 3].into_iter().collect::<Vec<_>>();
|
||||
| + ~
|
||||
| +
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user