-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Do not consider match/let/ref of place that evaluates to !
to diverge, disallow coercions from them too
#129392
Do not consider match/let/ref of place that evaluates to !
to diverge, disallow coercions from them too
#129392
Conversation
@bors try |
…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`
☀️ Try build successful - checks-actions |
5250e5d
to
1ee0400
Compare
@bors try |
…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`
@bors try |
…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`
This comment has been minimized.
This comment has been minimized.
☀️ Try build successful - checks-actions |
@craterbot check |
👌 Experiment ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more |
[CRATER] Crater Rollup This is a " crater rollup" of: * rust-lang#126452 * rust-lang#128784 * rust-lang#129392 * rust-lang#129422 * rust-lang#129543 **What is a crater rollup?** It's simply a crater job that is run on all of the containing PRs *together*, and then we can set the crates list for each of these jobs to just the failures after it's done. It should cut out on the bulk of "normal" crates that do nothing and simply just take time to build. r? `@ghost`
[CRATER] Crater Rollup This is a " crater rollup" of: * rust-lang#126452 * rust-lang#128784 * rust-lang#129392 * rust-lang#129422 * rust-lang#129543 * rust-lang#129604 **What is a crater rollup?** It's simply a crater job that is run on all of the containing PRs *together*, and then we can set the crates list for each of these jobs to just the failures after it's done. It should cut out on the bulk of "normal" crates that do nothing and simply just take time to build. r? `@ghost`
[CRATER] Crater Rollup This is a " crater rollup" of: * rust-lang#126452 * rust-lang#128784 * rust-lang#129392 * rust-lang#129422 * rust-lang#129543 * rust-lang#129604 **What is a crater rollup?** It's simply a crater job that is run on all of the containing PRs *together*, and then we can set the crates list for each of these jobs to just the failures after it's done. It should cut out on the bulk of "normal" crates that do nothing and simply just take time to build. r? `@ghost`
📝 Configuration of the ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more |
@craterbot p=1 (Bump priority is this will run quickly.) |
📝 Configuration of the ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more |
🚧 Experiment ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more |
🎉 Experiment
|
This comment has been minimized.
This comment has been minimized.
…eck_expr_has_type_or_error
8e0621e
to
e8d5eb2
Compare
Rebased to add a match arm for new node type. @bors r=lcnr |
…verge-but-more, r=lcnr Do not consider match/let/ref of place that evaluates to `!` to diverge, disallow coercions from them too Fixes rust-lang#117288. This PR implements a heuristic which disables two things that are currently being performed on the HIR when we have **expressions that involve place-like expressions that point to `!`**. Specifically, it will (in certain cases explained below): ### (1.) Disable the `NeverToAny` coercion we implicitly insert for `!`. Which fixes this inadvertent, sneaky unsoundness: ``` unsafe { let x: *const ! = &0 as *const u8 as *const !; let _: () = *x; } ``` which is UB because currently rust emits an *implicit* NeverToAny coercion even though we really shouldn't be, since there's no read of the value pointed by `x`. ### (2.) Disable the logic which considers expression which evaluate to `!` to diverge, which affects the type returned by the containing block. Which fixes this unsoundness: ``` fn make_up_a_value<T>() -> T { unsafe { let x: *const ! = &0 as *const u8 as *const !; let _ = *x; } } ``` We disable these two operations **if** the expression is a place-like expression (locals, statics, field projections, index operations, and deref operations), and if the parent expression is either: (1.) the LHS of an assignment (2.) AddrOf (3.) A match or let **unless** all of the *patterns consitute a read*, which is explained below: And finally, a pattern currently is considered to constitute a read **unless** it is a wildcard, or an OR pattern. An OR pattern is considered to constitute a read if all of its subpatterns constitute a read, to remain as conservative as possible in cases like `_ | subpat` or `subpat | _`. All other patterns are considered currently to constitute a read. Specifically, because `NeverToAny` is a coercion performed on a *value* and not a *place*, `Struct { .. }` on a `!` type must be a coercion currently, and we currently rely on this behavior to allow us to perform coercions like `let _: i32 = x;` where `x: !`. This is already considered UB by [miri](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=daf3a2246433fe43fdc07d1389c276c9), but also means it does not affect the preexisting UB in this case: ``` let Struct { .. } = *never_ptr; ``` Even though it's likely up for debate since we're not actually reading any data out of the struct, it almost certainly causes inference changes which I do *NOT* want to fix in this PR.
💔 Test failed - checks-actions |
@bors retry |
…iaskrgr Rollup of 5 pull requests Successful merges: - rust-lang#129392 (Do not consider match/let/ref of place that evaluates to `!` to diverge, disallow coercions from them too) - rust-lang#131279 (update "build/host" symlink comment) - rust-lang#131312 (On function and method calls in patterns, link to the book) - rust-lang#131315 (bootstrap: add `std_features` config) - rust-lang#131316 (Fix typo in primitive_docs.rs) r? `@ghost` `@rustbot` modify labels: rollup
…verge-but-more, r=lcnr Do not consider match/let/ref of place that evaluates to `!` to diverge, disallow coercions from them too Fixes rust-lang#117288. This PR implements a heuristic which disables two things that are currently being performed on the HIR when we have **expressions that involve place-like expressions that point to `!`**. Specifically, it will (in certain cases explained below): ### (1.) Disable the `NeverToAny` coercion we implicitly insert for `!`. Which fixes this inadvertent, sneaky unsoundness: ``` unsafe { let x: *const ! = &0 as *const u8 as *const !; let _: () = *x; } ``` which is UB because currently rust emits an *implicit* NeverToAny coercion even though we really shouldn't be, since there's no read of the value pointed by `x`. ### (2.) Disable the logic which considers expression which evaluate to `!` to diverge, which affects the type returned by the containing block. Which fixes this unsoundness: ``` fn make_up_a_value<T>() -> T { unsafe { let x: *const ! = &0 as *const u8 as *const !; let _ = *x; } } ``` We disable these two operations **if** the expression is a place-like expression (locals, statics, field projections, index operations, and deref operations), and if the parent expression is either: (1.) the LHS of an assignment (2.) AddrOf (3.) A match or let **unless** all of the *patterns consitute a read*, which is explained below: And finally, a pattern currently is considered to constitute a read **unless** it is a wildcard, or an OR pattern. An OR pattern is considered to constitute a read if all of its subpatterns constitute a read, to remain as conservative as possible in cases like `_ | subpat` or `subpat | _`. All other patterns are considered currently to constitute a read. Specifically, because `NeverToAny` is a coercion performed on a *value* and not a *place*, `Struct { .. }` on a `!` type must be a coercion currently, and we currently rely on this behavior to allow us to perform coercions like `let _: i32 = x;` where `x: !`. This is already considered UB by [miri](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=daf3a2246433fe43fdc07d1389c276c9), but also means it does not affect the preexisting UB in this case: ``` let Struct { .. } = *never_ptr; ``` Even though it's likely up for debate since we're not actually reading any data out of the struct, it almost certainly causes inference changes which I do *NOT* want to fix in this PR.
…iaskrgr Rollup of 5 pull requests Successful merges: - rust-lang#129392 (Do not consider match/let/ref of place that evaluates to `!` to diverge, disallow coercions from them too) - rust-lang#131279 (update "build/host" symlink comment) - rust-lang#131312 (On function and method calls in patterns, link to the book) - rust-lang#131315 (bootstrap: add `std_features` config) - rust-lang#131316 (Fix typo in primitive_docs.rs) r? `@ghost` `@rustbot` modify labels: rollup
Rollup merge of rust-lang#129392 - compiler-errors:raw-ref-op-doesnt-diverge-but-more, r=lcnr Do not consider match/let/ref of place that evaluates to `!` to diverge, disallow coercions from them too Fixes rust-lang#117288. This PR implements a heuristic which disables two things that are currently being performed on the HIR when we have **expressions that involve place-like expressions that point to `!`**. Specifically, it will (in certain cases explained below): ### (1.) Disable the `NeverToAny` coercion we implicitly insert for `!`. Which fixes this inadvertent, sneaky unsoundness: ``` unsafe { let x: *const ! = &0 as *const u8 as *const !; let _: () = *x; } ``` which is UB because currently rust emits an *implicit* NeverToAny coercion even though we really shouldn't be, since there's no read of the value pointed by `x`. ### (2.) Disable the logic which considers expression which evaluate to `!` to diverge, which affects the type returned by the containing block. Which fixes this unsoundness: ``` fn make_up_a_value<T>() -> T { unsafe { let x: *const ! = &0 as *const u8 as *const !; let _ = *x; } } ``` We disable these two operations **if** the expression is a place-like expression (locals, statics, field projections, index operations, and deref operations), and if the parent expression is either: (1.) the LHS of an assignment (2.) AddrOf (3.) A match or let **unless** all of the *patterns consitute a read*, which is explained below: And finally, a pattern currently is considered to constitute a read **unless** it is a wildcard, or an OR pattern. An OR pattern is considered to constitute a read if all of its subpatterns constitute a read, to remain as conservative as possible in cases like `_ | subpat` or `subpat | _`. All other patterns are considered currently to constitute a read. Specifically, because `NeverToAny` is a coercion performed on a *value* and not a *place*, `Struct { .. }` on a `!` type must be a coercion currently, and we currently rely on this behavior to allow us to perform coercions like `let _: i32 = x;` where `x: !`. This is already considered UB by [miri](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=daf3a2246433fe43fdc07d1389c276c9), but also means it does not affect the preexisting UB in this case: ``` let Struct { .. } = *never_ptr; ``` Even though it's likely up for debate since we're not actually reading any data out of the struct, it almost certainly causes inference changes which I do *NOT* want to fix in this PR.
Fixes #117288.
This PR implements a heuristic which disables two things that are currently being performed on the HIR when we have expressions that involve place-like expressions that point to
!
. Specifically, it will (in certain cases explained below):(1.) Disable the
NeverToAny
coercion we implicitly insert for!
.Which fixes this inadvertent, sneaky unsoundness:
which is UB because currently rust emits an implicit NeverToAny coercion even though we really shouldn't be, since there's no read of the value pointed by
x
.(2.) Disable the logic which considers expression which evaluate to
!
to diverge, which affects the type returned by the containing block.Which fixes this unsoundness:
We disable these two operations if the expression is a place-like expression (locals, statics, field projections, index operations, and deref operations), and if the parent expression is either:
(1.) the LHS of an assignment
(2.) AddrOf
(3.) A match or let unless all of the patterns consitute a read, which is explained below:
And finally, a pattern currently is considered to constitute a read unless it is a wildcard, or an OR pattern. An OR pattern is considered to constitute a read if all of its subpatterns constitute a read, to remain as conservative as possible in cases like
_ | subpat
orsubpat | _
.All other patterns are considered currently to constitute a read. Specifically, because
NeverToAny
is a coercion performed on a value and not a place,Struct { .. }
on a!
type must be a coercion currently, and we currently rely on this behavior to allow us to perform coercions likelet _: i32 = x;
wherex: !
.This is already considered UB by miri, but also means it does not affect the preexisting UB in this case:
Even though it's likely up for debate since we're not actually reading any data out of the struct, it almost certainly causes inference changes which I do NOT want to fix in this PR.