-
Notifications
You must be signed in to change notification settings - Fork 13k
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
Special-case raw ref op for diverging check in HIR typeck #129371
Special-case raw ref op for diverging check in HIR typeck #129371
Conversation
r? @davidtwco rustbot has assigned @davidtwco. Use |
cc @RalfJung, do you have a strong opinion about this? It seems a bit unfortunate that this is a special case, but raw ref is kinda special anyways. |
#![feature(never_type)] | ||
|
||
fn make_up_a_value<T>() -> T { | ||
unsafe { |
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.
After #129248, we can take away the unsafe {}
so it's especially important this turn into an error :)
If only the HIR had already made loads explicit... or would that actually handle this? |
@workingjubilee: It would probably simplify things a bit, though those loads being explicit would probably make approximately everything else in the HIR much harder to deal with (like dealing w the explicit scopes in THIR, lol). I think the real problem here is that divergence analysis is just a hot mess in HIR typeck. |
…verge-but-more, r=<try> [EXPERIMENT] Do not consider match/let/raw-ref of deref that evalautes to ! to diverge This is the more involved version of rust-lang#129371. It doesn't fully fix rust-lang#117288, since we still need to fix the fact that never type fallback can cause an unintended load via the `NeverToAny` coercion. But I did want to probe crater to see if anyone relies on this behavior currently, since that's almost certainly UB. r? `@ghost`
I think ideally we would treat all place expressions that we do not load from like this: so also LHS of assignments, and & for references.
Assignments always come with a value expression on the right so there it likely makes no difference. But shouldn't we treat &raw and & the same?
|
let _: ! = *x; | ||
// Since `*x` "diverges" in HIR, but doesn't count as a read in MIR, this | ||
// is unsound since we act as if it diverges but it doesn't. | ||
} |
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.
Can you make the return type of this function !
? I think that makes it much clearer that we're testing for "HIR detecting divergence" here.
&raw const *x; | ||
// Since `*x` is `!`, HIR typeck used to think that it diverges | ||
// and allowed the block to coerce to any value, leading to UB. | ||
} |
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.
Same here, a return type of !
would be more clear I think.
That list is based on MIR; I don't know what the full list is for HIR. #129392 mentions some candidates. |
@RalfJung: Doesn't the LHS of an assignment constitute a load? We still have to drop the old value stored in that place, right? |
Hm... a drop happens in-place though, via |
…verge-but-more, r=<try> [EXPERIMENT] Do not consider match/let/raw-ref of deref that evalautes to ! to diverge This is the more involved version of rust-lang#129371. It's pretty ugly rn. r? `@ghost`
…verge-but-more, r=<try> [EXPERIMENT] Do not consider match/let/raw-ref of deref that evalautes to ! to diverge This is the more involved version of rust-lang#129371. It's pretty ugly rn. r? `@ghost`
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.
This makes sense to me, r=me after addressing Ralf's comments unless you want to make a bigger change along the lines of Ralf's suggestion.
No need to special case this. I'll implement the "right" way of doing it here: #129392 |
See #117288.
&raw const EXPR
does not constitute a read ofEXPR
, so ifEXPR
's type is!
, then we don't want to consider that expression diverging. This was unsound when paired with #129248.This remains unsound for things like matches
let _: ! = *x;
, but I wanted to add a test for it.