rust/compiler
bors c37fbd873a Auto merge of #135318 - compiler-errors:vtable-fixes, r=lcnr
Fix deduplication mismatches in vtables leading to upcasting unsoundness

We currently have two cases where subtleties in supertraits can trigger disagreements in the vtable layout, e.g. leading to a different vtable layout being accessed at a callsite compared to what was prepared during unsizing. Namely:

### #135315

In this example, we were not normalizing supertraits when preparing vtables. In the example,

```
trait Supertrait<T> {
    fn _print_numbers(&self, mem: &[usize; 100]) {
        println!("{mem:?}");
    }
}
impl<T> Supertrait<T> for () {}

trait Identity {
    type Selff;
}
impl<Selff> Identity for Selff {
    type Selff = Selff;
}

trait Middle<T>: Supertrait<()> + Supertrait<T> {
    fn say_hello(&self, _: &usize) {
        println!("Hello!");
    }
}
impl<T> Middle<T> for () {}

trait Trait: Middle<<() as Identity>::Selff> {}
impl Trait for () {}

fn main() {
    (&() as &dyn Trait as &dyn Middle<()>).say_hello(&0);
}
```

When we prepare `dyn Trait`, we see a supertrait of `Middle<<() as Identity>::Selff>`, which itself has two supertraits `Supertrait<()>` and `Supertrait<<() as Identity>::Selff>`. These two supertraits are identical, but they are not duplicated because we were using structural equality and *not* considering normalization. This leads to a vtable layout with two trait pointers.

When we upcast to `dyn Middle<()>`, those two supertraits are now the same, leading to a vtable layout with only one trait pointer. This leads to an offset error, and we call the wrong method.

### #135316

This one is a bit more interesting, and is the bulk of the changes in this PR. It's a bit similar, except it uses binder equality instead of normalization to make the compiler get confused about two vtable layouts. In the example,

```
trait Supertrait<T> {
    fn _print_numbers(&self, mem: &[usize; 100]) {
        println!("{mem:?}");
    }
}
impl<T> Supertrait<T> for () {}

trait Trait<T, U>: Supertrait<T> + Supertrait<U> {
    fn say_hello(&self, _: &usize) {
        println!("Hello!");
    }
}
impl<T, U> Trait<T, U> for () {}

fn main() {
    (&() as &'static dyn for<'a> Trait<&'static (), &'a ()>
        as &'static dyn Trait<&'static (), &'static ()>)
        .say_hello(&0);
}
```

When we prepare the vtable for `dyn for<'a> Trait<&'static (), &'a ()>`, we currently consider the PolyTraitRef of the vtable as the key for a supertrait. This leads two two supertraits -- `Supertrait<&'static ()>` and `for<'a> Supertrait<&'a ()>`.

However, we can upcast[^up] without offsetting the vtable from `dyn for<'a> Trait<&'static (), &'a ()>` to `dyn Trait<&'static (), &'static ()>`. This is just instantiating the principal trait ref for a specific `'a = 'static`. However, when considering those supertraits, we now have only one distinct supertrait -- `Supertrait<&'static ()>` (which is deduplicated since there are two supertraits with the same substitutions). This leads to similar offsetting issues, leading to the wrong method being called.

[^up]: I say upcast but this is a cast that is allowed on stable, since it's not changing the vtable at all, just instantiating the binder of the principal trait ref for some lifetime.

