-
Notifications
You must be signed in to change notification settings - Fork 14k
Early return if span is from expansion so we dont get empty span and ice later on #147416
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
Conversation
|
|
|
these errors are recurring, how can we implement a long-term fix. |
|
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 |
|
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 |
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). |
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
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() { |
There was a problem hiding this comment.
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(_).
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
Show resolved
Hide resolved
4d673df to
b51eba3
Compare
|
compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
Outdated
Show resolved
Hide resolved
|
Thanks! r=me after fmt fix (CI should fail soon believe) & minor nit and once CI is green |
This comment has been minimized.
This comment has been minimized.
|
0_0, I ran |
compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
Outdated
Show resolved
Hide resolved
You might not have |
Maybe just |
01e4847 to
649a68a
Compare
This comment has been minimized.
This comment has been minimized.
649a68a to
cd09481
Compare
|
|
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)) |
|
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 |
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() { |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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> | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| //! Regression test <https://github.com/rust-lang/rust/issues/147255> | |
| //! Regression test for <https://github.com/rust-lang/rust/issues/147255> |
cd09481 to
62ccf14
Compare
|
@bors r+ |
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
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)
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)