Skip to content

Commit

Permalink
Implement assertions and fixes to not emit empty spans without sugges…
Browse files Browse the repository at this point in the history
…tions
  • Loading branch information
kper committed Oct 20, 2022
1 parent 4b8f431 commit 28d0312
Show file tree
Hide file tree
Showing 8 changed files with 81 additions and 117 deletions.
25 changes: 25 additions & 0 deletions compiler/rustc_errors/src/diagnostic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,11 @@ impl Diagnostic {
style: SuggestionStyle,
) -> &mut Self {
assert!(!suggestion.is_empty());
debug_assert!(
!(suggestion.iter().any(|(sp, text)| sp.is_empty() && text.is_empty())),
"Span must not be empty and have no suggestion"
);

self.push_suggestion(CodeSuggestion {
substitutions: vec![Substitution {
parts: suggestion
Expand Down Expand Up @@ -644,6 +649,10 @@ impl Diagnostic {
applicability: Applicability,
style: SuggestionStyle,
) -> &mut Self {
debug_assert!(
!(sp.is_empty() && suggestion.to_string().is_empty()),
"Span must not be empty and have no suggestion"
);
self.push_suggestion(CodeSuggestion {
substitutions: vec![Substitution {
parts: vec![SubstitutionPart { snippet: suggestion.to_string(), span: sp }],
Expand Down Expand Up @@ -684,6 +693,12 @@ impl Diagnostic {
) -> &mut Self {
let mut suggestions: Vec<_> = suggestions.collect();
suggestions.sort();

debug_assert!(
!(sp.is_empty() && suggestions.iter().any(|suggestion| suggestion.is_empty())),
"Span must not be empty and have no suggestion"
);

let substitutions = suggestions
.into_iter()
.map(|snippet| Substitution { parts: vec![SubstitutionPart { snippet, span: sp }] })
Expand All @@ -705,8 +720,18 @@ impl Diagnostic {
suggestions: impl Iterator<Item = Vec<(Span, String)>>,
applicability: Applicability,
) -> &mut Self {
let suggestions: Vec<_> = suggestions.collect();
debug_assert!(
!(suggestions
.iter()
.flat_map(|suggs| suggs)
.any(|(sp, suggestion)| sp.is_empty() && suggestion.is_empty())),
"Span must not be empty and have no suggestion"
);

self.push_suggestion(CodeSuggestion {
substitutions: suggestions
.into_iter()
.map(|sugg| Substitution {
parts: sugg
.into_iter()
Expand Down
5 changes: 3 additions & 2 deletions compiler/rustc_expand/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use rustc_span::edition::Edition;
use rustc_span::hygiene::{AstPass, ExpnData, ExpnKind, LocalExpnId};
use rustc_span::source_map::SourceMap;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{FileName, Span, DUMMY_SP};
use rustc_span::{BytePos, FileName, Span, DUMMY_SP};
use smallvec::{smallvec, SmallVec};

use std::default::Default;
Expand Down Expand Up @@ -1228,8 +1228,9 @@ pub fn expr_to_spanned_string<'a>(
ast::LitKind::Str(s, style) => return Ok((s, style, expr.span)),
ast::LitKind::ByteStr(_) => {
let mut err = cx.struct_span_err(l.span, err_msg);
let span = expr.span.shrink_to_lo();
err.span_suggestion(
expr.span.shrink_to_lo(),
span.with_hi(span.lo() + BytePos(1)),
"consider removing the leading `b`",
"",
Applicability::MaybeIncorrect,
Expand Down
25 changes: 14 additions & 11 deletions compiler/rustc_hir_analysis/src/astconv/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3051,24 +3051,27 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
.map_or(false, |s| s.trim_end().ends_with('<'));

let is_global = poly_trait_ref.trait_ref.path.is_global();
let sugg = Vec::from_iter([
(
self_ty.span.shrink_to_lo(),
format!(
"{}dyn {}",
if needs_bracket { "<" } else { "" },
if is_global { "(" } else { "" },
),

let mut sugg = Vec::from_iter([(
self_ty.span.shrink_to_lo(),
format!(
"{}dyn {}",
if needs_bracket { "<" } else { "" },
if is_global { "(" } else { "" },
),
(
)]);

if is_global || needs_bracket {
sugg.push((
self_ty.span.shrink_to_hi(),
format!(
"{}{}",
if is_global { ")" } else { "" },
if needs_bracket { ">" } else { "" },
),
),
]);
));
}

if self_ty.span.edition() >= Edition::Edition2021 {
let msg = "trait objects must include the `dyn` keyword";
let label = "add `dyn` keyword before this trait";
Expand Down
10 changes: 9 additions & 1 deletion compiler/rustc_parse/src/parser/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1374,9 +1374,17 @@ impl<'a> Parser<'a> {
kind: IncDecRecovery,
(pre_span, post_span): (Span, Span),
) -> MultiSugg {
let mut patches = Vec::new();

if !pre_span.is_empty() {
patches.push((pre_span, String::new()));
}

patches.push((post_span, format!(" {}= 1", kind.op.chr())));

MultiSugg {
msg: format!("use `{}= 1` instead", kind.op.chr()),
patches: vec![(pre_span, String::new()), (post_span, format!(" {}= 1", kind.op.chr()))],
patches,
applicability: Applicability::MachineApplicable,
}
}
Expand Down
12 changes: 7 additions & 5 deletions src/tools/clippy/clippy_lints/src/manual_assert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,13 @@ impl<'tcx> LateLintPass<'tcx> for ManualAssert {
"only a `panic!` in `if`-then statement",
|diag| {
// comments can be noisy, do not show them to the user
diag.tool_only_span_suggestion(
expr.span.shrink_to_lo(),
"add comments back",
comments,
applicability);
if !comments.is_empty() {
diag.tool_only_span_suggestion(
expr.span.shrink_to_lo(),
"add comments back",
comments,
applicability);
}
diag.span_suggestion(
expr.span,
"try instead",
Expand Down
11 changes: 7 additions & 4 deletions src/tools/clippy/clippy_lints/src/needless_late_init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,10 +180,13 @@ fn assignment_suggestions<'tcx>(
let suggestions = assignments
.iter()
.flat_map(|assignment| {
[
assignment.span.until(assignment.rhs_span),
assignment.rhs_span.shrink_to_hi().with_hi(assignment.span.hi()),
]
let mut spans = vec![assignment.span.until(assignment.rhs_span)];

if assignment.rhs_span.hi() != assignment.span.hi() {
spans.push(assignment.rhs_span.shrink_to_hi().with_hi(assignment.span.hi()));
}

spans
})
.map(|span| (span, String::new()))
.collect::<Vec<(Span, String)>>();
Expand Down
55 changes: 8 additions & 47 deletions src/tools/clippy/tests/ui/manual_assert.edition2018.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,104 +4,65 @@ error: only a `panic!` in `if`-then statement
LL | / if !a.is_empty() {
LL | | panic!("qaqaq{:?}", a);
LL | | }
| |_____^
| |_____^ help: try instead: `assert!(a.is_empty(), "qaqaq{:?}", a);`
|
= note: `-D clippy::manual-assert` implied by `-D warnings`
help: try instead
|
LL | assert!(a.is_empty(), "qaqaq{:?}", a);
|

error: only a `panic!` in `if`-then statement
--> $DIR/manual_assert.rs:34:5
|
LL | / if !a.is_empty() {
LL | | panic!("qwqwq");
LL | | }
| |_____^
|
help: try instead
|
LL | assert!(a.is_empty(), "qwqwq");
|
| |_____^ help: try instead: `assert!(a.is_empty(), "qwqwq");`

error: only a `panic!` in `if`-then statement
--> $DIR/manual_assert.rs:51:5
|
LL | / if b.is_empty() {
LL | | panic!("panic1");
LL | | }
| |_____^
|
help: try instead
|
LL | assert!(!b.is_empty(), "panic1");
|
| |_____^ help: try instead: `assert!(!b.is_empty(), "panic1");`

error: only a `panic!` in `if`-then statement
--> $DIR/manual_assert.rs:54:5
|
LL | / if b.is_empty() && a.is_empty() {
LL | | panic!("panic2");
LL | | }
| |_____^
|
help: try instead
|
LL | assert!(!(b.is_empty() && a.is_empty()), "panic2");
|
| |_____^ help: try instead: `assert!(!(b.is_empty() && a.is_empty()), "panic2");`

error: only a `panic!` in `if`-then statement
--> $DIR/manual_assert.rs:57:5
|
LL | / if a.is_empty() && !b.is_empty() {
LL | | panic!("panic3");
LL | | }
| |_____^
|
help: try instead
|
LL | assert!(!(a.is_empty() && !b.is_empty()), "panic3");
|
| |_____^ help: try instead: `assert!(!(a.is_empty() && !b.is_empty()), "panic3");`

error: only a `panic!` in `if`-then statement
--> $DIR/manual_assert.rs:60:5
|
LL | / if b.is_empty() || a.is_empty() {
LL | | panic!("panic4");
LL | | }
| |_____^
|
help: try instead
|
LL | assert!(!(b.is_empty() || a.is_empty()), "panic4");
|
| |_____^ help: try instead: `assert!(!(b.is_empty() || a.is_empty()), "panic4");`

error: only a `panic!` in `if`-then statement
--> $DIR/manual_assert.rs:63:5
|
LL | / if a.is_empty() || !b.is_empty() {
LL | | panic!("panic5");
LL | | }
| |_____^
|
help: try instead
|
LL | assert!(!(a.is_empty() || !b.is_empty()), "panic5");
|
| |_____^ help: try instead: `assert!(!(a.is_empty() || !b.is_empty()), "panic5");`

error: only a `panic!` in `if`-then statement
--> $DIR/manual_assert.rs:66:5
|
LL | / if a.is_empty() {
LL | | panic!("with expansion {}", one!())
LL | | }
| |_____^
|
help: try instead
|
LL | assert!(!a.is_empty(), "with expansion {}", one!());
|
| |_____^ help: try instead: `assert!(!a.is_empty(), "with expansion {}", one!());`

error: only a `panic!` in `if`-then statement
--> $DIR/manual_assert.rs:73:5
Expand Down
55 changes: 8 additions & 47 deletions src/tools/clippy/tests/ui/manual_assert.edition2021.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,104 +4,65 @@ error: only a `panic!` in `if`-then statement
LL | / if !a.is_empty() {
LL | | panic!("qaqaq{:?}", a);
LL | | }
| |_____^
| |_____^ help: try instead: `assert!(a.is_empty(), "qaqaq{:?}", a);`
|
= note: `-D clippy::manual-assert` implied by `-D warnings`
help: try instead
|
LL | assert!(a.is_empty(), "qaqaq{:?}", a);
|

error: only a `panic!` in `if`-then statement
--> $DIR/manual_assert.rs:34:5
|
LL | / if !a.is_empty() {
LL | | panic!("qwqwq");
LL | | }
| |_____^
|
help: try instead
|
LL | assert!(a.is_empty(), "qwqwq");
|
| |_____^ help: try instead: `assert!(a.is_empty(), "qwqwq");`

error: only a `panic!` in `if`-then statement
--> $DIR/manual_assert.rs:51:5
|
LL | / if b.is_empty() {
LL | | panic!("panic1");
LL | | }
| |_____^
|
help: try instead
|
LL | assert!(!b.is_empty(), "panic1");
|
| |_____^ help: try instead: `assert!(!b.is_empty(), "panic1");`

error: only a `panic!` in `if`-then statement
--> $DIR/manual_assert.rs:54:5
|
LL | / if b.is_empty() && a.is_empty() {
LL | | panic!("panic2");
LL | | }
| |_____^
|
help: try instead
|
LL | assert!(!(b.is_empty() && a.is_empty()), "panic2");
|
| |_____^ help: try instead: `assert!(!(b.is_empty() && a.is_empty()), "panic2");`

error: only a `panic!` in `if`-then statement
--> $DIR/manual_assert.rs:57:5
|
LL | / if a.is_empty() && !b.is_empty() {
LL | | panic!("panic3");
LL | | }
| |_____^
|
help: try instead
|
LL | assert!(!(a.is_empty() && !b.is_empty()), "panic3");
|
| |_____^ help: try instead: `assert!(!(a.is_empty() && !b.is_empty()), "panic3");`

error: only a `panic!` in `if`-then statement
--> $DIR/manual_assert.rs:60:5
|
LL | / if b.is_empty() || a.is_empty() {
LL | | panic!("panic4");
LL | | }
| |_____^
|
help: try instead
|
LL | assert!(!(b.is_empty() || a.is_empty()), "panic4");
|
| |_____^ help: try instead: `assert!(!(b.is_empty() || a.is_empty()), "panic4");`

error: only a `panic!` in `if`-then statement
--> $DIR/manual_assert.rs:63:5
|
LL | / if a.is_empty() || !b.is_empty() {
LL | | panic!("panic5");
LL | | }
| |_____^
|
help: try instead
|
LL | assert!(!(a.is_empty() || !b.is_empty()), "panic5");
|
| |_____^ help: try instead: `assert!(!(a.is_empty() || !b.is_empty()), "panic5");`

error: only a `panic!` in `if`-then statement
--> $DIR/manual_assert.rs:66:5
|
LL | / if a.is_empty() {
LL | | panic!("with expansion {}", one!())
LL | | }
| |_____^
|
help: try instead
|
LL | assert!(!a.is_empty(), "with expansion {}", one!());
|
| |_____^ help: try instead: `assert!(!a.is_empty(), "with expansion {}", one!());`

error: only a `panic!` in `if`-then statement
--> $DIR/manual_assert.rs:73:5
Expand Down

0 comments on commit 28d0312

Please sign in to comment.