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:
Matthias Krüger 2022-08-10 00:00:29 +02:00 committed by GitHub
commit e6c9594213
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 96 additions and 46 deletions

View file

@ -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));
} }
} }
} }

View 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!(á

View 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