@@ -3,7 +3,7 @@ use std::ops::ControlFlow;
3
3
4
4
use hir:: intravisit:: { self , Visitor } ;
5
5
use hir:: { GenericParamKind , HirId , Node } ;
6
- use rustc_hir:: def:: DefKind ;
6
+ use rustc_hir:: def:: { DefKind , Res } ;
7
7
use rustc_hir:: def_id:: LocalDefId ;
8
8
use rustc_hir:: intravisit:: VisitorExt ;
9
9
use rustc_hir:: { self as hir, AmbigArg } ;
@@ -192,8 +192,29 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
192
192
}
193
193
}
194
194
}
195
- Node :: ConstBlock ( _)
196
- | Node :: Expr ( & hir:: Expr { kind : hir:: ExprKind :: Closure { .. } , .. } ) => {
195
+ Node :: ConstBlock ( ConstBlock { body, .. } ) => {
196
+ let is_const_item = |node| {
197
+ matches ! (
198
+ node,
199
+ Node :: Item ( Item { kind: hir:: ItemKind :: Const ( ..) , .. } )
200
+ | Node :: TraitItem ( TraitItem { kind: hir:: TraitItemKind :: Const ( ..) , .. } )
201
+ | Node :: ImplItem ( ImplItem { kind: hir:: ImplItemKind :: Const ( ..) , .. } )
202
+ )
203
+ } ;
204
+ // HACK(mgca): we lower non-path const item bodies as const blocks
205
+ // so we can control use of generics independently from the const item's type etc
206
+ if tcx. features ( ) . min_generic_const_args ( )
207
+ && is_const_item ( tcx. parent_hir_node ( hir_id) )
208
+ && !does_body_reference_generics ( tcx, * body)
209
+ {
210
+ // If the body doesn't reference any generic params, we don't inherit from the parent.
211
+ // This allows us to know later that it's monomorphic.
212
+ None
213
+ } else {
214
+ Some ( tcx. typeck_root_def_id ( def_id. to_def_id ( ) ) )
215
+ }
216
+ }
217
+ Node :: Expr ( & hir:: Expr { kind : hir:: ExprKind :: Closure { .. } , .. } ) => {
197
218
Some ( tcx. typeck_root_def_id ( def_id. to_def_id ( ) ) )
198
219
}
199
220
Node :: OpaqueTy ( & hir:: OpaqueTy {
@@ -545,3 +566,24 @@ impl<'v> Visitor<'v> for AnonConstInParamTyDetector {
545
566
intravisit:: walk_anon_const ( self , c)
546
567
}
547
568
}
569
+
570
+ fn does_body_reference_generics < ' tcx > ( tcx : TyCtxt < ' tcx > , body : hir:: BodyId ) -> bool {
571
+ ReferenceToGenericsDetector { } . visit_body ( tcx. hir_body ( body) ) . is_break ( )
572
+ }
573
+
574
+ struct ReferenceToGenericsDetector { }
575
+
576
+ impl < ' v > Visitor < ' v > for ReferenceToGenericsDetector {
577
+ type Result = ControlFlow < ( ) > ;
578
+
579
+ fn visit_path ( & mut self , path : & hir:: Path < ' v > , _id : HirId ) -> Self :: Result {
580
+ // FIXME(mgca): should lifetimes disqualify or not? leave a comment about it if ignored
581
+ if let Res :: Def ( DefKind :: TyParam | DefKind :: ConstParam | DefKind :: LifetimeParam , _) =
582
+ path. res
583
+ {
584
+ return ControlFlow :: Break ( ( ) ) ;
585
+ }
586
+
587
+ intravisit:: walk_path ( self , path)
588
+ }
589
+ }
0 commit comments