Skip to content

Commit cff04a7

Browse files
committed
mgca: Don't inherent generics if none referenced in const item body
1 parent 96d02e9 commit cff04a7

File tree

1 file changed

+45
-3
lines changed

1 file changed

+45
-3
lines changed

compiler/rustc_hir_analysis/src/collect/generics_of.rs

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::ops::ControlFlow;
33

44
use hir::intravisit::{self, Visitor};
55
use hir::{GenericParamKind, HirId, Node};
6-
use rustc_hir::def::DefKind;
6+
use rustc_hir::def::{DefKind, Res};
77
use rustc_hir::def_id::LocalDefId;
88
use rustc_hir::intravisit::VisitorExt;
99
use 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

Comments
 (0)