Rollup merge of #102336 - compiler-errors:issue-102333, r=jackh726
Fix associated type bindings with anon const in GAT position The first commit formats `type_of.rs`, which is really hard to maintain since it uses a bunch of features like `let`-chains and `if let` match arm bindings. Best if you just review the second two diffs. Fixes #102333
This commit is contained in:
commit
1be9ec5443
2 changed files with 102 additions and 30 deletions
|
@ -333,7 +333,12 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
|
||||||
find_opaque_ty_constraints_for_tait(tcx, def_id)
|
find_opaque_ty_constraints_for_tait(tcx, def_id)
|
||||||
}
|
}
|
||||||
// Opaque types desugared from `impl Trait`.
|
// Opaque types desugared from `impl Trait`.
|
||||||
ItemKind::OpaqueTy(OpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn(owner) | hir::OpaqueTyOrigin::AsyncFn(owner), in_trait, .. }) => {
|
ItemKind::OpaqueTy(OpaqueTy {
|
||||||
|
origin:
|
||||||
|
hir::OpaqueTyOrigin::FnReturn(owner) | hir::OpaqueTyOrigin::AsyncFn(owner),
|
||||||
|
in_trait,
|
||||||
|
..
|
||||||
|
}) => {
|
||||||
if in_trait {
|
if in_trait {
|
||||||
span_bug!(item.span, "impl-trait in trait has no default")
|
span_bug!(item.span, "impl-trait in trait has no default")
|
||||||
} else {
|
} else {
|
||||||
|
@ -378,7 +383,9 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
|
||||||
|
|
||||||
Node::Field(field) => icx.to_ty(field.ty),
|
Node::Field(field) => icx.to_ty(field.ty),
|
||||||
|
|
||||||
Node::Expr(&Expr { kind: ExprKind::Closure{..}, .. }) => tcx.typeck(def_id).node_type(hir_id),
|
Node::Expr(&Expr { kind: ExprKind::Closure { .. }, .. }) => {
|
||||||
|
tcx.typeck(def_id).node_type(hir_id)
|
||||||
|
}
|
||||||
|
|
||||||
Node::AnonConst(_) if let Some(param) = tcx.opt_const_param_of(def_id) => {
|
Node::AnonConst(_) if let Some(param) = tcx.opt_const_param_of(def_id) => {
|
||||||
// We defer to `type_of` of the corresponding parameter
|
// We defer to `type_of` of the corresponding parameter
|
||||||
|
@ -410,30 +417,38 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
|
||||||
| Node::Item(&Item { kind: ItemKind::GlobalAsm(asm), .. })
|
| Node::Item(&Item { kind: ItemKind::GlobalAsm(asm), .. })
|
||||||
if asm.operands.iter().any(|(op, _op_sp)| match op {
|
if asm.operands.iter().any(|(op, _op_sp)| match op {
|
||||||
hir::InlineAsmOperand::Const { anon_const }
|
hir::InlineAsmOperand::Const { anon_const }
|
||||||
| hir::InlineAsmOperand::SymFn { anon_const } => anon_const.hir_id == hir_id,
|
| hir::InlineAsmOperand::SymFn { anon_const } => {
|
||||||
|
anon_const.hir_id == hir_id
|
||||||
|
}
|
||||||
_ => false,
|
_ => false,
|
||||||
}) =>
|
}) =>
|
||||||
{
|
{
|
||||||
tcx.typeck(def_id).node_type(hir_id)
|
tcx.typeck(def_id).node_type(hir_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
Node::Variant(Variant { disr_expr: Some(ref e), .. }) if e.hir_id == hir_id => tcx
|
Node::Variant(Variant { disr_expr: Some(ref e), .. }) if e.hir_id == hir_id => {
|
||||||
.adt_def(tcx.hir().get_parent_item(hir_id))
|
tcx.adt_def(tcx.hir().get_parent_item(hir_id)).repr().discr_type().to_ty(tcx)
|
||||||
.repr()
|
}
|
||||||
.discr_type()
|
|
||||||
.to_ty(tcx),
|
|
||||||
|
|
||||||
Node::TypeBinding(binding @ &TypeBinding { hir_id: binding_id, .. })
|
Node::TypeBinding(
|
||||||
if let Node::TraitRef(trait_ref) = tcx.hir().get(
|
binding @ &TypeBinding {
|
||||||
tcx.hir().get_parent_node(binding_id)
|
hir_id: binding_id,
|
||||||
) =>
|
kind: TypeBindingKind::Equality { term: Term::Const(ref e) },
|
||||||
|
..
|
||||||
|
},
|
||||||
|
) if let Node::TraitRef(trait_ref) =
|
||||||
|
tcx.hir().get(tcx.hir().get_parent_node(binding_id))
|
||||||
|
&& e.hir_id == hir_id =>
|
||||||
{
|
{
|
||||||
let Some(trait_def_id) = trait_ref.trait_def_id() else {
|
let Some(trait_def_id) = trait_ref.trait_def_id() else {
|
||||||
return tcx.ty_error_with_message(DUMMY_SP, "Could not find trait");
|
return tcx.ty_error_with_message(DUMMY_SP, "Could not find trait");
|
||||||
};
|
};
|
||||||
let assoc_items = tcx.associated_items(trait_def_id);
|
let assoc_items = tcx.associated_items(trait_def_id);
|
||||||
let assoc_item = assoc_items.find_by_name_and_kind(
|
let assoc_item = assoc_items.find_by_name_and_kind(
|
||||||
tcx, binding.ident, ty::AssocKind::Const, def_id.to_def_id(),
|
tcx,
|
||||||
|
binding.ident,
|
||||||
|
ty::AssocKind::Const,
|
||||||
|
def_id.to_def_id(),
|
||||||
);
|
);
|
||||||
if let Some(assoc_item) = assoc_item {
|
if let Some(assoc_item) = assoc_item {
|
||||||
tcx.type_of(assoc_item.def_id)
|
tcx.type_of(assoc_item.def_id)
|
||||||
|
@ -446,14 +461,56 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Node::TypeBinding(
|
||||||
|
binding @ &TypeBinding { hir_id: binding_id, gen_args, ref kind, .. },
|
||||||
|
) if let Node::TraitRef(trait_ref) =
|
||||||
|
tcx.hir().get(tcx.hir().get_parent_node(binding_id))
|
||||||
|
&& let Some((idx, _)) =
|
||||||
|
gen_args.args.iter().enumerate().find(|(_, arg)| {
|
||||||
|
if let GenericArg::Const(ct) = arg {
|
||||||
|
ct.value.hir_id == hir_id
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}) =>
|
||||||
|
{
|
||||||
|
let Some(trait_def_id) = trait_ref.trait_def_id() else {
|
||||||
|
return tcx.ty_error_with_message(DUMMY_SP, "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,
|
||||||
|
match kind {
|
||||||
|
// I think `<A: T>` type bindings requires that `A` is a type
|
||||||
|
TypeBindingKind::Constraint { .. }
|
||||||
|
| TypeBindingKind::Equality { term: Term::Ty(..) } => {
|
||||||
|
ty::AssocKind::Type
|
||||||
|
}
|
||||||
|
TypeBindingKind::Equality { term: Term::Const(..) } => {
|
||||||
|
ty::AssocKind::Const
|
||||||
|
}
|
||||||
|
},
|
||||||
|
def_id.to_def_id(),
|
||||||
|
);
|
||||||
|
if let Some(assoc_item) = assoc_item {
|
||||||
|
tcx.type_of(tcx.generics_of(assoc_item.def_id).params[idx].def_id)
|
||||||
|
} else {
|
||||||
|
// FIXME(associated_const_equality): add a useful error message here.
|
||||||
|
tcx.ty_error_with_message(
|
||||||
|
DUMMY_SP,
|
||||||
|
"Could not find associated const on trait",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Node::GenericParam(&GenericParam {
|
Node::GenericParam(&GenericParam {
|
||||||
hir_id: param_hir_id,
|
hir_id: param_hir_id,
|
||||||
kind: GenericParamKind::Const { default: Some(ct), .. },
|
kind: GenericParamKind::Const { default: Some(ct), .. },
|
||||||
..
|
..
|
||||||
}) if ct.hir_id == hir_id => tcx.type_of(tcx.hir().local_def_id(param_hir_id)),
|
}) if ct.hir_id == hir_id => tcx.type_of(tcx.hir().local_def_id(param_hir_id)),
|
||||||
|
|
||||||
x =>
|
x => tcx.ty_error_with_message(
|
||||||
tcx.ty_error_with_message(
|
|
||||||
DUMMY_SP,
|
DUMMY_SP,
|
||||||
&format!("unexpected const parent in type_of(): {x:?}"),
|
&format!("unexpected const parent in type_of(): {x:?}"),
|
||||||
),
|
),
|
||||||
|
|
15
src/test/ui/generic-associated-types/issue-102333.rs
Normal file
15
src/test/ui/generic-associated-types/issue-102333.rs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
// check-pass
|
||||||
|
|
||||||
|
trait A {
|
||||||
|
type T: B<U<1i32> = ()>;
|
||||||
|
}
|
||||||
|
|
||||||
|
trait B {
|
||||||
|
type U<const C: i32>;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn f<T: A>() {
|
||||||
|
let _: <<T as A>::T as B>::U<1i32> = ();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
Loading…
Add table
Add a link
Reference in a new issue