Stop allocating vtable entries for non-object-safe methods
This commit is contained in:
parent
03c775c955
commit
871eb6233e
6 changed files with 54 additions and 12 deletions
|
@ -647,14 +647,14 @@ fn vtable_entries<'tcx>(
|
|||
.filter(|item| item.kind == ty::AssocKind::Fn);
|
||||
// Now list each method's DefId and InternalSubsts (for within its trait).
|
||||
// If the method can never be called from this object, produce `Vacant`.
|
||||
let own_entries = trait_methods.map(move |trait_method| {
|
||||
let own_entries = trait_methods.filter_map(move |trait_method| {
|
||||
debug!("vtable_entries: trait_method={:?}", trait_method);
|
||||
let def_id = trait_method.def_id;
|
||||
|
||||
// Some methods cannot be called on an object; skip those.
|
||||
if !is_vtable_safe_method(tcx, trait_ref.def_id(), &trait_method) {
|
||||
debug!("vtable_entries: not vtable safe");
|
||||
return VtblEntry::Vacant;
|
||||
return None;
|
||||
}
|
||||
|
||||
// The method may have some early-bound lifetimes; add regions for those.
|
||||
|
@ -681,7 +681,7 @@ fn vtable_entries<'tcx>(
|
|||
let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, substs);
|
||||
if impossible_predicates(tcx, predicates.predicates) {
|
||||
debug!("vtable_entries: predicates do not hold");
|
||||
return VtblEntry::Vacant;
|
||||
return Some(VtblEntry::Vacant);
|
||||
}
|
||||
|
||||
let instance = ty::Instance::resolve_for_vtable(
|
||||
|
@ -691,7 +691,7 @@ fn vtable_entries<'tcx>(
|
|||
substs,
|
||||
)
|
||||
.expect("resolution failed during building vtable representation");
|
||||
VtblEntry::Method(instance)
|
||||
Some(VtblEntry::Method(instance))
|
||||
});
|
||||
|
||||
entries.extend(own_entries);
|
||||
|
|
|
@ -289,7 +289,9 @@ pub fn count_own_vtable_entries(tcx: TyCtxt<'tcx>, trait_ref: ty::PolyTraitRef<'
|
|||
// Count number of methods and add them to the total offset.
|
||||
// Skip over associated types and constants.
|
||||
for trait_item in tcx.associated_items(trait_ref.def_id()).in_definition_order() {
|
||||
if trait_item.kind == ty::AssocKind::Fn {
|
||||
let is_vtable_safe_method = trait_item.kind == ty::AssocKind::Fn
|
||||
&& super::is_vtable_safe_method(tcx, trait_ref.def_id(), trait_item);
|
||||
if is_vtable_safe_method {
|
||||
entries += 1;
|
||||
}
|
||||
}
|
||||
|
@ -308,13 +310,16 @@ pub fn get_vtable_index_of_object_method<N>(
|
|||
// add them to the total offset.
|
||||
// Skip over associated types and constants, as those aren't stored in the vtable.
|
||||
let mut entries = object.vtable_base;
|
||||
for trait_item in tcx.associated_items(object.upcast_trait_ref.def_id()).in_definition_order() {
|
||||
let trait_def_id = object.upcast_trait_ref.def_id();
|
||||
for trait_item in tcx.associated_items(trait_def_id).in_definition_order() {
|
||||
let is_vtable_safe_method = trait_item.kind == ty::AssocKind::Fn
|
||||
&& super::is_vtable_safe_method(tcx, trait_def_id, trait_item);
|
||||
if trait_item.def_id == method_def_id {
|
||||
// The item with the ID we were given really ought to be a method.
|
||||
assert_eq!(trait_item.kind, ty::AssocKind::Fn);
|
||||
assert!(is_vtable_safe_method);
|
||||
return entries;
|
||||
}
|
||||
if trait_item.kind == ty::AssocKind::Fn {
|
||||
if is_vtable_safe_method {
|
||||
entries += 1;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue