Skip to content

Commit 32e5e34

Browse files
Instantiate binders in supertrait_vtable_slot
1 parent 42ff2ee commit 32e5e34

File tree

2 files changed

+38
-17
lines changed

2 files changed

+38
-17
lines changed

compiler/rustc_trait_selection/src/traits/vtable.rs

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ use std::fmt::Debug;
22
use std::ops::ControlFlow;
33

44
use rustc_hir::def_id::DefId;
5+
use rustc_infer::infer::{BoundRegionConversionTime, TyCtxtInferExt};
6+
use rustc_infer::traits::ObligationCause;
57
use rustc_infer::traits::util::PredicateSet;
68
use rustc_middle::bug;
79
use rustc_middle::query::Providers;
@@ -13,7 +15,7 @@ use smallvec::{SmallVec, smallvec};
1315
use tracing::debug;
1416

1517
use crate::errors::DumpVTableEntries;
16-
use crate::traits::{impossible_predicates, is_vtable_safe_method};
18+
use crate::traits::{ObligationCtxt, impossible_predicates, is_vtable_safe_method};
1719

1820
#[derive(Clone, Debug)]
1921
pub enum VtblSegment<'tcx> {
@@ -383,17 +385,37 @@ pub(crate) fn supertrait_vtable_slot<'tcx>(
383385
let ty::Dynamic(target, _, _) = *target.kind() else {
384386
bug!();
385387
};
386-
let target_principal = tcx
387-
.normalize_erasing_regions(ty::ParamEnv::reveal_all(), target.principal()?)
388-
.with_self_ty(tcx, tcx.types.trait_object_dummy_self);
388+
let target_principal = target.principal()?.with_self_ty(tcx, tcx.types.trait_object_dummy_self);
389389

390390
// Given that we have a target principal, it is a bug for there not to be a source principal.
391391
let ty::Dynamic(source, _, _) = *source.kind() else {
392392
bug!();
393393
};
394-
let source_principal = tcx
395-
.normalize_erasing_regions(ty::ParamEnv::reveal_all(), source.principal().unwrap())
396-
.with_self_ty(tcx, tcx.types.trait_object_dummy_self);
394+
let source_principal =
395+
source.principal().unwrap().with_self_ty(tcx, tcx.types.trait_object_dummy_self);
396+
397+
let infcx = tcx.infer_ctxt().build();
398+
let param_env = ty::ParamEnv::reveal_all();
399+
let trait_refs_are_compatible =
400+
|source: ty::PolyTraitRef<'tcx>, target: ty::PolyTraitRef<'tcx>| {
401+
infcx.probe(|_| {
402+
let ocx = ObligationCtxt::new(&infcx);
403+
let source = ocx.normalize(&ObligationCause::dummy(), param_env, source);
404+
let target = ocx.normalize(&ObligationCause::dummy(), param_env, target);
405+
infcx.enter_forall(target, |target| {
406+
let source = infcx.instantiate_binder_with_fresh_vars(
407+
DUMMY_SP,
408+
BoundRegionConversionTime::HigherRankedType,
409+
source,
410+
);
411+
let Ok(()) = ocx.eq(&ObligationCause::dummy(), param_env, target, source)
412+
else {
413+
return false;
414+
};
415+
ocx.select_all_or_error().is_empty()
416+
})
417+
})
418+
};
397419

398420
let vtable_segment_callback = {
399421
let mut vptr_offset = 0;
@@ -404,9 +426,7 @@ pub(crate) fn supertrait_vtable_slot<'tcx>(
404426
}
405427
VtblSegment::TraitOwnEntries { trait_ref, emit_vptr } => {
406428
vptr_offset += tcx.own_existential_vtable_entries(trait_ref.def_id()).len();
407-
if tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), trait_ref)
408-
== target_principal
409-
{
429+
if trait_refs_are_compatible(trait_ref, target_principal) {
410430
if emit_vptr {
411431
return ControlFlow::Break(Some(vptr_offset));
412432
} else {
Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,22 @@
11
//@ revisions: current next
22
//@ ignore-compare-mode-next-solver (explicit revisions)
33
//@[next] compile-flags: -Znext-solver
4-
//@ check-pass
4+
//@ build-pass
55

6-
// We should be able to instantiate a binder during trait upcasting.
7-
// This test could be `check-pass`, but we should make sure that we
8-
// do so in both trait solvers.
6+
// Check that we are able to instantiate a binder during trait upcasting,
7+
// and that it doesn't cause any issues with codegen either.
98

109
#![feature(trait_upcasting)]
1110

1211
trait Supertrait<'a, 'b> {}
1312
trait Subtrait<'a, 'b>: Supertrait<'a, 'b> {}
1413

15-
impl<'a> Supertrait<'a, 'a> for () {}
16-
impl<'a> Subtrait<'a, 'a> for () {}
14+
impl Supertrait<'_, '_> for () {}
15+
impl Subtrait<'_, '_> for () {}
1716
fn ok(x: &dyn for<'a, 'b> Subtrait<'a, 'b>) -> &dyn for<'a> Supertrait<'a, 'a> {
1817
x
1918
}
2019

21-
fn main() {}
20+
fn main() {
21+
ok(&());
22+
}

0 commit comments

Comments
 (0)