Skip to content

Commit 288ced5

Browse files
committed
Auto merge of #137295 - matthiaskrgr:rollup-tdu3t39, r=matthiaskrgr
Rollup of 9 pull requests Successful merges: - #135296 (interpret: adjust vtable validity check for higher-ranked types) - #137106 (Add customized compare for Link in rustdoc) - #137253 (Restrict `bevy_ecs` `ParamSet` hack) - #137262 (Make fewer crates depend on `rustc_ast_ir`) - #137263 (Register `USAGE_OF_TYPE_IR_INHERENT`, remove inherent usages) - #137266 (MIR visitor tweaks) - #137269 (Pattern Migration 2024: properly label `&` patterns whose subpatterns are from macro expansions) - #137277 (stabilize `inherent_str_constructors`) - #137281 (Tweak "expected ident" parse error to avoid talking about doc comments) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 5dc0064 + ccdf5e2 commit 288ced5

File tree

3 files changed

+75
-0
lines changed

3 files changed

+75
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Test that transmuting from `&dyn Trait<fn(&'static ())>` to `&dyn Trait<for<'a> fn(&'a ())>` is UB.
2+
//
3+
// The vtable of `() as Trait<fn(&'static ())>` and `() as Trait<for<'a> fn(&'a ())>` can have
4+
// different entries and, because in the former the entry for `foo` is vacant, this test will
5+
// segfault at runtime.
6+
7+
trait Trait<U> {
8+
fn foo(&self)
9+
where
10+
U: HigherRanked,
11+
{
12+
}
13+
}
14+
impl<T, U> Trait<U> for T {}
15+
16+
trait HigherRanked {}
17+
impl HigherRanked for for<'a> fn(&'a ()) {}
18+
19+
// 2nd candidate is required so that selecting `(): Trait<fn(&'static ())>` will
20+
// evaluate the candidates and fail the leak check instead of returning the
21+
// only applicable candidate.
22+
trait Unsatisfied {}
23+
impl<T: Unsatisfied> HigherRanked for T {}
24+
25+
fn main() {
26+
let x: &dyn Trait<fn(&'static ())> = &();
27+
let y: &dyn Trait<for<'a> fn(&'a ())> = unsafe { std::mem::transmute(x) };
28+
//~^ ERROR: wrong trait in wide pointer vtable
29+
y.foo();
30+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error: Undefined Behavior: constructing invalid value: wrong trait in wide pointer vtable: expected `Trait<for<'a> fn(&'a ())>`, but encountered `Trait<fn(&())>`
2+
--> tests/fail/validity/dyn-transmute-inner-binder.rs:LL:CC
3+
|
4+
LL | let y: &dyn Trait<for<'a> fn(&'a ())> = unsafe { std::mem::transmute(x) };
5+
| ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: wrong trait in wide pointer vtable: expected `Trait<for<'a> fn(&'a ())>`, but encountered `Trait<fn(&())>`
6+
|
7+
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
8+
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
9+
= note: BACKTRACE:
10+
= note: inside `main` at tests/fail/validity/dyn-transmute-inner-binder.rs:LL:CC
11+
12+
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
13+
14+
error: aborting due to 1 previous error
15+

tests/pass/dyn-upcast.rs

+30
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ fn main() {
99
drop_principal();
1010
modulo_binder();
1111
modulo_assoc();
12+
bidirectional_subtyping();
1213
}
1314

1415
fn vtable_nop_cast() {
@@ -531,3 +532,32 @@ fn modulo_assoc() {
531532

532533
(&() as &dyn Trait as &dyn Middle<()>).say_hello(&0);
533534
}
535+
536+
fn bidirectional_subtyping() {
537+
// Test that transmuting between subtypes of dyn traits is fine, even in the
538+
// "wrong direction", i.e. going from a lower-ranked to a higher-ranked dyn trait.
539+
// Note that compared to the `dyn-transmute-inner-binder` test, the `for` is on the
540+
// *outside* here!
541+
542+
trait Trait<U: ?Sized> {}
543+
impl<T, U: ?Sized> Trait<U> for T {}
544+
545+
struct Wrapper<T: ?Sized>(T);
546+
547+
let x: &dyn Trait<fn(&'static ())> = &();
548+
let _y: &dyn for<'a> Trait<fn(&'a ())> = unsafe { std::mem::transmute(x) };
549+
550+
let x: &dyn for<'a> Trait<fn(&'a ())> = &();
551+
let _y: &dyn Trait<fn(&'static ())> = unsafe { std::mem::transmute(x) };
552+
553+
let x: &dyn Trait<dyn Trait<fn(&'static ())>> = &();
554+
let _y: &dyn for<'a> Trait<dyn Trait<fn(&'a ())>> = unsafe { std::mem::transmute(x) };
555+
556+
let x: &dyn for<'a> Trait<dyn Trait<fn(&'a ())>> = &();
557+
let _y: &dyn Trait<dyn Trait<fn(&'static ())>> = unsafe { std::mem::transmute(x) };
558+
559+
// This lowers to a ptr-to-ptr cast (which behaves like a transmute)
560+
// and not an unsizing coercion:
561+
let x: *const dyn for<'a> Trait<&'a ()> = &();
562+
let _y: *const Wrapper<dyn Trait<&'static ()>> = x as _;
563+
}

0 commit comments

Comments
 (0)