@@ -6,7 +6,7 @@ use rustc_hir::def::{DefKind, Res};
66use rustc_hir:: def_id:: { DefId , LocalDefId } ;
77use rustc_hir:: intravisit;
88use rustc_hir:: intravisit:: Visitor ;
9- use rustc_hir:: Node ;
9+ use rustc_hir:: { HirId , Node } ;
1010use rustc_middle:: hir:: map:: Map ;
1111use rustc_middle:: ty:: subst:: { GenericArgKind , InternalSubsts } ;
1212use rustc_middle:: ty:: util:: IntTypeExt ;
@@ -22,7 +22,6 @@ use super::{bad_placeholder_type, is_suggestable_infer_ty};
2222/// This should be called using the query `tcx.opt_const_param_of`.
2323pub ( super ) fn opt_const_param_of ( tcx : TyCtxt < ' _ > , def_id : LocalDefId ) -> Option < DefId > {
2424 use hir:: * ;
25-
2625 let hir_id = tcx. hir ( ) . local_def_id_to_hir_id ( def_id) ;
2726
2827 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<
6261 }
6362
6463 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 ( _ ) => {
6867 let path = match parent_node {
6968 Node :: Ty ( & Ty { kind : TyKind :: Path ( QPath :: Resolved ( _, path) ) , .. } )
7069 | Node :: TraitRef ( & TraitRef { path, .. } ) => & * path,
@@ -79,6 +78,20 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
7978 let _tables = tcx. typeck ( body_owner) ;
8079 & * path
8180 }
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+ }
8295 _ => {
8396 tcx. sess . delay_span_bug (
8497 tcx. def_span ( def_id) ,
@@ -91,7 +104,6 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
91104 // We've encountered an `AnonConst` in some path, so we need to
92105 // figure out which generic parameter it corresponds to and return
93106 // the relevant type.
94-
95107 let ( arg_index, segment) = path
96108 . segments
97109 . iter ( )
@@ -144,6 +156,34 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
144156 }
145157}
146158
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+
147187pub ( super ) fn type_of ( tcx : TyCtxt < ' _ > , def_id : DefId ) -> Ty < ' _ > {
148188 let def_id = def_id. expect_local ( ) ;
149189 use rustc_hir:: * ;
0 commit comments