about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2022-09-26 23:57:33 +0000
committerJosh Stone <jistone@redhat.com>2022-10-06 10:07:34 -0700
commit328b53f5f09e571046a38e39be459a188d02631b (patch)
tree94a89816b02e62de4c6d833566a3b3be374bd2ae
parent99a8cc16d83c209a2886dcff049fe8382c5be0bd (diff)
downloadrust-328b53f5f09e571046a38e39be459a188d02631b.tar.gz
rust-328b53f5f09e571046a38e39be459a188d02631b.zip
Support bindings with anon consts in generics
(cherry picked from commit 92561f43f185b54c81167ddc89fbe2dcd94b4efb)
-rw-r--r--compiler/rustc_typeck/src/collect/type_of.rs47
-rw-r--r--src/test/ui/generic-associated-types/issue-102333.rs15
2 files changed, 60 insertions, 2 deletions
diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs
index 16e995b02fe..a1d1f125f78 100644
--- a/compiler/rustc_typeck/src/collect/type_of.rs
+++ b/compiler/rustc_typeck/src/collect/type_of.rs
@@ -441,8 +441,8 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
                     && e.hir_id == hir_id =>
                 {
                     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_item = assoc_items.find_by_name_and_kind(
                         tcx,
@@ -461,6 +461,49 @@ 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 {
                     hir_id: param_hir_id,
                     kind: GenericParamKind::Const { default: Some(ct), .. },
diff --git a/src/test/ui/generic-associated-types/issue-102333.rs b/src/test/ui/generic-associated-types/issue-102333.rs
new file mode 100644
index 00000000000..6c72563322f
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-102333.rs
@@ -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() {}