The solution here is to recognize that a vtable isn't really meaningfully higher ranked, and to just treat a vtable as corresponding to a `TraitRef` so we can do this deduplication more faithfully. That is to say, the vtable for `dyn for<'a> Tr<'a>` and `dyn Tr<'x>` are always identical, since they both would correspond to a set of free regions on an impl... Do note that `Tr<for<'a> fn(&'a ())>` and `Tr<fn(&'static ())>` are still distinct.

----

There's a bit more that can be cleaned up. In codegen, we can stop using `PolyExistentialTraitRef` basically everywhere. We can also fix SMIR to stop storing `PolyExistentialTraitRef` in its vtable allocations.

As for testing, it's difficult to actually turn this into something that can be tested with `rustc_dump_vtable`, since having multiple supertraits that are identical is a recipe for ambiguity errors. Maybe someone else is more creative with getting that attr to work, since the tests I added being run-pass tests is a bit unsatisfying. Miri also doesn't help here, since it doesn't really generate vtables that are offset by an index in the same way as codegen.

r? `@lcnr` for the vibe check? Or reassign, idk. Maybe let's talk about whether this makes sense.

<sup>(I guess an alternative would also be to not do any deduplication of vtable supertraits (or only a really conservative subset) rather than trying to normalize and deduplicate more faithfully here. Not sure if that works and is sufficient tho.)</sup>

cc `@steffahn` -- ty for the minimizations
cc `@WaffleLapkin` -- since you're overseeing the feature stabilization :3

Fixes #135315
Fixes #135316
2025-01-31 04:09:11 +00:00
..
rustc switch jemalloc-sys back to tikv-jemalloc-sys, and update to 0.6.0 2024-12-03 08:56:33 +00:00
rustc_abi Auto merge of #135047 - Flakebi:amdgpu-kernel-cc, r=workingjubilee 2025-01-17 04:36:09 +00:00
rustc_arena Add inherent versions of MaybeUninit methods for slices 2025-01-11 23:57:00 -05:00
rustc_ast Rollup merge of #135882 - hkBst:master, r=estebank 2025-01-30 12:45:27 +01:00
rustc_ast_ir Add sugar for &pin (const|mut) types 2024-10-07 11:15:04 -07:00
rustc_ast_lowering Eliminate PatKind::Path 2025-01-29 15:45:13 +00:00
rustc_ast_passes Refactor FnKind variant to hold &Fn 2025-01-28 11:22:25 -08:00
rustc_ast_pretty Refactor FnKind variant to hold &Fn 2025-01-28 11:22:25 -08:00
rustc_attr_data_structures Rename OptimizeAttr::None to Default 2025-01-24 19:34:01 +00:00
rustc_attr_parsing Run clippy --fix for unnecessary_map_or lint 2025-01-19 19:15:00 +00:00
rustc_baked_icu_data Delete the cfg(not(parallel)) serial compiler 2024-11-12 13:38:58 +00:00
rustc_borrowck Auto merge of #136038 - compiler-errors:outlives, r=lcnr 2025-01-30 11:40:32 +00:00
rustc_builtin_macros Rollup merge of #135882 - hkBst:master, r=estebank 2025-01-30 12:45:27 +01:00
rustc_codegen_cranelift Auto merge of #135318 - compiler-errors:vtable-fixes, r=lcnr 2025-01-31 04:09:11 +00:00
rustc_codegen_gcc Use ExistentialTraitRef throughout codegen 2025-01-30 15:34:00 +00:00
rustc_codegen_llvm Auto merge of #135318 - compiler-errors:vtable-fixes, r=lcnr 2025-01-31 04:09:11 +00:00
rustc_codegen_ssa Auto merge of #135318 - compiler-errors:vtable-fixes, r=lcnr 2025-01-31 04:09:11 +00:00
rustc_const_eval Auto merge of #135318 - compiler-errors:vtable-fixes, r=lcnr 2025-01-31 04:09:11 +00:00
rustc_data_structures Rollup merge of #136149 - cuviper:rustc-rayon-indexmap, r=compiler-errors 2025-01-28 18:17:29 +01:00
rustc_driver
rustc_driver_impl Make crate AST mutation accessible for driver callback 2025-01-28 19:45:20 +00:00
rustc_error_codes Auto merge of #133154 - estebank:issue-133137, r=wesleywiser 2025-01-25 11:41:21 +00:00
rustc_error_messages Convert some Into impls into From impls 2024-12-31 01:56:33 +00:00
rustc_errors Auto merge of #119286 - jyn514:linker-output, r=bjorn3 2025-01-25 17:16:33 +00:00
rustc_expand Auto merge of #134478 - compiler-errors:attr-span, r=oli-obk 2025-01-22 14:46:41 +00:00
rustc_feature Rework rustc_dump_vtable 2025-01-30 15:30:04 +00:00
rustc_fluent_macro use tracked_path in rustc_fluent_macro 2024-10-19 22:32:38 +08:00
rustc_fs_util Couple of changes to make it easier to compile rustc for wasm 2024-09-26 19:51:14 +00:00
rustc_graphviz Reformat using the new identifier sorting from rustfmt 2024-09-22 19:11:29 -04:00
rustc_hir Eliminate PatKind::Path 2025-01-29 15:45:13 +00:00
rustc_hir_analysis Do not treat vtable supertraits as distinct when bound with different bound vars 2025-01-30 15:33:58 +00:00
rustc_hir_pretty Eliminate PatKind::Path 2025-01-29 15:45:13 +00:00
rustc_hir_typeck Rollup merge of #135434 - dianne:match-2024-for-edition-2024, r=Nadrieril 2025-01-30 12:45:18 +01:00
rustc_incremental turn hir::ItemKind::Fn into a named-field variant 2025-01-04 11:35:31 +01:00
rustc_index Run clippy --fix for unnecessary_map_or lint 2025-01-19 19:15:00 +00:00
rustc_index_macros update rustc_index_macros feature handling 2024-12-19 20:32:12 +03:00
rustc_infer Auto merge of #135318 - compiler-errors:vtable-fixes, r=lcnr 2025-01-31 04:09:11 +00:00
rustc_interface Remove print_vtable_sizes 2025-01-30 15:30:04 +00:00
rustc_lexer Add test to check unicode identifier version 2024-12-09 06:23:59 -08:00
rustc_lint Auto merge of #136038 - compiler-errors:outlives, r=lcnr 2025-01-30 11:40:32 +00:00
rustc_lint_defs Downgrade linker-warnings to allow-by-default 2025-01-26 22:57:20 -05:00
rustc_llvm Make our DIFlags match LLVMDIFlags in the LLVM-C API 2025-01-21 14:41:44 +11:00
rustc_log Avoid naming variables str 2025-01-07 14:30:02 +02:00
rustc_macros Avoid naming variables str 2025-01-07 14:30:02 +02:00
rustc_metadata Make item self/non-self bound naming less whack 2025-01-28 19:08:50 +00:00
rustc_middle Auto merge of #135318 - compiler-errors:vtable-fixes, r=lcnr 2025-01-31 04:09:11 +00:00
rustc_mir_build add comments 2025-01-30 18:13:16 +01:00
rustc_mir_dataflow Represent the raw pointer for a array length check as a new kind of fake borrow 2025-01-28 00:00:33 +00:00
rustc_mir_transform Rollup merge of #135748 - compiler-errors:len-2, r=RalfJung,oli-obk 2025-01-28 14:23:22 +01:00
rustc_monomorphize Do not treat vtable supertraits as distinct when bound with different bound vars 2025-01-30 15:33:58 +00:00
rustc_next_trait_solver introduce ty::Value 2025-01-30 17:47:44 +01:00
rustc_parse Rollup merge of #135882 - hkBst:master, r=estebank 2025-01-30 12:45:27 +01:00
rustc_parse_format use impl Into<String> 2025-01-29 09:48:08 +01:00
rustc_passes Handle all PatExprs in dead code analysis 2025-01-29 15:45:13 +00:00
rustc_pattern_analysis Get rid of mir::Const::from_ty_const 2025-01-20 04:26:44 +00:00
rustc_privacy Split hir TyKind and ConstArgKind in two and update hir::Visitor 2025-01-23 06:01:36 +00:00
rustc_query_impl don't return an Option from try_find_dep_kind 2025-01-07 21:57:00 +01:00
rustc_query_system Properly note when query stack is being cut off 2025-01-16 19:12:22 +00:00
rustc_resolve Refactor FnKind variant to hold &Fn 2025-01-28 11:22:25 -08:00
rustc_sanitizers check the types in ty::Value to value conversion 2025-01-30 18:13:16 +01:00
rustc_serialize Fix explicit_iter_loop in rustc_serialize 2024-10-16 15:44:16 +02:00
rustc_session Auto merge of #135318 - compiler-errors:vtable-fixes, r=lcnr 2025-01-31 04:09:11 +00:00
rustc_smir Auto merge of #135318 - compiler-errors:vtable-fixes, r=lcnr 2025-01-31 04:09:11 +00:00
rustc_span Rollup merge of #136071 - wowinter13:clippy-add-diagnostic-items, r=flip1995 2025-01-28 18:17:26 +01:00
rustc_symbol_mangling Auto merge of #135318 - compiler-errors:vtable-fixes, r=lcnr 2025-01-31 04:09:11 +00:00
rustc_target Auto merge of #135030 - Flakebi:require-cpu, r=workingjubilee 2025-01-30 20:21:50 +00:00
rustc_trait_selection Auto merge of #135318 - compiler-errors:vtable-fixes, r=lcnr 2025-01-31 04:09:11 +00:00
rustc_traits Auto merge of #136011 - compiler-errors:query-norm-vaniquishes-us, r=jackh726 2025-01-29 02:12:12 +00:00
rustc_transmute introduce ty::Value 2025-01-30 17:47:44 +01:00
rustc_ty_utils introduce ty::Value 2025-01-30 17:47:44 +01:00
rustc_type_ir introduce ty::Value 2025-01-30 17:47:44 +01:00
rustc_type_ir_macros do not relate Abi and Safety 2024-10-22 23:13:04 +02:00
stable_mir Represent the raw pointer for a array length check as a new kind of fake borrow 2025-01-28 00:00:33 +00:00