Skip to content

Commit

Permalink
Auto merge of #86461 - crlf0710:rich_vtable, r=nikomatsakis
Browse files Browse the repository at this point in the history
Refactor vtable format for upcoming trait_upcasting feature.

This modifies vtable format:
1. reordering occurrence order of methods coming from different traits
2. include `VPtr`s for supertraits where this vtable cannot be directly reused during trait upcasting.
Also, during codegen, the vtables corresponding to these newly included `VPtr` will be requested and generated.

For the cases where this vtable can directly used, now the super trait vtable has exactly the same content to some prefix of this one.

r? `@bjorn3`
cc `@RalfJung`
cc `@rust-lang/wg-traits`
  • Loading branch information
bors committed Jul 24, 2021
2 parents 1c66d11 + fbb353a commit f9b95f9
Show file tree
Hide file tree
Showing 15 changed files with 894 additions and 87 deletions.
1 change: 1 addition & 0 deletions compiler/rustc_feature/src/builtin_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -603,6 +603,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
rustc_attr!(TEST, rustc_dump_program_clauses, AssumedUsed, template!(Word)),
rustc_attr!(TEST, rustc_dump_env_program_clauses, AssumedUsed, template!(Word)),
rustc_attr!(TEST, rustc_object_lifetime_default, AssumedUsed, template!(Word)),
rustc_attr!(TEST, rustc_dump_vtable, AssumedUsed, template!(Word)),
rustc_attr!(TEST, rustc_dummy, Normal, template!(Word /* doesn't matter*/)),
gated!(
omit_gdb_pretty_printer_section, AssumedUsed, template!(Word),
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_infer/src/traits/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,17 @@ pub fn anonymize_predicate<'tcx>(
tcx.reuse_or_mk_predicate(pred, new)
}

struct PredicateSet<'tcx> {
pub struct PredicateSet<'tcx> {
tcx: TyCtxt<'tcx>,
set: FxHashSet<ty::Predicate<'tcx>>,
}

