8000 fix: Ensure empty sources have one "line" by Muscraft · Pull Request #219 · rust-lang/annotate-snippets-rs · GitHub
[go: up one dir, main page]

Skip to content

fix: Ensure empty sources have one "line" #219

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 24, 2025

Conversation

Muscraft
Copy link
Member

rustc will occasionally give us a Snippet with an empty source and an Annotation with the span 0..0, which causes annotate-snippets to panic. The root cause of the panic is that a few places in SourceMap expect at least one LineInfo, when none are created for an empty source. To fix this, I made it so when we are given an empty source, we add a single "empty" LineInfo, with the appropriate line_index.


When looking into how to fix this, I noticed that rustc doesn't show the annotation even though there is one that could be displayed. Because of this, I felt it was best to diverge from how rustc would render this and show the annotation (and the correct line).

Original Test
#[test]
fn mismatched_types1() {
    // tests/ui/include-macros/mismatched-types.rs

    let file_txt_source = r#""#;

    let rust_source = r#"fn main() {
    let b: &[u8] = include_str!("file.txt");    //~ ERROR mismatched types
    let s: &str = include_bytes!("file.txt");   //~ ERROR mismatched types
}"#;

    let input = Level::ERROR.header("mismatched types").id("E0308").group(
        Group::new()
            .element(
                Snippet::source(file_txt_source)
                    .fold(true)
                    .line_start(3)
                    .origin("$DIR/file.txt")
                    .annotation(
                        AnnotationKind::Primary
                            .span(0..0)
                            .label("expected `&[u8]`, found `&str`"),
                    ),
            )
            .element(
                Snippet::source(rust_source)
                    .origin("$DIR/mismatched-types.rs")
                    .fold(true)
                    .annotation(
                        AnnotationKind::Context
                            .span(23..28)
                            .label("expected due to this"),
                    )
                    .annotation(
                        AnnotationKind::Context
                            .span(31..55)
                            .label("in this macro invocation"),
                    ),
            )
            .element(
                Level::NOTE.title("expected reference `&[u8]`\n   found reference `&'static str`"),
            ),
    );

    let expected = str![[r#"
error[E0308]: mismatched types
  --> $DIR/file.txt:0:1
   |
   |
  ::: $DIR/mismatched-types.rs:2:12
   |
LL |     let b: &[u8] = include_str!("file.txt");    //~ ERROR mismatched types
   |            -----   ------------------------ in this macro invocation
   |            |
   |            expected due to this
   |
   = note: expected reference `&[u8]`
              found reference `&'static str`
"#]];
    let renderer = Renderer::plain().anonymized_line_numbers(true);
    assert_data_eq!(renderer.render(input), expected);
}
Proposed
#[test]
fn mismatched_types1() {
    // tests/ui/include-macros/mismatched-types.rs

    let file_txt_source = r#""#;

    let rust_source = r#"fn main() {
    let b: &[u8] = include_str!("file.txt");    //~ ERROR mismatched types
    let s: &str = include_bytes!("file.txt");   //~ ERROR mismatched types
}"#;

    let input = Level::ERROR.header("mismatched types").id("E0308").group(
        Group::new()
            .element(
                Snippet::source(file_txt_source)
                    .fold(true)
                    .line_start(3)
                    .origin("$DIR/file.txt")
                    .annotation(
                        AnnotationKind::Primary
                            .span(0..0)
                            .label("expected `&[u8]`, found `&str`"),
                    ),
            )
            .element(
                Snippet::source(rust_source)
                    .origin("$DIR/mismatched-types.rs")
                    .fold(true)
                    .annotation(
                        AnnotationKind::Context
                            .span(23..28)
                            .label("expected due to this"),
                    )
                    .annotation(
                        AnnotationKind::Context
                            .span(31..55)
                            .label("in this macro invocation"),
                    ),
            )
            .element(
                Level::NOTE.title("expected reference `&[u8]`\n   found reference `&'static str`"),
            ),
    );

    let expected = str![[r#"
error[E0308]: mismatched types
  --> $DIR/file.txt:3:1
   |
LL |
   | ^ expected `&[u8]`, found `&str`
   |
  ::: $DIR/mismatched-types.rs:2:12
   |
LL |     let b: &[u8] = include_str!("file.txt");    //~ ERROR mismatched types
   |            -----   ------------------------ in this macro invocation
   |            |
   |            expected due to this
   |
   = note: expected reference `&[u8]`
              found reference `&'static str`
"#]];
    let renderer = Renderer::plain().anonymized_line_numbers(true);
    assert_data_eq!(renderer.render(input), expected);
}

Note: I will try to backport this change to rustc so that this is only a temporary divergence in output.

@epage epage merged commit b228756 into rust-lang:master Jun 24, 2025
15 checks passed
@Muscraft Muscraft deleted the atleast-one-line branch June 24, 2025 19:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants
0