Skip to content

Remove 'static requirement on try_as_dyn#150161

Open
oli-obk wants to merge 2 commits intorust-lang:mainfrom
oli-obk:try_as_dyn_non_static
Open

Remove 'static requirement on try_as_dyn#150161
oli-obk wants to merge 2 commits intorust-lang:mainfrom
oli-obk:try_as_dyn_non_static

Conversation

@oli-obk
Copy link
Copy Markdown
Contributor

@oli-obk oli-obk commented Dec 19, 2025

@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented Dec 19, 2025

Some changes occurred to the CTFE machinery

cc @RalfJung, @oli-obk, @lcnr

Some changes occurred to the core trait solver

cc @rust-lang/initiative-trait-system-refactor

Some changes occurred to the CTFE / Miri interpreter

cc @rust-lang/miri

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Dec 19, 2025
@rustbot rustbot added the WG-trait-system-refactor The Rustc Trait System Refactor Initiative (-Znext-solver) label Dec 19, 2025
@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented Dec 19, 2025

r? @SparrowLii

rustbot has assigned @SparrowLii.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

@rust-log-analyzer

This comment has been minimized.

@oli-obk oli-obk force-pushed the try_as_dyn_non_static branch 2 times, most recently from e7ef1ee to 29f1dba Compare December 19, 2025 16:44
Copy link
Copy Markdown
Contributor

@danielhenrymantilla danielhenrymantilla left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some drive-by comments; but I'm not rustc/HIR-savy, so take these with a grain of salt 🙇

View changes since this review

Comment thread compiler/rustc_hir/src/hir.rs Outdated
Comment thread tests/ui/any/non_static.rs Outdated
Comment thread tests/ui/any/non_static.rs
Comment thread tests/ui/any/non_static.rs Outdated
Comment thread compiler/rustc_hir/src/hir.rs Outdated
Comment thread tests/ui/any/non_static.rs Outdated
Comment thread compiler/rustc_hir/src/hir.rs Outdated
Comment thread compiler/rustc_next_trait_solver/src/solve/trait_goals.rs Outdated
@BoxyUwU
Copy link
Copy Markdown
Member

BoxyUwU commented Dec 19, 2025

r? BoxyUwU

@rustbot rustbot assigned BoxyUwU and unassigned SparrowLii Dec 19, 2025
Comment thread library/core/src/any.rs Outdated
Comment thread tests/ui/any/non_static.rs Outdated
@theemathas

This comment has been minimized.

@theemathas

This comment has been minimized.

@theemathas

This comment has been minimized.

@BoxyUwU BoxyUwU added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Dec 30, 2025
@oli-obk oli-obk force-pushed the try_as_dyn_non_static branch from 29f1dba to fe33b0c Compare January 7, 2026 12:41
@rustbot

This comment has been minimized.

@oli-obk oli-obk force-pushed the try_as_dyn_non_static branch 3 times, most recently from dfa5c33 to 30f5641 Compare January 7, 2026 12:44
Comment thread tests/ui/any/static_method_bound.rs
@rust-log-analyzer

This comment has been minimized.

@oli-obk
Copy link
Copy Markdown
Contributor Author

oli-obk commented Jan 13, 2026

The hacky solution is obviously not a general fix. But I think it's progress. As a next step I will add the input type as a generic parameter on TryAsDynCompat, at which point we should be able to enforce (in borrowck) that the input type outlives any lifetimes on the dyn Trait or its generic parameters. So if a generic parameter T has a 'static bound, it could be used as an input type for a try_as_dyn irrespective of the bounds on the dyn Trait. In the other direction, we will likely end up rejecting many traits that have generic parameters as the bounds are not something that can be written in Rust.

@theemathas

This comment was marked as resolved.

@rustbot

This comment has been minimized.

@oli-obk
Copy link
Copy Markdown
Contributor Author

oli-obk commented Mar 10, 2026

Thanks @danielhenrymantilla for writing down this summary. I haven't addressed the concern about the restriction yet, but I included your summary mostly verbatim in the unstable book

@rust-log-analyzer

This comment has been minimized.


### Each trait `where` bound with an associated type equality (`Type: Trait<Assoc = Type2>`) does not mention lifetime-infected parameters.

Checking whether `Option<&'? str>: IntoIterator<Item = &'static str>` holds discriminates `'?` against `'static`.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would already run into the "no 'static rule". I'm unsure if this rule is needed or not.

Copy link
Copy Markdown
Contributor

@danielhenrymantilla danielhenrymantilla Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very true, let's go with the following example, then:

impl<'a, 'b> Trait<'b> for &'a str
where
    Option<&'a str>: IntoIterator<Item = &'b str>,
{}

which amounts to having done:

impl<'a> Trait<'a> for &'a str {}

which brings us back to "no repetitions in header" (&'? str: Trait<'static> discriminates '? against 'static).


