-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Improve divergence checking for loops #51053
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
This comment has been minimized.
This comment has been minimized.
4343104
to
a4eaa41
Compare
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.
The code looks good as is, but I am worried it's trying to extend the divergence mechanism beyond its design. Might be still worth fixing, not sure. Kind of a matter of "predictability" I guess — thoughts @rust-lang/lang (and specifically @eddyb and maybe @arielb1)?
(Also, @varkor, please verify my test case — though if that one is wrong, I'm sure there is a similar one that is right.)
// the function is already diverging. In this case, we | ||
// don't need to supply any value (in which case, the | ||
// value will be considered to have type `!`). | ||
if !prev_diverges.always() { |
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, I think if we are going to "do this", we might want to consider "doing it right". In particular, the value of the diverges flag on entry to an expression does not indicate if "all prior points in the CFG diverged" but rather if some preceding subexpression within the parent diverged.
This means that while this test works now:
if false {
let _: ! = {
loop { return; break } // ok
};
}
I expect that this one will fail, right?
if false {
let _: ! = {
loop {
return;
{ break; } // now the break is part of a sub-block...
}
};
}
Put another way, I am wary of adding rules that try to use the existing divergence mechanism to figure out if prior code had diverged.
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.
Yes, that's correct.
I know in the past @arielb1 and I had talked about adding a separate divergence mechanism to track whether "prior code has diverged" basically... |
This change permits `break`s to be considered diverging (i.e. having type `!`) in diverging blocks, which allows constructions like `let _: ! = { loop { return; break } }`, relaxing the overly-restrictive divergence rules.
Perhaps that would be worthing thinking about in a little more detail, yes. |
a4eaa41
to
2039a9b
Compare
I don't see a lot of comments either way yet =) |
I'll try taking a look at more sophisticated divergence checking soon. |
I think the deeper question is if we want the compiler to be that smart. |
Let me just spell out my concerns: I know we could implement this, but it means making the type checker that much more clever. The existing check and its implications are pretty subtle! Now we would have to be threading two notions of divergence through typeck, with lots of opportunity to make a small mistake. The result of making a mistake like that would be bugs that may wind up in code that lives in crates.io. Or even if there are no bugs, it's just complexity that we have to support forever. The counter-argument, I guess, is that we already do some amount of dead-code reasoning, and it's kind of surprising that things like So I guess I remain sort of vaguely biased against making this work at this time. I'd feel better if the type-checker were refactored into something clean where we could easily specify this extra analysis, versus being the current setup where we'd really have to thread it around by hand. |
Okay, I'm happy to close this for now and we can potentially take another look at some later point. It's an edge case anyway. |
This change permits
break
s to be considered diverging (i.e. having type!
) in diverging blocks, which allows constructions like:thus relaxing the overly-restrictive divergence rules.
r? @nikomatsakis