-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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 promote &mut of a non-ZST ever #75585
Conversation
r? @davidtwco (rust_highfive has picked a reviewer for you, use r? to override) |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
r? @oli-obk |
@bors try (for crater) |
⌛ Trying commit 300900ec7474859b619ae161eb847f5a4f5928bd with merge ffa4a0215752773248fb0f0a8092f1c3e7907e9e... |
☀️ Try build successful - checks-actions, checks-azure |
@craterbot check |
👌 Experiment ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more |
Left a comment on the issue (#75556 (comment)):
Also, you write:
But aren'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.
Implementation seems fine, but can you add a test that compiled before and now doesn't?
E.g.: static mut FOO: Option<&mut [i32]> = Some(&mut [1, 2, 3]);
Oh, that's a good point. I was just going by this already existing in #21744, but it seems that same analysis was doing something else back then. Interestingly, in Rust 1.35 this actually fails, even though the analysis already carried this exception:
Rust 1.36 seems to be the first version where this is accepted. |
Keep in mind that only recently (last year?), did we actually uncouple promotion from const-checking. Also, promotion was in the compiler for a long time (predating MIR itself) but it wasn't exposed to the user (i.e. borrow-checking didn't know about it) until the RFC was accepted, much later. |
This one is even more interesting: pub static mut FOO: Option<&mut [i32]> = Some(&mut [1, 2, 3]); It works in Rust 1.21, fails with 1.22 - 1.35, and then works again since 1.36. Wtf.
Well it did also accept something, until 1.21, it seems? |
Hmm, if it broke in between, that means we weren't promoting it, and it should've stayed that way (hopefully that means crater won't find anything. What did 1.36 do to start promoting it again? Sounds like a bug.
No, I think 1.21 must've been when I introduced the "outermost scope" rule, i.e. these two started being different:
|
Rust 1.36 is when we got "NLL for Rust 2015", not sure if that would have an effect? Maybe this indicates a difference between HIR and MIR promotion / borrowck? |
Done. |
Were you testing with Anyway I was expecting a change to MIR promotion, but maybe MIR promotion was wrong all along? Okay I went and checked, and indeed it looks like MIR borrowck is the culprit here, which explains why we ended up with this bug: the MIR version of the code was just never 100% correct, so if we were trying to maintain its behavior, we were keeping original bugs around. |
That makes sense. |
This comment has been minimized.
This comment has been minimized.
🚧 Experiment ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more |
🎉 Experiment
|
@bors r+ Bugfix, simpler compiler code and no regressions, I see no reason to not merge this. |
📌 Commit 28ddda7 has been approved by |
Do not promote &mut of a non-ZST ever Since ~pre-1.0~ 1.36, we have accepted code like this: ```rust static mut TEST: &'static mut [i32] = { let x = &mut [1,2,3]; x }; ``` I tracked it back to rust-lang#21744, but unfortunately could not find any discussion or RFC that would explain why we thought this was a good idea. And it's not, it breaks all sorts of things -- see rust-lang#75556. To fix rust-lang#75556, we have to stop promoting non-ZST mutable references no matter the context, which is what this PR does. It's a breaking change. Notice that this still works, since it does not rely on promotion: ```rust static mut TEST: &'static mut [i32] = &mut [0,1,2]; ``` Cc @rust-lang/wg-const-eval
☀️ Test successful - checks-actions, checks-azure |
I marked this as relnotes but I am not fully sure -- I'll leave it up to the release team if they think this should be mentioned or not. |
…tatic-morse Some promotion cleanup Based on top of both rust-lang#75502 and rust-lang#75585, this does some cleanup of the promotion code. The last 2 commits are new. * Remove the remaining cases where `const fn` is treated different from `fn`. This means no longer promoting ptr-to-int casts, raw ptr operations, and union field accesses in `const fn` -- or anywhere, for that matter. These are all unstable in const-context so this should not break any stable code. Fixes rust-lang#75586. * ~~Promote references to statics even outside statics (i.e., in functions) for consistency.~~ * Promote `&mut []` everywhere, not just in non-`const` functions, for consistency. * Explain why we do not promote deref's of statics outside statics. ~~(This is the only remaining direct user of `const_kind`.)~~ This can only land once the other two PRs land; I am mostly putting this up already because I couldn't wait ;) and to get some feedback from @rust-lang/wg-const-eval .
…tatic-morse Some promotion cleanup Based on top of both rust-lang#75502 and rust-lang#75585, this does some cleanup of the promotion code. The last 2 commits are new. * Remove the remaining cases where `const fn` is treated different from `fn`. This means no longer promoting ptr-to-int casts, raw ptr operations, and union field accesses in `const fn` -- or anywhere, for that matter. These are all unstable in const-context so this should not break any stable code. Fixes rust-lang#75586. * ~~Promote references to statics even outside statics (i.e., in functions) for consistency.~~ * Promote `&mut []` everywhere, not just in non-`const` functions, for consistency. * Explain why we do not promote deref's of statics outside statics. ~~(This is the only remaining direct user of `const_kind`.)~~ This can only land once the other two PRs land; I am mostly putting this up already because I couldn't wait ;) and to get some feedback from @rust-lang/wg-const-eval .
…tatic-morse Some promotion cleanup Based on top of both rust-lang#75502 and rust-lang#75585, this does some cleanup of the promotion code. The last 2 commits are new. * Remove the remaining cases where `const fn` is treated different from `fn`. This means no longer promoting ptr-to-int casts, raw ptr operations, and union field accesses in `const fn` -- or anywhere, for that matter. These are all unstable in const-context so this should not break any stable code. Fixes rust-lang#75586. * ~~Promote references to statics even outside statics (i.e., in functions) for consistency.~~ * Promote `&mut []` everywhere, not just in non-`const` functions, for consistency. * Explain why we do not promote deref's of statics outside statics. ~~(This is the only remaining direct user of `const_kind`.)~~ This can only land once the other two PRs land; I am mostly putting this up already because I couldn't wait ;) and to get some feedback from @rust-lang/wg-const-eval .
…tatic-morse Some promotion cleanup Based on top of both rust-lang#75502 and rust-lang#75585, this does some cleanup of the promotion code. The last 2 commits are new. * Remove the remaining cases where `const fn` is treated different from `fn`. This means no longer promoting ptr-to-int casts, raw ptr operations, and union field accesses in `const fn` -- or anywhere, for that matter. These are all unstable in const-context so this should not break any stable code. Fixes rust-lang#75586. * ~~Promote references to statics even outside statics (i.e., in functions) for consistency.~~ * Promote `&mut []` everywhere, not just in non-`const` functions, for consistency. * Explain why we do not promote deref's of statics outside statics. ~~(This is the only remaining direct user of `const_kind`.)~~ This can only land once the other two PRs land; I am mostly putting this up already because I couldn't wait ;) and to get some feedback from @rust-lang/wg-const-eval .
…tic-morse Some promotion cleanup Based on top of both rust-lang#75502 and rust-lang#75585, this does some cleanup of the promotion code. The last 2 commits are new. * Remove the remaining cases where `const fn` is treated different from `fn`. This means no longer promoting ptr-to-int casts, raw ptr operations, and union field accesses in `const fn` -- or anywhere, for that matter. These are all unstable in const-context so this should not break any stable code. Fixes rust-lang#75586. * ~~Promote references to statics even outside statics (i.e., in functions) for consistency.~~ * Promote `&mut []` everywhere, not just in non-`const` functions, for consistency. * Explain why we do not promote deref's of statics outside statics. ~~(This is the only remaining direct user of `const_kind`.)~~ This can only land once the other two PRs land; I am mostly putting this up already because I couldn't wait ;) and to get some feedback from `@rust-lang/wg-const-eval` .
Clean up some of the pkgsrc Makefile, there's still lots in here that should just be deleted though. Switch SunOS to the illumos bootstrap by default. Version 1.48.0 (2020-11-19) ========================== Language -------- - [The `unsafe` keyword is now syntactically permitted on modules.][75857] This is still rejected *semantically*, but can now be parsed by procedural macros. Compiler -------- - [Stabilised the `-C link-self-contained=<yes|no>` compiler flag.][76158] This tells `rustc` whether to link its own C runtime and libraries or to rely on a external linker to find them. (Supported only on `windows-gnu`, `linux-musl`, and `wasi` platforms.) - [You can now use `-C target-feature=+crt-static` on `linux-gnu` targets.][77386] Note: If you're using cargo you must explicitly pass the `--target` flag. - [Added tier 2\* support for `aarch64-unknown-linux-musl`.][76420] \* Refer to Rust's [platform support page][forge-platform-support] for more information on Rust's tiered platform support. Libraries --------- - [`io::Write` is now implemented for `&ChildStdin` `&Sink`, `&Stdout`, and `&Stderr`.][76275] - [All arrays of any length now implement `TryFrom<Vec<T>>`.][76310] - [The `matches!` macro now supports having a trailing comma.][74880] - [`Vec<A>` now implements `PartialEq<[B]>` where `A: PartialEq<B>`.][74194] - [The `RefCell::{replace, replace_with, clone}` methods now all use `#[track_caller]`.][77055] Stabilized APIs --------------- - [`slice::as_ptr_range`] - [`slice::as_mut_ptr_range`] - [`VecDeque::make_contiguous`] - [`future::pending`] - [`future::ready`] The following previously stable methods are now `const fn`'s: - [`Option::is_some`] - [`Option::is_none`] - [`Option::as_ref`] - [`Result::is_ok`] - [`Result::is_err`] - [`Result::as_ref`] - [`Ordering::reverse`] - [`Ordering::then`] Cargo ----- Rustdoc ------- - [You can now link to items in `rustdoc` using the intra-doc link syntax.][74430] E.g. ``/// Uses [`std::future`]`` will automatically generate a link to `std::future`'s documentation. See ["Linking to items by name"][intradoc-links] for more information. - [You can now specify `#[doc(alias = "<alias>")]` on items to add search aliases when searching through `rustdoc`'s UI.][75740] Compatibility Notes ------------------- - [Promotion of references to `'static` lifetime inside `const fn` now follows the same rules as inside a `fn` body.][75502] In particular, `&foo()` will not be promoted to `'static` lifetime any more inside `const fn`s. - [Associated type bindings on trait objects are now verified to meet the bounds declared on the trait when checking that they implement the trait.][27675] - [When trait bounds on associated types or opaque types are ambiguous, the compiler no longer makes an arbitrary choice on which bound to use.][54121] - [Fixed recursive nonterminals not being expanded in macros during pretty-print/reparse check.][77153] This may cause errors if your macro wasn't correctly handling recursive nonterminal tokens. - [`&mut` references to non zero-sized types are no longer promoted.][75585] - [`rustc` will now warn if you use attributes like `#[link_name]` or `#[cold]` in places where they have no effect.][73461] - [Updated `_mm256_extract_epi8` and `_mm256_extract_epi16` signatures in `arch::{x86, x86_64}` to return `i32` to match the vendor signatures.][73166] - [`mem::uninitialized` will now panic if any inner types inside a struct or enum disallow zero-initialization.][71274] - [`#[target_feature]` will now error if used in a place where it has no effect.][78143] - [Foreign exceptions are now caught by `catch_unwind` and will cause an abort.][70212] Note: This behaviour is not guaranteed and is still considered undefined behaviour, see the [`catch_unwind`] documentation for further information. Internal Only ------------- These changes provide no direct user facing benefits, but represent significant improvements to the internals and overall performance of rustc and related tools. - [Building `rustc` from source now uses `ninja` by default over `make`.][74922] You can continue building with `make` by setting `ninja=false` in your `config.toml`. - [cg_llvm: `fewer_names` in `uncached_llvm_type`][76030] - [Made `ensure_sufficient_stack()` non-generic][76680] [78143]: rust-lang/rust#78143 [76680]: rust-lang/rust#76680 [76030]: rust-lang/rust#76030 [70212]: rust-lang/rust#70212 [27675]: rust-lang/rust#27675 [54121]: rust-lang/rust#54121 [71274]: rust-lang/rust#71274 [77386]: rust-lang/rust#77386 [77153]: rust-lang/rust#77153 [77055]: rust-lang/rust#77055 [76275]: rust-lang/rust#76275 [76310]: rust-lang/rust#76310 [76420]: rust-lang/rust#76420 [76158]: rust-lang/rust#76158 [75857]: rust-lang/rust#75857 [75585]: rust-lang/rust#75585 [75740]: rust-lang/rust#75740 [75502]: rust-lang/rust#75502 [74880]: rust-lang/rust#74880 [74922]: rust-lang/rust#74922 [74430]: rust-lang/rust#74430 [74194]: rust-lang/rust#74194 [73461]: rust-lang/rust#73461 [73166]: rust-lang/rust#73166 [intradoc-links]: https://doc.rust-lang.org/rustdoc/linking-to-items-by-name.html [`catch_unwind`]: https://doc.rust-lang.org/std/panic/fn.catch_unwind.html [`Option::is_some`]: https://doc.rust-lang.org/std/option/enum.Option.html#method.is_some [`Option::is_none`]: https://doc.rust-lang.org/std/option/enum.Option.html#method.is_none [`Option::as_ref`]: https://doc.rust-lang.org/std/option/enum.Option.html#method.as_ref [`Result::is_ok`]: https://doc.rust-lang.org/std/result/enum.Result.html#method.is_ok [`Result::is_err`]: https://doc.rust-lang.org/std/result/enum.Result.html#method.is_err [`Result::as_ref`]: https://doc.rust-lang.org/std/result/enum.Result.html#method.as_ref [`Ordering::reverse`]: https://doc.rust-lang.org/std/cmp/enum.Ordering.html#method.reverse [`Ordering::then`]: https://doc.rust-lang.org/std/cmp/enum.Ordering.html#method.then [`slice::as_ptr_range`]: https://doc.rust-lang.org/std/primitive.slice.html#method.as_ptr_range [`slice::as_mut_ptr_range`]: https://doc.rust-lang.org/std/primitive.slice.html#method.as_mut_ptr_range [`VecDeque::make_contiguous`]: https://doc.rust-lang.org/std/collections/struct.VecDeque.html#method.make_contiguous [`future::pending`]: https://doc.rust-lang.org/std/future/fn.pending.html [`future::ready`]: https://doc.rust-lang.org/std/future/fn.ready.html
Pkgsrc changes: * Compensate for files being moved around upstream. * Introduce optional, on-by-default semi-static building of cargo, using the internal curl and openssl sources. This reduces the dynamic dependencies of cargo and therefore the rust package itself. Ref. options.mk. * The 1.47.0 bootstrap kits have been re-built with the above option turned on, so no longer depends on curl or openssl from pkgsrc and/or from earlier OS or pkgsrc versions. This should hopefully fix installation of rust with non-default PREFIX, ref. PR#54453. Upstream changes: Version 1.48.0 (2020-11-19) ========================== Language -------- - [The `unsafe` keyword is now syntactically permitted on modules.][75857] This is still rejected *semantically*, but can now be parsed by procedural macros. Compiler -------- - [Stabilised the `-C link-self-contained=<yes|no>` compiler flag.][76158] This tells `rustc` whether to link its own C runtime and libraries or to rely on a external linker to find them. (Supported only on `windows-gnu`, `linux-musl`, and `wasi` platforms.) - [You can now use `-C target-feature=+crt-static` on `linux-gnu` targets.] [77386] Note: If you're using cargo you must explicitly pass the `--target` flag. - [Added tier 2\* support for `aarch64-unknown-linux-musl`.][76420] \* Refer to Rust's [platform support page][forge-platform-support] for more information on Rust's tiered platform support. Libraries --------- - [`io::Write` is now implemented for `&ChildStdin` `&Sink`, `&Stdout`, and `&Stderr`.][76275] - [All arrays of any length now implement `TryFrom<Vec<T>>`.][76310] - [The `matches!` macro now supports having a trailing comma.][74880] - [`Vec<A>` now implements `PartialEq<[B]>` where `A: PartialEq<B>`.][74194] - [The `RefCell::{replace, replace_with, clone}` methods now all use `#[track_caller]`.][77055] Stabilized APIs --------------- - [`slice::as_ptr_range`] - [`slice::as_mut_ptr_range`] - [`VecDeque::make_contiguous`] - [`future::pending`] - [`future::ready`] The following previously stable methods are now `const fn`'s: - [`Option::is_some`] - [`Option::is_none`] - [`Option::as_ref`] - [`Result::is_ok`] - [`Result::is_err`] - [`Result::as_ref`] - [`Ordering::reverse`] - [`Ordering::then`] Cargo ----- Rustdoc ------- - [You can now link to items in `rustdoc` using the intra-doc link syntax.][74430] E.g. ``/// Uses [`std::future`]`` will automatically generate a link to `std::future`'s documentation. See ["Linking to items by name"][intradoc-links] for more information. - [You can now specify `#[doc(alias = "<alias>")]` on items to add search aliases when searching through `rustdoc`'s UI.][75740] Compatibility Notes ------------------- - [Promotion of references to `'static` lifetime inside `const fn` now follows the same rules as inside a `fn` body.][75502] In particular, `&foo()` will not be promoted to `'static` lifetime any more inside `const fn`s. - [Associated type bindings on trait objects are now verified to meet the bounds declared on the trait when checking that they implement the trait.][27675] - [When trait bounds on associated types or opaque types are ambiguous, the compiler no longer makes an arbitrary choice on which bound to use.][54121] - [Fixed recursive nonterminals not being expanded in macros during pretty-print/reparse check.][77153] This may cause errors if your macro wasn't correctly handling recursive nonterminal tokens. - [`&mut` references to non zero-sized types are no longer promoted.][75585] - [`rustc` will now warn if you use attributes like `#[link_name]` or `#[cold]` in places where they have no effect.][73461] - [Updated `_mm256_extract_epi8` and `_mm256_extract_epi16` signatures in `arch::{x86, x86_64}` to return `i32` to match the vendor signatures.][73166] - [`mem::uninitialized` will now panic if any inner types inside a struct or enum disallow zero-initialization.][71274] - [`#[target_feature]` will now error if used in a place where it has no effect.][78143] - [Foreign exceptions are now caught by `catch_unwind` and will cause an abort.][70212] Note: This behaviour is not guaranteed and is still considered undefined behaviour, see the [`catch_unwind`] documentation for further information. Internal Only ------------- These changes provide no direct user facing benefits, but represent significant improvements to the internals and overall performance of rustc and related tools. - [Building `rustc` from source now uses `ninja` by default over `make`.][74922] You can continue building with `make` by setting `ninja=false` in your `config.toml`. - [cg_llvm: `fewer_names` in `uncached_llvm_type`][76030] - [Made `ensure_sufficient_stack()` non-generic][76680] [78143]: rust-lang/rust#78143 [76680]: rust-lang/rust#76680 [76030]: rust-lang/rust#76030 [70212]: rust-lang/rust#70212 [27675]: rust-lang/rust#27675 [54121]: rust-lang/rust#54121 [71274]: rust-lang/rust#71274 [77386]: rust-lang/rust#77386 [77153]: rust-lang/rust#77153 [77055]: rust-lang/rust#77055 [76275]: rust-lang/rust#76275 [76310]: rust-lang/rust#76310 [76420]: rust-lang/rust#76420 [76158]: rust-lang/rust#76158 [75857]: rust-lang/rust#75857 [75585]: rust-lang/rust#75585 [75740]: rust-lang/rust#75740 [75502]: rust-lang/rust#75502 [74880]: rust-lang/rust#74880 [74922]: rust-lang/rust#74922 [74430]: rust-lang/rust#74430 [74194]: rust-lang/rust#74194 [73461]: rust-lang/rust#73461 [73166]: rust-lang/rust#73166 [intradoc-links]: https://doc.rust-lang.org/rustdoc/linking-to-items-by-name.html [`catch_unwind`]: https://doc.rust-lang.org/std/panic/fn.catch_unwind.html [`Option::is_some`]: https://doc.rust-lang.org/std/option/enum.Option.html#method.is_some [`Option::is_none`]: https://doc.rust-lang.org/std/option/enum.Option.html#method.is_none [`Option::as_ref`]: https://doc.rust-lang.org/std/option/enum.Option.html#method.as_ref [`Result::is_ok`]: https://doc.rust-lang.org/std/result/enum.Result.html#method.is_ok [`Result::is_err`]: https://doc.rust-lang.org/std/result/enum.Result.html#method.is_err [`Result::as_ref`]: https://doc.rust-lang.org/std/result/enum.Result.html#method.as_ref [`Ordering::reverse`]: https://doc.rust-lang.org/std/cmp/enum.Ordering.html#method.reverse [`Ordering::then`]: https://doc.rust-lang.org/std/cmp/enum.Ordering.html#method.then [`slice::as_ptr_range`]: https://doc.rust-lang.org/std/primitive.slice.html#method.as_ptr_range [`slice::as_mut_ptr_range`]: https://doc.rust-lang.org/std/primitive.slice.html#method.as_mut_ptr_range [`VecDeque::make_contiguous`]: https://doc.rust-lang.org/std/collections/struct.VecDeque.html#method.make_contiguous [`future::pending`]: https://doc.rust-lang.org/std/future/fn.pending.html [`future::ready`]: https://doc.rust-lang.org/std/future/fn.ready.html
Since
pre-1.01.36, we have accepted code like this:I tracked it back to #21744, but unfortunately could not find any discussion or RFC that would explain why we thought this was a good idea. And it's not, it breaks all sorts of things -- see #75556.
To fix #75556, we have to stop promoting non-ZST mutable references no matter the context, which is what this PR does. It's a breaking change.
Notice that this still works, since it does not rely on promotion:
Cc @rust-lang/wg-const-eval