Skip to content

Commit d049c3e

Browse files
authored
Rollup merge of rust-lang#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 rust-lang#102333
2 parents 528956c + 92561f4 commit d049c3e

File tree

2 files changed

+102
-30
lines changed

2 files changed

+102
-30
lines changed

compiler/rustc_hir_analysis/src/collect/type_of.rs

+87-30
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,12 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
333333
find_opaque_ty_constraints_for_tait(tcx, def_id)
334334
}
335335
// Opaque types desugared from `impl Trait`.
336-
ItemKind::OpaqueTy(OpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn(owner) | hir::OpaqueTyOrigin::AsyncFn(owner), in_trait, .. }) => {
336+
ItemKind::OpaqueTy(OpaqueTy {
337+
origin:
338+
hir::OpaqueTyOrigin::FnReturn(owner) | hir::OpaqueTyOrigin::AsyncFn(owner),
339+
in_trait,
340+
..
341+
}) => {
337342
if in_trait {
338343
span_bug!(item.span, "impl-trait in trait has no default")
339344
} else {
@@ -378,7 +383,9 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
378383

379384
Node::Field(field) => icx.to_ty(field.ty),
380385

381-
Node::Expr(&Expr { kind: ExprKind::Closure{..}, .. }) => tcx.typeck(def_id).node_type(hir_id),
386+
Node::Expr(&Expr { kind: ExprKind::Closure { .. }, .. }) => {
387+
tcx.typeck(def_id).node_type(hir_id)
388+
}
382389

383390
Node::AnonConst(_) if let Some(param) = tcx.opt_const_param_of(def_id) => {
384391
// We defer to `type_of` of the corresponding parameter
@@ -410,40 +417,91 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
410417
| Node::Item(&Item { kind: ItemKind::GlobalAsm(asm), .. })
411418
if asm.operands.iter().any(|(op, _op_sp)| match op {
412419
hir::InlineAsmOperand::Const { anon_const }
413-
| hir::InlineAsmOperand::SymFn { anon_const } => anon_const.hir_id == hir_id,
420+
| hir::InlineAsmOperand::SymFn { anon_const } => {
421+
anon_const.hir_id == hir_id
422+
}
414423
_ => false,
415424
}) =>
416425
{
417426
tcx.typeck(def_id).node_type(hir_id)
418427
}
419428

420-
Node::Variant(Variant { disr_expr: Some(ref e), .. }) if e.hir_id == hir_id => tcx
421-
.adt_def(tcx.hir().get_parent_item(hir_id))
422-
.repr()
423-
.discr_type()
424-
.to_ty(tcx),
429+
Node::Variant(Variant { disr_expr: Some(ref e), .. }) if e.hir_id == hir_id => {
430+
tcx.adt_def(tcx.hir().get_parent_item(hir_id)).repr().discr_type().to_ty(tcx)
431+
}
425432

426-
Node::TypeBinding(binding @ &TypeBinding { hir_id: binding_id, .. })
427-
if let Node::TraitRef(trait_ref) = tcx.hir().get(
428-
tcx.hir().get_parent_node(binding_id)
429-
) =>
433+
Node::TypeBinding(
434+
binding @ &TypeBinding {
435+
hir_id: binding_id,
436+
kind: TypeBindingKind::Equality { term: Term::Const(ref e) },
437+
..
438+
},
439+
) if let Node::TraitRef(trait_ref) =
440+
tcx.hir().get(tcx.hir().get_parent_node(binding_id))
441+
&& e.hir_id == hir_id =>
430442
{
431-
let Some(trait_def_id) = trait_ref.trait_def_id() else {
432-
return tcx.ty_error_with_message(DUMMY_SP, "Could not find trait");
433-
};
434-
let assoc_items = tcx.associated_items(trait_def_id);
435-
let assoc_item = assoc_items.find_by_name_and_kind(
436-
tcx, binding.ident, ty::AssocKind::Const, def_id.to_def_id(),
437-
);
438-
if let Some(assoc_item) = assoc_item {
439-
tcx.type_of(assoc_item.def_id)
440-
} else {
441-
// FIXME(associated_const_equality): add a useful error message here.
442-
tcx.ty_error_with_message(
443-
DUMMY_SP,
444-
"Could not find associated const on trait",
445-
)
446-
}
443+
let Some(trait_def_id) = trait_ref.trait_def_id() else {
444+
return tcx.ty_error_with_message(DUMMY_SP, "Could not find trait");
445+
};
446+
let assoc_items = tcx.associated_items(trait_def_id);
447+
let assoc_item = assoc_items.find_by_name_and_kind(
448+
tcx,
449+
binding.ident,
450+
ty::AssocKind::Const,
451+
def_id.to_def_id(),
452+
);
453+
if let Some(assoc_item) = assoc_item {
454+
tcx.type_of(assoc_item.def_id)
455+
} else {
456+
// FIXME(associated_const_equality): add a useful error message here.
457+
tcx.ty_error_with_message(
458+
DUMMY_SP,
459+
"Could not find associated const on trait",
460+
)
461+
}
462+
}
463+
464+
Node::TypeBinding(
465+
binding @ &TypeBinding { hir_id: binding_id, gen_args, ref kind, .. },
466+
) if let Node::TraitRef(trait_ref) =
467+
tcx.hir().get(tcx.hir().get_parent_node(binding_id))
468+
&& let Some((idx, _)) =
469+
gen_args.args.iter().enumerate().find(|(_, arg)| {
470+
if let GenericArg::Const(ct) = arg {
471+
ct.value.hir_id == hir_id
472+
} else {
473+
false
474+
}
475+
}) =>
476+
{
477+
let Some(trait_def_id) = trait_ref.trait_def_id() else {
478+
return tcx.ty_error_with_message(DUMMY_SP, "Could not find trait");
479+
};
480+
let assoc_items = tcx.associated_items(trait_def_id);
481+
let assoc_item = assoc_items.find_by_name_and_kind(
482+
tcx,
483+
binding.ident,
484+
match kind {
485+
// I think `<A: T>` type bindings requires that `A` is a type
486+
TypeBindingKind::Constraint { .. }
487+
| TypeBindingKind::Equality { term: Term::Ty(..) } => {
488+
ty::AssocKind::Type
489+
}
490+
TypeBindingKind::Equality { term: Term::Const(..) } => {
491+
ty::AssocKind::Const
492+
}
493+
},
494+
def_id.to_def_id(),
495+
);
496+
if let Some(assoc_item) = assoc_item {
497+
tcx.type_of(tcx.generics_of(assoc_item.def_id).params[idx].def_id)
498+
} else {
499+
// FIXME(associated_const_equality): add a useful error message here.
500+
tcx.ty_error_with_message(
501+
DUMMY_SP,
502+
"Could not find associated const on trait",
503+
)
504+
}
447505
}
448506

449507
Node::GenericParam(&GenericParam {
@@ -452,8 +510,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
452510
..
453511
}) if ct.hir_id == hir_id => tcx.type_of(tcx.hir().local_def_id(param_hir_id)),
454512

455-
x =>
456-
tcx.ty_error_with_message(
513+
x => tcx.ty_error_with_message(
457514
DUMMY_SP,
458515
&format!("unexpected const parent in type_of(): {x:?}"),
459516
),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// check-pass
2+
3+
trait A {
4+
type T: B<U<1i32> = ()>;
5+
}
6+
7+
trait B {
8+
type U<const C: i32>;
9+
}
10+
11+
fn f<T: A>() {
12+
let _: <<T as A>::T as B>::U<1i32> = ();
13+
}
14+
15+
fn main() {}

0 commit comments

Comments
 (0)