Skip to content

Some code suggestions failed to be shown due to span tweaking #134061

Open
@js2xxx

Description

@js2xxx

Code

const x: () = |&'a

Current output

error: unexpected lifetime `'a` in pattern
 --> fuzz_input.rs:1:19
  |
1 | const x: () = |&'a
  |                 ^^
  |

error: expected parameter name, found `<eof>`
 --> fuzz_input.rs:1:19
  |
1 | const x: () = |&'a
  |                 ^^ expected parameter name

error: aborting due to 2 previous errors

Desired output

error: unexpected lifetime `'a` in pattern
 --> fuzz_input.rs:1:19
  |
1 | const x: () = |&'a
  |                 ^^
  |
help: remove the lifetime
  |
1 - const x: () = |&'a
1 + const x: () = |&
  |

error: expected parameter name, found `<eof>`
 --> fuzz_input.rs:1:21
  |
1 | const x: () = |&'a
  |                   ^ expected parameter name

error: aborting due to 2 previous errors

Rationale and extra context

This originates from this line in the bump function:

if next.0.span.is_dummy() {
    // Tweak the location for better diagnostics, but keep syntactic context intact.
    let fallback_span = self.token.span; // <------ This line
    next.0.span = fallback_span.with_ctxt(next.0.span.ctxt());
}

In the example input, the lifetime token is followed by an <eof> token, which has the dummy span as specified in inlined_next function. Thus the bump function sets the span of the latter to that of the former, leading to an overlap. Then, in the construction site of the UnexpectedLifetimeInPattern diagnostic in the parse_pat_deref function, the suggestion span constructed from untiling these spans becomes an empty span. Coincidentally, the suggestion code of this diagnostic is empty (removing the lifetime), causing the suggestion to be suppressed.

self.dcx().emit_err(UnexpectedLifetimeInPattern {
    span: self.prev_token.span,
    symbol: lifetime.name,
    suggestion: self.prev_token.span.until(self.token.span), // <------ This line
});

In fact, the current behavior also causes a debug_assert! to fail in the span_suggestion_with_style function:

debug_assert!(
    !(sp.is_empty() && suggestion.to_string().is_empty()),
    "Span must not be empty and have no suggestion"
);

I have 2 possible suggestions for fixing the problem:

  1. Change the assignment of the span to be self.token.span.shrink_to_hi(), or;
  2. Change the span of the returned <eof> token to be at the end position instead of the dummy span.

I have implemented and tested the first suggestion, and it works as expected. However, due to my lack of knowledge of the code base, I cannot figure out the other possible effects on the rest of the code, so I didn't open a pull request to fix this directly.

Other cases

Rust Version

rustc 1.85.0-nightly (9c707a8b7 2024-12-07)
binary: rustc
commit-hash: 9c707a8b769523bb6768bf58e74fa2c39cc24844
commit-date: 2024-12-07
host: x86_64-unknown-linux-gnu
release: 1.85.0-nightly
LLVM version: 19.1.5

Anything else?

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-diagnosticsArea: Messages for errors, warnings, and lintsA-parserArea: The lexing & parsing of Rust source code to an ASTA-suggestion-diagnosticsArea: Suggestions generated by the compiler applied by `cargo fix`C-bugCategory: This is a bug.D-invalid-suggestionDiagnostics: A structured suggestion resulting in incorrect code.I-ICEIssue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️S-bug-has-testStatus: This bug is tracked inside the repo by a `known-bug` test.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.requires-debug-assertionsThis issue requires a build of rustc or tooling with debug-assertions in some way

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions