Skip to content

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