Do not manually craft a span pointing inside a multibyte character.
This commit is contained in:
parent
55f46419af
commit
db7ddc50b6
@ -11,7 +11,7 @@
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_span::symbol::Symbol;
|
||||
use rustc_span::symbol::{kw, sym};
|
||||
use rustc_span::{BytePos, Span, DUMMY_SP};
|
||||
use rustc_span::{BytePos, Span};
|
||||
|
||||
declare_lint! {
|
||||
/// The `unused_must_use` lint detects unused result of a type flagged as
|
||||
@ -504,23 +504,23 @@ fn emit_unused_delims_expr(
|
||||
ast::ExprKind::Block(ref block, None) if block.stmts.len() > 0 => {
|
||||
let start = block.stmts[0].span;
|
||||
let end = block.stmts[block.stmts.len() - 1].span;
|
||||
if value.span.from_expansion() || start.from_expansion() || end.from_expansion() {
|
||||
(
|
||||
value.span.with_hi(value.span.lo() + BytePos(1)),
|
||||
value.span.with_lo(value.span.hi() - BytePos(1)),
|
||||
)
|
||||
if let Some(start) = start.find_ancestor_inside(value.span)
|
||||
&& let Some(end) = end.find_ancestor_inside(value.span)
|
||||
{
|
||||
Some((
|
||||
value.span.with_hi(start.lo()),
|
||||
value.span.with_lo(end.hi()),
|
||||
))
|
||||
} else {
|
||||
(value.span.with_hi(start.lo()), value.span.with_lo(end.hi()))
|
||||
None
|
||||
}
|
||||
}
|
||||
ast::ExprKind::Paren(ref expr) => {
|
||||
if value.span.from_expansion() || expr.span.from_expansion() {
|
||||
(
|
||||
value.span.with_hi(value.span.lo() + BytePos(1)),
|
||||
value.span.with_lo(value.span.hi() - BytePos(1)),
|
||||
)
|
||||
let expr_span = expr.span.find_ancestor_inside(value.span);
|
||||
if let Some(expr_span) = expr_span {
|
||||
Some((value.span.with_hi(expr_span.lo()), value.span.with_lo(expr_span.hi())))
|
||||
} else {
|
||||
(value.span.with_hi(expr.span.lo()), value.span.with_lo(expr.span.hi()))
|
||||
None
|
||||
}
|
||||
}
|
||||
_ => return,
|
||||
@ -529,36 +529,38 @@ fn emit_unused_delims_expr(
|
||||
left_pos.map_or(false, |s| s >= value.span.lo()),
|
||||
right_pos.map_or(false, |s| s <= value.span.hi()),
|
||||
);
|
||||
self.emit_unused_delims(cx, spans, ctx.into(), keep_space);
|
||||
self.emit_unused_delims(cx, value.span, spans, ctx.into(), keep_space);
|
||||
}
|
||||
|
||||
fn emit_unused_delims(
|
||||
&self,
|
||||
cx: &EarlyContext<'_>,
|
||||
spans: (Span, Span),
|
||||
value_span: Span,
|
||||
spans: Option<(Span, Span)>,
|
||||
msg: &str,
|
||||
keep_space: (bool, bool),
|
||||
) {
|
||||
// FIXME(flip1995): Quick and dirty fix for #70814. This should be fixed in rustdoc
|
||||
// properly.
|
||||
if spans.0 == DUMMY_SP || spans.1 == DUMMY_SP {
|
||||
return;
|
||||
}
|
||||
|
||||
cx.struct_span_lint(self.lint(), MultiSpan::from(vec![spans.0, spans.1]), |lint| {
|
||||
let primary_span = if let Some((lo, hi)) = spans {
|
||||
MultiSpan::from(vec![lo, hi])
|
||||
} else {
|
||||
MultiSpan::from(value_span)
|
||||
};
|
||||
cx.struct_span_lint(self.lint(), primary_span, |lint| {
|
||||
let mut db = lint.build(fluent::lint::unused_delim);
|
||||
db.set_arg("delim", Self::DELIM_STR);
|
||||
db.set_arg("item", msg);
|
||||
if let Some((lo, hi)) = spans {
|
||||
let replacement = vec![
|
||||
(spans.0, if keep_space.0 { " ".into() } else { "".into() }),
|
||||
(spans.1, if keep_space.1 { " ".into() } else { "".into() }),
|
||||
(lo, if keep_space.0 { " ".into() } else { "".into() }),
|
||||
(hi, if keep_space.1 { " ".into() } else { "".into() }),
|
||||
];
|
||||
lint.build(fluent::lint::unused_delim)
|
||||
.set_arg("delim", Self::DELIM_STR)
|
||||
.set_arg("item", msg)
|
||||
.multipart_suggestion(
|
||||
db.multipart_suggestion(
|
||||
fluent::lint::suggestion,
|
||||
replacement,
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.emit();
|
||||
);
|
||||
}
|
||||
db.emit();
|
||||
});
|
||||
}
|
||||
|
||||
@ -766,15 +768,12 @@ fn check_unused_parens_pat(
|
||||
// Otherwise proceed with linting.
|
||||
_ => {}
|
||||
}
|
||||
let spans = if value.span.from_expansion() || inner.span.from_expansion() {
|
||||
(
|
||||
value.span.with_hi(value.span.lo() + BytePos(1)),
|
||||
value.span.with_lo(value.span.hi() - BytePos(1)),
|
||||
)
|
||||
let spans = if let Some(inner) = inner.span.find_ancestor_inside(value.span) {
|
||||
Some((value.span.with_hi(inner.lo()), value.span.with_lo(inner.hi())))
|
||||
} else {
|
||||
(value.span.with_hi(inner.span.lo()), value.span.with_lo(inner.span.hi()))
|
||||
None
|
||||
};
|
||||
self.emit_unused_delims(cx, spans, "pattern", (false, false));
|
||||
self.emit_unused_delims(cx, value.span, spans, "pattern", (false, false));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -879,15 +878,12 @@ fn check_ty(&mut self, cx: &EarlyContext<'_>, ty: &ast::Ty) {
|
||||
);
|
||||
}
|
||||
_ => {
|
||||
let spans = if ty.span.from_expansion() || r.span.from_expansion() {
|
||||
(
|
||||
ty.span.with_hi(ty.span.lo() + BytePos(1)),
|
||||
ty.span.with_lo(ty.span.hi() - BytePos(1)),
|
||||
)
|
||||
let spans = if let Some(r) = r.span.find_ancestor_inside(ty.span) {
|
||||
Some((ty.span.with_hi(r.lo()), ty.span.with_lo(r.hi())))
|
||||
} else {
|
||||
(ty.span.with_hi(r.span.lo()), ty.span.with_lo(r.span.hi()))
|
||||
None
|
||||
};
|
||||
self.emit_unused_delims(cx, spans, "type", (false, false));
|
||||
self.emit_unused_delims(cx, ty.span, spans, "type", (false, false));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
11
src/test/ui/lint/unused_parens_multibyte_recovery.rs
Normal file
11
src/test/ui/lint/unused_parens_multibyte_recovery.rs
Normal file
@ -0,0 +1,11 @@
|
||||
// ignore-tidy-trailing-newlines
|
||||
//
|
||||
// error-pattern: this file contains an unclosed delimiter
|
||||
// error-pattern: this file contains an unclosed delimiter
|
||||
// error-pattern: this file contains an unclosed delimiter
|
||||
// error-pattern: format argument must be a string literal
|
||||
//
|
||||
// Verify that unused parens lint does not try to create a span
|
||||
// which points in the middle of a multibyte character.
|
||||
|
||||
fn f(){(print!(á
|
43
src/test/ui/lint/unused_parens_multibyte_recovery.stderr
Normal file
43
src/test/ui/lint/unused_parens_multibyte_recovery.stderr
Normal file
@ -0,0 +1,43 @@
|
||||
error: this file contains an unclosed delimiter
|
||||
--> $DIR/unused_parens_multibyte_recovery.rs:11:17
|
||||
|
|
||||
LL | fn f(){(print!(á
|
||||
| -- - ^
|
||||
| || |
|
||||
| || unclosed delimiter
|
||||
| |unclosed delimiter
|
||||
| unclosed delimiter
|
||||
|
||||
error: this file contains an unclosed delimiter
|
||||
--> $DIR/unused_parens_multibyte_recovery.rs:11:17
|
||||
|
|
||||
LL | fn f(){(print!(á
|
||||
| -- - ^
|
||||
| || |
|
||||
| || unclosed delimiter
|
||||
| |unclosed delimiter
|
||||
| unclosed delimiter
|
||||
|
||||
error: this file contains an unclosed delimiter
|
||||
--> $DIR/unused_parens_multibyte_recovery.rs:11:17
|
||||
|
|
||||
LL | fn f(){(print!(á
|
||||
| -- - ^
|
||||
| || |
|
||||
| || unclosed delimiter
|
||||
| |unclosed delimiter
|
||||
| unclosed delimiter
|
||||
|
||||
error: format argument must be a string literal
|
||||
--> $DIR/unused_parens_multibyte_recovery.rs:11:16
|
||||
|
|
||||
LL | fn f(){(print!(á
|
||||
| ^
|
||||
|
|
||||
help: you might be missing a string literal to format with
|
||||
|
|
||||
LL | fn f(){(print!("{}", á
|
||||
| +++++
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
Loading…
Reference in New Issue
Block a user