1
Fork 0

Propagate the resolved type of assoc const bindings via query feeding

This commit is contained in:
León Orell Valerian Liehr 2023-12-31 05:06:53 +01:00
parent 23a3d777c8
commit 8bb49e22b5
No known key found for this signature in database
GPG key ID: D17A07215F68E713
9 changed files with 92 additions and 38 deletions

View file

@ -408,7 +408,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
// Create the generic arguments for the associated type or constant by joining the
// parent arguments (the arguments of the trait) and the own arguments (the ones of
// the associated item itself) and construct an alias type using them.
candidate.map_bound(|trait_ref| {
let alias_ty = candidate.map_bound(|trait_ref| {
let ident = Ident::new(assoc_item.name, binding.ident.span);
let item_segment = hir::PathSegment {
ident,
@ -430,7 +430,18 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
// *constants* to represent *const projections*. Alias *term* would be a more
// appropriate name but alas.
ty::AliasTy::new(tcx, assoc_item.def_id, alias_args)
})
});
// Provide the resolved type of the associated constant to `type_of(AnonConst)`.
if !speculative && let ty::AssocKind::Const = assoc_kind {
let ty = alias_ty.map_bound(|ty| tcx.type_of(ty.def_id).instantiate(tcx, ty.args));
// Since the arguments passed to the alias type above may contain early-bound
// generic parameters, the instantiated type may contain some as well.
// Therefore wrap it in `EarlyBinder`.
tcx.feed_type_of_assoc_const_binding(binding.hir_id, ty::EarlyBinder::bind(ty));
}
alias_ty
};
match binding.kind {

View file

@ -63,6 +63,7 @@ pub fn provide(providers: &mut Providers) {
*providers = Providers {
type_of: type_of::type_of,
type_of_opaque: type_of::type_of_opaque,
type_of_assoc_const_binding: type_of::type_of_assoc_const_binding,
type_alias_is_lazy: type_of::type_alias_is_lazy,
item_bounds: item_bounds::item_bounds,
explicit_item_bounds: item_bounds::explicit_item_bounds,

View file

@ -78,35 +78,10 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
.expect("const parameter types cannot be generic");
}
Node::TypeBinding(binding @ &TypeBinding { hir_id: binding_id, .. })
if let Node::TraitRef(trait_ref) = tcx.parent_hir_node(binding_id) =>
{
let Some(trait_def_id) = trait_ref.trait_def_id() else {
return Ty::new_error_with_message(
tcx,
tcx.def_span(def_id),
"Could not find trait",
);
};
let assoc_items = tcx.associated_items(trait_def_id);
let assoc_item = assoc_items.find_by_name_and_kind(
tcx,
binding.ident,
ty::AssocKind::Const,
def_id.to_def_id(),
);
return if let Some(assoc_item) = assoc_item {
tcx.type_of(assoc_item.def_id)
.no_bound_vars()
.expect("const parameter types cannot be generic")
} else {
// FIXME(associated_const_equality): add a useful error message here.
Ty::new_error_with_message(
tcx,
tcx.def_span(def_id),
"Could not find associated const on trait",
)
};
Node::TypeBinding(&TypeBinding { hir_id, .. }) => {
// FIXME(fmease): Reject “escaping” early-bound generic parameters.
// FIXME(fmease): Reject escaping late-bound vars.
return tcx.type_of_assoc_const_binding(hir_id).skip_binder().skip_binder();
}
// This match arm is for when the def_id appears in a GAT whose
@ -315,6 +290,18 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
}
}
pub(super) fn type_of_assoc_const_binding<'tcx>(
tcx: TyCtxt<'tcx>,
hir_id: HirId,
) -> ty::EarlyBinder<ty::Binder<'tcx, Ty<'tcx>>> {
let reported = tcx.dcx().delayed_bug(format!(
"attempt to obtain type of assoc const binding `{hir_id}` before \
it was resolved by `add_predicates_for_ast_type_binding`"
));
ty::EarlyBinder::bind(ty::Binder::dummy(Ty::new_error(tcx, reported)))
}
fn get_path_containing_arg_in_pat<'hir>(
pat: &'hir hir::Pat<'hir>,
arg_id: HirId,