Skip to content

Commit c71a011

Browse files
committed
Introduce trait_obj_ty query
This query computes the trait object, complete with associated type projections for its supertraits, from a trait ref. This is intended for use by CFI labeling, to allow it to determine the abstract type that will be used by a receiver, based on the instantiated trait that defines the vtable.
1 parent 6a92312 commit c71a011

File tree

2 files changed

+38
-0
lines changed
  • compiler

2 files changed

+38
-0
lines changed

compiler/rustc_middle/src/query/mod.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2257,6 +2257,15 @@ rustc_queries! {
22572257
query find_field((def_id, ident): (DefId, rustc_span::symbol::Ident)) -> Option<rustc_target::abi::FieldIdx> {
22582258
desc { |tcx| "find the index of maybe nested field `{ident}` in `{}`", tcx.def_path_str(def_id) }
22592259
}
2260+
2261+
/// Construct a type for a trait object corresponding to `trait_ref`. This type will have all
2262+
/// associated types for it and its supertraits expanded and resolved as additional predicates.
2263+
///
2264+
/// The provided `trait_ref` must be sufficiently instantiated that all associated types can be
2265+
/// successfully resolved.
2266+
query trait_object_ty(trait_ref: ty::PolyTraitRef<'tcx>) -> Ty<'tcx> {
2267+
desc { "Compute the trait object type for calling a method on a trait" }
2268+
}
22602269
}
22612270

22622271
rustc_query_append! { define_callbacks! }

compiler/rustc_trait_selection/src/traits/vtable.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::errors::DumpVTableEntries;
2+
use crate::traits;
23
use crate::traits::{impossible_predicates, is_vtable_safe_method};
34
use rustc_hir::def_id::DefId;
45
use rustc_hir::lang_items::LangItem;
@@ -13,6 +14,7 @@ use rustc_span::{sym, Span};
1314
use smallvec::SmallVec;
1415

1516
use std::fmt::Debug;
17+
use std::iter;
1618
use std::ops::ControlFlow;
1719

1820
#[derive(Clone, Debug)]
@@ -232,6 +234,32 @@ fn own_existential_vtable_entries_iter(
232234
own_entries
233235
}
234236

237+
fn trait_object_ty<'tcx>(tcx: TyCtxt<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tcx>) -> Ty<'tcx> {
238+
let principal_pred = poly_trait_ref.map_bound(|trait_ref| {
239+
ty::ExistentialPredicate::Trait(ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref))
240+
});
241+
let assoc_preds = traits::supertraits(tcx, poly_trait_ref).flat_map(|super_poly_trait_ref| {
242+
tcx.associated_items(super_poly_trait_ref.def_id())
243+
.in_definition_order()
244+
.filter(|item| item.kind == ty::AssocKind::Type)
245+
.map(move |assoc_ty| {
246+
super_poly_trait_ref.map_bound(|super_trait_ref| {
247+
let alias_ty = ty::AliasTy::new(tcx, assoc_ty.def_id, super_trait_ref.args);
248+
let resolved = tcx
249+
.normalize_erasing_regions(ty::ParamEnv::reveal_all(), alias_ty.to_ty(tcx));
250+
ty::ExistentialPredicate::Projection(ty::ExistentialProjection {
251+
def_id: assoc_ty.def_id,
252+
args: ty::ExistentialTraitRef::erase_self_ty(tcx, super_trait_ref).args,
253+
term: resolved.into(),
254+
})
255+
})
256+
})
257+
});
258+
let preds =
259+
tcx.mk_poly_existential_predicates_from_iter(iter::once(principal_pred).chain(assoc_preds));
260+
Ty::new_dynamic(tcx, preds, tcx.lifetimes.re_erased, ty::Dyn)
261+
}
262+
235263
/// Given a trait `trait_ref`, iterates the vtable entries
236264
/// that come from `trait_ref`, including its supertraits.
237265
fn vtable_entries<'tcx>(
@@ -404,6 +432,7 @@ pub(super) fn provide(providers: &mut Providers) {
404432
own_existential_vtable_entries,
405433
vtable_entries,
406434
vtable_trait_upcasting_coercion_new_vptr_slot,
435+
trait_object_ty,
407436
..*providers
408437
};
409438
}

0 commit comments

Comments
 (0)