Skip to content

Conversation

@Kivooeo
Copy link
Member

@Kivooeo Kivooeo commented Oct 6, 2025

Fixes #147255

The problem original was from that stmt.span was from expansion and it span was bigger than right part which is block.span, so it causes empty span and panic later on, I decided to add checks for both of them to be on the safe side

r? @fmease (you were in discussion on this issue so I decided to assign you, feel free to reroll)

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Oct 6, 2025
@rustbot
Copy link
Collaborator

rustbot commented Oct 6, 2025

fmease is not on the review rotation at the moment.
They may take a while to respond.

@chenyukang
Copy link
Member

these errors are recurring, how can we implement a long-term fix.
i remember we had a try, but it was blocked by performance regression.

@Kivooeo
Copy link
Member Author

Kivooeo commented Oct 7, 2025

This should not affect performance. As for a long-term fix, I’m not sure we can implement one, since it may occur in unexpected places. We can probably fix issues like this only gradually over time

@Kivooeo
Copy link
Member Author

Kivooeo commented Oct 7, 2025

For example this ICE was since 1.86, which is pretty old, but I have no idea what has changed after 1.85 that could break this

@chenyukang
Copy link
Member

This should not affect performance. As for a long-term fix, I’m not sure we can implement one, since it may occur in unexpected places. We can probably fix issues like this only gradually over time

i'm referring this one which have perf regression: #109082

i have a revisit on that PR, seems it was fixing a different issue (but general in similar kind).

matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Oct 14, 2025
Add check if span is from macro expansion

The same thing I did in rust-lang#147416, actually the same bug but in another place, I'm not really sure how this method is good for fixing such ICEs, but, it does work and not conflicting with any existing tests, so I guess, it's fine

Fixes rust-lang#147408

r? compiler
jdonszelmann added a commit to jdonszelmann/rust that referenced this pull request Oct 14, 2025
Add check if span is from macro expansion

The same thing I did in rust-lang#147416, actually the same bug but in another place, I'm not really sure how this method is good for fixing such ICEs, but, it does work and not conflicting with any existing tests, so I guess, it's fine

Fixes rust-lang#147408

