@@ -3,7 +3,7 @@ use std::ops::ControlFlow;
33
44use hir:: intravisit:: { self , Visitor } ;
55use hir:: { GenericParamKind , HirId , Node } ;
6- use rustc_hir:: def:: DefKind ;
6+ use rustc_hir:: def:: { DefKind , Res } ;
77use rustc_hir:: def_id:: LocalDefId ;
88use rustc_hir:: intravisit:: VisitorExt ;
99use rustc_hir:: { self as hir, AmbigArg } ;
@@ -192,8 +192,29 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
192192 }
193193 }
194194 }
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 { .. } , .. } ) => {
197218 Some ( tcx. typeck_root_def_id ( def_id. to_def_id ( ) ) )
198219 }
199220 Node :: OpaqueTy ( & hir:: OpaqueTy {
@@ -545,3 +566,24 @@ impl<'v> Visitor<'v> for AnonConstInParamTyDetector {
545566 intravisit:: walk_anon_const ( self , c)
546567 }
547568}
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