-
Notifications
You must be signed in to change notification settings - Fork 13.1k
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
melt the ICE when lowering an impossible range #32267
Conversation
Should I define an error code and use |
"melt the ICE" -- this is an amazing phrase 🍧 |
Also, if |
Ideally yes, but I don't think it is essential.
span_fatal is for things we can't recover from, rather than things that shouldn't happen. It's nice if those two things align, since unrecoverable errors are not great for the user, so should be rare. I think we should try and catch a lone |
@@ -336,6 +336,10 @@ impl NodeIdAssigner for Session { | |||
fn peek_node_id(&self) -> NodeId { | |||
self.next_node_id.get().checked_add(1).unwrap() | |||
} | |||
|
|||
fn span_fatal(&self, sp: MultiSpan, msg: &str) -> ! { |
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.
NodeIdAssigner could have a GetDiagnostic method returning Option, that avoids having error methods for every kind of error in NodeIdAssigner.
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.
Or just a Diagnostic and panic if it can't be done.
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.
Hmm so bring in DiagnosticBuilder
from libsyntax?
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.
syntax::errors::Handler (sorry, naming has changed somewhat); and GetHandler.
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.
Done (except this code path is now untested because the parse error was made fatal).
I was wondering about this. What does the parser leave behind in the AST when it recovers? Does it just skip the line of code? I tried to inspect the AST, but apparently semicolon recovery isn't enough to get to |
In the AST there isn't an 'error' node. We only recover if we can make a valid AST. |
..1; | ||
0..1; | ||
|
||
...; //~ERROR inclusive range with no end |
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'm a little confused. We get to this error during lowering, so I assumed the one on the next line (which is a parse error) was recovered. But what valid AST could be left behind?
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.
A range with neither start nor end - the AST doesn't have to be well-formed (for some definition), it just must be constructable. We don't get the lowering error there because the first error was fatal. I suspect if you have a test case with just that line, you would get both a parsing and lowering error.
Here's my plan (can't work on it until tonight): add a field to Anyway, this situation will probably go away when @aturon and I get around to writing that RFC to change the syntax and allow all types of ranges :) |
cf055e3
to
fb88d61
Compare
I added the parse error. Haven't implemented the |
fb88d61
to
d8ca46e
Compare
OK, ready for review. |
d8ca46e
to
9f4b098
Compare
@@ -336,6 +336,10 @@ impl NodeIdAssigner for Session { | |||
fn peek_node_id(&self) -> NodeId { | |||
self.next_node_id.get().checked_add(1).unwrap() | |||
} | |||
|
|||
fn diagnostic(&self) -> &errors::Handler { | |||
self.diagnostic() |
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.
Um. This looks... weird. Did I introduce an infinite recursion (I didn't see a warning) or it's OK because inherent fns take precedence over trait fns?
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.
yeah, inherent has precedence.
and looking more at this has made me realized that one cannot resort to UFCS as a way to try to "clarify" that the inherent method is what is intended. There's no way to say "I want an inherent impl and only an inherent impl", at least not via UFCS...
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 think you can.
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.
There's no way to say "I want an inherent impl and only an inherent impl"
That seems good. Then you can factor out an inherent method into a trait method without a breaking change, is that true?
9f4b098
to
bbe56ac
Compare
@@ -140,6 +141,11 @@ impl<'a, 'hir> LoweringContext<'a> { | |||
result | |||
} | |||
} | |||
|
|||
// panics if this LoweringContext's NodeIdAssigner is not a Session |
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 think the bit about being a Session is too much detail, one could imagine implementing NodeIdAssigner with something that is not a Session but can still provide a diagnostic (also, nit, comments should start with a capital and end with a period).
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.
Fixed.
looks good, r+ with the minor comments addressed |
2/3 nits addressed, 1/3 nits quibbled with. |
411c740
to
0046090
Compare
Should be good to go now. |
☔ The latest upstream changes (presumably #32454) made this pull request unmergeable. Please resolve the merge conflicts. |
r+, but needs a rebase |
End-less ranges (`a...`) don't parse but bad syntax extensions could conceivably produce them. Unbounded ranges (`...`) do parse and are caught here. The other panics in HIR lowering are all for unexpanded macros, which cannot be constructed by bad syntax extensions.
Guh. The untry conversion broke a bunch of alignment in libsyntax. Don't know why y'all let that through without reformatting. |
Now it is impossible for `...` or `a...` to reach HIR lowering without a rogue syntax extension in play.
0046090
to
861644f
Compare
Rebased. |
.map(|x|{ | ||
hi = x.span.hi; | ||
x | ||
})?) |
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.
Just for the record, I think this is much harder to read than the old version with try!
. You have to parse the entire expression backwards from ?
to see what it applies to.
@bors: r+ |
📌 Commit 861644f has been approved by |
Emit a fatal error instead of panicking when HIR lowering encounters a range with no
end
point.This involved adding a method to wire up
LoweringContext::span_fatal
.Fixes #32245 (cc @nodakai).
r? @nrc