mirror of
https://github.com/rust-lang/rust
synced 2024-09-30 22:04:36 +00:00
Auto merge of #122505 - oli-obk:visit_nested_body2, r=tmiasko
Don't walk the bodies of free constants for reachability. follow-up to #122371 cc #119214 This avoids codegening items (e.g. functions) that are only used during const eval, but do not reach their final constant value (e.g. via function pointers). r? `@tmiasko`
This commit is contained in:
commit
d0ccb5413e
|
@ -1,4 +1,6 @@
|
|||
use super::{ErrorHandled, EvalToConstValueResult, EvalToValTreeResult, GlobalId};
|
||||
use super::{
|
||||
ErrorHandled, EvalToAllocationRawResult, EvalToConstValueResult, EvalToValTreeResult, GlobalId,
|
||||
};
|
||||
|
||||
use crate::mir;
|
||||
use crate::query::TyCtxtEnsure;
|
||||
|
@ -13,7 +15,7 @@
|
|||
|
||||
impl<'tcx> TyCtxt<'tcx> {
|
||||
/// Evaluates a constant without providing any generic parameters. This is useful to evaluate consts
|
||||
/// that can't take any generic arguments like statics, const items or enum discriminants. If a
|
||||
/// that can't take any generic arguments like const items or enum discriminants. If a
|
||||
/// generic parameter is used within the constant `ErrorHandled::ToGeneric` will be returned.
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
pub fn const_eval_poly(self, def_id: DefId) -> EvalToConstValueResult<'tcx> {
|
||||
|
@ -27,6 +29,24 @@ pub fn const_eval_poly(self, def_id: DefId) -> EvalToConstValueResult<'tcx> {
|
|||
let param_env = self.param_env(def_id).with_reveal_all_normalized(self);
|
||||
self.const_eval_global_id(param_env, cid, DUMMY_SP)
|
||||
}
|
||||
|
||||
/// Evaluates a constant without providing any generic parameters. This is useful to evaluate consts
|
||||
/// that can't take any generic arguments like const items or enum discriminants. If a
|
||||
/// generic parameter is used within the constant `ErrorHandled::ToGeneric` will be returned.
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
pub fn const_eval_poly_to_alloc(self, def_id: DefId) -> EvalToAllocationRawResult<'tcx> {
|
||||
// In some situations def_id will have generic parameters within scope, but they aren't allowed
|
||||
// to be used. So we can't use `Instance::mono`, instead we feed unresolved generic parameters
|
||||
// into `const_eval` which will return `ErrorHandled::ToGeneric` if any of them are
|
||||
// encountered.
|
||||
let args = GenericArgs::identity_for_item(self, def_id);
|
||||
let instance = ty::Instance::new(def_id, args);
|
||||
let cid = GlobalId { instance, promoted: None };
|
||||
let param_env = self.param_env(def_id).with_reveal_all_normalized(self);
|
||||
let inputs = self.erase_regions(param_env.and(cid));
|
||||
self.eval_to_allocation_raw(inputs)
|
||||
}
|
||||
|
||||
/// Resolves and evaluates a constant.
|
||||
///
|
||||
/// The constant can be located on a trait like `<A as B>::C`, in which case the given
|
||||
|
@ -177,7 +197,7 @@ pub fn const_eval_global_id_for_typeck(
|
|||
|
||||
impl<'tcx> TyCtxtEnsure<'tcx> {
|
||||
/// Evaluates a constant without providing any generic parameters. This is useful to evaluate consts
|
||||
/// that can't take any generic arguments like statics, const items or enum discriminants. If a
|
||||
/// that can't take any generic arguments like const items or enum discriminants. If a
|
||||
/// generic parameter is used within the constant `ErrorHandled::ToGeneric` will be returned.
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
pub fn const_eval_poly(self, def_id: DefId) {
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
use rustc_middle::bug;
|
||||
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
|
||||
use rustc_middle::middle::privacy::{self, Level};
|
||||
use rustc_middle::mir::interpret::{ConstAllocation, GlobalAlloc};
|
||||
use rustc_middle::mir::interpret::{ConstAllocation, ErrorHandled, GlobalAlloc};
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::{self, ExistentialTraitRef, TyCtxt};
|
||||
use rustc_privacy::DefIdVisitor;
|
||||
|
@ -206,11 +206,21 @@ fn propagate_node(&mut self, node: &Node<'tcx>, search_item: LocalDefId) {
|
|||
}
|
||||
}
|
||||
|
||||
// Reachable constants will be inlined into other crates
|
||||
// unconditionally, so we need to make sure that their
|
||||
// contents are also reachable.
|
||||
hir::ItemKind::Const(_, _, init) => {
|
||||
self.visit_nested_body(init);
|
||||
// Only things actually ending up in the final constant need to be reachable.
|
||||
// Everything else is either already available as `mir_for_ctfe`, or can't be used
|
||||
// by codegen anyway.
|
||||
match self.tcx.const_eval_poly_to_alloc(item.owner_id.def_id.into()) {
|
||||
Ok(alloc) => {
|
||||
let alloc = self.tcx.global_alloc(alloc.alloc_id).unwrap_memory();
|
||||
self.propagate_from_alloc(alloc);
|
||||
}
|
||||
// Reachable generic constants will be inlined into other crates
|
||||
// unconditionally, so we need to make sure that their
|
||||
// contents are also reachable.
|
||||
Err(ErrorHandled::TooGeneric(_)) => self.visit_nested_body(init),
|
||||
Err(ErrorHandled::Reported(..)) => {}
|
||||
}
|
||||
}
|
||||
hir::ItemKind::Static(..) => {
|
||||
if let Ok(alloc) = self.tcx.eval_static_initializer(item.owner_id.def_id) {
|
||||
|
|
|
@ -3,8 +3,25 @@
|
|||
|
||||
//@compile-flags: --crate-type=lib -Copt-level=0
|
||||
|
||||
#![feature(generic_const_items)]
|
||||
|
||||
const fn foo() {}
|
||||
|
||||
pub static FOO: () = foo();
|
||||
|
||||
// CHECK-NOT: define{{.*}}foo{{.*}}
|
||||
|
||||
const fn bar() {}
|
||||
|
||||
pub const BAR: () = bar();
|
||||
|
||||
// CHECK-NOT: define{{.*}}bar{{.*}}
|
||||
|
||||
const fn baz() {}
|
||||
|
||||
#[rustfmt::skip]
|
||||
pub const BAZ<const C: bool>: () = if C {
|
||||
baz()
|
||||
};
|
||||
|
||||
// CHECK: define{{.*}}baz{{.*}}
|
||||
|
|
Loading…
Reference in a new issue