Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor vtable format for upcoming trait_upcasting feature. #86461

Merged
merged 4 commits into from
Jul 24, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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