Skip to content

Commit a60669d

Browse files
committed
Properly use parent generics for opaque types
Fixes #67844 Previously, opaque types would only get parent generics if they a return-position-impl-trait (e.g. `fn foo<A>() -> impl MyTrait<A>`). However, it's possible for opaque types to be nested inside one another: ```rust trait WithAssoc { type AssocType; } trait WithParam<A> {} type Return<A> = impl WithAssoc<AssocType = impl WithParam<A>>; ``` When this occurs, we need to ensure that the nested opaque types properly inherit generic parameters from their parent opaque type. This commit fixes the `generics_of` query to take the parent item into account when determining the generics for an opaque type.
1 parent 71c7e14 commit a60669d

File tree

2 files changed

+45
-1
lines changed

2 files changed

+45
-1
lines changed

src/librustc_typeck/collect.rs

+13-1
Original file line numberDiff line numberDiff line change
@@ -1054,7 +1054,19 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::Generics {
10541054
Some(tcx.closure_base_def_id(def_id))
10551055
}
10561056
Node::Item(item) => match item.kind {
1057-
ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn, .. }) => impl_trait_fn,
1057+
ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn, .. }) => {
1058+
impl_trait_fn.or_else(|| {
1059+
let parent_id = tcx.hir().get_parent_item(hir_id);
1060+
// This opaque type might occur inside another opaque type
1061+
// (e.g. `impl Foo<MyType = impl Bar<A>>`)
1062+
if parent_id != hir_id && parent_id != CRATE_HIR_ID {
1063+
debug!("generics_of: parent of opaque ty {:?} is {:?}", def_id, parent_id);
1064+
Some(tcx.hir().local_def_id(parent_id))
1065+
} else {
1066+
None
1067+
}
1068+
})
1069+
}
10581070
_ => None,
10591071
},
10601072
_ => None,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// check-pass
2+
// Regression test for issue #67844
3+
// Ensures that we properly handle nested TAIT occurences
4+
// with generic parameters
5+
6+
#![feature(type_alias_impl_trait)]
7+
8+
trait WithAssoc { type AssocType; }
9+
10+
trait WithParam<A> {}
11+
12+
type Return<A> = impl WithAssoc<AssocType = impl WithParam<A>>;
13+
14+
struct MyParam;
15+
impl<A> WithParam<A> for MyParam {}
16+
17+
struct MyStruct;
18+
19+
impl WithAssoc for MyStruct {
20+
type AssocType = MyParam;
21+
}
22+
23+
24+
fn my_fun<A>() -> Return<A> {
25+
MyStruct
26+
}
27+
28+
fn my_other_fn<A>() -> impl WithAssoc<AssocType = impl WithParam<A>> {
29+
MyStruct
30+
}
31+
32+
fn main() {}

0 commit comments

Comments
 (0)