diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2025-02-06 13:09:58 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-02-06 13:09:58 +0100 |
| commit | b62f318a3b77cce4809d26baa5c54dcf50ed1ce5 (patch) | |
| tree | d8b745df4c288897870dfb83b0a09b68c05bf49f | |
| parent | 62cad970e86b00bd731226426cb259148679fbb7 (diff) | |
| parent | 0a8b81eb4ed791bec10c86d66ac4f622b1d83351 (diff) | |
| download | rust-b62f318a3b77cce4809d26baa5c54dcf50ed1ce5.tar.gz rust-b62f318a3b77cce4809d26baa5c54dcf50ed1ce5.zip | |
Rollup merge of #136311 - compiler-errors:vtable-fixes-2, r=lcnr
Ensure that we never try to monomorphize the upcasting or vtable calls of impossible dyn types Check for impossible obligations in the `dyn Trait` type we're trying to compute its the vtable upcasting and method call slots. r? lcnr
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/vtable.rs | 26 | ||||
| -rw-r--r-- | tests/ui/traits/trait-upcasting/mono-impossible.rs | 26 |
2 files changed, 47 insertions, 5 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs index 000e6a765d3..0024316b877 100644 --- a/compiler/rustc_trait_selection/src/traits/vtable.rs +++ b/compiler/rustc_trait_selection/src/traits/vtable.rs @@ -318,9 +318,17 @@ pub(crate) fn first_method_vtable_slot<'tcx>(tcx: TyCtxt<'tcx>, key: ty::TraitRe bug!(); }; let source_principal = tcx.instantiate_bound_regions_with_erased( - source.principal().unwrap().with_self_ty(tcx, tcx.types.trait_object_dummy_self), + source.principal().unwrap().with_self_ty(tcx, key.self_ty()), ); + // We're monomorphizing a call to a dyn trait object that can never be constructed. + if tcx.instantiate_and_check_impossible_predicates(( + source_principal.def_id, + source_principal.args, + )) { + return 0; + } + let target_principal = ty::ExistentialTraitRef::erase_self_ty(tcx, key); let vtable_segment_callback = { @@ -373,19 +381,27 @@ pub(crate) fn supertrait_vtable_slot<'tcx>( let (source, target) = key; // If the target principal is `None`, we can just return `None`. - let ty::Dynamic(target, _, _) = *target.kind() else { + let ty::Dynamic(target_data, _, _) = *target.kind() else { bug!(); }; - let target_principal = tcx.instantiate_bound_regions_with_erased(target.principal()?); + let target_principal = tcx.instantiate_bound_regions_with_erased(target_data.principal()?); // Given that we have a target principal, it is a bug for there not to be a source principal. - let ty::Dynamic(source, _, _) = *source.kind() else { + let ty::Dynamic(source_data, _, _) = *source.kind() else { bug!(); }; let source_principal = tcx.instantiate_bound_regions_with_erased( - source.principal().unwrap().with_self_ty(tcx, tcx.types.trait_object_dummy_self), + source_data.principal().unwrap().with_self_ty(tcx, source), ); + // We're monomorphizing a dyn trait object upcast that can never be constructed. + if tcx.instantiate_and_check_impossible_predicates(( + source_principal.def_id, + source_principal.args, + )) { + return None; + } + let vtable_segment_callback = { let mut vptr_offset = 0; move |segment| { diff --git a/tests/ui/traits/trait-upcasting/mono-impossible.rs b/tests/ui/traits/trait-upcasting/mono-impossible.rs new file mode 100644 index 00000000000..88f19e1c95f --- /dev/null +++ b/tests/ui/traits/trait-upcasting/mono-impossible.rs @@ -0,0 +1,26 @@ +//@ build-pass + +#![feature(trait_upcasting)] + +trait Supertrait<T> { + fn method(&self) {} +} +impl<T> Supertrait<T> for () {} + +trait WithAssoc { + type Assoc; +} +trait Trait<P: WithAssoc>: Supertrait<P::Assoc> + Supertrait<()> {} + +fn upcast<P>(x: &dyn Trait<P>) -> &dyn Supertrait<()> { + x +} + +fn call<P>(x: &dyn Trait<P>) { + x.method(); +} + +fn main() { + println!("{:p}", upcast::<()> as *const ()); + println!("{:p}", call::<()> as *const ()); +} |