Suggested change
Checking whether `Option<&'? str>: IntoIterator<Item = &'static str>` holds discriminates `'?` against `'static`.
Associated-type equality bounds can very much amount to lifetime-infected parameter equality constraints, which are problematic as per the "at most one mention of each lifetime-infected parameter in header" rule.
To illustrate, with the following definitions, `&'? str: Trait<'static>` discriminates `'?` against `'static`:
```rust
impl<'a, 'b> Trait<'b> for &'a str
where
// &'a str = &'b str,
Option<&'a str>: IntoIterator<Item = &'b str>,
{}
impl<'a> Trait<'a> for &'a str {}
```


The most obvious one: if you have `impl IsStatic for &'static str`, then determining whether `&'? str : IsStatic` does hold amounts to discriminating `'? : 'static`.

### Each outlives `where` bound (`Type: 'a` and `'a: 'b`) does not mention lifetime-infected parameters.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This page doesn't define "lifetime-infected parameter" anywhere.

@rust-bors

This comment has been minimized.

@theemathas
Copy link
Copy Markdown
Contributor

theemathas commented Mar 17, 2026

This PR's TypeId::trait_info_of method is unsound when combined with ptr_metadata and arbitrary_self_types_pointers. This unsoundness occurs because TypeId::trait_info_of does not check whether the trait is TryAsDynCompatible.

I'm unsure whether arbitrary_self_types_pointers is necessary for the unsoundness. See rust-lang/unsafe-code-guidelines#516.

The following code performs a use-after-free with this PR.

#![feature(type_info, ptr_metadata, arbitrary_self_types_pointers)]

use std::{
    any::TypeId,
    ptr::{self, DynMetadata},
};

type Payload = Box<i32>;

trait Trait {
    type Assoc;
    fn method(self: *const Self, value: Self::Assoc) -> &'static Payload;
}
struct Thing;
impl Trait for Thing {
    type Assoc = &'static Payload;
    fn method(self: *const Self, value: Self::Assoc) -> &'static Payload {
        value
    }
}

fn extend<'a>(payload: &'a Payload) -> &'static Payload {
    let metadata: DynMetadata<dyn Trait<Assoc = &'a Payload>> = const {
        TypeId::of::<Thing>()
            .trait_info_of::<dyn Trait<Assoc = &'a Payload>>()
            .unwrap()
            .get_vtable()
    };
    let ptr: *const dyn Trait<Assoc = &'a Payload> =
        ptr::from_raw_parts(std::ptr::null::<()>(), metadata);
    ptr.method(payload)
}

fn main() {
    let payload: Box<Payload> = Box::new(Box::new(1i32));
    let wrong: &'static Payload = extend(&*payload);
    drop(payload);
    println!("{wrong}");
}

Potential solutions include:

  • Add a (): TryAsDynCompatible<T> bound to TypeId::TraitInfoOf
    • Alternatively, change the TryAsDynCompatible trait to be a bound like dyn Trait: TryAsDynCompatible<'a>, and have a separate SourceType: 'a bound. And add T: TryAsDynCompatible<'a> to TypeId::TraitInfoOf.
  • Change TraitImpl::get_vtable to be unsafe.

@oli-obk
Copy link
Copy Markdown
Contributor Author

oli-obk commented Apr 21, 2026

change the TryAsDynCompatible trait to be a bound like dyn Trait: TryAsDynCompatible<'a>, and have a separate SourceType: 'a bound.

hmm... and desugar dyn Trait: TryAsDynCompatible<'a> to adding a constraint on the lifetime 'foo of the trait object? Bidirectional outlives bounds? It feels a bit icky to connect it that way, but I guess so does (): TryAsDynCompatible

@oli-obk oli-obk force-pushed the try_as_dyn_non_static branch from ae17524 to ceb4679 Compare April 21, 2026 09:28
@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented Apr 21, 2026

Some changes occurred to MIR optimizations

cc @rust-lang/wg-mir-opt

@rustbot

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@oli-obk oli-obk force-pushed the try_as_dyn_non_static branch from ceb4679 to 9aba3c3 Compare April 21, 2026 09:55
@rust-log-analyzer

This comment has been minimized.

@oli-obk oli-obk force-pushed the try_as_dyn_non_static branch from 9aba3c3 to a85463d Compare April 21, 2026 11:27
@oli-obk
Copy link
Copy Markdown
Contributor Author

oli-obk commented Apr 21, 2026

@rustbot ready

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Apr 21, 2026
@rust-log-analyzer

This comment has been minimized.

@oli-obk oli-obk force-pushed the try_as_dyn_non_static branch from a85463d to 0b2da7a Compare April 21, 2026 12:09
@rust-log-analyzer

This comment has been minimized.

@oli-obk oli-obk force-pushed the try_as_dyn_non_static branch from 0b2da7a to 676173f Compare April 23, 2026 09:21
@rustbot

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@oli-obk oli-obk force-pushed the try_as_dyn_non_static branch from 676173f to 67f7c3d Compare April 23, 2026 11:09
@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented Apr 23, 2026

This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-libs Relevant to the library team, which will review and decide on the PR/issue. T-types Relevant to the types team, which will review and decide on the PR/issue. WG-trait-system-refactor The Rustc Trait System Refactor Initiative (-Znext-solver)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants