Remove 'static requirement on try_as_dyn#150161
Remove 'static requirement on try_as_dyn#150161oli-obk wants to merge 2 commits intorust-lang:mainfrom
Conversation
|
r? @SparrowLii rustbot has assigned @SparrowLii. Use |
This comment has been minimized.
This comment has been minimized.
e7ef1ee to
29f1dba
Compare
|
r? BoxyUwU |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
29f1dba to
fe33b0c
Compare
This comment has been minimized.
This comment has been minimized.
dfa5c33 to
30f5641
Compare
This comment has been minimized.
This comment has been minimized.
|
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 |
This comment was marked as resolved.
This comment was marked as resolved.
|
|
||
| ### 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`. |
There was a problem hiding this comment.
This would already run into the "no 'static rule". I'm unsure if this rule is needed or not.
There was a problem hiding this comment.
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).
| 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. |
There was a problem hiding this comment.
This page doesn't define "lifetime-infected parameter" anywhere.
This comment has been minimized.
This comment has been minimized.
|
This PR's I'm unsure whether 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:
|
hmm... and desugar |
ae17524 to
ceb4679
Compare
|
Some changes occurred to MIR optimizations cc @rust-lang/wg-mir-opt |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
ceb4679 to
9aba3c3
Compare
This comment has been minimized.
This comment has been minimized.
9aba3c3 to
a85463d
Compare
|
@rustbot ready |
This comment has been minimized.
This comment has been minimized.
a85463d to
0b2da7a
Compare
This comment has been minimized.
This comment has been minimized.
0b2da7a to
676173f
Compare
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
676173f to
67f7c3d
Compare
|
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. |
|
|
||
| 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() |
There was a problem hiding this comment.
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
| } | ||
|
|
||
| /// Allow simple where bounds like `T: Debug`, but prevent any kind of | ||
| /// outlives bounds or uses of generic parameters on the right hand side. |
There was a problem hiding this comment.
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
| } | ||
|
|
||
| impl<'tcx> ImplTraitHeader<'tcx> { | ||
| /// For trait impls, checks whether the type and trait only have generic parameters in their |
There was a problem hiding this comment.
so sth like impl Trait for Vec<u32> would be considered not fully generic?
There was a problem hiding this comment.
no this is just "forbid repeated parameters and aliases" need to update this comment :3
| } | ||
| } | ||
|
|
||
| fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result { |
There was a problem hiding this comment.
no visit_const? I guess because equality of const generics is always applicable? comment :3
| } | ||
| } | ||
|
|
||
| fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result { |
There was a problem hiding this comment.
no visit_const? I guess because equality of const generics is always applicable? comment :3
| 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). |
There was a problem hiding this comment.
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: '_
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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
|
@rustbot author |
| } | ||
|
|
||
| /// 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. |
There was a problem hiding this comment.
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 all comments
tracking issue: #144361
cc @ivarflakstad @izagawd