Skip to content

Remove 'static requirement on try_as_dyn#150161

Open
oli-obk wants to merge 2 commits into
rust-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 into
rust-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.

@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

This comment has been minimized.


fn impl_is_fully_generic_for_reflection(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
tcx.impl_trait_header(def_id).is_fully_generic_for_reflection()
&& tcx.explicit_predicates_of(def_id).is_fully_generic_for_reflection()
Copy link
Copy Markdown
Member

@BoxyUwU BoxyUwU May 1, 2026

Choose a reason for hiding this comment

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

If we don't need to check elaborated clauses does that mean we actually don't need to check any predicates since we'll wind up proving them in Reflection mode too

View changes since the review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

well, we do need to prevent outlives bounds, but I guess we could allow any trait bound that doesn't repeat generic params or uses 'static

}

/// Allow simple where bounds like `T: Debug`, but prevent any kind of
/// outlives bounds or uses of generic parameters on the right hand side.
Copy link
Copy Markdown
Member

@BoxyUwU BoxyUwU May 1, 2026

Choose a reason for hiding this comment

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

this feels kind of arbitrary to me, Self parameters are not special in any way in the type system afaik, what's the reason we want this

View changes since the review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The reason is basically that things like T: Debug get checked for fully-genericness when the trait solver actually gets to the impl for it, so recursively everything will be fine. There is probably more we can allow, but this one was easy to reason about

Comment thread compiler/rustc_middle/src/ty/mod.rs Outdated
Comment thread compiler/rustc_middle/src/ty/mod.rs
Comment thread compiler/rustc_middle/src/ty/generics.rs
PostBorrowckAnalysis { defined_opaque_types: I::LocalDefIds },
/// During the evaluation of reflection logic that ignores lifetimes, we can only
/// handle impls that are fully generic over all lifetimes without constraints on
/// those lifetimes (other than implied bounds).
Copy link
Copy Markdown
Member

@BoxyUwU BoxyUwU May 1, 2026

Choose a reason for hiding this comment

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

why other than implied bounds? unlike normal specialization we don't have a base impl whose lifetime constraints have been checked to hold which we can rely on.

impl<T> Trait for &'_ T seems problematic for try_as_dyn given noone can ever actually check T: '_

View changes since the review

Copy link
Copy Markdown
Member

@BoxyUwU BoxyUwU May 1, 2026

Choose a reason for hiding this comment

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

i guess you can rely on wfness of the traitref the user wrote for the try_as_dyn 🤔 so yeah maybe that is fine?

return Err(());
match self.infcx.typing_mode() {
TypingMode::Coherence => {}
TypingMode::Reflection
Copy link
Copy Markdown
Member

@BoxyUwU BoxyUwU May 1, 2026

Choose a reason for hiding this comment

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

why do we not handle reservation impls in reflection mode. is there a test for try_as_dyn'ing a trait ref which has a reservation impl

View changes since the review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

We do handle them, this is just the code path for when we fail to resolve the impl anyway. In case the impl is fully generic for reflection we fall through to the normal code path below

@BoxyUwU
Copy link
Copy Markdown
Member

BoxyUwU commented May 1, 2026

@rustbot author

@rustbot rustbot 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 May 1, 2026
Comment thread library/core/src/any.rs
}

/// Returns `Some(&U)` if `T` can be coerced to the trait object type `U`. Otherwise, it returns `None`.
/// Trait that is automatically implemented for all `dyn Trait<'b, C> + 'a` without assoc type bounds.
Copy link
Copy Markdown
Member

@BoxyUwU BoxyUwU May 1, 2026

Choose a reason for hiding this comment

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

why no assoc type bounds? this trait just exists to ensure that the type being try_as_dyn'd outlives the lifetime bound of the resulting trait object right?

View changes since the review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

We'd need to find some other way to handle

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

use std::any::TypeId;
use std::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>>()
            //~^ ERROR `dyn Trait<Assoc = &'a Box<i32>>: TryAsDynCompatible<'_>` is not satisfied
            .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}");
}

So I punted on all assoc types

@rust-bors

This comment has been minimized.

@oli-obk oli-obk force-pushed the try_as_dyn_non_static branch from 67f7c3d to 0d0eec0 Compare May 29, 2026 14:16
@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented May 29, 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.

@rust-log-analyzer
Copy link
Copy Markdown
Collaborator

The job tidy failed! Check out the build log: (web) (plain enhanced) (plain)

Click to see the possible cause of the failure (guessed by this bot)
[TIMING:end] tool::Tidy { compiler: Compiler { stage: 0, host: x86_64-unknown-linux-gnu, forced_compiler: false }, target: x86_64-unknown-linux-gnu } -- 0.000
fmt check
Diff in /checkout/compiler/rustc_middle/src/ty/mod.rs:284:
     /// For trait impls, checks whether
     /// * the type and trait only use generic lifetime arguments (and no concrete ones like `'static`), and
     /// * uses any generic param (lifetime or type) only once.
-    /// 
+    ///
     /// This is a pessimistic analysis, so it will reject alias types
     /// and other types that may be actually ok. We can allow more in the future.
     ///

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

Labels

S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. 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