-
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
const_mut_refs: allow mutable pointers to statics #120932
Conversation
// `StorageDead` in every control flow path leading to a `return` terminator. | ||
// The good news is that interning will detect if any unexpected mutable | ||
// pointer slips through. | ||
if place.is_indirect_first_projection() || self.local_has_storage_dead(place.local) |
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 assume this runs after the deref'er? Debug assertions would fire if the Deref
was later in the projection chain.
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.
Ah, I get a bunch of debug assertion failures.^^
Hm, but... the "reborrow" checks only check the first projection. How does that make sense then?
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.
derefer is still after borrowck. We haven't managed to move it earlier yet
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 means &mut (*ptr).field
will not hit the reborrow code path in const-checking. I wonder if there's an example here where this PR changes behavior because of that...
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.
Ah no, not hitting that codepath is largely inconsequential for shared references since the qualif will say "there is no interior mutability" for any path that involves a Deref
, and thus just allow it.
So there's just the mutable reborrow path that could act strangely. I'm surprised we allow mutable reborrows at all given that we don't usually want to allow anything with mutable borrows.
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.
Okay, I think for mutable references that reborrow logic largely serves to avoid duplicate errors, and to paper over particular desugarings (like how _ as *mut _
becomes a reborrow).
I can't wait to rip out all this half-effective logic when we stabilize const_mut_refs
.^^
This comment has been minimized.
This comment has been minimized.
b5989ee
to
ea09986
Compare
This comment has been minimized.
This comment has been minimized.
ea09986
to
590171e
Compare
This comment has been minimized.
This comment has been minimized.
590171e
to
81f3568
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.
FWIW this file does not trigger error code 0017. Nor does the other file trigger error code 0388.
Cc #120935
This comment has been minimized.
This comment has been minimized.
81f3568
to
41fcbdb
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.
before I try to understand the full logic, here are some things I def don't understand
check_consts: fix duplicate errors, make importance consistent This is stuff I noticed while working on rust-lang#120932, but it's orthogonal to that PR. r? `@oli-obk`
check_consts: fix duplicate errors, make importance consistent This is stuff I noticed while working on rust-lang#120932, but it's orthogonal to that PR. r? ``@oli-obk``
41fcbdb
to
9482599
Compare
9482599
to
d17bd91
Compare
Rollup merge of rust-lang#120933 - RalfJung:const-check-misc, r=oli-obk check_consts: fix duplicate errors, make importance consistent This is stuff I noticed while working on rust-lang#120932, but it's orthogonal to that PR. r? ``@oli-obk``
Rollup of 8 pull requests Successful merges: - rust-lang#119032 (Use a hardcoded constant instead of calling OpenProcessToken.) - rust-lang#120932 (const_mut_refs: allow mutable pointers to statics) - rust-lang#121059 (Add and use a simple extension trait derive macro in the compiler) - rust-lang#121135 (coverage: Discard spans that fill the entire function body) - rust-lang#121187 (Add examples to document the return type of quickselect functions) - rust-lang#121191 (Add myself to review rotation (and a rustbot ping)) - rust-lang#121192 (Give some intrinsics fallback bodies) - rust-lang#121197 (Ensure `./configure` works when `configure.py` path contains spaces) r? `@ghost` `@rustbot` modify labels: rollup
Rollup merge of rust-lang#120932 - RalfJung:mut-ptr-to-static, r=oli-obk const_mut_refs: allow mutable pointers to statics Fixes rust-lang#118447 Writing this PR became a bit messy, see [Zulip](https://rust-lang.zulipchat.com/#narrow/stream/146212-t-compiler.2Fconst-eval/topic/Statics.20pointing.20to.20interior.20mutable.20statics) for some of my journey.^^ Turns out there was a long-standing bug in our qualif logic that led to us incorrectly classifying certain places as "no interior mut" when they actually had interior mut. Due to that the `const_refs_to_cell` feature gate was required far less often than it otherwise would, e.g. in [this code](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=9e0c042c451b3d11d64dd6263679a164). Fixing this however would be a massive breaking change all over libcore and likely the wider ecosystem. So I also changed the const-checking logic to just not require the feature gate for the affected cases. While doing so I discovered a bunch of logic that is not explained and that I could not explain. However I think stabilizing some const-eval feature will make most of that logic inconsequential so I just added some FIXMEs and left it at that. r? `@oli-obk`
This turned out to be a breaking change: #121250. Let's see if we can crater this after the fact... @craterbot run start=dfdbe30004a095ad63951c4cd6e10a9a971a7399 end=ba824a2e25948a86596ccf7594afe548020e86e6 mode=check-only |
👌 Experiment ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more |
Since this crater run is on the critical path for what to do with #121250... |
📝 Configuration of the ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more |
@craterbot start=master#dfdbe30004a095ad63951c4cd6e10a9a971a7399 end=master#ba824a2e25948a86596ccf7594afe548020e86e6 |
📝 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
|
(Will post findings in #121250) |
This is the next upgrade to the Rust toolchain, from 1.77.1 to 1.78.0 (i.e. the latest) [1]. See the upgrade policy [2] and the comments on the first upgrade in commit 3ed03f4 ("rust: upgrade to Rust 1.68.2"). # Unstable features There have been no changes to the set of unstable features used in our own code. Therefore, the only unstable features allowed to be used outside the `kernel` crate is still `new_uninit`. However, since we are finally dropping our `alloc` fork [3], all the unstable features used by `alloc` (~30 language ones, ~60 library ones) are not a concern anymore. This reduces the maintanance burden, increases the chances of new compiler versions working without changes and gets us closer to the goal of supporting several compiler versions. It also means that, ignoring non-language/library features, we are currently left with just the few language features needed to implement the kernel `Arc`, the `new_uninit` library feature, the `compiler_builtins` marker and the few `no_*` `cfg`s we pass when compiling `core`/`alloc`. Please see [4] for details. # Required changes ## LLVM's data layout Rust 1.77.0 (i.e. the previous upgrade) introduced a check for matching LLVM data layouts [5]. Then, Rust 1.78.0 upgraded LLVM's bundled major version from 17 to 18 [6], which changed the data layout in x86 [7]. Thus update the data layout in our custom target specification for x86 so that the compiler does not complain about the mismatch: error: data-layout for target `target-5559158138856098584`, `e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128`, differs from LLVM target's `x86_64-linux-gnu` default layout, `e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128` In the future, the goal is to drop the custom target specification files. Meanwhile, if we want to support other LLVM versions used in `rustc` (e.g. for LTO), we will need to add some extra logic (e.g. conditional on LLVM's version, or extracting the data layout from an existing built-in target specification). ## `unused_imports` Rust's `unused_imports` lint covers both unused and redudant imports. Now, in 1.78.0, the lint detects more cases of redundant imports [8]. Thus the previous commit cleaned them up. ## Clippy's `new_without_default` Clippy now suggests to implement `Default` even when `new()` is `const`, since `Default::default()` may call `const` functions even if it is not `const` itself [9]. Thus the previous commit added the implementation. # Other changes in Rust Rust 1.78.0 introduces `feature(asm_goto)` [10] [11]. This feature was discussed in the past [12]. Rust 1.78.0 introduced support for mutable pointers to Rust statics, including a test case for the Linux kernel's `VTABLE` use case [13]. Rust 1.78.0 with debug assertions enabled (i.e. `-Cdebug-assertions=y`, kernel's `CONFIG_RUST_DEBUG_ASSERTIONS=y`) will now always check all unsafe preconditions, without a way to opt-out for particular cases [14]. Rust 1.78.0 also improved a couple issues we reported when giving feedback for the new `--check-cfg` feature [15] [16]. # `alloc` upgrade and reviewing As mentioned above, compiler upgrades will not update `alloc` anymore, since we are dropping our `alloc` fork [3]. As a bonus, even if that series is not applied, the new compiler release happens to build cleanly the existing `alloc` too (i.e. the previous version's). Link: https://github.com/rust-lang/rust/blob/stable/RELEASES.md#version-1770-2024-03-21 [1] Link: https://rust-for-linux.com/rust-version-policy [2] Link: https://lore.kernel.org/rust-for-linux/[email protected]/ [3] Link: Rust-for-Linux#2 [4] Link: rust-lang/rust#120062 [5] Link: rust-lang/rust#120055 [6] Link: https://reviews.llvm.org/D86310 [7] Link: rust-lang/rust#117772 [8] Link: rust-lang/rust-clippy#10903 [9] Link: rust-lang/rust#119365 [10] Link: rust-lang/rust#119364 [11] Link: https://lore.kernel.org/rust-for-linux/[email protected]/ [12] Link: rust-lang/rust#120932 [13] Link: rust-lang/rust#120969 [14] Link: rust-lang/rust#121202 [15] Link: rust-lang/rust#121237 [16] Signed-off-by: Miguel Ojeda <[email protected]>
This is the next upgrade to the Rust toolchain, from 1.77.1 to 1.78.0 (i.e. the latest) [1]. See the upgrade policy [2] and the comments on the first upgrade in commit 3ed03f4 ("rust: upgrade to Rust 1.68.2"). # Unstable features There have been no changes to the set of unstable features used in our own code. Therefore, the only unstable features allowed to be used outside the `kernel` crate is still `new_uninit`. However, since we are finally dropping our `alloc` fork [3], all the unstable features used by `alloc` (~30 language ones, ~60 library ones) are not a concern anymore. This reduces the maintenance burden, increases the chances of new compiler versions working without changes and gets us closer to the goal of supporting several compiler versions. It also means that, ignoring non-language/library features, we are currently left with just the few language features needed to implement the kernel `Arc`, the `new_uninit` library feature, the `compiler_builtins` marker and the few `no_*` `cfg`s we pass when compiling `core`/`alloc`. Please see [4] for details. # Required changes ## LLVM's data layout Rust 1.77.0 (i.e. the previous upgrade) introduced a check for matching LLVM data layouts [5]. Then, Rust 1.78.0 upgraded LLVM's bundled major version from 17 to 18 [6], which changed the data layout in x86 [7]. Thus update the data layout in our custom target specification for x86 so that the compiler does not complain about the mismatch: error: data-layout for target `target-5559158138856098584`, `e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128`, differs from LLVM target's `x86_64-linux-gnu` default layout, `e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128` In the future, the goal is to drop the custom target specification files. Meanwhile, if we want to support other LLVM versions used in `rustc` (e.g. for LTO), we will need to add some extra logic (e.g. conditional on LLVM's version, or extracting the data layout from an existing built-in target specification). ## `unused_imports` Rust's `unused_imports` lint covers both unused and redundant imports. Now, in 1.78.0, the lint detects more cases of redundant imports [8]. Thus one of the previous patches cleaned them up. ## Clippy's `new_without_default` Clippy now suggests to implement `Default` even when `new()` is `const`, since `Default::default()` may call `const` functions even if it is not `const` itself [9]. Thus one of the previous patches implemented it. # Other changes in Rust Rust 1.78.0 introduced `feature(asm_goto)` [10] [11]. This feature was discussed in the past [12]. Rust 1.78.0 introduced support for mutable pointers to Rust statics, including a test case for the Linux kernel's `VTABLE` use case [13]. Rust 1.78.0 with debug assertions enabled (i.e. `-Cdebug-assertions=y`, kernel's `CONFIG_RUST_DEBUG_ASSERTIONS=y`) now always checks all unsafe preconditions, without a way to opt-out for particular cases [14]. Rust 1.78.0 also improved a couple issues we reported when giving feedback for the new `--check-cfg` feature [15] [16]. # `alloc` upgrade and reviewing As mentioned above, compiler upgrades will not update `alloc` anymore, since we are dropping our `alloc` fork [3]. Link: https://github.com/rust-lang/rust/blob/stable/RELEASES.md#version-1780-2024-05-02 [1] Link: https://rust-for-linux.com/rust-version-policy [2] Link: https://lore.kernel.org/rust-for-linux/[email protected]/ [3] Link: Rust-for-Linux#2 [4] Link: rust-lang/rust#120062 [5] Link: rust-lang/rust#120055 [6] Link: https://reviews.llvm.org/D86310 [7] Link: rust-lang/rust#117772 [8] Link: rust-lang/rust-clippy#10903 [9] Link: rust-lang/rust#119365 [10] Link: rust-lang/rust#119364 [11] Link: https://lore.kernel.org/rust-for-linux/[email protected]/ [12] Link: rust-lang/rust#120932 [13] Link: rust-lang/rust#120969 [14] Link: rust-lang/rust#121202 [15] Link: rust-lang/rust#121237 [16] Signed-off-by: Miguel Ojeda <[email protected]>
This is the next upgrade to the Rust toolchain, from 1.77.1 to 1.78.0 (i.e. the latest) [1]. See the upgrade policy [2] and the comments on the first upgrade in commit 3ed03f4 ("rust: upgrade to Rust 1.68.2"). # Unstable features There have been no changes to the set of unstable features used in our own code. Therefore, the only unstable features allowed to be used outside the `kernel` crate is still `new_uninit`. However, since we are finally dropping our `alloc` fork [3], all the unstable features used by `alloc` (~30 language ones, ~60 library ones) are not a concern anymore. This reduces the maintenance burden, increases the chances of new compiler versions working without changes and gets us closer to the goal of supporting several compiler versions. It also means that, ignoring non-language/library features, we are currently left with just the few language features needed to implement the kernel `Arc`, the `new_uninit` library feature, the `compiler_builtins` marker and the few `no_*` `cfg`s we pass when compiling `core`/`alloc`. Please see [4] for details. # Required changes ## LLVM's data layout Rust 1.77.0 (i.e. the previous upgrade) introduced a check for matching LLVM data layouts [5]. Then, Rust 1.78.0 upgraded LLVM's bundled major version from 17 to 18 [6], which changed the data layout in x86 [7]. Thus update the data layout in our custom target specification for x86 so that the compiler does not complain about the mismatch: error: data-layout for target `target-5559158138856098584`, `e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128`, differs from LLVM target's `x86_64-linux-gnu` default layout, `e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128` In the future, the goal is to drop the custom target specifications. Meanwhile, if we want to support other LLVM versions used in `rustc` (e.g. for LTO), we will need to add some extra logic (e.g. conditional on LLVM's version, or extracting the data layout from an existing built-in target specification). ## `unused_imports` Rust's `unused_imports` lint covers both unused and redundant imports. Now, in 1.78.0, the lint detects more cases of redundant imports [8]. Thus one of the previous patches cleaned them up. ## Clippy's `new_without_default` Clippy now suggests to implement `Default` even when `new()` is `const`, since `Default::default()` may call `const` functions even if it is not `const` itself [9]. Thus one of the previous patches implemented it. # Other changes in Rust Rust 1.78.0 introduced `feature(asm_goto)` [10] [11]. This feature was discussed in the past [12]. Rust 1.78.0 introduced support for mutable pointers to Rust statics, including a test case for the Linux kernel's `VTABLE` use case [13]. Rust 1.78.0 with debug assertions enabled (i.e. `-Cdebug-assertions=y`, kernel's `CONFIG_RUST_DEBUG_ASSERTIONS=y`) now always checks all unsafe preconditions, without a way to opt-out for particular cases [14]. Rust 1.78.0 also improved a couple issues we reported when giving feedback for the new `--check-cfg` feature [15] [16]. # `alloc` upgrade and reviewing As mentioned above, compiler upgrades will not update `alloc` anymore, since we are dropping our `alloc` fork [3]. Link: https://github.com/rust-lang/rust/blob/stable/RELEASES.md#version-1780-2024-05-02 [1] Link: https://rust-for-linux.com/rust-version-policy [2] Link: https://lore.kernel.org/rust-for-linux/[email protected]/ [3] Link: Rust-for-Linux#2 [4] Link: rust-lang/rust#120062 [5] Link: rust-lang/rust#120055 [6] Link: https://reviews.llvm.org/D86310 [7] Link: rust-lang/rust#117772 [8] Link: rust-lang/rust-clippy#10903 [9] Link: rust-lang/rust#119365 [10] Link: rust-lang/rust#119364 [11] Link: https://lore.kernel.org/rust-for-linux/[email protected]/ [12] Link: rust-lang/rust#120932 [13] Link: rust-lang/rust#120969 [14] Link: rust-lang/rust#121202 [15] Link: rust-lang/rust#121237 [16] Signed-off-by: Miguel Ojeda <[email protected]>
check_consts: fix duplicate errors, make importance consistent This is stuff I noticed while working on rust-lang/rust#120932, but it's orthogonal to that PR. r? ``@oli-obk``
check_consts: fix duplicate errors, make importance consistent This is stuff I noticed while working on rust-lang/rust#120932, but it's orthogonal to that PR. r? ``@oli-obk``
This is the next upgrade to the Rust toolchain, from 1.77.1 to 1.78.0 (i.e. the latest) [1]. See the upgrade policy [2] and the comments on the first upgrade in commit 3ed03f4 ("rust: upgrade to Rust 1.68.2"). It is much smaller than previous upgrades, since the `alloc` fork was dropped in commit 9d0441b ("rust: alloc: remove our fork of the `alloc` crate") [3]. # Unstable features There have been no changes to the set of unstable features used in our own code. Therefore, the only unstable features allowed to be used outside the `kernel` crate is still `new_uninit`. However, since we finally dropped our `alloc` fork [3], all the unstable features used by `alloc` (~30 language ones, ~60 library ones) are not a concern anymore. This reduces the maintenance burden, increases the chances of new compiler versions working without changes and gets us closer to the goal of supporting several compiler versions. It also means that, ignoring non-language/library features, we are currently left with just the few language features needed to implement the kernel `Arc`, the `new_uninit` library feature, the `compiler_builtins` marker and the few `no_*` `cfg`s we pass when compiling `core`/`alloc`. Please see [4] for details. # Required changes ## LLVM's data layout Rust 1.77.0 (i.e. the previous upgrade) introduced a check for matching LLVM data layouts [5]. Then, Rust 1.78.0 upgraded LLVM's bundled major version from 17 to 18 [6], which changed the data layout in x86 [7]. Thus update the data layout in our custom target specification for x86 so that the compiler does not complain about the mismatch: error: data-layout for target `target-5559158138856098584`, `e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128`, differs from LLVM target's `x86_64-linux-gnu` default layout, `e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128` In the future, the goal is to drop the custom target specifications. Meanwhile, if we want to support other LLVM versions used in `rustc` (e.g. for LTO), we will need to add some extra logic (e.g. conditional on LLVM's version, or extracting the data layout from an existing built-in target specification). ## `unused_imports` Rust's `unused_imports` lint covers both unused and redundant imports. Now, in 1.78.0, the lint detects more cases of redundant imports [8]. Thus one of the previous patches cleaned them up. ## Clippy's `new_without_default` Clippy now suggests to implement `Default` even when `new()` is `const`, since `Default::default()` may call `const` functions even if it is not `const` itself [9]. Thus one of the previous patches implemented it. # Other changes in Rust Rust 1.78.0 introduced `feature(asm_goto)` [10] [11]. This feature was discussed in the past [12]. Rust 1.78.0 introduced `feature(const_refs_to_static)` [13] to allow referencing statics in constants and extended `feature(const_mut_refs)` to allow raw mutable pointers in constants. Together, this should cover the kernel's `VTABLE` use case. In fact, the implementation [14] in upstream Rust added a test case for it [15]. Rust 1.78.0 with debug assertions enabled (i.e. `-Cdebug-assertions=y`, kernel's `CONFIG_RUST_DEBUG_ASSERTIONS=y`) now always checks all unsafe preconditions, though without a way to opt-out for particular cases [16]. It would be ideal to have a way to selectively disable certain checks per-call site for this one (i.e. not just per check but for particular instances of a check), even if the vast majority of the checks remain in place [17]. Rust 1.78.0 also improved a couple issues we reported when giving feedback for the new `--check-cfg` feature [18] [19]. # `alloc` upgrade and reviewing As mentioned above, compiler upgrades will not update `alloc` anymore, since we dropped our `alloc` fork [3]. Link: https://github.com/rust-lang/rust/blob/stable/RELEASES.md#version-1780-2024-05-02 [1] Link: https://rust-for-linux.com/rust-version-policy [2] Link: https://lore.kernel.org/rust-for-linux/[email protected]/ [3] Link: Rust-for-Linux#2 [4] Link: rust-lang/rust#120062 [5] Link: rust-lang/rust#120055 [6] Link: https://reviews.llvm.org/D86310 [7] Link: rust-lang/rust#117772 [8] Link: rust-lang/rust-clippy#10903 [9] Link: rust-lang/rust#119365 [10] Link: rust-lang/rust#119364 [11] Link: https://lore.kernel.org/rust-for-linux/[email protected]/ [12] Link: rust-lang/rust#119618 [13] Link: rust-lang/rust#120932 [14] Link: https://github.com/rust-lang/rust/pull/120932/files#diff-e6fc1622c46054cd46b1d225c5386c5554564b3b0fa8a03c2dc2d8627a1079d9 [15] Link: rust-lang/rust#120969 [16] Link: Rust-for-Linux#354 [17] Link: rust-lang/rust#121202 [18] Link: rust-lang/rust#121237 [19] Reviewed-by: Alice Ryhl <[email protected]> Link: https://lore.kernel.org/r/[email protected] [ Added a few more details and links I mentioned in the list. - Miguel ] Signed-off-by: Miguel Ojeda <[email protected]>
Fixes #118447
Writing this PR became a bit messy, see Zulip for some of my journey.^^ Turns out there was a long-standing bug in our qualif logic that led to us incorrectly classifying certain places as "no interior mut" when they actually had interior mut. Due to that the
const_refs_to_cell
feature gate was required far less often than it otherwise would, e.g. in this code. Fixing this however would be a massive breaking change all over libcore and likely the wider ecosystem. So I also changed the const-checking logic to just not require the feature gate for the affected cases. While doing so I discovered a bunch of logic that is not explained and that I could not explain. However I think stabilizing some const-eval feature will make most of that logic inconsequential so I just added some FIXMEs and left it at that.r? @oli-obk