Rollup merge of #130944 - lukas-code:ptr-ptr-sub, r=compiler-errors
Allow instantiating trait object binder in ptr-to-ptr casts For unsizing coercions between trait objects with the same principal, we already allow instantiating the for binder. For example, coercing `Box<dyn for<'a> Trait<'a>` to `Box<dyn Trait<'static>>` is allowed. Since ptr-to-ptr casts will insert an unsizing coercion before the cast if possible, this has the consequence that the following compiles already: ```rust // This compiles today. fn cast<'b>(x: *mut dyn for<'a> Trait<'a>) -> *mut dyn Trait<'b> { // lowered as (roughly) // tmp: *mut dyn Trait<'?0> = Unsize(x) // requires dyn for<'a> Trait<'a> <: dyn Trait<'?0> // ret: *mut dyn Trait<'b> = PtrToPtr(tmp) // requires dyn Trait<'?0> == dyn Trait<'b> x as _ } ``` However, if no unsizing coercion is inserted then this currently fails to compile as one type is more general than the other. This PR will allow this code to compile, too, by changing ptr-to-ptr casts of pointers with vtable metadata to use sutyping instead of type equality. ```rust // This will compile after this PR. fn cast<'b>(x: *mut dyn for<'a> Trait<'a>) -> *mut Wrapper<dyn Trait<'b>> { // lowered as (roughly) // no Unsize here! // ret: *mut Wrapper<dyn Trait<'b>> = PtrToPtr(x) // requires dyn for<'a> Trait<'a> == dyn Trait<'b> x as _ } ``` Note that it is already possible to work around the current restrictions and make the code compile before this PR by splitting the cast in two, so this shouldn't allow a new class of programs to compile: ```rust // Workaround that compiles today. fn cast<'b>(x: *mut dyn for<'a> Trait<'a>) -> *mut Wrapper<dyn Trait<'b>> { x as *mut dyn Trait<'_> as _ } ``` r? `@compiler-errors` cc `@WaffleLapkin`
This commit is contained in:
commit
58d0730fb8
@ -2437,7 +2437,7 @@ fn check_rvalue(&mut self, body: &Body<'tcx>, rvalue: &Rvalue<'tcx>, location: L
|
||||
|
||||
debug!(?src_tty, ?dst_tty, ?src_obj, ?dst_obj);
|
||||
|
||||
self.eq_types(
|
||||
self.sub_types(
|
||||
src_obj,
|
||||
dst_obj,
|
||||
location.to_locations(),
|
||||
|
@ -15,6 +15,12 @@ fn change_lt_ba<'a, 'b: 'a>(x: *mut dyn Trait<'a>) -> *mut dyn Trait<'b> {
|
||||
x as _ //~ error: lifetime may not live long enough
|
||||
}
|
||||
|
||||
fn change_lt_hr<'a>(x: *mut dyn Trait<'a>) -> *mut dyn for<'b> Trait<'b> {
|
||||
x as _ //~ error: lifetime may not live long enough
|
||||
//~^ error: mismatched types
|
||||
//~| one type is more general than the other
|
||||
}
|
||||
|
||||
trait Assocked {
|
||||
type Assoc: ?Sized;
|
||||
}
|
||||
|
@ -61,7 +61,29 @@ LL | x as _
|
||||
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/ptr-to-trait-obj-different-regions-misc.rs:25:5
|
||||
--> $DIR/ptr-to-trait-obj-different-regions-misc.rs:19:5
|
||||
|
|
||||
LL | fn change_lt_hr<'a>(x: *mut dyn Trait<'a>) -> *mut dyn for<'b> Trait<'b> {
|
||||
| -- lifetime `'a` defined here
|
||||
LL | x as _
|
||||
| ^^^^^^ cast requires that `'a` must outlive `'static`
|
||||
|
|
||||
help: to declare that the trait object captures data from argument `x`, you can add an explicit `'a` lifetime bound
|
||||
|
|
||||
LL | fn change_lt_hr<'a>(x: *mut dyn Trait<'a>) -> *mut dyn for<'b> Trait<'b> + 'a {
|
||||
| ++++
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/ptr-to-trait-obj-different-regions-misc.rs:19:5
|
||||
|
|
||||
LL | x as _
|
||||
| ^^^^^^ one type is more general than the other
|
||||
|
|
||||
= note: expected trait object `dyn for<'b> Trait<'b>`
|
||||
found trait object `dyn Trait<'_>`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/ptr-to-trait-obj-different-regions-misc.rs:31:5
|
||||
|
|
||||
LL | fn change_assoc_0<'a, 'b>(
|
||||
| -- -- lifetime `'b` defined here
|
||||
@ -77,7 +99,7 @@ LL | x as _
|
||||
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/ptr-to-trait-obj-different-regions-misc.rs:25:5
|
||||
--> $DIR/ptr-to-trait-obj-different-regions-misc.rs:31:5
|
||||
|
|
||||
LL | fn change_assoc_0<'a, 'b>(
|
||||
| -- -- lifetime `'b` defined here
|
||||
@ -97,7 +119,7 @@ help: `'b` and `'a` must be the same: replace one with the other
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/ptr-to-trait-obj-different-regions-misc.rs:32:5
|
||||
--> $DIR/ptr-to-trait-obj-different-regions-misc.rs:38:5
|
||||
|
|
||||
LL | fn change_assoc_1<'a, 'b>(
|
||||
| -- -- lifetime `'b` defined here
|
||||
@ -113,7 +135,7 @@ LL | x as _
|
||||
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/ptr-to-trait-obj-different-regions-misc.rs:32:5
|
||||
--> $DIR/ptr-to-trait-obj-different-regions-misc.rs:38:5
|
||||
|
|
||||
LL | fn change_assoc_1<'a, 'b>(
|
||||
| -- -- lifetime `'b` defined here
|
||||
@ -133,12 +155,13 @@ help: `'b` and `'a` must be the same: replace one with the other
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/ptr-to-trait-obj-different-regions-misc.rs:39:20
|
||||
--> $DIR/ptr-to-trait-obj-different-regions-misc.rs:45:20
|
||||
|
|
||||
LL | fn extend_to_static<'a>(ptr: *const dyn Trait<'a>) {
|
||||
| -- lifetime `'a` defined here
|
||||
LL | require_static(ptr as _)
|
||||
| ^^^^^^^^ cast requires that `'a` must outlive `'static`
|
||||
|
||||
error: aborting due to 9 previous errors
|
||||
error: aborting due to 11 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
@ -10,8 +10,37 @@ fn cast_inherent_lt<'a, 'b>(x: *mut (dyn Trait<'static> + 'a)) -> *mut (dyn Trai
|
||||
x as _
|
||||
}
|
||||
|
||||
fn cast_away_higher_ranked<'a>(x: *mut dyn for<'b> Trait<'b>) -> *mut dyn Trait<'a> {
|
||||
x as _
|
||||
}
|
||||
|
||||
fn unprincipled<'a, 'b>(x: *mut (dyn Send + 'a)) -> *mut (dyn Sync + 'b) {
|
||||
x as _
|
||||
}
|
||||
|
||||
// If it is possible to coerce from the source to the target type modulo
|
||||
// regions, then we skip the HIR checks for ptr-to-ptr casts and possibly
|
||||
// insert an unsizing coercion into the MIR before the ptr-to-ptr cast.
|
||||
// By wrapping the target type, we ensure that no coercion happens
|
||||
// and also test the non-coercion cast behavior.
|
||||
struct Wrapper<T: ?Sized>(T);
|
||||
|
||||
fn remove_auto_wrap<'a>(x: *mut (dyn Trait<'a> + Send)) -> *mut Wrapper<dyn Trait<'a>> {
|
||||
x as _
|
||||
}
|
||||
|
||||
fn cast_inherent_lt_wrap<'a, 'b>(
|
||||
x: *mut (dyn Trait<'static> + 'a),
|
||||
) -> *mut Wrapper<dyn Trait<'static> + 'b> {
|
||||
x as _
|
||||
}
|
||||
|
||||
fn cast_away_higher_ranked_wrap<'a>(x: *mut dyn for<'b> Trait<'b>) -> *mut Wrapper<dyn Trait<'a>> {
|
||||
x as _
|
||||
}
|
||||
|
||||
fn unprincipled_wrap<'a, 'b>(x: *mut (dyn Send + 'a)) -> *mut Wrapper<dyn Sync + 'b> {
|
||||
x as _
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
Loading…
Reference in New Issue
Block a user