@@ -29,6 +29,73 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
29
29
let parent_node = tcx. hir ( ) . get ( parent_node_id) ;
30
30
31
31
match parent_node {
32
+ // This match arm is for when the def_id appears in a GAT whose
33
+ // path can't be resolved without typechecking e.g.
34
+ //
35
+ // trait Foo {
36
+ // type Assoc<const N: usize>;
37
+ // fn foo() -> Self::Assoc<3>;
38
+ // }
39
+ //
40
+ // In the above code we would call this query with the def_id of 3 and
41
+ // the parent_node we match on would be the hir node for Self::Assoc<3>
42
+ //
43
+ // `Self::Assoc<3>` cant be resolved without typchecking here as we
44
+ // didnt write <Self as Foo>::Assoc<3>. If we did then another match
45
+ // arm would handle this.
46
+ //
47
+ // I believe this match arm is only needed for GAT but I am not 100% sure - BoxyUwU
48
+ Node :: Ty ( hir_ty @ Ty { kind : TyKind :: Path ( QPath :: TypeRelative ( _, segment) ) , .. } ) => {
49
+ // Find the Item containing the associated type so we can create an ItemCtxt.
50
+ // Using the ItemCtxt convert the HIR for the unresolved assoc type into a
51
+ // ty which is a fully resolved projection.
52
+ // For the code example above, this would mean converting Self::Assoc<3>
53
+ // into a ty::Projection(<Self as Foo>::Assoc<3>)
54
+ let item_hir_id = tcx
55
+ . hir ( )
56
+ . parent_iter ( hir_id)
57
+ . filter ( |( _, node) | matches ! ( node, Node :: Item ( _) ) )
58
+ . map ( |( id, _) | id)
59
+ . next ( )
60
+ . unwrap ( ) ;
61
+ let item_did = tcx. hir ( ) . local_def_id ( item_hir_id) . to_def_id ( ) ;
62
+ let item_ctxt = & ItemCtxt :: new ( tcx, item_did) as & dyn crate :: astconv:: AstConv < ' _ > ;
63
+ let ty = item_ctxt. ast_ty_to_ty ( hir_ty) ;
64
+
65
+ // Iterate through the generics of the projection to find the one that corresponds to
66
+ // the def_id that this query was called with. We filter to only const args here as a
67
+ // precaution for if it's ever allowed to elide lifetimes in GAT's. It currently isn't
68
+ // but it can't hurt to be safe ^^
69
+ if let ty:: Projection ( projection) = ty. kind ( ) {
70
+ let generics = tcx. generics_of ( projection. item_def_id ) ;
71
+
72
+ let arg_index = segment
73
+ . args
74
+ . and_then ( |args| {
75
+ args. args
76
+ . iter ( )
77
+ . filter ( |arg| arg. is_const ( ) )
78
+ . position ( |arg| arg. id ( ) == hir_id)
79
+ } )
80
+ . unwrap_or_else ( || {
81
+ bug ! ( "no arg matching AnonConst in segment" ) ;
82
+ } ) ;
83
+
84
+ return generics
85
+ . params
86
+ . iter ( )
87
+ . filter ( |param| matches ! ( param. kind, ty:: GenericParamDefKind :: Const ) )
88
+ . nth ( arg_index)
89
+ . map ( |param| param. def_id ) ;
90
+ }
91
+
92
+ // I dont think it's possible to reach this but I'm not 100% sure - BoxyUwU
93
+ tcx. sess . delay_span_bug (
94
+ tcx. def_span ( def_id) ,
95
+ "unexpected non-GAT usage of an anon const" ,
96
+ ) ;
97
+ return None ;
98
+ }
32
99
Node :: Expr ( & Expr {
33
100
kind :
34
101
ExprKind :: MethodCall ( segment, ..) | ExprKind :: Path ( QPath :: TypeRelative ( _, segment) ) ,
0 commit comments