impl PredicateSet<'tcx> {
fn new(tcx: TyCtxt<'tcx>) -> Self {
pub fn new(tcx: TyCtxt<'tcx>) -> Self {
Self { tcx, set: Default::default() }
}

fn insert(&mut self, pred: ty::Predicate<'tcx>) -> bool {
pub fn insert(&mut self, pred: ty::Predicate<'tcx>) -> bool {
// We have to be careful here because we want
//
// for<'a> Foo<&'a i32>
Expand Down
58 changes: 39 additions & 19 deletions compiler/rustc_middle/src/ty/vtable.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,39 @@
use std::convert::TryFrom;
use std::fmt;

use crate::mir::interpret::{alloc_range, AllocId, Allocation, Pointer, Scalar, ScalarMaybeUninit};
use crate::ty::fold::TypeFoldable;
use crate::ty::{self, DefId, SubstsRef, Ty, TyCtxt};
use crate::ty::{self, Instance, PolyTraitRef, Ty, TyCtxt};
use rustc_ast::Mutability;

#[derive(Clone, Copy, Debug, PartialEq, HashStable)]
#[derive(Clone, Copy, PartialEq, HashStable)]
pub enum VtblEntry<'tcx> {
/// destructor of this type (used in vtable header)
MetadataDropInPlace,
/// layout size of this type (used in vtable header)
MetadataSize,
/// layout align of this type (used in vtable header)
MetadataAlign,
/// non-dispatchable associated function that is excluded from trait object
Vacant,
Method(DefId, SubstsRef<'tcx>),
/// dispatchable associated function
Method(Instance<'tcx>),
/// pointer to a separate supertrait vtable, can be used by trait upcasting coercion
TraitVPtr(PolyTraitRef<'tcx>),
}

impl<'tcx> fmt::Debug for VtblEntry<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// We want to call `Display` on `Instance` and `PolyTraitRef`,
// so we implement this manually.
match self {
VtblEntry::MetadataDropInPlace => write!(f, "MetadataDropInPlace"),
VtblEntry::MetadataSize => write!(f, "MetadataSize"),
VtblEntry::MetadataAlign => write!(f, "MetadataAlign"),
VtblEntry::Vacant => write!(f, "Vacant"),
VtblEntry::Method(instance) => write!(f, "Method({})", instance),
VtblEntry::TraitVPtr(trait_ref) => write!(f, "TraitVPtr({})", trait_ref),
}
}
}

pub const COMMON_VTABLE_ENTRIES: &[VtblEntry<'_>] =
Expand All @@ -36,11 +58,6 @@ impl<'tcx> TyCtxt<'tcx> {
}
drop(vtables_cache);

// See https://github.com/rust-lang/rust/pull/86475#discussion_r655162674
assert!(
!ty.needs_subst() && !poly_trait_ref.map_or(false, |trait_ref| trait_ref.needs_subst())
);
let param_env = ty::ParamEnv::reveal_all();
let vtable_entries = if let Some(poly_trait_ref) = poly_trait_ref {
let trait_ref = poly_trait_ref.with_self_ty(tcx, ty);
let trait_ref = tcx.erase_regions(trait_ref);
Expand All @@ -50,8 +67,9 @@ impl<'tcx> TyCtxt<'tcx> {
COMMON_VTABLE_ENTRIES
};

let layout =
tcx.layout_of(param_env.and(ty)).expect("failed to build vtable representation");
let layout = tcx
.layout_of(ty::ParamEnv::reveal_all().and(ty))
.expect("failed to build vtable representation");
assert!(!layout.is_unsized(), "can't create a vtable for an unsized type");
let size = layout.size.bytes();
let align = layout.align.abi.bytes();
Expand Down Expand Up @@ -79,19 +97,21 @@ impl<'tcx> TyCtxt<'tcx> {
VtblEntry::MetadataSize => Scalar::from_uint(size, ptr_size).into(),
VtblEntry::MetadataAlign => Scalar::from_uint(align, ptr_size).into(),
VtblEntry::Vacant => continue,
VtblEntry::Method(def_id, substs) => {
// See https://github.com/rust-lang/rust/pull/86475#discussion_r655162674
assert!(!substs.needs_subst());

VtblEntry::Method(instance) => {
// Prepare the fn ptr we write into the vtable.
let instance =
ty::Instance::resolve_for_vtable(tcx, param_env, *def_id, substs)
.expect("resolution failed during building vtable representation")
.polymorphize(tcx);
let instance = instance.polymorphize(tcx);
let fn_alloc_id = tcx.create_fn_alloc(instance);
let fn_ptr = Pointer::from(fn_alloc_id);
ScalarMaybeUninit::from_pointer(fn_ptr, &tcx)
}
VtblEntry::TraitVPtr(trait_ref) => {
let super_trait_ref = trait_ref.map_bound(|trait_ref| {
ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref)
});
let supertrait_alloc_id = self.vtable_allocation(ty, Some(super_trait_ref));
let vptr = Pointer::from(supertrait_alloc_id);
ScalarMaybeUninit::from_pointer(vptr, &tcx)
}
};
vtable
.write_scalar(&tcx, alloc_range(ptr_size * idx, ptr_size), scalar)
Expand Down
14 changes: 7 additions & 7 deletions compiler/rustc_mir/src/monomorphize/collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1116,13 +1116,13 @@ fn create_mono_items_for_vtable_methods<'tcx>(
| VtblEntry::MetadataSize
| VtblEntry::MetadataAlign
| VtblEntry::Vacant => None,
VtblEntry::Method(def_id, substs) => ty::Instance::resolve_for_vtable(
tcx,
ty::ParamEnv::reveal_all(),
*def_id,
substs,
)
.filter(|instance| should_codegen_locally(tcx, instance)),
VtblEntry::TraitVPtr(_) => {
// all super trait items already covered, so skip them.
None
}
VtblEntry::Method(instance) => {
Some(*instance).filter(|instance| should_codegen_locally(tcx, instance))
}
})
.map(|item| create_fn_mono_item(tcx, item, source));
output.extend(methods);
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1047,6 +1047,7 @@ symbols! {
rustc_dump_env_program_clauses,
rustc_dump_program_clauses,
rustc_dump_user_substs,
rustc_dump_vtable,
rustc_error,
rustc_evaluate_where_clauses,
rustc_expected_cgu_reuse,
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_trait_selection/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ extern crate rustc_data_structures;
extern crate tracing;
#[macro_use]
extern crate rustc_middle;
#[macro_use]
extern crate smallvec;

pub mod autoderef;
pub mod infer;
Expand Down
Loading

0 comments on commit f9b95f9

Please sign in to comment.