Skip to content

Commit d46c98d

Browse files
committed
Don't walk the bodies of free constants for reachability.
1 parent 296abcf commit d46c98d

File tree

3 files changed

+38
-7
lines changed

3 files changed

+38
-7
lines changed

compiler/rustc_middle/src/mir/interpret/queries.rs

+24-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
use super::{ErrorHandled, EvalToConstValueResult, EvalToValTreeResult, GlobalId};
1+
use super::{
2+
ErrorHandled, EvalToAllocationRawResult, EvalToConstValueResult, EvalToValTreeResult, GlobalId,
3+
};
24

35
use crate::mir;
46
use crate::query::TyCtxtEnsure;
@@ -12,7 +14,7 @@ use rustc_span::{Span, DUMMY_SP};
1214

1315
impl<'tcx> TyCtxt<'tcx> {
1416
/// Evaluates a constant without providing any generic parameters. This is useful to evaluate consts
15-
/// that can't take any generic arguments like statics, const items or enum discriminants. If a
17+
/// that can't take any generic arguments like const items or enum discriminants. If a
1618
/// generic parameter is used within the constant `ErrorHandled::ToGeneric` will be returned.
1719
#[instrument(skip(self), level = "debug")]
1820
pub fn const_eval_poly(self, def_id: DefId) -> EvalToConstValueResult<'tcx> {
@@ -26,6 +28,25 @@ impl<'tcx> TyCtxt<'tcx> {
2628
let param_env = self.param_env(def_id).with_reveal_all_normalized(self);
2729
self.const_eval_global_id(param_env, cid, None)
2830
}
31+
32+
/// Evaluates a constant without providing any generic parameters. This is useful to evaluate consts
33+
/// that can't take any generic arguments like const items or enum discriminants. If a
34+
/// generic parameter is used within the constant `ErrorHandled::ToGeneric` will be returned.
35+
#[instrument(skip(self), level = "debug")]
36+
pub fn const_eval_poly_to_alloc(self, def_id: DefId) -> EvalToAllocationRawResult<'tcx> {
37+
// In some situations def_id will have generic parameters within scope, but they aren't allowed
38+
// to be used. So we can't use `Instance::mono`, instead we feed unresolved generic parameters
39+
// into `const_eval` which will return `ErrorHandled::ToGeneric` if any of them are
40+
// encountered.
41+
let args = GenericArgs::identity_for_item(self, def_id);
42+
let instance = ty::Instance::new(def_id, args);
43+
let cid = GlobalId { instance, promoted: None };
44+
let param_env = self.param_env(def_id).with_reveal_all_normalized(self);
45+
let inputs = self.erase_regions(param_env.and(cid));
46+
// The query doesn't know where it is being invoked, so we need to fix the span.
47+
self.eval_to_allocation_raw(inputs)
48+
}
49+
2950
/// Resolves and evaluates a constant.
3051
///
3152
/// The constant can be located on a trait like `<A as B>::C`, in which case the given
@@ -177,7 +198,7 @@ impl<'tcx> TyCtxt<'tcx> {
177198

178199
impl<'tcx> TyCtxtEnsure<'tcx> {
179200
/// Evaluates a constant without providing any generic parameters. This is useful to evaluate consts
180-
/// that can't take any generic arguments like statics, const items or enum discriminants. If a
201+
/// that can't take any generic arguments like const items or enum discriminants. If a
181202
/// generic parameter is used within the constant `ErrorHandled::ToGeneric` will be returned.
182203
#[instrument(skip(self), level = "debug")]
183204
pub fn const_eval_poly(self, def_id: DefId) {

compiler/rustc_passes/src/reachable.rs

+13-3
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use rustc_hir::intravisit::{self, Visitor};
1414
use rustc_hir::Node;
1515
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
1616
use rustc_middle::middle::privacy::{self, Level};
17-
use rustc_middle::mir::interpret::{ConstAllocation, GlobalAlloc};
17+
use rustc_middle::mir::interpret::{ConstAllocation, ErrorHandled, GlobalAlloc};
1818
use rustc_middle::query::Providers;
1919
use rustc_middle::ty::{self, ExistentialTraitRef, TyCtxt};
2020
use rustc_privacy::DefIdVisitor;
@@ -185,8 +185,18 @@ impl<'tcx> ReachableContext<'tcx> {
185185
// Reachable constants will be inlined into other crates
186186
// unconditionally, so we need to make sure that their
187187
// contents are also reachable.
188-
hir::ItemKind::Const(_, _, init) => {
189-
self.visit_nested_body(init);
188+
hir::ItemKind::Const(..) => {
189+
match self.tcx.const_eval_poly_to_alloc(item.owner_id.def_id.into()) {
190+
Ok(alloc) => {
191+
let alloc = self.tcx.global_alloc(alloc.alloc_id).unwrap_memory();
192+
self.propagate_from_alloc(alloc);
193+
}
194+
Err(ErrorHandled::TooGeneric(span)) => span_bug!(
195+
span,
196+
"generic constants aren't implemented in reachability"
197+
),
198+
Err(ErrorHandled::Reported(..)) => {}
199+
}
190200
}
191201
hir::ItemKind::Static(..) => {
192202
if let Ok(alloc) = self.tcx.eval_static_initializer(item.owner_id.def_id) {

tests/codegen/dont_codegen_private_const_fn_only_used_in_const_eval.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,4 @@ const fn bar() {}
1313

1414
pub const BAR: () = bar();
1515

16-
// CHECK: define{{.*}}bar{{.*}}
16+
// CHECK-NOT: define{{.*}}bar{{.*}}

0 commit comments

Comments
 (0)