Instantiate binders in supertrait_vtable_slot
This commit is contained in:
parent
c3ce4e66a5
commit
af3f212453
@ -2,6 +2,8 @@
|
|||||||
use std::ops::ControlFlow;
|
use std::ops::ControlFlow;
|
||||||
|
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
|
use rustc_infer::infer::{BoundRegionConversionTime, TyCtxtInferExt};
|
||||||
|
use rustc_infer::traits::ObligationCause;
|
||||||
use rustc_infer::traits::util::PredicateSet;
|
use rustc_infer::traits::util::PredicateSet;
|
||||||
use rustc_middle::bug;
|
use rustc_middle::bug;
|
||||||
use rustc_middle::query::Providers;
|
use rustc_middle::query::Providers;
|
||||||
@ -13,7 +15,7 @@
|
|||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
|
|
||||||
use crate::errors::DumpVTableEntries;
|
use crate::errors::DumpVTableEntries;
|
||||||
use crate::traits::{impossible_predicates, is_vtable_safe_method};
|
use crate::traits::{ObligationCtxt, impossible_predicates, is_vtable_safe_method};
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum VtblSegment<'tcx> {
|
pub enum VtblSegment<'tcx> {
|
||||||
@ -383,17 +385,37 @@ pub(crate) fn supertrait_vtable_slot<'tcx>(
|
|||||||
let ty::Dynamic(target, _, _) = *target.kind() else {
|
let ty::Dynamic(target, _, _) = *target.kind() else {
|
||||||
bug!();
|
bug!();
|
||||||
};
|
};
|
||||||
let target_principal = tcx
|
let target_principal = target.principal()?.with_self_ty(tcx, tcx.types.trait_object_dummy_self);
|
||||||
.normalize_erasing_regions(ty::ParamEnv::reveal_all(), target.principal()?)
|
|
||||||
.with_self_ty(tcx, tcx.types.trait_object_dummy_self);
|
|
||||||
|
|
||||||
// Given that we have a target principal, it is a bug for there not to be a source 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, _, _) = *source.kind() else {
|
||||||
bug!();
|
bug!();
|
||||||
};
|
};
|
||||||
let source_principal = tcx
|
let source_principal =
|
||||||
.normalize_erasing_regions(ty::ParamEnv::reveal_all(), source.principal().unwrap())
|
source.principal().unwrap().with_self_ty(tcx, tcx.types.trait_object_dummy_self);
|
||||||
.with_self_ty(tcx, tcx.types.trait_object_dummy_self);
|
|
||||||
|
let infcx = tcx.infer_ctxt().build();
|
||||||
|
let param_env = ty::ParamEnv::reveal_all();
|
||||||
|
let trait_refs_are_compatible =
|
||||||
|
|source: ty::PolyTraitRef<'tcx>, target: ty::PolyTraitRef<'tcx>| {
|
||||||
|
infcx.probe(|_| {
|
||||||
|
let ocx = ObligationCtxt::new(&infcx);
|
||||||
|
let source = ocx.normalize(&ObligationCause::dummy(), param_env, source);
|
||||||
|
let target = ocx.normalize(&ObligationCause::dummy(), param_env, target);
|
||||||
|
infcx.enter_forall(target, |target| {
|
||||||
|
let source = infcx.instantiate_binder_with_fresh_vars(
|
||||||
|
DUMMY_SP,
|
||||||
|
BoundRegionConversionTime::HigherRankedType,
|
||||||
|
source,
|
||||||
|
);
|
||||||
|
let Ok(()) = ocx.eq(&ObligationCause::dummy(), param_env, target, source)
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
ocx.select_all_or_error().is_empty()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
let vtable_segment_callback = {
|
let vtable_segment_callback = {
|
||||||
let mut vptr_offset = 0;
|
let mut vptr_offset = 0;
|
||||||
@ -404,9 +426,7 @@ pub(crate) fn supertrait_vtable_slot<'tcx>(
|
|||||||
}
|
}
|
||||||
VtblSegment::TraitOwnEntries { trait_ref, emit_vptr } => {
|
VtblSegment::TraitOwnEntries { trait_ref, emit_vptr } => {
|
||||||
vptr_offset += tcx.own_existential_vtable_entries(trait_ref.def_id()).len();
|
vptr_offset += tcx.own_existential_vtable_entries(trait_ref.def_id()).len();
|
||||||
if tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), trait_ref)
|
if trait_refs_are_compatible(trait_ref, target_principal) {
|
||||||
== target_principal
|
|
||||||
{
|
|
||||||
if emit_vptr {
|
if emit_vptr {
|
||||||
return ControlFlow::Break(Some(vptr_offset));
|
return ControlFlow::Break(Some(vptr_offset));
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,21 +1,22 @@
|
|||||||
//@ revisions: current next
|
//@ revisions: current next
|
||||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||||
//@[next] compile-flags: -Znext-solver
|
//@[next] compile-flags: -Znext-solver
|
||||||
//@ check-pass
|
//@ build-pass
|
||||||
|
|
||||||
// We should be able to instantiate a binder during trait upcasting.
|
// Check that we are able to instantiate a binder during trait upcasting,
|
||||||
// This test could be `check-pass`, but we should make sure that we
|
// and that it doesn't cause any issues with codegen either.
|
||||||
// do so in both trait solvers.
|
|
||||||
|
|
||||||
#![feature(trait_upcasting)]
|
#![feature(trait_upcasting)]
|
||||||
|
|
||||||
trait Supertrait<'a, 'b> {}
|
trait Supertrait<'a, 'b> {}
|
||||||
trait Subtrait<'a, 'b>: Supertrait<'a, 'b> {}
|
trait Subtrait<'a, 'b>: Supertrait<'a, 'b> {}
|
||||||
|
|
||||||
impl<'a> Supertrait<'a, 'a> for () {}
|
impl Supertrait<'_, '_> for () {}
|
||||||
impl<'a> Subtrait<'a, 'a> for () {}
|
impl Subtrait<'_, '_> for () {}
|
||||||
fn ok(x: &dyn for<'a, 'b> Subtrait<'a, 'b>) -> &dyn for<'a> Supertrait<'a, 'a> {
|
fn ok(x: &dyn for<'a, 'b> Subtrait<'a, 'b>) -> &dyn for<'a> Supertrait<'a, 'a> {
|
||||||
x
|
x
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {
|
||||||
|
ok(&());
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user