@@ -6,7 +6,7 @@ use rustc_hir::def::{DefKind, Res};
6
6
use rustc_hir:: def_id:: { DefId , LocalDefId } ;
7
7
use rustc_hir:: intravisit;
8
8
use rustc_hir:: intravisit:: Visitor ;
9
- use rustc_hir:: Node ;
9
+ use rustc_hir:: { HirId , Node } ;
10
10
use rustc_middle:: hir:: map:: Map ;
11
11
use rustc_middle:: ty:: subst:: { GenericArgKind , InternalSubsts } ;
12
12
use rustc_middle:: ty:: util:: IntTypeExt ;
@@ -22,7 +22,6 @@ use super::{bad_placeholder_type, is_suggestable_infer_ty};
22
22
/// This should be called using the query `tcx.opt_const_param_of`.
23
23
pub ( super ) fn opt_const_param_of ( tcx : TyCtxt < ' _ > , def_id : LocalDefId ) -> Option < DefId > {
24
24
use hir:: * ;
25
-
26
25
let hir_id = tcx. hir ( ) . local_def_id_to_hir_id ( def_id) ;
27
26
28
27
if let Node :: AnonConst ( _) = tcx. hir ( ) . get ( hir_id) {
@@ -62,9 +61,9 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
62
61
}
63
62
64
63
Node :: Ty ( & Ty { kind : TyKind :: Path ( _) , .. } )
65
- | Node :: Expr ( & Expr { kind : ExprKind :: Struct ( ..) , .. } )
66
- | Node :: Expr ( & Expr { kind : ExprKind :: Path ( _ ) , .. } )
67
- | Node :: TraitRef ( .. ) => {
64
+ | Node :: Expr ( & Expr { kind : ExprKind :: Path ( _ ) | ExprKind :: Struct ( ..) , .. } )
65
+ | Node :: TraitRef ( .. )
66
+ | Node :: Pat ( _ ) => {
68
67
let path = match parent_node {
69
68
Node :: Ty ( & Ty { kind : TyKind :: Path ( QPath :: Resolved ( _, path) ) , .. } )
70
69
| Node :: TraitRef ( & TraitRef { path, .. } ) => & * path,
@@ -79,6 +78,20 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
79
78
let _tables = tcx. typeck ( body_owner) ;
80
79
& * path
81
80
}
81
+ Node :: Pat ( pat) => {
82
+ if let Some ( path) = get_path_containing_arg_in_pat ( pat, hir_id) {
83
+ path
84
+ } else {
85
+ tcx. sess . delay_span_bug (
86
+ tcx. def_span ( def_id) ,
87
+ & format ! (
88
+ "unable to find const parent for {} in pat {:?}" ,
89
+ hir_id, pat
90
+ ) ,
91
+ ) ;
92
+ return None ;
93
+ }
94
+ }
82
95
_ => {
83
96
tcx. sess . delay_span_bug (
84
97
tcx. def_span ( def_id) ,
@@ -91,7 +104,6 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
91
104
// We've encountered an `AnonConst` in some path, so we need to
92
105
// figure out which generic parameter it corresponds to and return
93
106
// the relevant type.
94
-
95
107
let ( arg_index, segment) = path
96
108
. segments
97
109
. iter ( )
@@ -144,6 +156,34 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
144
156
}
145
157
}
146
158
159
+ fn get_path_containing_arg_in_pat < ' hir > (
160
+ pat : & ' hir hir:: Pat < ' hir > ,
161
+ arg_id : HirId ,
162
+ ) -> Option < & ' hir hir:: Path < ' hir > > {
163
+ use hir:: * ;
164
+
165
+ let is_arg_in_path = |p : & hir:: Path < ' _ > | {
166
+ p. segments
167
+ . iter ( )
168
+ . filter_map ( |seg| seg. args )
169
+ . flat_map ( |args| args. args )
170
+ . any ( |arg| arg. id ( ) == arg_id)
171
+ } ;
172
+ let mut arg_path = None ;
173
+ pat. walk ( |pat| match pat. kind {
174
+ PatKind :: Struct ( QPath :: Resolved ( _, path) , _, _)
175
+ | PatKind :: TupleStruct ( QPath :: Resolved ( _, path) , _, _)
176
+ | PatKind :: Path ( QPath :: Resolved ( _, path) )
177
+ if is_arg_in_path ( path) =>
178
+ {
179
+ arg_path = Some ( path) ;
180
+ false
181
+ }
182
+ _ => true ,
183
+ } ) ;
184
+ arg_path
185
+ }
186
+
147
187
pub ( super ) fn type_of ( tcx : TyCtxt < ' _ > , def_id : DefId ) -> Ty < ' _ > {
148
188
let def_id = def_id. expect_local ( ) ;
149
189
use rustc_hir:: * ;
0 commit comments