Skip to content

Commit ca9f5e5

Browse files
authored
Merge pull request #250 from Muscraft/sugg-span-beyond-buffer
fix!: Panic if Patch span is beyond the end of buffer
2 parents 6b314dd + 83d2cbb commit ca9f5e5

File tree

2 files changed

+131
-0
lines changed

2 files changed

+131
-0
lines changed

src/renderer/source_map.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,19 @@ impl<'a> SourceMap<'a> {
379379
}
380380
line_count
381381
}
382+
383+
let source_len = self.source.len();
384+
if let Some(bigger) = patches.iter().find_map(|x| {
385+
// Allow patching one past the last character in the source.
386+
if source_len + 1 < x.span.end {
387+
Some(&x.span)
388+
} else {
389+
None
390+
}
391+
}) {
392+
panic!("Patch span `{bigger:?}` is beyond the end of buffer `{source_len}`")
393+
}
394+
382395
// Assumption: all spans are in the same file, and all spans
383396
// are disjoint. Sort in ascending order.
384397
patches.sort_by_key(|p| p.span.start);

tests/formatter.rs

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2635,3 +2635,121 @@ fn empty_span_start_line() {
26352635
let renderer = Renderer::plain();
26362636
assert_data_eq!(renderer.render(input), expected);
26372637
}
2638+
2639+
#[test]
2640+
fn suggestion_span_one_bigger_than_source() {
2641+
let snippet_source = r#"#![allow(unused)]
2642+
fn main() {
2643+
[1, 2, 3].into_iter().for_each(|n| { *n; });
2644+
}
2645+
"#;
2646+
2647+
let suggestion_source = r#"[1, 2, 3].into_iter().for_each(|n| { *n; });
2648+
"#;
2649+
2650+
let long_title1 ="this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to `<[T; N] as IntoIterator>::into_iter` in Rust 2021";
2651+
let long_title2 = "for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>";
2652+
let long_title3 = "or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value";
2653+
2654+
let input = &[
2655+
Group::with_title(Level::WARNING.title(long_title1))
2656+
.element(
2657+
Snippet::source(snippet_source)
2658+
.path("lint_example.rs")
2659+
.annotation(AnnotationKind::Primary.span(40..49)),
2660+
)
2661+
.element(Level::WARNING.message("this changes meaning in Rust 2021"))
2662+
.element(Level::NOTE.message(long_title2))
2663+
.element(Level::NOTE.message("`#[warn(array_into_iter)]` on by default")),
2664+
Group::with_title(
2665+
Level::HELP.title("use `.iter()` instead of `.into_iter()` to avoid ambiguity"),
2666+
)
2667+
.element(
2668+
Snippet::source(suggestion_source)
2669+
.path("lint_example.rs")
2670+
.line_start(3)
2671+
.patch(Patch::new(10..19, "iter")),
2672+
),
2673+
Group::with_title(Level::HELP.title(long_title3)).element(
2674+
Snippet::source(suggestion_source)
2675+
.path("lint_example.rs")
2676+
.line_start(3)
2677+
.patch(Patch::new(
2678+
suggestion_source.len() + 1..suggestion_source.len() + 1,
2679+
"IntoIterator::into_iter(",
2680+
)),
2681+
),
2682+
];
2683+
2684+
let expected = str![[r#"
2685+
warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to `<[T; N] as IntoIterator>::into_iter` in Rust 2021
2686+
--> lint_example.rs:3:11
2687+
|
2688+
3 | [1, 2, 3].into_iter().for_each(|n| { *n; });
2689+
| ^^^^^^^^^
2690+
|
2691+
= warning: this changes meaning in Rust 2021
2692+
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
2693+
= note: `#[warn(array_into_iter)]` on by default
2694+
help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
2695+
|
2696+
3 - [1, 2, 3].into_iter().for_each(|n| { *n; });
2697+
3 + [1, 2, 3].iter().for_each(|n| { *n; });
2698+
|
2699+
help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value
2700+
|
2701+
3 | IntoIterator::into_iter(
2702+
|
2703+
"#]];
2704+
let renderer = Renderer::plain();
2705+
assert_data_eq!(renderer.render(input), expected);
2706+
}
2707+
2708+
#[test]
2709+
#[should_panic = "Patch span `47..47` is beyond the end of buffer `45`"]
2710+
fn suggestion_span_bigger_than_source() {
2711+
let snippet_source = r#"#![allow(unused)]
2712+
fn main() {
2713+
[1, 2, 3].into_iter().for_each(|n| { *n; });
2714+
}
2715+
"#;
2716+
let suggestion_source = r#"[1, 2, 3].into_iter().for_each(|n| { *n; });
2717+
"#;
2718+
2719+
let long_title1 ="this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to `<[T; N] as IntoIterator>::into_iter` in Rust 2021";
2720+
let long_title2 = "for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>";
2721+
let long_title3 = "or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value";
2722+
2723+
let input = &[
2724+
Group::with_title(Level::WARNING.title(long_title1))
2725+
.element(
2726+
Snippet::source(snippet_source)
2727+
.path("lint_example.rs")
2728+
.annotation(AnnotationKind::Primary.span(40..49)),
2729+
)
2730+
.element(Level::WARNING.message("this changes meaning in Rust 2021"))
2731+
.element(Level::NOTE.message(long_title2))
2732+
.element(Level::NOTE.message("`#[warn(array_into_iter)]` on by default")),
2733+
Group::with_title(
2734+
Level::HELP.title("use `.iter()` instead of `.into_iter()` to avoid ambiguity"),
2735+
)
2736+
.element(
2737+
Snippet::source(suggestion_source)
2738+
.path("lint_example.rs")
2739+
.line_start(3)
2740+
.patch(Patch::new(10..19, "iter")),
2741+
),
2742+
Group::with_title(Level::HELP.title(long_title3)).element(
2743+
Snippet::source(suggestion_source)
2744+
.path("lint_example.rs")
2745+
.line_start(3)
2746+
.patch(Patch::new(
2747+
suggestion_source.len() + 2..suggestion_source.len() + 2,
2748+
"IntoIterator::into_iter(",
2749+
)),
2750+
),
2751+
];
2752+
2753+
let renderer = Renderer::plain();
2754+
renderer.render(input);
2755+
}

0 commit comments

Comments
 (0)