-
-
Notifications
You must be signed in to change notification settings - Fork 14.4k
Make casts of pointers to trait objects stricter #120248
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
|
r? @TaKO8Ki (rustbot has picked a reviewer for you, use r? to override) |
| Ok(match *t.kind() { | ||
| ty::Slice(_) | ty::Str => Some(PointerKind::Length), | ||
| ty::Dynamic(tty, _, ty::Dyn) => Some(PointerKind::VTable(tty.principal_def_id())), | ||
| ty::Dynamic(tty, _, ty::Dyn) => Some(PointerKind::VTable(tty.principal())), |
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, ok, so this is fine because we erase regions in check_ptr_ptr_cast.
|
@bors try |
…r=<try> Make casts of pointers to trait objects stricter This is an attempt to `fix` rust-lang#120222 and rust-lang#120217. cc `@oli-obk` `@compiler-errors` `@lcnr`
This comment has been minimized.
This comment has been minimized.
| if let ty::RawPtr(src_pointee) = self.expr_ty.kind() | ||
| && let ty::RawPtr(tgt_pointee) = self.cast_ty.kind() | ||
| { | ||
| if let Ok(Some(src_kind)) = fcx.pointer_kind(src_pointee.ty, self.expr_span) | ||
| && let Ok(Some(tgt_kind)) = | ||
| fcx.pointer_kind(tgt_pointee.ty, self.cast_span) | ||
| { | ||
| match (src_kind, tgt_kind) { | ||
| // When casting a raw pointer to another raw pointer, we cannot convert the cast into | ||
| // a coercion because the pointee types might only differ in regions, which HIR typeck | ||
| // cannot distinguish. This would cause us to erroneously discard a cast which will | ||
| // lead to a borrowck error like #113257. | ||
| // We still did a coercion above to unify inference variables for `ptr as _` casts. | ||
| // This does cause us to miss some trivial casts in the trivial cast lint. | ||
| (PointerKind::Thin, PointerKind::Thin) | ||
| | (PointerKind::Length, PointerKind::Length) => { | ||
| debug!(" -> PointerCast"); | ||
| } | ||
|
|
||
| // If we are not casting pointers to sized types or slice-ish DSTs | ||
| // (handled above), we need to make a coercion cast. This prevents | ||
| // casts like `*const dyn Trait<'a> -> *const dyn Trait<'b>` which | ||
| // are unsound. | ||
| // | ||
| // See <https://github.com/rust-lang/rust/issues/120217> | ||
| (_, _) => { | ||
| debug!(" -> CoercionCast"); | ||
| fcx.typeck_results | ||
| .borrow_mut() | ||
| .set_coercion_cast(self.expr.hir_id.local_id); | ||
| } | ||
| } | ||
| } |
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 will only work for pointers that can be coerced modulo regions, it will still let something like this pass:
trait Trait<'a> {}
fn cast<'a, 'b>(x: *mut dyn Trait<'a>) -> *mut (dyn Trait<'b> + Send) {
x as _
}I think the correct fix would be to actually borrow check the principals for equality around here:
| CastKind::PtrToPtr => { |
Also, extending the trait object lifetime itself (e.g. *mut dyn Trait<'a> + 'a -> *mut dyn Trait<'a> + 'static) is harmless and should be allowed, just like adding auto-traits is.
Edit: borrowck version here: c471b9b
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.
something like this pass:
It does indeed let it pass, but why? These are not coercible?..
I think the correct fix would be to actually borrow check the principals for equality around here:
I also thought of that, but it seemed somewhat painful to do. And since we handle upcasts with CastKind::PointerCoercion, this seemed like a good solution. Borrowck change might be the right solution after all though.
Edit: borrowck version here: c471b9b
This won't help with *mut (u8, dyn Trait<'a>) -> *mut (u8, dyn Trait<'b>), but that should be an easy fix with struct_tail...
Also, extending the trait object lifetime itself (e.g. *mut dyn Trait<'a> + 'a -> *mut dyn Trait<'a> + 'static) is harmless and should be allowed, [...]
Hm, I can't find an example why it isn't harmless, but I also can't really convince myself that it is. Is this something to do with the fact that you can given dyn Trait<'a> + 'b you can use 'a in Trait's method's signatures, but not 'b?
[...], harmless and should be allowed, just like adding auto-traits is.
Adding auto-traits is not harmless. Here is an example that segfaults in safe code with arbitraty self receivers and adding send:
example
#![feature(arbitrary_self_types)]
trait Trait {
fn f(self: *const Self)
where
Self: Send;
}
impl Trait for *const () {
fn f(self: *const Self) {
unreachable!()
}
}
fn main() {
let unsend: *const dyn Trait = &(&() as *const ());
let send_bad: *const (dyn Trait + Send) = unsend as _;
send_bad.f();
}fish: Job 1, './t' terminated by signal SIGSEGV (Address boundary error)
(play)
Notably, even though we had to implement f, it's not actually in a vtable, since you should not be able to call it (because of unsatisfied Send bound):
vtable layout
error: vtable entries for `<*const () as Trait>`: [
MetadataDropInPlace,
MetadataSize,
MetadataAlign,
Vacant,
]
--> ./t.rs:24:1
|
24 | trait Trait {
| ^^^^^^^^^^^
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.
Adding auto-traits is not harmless. Here is an example that segfaults in safe code with arbitraty self receivers and adding send:
Interesting. I was somehow convinced these functions were still codegened and thought it'd be harmless because you can't do anything bad with with a sendable raw pointer alone.
This also means that borrow check alone won't be enough and we need to treat these casts more like coercions.
Is this something to do with the fact that you can given
dyn Trait<'a> + 'byou can use'ainTrait's method's signatures, but not'b?
Yeah that was my reasoning as well. You can add bounds like Self: 'static, but since the maybe-not-'static thing is behind a raw pointer you shouldn't be able to do anything bad with it. But that same reasoning was already wrong for auto traits so I'm not sure anymore.
Also, extending the lifetime of trait objects is often used in unsafe code (like the one in std), so forbidding this will probably cause widespread breakage.
something like this pass:
It does indeed let it pass, but why? These are not coercible?..
What I'm trying to say is that because these are not coercible, the try_coercion_cast above will fail, which means that the cast will be a CastKind::PtrToPtr and not a coercion. And CastKind::PtrToPtr is absolutely not borrow checked so any lifetime can be cast to any other lifetime.
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 also means that borrow check alone won't be enough and we need to treat these casts more like coercions.
I think that we can check that in hir_typeck, the same way we check
let x: &dyn Trait + Send = &();
let y: &dyn Trait = x;(I think this is done in hir_typeck? will have to find out...)
What I'm trying to say is that because these are not coercible, the
try_coercion_castabove will fail, which means that the cast will be aCastKind::PtrToPtrand not a coercion. AndCastKind::PtrToPtris absolutely not borrow checked so any lifetime can be cast to any other lifetime.
Ah, I see. Right.
Do you think moving the check out of try_coercion_cast's match would fix the issue (possibly always reporting an error if try_coercion_cast fails for *mut dyn ...)? Or should I move to your proposed solution with doing things for PtrToPtr in borrowck?
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.
Do you think moving the check out of
try_coercion_cast'smatchwould fix the issue (possibly always reporting an error iftry_coercion_castfails for*mut dyn ...)?
Where exactly do you want to move it? If this is checked unconditionally even after do_check, then all ptr-ptr casts with vtables that can't be coerced will be just be forbidden, right? Like casting *mut Wrapper<dyn Trait> <-> *mut dyn Trait.
I think that we can check that in
hir_typeck, the same way we checklet x: &dyn Trait + Send = &(); let y: &dyn Trait = x;
I think checking this here in check_ptr_ptr_cast where we also compare the principals might be fine. Just check that the source includes all auto traits from the target.
And I'm pretty sure we'd still need borrowck for the principal on top 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.
Checking this with the Unsize looks risky to me. That trait is also implemented for trait upcasts, e.g. dyn Subtrait: Unsize<dyn Supertrait>, because trait upcasting is essentially treated as a "unsizing" coercion before codegen, except that the source type is already unsized.
Because of that, with your current implementation this will compile:
trait Super {}
trait Sub: Super {}
struct Wrapper<T: ?Sized>(T);
fn cast(ptr: *const dyn Sub) -> *const Wrapper<dyn Super> {
// this is a "reinterpret cast" and not an upcast, the vtable is just copied
ptr as _
}This could theoretically be fine, because it looks like there is currently no (safe) way to cast from *const Wrapper<dyn Super> to *const dyn Super. This happens, because try_coercion_cast will (via Coerce::coerce_unsized) eagerly evaluate the CoerceUnsized and Unsize obligations, but not their nested obligations, which means that casting *const Wrapper<dyn Super> to *const dyn Super is treated as a coercion and fails. But this also leads to weird inconsistencies whether a cast is considered a coercion cast or pointer-pointer cast.
example
trait Trait {}
struct Wrapper<T: ?Sized>(T);
fn cast1(x: *const dyn Send) -> *const (dyn Send + Sync) {
x as _ // is a ptr-ptr cast, compiles
}
fn cast2(x: *const Wrapper<dyn Send>) -> *const (dyn Send + Sync) {
x as _ // is an unsizing coercion cast, error
}So I'd argue the current behavior is a bug and it should always be allowed to cast *const Wrapper<dyn Trait> to *const dyn Trait, which would make your implementation incorrect.
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.
*const dyn Sub -> *const Wrapper<dyn Super> being a "reinterpret cast" is very bad, for the same reasons we have the issues this PR attempts to fix — having an incorrect vtable is not sound with other features. I'll add back the check that the principal traits are the same. While I don't see a safe way to go *const W<dyn Trait> -> *const dyn Trait, this transformation looks more than fine for me, so I really don't want to depend on it being impossible. (tbh I assumed it was possible, considering you can do *const dyn Trait -> *const W<dyn Trait>, it's very weird we don't allow the opposite...)
So I'd argue the current behavior is a bug and it should always be allowed to cast
*const Wrapper<dyn Trait>to*const dyn Trait, which would make your implementation incorrect.
In other words: I agree with this.
Although I'm not sure how you can add this in a non-confusing way.
*const ()->*const Sendmust be unsizing*const W<dyn Trait>->*const dyn Traitshould be ptr-ptr- But what if
W<dyn Trait>: Trait? Currently it's unsizing, do we keep that?
- But what if
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.
- But what if
W<dyn Trait>: Trait? Currently it's unsizing, do we keep that?
*const W<dyn Trait> -> *const dyn Trait can't be an unsizing cast, because W<dyn Trait> is not sized and not a trait object. We can't keep the vtable metadata that is already in the fat pointer *const W<dyn Trait> and add the metadata of an impl Trait for W<dyn Trait> on top of that.
Casting *const T to *const U should be an unsizing coercion if and only if T: Unsize<U>, but W<dyn Trait> can never implement Unsize<dyn Trait>.
The problem with the current implementation is that it doesn't fully check W<dyn Trait>: Unsize<dyn Trait>. It only sees that W<dyn Trait>: Unsize<dyn Trait> holds if the nested obligations W<dyn Trait>: Sized and W<dyn Trait>: Trait hold but then directly assumes the cast must be an unsizing coercion and only checks the nested obligations too late.
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.
Oooh, right.
Yeah, then *const W<dyn Trait> -> *const dyn Trait should definitely be supported, but maybe as a follow up to this :)
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.
It is possible to do *const W<dyn Trait> -> *const dyn Trait right now in safe code. You just need to write a small helper function
impl<T: ?Sized> Wrapper<T> {
fn get(this: *const Self) -> *const T {
this as _
}
}
fn cast(ptr: *const Wrapper<dyn Super>) -> *const dyn Super {
Wrapper::get(ptr)
}|
☀️ Try build successful - checks-actions |
|
@rustbot author |
This comment has been minimized.
This comment has been minimized.
|
not following this pr too closely for now 🙇 afaict there are some challenges in getting this to work correctly. wanted to quickly chime in that i believe at some point #120222 (comment) to be preferable simply because it's easier to confirm that it is actually correct.
for #120217 we could similarly simply forbid calling raw-ptr methods on trait objects/not making them object safe. |
3c3cf17 to
5f27951
Compare
This comment has been minimized.
This comment has been minimized.
|
@bors try |
…r=<try> Make casts of pointers to trait objects stricter This is an attempt to `fix` rust-lang#120222 and rust-lang#120217. This is done by adding restrictions on casting pointers to trait objects. Currently the restriction is > When casting `*const X<dyn A>` -> `*const Y<dyn B>`, if `B` has a principal trait, `dyn A + 'erased: Unsize<dyn B + 'erased>` must hold This ensures that 1. Principal trait's generic arguments match (no `*const dyn Tr<A>` -> `*const dyn Tr<B>` casts, which are a problem for [rust-lang#120222](rust-lang#120222)) 2. Principal trait's lifetime arguments match (no `*const dyn Tr<'a>` -> `*const dyn Tr<'b>` casts, which are a problem for [rust-lang#120217](rust-lang#120217)) 3. No auto traits can be _added_ (this is a problem for arbitrary self types, see [this comment](rust-lang#120248 (comment))) Some notes: - We only care about the metadata/last field, so you can still cast `*const dyn T` to `*const WithHeader<dyn T>`, etc - The lifetime of the trait object itself (`dyn A + 'lt`) is not checked, so you can still cast `*mut FnOnce() + '_` to `*mut FnOnce() + 'static`, etc - This feels fishy, but I couldn't come up with a reason it must be checked - The new checks are only done if `B` has a principal, so you can still do any kinds of cast, if the target only has auto traits - This is because auto traits are not enough to get unsoundness issues that this PR fixes - ...and so it makes sense to minimize breakage The plan is to, ~~once the checks are properly implemented~~, run crate to determine how much damage does this do. The diagnostics are currently not great, to say the least, but as far as I can tell this correctly fixes the issues. cc `@oli-obk` `@compiler-errors` `@lcnr`
|
☀️ Try build successful - checks-actions |
1 similar comment
|
☀️ Try build successful - checks-actions |
|
@craterbot check |
|
👌 Experiment ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more |
|
So, this broke my code when updating from 1.80 to 1.81. Shouldn't such change come with deprecation/warning? Out of curiosity, this is the code snippet: let p3: Box<dyn Backend<FInner>> = p3;
let p3 = Box::into_raw(p3);
// This is safe because we know that FInner == FOuter.
Some(unsafe { Box::from_raw(p3 as *mut dyn Backend<FOuter>) }) |
|
@lvella IIRC we decided that because this is a very rare pattern of code, we can go straight to a hard error. (note that before code was unsound pretty much always (unless, like in your case, there is some kind of proof invisible to the compiler that types are actually the same)). |
This MR contains the following updates: | Package | Update | Change | |---|---|---| | [rust](https://github.com/rust-lang/rust) | minor | `1.80.1` -> `1.81.0` | MR created with the help of [el-capitano/tools/renovate-bot](https://gitlab.com/el-capitano/tools/renovate-bot). **Proposed changes to behavior should be submitted there as MRs.** --- ### Release Notes <details> <summary>rust-lang/rust (rust)</summary> ### [`v1.81.0`](https://github.com/rust-lang/rust/blob/HEAD/RELEASES.md#Version-1810-2024-09-05) [Compare Source](rust-lang/rust@1.80.1...1.81.0) \========================== <a id="1.81.0-Language"></a> ## Language - [Abort on uncaught panics in `extern "C"` functions.](rust-lang/rust#116088) - [Fix ambiguous cases of multiple `&` in elided self lifetimes.](rust-lang/rust#117967) - [Stabilize `#[expect]` for lints (RFC 2383),](rust-lang/rust#120924) like `#[allow]` with a warning if the lint is *not* fulfilled. - [Change method resolution to constrain hidden types instead of rejecting method candidates.](rust-lang/rust#123962) - [Bump `elided_lifetimes_in_associated_constant` to deny.](rust-lang/rust#124211) - [`offset_from`: always allow pointers to point to the same address.](rust-lang/rust#124921) - [Allow constraining opaque types during subtyping in the trait system.](rust-lang/rust#125447) - [Allow constraining opaque types during various unsizing casts.](rust-lang/rust#125610) - [Deny keyword lifetimes pre-expansion.](rust-lang/rust#126762) <a id="1.81.0-Compiler"></a> ## Compiler - [Make casts of pointers to trait objects stricter.](rust-lang/rust#120248) - [Check alias args for well-formedness even if they have escaping bound vars.](rust-lang/rust#123737) - [Deprecate no-op codegen option `-Cinline-threshold=...`.](rust-lang/rust#124712) - [Re-implement a type-size based limit.](rust-lang/rust#125507) - [Properly account for alignment in `transmute` size checks.](rust-lang/rust#125740) - [Remove the `box_pointers` lint.](rust-lang/rust#126018) - [Ensure the interpreter checks bool/char for validity when they are used in a cast.](rust-lang/rust#126265) - [Improve coverage instrumentation for functions containing nested items.](rust-lang/rust#127199) - Target changes: - [Add Tier 3 `no_std` Xtensa targets:](rust-lang/rust#125141) `xtensa-esp32-none-elf`, `xtensa-esp32s2-none-elf`, `xtensa-esp32s3-none-elf` - [Add Tier 3 `std` Xtensa targets:](rust-lang/rust#126380) `xtensa-esp32-espidf`, `xtensa-esp32s2-espidf`, `xtensa-esp32s3-espidf` - [Add Tier 3 i686 Redox OS target:](rust-lang/rust#126192) `i686-unknown-redox` - [Promote `arm64ec-pc-windows-msvc` to Tier 2.](rust-lang/rust#126039) - [Promote `loongarch64-unknown-linux-musl` to Tier 2 with host tools.](rust-lang/rust#126298) - [Enable full tools and profiler for LoongArch Linux targets.](rust-lang/rust#127078) - [Unconditionally warn on usage of `wasm32-wasi`.](rust-lang/rust#126662) (see compatibility note below) - Refer to Rust's \[platform support page]\[platform-support-doc] for more information on Rust's tiered platform support. <a id="1.81.0-Libraries"></a> ## Libraries - [Split core's `PanicInfo` and std's `PanicInfo`.](rust-lang/rust#115974) (see compatibility note below) - [Generalize `{Rc,Arc}::make_mut()` to unsized types.](rust-lang/rust#116113) - [Replace sort implementations with stable `driftsort` and unstable `ipnsort`.](rust-lang/rust#124032) All `slice::sort*` and `slice::select_nth*` methods are expected to see significant performance improvements. See the [research project](https://github.com/Voultapher/sort-research-rs) for more details. - [Document behavior of `create_dir_all` with respect to empty paths.](rust-lang/rust#125112) - [Fix interleaved output in the default panic hook when multiple threads panic simultaneously.](rust-lang/rust#127397) <a id="1.81.0-Stabilized-APIs"></a> ## Stabilized APIs - [`core::error`](https://doc.rust-lang.org/stable/core/error/index.html) - [`hint::assert_unchecked`](https://doc.rust-lang.org/stable/core/hint/fn.assert_unchecked.html) - [`fs::exists`](https://doc.rust-lang.org/stable/std/fs/fn.exists.html) - [`AtomicBool::fetch_not`](https://doc.rust-lang.org/stable/core/sync/atomic/struct.AtomicBool.html#method.fetch_not) - [`Duration::abs_diff`](https://doc.rust-lang.org/stable/core/time/struct.Duration.html#method.abs_diff) - [`IoSlice::advance`](https://doc.rust-lang.org/stable/std/io/struct.IoSlice.html#method.advance) - [`IoSlice::advance_slices`](https://doc.rust-lang.org/stable/std/io/struct.IoSlice.html#method.advance_slices) - [`IoSliceMut::advance`](https://doc.rust-lang.org/stable/std/io/struct.IoSliceMut.html#method.advance) - [`IoSliceMut::advance_slices`](https://doc.rust-lang.org/stable/std/io/struct.IoSliceMut.html#method.advance_slices) - [`PanicHookInfo`](https://doc.rust-lang.org/stable/std/panic/struct.PanicHookInfo.html) - [`PanicInfo::message`](https://doc.rust-lang.org/stable/core/panic/struct.PanicInfo.html#method.message) - [`PanicMessage`](https://doc.rust-lang.org/stable/core/panic/struct.PanicMessage.html) These APIs are now stable in const contexts: - [`char::from_u32_unchecked`](https://doc.rust-lang.org/stable/core/char/fn.from_u32\_unchecked.html) (function) - [`char::from_u32_unchecked`](https://doc.rust-lang.org/stable/core/primitive.char.html#method.from_u32\_unchecked) (method) - [`CStr::count_bytes`](https://doc.rust-lang.org/stable/core/ffi/c_str/struct.CStr.html#method.count_bytes) - [`CStr::from_ptr`](https://doc.rust-lang.org/stable/core/ffi/c_str/struct.CStr.html#method.from_ptr) <a id="1.81.0-Cargo"></a> ## Cargo - [Generated `.cargo_vcs_info.json` is always included, even when `--allow-dirty` is passed.](rust-lang/cargo#13960) - [Disallow `package.license-file` and `package.readme` pointing to non-existent files during packaging.](rust-lang/cargo#13921) - [Disallow passing `--release`/`--debug` flag along with the `--profile` flag.](rust-lang/cargo#13971) - [Remove `lib.plugin` key support in `Cargo.toml`. Rust plugin support has been deprecated for four years and was removed in 1.75.0.](rust-lang/cargo#13902) <a id="1.81.0-Compatibility-Notes"></a> ## Compatibility Notes - Usage of the `wasm32-wasi` target will now issue a compiler warning and request users switch to the `wasm32-wasip1` target instead. Both targets are the same, `wasm32-wasi` is only being renamed, and this [change to the WASI target](https://blog.rust-lang.org/2024/04/09/updates-to-rusts-wasi-targets.html) is being done to enable removing `wasm32-wasi` in January 2025. - We have renamed `std::panic::PanicInfo` to `std::panic::PanicHookInfo`. The old name will continue to work as an alias, but will result in a deprecation warning starting in Rust 1.82.0. `core::panic::PanicInfo` will remain unchanged, however, as this is now a *different type*. The reason is that these types have different roles: `std::panic::PanicHookInfo` is the argument to the [panic hook](https://doc.rust-lang.org/stable/std/panic/fn.set_hook.html) in std context (where panics can have an arbitrary payload), while `core::panic::PanicInfo` is the argument to the [`#[panic_handler]`](https://doc.rust-lang.org/nomicon/panic-handler.html) in no_std context (where panics always carry a formatted *message*). Separating these types allows us to add more useful methods to these types, such as `std::panic::PanicHookInfo::payload_as_str()` and `core::panic::PanicInfo::message()`. - The new sort implementations may panic if a type's implementation of [`Ord`](https://doc.rust-lang.org/std/cmp/trait.Ord.html) (or the given comparison function) does not implement a [total order](https://en.wikipedia.org/wiki/Total_order) as the trait requires. `Ord`'s supertraits (`PartialOrd`, `Eq`, and `PartialEq`) must also be consistent. The previous implementations would not "notice" any problem, but the new implementations have a good chance of detecting inconsistencies, throwing a panic rather than returning knowingly unsorted data. - [In very rare cases, a change in the internal evaluation order of the trait solver may result in new fatal overflow errors.](rust-lang/rust#126128) <a id="1.81.0-Internal-Changes"></a> ## Internal Changes These changes do not affect any public interfaces of Rust, but they represent significant improvements to the performance or internals of rustc and related tools. - [Add a Rust-for Linux `auto` CI job to check kernel builds.](rust-lang/rust#125209) </details> --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever MR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this MR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this MR, check this box --- This MR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy40NDAuNyIsInVwZGF0ZWRJblZlciI6IjM3LjQ0MC43IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJSZW5vdmF0ZSBCb3QiXX0=-->
Pkgsrc changes: * Adapt patches, apply to new vendored crates where needed. * Back-port rust pull request 130110, "make dist vendoring configurable" * Disable "dist vendoring", otherwise cargo would try to access the network during the build phase. Upstream changes: Version 1.81.0 (2024-09-05) ========================== Language -------- - [Abort on uncaught panics in `extern "C"` functions.] (rust-lang/rust#116088) - [Fix ambiguous cases of multiple `&` in elided self lifetimes.] (rust-lang/rust#117967) - [Stabilize `#[expect]` for lints (RFC 2383),] (rust-lang/rust#120924) like `#[allow]` with a warning if the lint is _not_ fulfilled. - [Change method resolution to constrain hidden types instead of rejecting method candidates.] (rust-lang/rust#123962) - [Bump `elided_lifetimes_in_associated_constant` to deny.] (rust-lang/rust#124211) - [`offset_from`: always allow pointers to point to the same address.] (rust-lang/rust#124921) - [Allow constraining opaque types during subtyping in the trait system.] (rust-lang/rust#125447) - [Allow constraining opaque types during various unsizing casts.] (rust-lang/rust#125610) - [Deny keyword lifetimes pre-expansion.] (rust-lang/rust#126762) Compiler -------- - [Make casts of pointers to trait objects stricter.] (rust-lang/rust#120248) - [Check alias args for well-formedness even if they have escaping bound vars.] (rust-lang/rust#123737) - [Deprecate no-op codegen option `-Cinline-threshold=...`.] (rust-lang/rust#124712) - [Re-implement a type-size based limit.] (rust-lang/rust#125507) - [Properly account for alignment in `transmute` size checks.] (rust-lang/rust#125740) - [Remove the `box_pointers` lint.] (rust-lang/rust#126018) - [Ensure the interpreter checks bool/char for validity when they are used in a cast.] (rust-lang/rust#126265) - [Improve coverage instrumentation for functions containing nested items.] (rust-lang/rust#127199) - Target changes: - [Add Tier 3 `no_std` Xtensa targets:] (rust-lang/rust#125141) `xtensa-esp32-none-elf`, `xtensa-esp32s2-none-elf`, `xtensa-esp32s3-none-elf` - [Add Tier 3 `std` Xtensa targets:] (rust-lang/rust#126380) `xtensa-esp32-espidf`, `xtensa-esp32s2-espidf`, `xtensa-esp32s3-espidf` - [Add Tier 3 i686 Redox OS target:] (rust-lang/rust#126192) `i686-unknown-redox` - [Promote `arm64ec-pc-windows-msvc` to Tier 2.] (rust-lang/rust#126039) - [Promote `wasm32-wasip2` to Tier 2.] (rust-lang/rust#126967) - [Promote `loongarch64-unknown-linux-musl` to Tier 2 with host tools.] (rust-lang/rust#126298) - [Enable full tools and profiler for LoongArch Linux targets.] (rust-lang/rust#127078) - [Unconditionally warn on usage of `wasm32-wasi`.] (rust-lang/rust#126662) (see compatibility note below) - Refer to Rust's [platform support page][platform-support-doc] for more information on Rust's tiered platform support. Libraries --------- - [Split core's `PanicInfo` and std's `PanicInfo`.] (rust-lang/rust#115974) (see compatibility note below) - [Generalize `{Rc,Arc}::make_mut()` to unsized types.] (rust-lang/rust#116113) - [Replace sort implementations with stable `driftsort` and unstable `ipnsort`.] (rust-lang/rust#124032) All `slice::sort*` and `slice::select_nth*` methods are expected to see significant performance improvements. See the [research project] (https://github.com/Voultapher/sort-research-rs) for more details. - [Document behavior of `create_dir_all` with respect to empty paths.] (rust-lang/rust#125112) - [Fix interleaved output in the default panic hook when multiple threads panic simultaneously.] (rust-lang/rust#127397) - Fix `Command`'s batch files argument escaping not working when file name has trailing whitespace or periods (CVE-2024-43402). Stabilized APIs --------------- - [`core::error`] (https://doc.rust-lang.org/stable/core/error/index.html) - [`hint::assert_unchecked`] (https://doc.rust-lang.org/stable/core/hint/fn.assert_unchecked.html) - [`fs::exists`] (https://doc.rust-lang.org/stable/std/fs/fn.exists.html) - [`AtomicBool::fetch_not`] (https://doc.rust-lang.org/stable/core/sync/atomic/struct.AtomicBool.html#method.fetch_not) - [`Duration::abs_diff`] (https://doc.rust-lang.org/stable/core/time/struct.Duration.html#method.abs_diff) - [`IoSlice::advance`] (https://doc.rust-lang.org/stable/std/io/struct.IoSlice.html#method.advance) - [`IoSlice::advance_slices`] (https://doc.rust-lang.org/stable/std/io/struct.IoSlice.html#method.advance_slices) - [`IoSliceMut::advance`] (https://doc.rust-lang.org/stable/std/io/struct.IoSliceMut.html#method.advance) - [`IoSliceMut::advance_slices`] (https://doc.rust-lang.org/stable/std/io/struct.IoSliceMut.html#method.advance_slices) - [`PanicHookInfo`] (https://doc.rust-lang.org/stable/std/panic/struct.PanicHookInfo.html) - [`PanicInfo::message`] (https://doc.rust-lang.org/stable/core/panic/struct.PanicInfo.html#method.message) - [`PanicMessage`] (https://doc.rust-lang.org/stable/core/panic/struct.PanicMessage.html) These APIs are now stable in const contexts: - [`char::from_u32_unchecked`] (https://doc.rust-lang.org/stable/core/char/fn.from_u32_unchecked.html) (function) - [`char::from_u32_unchecked`] (https://doc.rust-lang.org/stable/core/primitive.char.html#method.from_u32_unchecked) (method) - [`CStr::count_bytes`] (https://doc.rust-lang.org/stable/core/ffi/c_str/struct.CStr.html#method.count_bytes) - [`CStr::from_ptr`] (https://doc.rust-lang.org/stable/core/ffi/c_str/struct.CStr.html#method.from_ptr) Cargo ----- - [Generated `.cargo_vcs_info.json` is always included, even when `--allow-dirty` is passed.] (rust-lang/cargo#13960) - [Disallow `package.license-file` and `package.readme` pointing to non-existent files during packaging.] (rust-lang/cargo#13921) - [Disallow passing `--release`/`--debug` flag along with the `--profile` flag.] (rust-lang/cargo#13971) - [Remove `lib.plugin` key support in `Cargo.toml`. Rust plugin support has been deprecated for four years and was removed in 1.75.0.] (rust-lang/cargo#13902) Compatibility Notes ------------------- * Usage of the `wasm32-wasi` target will now issue a compiler warning and request users switch to the `wasm32-wasip1` target instead. Both targets are the same, `wasm32-wasi` is only being renamed, and this [change to the WASI target] (https://blog.rust-lang.org/2024/04/09/updates-to-rusts-wasi-targets.html) is being done to enable removing `wasm32-wasi` in January 2025. * We have renamed `std::panic::PanicInfo` to `std::panic::PanicHookInfo`. The old name will continue to work as an alias, but will result in a deprecation warning starting in Rust 1.82.0. `core::panic::PanicInfo` will remain unchanged, however, as this is now a *different type*. The reason is that these types have different roles: `std::panic::PanicHookInfo` is the argument to the [panic hook](https://doc.rust-lang.org/stable/std/panic/fn.set_hook.html) in std context (where panics can have an arbitrary payload), while `core::panic::PanicInfo` is the argument to the [`#[panic_handler]`](https://doc.rust-lang.org/nomicon/panic-handler.html) in no_std context (where panics always carry a formatted *message*). Separating these types allows us to add more useful methods to these types, such as `std::panic::PanicHookInfo::payload_as_str()` and `core::panic::PanicInfo::message()`. * The new sort implementations may panic if a type's implementation of [`Ord`](https://doc.rust-lang.org/std/cmp/trait.Ord.html) (or the given comparison function) does not implement a [total order](https://en.wikipedia.org/wiki/Total_order) as the trait requires. `Ord`'s supertraits (`PartialOrd`, `Eq`, and `PartialEq`) must also be consistent. The previous implementations would not "notice" any problem, but the new implementations have a good chance of detecting inconsistencies, throwing a panic rather than returning knowingly unsorted data. * [In very rare cases, a change in the internal evaluation order of the trait solver may result in new fatal overflow errors.] (rust-lang/rust#126128) Internal Changes ---------------- These changes do not affect any public interfaces of Rust, but they represent significant improvements to the performance or internals of rustc and related tools. - [Add a Rust-for Linux `auto` CI job to check kernel builds.] (rust-lang/rust#125209)
…leLapkin improve compile errors for invalid ptr-to-ptr casts with trait objects This is a follow-up to rust-lang#120248 to improve some of its error messages. 1. Make the borrowcheck error for "type annotation requires that x must outlive y" actually point at the type annotation, i.e. the type `T` in a `x as T` cast. This makes the error more consistent with other errors caused by type annotation in other places, such as ```text error: lifetime may not live long enough --> src/lib.rs:4:12 | 3 | fn bar(a: &i32) { | - let's call the lifetime of this reference `'1` 4 | let b: &'static i32 = a; | ^^^^^^^^^^^^ type annotation requires that `'1` must outlive `'static` ``` 2. Don't say "cast" when we actually mean "coercion" and give borrowcheck errors from actual casts (which is currently just the check added in rust-lang#120248) a higher priority than ones from coercions. This can improve the errors for ptr-to-ptr cast between trait objects because they are are lowered as an upcast "unsizing" coercion if possible (which may be the identity upcast) followed by the actual cast. 3. Bring back the old "casting X as Y is invalid" message for type mismatch in the principals and reword the "vtable kinds may not match" message to more accurately describe the pointer metadata and not refer to "vtables" if the metadata is unknown. fixes rust-lang#130030 r? `@WaffleLapkin` but feel free to reassign
Rollup merge of rust-lang#130234 - lukas-code:ptr-cast-errors, r=WaffleLapkin improve compile errors for invalid ptr-to-ptr casts with trait objects This is a follow-up to rust-lang#120248 to improve some of its error messages. 1. Make the borrowcheck error for "type annotation requires that x must outlive y" actually point at the type annotation, i.e. the type `T` in a `x as T` cast. This makes the error more consistent with other errors caused by type annotation in other places, such as ```text error: lifetime may not live long enough --> src/lib.rs:4:12 | 3 | fn bar(a: &i32) { | - let's call the lifetime of this reference `'1` 4 | let b: &'static i32 = a; | ^^^^^^^^^^^^ type annotation requires that `'1` must outlive `'static` ``` 2. Don't say "cast" when we actually mean "coercion" and give borrowcheck errors from actual casts (which is currently just the check added in rust-lang#120248) a higher priority than ones from coercions. This can improve the errors for ptr-to-ptr cast between trait objects because they are are lowered as an upcast "unsizing" coercion if possible (which may be the identity upcast) followed by the actual cast. 3. Bring back the old "casting X as Y is invalid" message for type mismatch in the principals and reword the "vtable kinds may not match" message to more accurately describe the pointer metadata and not refer to "vtables" if the metadata is unknown. fixes rust-lang#130030 r? `@WaffleLapkin` but feel free to reassign
improve compile errors for invalid ptr-to-ptr casts with trait objects This is a follow-up to rust-lang/rust#120248 to improve some of its error messages. 1. Make the borrowcheck error for "type annotation requires that x must outlive y" actually point at the type annotation, i.e. the type `T` in a `x as T` cast. This makes the error more consistent with other errors caused by type annotation in other places, such as ```text error: lifetime may not live long enough --> src/lib.rs:4:12 | 3 | fn bar(a: &i32) { | - let's call the lifetime of this reference `'1` 4 | let b: &'static i32 = a; | ^^^^^^^^^^^^ type annotation requires that `'1` must outlive `'static` ``` 2. Don't say "cast" when we actually mean "coercion" and give borrowcheck errors from actual casts (which is currently just the check added in rust-lang/rust#120248) a higher priority than ones from coercions. This can improve the errors for ptr-to-ptr cast between trait objects because they are are lowered as an upcast "unsizing" coercion if possible (which may be the identity upcast) followed by the actual cast. 3. Bring back the old "casting X as Y is invalid" message for type mismatch in the principals and reword the "vtable kinds may not match" message to more accurately describe the pointer metadata and not refer to "vtables" if the metadata is unknown. fixes rust-lang/rust#130030 r? `@WaffleLapkin` but feel free to reassign
This check makes the pointer metadata of a struct observable by struct S<T: ?Sized> {
// s: Box<T>, // error: thin to fat pointer cast
// _marker: PhantomData<T>, s: [u8], // error: ptr metadata mismatch
s: T, // OK
}
fn cast_dyn<T: ?Sized>(t: *mut S<T>) -> *mut T {
t as _
}It's reasonable that changing between thin and fat pointer is breaking. But also exposing the unsized representation ( |
This behavior was not introduced by this PR, it's been like that since Rust 1.2.0. |
Pkgsrc changes: * Adapt patches, apply to new vendored crates where needed. * Back-port rust pull request 130110, "make dist vendoring configurable" * Disable "dist vendoring", otherwise cargo would try to access the network during the build phase. Upstream changes: Version 1.81.0 (2024-09-05) ========================== Language -------- - [Abort on uncaught panics in `extern "C"` functions.] (rust-lang/rust#116088) - [Fix ambiguous cases of multiple `&` in elided self lifetimes.] (rust-lang/rust#117967) - [Stabilize `#[expect]` for lints (RFC 2383),] (rust-lang/rust#120924) like `#[allow]` with a warning if the lint is _not_ fulfilled. - [Change method resolution to constrain hidden types instead of rejecting method candidates.] (rust-lang/rust#123962) - [Bump `elided_lifetimes_in_associated_constant` to deny.] (rust-lang/rust#124211) - [`offset_from`: always allow pointers to point to the same address.] (rust-lang/rust#124921) - [Allow constraining opaque types during subtyping in the trait system.] (rust-lang/rust#125447) - [Allow constraining opaque types during various unsizing casts.] (rust-lang/rust#125610) - [Deny keyword lifetimes pre-expansion.] (rust-lang/rust#126762) Compiler -------- - [Make casts of pointers to trait objects stricter.] (rust-lang/rust#120248) - [Check alias args for well-formedness even if they have escaping bound vars.] (rust-lang/rust#123737) - [Deprecate no-op codegen option `-Cinline-threshold=...`.] (rust-lang/rust#124712) - [Re-implement a type-size based limit.] (rust-lang/rust#125507) - [Properly account for alignment in `transmute` size checks.] (rust-lang/rust#125740) - [Remove the `box_pointers` lint.] (rust-lang/rust#126018) - [Ensure the interpreter checks bool/char for validity when they are used in a cast.] (rust-lang/rust#126265) - [Improve coverage instrumentation for functions containing nested items.] (rust-lang/rust#127199) - Target changes: - [Add Tier 3 `no_std` Xtensa targets:] (rust-lang/rust#125141) `xtensa-esp32-none-elf`, `xtensa-esp32s2-none-elf`, `xtensa-esp32s3-none-elf` - [Add Tier 3 `std` Xtensa targets:] (rust-lang/rust#126380) `xtensa-esp32-espidf`, `xtensa-esp32s2-espidf`, `xtensa-esp32s3-espidf` - [Add Tier 3 i686 Redox OS target:] (rust-lang/rust#126192) `i686-unknown-redox` - [Promote `arm64ec-pc-windows-msvc` to Tier 2.] (rust-lang/rust#126039) - [Promote `wasm32-wasip2` to Tier 2.] (rust-lang/rust#126967) - [Promote `loongarch64-unknown-linux-musl` to Tier 2 with host tools.] (rust-lang/rust#126298) - [Enable full tools and profiler for LoongArch Linux targets.] (rust-lang/rust#127078) - [Unconditionally warn on usage of `wasm32-wasi`.] (rust-lang/rust#126662) (see compatibility note below) - Refer to Rust's [platform support page][platform-support-doc] for more information on Rust's tiered platform support. Libraries --------- - [Split core's `PanicInfo` and std's `PanicInfo`.] (rust-lang/rust#115974) (see compatibility note below) - [Generalize `{Rc,Arc}::make_mut()` to unsized types.] (rust-lang/rust#116113) - [Replace sort implementations with stable `driftsort` and unstable `ipnsort`.] (rust-lang/rust#124032) All `slice::sort*` and `slice::select_nth*` methods are expected to see significant performance improvements. See the [research project] (https://github.com/Voultapher/sort-research-rs) for more details. - [Document behavior of `create_dir_all` with respect to empty paths.] (rust-lang/rust#125112) - [Fix interleaved output in the default panic hook when multiple threads panic simultaneously.] (rust-lang/rust#127397) - Fix `Command`'s batch files argument escaping not working when file name has trailing whitespace or periods (CVE-2024-43402). Stabilized APIs --------------- - [`core::error`] (https://doc.rust-lang.org/stable/core/error/index.html) - [`hint::assert_unchecked`] (https://doc.rust-lang.org/stable/core/hint/fn.assert_unchecked.html) - [`fs::exists`] (https://doc.rust-lang.org/stable/std/fs/fn.exists.html) - [`AtomicBool::fetch_not`] (https://doc.rust-lang.org/stable/core/sync/atomic/struct.AtomicBool.html#method.fetch_not) - [`Duration::abs_diff`] (https://doc.rust-lang.org/stable/core/time/struct.Duration.html#method.abs_diff) - [`IoSlice::advance`] (https://doc.rust-lang.org/stable/std/io/struct.IoSlice.html#method.advance) - [`IoSlice::advance_slices`] (https://doc.rust-lang.org/stable/std/io/struct.IoSlice.html#method.advance_slices) - [`IoSliceMut::advance`] (https://doc.rust-lang.org/stable/std/io/struct.IoSliceMut.html#method.advance) - [`IoSliceMut::advance_slices`] (https://doc.rust-lang.org/stable/std/io/struct.IoSliceMut.html#method.advance_slices) - [`PanicHookInfo`] (https://doc.rust-lang.org/stable/std/panic/struct.PanicHookInfo.html) - [`PanicInfo::message`] (https://doc.rust-lang.org/stable/core/panic/struct.PanicInfo.html#method.message) - [`PanicMessage`] (https://doc.rust-lang.org/stable/core/panic/struct.PanicMessage.html) These APIs are now stable in const contexts: - [`char::from_u32_unchecked`] (https://doc.rust-lang.org/stable/core/char/fn.from_u32_unchecked.html) (function) - [`char::from_u32_unchecked`] (https://doc.rust-lang.org/stable/core/primitive.char.html#method.from_u32_unchecked) (method) - [`CStr::count_bytes`] (https://doc.rust-lang.org/stable/core/ffi/c_str/struct.CStr.html#method.count_bytes) - [`CStr::from_ptr`] (https://doc.rust-lang.org/stable/core/ffi/c_str/struct.CStr.html#method.from_ptr) Cargo ----- - [Generated `.cargo_vcs_info.json` is always included, even when `--allow-dirty` is passed.] (rust-lang/cargo#13960) - [Disallow `package.license-file` and `package.readme` pointing to non-existent files during packaging.] (rust-lang/cargo#13921) - [Disallow passing `--release`/`--debug` flag along with the `--profile` flag.] (rust-lang/cargo#13971) - [Remove `lib.plugin` key support in `Cargo.toml`. Rust plugin support has been deprecated for four years and was removed in 1.75.0.] (rust-lang/cargo#13902) Compatibility Notes ------------------- * Usage of the `wasm32-wasi` target will now issue a compiler warning and request users switch to the `wasm32-wasip1` target instead. Both targets are the same, `wasm32-wasi` is only being renamed, and this [change to the WASI target] (https://blog.rust-lang.org/2024/04/09/updates-to-rusts-wasi-targets.html) is being done to enable removing `wasm32-wasi` in January 2025. * We have renamed `std::panic::PanicInfo` to `std::panic::PanicHookInfo`. The old name will continue to work as an alias, but will result in a deprecation warning starting in Rust 1.82.0. `core::panic::PanicInfo` will remain unchanged, however, as this is now a *different type*. The reason is that these types have different roles: `std::panic::PanicHookInfo` is the argument to the [panic hook](https://doc.rust-lang.org/stable/std/panic/fn.set_hook.html) in std context (where panics can have an arbitrary payload), while `core::panic::PanicInfo` is the argument to the [`#[panic_handler]`](https://doc.rust-lang.org/nomicon/panic-handler.html) in no_std context (where panics always carry a formatted *message*). Separating these types allows us to add more useful methods to these types, such as `std::panic::PanicHookInfo::payload_as_str()` and `core::panic::PanicInfo::message()`. * The new sort implementations may panic if a type's implementation of [`Ord`](https://doc.rust-lang.org/std/cmp/trait.Ord.html) (or the given comparison function) does not implement a [total order](https://en.wikipedia.org/wiki/Total_order) as the trait requires. `Ord`'s supertraits (`PartialOrd`, `Eq`, and `PartialEq`) must also be consistent. The previous implementations would not "notice" any problem, but the new implementations have a good chance of detecting inconsistencies, throwing a panic rather than returning knowingly unsorted data. * [In very rare cases, a change in the internal evaluation order of the trait solver may result in new fatal overflow errors.] (rust-lang/rust#126128) Internal Changes ---------------- These changes do not affect any public interfaces of Rust, but they represent significant improvements to the performance or internals of rustc and related tools. - [Add a Rust-for Linux `auto` CI job to check kernel builds.] (rust-lang/rust#125209)
|
I had two follow-ups in mind:
|
…r=compiler-errors Allow `*const W<dyn A> -> *const dyn A` ptr cast Followup of rust-lang#120248 (comment). This PR allows casting pointers from something wrapping a trait object, to the trait object, i.e. `*const W<dyn A> -> *const dyn A` where `W` is `struct W<T: ?Sized>(T);`. r? compiler-errors Fixes rust-lang#128625
…r=compiler-errors Allow `*const W<dyn A> -> *const dyn A` ptr cast Followup of rust-lang#120248 (comment). This PR allows casting pointers from something wrapping a trait object, to the trait object, i.e. `*const W<dyn A> -> *const dyn A` where `W` is `struct W<T: ?Sized>(T);`. r? compiler-errors Fixes rust-lang#128625
Rollup merge of rust-lang#136127 - WaffleLapkin:dyn_ptr_unwrap_cast, r=compiler-errors Allow `*const W<dyn A> -> *const dyn A` ptr cast Followup of rust-lang#120248 (comment). This PR allows casting pointers from something wrapping a trait object, to the trait object, i.e. `*const W<dyn A> -> *const dyn A` where `W` is `struct W<T: ?Sized>(T);`. r? compiler-errors Fixes rust-lang#128625
This is an attempt to
fix#120222 and #120217.This is done by adding restrictions on casting pointers to trait objects.
Before this PR the rules were as follows:
With this PR the rules are changed to
This ensures that
*const dyn Tr<A>->*const dyn Tr<B>casts, which are a problem for #120222)*const dyn Tr<'a>->*const dyn Tr<'b>casts, which are a problem for #120217)Some notes:
*const dyn Tto*const WithHeader<dyn T>, etcdyn A + 'lt) is not checked, so you can still cast*mut FnOnce() + '_to*mut FnOnce() + 'static, etcThe diagnostics are currently not great, to say the least, but as far as I can tell this correctly fixes the issues.
cc @oli-obk @compiler-errors @lcnr