Rollup merge of #100226 - cjgillot:noice-multibyte, r=davidtwco
Do not manually craft a span pointing inside a multibyte character. Fixes https://github.com/rust-lang/rust/issues/92462
This commit is contained in:
commit
e6c9594213
3 changed files with 96 additions and 46 deletions
|
@ -11,7 +11,7 @@ use rustc_middle::ty::adjustment;
|
||||||
use rustc_middle::ty::{self, Ty};
|
use rustc_middle::ty::{self, Ty};
|
||||||
use rustc_span::symbol::Symbol;
|
use rustc_span::symbol::Symbol;
|
||||||
use rustc_span::symbol::{kw, sym};
|
use rustc_span::symbol::{kw, sym};
|
||||||
use rustc_span::{BytePos, Span, DUMMY_SP};
|
use rustc_span::{BytePos, Span};
|
||||||
|
|
||||||
declare_lint! {
|
declare_lint! {
|
||||||
/// The `unused_must_use` lint detects unused result of a type flagged as
|
/// The `unused_must_use` lint detects unused result of a type flagged as
|
||||||
|
@ -504,23 +504,23 @@ trait UnusedDelimLint {
|
||||||
ast::ExprKind::Block(ref block, None) if block.stmts.len() > 0 => {
|
ast::ExprKind::Block(ref block, None) if block.stmts.len() > 0 => {
|
||||||
let start = block.stmts[0].span;
|
let start = block.stmts[0].span;
|
||||||
let end = block.stmts[block.stmts.len() - 1].span;
|
let end = block.stmts[block.stmts.len() - 1].span;
|
||||||
if value.span.from_expansion() || start.from_expansion() || end.from_expansion() {
|
if let Some(start) = start.find_ancestor_inside(value.span)
|
||||||
(
|
&& let Some(end) = end.find_ancestor_inside(value.span)
|
||||||
value.span.with_hi(value.span.lo() + BytePos(1)),
|
{
|
||||||
value.span.with_lo(value.span.hi() - BytePos(1)),
|
Some((
|
||||||
)
|
value.span.with_hi(start.lo()),
|
||||||
|
value.span.with_lo(end.hi()),
|
||||||
|
))
|
||||||
} else {
|
} else {
|
||||||
(value.span.with_hi(start.lo()), value.span.with_lo(end.hi()))
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::ExprKind::Paren(ref expr) => {
|
ast::ExprKind::Paren(ref expr) => {
|
||||||
if value.span.from_expansion() || expr.span.from_expansion() {
|
let expr_span = expr.span.find_ancestor_inside(value.span);
|
||||||
(
|
if let Some(expr_span) = expr_span {
|
||||||
value.span.with_hi(value.span.lo() + BytePos(1)),
|
Some((value.span.with_hi(expr_span.lo()), value.span.with_lo(expr_span.hi())))
|
||||||
value.span.with_lo(value.span.hi() - BytePos(1)),
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
(value.span.with_hi(expr.span.lo()), value.span.with_lo(expr.span.hi()))
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => return,
|
_ => return,
|
||||||
|
@ -529,36 +529,38 @@ trait UnusedDelimLint {
|
||||||
left_pos.map_or(false, |s| s >= value.span.lo()),
|
left_pos.map_or(false, |s| s >= value.span.lo()),
|
||||||
right_pos.map_or(false, |s| s <= value.span.hi()),
|
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(
|
fn emit_unused_delims(
|
||||||
&self,
|
&self,
|
||||||
cx: &EarlyContext<'_>,
|
cx: &EarlyContext<'_>,
|
||||||
spans: (Span, Span),
|
value_span: Span,
|
||||||
|
spans: Option<(Span, Span)>,
|
||||||
msg: &str,
|
msg: &str,
|
||||||
keep_space: (bool, bool),
|
keep_space: (bool, bool),
|
||||||
) {
|
) {
|
||||||
// FIXME(flip1995): Quick and dirty fix for #70814. This should be fixed in rustdoc
|
let primary_span = if let Some((lo, hi)) = spans {
|
||||||
// properly.
|
MultiSpan::from(vec![lo, hi])
|
||||||
if spans.0 == DUMMY_SP || spans.1 == DUMMY_SP {
|
} else {
|
||||||
return;
|
MultiSpan::from(value_span)
|
||||||
}
|
};
|
||||||
|
cx.struct_span_lint(self.lint(), primary_span, |lint| {
|
||||||
cx.struct_span_lint(self.lint(), MultiSpan::from(vec![spans.0, spans.1]), |lint| {
|
let mut db = lint.build(fluent::lint::unused_delim);
|
||||||
let replacement = vec![
|
db.set_arg("delim", Self::DELIM_STR);
|
||||||
(spans.0, if keep_space.0 { " ".into() } else { "".into() }),
|
db.set_arg("item", msg);
|
||||||
(spans.1, if keep_space.1 { " ".into() } else { "".into() }),
|
if let Some((lo, hi)) = spans {
|
||||||
];
|
let replacement = vec![
|
||||||
lint.build(fluent::lint::unused_delim)
|
(lo, if keep_space.0 { " ".into() } else { "".into() }),
|
||||||
.set_arg("delim", Self::DELIM_STR)
|
(hi, if keep_space.1 { " ".into() } else { "".into() }),
|
||||||
.set_arg("item", msg)
|
];
|
||||||
.multipart_suggestion(
|
db.multipart_suggestion(
|
||||||
fluent::lint::suggestion,
|
fluent::lint::suggestion,
|
||||||
replacement,
|
replacement,
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
)
|
);
|
||||||
.emit();
|
}
|
||||||
|
db.emit();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -766,15 +768,12 @@ impl UnusedParens {
|
||||||
// Otherwise proceed with linting.
|
// Otherwise proceed with linting.
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
let spans = if value.span.from_expansion() || inner.span.from_expansion() {
|
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())))
|
||||||
value.span.with_hi(value.span.lo() + BytePos(1)),
|
|
||||||
value.span.with_lo(value.span.hi() - BytePos(1)),
|
|
||||||
)
|
|
||||||
} else {
|
} 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 @@ impl EarlyLintPass for UnusedParens {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let spans = if ty.span.from_expansion() || r.span.from_expansion() {
|
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())))
|
||||||
ty.span.with_hi(ty.span.lo() + BytePos(1)),
|
|
||||||
ty.span.with_lo(ty.span.hi() - BytePos(1)),
|
|
||||||
)
|
|
||||||
} else {
|
} 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…
Add table
Reference in a new issue