r? compiler
return;
};
if block.expr.is_some() {
if block.expr.is_some() || block.span.from_expansion() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using .from_expansion() is always a "heavy hammer" (see also #147577 (comment)) since it leads to us flat out suppressing diagnostics once macros are in the vicinity even if they don't pose any problem.

In #147255 (comment), you wrote that tail_expr.span and stmt.span were identical. However, that seems a bit surprising to me because "usually" (i.e.., when no macros are involved), the stmt span should include the ; while the expr span should not. Consider:

fn main() {
    let s = {
        "hello"    ;
    };
    println!("{}", s);
}

Using a nightly/master rustc (output trimmed by me):

error[E0277]: `()` doesn't implement `std::fmt::Display`
 --> src/main.rs:5:20
  |
3 |         "hello"    ;
  |                ----- help: remove this semicolon
4 |     };

As you probably already know with stmt.span.with_lo(tail_expr.span.hi()) later on we try to "diff" the stmt span (which includes the semicolon) with the inner expr one (which can include whitespace as seen above for demo purposes).

I mean I have no reason to doubt that what you wrote in #147255 (comment) is accurate. If they indeed the same span if a macro is involved, then I would consider that a bug / unfortunate decision in macro expansion (it would ignore the SyntaxContext of the ; when marking or concatenating Spans maybe)?

If they were different, we could then simply tail_expr.span.find_ancestor_in_same_ctxt(stmt.span) and use that inside stmt.span.with_lo(_).

Copy link
Member

@fmease fmease Nov 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using .from_expansion() is always a "heavy hammer" (see also #147577 (comment)) since it leads to us flat out suppressing diagnostics once macros are in the vicinity even if they don't pose any problem.

E.g., it means that under your PR we would suppress the semicolon suggestion in the following case I'm pretty sure:

fn main() {
    macro_rules! generate {
        () => {{
            "txt";
        }}
    }

    let s = generate!();
    println!("{}", s);
}

Even though the suggestion would be perfectly fine and correct as s seen on nightly/master:

error[E0277]: `()` doesn't implement `std::fmt::Display`
 --> src/main.rs:9:20
  |
4 |             "txt";
  |                  - help: remove this semicolon

Copy link
Member

@fmease fmease Nov 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If they indeed the same span if a macro is involved,

Yeah, it looks like you're absolutely right. For fn main() { ""; } the expr.span ("") and stmt.span ("";) are obv. different but for macro_rules! s { () = { "" } } fn main() { s!(); }, stmt.span (s!();) and expr.span (s!()) are the same! Unbelievable.

I wonder if that's intentional (simplicity of implementation) or a bug we can easily fix.

Copy link
Member

@fmease fmease Nov 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if that's intentional (simplicity of implementation) or a bug we can easily fix.

IMO, this is the real fix. Remember, at a high-level we're simply trying to compute the "span of the semicolon" by diffing two spans but that sadly doesn't work correctly because the stmt&expr span are the same if the expr is a macro call, as a result the span is empty (as you've already come to realize) and the suggestion is also empty (since it's a removal).

So, the debug assert from the linked issue uncovered a real bug which is its purpose.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we can just do this instead (or something similar for empty span) #147255 (comment)

Maybe even under some FIXME comment with link to this

Because as you pointed correctly, current approach does suppress a semicolon suggestion in macro which is incorrect

@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Nov 6, 2025
@rustbot
Copy link
Collaborator

rustbot commented Nov 6, 2025

⚠️ Warning ⚠️

@fmease
Copy link
Member

fmease commented Nov 6, 2025

Thanks! r=me after fmt fix (CI should fail soon believe) & minor nit and once CI is green
@bors rollup

@rust-log-analyzer

This comment has been minimized.

@Kivooeo
Copy link
Member Author

Kivooeo commented Nov 6, 2025

0_0,

I ran ./x test ui before pushing

@fmease
Copy link
Member

fmease commented Nov 6, 2025

0_0,

I ran ./x test ui before pushing

You might not have rust.debug = true set in your local bootstrap.toml

@Kivooeo
Copy link
Member Author

Kivooeo commented Nov 6, 2025

The spans are identical, so that's always true

Maybe just !stmt.span.eq_ctxt(tail_expr.span) then? (added negation)

@rust-cloud-vms rust-cloud-vms bot force-pushed the ice-fix23456 branch 3 times, most recently from 01e4847 to 649a68a Compare November 6, 2025 18:49
@rust-log-analyzer

This comment has been minimized.

@fmease
Copy link
Member

fmease commented Nov 6, 2025

The spans are identical, so that's always true

Maybe just !stmt.span.eq_ctxt(tail_expr.span) then? (added negation)

eq_ctxt means "do these spans come from different macro expansions" (simplified), so !eq_ctxt would mean we'd suppress the note for as simple cases as "text"; where both "text" and "text"; obviously come from the same "expansion" (well, syntax context), namely ROOT.

@fmease
Copy link
Member

fmease commented Nov 6, 2025

Sorry for forcing you to jump through some hoops, I was kinda investigating everything in real time and my bad suggestion slipped through.

r=me once green once again :)

Edit: Two final nits ^^' (#147416 (comment), #147416 (comment))

@Kivooeo
Copy link
Member Author

Kivooeo commented Nov 6, 2025

Yeah I already tried that without success, also tried check if span is empty before suggeestion also with no luck, so I just reverted and unified it into one if to put FIXME on it

@Kivooeo
Copy link
Member Author

Kivooeo commented Nov 6, 2025

I was kinda investigating everything

That's totally fine, I was also interested to find better solution instead of suppressing it

};
// FIXME expr and stmt have the same span if expr comes from expansion
// cc: https://github.com/rust-lang/rust/pull/147416#discussion_r2499407523
if stmt.span.from_expansion() || block.span.from_expansion() {
Copy link
Member

@fmease fmease Nov 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When is block.span.from_expansion() actually necessary? The following doesn't crash under debug-asserts:

fn main() {
    macro_rules! generate {
        () => {{ "text"; }}
    }
    let x_str = generate!();

    println!("{}", x_str);
}

but I think due to the block.span.from_expansion() it's now suppressed.

stmt.span.from_expansion() or equivalently tail_expr.span.from_expansion() should suffice.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well I keep only stmt.span.from_expansion(), but it still suppressing this suggestion here

I don't remember originally why I added this check, was it just sanity check or on purpose

@@ -0,0 +1,10 @@
//! Regression test <https://github.com/rust-lang/rust/issues/147255>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
//! Regression test <https://github.com/rust-lang/rust/issues/147255>
//! Regression test for <https://github.com/rust-lang/rust/issues/147255>

@fmease
Copy link
Member

fmease commented Nov 6, 2025

@bors r+

@bors
Copy link
Collaborator

bors commented Nov 6, 2025

📌 Commit 62ccf14 has been approved by fmease

It is now in the queue for this repository.

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Nov 6, 2025
bors added a commit that referenced this pull request Nov 7, 2025
Rollup of 12 pull requests

Successful merges:

 - #145768 (Offload device)
 - #145992 (Stabilize `vec_deque_pop_if`)
 - #147416 (Early return if span is from expansion so we dont get empty span and ice later on)
 - #147808 (btree: cleanup difference, intersection, is_subset)
 - #148520 (style: Use binary literals instead of hex literals in doctests for `highest_one` and `lowest_one`)
 - #148559 (Add typo suggestion for a misspelt Cargo environment variable)
 - #148567 (Fix incorrect precedence caused by range expression)
 - #148570 (Fix mismatched brackets in generated .dir-locals.el)
 - #148575 (fix dev guide link in rustc_query_system/dep_graph/README.md)
 - #148578 (core docs: add notes about availability of `Atomic*::from_mut_slice`)
 - #148603 (Backport 1.91.1 relnotes to main)
 - #148609 (Sync str::rsplit_once example with str::split_once)

r? `@ghost`
`@rustbot` modify labels: rollup
@bors bors merged commit 7af1ee3 into rust-lang:master Nov 7, 2025
11 checks passed
@rustbot rustbot added this to the 1.93.0 milestone Nov 7, 2025
rust-timer added a commit that referenced this pull request Nov 7, 2025
Rollup merge of #147416 - Kivooeo:ice-fix23456, r=fmease

Early return if span is from expansion so we dont get empty span and ice later on

Fixes #147255

The problem original was from that stmt.span was from expansion and it span was bigger than right part which is block.span, so it causes empty span and panic later on, I decided to add checks for both of them to be on the safe side

r? `@fmease` (you were in discussion on this issue so I decided to assign you, feel free to reroll)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[ICE] thread 'rustc' panicked at compiler/rustc_errors/src/diagnostic.rs:1025:9

6 participants