diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2024-10-02 17:10:43 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-10-02 17:10:43 +0200 |
| commit | f9ba5529ebd59dff80e81354f207f6b1566f9143 (patch) | |
| tree | f832106059515d9093de47e7e35088a7de3342c5 /compiler/rustc_codegen_ssa/src | |
| parent | 360f7d7b731c508c88b7b56921a92d281c05dbf7 (diff) | |
| parent | cbb5047d35d76cd34ccf238220ccc70316f6ab77 (diff) | |
| download | rust-f9ba5529ebd59dff80e81354f207f6b1566f9143.tar.gz rust-f9ba5529ebd59dff80e81354f207f6b1566f9143.zip | |
Rollup merge of #130863 - compiler-errors:relax-codegen-dyn-assert, r=lcnr
Relax a debug assertion for dyn principal *equality* in codegen Maybe this sucks and I should just bite the bullet and use `infcx.sub` here. Thoughts? r? lcnr Fixes #130855
Diffstat (limited to 'compiler/rustc_codegen_ssa/src')
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/base.rs | 59 |
1 files changed, 53 insertions, 6 deletions
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 5c67600e4ee..d91c0f0790d 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -27,6 +27,9 @@ use rustc_session::config::{self, CrateType, EntryFnType, OptLevel, OutputType}; use rustc_span::symbol::sym; use rustc_span::{DUMMY_SP, Symbol}; use rustc_target::abi::FIRST_VARIANT; +use rustc_trait_selection::infer::at::ToTrace; +use rustc_trait_selection::infer::{BoundRegionConversionTime, TyCtxtInferExt}; +use rustc_trait_selection::traits::{ObligationCause, ObligationCtxt}; use tracing::{debug, info}; use crate::assert_module_sources::CguReuse; @@ -101,6 +104,54 @@ pub fn compare_simd_types<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( bx.sext(cmp, ret_ty) } +/// Codegen takes advantage of the additional assumption, where if the +/// principal trait def id of what's being casted doesn't change, +/// then we don't need to adjust the vtable at all. This +/// corresponds to the fact that `dyn Tr<A>: Unsize<dyn Tr<B>>` +/// requires that `A = B`; we don't allow *upcasting* objects +/// between the same trait with different args. If we, for +/// some reason, were to relax the `Unsize` trait, it could become +/// unsound, so let's validate here that the trait refs are subtypes. +pub fn validate_trivial_unsize<'tcx>( + tcx: TyCtxt<'tcx>, + source_data: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>, + target_data: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>, +) -> bool { + match (source_data.principal(), target_data.principal()) { + (Some(hr_source_principal), Some(hr_target_principal)) => { + let infcx = tcx.infer_ctxt().build(); + let universe = infcx.universe(); + let ocx = ObligationCtxt::new(&infcx); + infcx.enter_forall(hr_target_principal, |target_principal| { + let source_principal = infcx.instantiate_binder_with_fresh_vars( + DUMMY_SP, + BoundRegionConversionTime::HigherRankedType, + hr_source_principal, + ); + let Ok(()) = ocx.eq_trace( + &ObligationCause::dummy(), + ty::ParamEnv::reveal_all(), + ToTrace::to_trace( + &ObligationCause::dummy(), + hr_target_principal, + hr_source_principal, + ), + target_principal, + source_principal, + ) else { + return false; + }; + if !ocx.select_all_or_error().is_empty() { + return false; + } + infcx.leak_check(universe, None).is_ok() + }) + } + (None, None) => true, + _ => false, + } +} + /// Retrieves the information we are losing (making dynamic) in an unsizing /// adjustment. /// @@ -133,12 +184,8 @@ fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // between the same trait with different args. If we, for // some reason, were to relax the `Unsize` trait, it could become // unsound, so let's assert here that the trait refs are *equal*. - // - // We can use `assert_eq` because the binders should have been anonymized, - // and because higher-ranked equality now requires the binders are equal. - debug_assert_eq!( - data_a.principal(), - data_b.principal(), + debug_assert!( + validate_trivial_unsize(cx.tcx(), data_a, data_b), "NOP unsize vtable changed principal trait ref: {data_a} -> {data_b}" ); |
