Skip to content

Commit e6c9594

Browse files
authored
Rollup merge of #100226 - cjgillot:noice-multibyte, r=davidtwco
Do not manually craft a span pointing inside a multibyte character. Fixes #92462
2 parents 867453e + db7ddc5 commit e6c9594

File tree

3 files changed

+96
-46
lines changed

3 files changed

+96
-46
lines changed

compiler/rustc_lint/src/unused.rs

+42-46
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use rustc_middle::ty::adjustment;
1111
use rustc_middle::ty::{self, Ty};
1212
use rustc_span::symbol::Symbol;
1313
use rustc_span::symbol::{kw, sym};
14-
use rustc_span::{BytePos, Span, DUMMY_SP};
14+
use rustc_span::{BytePos, Span};
1515

1616
declare_lint! {
1717
/// The `unused_must_use` lint detects unused result of a type flagged as
@@ -504,23 +504,23 @@ trait UnusedDelimLint {
504504
ast::ExprKind::Block(ref block, None) if block.stmts.len() > 0 => {
505505
let start = block.stmts[0].span;
506506
let end = block.stmts[block.stmts.len() - 1].span;
507-
if value.span.from_expansion() || start.from_expansion() || end.from_expansion() {
508-
(
509-
value.span.with_hi(value.span.lo() + BytePos(1)),
510-
value.span.with_lo(value.span.hi() - BytePos(1)),
511-
)
507+
if let Some(start) = start.find_ancestor_inside(value.span)
508+
&& let Some(end) = end.find_ancestor_inside(value.span)
509+
{
510+
Some((
511+
value.span.with_hi(start.lo()),
512+
value.span.with_lo(end.hi()),
513+
))
512514
} else {
513-
(value.span.with_hi(start.lo()), value.span.with_lo(end.hi()))
515+
None
514516
}
515517
}
516518
ast::ExprKind::Paren(ref expr) => {
517-
if value.span.from_expansion() || expr.span.from_expansion() {
518-
(
519-
value.span.with_hi(value.span.lo() + BytePos(1)),
520-
value.span.with_lo(value.span.hi() - BytePos(1)),
521-
)
519+
let expr_span = expr.span.find_ancestor_inside(value.span);
520+
if let Some(expr_span) = expr_span {
521+
Some((value.span.with_hi(expr_span.lo()), value.span.with_lo(expr_span.hi())))
522522
} else {
523-
(value.span.with_hi(expr.span.lo()), value.span.with_lo(expr.span.hi()))
523+
None
524524
}
525525
}
526526
_ => return,
@@ -529,36 +529,38 @@ trait UnusedDelimLint {
529529
left_pos.map_or(false, |s| s >= value.span.lo()),
530530
right_pos.map_or(false, |s| s <= value.span.hi()),
531531
);
532-
self.emit_unused_delims(cx, spans, ctx.into(), keep_space);
532+
self.emit_unused_delims(cx, value.span, spans, ctx.into(), keep_space);
533533
}
534534

535535
fn emit_unused_delims(
536536
&self,
537537
cx: &EarlyContext<'_>,
538-
spans: (Span, Span),
538+
value_span: Span,
539+
spans: Option<(Span, Span)>,
539540
msg: &str,
540541
keep_space: (bool, bool),
541542
) {
542-
// FIXME(flip1995): Quick and dirty fix for #70814. This should be fixed in rustdoc
543-
// properly.
544-
if spans.0 == DUMMY_SP || spans.1 == DUMMY_SP {
545-
return;
546-
}
547-
548-
cx.struct_span_lint(self.lint(), MultiSpan::from(vec![spans.0, spans.1]), |lint| {
549-
let replacement = vec![
550-
(spans.0, if keep_space.0 { " ".into() } else { "".into() }),
551-
(spans.1, if keep_space.1 { " ".into() } else { "".into() }),
552-
];
553-
lint.build(fluent::lint::unused_delim)
554-
.set_arg("delim", Self::DELIM_STR)
555-
.set_arg("item", msg)
556-
.multipart_suggestion(
543+
let primary_span = if let Some((lo, hi)) = spans {
544+
MultiSpan::from(vec![lo, hi])
545+
} else {
546+
MultiSpan::from(value_span)
547+
};
548+
cx.struct_span_lint(self.lint(), primary_span, |lint| {
549+
let mut db = lint.build(fluent::lint::unused_delim);
550+
db.set_arg("delim", Self::DELIM_STR);
551+
db.set_arg("item", msg);
552+
if let Some((lo, hi)) = spans {
553+
let replacement = vec![
554+
(lo, if keep_space.0 { " ".into() } else { "".into() }),
555+
(hi, if keep_space.1 { " ".into() } else { "".into() }),
556+
];
557+
db.multipart_suggestion(
557558
fluent::lint::suggestion,
558559
replacement,
559560
Applicability::MachineApplicable,
560-
)
561-
.emit();
561+
);
562+
}
563+
db.emit();
562564
});
563565
}
564566

@@ -766,15 +768,12 @@ impl UnusedParens {
766768
// Otherwise proceed with linting.
767769
_ => {}
768770
}
769-
let spans = if value.span.from_expansion() || inner.span.from_expansion() {
770-
(
771-
value.span.with_hi(value.span.lo() + BytePos(1)),
772-
value.span.with_lo(value.span.hi() - BytePos(1)),
773-
)
771+
let spans = if let Some(inner) = inner.span.find_ancestor_inside(value.span) {
772+
Some((value.span.with_hi(inner.lo()), value.span.with_lo(inner.hi())))
774773
} else {
775-
(value.span.with_hi(inner.span.lo()), value.span.with_lo(inner.span.hi()))
774+
None
776775
};
777-
self.emit_unused_delims(cx, spans, "pattern", (false, false));
776+
self.emit_unused_delims(cx, value.span, spans, "pattern", (false, false));
778777
}
779778
}
780779
}
@@ -879,15 +878,12 @@ impl EarlyLintPass for UnusedParens {
879878
);
880879
}
881880
_ => {
882-
let spans = if ty.span.from_expansion() || r.span.from_expansion() {
883-
(
884-
ty.span.with_hi(ty.span.lo() + BytePos(1)),
885-
ty.span.with_lo(ty.span.hi() - BytePos(1)),
886-
)
881+
let spans = if let Some(r) = r.span.find_ancestor_inside(ty.span) {
882+
Some((ty.span.with_hi(r.lo()), ty.span.with_lo(r.hi())))
887883
} else {
888-
(ty.span.with_hi(r.span.lo()), ty.span.with_lo(r.span.hi()))
884+
None
889885
};
890-
self.emit_unused_delims(cx, spans, "type", (false, false));
886+
self.emit_unused_delims(cx, ty.span, spans, "type", (false, false));
891887
}
892888
}
893889
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// ignore-tidy-trailing-newlines
2+
//
3+
// error-pattern: this file contains an unclosed delimiter
4+
// error-pattern: this file contains an unclosed delimiter
5+
// error-pattern: this file contains an unclosed delimiter
6+
// error-pattern: format argument must be a string literal
7+
//
8+
// Verify that unused parens lint does not try to create a span
9+
// which points in the middle of a multibyte character.
10+
11+
fn f(){(print!(á
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
error: this file contains an unclosed delimiter
2+
--> $DIR/unused_parens_multibyte_recovery.rs:11:17
3+
|
4+
LL | fn f(){(print!(á
5+
| -- - ^
6+
| || |
7+
| || unclosed delimiter
8+
| |unclosed delimiter
9+
| unclosed delimiter
10+
11+
error: this file contains an unclosed delimiter
12+
--> $DIR/unused_parens_multibyte_recovery.rs:11:17
13+
|
14+
LL | fn f(){(print!(á
15+
| -- - ^
16+
| || |
17+
| || unclosed delimiter
18+
| |unclosed delimiter
19+
| unclosed delimiter
20+
21+
error: this file contains an unclosed delimiter
22+
--> $DIR/unused_parens_multibyte_recovery.rs:11:17
23+
|
24+
LL | fn f(){(print!(á
25+
| -- - ^
26+
| || |
27+
| || unclosed delimiter
28+
| |unclosed delimiter
29+
| unclosed delimiter
30+
31+
error: format argument must be a string literal
32+
--> $DIR/unused_parens_multibyte_recovery.rs:11:16
33+
|
34+
LL | fn f(){(print!(á
35+
| ^
36+
|
37+
help: you might be missing a string literal to format with
38+
|
39+
LL | fn f(){(print!("{}", á
40+
| +++++
41+
42+
error: aborting due to 4 previous errors
43+

0 commit comments

Comments
 (0)