diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 2a450f4b4e8b1..242faebe53ec8 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>`), 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 0000000000000..2f844b4a05f5f --- /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 {} + +type Return = impl WithAssoc>; + +struct MyParam; +impl WithParam for MyParam {} + +struct MyStruct; + +impl WithAssoc for MyStruct { + type AssocType = MyParam; +} + + +fn my_fun() -> Return { + MyStruct +} + +fn my_other_fn() -> impl WithAssoc> { + MyStruct +} + +fn main() {}