about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_typeck/collect.rs22
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-67844-nested-opaque.rs32
2 files changed, 53 insertions, 1 deletions
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index ea0e4719a24..a7d38725d32 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -1054,7 +1054,27 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::Generics {
             Some(tcx.closure_base_def_id(def_id))
         }
         Node::Item(item) => match item.kind {
-            ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn, .. }) => impl_trait_fn,
+            ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn, .. }) => {
+                impl_trait_fn.or_else(|| {
+                    let parent_id = tcx.hir().get_parent_item(hir_id);
+                    if parent_id != hir_id && parent_id != CRATE_HIR_ID {
+                        debug!("generics_of: parent of opaque ty {:?} is {:?}", def_id, parent_id);
+                        // If this 'impl Trait' is nested inside another 'impl Trait'
+                        // (e.g. `impl Foo<MyType = impl Bar<A>>`), we need to use the 'parent'
+                        // 'impl Trait' for its generic parameters, since we can reference them
+                        // from the 'child' 'impl Trait'
+                        if let Node::Item(hir::Item { kind: ItemKind::OpaqueTy(..), .. }) =
+                            tcx.hir().get(parent_id)
+                        {
+                            Some(tcx.hir().local_def_id(parent_id))
+                        } else {
+                            None
+                        }
+                    } else {
+                        None
+                    }
+                })
+            }
             _ => None,
         },
         _ => None,
diff --git a/src/test/ui/type-alias-impl-trait/issue-67844-nested-opaque.rs b/src/test/ui/type-alias-impl-trait/issue-67844-nested-opaque.rs
new file mode 100644
index 00000000000..2f844b4a05f
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/issue-67844-nested-opaque.rs
@@ -0,0 +1,32 @@
+// check-pass
+// Regression test for issue #67844
+// Ensures that we properly handle nested TAIT occurences
+// with generic parameters
+
+#![feature(type_alias_impl_trait)]
+
+trait WithAssoc { type AssocType; }
+
+trait WithParam<A> {}
+
+type Return<A> = impl WithAssoc<AssocType = impl WithParam<A>>;
+
+struct MyParam;
+impl<A> WithParam<A> for MyParam {}
+
+struct MyStruct;
+
+impl WithAssoc for MyStruct {
+    type AssocType = MyParam;
+}
+
+
+fn my_fun<A>() -> Return<A> {
+    MyStruct
+}
+
+fn my_other_fn<A>() -> impl WithAssoc<AssocType = impl WithParam<A>> {
+    MyStruct
+}
+
+fn main() {}