Auto merge of #121644 - oli-obk:unique_static_innards2, r=RalfJung,nnethercote
Ensure nested allocations in statics neither get deduplicated nor duplicated This PR generates new `DefId`s for nested allocations in static items and feeds all the right queries to make the compiler believe these are regular `static` items. I chose this design, because all other designs are fragile and make the compiler horribly complex for such a niche use case. At present this wrecks incremental compilation performance *in case nested allocations exist* (because any query creating a `DefId` will be recomputed and never loaded from the cache). This will be resolved later in https://github.com/rust-lang/rust/pull/115613 . All other statics are unaffected by this change and will not have performance regressions (heh, famous last words) This PR contains various smaller refactorings that can be pulled out into separate PRs. It is best reviewed commit-by-commit. The last commit is where the actual magic happens. r? `@RalfJung` on the const interner and engine changes fixes https://github.com/rust-lang/rust/issues/79738
This commit is contained in:
commit
3b85d2c7fc
66 changed files with 461 additions and 170 deletions
|
@ -196,7 +196,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
.get_partial_res(sym.id)
|
.get_partial_res(sym.id)
|
||||||
.and_then(|res| res.full_res())
|
.and_then(|res| res.full_res())
|
||||||
.and_then(|res| match res {
|
.and_then(|res| match res {
|
||||||
Res::Def(DefKind::Static(_), def_id) => Some(def_id),
|
Res::Def(DefKind::Static { .. }, def_id) => Some(def_id),
|
||||||
_ => None,
|
_ => None,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -63,7 +63,7 @@ impl<'gcc, 'tcx> StaticMethods for CodegenCx<'gcc, 'tcx> {
|
||||||
global_value
|
global_value
|
||||||
}
|
}
|
||||||
|
|
||||||
fn codegen_static(&self, def_id: DefId, is_mutable: bool) {
|
fn codegen_static(&self, def_id: DefId) {
|
||||||
let attrs = self.tcx.codegen_fn_attrs(def_id);
|
let attrs = self.tcx.codegen_fn_attrs(def_id);
|
||||||
|
|
||||||
let value = match codegen_static_initializer(&self, def_id) {
|
let value = match codegen_static_initializer(&self, def_id) {
|
||||||
|
@ -92,7 +92,7 @@ impl<'gcc, 'tcx> StaticMethods for CodegenCx<'gcc, 'tcx> {
|
||||||
|
|
||||||
// As an optimization, all shared statics which do not have interior
|
// As an optimization, all shared statics which do not have interior
|
||||||
// mutability are placed into read-only memory.
|
// mutability are placed into read-only memory.
|
||||||
if !is_mutable && self.type_is_freeze(ty) {
|
if !self.tcx.static_mutability(def_id).unwrap().is_mut() && self.type_is_freeze(ty) {
|
||||||
#[cfg(feature = "master")]
|
#[cfg(feature = "master")]
|
||||||
global.global_set_readonly();
|
global.global_set_readonly();
|
||||||
}
|
}
|
||||||
|
@ -349,7 +349,7 @@ pub fn const_alloc_to_gcc<'gcc, 'tcx>(
|
||||||
cx.const_struct(&llvals, true)
|
cx.const_struct(&llvals, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn codegen_static_initializer<'gcc, 'tcx>(
|
fn codegen_static_initializer<'gcc, 'tcx>(
|
||||||
cx: &CodegenCx<'gcc, 'tcx>,
|
cx: &CodegenCx<'gcc, 'tcx>,
|
||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
) -> Result<(RValue<'gcc>, ConstAllocation<'tcx>), ErrorHandled> {
|
) -> Result<(RValue<'gcc>, ConstAllocation<'tcx>), ErrorHandled> {
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
#[cfg(feature = "master")]
|
#[cfg(feature = "master")]
|
||||||
use gccjit::{FnAttribute, VarAttribute};
|
use gccjit::{FnAttribute, VarAttribute};
|
||||||
use rustc_codegen_ssa::traits::PreDefineMethods;
|
use rustc_codegen_ssa::traits::PreDefineMethods;
|
||||||
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
|
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
|
||||||
|
use rustc_middle::bug;
|
||||||
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
||||||
use rustc_middle::mir::mono::{Linkage, Visibility};
|
use rustc_middle::mir::mono::{Linkage, Visibility};
|
||||||
use rustc_middle::ty::layout::{FnAbiOf, LayoutOf};
|
use rustc_middle::ty::layout::{FnAbiOf, LayoutOf};
|
||||||
|
@ -23,7 +25,14 @@ impl<'gcc, 'tcx> PreDefineMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
||||||
) {
|
) {
|
||||||
let attrs = self.tcx.codegen_fn_attrs(def_id);
|
let attrs = self.tcx.codegen_fn_attrs(def_id);
|
||||||
let instance = Instance::mono(self.tcx, def_id);
|
let instance = Instance::mono(self.tcx, def_id);
|
||||||
let ty = instance.ty(self.tcx, ty::ParamEnv::reveal_all());
|
let DefKind::Static { nested, .. } = self.tcx.def_kind(def_id) else { bug!() };
|
||||||
|
// Nested statics do not have a type, so pick a dummy type and let `codegen_static` figure out
|
||||||
|
// the gcc type from the actual evaluated initializer.
|
||||||
|
let ty = if nested {
|
||||||
|
self.tcx.types.unit
|
||||||
|
} else {
|
||||||
|
instance.ty(self.tcx, ty::ParamEnv::reveal_all())
|
||||||
|
};
|
||||||
let gcc_type = self.layout_of(ty).gcc_type(self);
|
let gcc_type = self.layout_of(ty).gcc_type(self);
|
||||||
|
|
||||||
let is_tls = attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL);
|
let is_tls = attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL);
|
||||||
|
|
|
@ -9,6 +9,7 @@ use crate::type_::Type;
|
||||||
use crate::type_of::LayoutLlvmExt;
|
use crate::type_of::LayoutLlvmExt;
|
||||||
use crate::value::Value;
|
use crate::value::Value;
|
||||||
use rustc_codegen_ssa::traits::*;
|
use rustc_codegen_ssa::traits::*;
|
||||||
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
|
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
|
||||||
use rustc_middle::mir::interpret::{
|
use rustc_middle::mir::interpret::{
|
||||||
|
@ -17,7 +18,7 @@ use rustc_middle::mir::interpret::{
|
||||||
};
|
};
|
||||||
use rustc_middle::mir::mono::MonoItem;
|
use rustc_middle::mir::mono::MonoItem;
|
||||||
use rustc_middle::ty::layout::LayoutOf;
|
use rustc_middle::ty::layout::LayoutOf;
|
||||||
use rustc_middle::ty::{self, Instance, Ty};
|
use rustc_middle::ty::{self, Instance};
|
||||||
use rustc_middle::{bug, span_bug};
|
use rustc_middle::{bug, span_bug};
|
||||||
use rustc_session::config::Lto;
|
use rustc_session::config::Lto;
|
||||||
use rustc_target::abi::{
|
use rustc_target::abi::{
|
||||||
|
@ -114,7 +115,7 @@ pub fn const_alloc_to_llvm<'ll>(cx: &CodegenCx<'ll, '_>, alloc: ConstAllocation<
|
||||||
cx.const_struct(&llvals, true)
|
cx.const_struct(&llvals, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn codegen_static_initializer<'ll, 'tcx>(
|
fn codegen_static_initializer<'ll, 'tcx>(
|
||||||
cx: &CodegenCx<'ll, 'tcx>,
|
cx: &CodegenCx<'ll, 'tcx>,
|
||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
) -> Result<(&'ll Value, ConstAllocation<'tcx>), ErrorHandled> {
|
) -> Result<(&'ll Value, ConstAllocation<'tcx>), ErrorHandled> {
|
||||||
|
@ -147,11 +148,10 @@ fn set_global_alignment<'ll>(cx: &CodegenCx<'ll, '_>, gv: &'ll Value, mut align:
|
||||||
fn check_and_apply_linkage<'ll, 'tcx>(
|
fn check_and_apply_linkage<'ll, 'tcx>(
|
||||||
cx: &CodegenCx<'ll, 'tcx>,
|
cx: &CodegenCx<'ll, 'tcx>,
|
||||||
attrs: &CodegenFnAttrs,
|
attrs: &CodegenFnAttrs,
|
||||||
ty: Ty<'tcx>,
|
llty: &'ll Type,
|
||||||
sym: &str,
|
sym: &str,
|
||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
) -> &'ll Value {
|
) -> &'ll Value {
|
||||||
let llty = cx.layout_of(ty).llvm_type(cx);
|
|
||||||
if let Some(linkage) = attrs.import_linkage {
|
if let Some(linkage) = attrs.import_linkage {
|
||||||
debug!("get_static: sym={} linkage={:?}", sym, linkage);
|
debug!("get_static: sym={} linkage={:?}", sym, linkage);
|
||||||
|
|
||||||
|
@ -226,9 +226,28 @@ impl<'ll> CodegenCx<'ll, '_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(level = "debug", skip(self))]
|
||||||
pub(crate) fn get_static(&self, def_id: DefId) -> &'ll Value {
|
pub(crate) fn get_static(&self, def_id: DefId) -> &'ll Value {
|
||||||
let instance = Instance::mono(self.tcx, def_id);
|
let instance = Instance::mono(self.tcx, def_id);
|
||||||
if let Some(&g) = self.instances.borrow().get(&instance) {
|
trace!(?instance);
|
||||||
|
|
||||||
|
let DefKind::Static { nested, .. } = self.tcx.def_kind(def_id) else { bug!() };
|
||||||
|
// Nested statics do not have a type, so pick a dummy type and let `codegen_static` figure out
|
||||||
|
// the llvm type from the actual evaluated initializer.
|
||||||
|
let llty = if nested {
|
||||||
|
self.type_i8()
|
||||||
|
} else {
|
||||||
|
let ty = instance.ty(self.tcx, ty::ParamEnv::reveal_all());
|
||||||
|
trace!(?ty);
|
||||||
|
self.layout_of(ty).llvm_type(self)
|
||||||
|
};
|
||||||
|
self.get_static_inner(def_id, llty)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[instrument(level = "debug", skip(self, llty))]
|
||||||
|
pub(crate) fn get_static_inner(&self, def_id: DefId, llty: &'ll Type) -> &'ll Value {
|
||||||
|
if let Some(&g) = self.instances.borrow().get(&Instance::mono(self.tcx, def_id)) {
|
||||||
|
trace!("used cached value");
|
||||||
return g;
|
return g;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -240,14 +259,12 @@ impl<'ll> CodegenCx<'ll, '_> {
|
||||||
statics defined in the same CGU, but did not for `{def_id:?}`"
|
statics defined in the same CGU, but did not for `{def_id:?}`"
|
||||||
);
|
);
|
||||||
|
|
||||||
let ty = instance.ty(self.tcx, ty::ParamEnv::reveal_all());
|
let sym = self.tcx.symbol_name(Instance::mono(self.tcx, def_id)).name;
|
||||||
let sym = self.tcx.symbol_name(instance).name;
|
|
||||||
let fn_attrs = self.tcx.codegen_fn_attrs(def_id);
|
let fn_attrs = self.tcx.codegen_fn_attrs(def_id);
|
||||||
|
|
||||||
debug!("get_static: sym={} instance={:?} fn_attrs={:?}", sym, instance, fn_attrs);
|
debug!(?sym, ?fn_attrs);
|
||||||
|
|
||||||
let g = if def_id.is_local() && !self.tcx.is_foreign_item(def_id) {
|
let g = if def_id.is_local() && !self.tcx.is_foreign_item(def_id) {
|
||||||
let llty = self.layout_of(ty).llvm_type(self);
|
|
||||||
if let Some(g) = self.get_declared_value(sym) {
|
if let Some(g) = self.get_declared_value(sym) {
|
||||||
if self.val_ty(g) != self.type_ptr() {
|
if self.val_ty(g) != self.type_ptr() {
|
||||||
span_bug!(self.tcx.def_span(def_id), "Conflicting types for static");
|
span_bug!(self.tcx.def_span(def_id), "Conflicting types for static");
|
||||||
|
@ -264,7 +281,7 @@ impl<'ll> CodegenCx<'ll, '_> {
|
||||||
|
|
||||||
g
|
g
|
||||||
} else {
|
} else {
|
||||||
check_and_apply_linkage(self, fn_attrs, ty, sym, def_id)
|
check_and_apply_linkage(self, fn_attrs, llty, sym, def_id)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Thread-local statics in some other crate need to *always* be linked
|
// Thread-local statics in some other crate need to *always* be linked
|
||||||
|
@ -332,34 +349,18 @@ impl<'ll> CodegenCx<'ll, '_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.instances.borrow_mut().insert(instance, g);
|
self.instances.borrow_mut().insert(Instance::mono(self.tcx, def_id), g);
|
||||||
g
|
g
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl<'ll> StaticMethods for CodegenCx<'ll, '_> {
|
fn codegen_static_item(&self, def_id: DefId) {
|
||||||
fn static_addr_of(&self, cv: &'ll Value, align: Align, kind: Option<&str>) -> &'ll Value {
|
|
||||||
if let Some(&gv) = self.const_globals.borrow().get(&cv) {
|
|
||||||
unsafe {
|
|
||||||
// Upgrade the alignment in cases where the same constant is used with different
|
|
||||||
// alignment requirements
|
|
||||||
let llalign = align.bytes() as u32;
|
|
||||||
if llalign > llvm::LLVMGetAlignment(gv) {
|
|
||||||
llvm::LLVMSetAlignment(gv, llalign);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return gv;
|
|
||||||
}
|
|
||||||
let gv = self.static_addr_of_mut(cv, align, kind);
|
|
||||||
unsafe {
|
|
||||||
llvm::LLVMSetGlobalConstant(gv, True);
|
|
||||||
}
|
|
||||||
self.const_globals.borrow_mut().insert(cv, gv);
|
|
||||||
gv
|
|
||||||
}
|
|
||||||
|
|
||||||
fn codegen_static(&self, def_id: DefId, is_mutable: bool) {
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
assert!(
|
||||||
|
llvm::LLVMGetInitializer(
|
||||||
|
self.instances.borrow().get(&Instance::mono(self.tcx, def_id)).unwrap()
|
||||||
|
)
|
||||||
|
.is_none()
|
||||||
|
);
|
||||||
let attrs = self.tcx.codegen_fn_attrs(def_id);
|
let attrs = self.tcx.codegen_fn_attrs(def_id);
|
||||||
|
|
||||||
let Ok((v, alloc)) = codegen_static_initializer(self, def_id) else {
|
let Ok((v, alloc)) = codegen_static_initializer(self, def_id) else {
|
||||||
|
@ -368,13 +369,11 @@ impl<'ll> StaticMethods for CodegenCx<'ll, '_> {
|
||||||
};
|
};
|
||||||
let alloc = alloc.inner();
|
let alloc = alloc.inner();
|
||||||
|
|
||||||
let g = self.get_static(def_id);
|
|
||||||
|
|
||||||
let val_llty = self.val_ty(v);
|
let val_llty = self.val_ty(v);
|
||||||
|
|
||||||
let instance = Instance::mono(self.tcx, def_id);
|
let g = self.get_static_inner(def_id, val_llty);
|
||||||
let ty = instance.ty(self.tcx, ty::ParamEnv::reveal_all());
|
let llty = self.val_ty(g);
|
||||||
let llty = self.layout_of(ty).llvm_type(self);
|
|
||||||
let g = if val_llty == llty {
|
let g = if val_llty == llty {
|
||||||
g
|
g
|
||||||
} else {
|
} else {
|
||||||
|
@ -409,16 +408,15 @@ impl<'ll> StaticMethods for CodegenCx<'ll, '_> {
|
||||||
self.statics_to_rauw.borrow_mut().push((g, new_g));
|
self.statics_to_rauw.borrow_mut().push((g, new_g));
|
||||||
new_g
|
new_g
|
||||||
};
|
};
|
||||||
set_global_alignment(self, g, self.align_of(ty));
|
set_global_alignment(self, g, alloc.align);
|
||||||
llvm::LLVMSetInitializer(g, v);
|
llvm::LLVMSetInitializer(g, v);
|
||||||
|
|
||||||
if self.should_assume_dso_local(g, true) {
|
if self.should_assume_dso_local(g, true) {
|
||||||
llvm::LLVMRustSetDSOLocal(g, true);
|
llvm::LLVMRustSetDSOLocal(g, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// As an optimization, all shared statics which do not have interior
|
// Forward the allocation's mutability (picked by the const interner) to LLVM.
|
||||||
// mutability are placed into read-only memory.
|
if alloc.mutability.is_not() {
|
||||||
if !is_mutable && self.type_is_freeze(ty) {
|
|
||||||
llvm::LLVMSetGlobalConstant(g, llvm::True);
|
llvm::LLVMSetGlobalConstant(g, llvm::True);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -541,6 +539,32 @@ impl<'ll> StaticMethods for CodegenCx<'ll, '_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'ll> StaticMethods for CodegenCx<'ll, '_> {
|
||||||
|
fn static_addr_of(&self, cv: &'ll Value, align: Align, kind: Option<&str>) -> &'ll Value {
|
||||||
|
if let Some(&gv) = self.const_globals.borrow().get(&cv) {
|
||||||
|
unsafe {
|
||||||
|
// Upgrade the alignment in cases where the same constant is used with different
|
||||||
|
// alignment requirements
|
||||||
|
let llalign = align.bytes() as u32;
|
||||||
|
if llalign > llvm::LLVMGetAlignment(gv) {
|
||||||
|
llvm::LLVMSetAlignment(gv, llalign);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return gv;
|
||||||
|
}
|
||||||
|
let gv = self.static_addr_of_mut(cv, align, kind);
|
||||||
|
unsafe {
|
||||||
|
llvm::LLVMSetGlobalConstant(gv, True);
|
||||||
|
}
|
||||||
|
self.const_globals.borrow_mut().insert(cv, gv);
|
||||||
|
gv
|
||||||
|
}
|
||||||
|
|
||||||
|
fn codegen_static(&self, def_id: DefId) {
|
||||||
|
self.codegen_static_item(def_id)
|
||||||
|
}
|
||||||
|
|
||||||
/// Add a global value to a list to be stored in the `llvm.used` variable, an array of ptr.
|
/// Add a global value to a list to be stored in the `llvm.used` variable, an array of ptr.
|
||||||
fn add_used_global(&self, global: &'ll Value) {
|
fn add_used_global(&self, global: &'ll Value) {
|
||||||
|
|
|
@ -26,6 +26,7 @@ use rustc_codegen_ssa::debuginfo::type_names::VTableNameKind;
|
||||||
use rustc_codegen_ssa::traits::*;
|
use rustc_codegen_ssa::traits::*;
|
||||||
use rustc_fs_util::path_to_c_string;
|
use rustc_fs_util::path_to_c_string;
|
||||||
use rustc_hir::def::CtorKind;
|
use rustc_hir::def::CtorKind;
|
||||||
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
|
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
|
||||||
use rustc_middle::bug;
|
use rustc_middle::bug;
|
||||||
use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
|
use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
|
||||||
|
@ -1309,6 +1310,11 @@ pub fn build_global_var_di_node<'ll>(cx: &CodegenCx<'ll, '_>, def_id: DefId, glo
|
||||||
};
|
};
|
||||||
|
|
||||||
let is_local_to_unit = is_node_local_to_unit(cx, def_id);
|
let is_local_to_unit = is_node_local_to_unit(cx, def_id);
|
||||||
|
|
||||||
|
let DefKind::Static { nested, .. } = cx.tcx.def_kind(def_id) else { bug!() };
|
||||||
|
if nested {
|
||||||
|
return;
|
||||||
|
}
|
||||||
let variable_type = Instance::mono(cx.tcx, def_id).ty(cx.tcx, ty::ParamEnv::reveal_all());
|
let variable_type = Instance::mono(cx.tcx, def_id).ty(cx.tcx, ty::ParamEnv::reveal_all());
|
||||||
let type_di_node = type_di_node(cx, variable_type);
|
let type_di_node = type_di_node(cx, variable_type);
|
||||||
let var_name = tcx.item_name(def_id);
|
let var_name = tcx.item_name(def_id);
|
||||||
|
|
|
@ -5,7 +5,9 @@ use crate::errors::SymbolAlreadyDefined;
|
||||||
use crate::llvm;
|
use crate::llvm;
|
||||||
use crate::type_of::LayoutLlvmExt;
|
use crate::type_of::LayoutLlvmExt;
|
||||||
use rustc_codegen_ssa::traits::*;
|
use rustc_codegen_ssa::traits::*;
|
||||||
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
|
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
|
||||||
|
use rustc_middle::bug;
|
||||||
use rustc_middle::mir::mono::{Linkage, Visibility};
|
use rustc_middle::mir::mono::{Linkage, Visibility};
|
||||||
use rustc_middle::ty::layout::{FnAbiOf, LayoutOf};
|
use rustc_middle::ty::layout::{FnAbiOf, LayoutOf};
|
||||||
use rustc_middle::ty::{self, Instance, TypeVisitableExt};
|
use rustc_middle::ty::{self, Instance, TypeVisitableExt};
|
||||||
|
@ -21,7 +23,14 @@ impl<'tcx> PreDefineMethods<'tcx> for CodegenCx<'_, 'tcx> {
|
||||||
symbol_name: &str,
|
symbol_name: &str,
|
||||||
) {
|
) {
|
||||||
let instance = Instance::mono(self.tcx, def_id);
|
let instance = Instance::mono(self.tcx, def_id);
|
||||||
let ty = instance.ty(self.tcx, ty::ParamEnv::reveal_all());
|
let DefKind::Static { nested, .. } = self.tcx.def_kind(def_id) else { bug!() };
|
||||||
|
// Nested statics do not have a type, so pick a dummy type and let `codegen_static` figure out
|
||||||
|
// the llvm type from the actual evaluated initializer.
|
||||||
|
let ty = if nested {
|
||||||
|
self.tcx.types.unit
|
||||||
|
} else {
|
||||||
|
instance.ty(self.tcx, ty::ParamEnv::reveal_all())
|
||||||
|
};
|
||||||
let llty = self.layout_of(ty).llvm_type(self);
|
let llty = self.layout_of(ty).llvm_type(self);
|
||||||
|
|
||||||
let g = self.define_global(symbol_name, llty).unwrap_or_else(|| {
|
let g = self.define_global(symbol_name, llty).unwrap_or_else(|| {
|
||||||
|
|
|
@ -87,7 +87,7 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> DefIdMap<S
|
||||||
|
|
||||||
// Only consider nodes that actually have exported symbols.
|
// Only consider nodes that actually have exported symbols.
|
||||||
match tcx.def_kind(def_id) {
|
match tcx.def_kind(def_id) {
|
||||||
DefKind::Fn | DefKind::Static(_) => {}
|
DefKind::Fn | DefKind::Static { .. } => {}
|
||||||
DefKind::AssocFn if tcx.impl_of_method(def_id.to_def_id()).is_some() => {}
|
DefKind::AssocFn if tcx.impl_of_method(def_id.to_def_id()).is_some() => {}
|
||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
|
@ -483,7 +483,7 @@ fn symbol_export_level(tcx: TyCtxt<'_>, sym_def_id: DefId) -> SymbolExportLevel
|
||||||
let target = &tcx.sess.target.llvm_target;
|
let target = &tcx.sess.target.llvm_target;
|
||||||
// WebAssembly cannot export data symbols, so reduce their export level
|
// WebAssembly cannot export data symbols, so reduce their export level
|
||||||
if target.contains("emscripten") {
|
if target.contains("emscripten") {
|
||||||
if let DefKind::Static(_) = tcx.def_kind(sym_def_id) {
|
if let DefKind::Static { .. } = tcx.def_kind(sym_def_id) {
|
||||||
return SymbolExportLevel::Rust;
|
return SymbolExportLevel::Rust;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ impl<'a, 'tcx: 'a> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> {
|
||||||
|
|
||||||
match *self {
|
match *self {
|
||||||
MonoItem::Static(def_id) => {
|
MonoItem::Static(def_id) => {
|
||||||
cx.codegen_static(def_id, cx.tcx().is_mutable_static(def_id));
|
cx.codegen_static(def_id);
|
||||||
}
|
}
|
||||||
MonoItem::GlobalAsm(item_id) => {
|
MonoItem::GlobalAsm(item_id) => {
|
||||||
let item = cx.tcx().hir().item(item_id);
|
let item = cx.tcx().hir().item(item_id);
|
||||||
|
|
|
@ -4,7 +4,7 @@ use rustc_target::abi::Align;
|
||||||
|
|
||||||
pub trait StaticMethods: BackendTypes {
|
pub trait StaticMethods: BackendTypes {
|
||||||
fn static_addr_of(&self, cv: Self::Value, align: Align, kind: Option<&str>) -> Self::Value;
|
fn static_addr_of(&self, cv: Self::Value, align: Align, kind: Option<&str>) -> Self::Value;
|
||||||
fn codegen_static(&self, def_id: DefId, is_mutable: bool);
|
fn codegen_static(&self, def_id: DefId);
|
||||||
|
|
||||||
/// Mark the given global value as "used", to prevent the compiler and linker from potentially
|
/// Mark the given global value as "used", to prevent the compiler and linker from potentially
|
||||||
/// removing a static variable that may otherwise appear unused.
|
/// removing a static variable that may otherwise appear unused.
|
||||||
|
|
|
@ -37,7 +37,7 @@ fn eval_body_using_ecx<'mir, 'tcx>(
|
||||||
|| matches!(
|
|| matches!(
|
||||||
ecx.tcx.def_kind(cid.instance.def_id()),
|
ecx.tcx.def_kind(cid.instance.def_id()),
|
||||||
DefKind::Const
|
DefKind::Const
|
||||||
| DefKind::Static(_)
|
| DefKind::Static { .. }
|
||||||
| DefKind::ConstParam
|
| DefKind::ConstParam
|
||||||
| DefKind::AnonConst
|
| DefKind::AnonConst
|
||||||
| DefKind::InlineConst
|
| DefKind::InlineConst
|
||||||
|
@ -59,7 +59,7 @@ fn eval_body_using_ecx<'mir, 'tcx>(
|
||||||
};
|
};
|
||||||
|
|
||||||
let ret = if let InternKind::Static(_) = intern_kind {
|
let ret = if let InternKind::Static(_) = intern_kind {
|
||||||
create_static_alloc(ecx, cid.instance.def_id(), layout)?
|
create_static_alloc(ecx, cid.instance.def_id().expect_local(), layout)?
|
||||||
} else {
|
} else {
|
||||||
ecx.allocate(layout, MemoryKind::Stack)?
|
ecx.allocate(layout, MemoryKind::Stack)?
|
||||||
};
|
};
|
||||||
|
@ -380,7 +380,11 @@ pub fn eval_in_interpreter<'mir, 'tcx>(
|
||||||
}
|
}
|
||||||
Ok(mplace) => {
|
Ok(mplace) => {
|
||||||
// Since evaluation had no errors, validate the resulting constant.
|
// Since evaluation had no errors, validate the resulting constant.
|
||||||
|
|
||||||
|
// Temporarily allow access to the static_root_ids for the purpose of validation.
|
||||||
|
let static_root_ids = ecx.machine.static_root_ids.take();
|
||||||
let res = const_validate_mplace(&ecx, &mplace, cid);
|
let res = const_validate_mplace(&ecx, &mplace, cid);
|
||||||
|
ecx.machine.static_root_ids = static_root_ids;
|
||||||
|
|
||||||
let alloc_id = mplace.ptr().provenance.unwrap().alloc_id();
|
let alloc_id = mplace.ptr().provenance.unwrap().alloc_id();
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ use rustc_data_structures::fx::FxIndexMap;
|
||||||
use rustc_data_structures::fx::IndexEntry;
|
use rustc_data_structures::fx::IndexEntry;
|
||||||
use rustc_hir::def::DefKind;
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
|
use rustc_hir::def_id::LocalDefId;
|
||||||
use rustc_hir::LangItem;
|
use rustc_hir::LangItem;
|
||||||
use rustc_middle::mir;
|
use rustc_middle::mir;
|
||||||
use rustc_middle::mir::AssertMessage;
|
use rustc_middle::mir::AssertMessage;
|
||||||
|
@ -59,8 +60,10 @@ pub struct CompileTimeInterpreter<'mir, 'tcx> {
|
||||||
/// Whether to check alignment during evaluation.
|
/// Whether to check alignment during evaluation.
|
||||||
pub(super) check_alignment: CheckAlignment,
|
pub(super) check_alignment: CheckAlignment,
|
||||||
|
|
||||||
/// Used to prevent reads from a static's base allocation, as that may allow for self-initialization.
|
/// If `Some`, we are evaluating the initializer of the static with the given `LocalDefId`,
|
||||||
pub(crate) static_root_alloc_id: Option<AllocId>,
|
/// storing the result in the given `AllocId`.
|
||||||
|
/// Used to prevent reads from a static's base allocation, as that may allow for self-initialization loops.
|
||||||
|
pub(crate) static_root_ids: Option<(AllocId, LocalDefId)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
|
@ -94,7 +97,7 @@ impl<'mir, 'tcx> CompileTimeInterpreter<'mir, 'tcx> {
|
||||||
stack: Vec::new(),
|
stack: Vec::new(),
|
||||||
can_access_mut_global,
|
can_access_mut_global,
|
||||||
check_alignment,
|
check_alignment,
|
||||||
static_root_alloc_id: None,
|
static_root_ids: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -749,7 +752,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
|
||||||
ecx: &InterpCx<'mir, 'tcx, Self>,
|
ecx: &InterpCx<'mir, 'tcx, Self>,
|
||||||
alloc_id: AllocId,
|
alloc_id: AllocId,
|
||||||
) -> InterpResult<'tcx> {
|
) -> InterpResult<'tcx> {
|
||||||
if Some(alloc_id) == ecx.machine.static_root_alloc_id {
|
if Some(alloc_id) == ecx.machine.static_root_ids.map(|(id, _)| id) {
|
||||||
Err(ConstEvalErrKind::RecursiveStatic.into())
|
Err(ConstEvalErrKind::RecursiveStatic.into())
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -13,12 +13,16 @@
|
||||||
//! but that would require relying on type information, and given how many ways Rust has to lie
|
//! but that would require relying on type information, and given how many ways Rust has to lie
|
||||||
//! about type information, we want to avoid doing that.
|
//! about type information, we want to avoid doing that.
|
||||||
|
|
||||||
|
use hir::def::DefKind;
|
||||||
use rustc_ast::Mutability;
|
use rustc_ast::Mutability;
|
||||||
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
|
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
|
||||||
use rustc_errors::ErrorGuaranteed;
|
use rustc_errors::ErrorGuaranteed;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_middle::mir::interpret::{CtfeProvenance, InterpResult};
|
use rustc_middle::mir::interpret::{ConstAllocation, CtfeProvenance, InterpResult};
|
||||||
|
use rustc_middle::query::TyCtxtAt;
|
||||||
use rustc_middle::ty::layout::TyAndLayout;
|
use rustc_middle::ty::layout::TyAndLayout;
|
||||||
|
use rustc_span::def_id::LocalDefId;
|
||||||
|
use rustc_span::sym;
|
||||||
|
|
||||||
use super::{AllocId, Allocation, InterpCx, MPlaceTy, Machine, MemoryKind, PlaceTy};
|
use super::{AllocId, Allocation, InterpCx, MPlaceTy, Machine, MemoryKind, PlaceTy};
|
||||||
use crate::const_eval;
|
use crate::const_eval;
|
||||||
|
@ -33,7 +37,19 @@ pub trait CompileTimeMachine<'mir, 'tcx: 'mir, T> = Machine<
|
||||||
FrameExtra = (),
|
FrameExtra = (),
|
||||||
AllocExtra = (),
|
AllocExtra = (),
|
||||||
MemoryMap = FxIndexMap<AllocId, (MemoryKind<T>, Allocation)>,
|
MemoryMap = FxIndexMap<AllocId, (MemoryKind<T>, Allocation)>,
|
||||||
>;
|
> + HasStaticRootDefId;
|
||||||
|
|
||||||
|
pub trait HasStaticRootDefId {
|
||||||
|
/// Returns the `DefId` of the static item that is currently being evaluated.
|
||||||
|
/// Used for interning to be able to handle nested allocations.
|
||||||
|
fn static_def_id(&self) -> Option<LocalDefId>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl HasStaticRootDefId for const_eval::CompileTimeInterpreter<'_, '_> {
|
||||||
|
fn static_def_id(&self) -> Option<LocalDefId> {
|
||||||
|
Some(self.static_root_ids?.1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Intern an allocation. Returns `Err` if the allocation does not exist in the local memory.
|
/// Intern an allocation. Returns `Err` if the allocation does not exist in the local memory.
|
||||||
///
|
///
|
||||||
|
@ -67,10 +83,35 @@ fn intern_shallow<'rt, 'mir, 'tcx, T, M: CompileTimeMachine<'mir, 'tcx, T>>(
|
||||||
}
|
}
|
||||||
// link the alloc id to the actual allocation
|
// link the alloc id to the actual allocation
|
||||||
let alloc = ecx.tcx.mk_const_alloc(alloc);
|
let alloc = ecx.tcx.mk_const_alloc(alloc);
|
||||||
|
if let Some(static_id) = ecx.machine.static_def_id() {
|
||||||
|
intern_as_new_static(ecx.tcx, static_id, alloc_id, alloc);
|
||||||
|
} else {
|
||||||
ecx.tcx.set_alloc_id_memory(alloc_id, alloc);
|
ecx.tcx.set_alloc_id_memory(alloc_id, alloc);
|
||||||
|
}
|
||||||
Ok(alloc.0.0.provenance().ptrs().iter().map(|&(_, prov)| prov))
|
Ok(alloc.0.0.provenance().ptrs().iter().map(|&(_, prov)| prov))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates a new `DefId` and feeds all the right queries to make this `DefId`
|
||||||
|
/// appear as if it were a user-written `static` (though it has no HIR).
|
||||||
|
fn intern_as_new_static<'tcx>(
|
||||||
|
tcx: TyCtxtAt<'tcx>,
|
||||||
|
static_id: LocalDefId,
|
||||||
|
alloc_id: AllocId,
|
||||||
|
alloc: ConstAllocation<'tcx>,
|
||||||
|
) {
|
||||||
|
let feed = tcx.create_def(
|
||||||
|
static_id,
|
||||||
|
sym::nested,
|
||||||
|
DefKind::Static { mutability: alloc.0.mutability, nested: true },
|
||||||
|
);
|
||||||
|
tcx.set_nested_alloc_id_static(alloc_id, feed.def_id());
|
||||||
|
feed.codegen_fn_attrs(tcx.codegen_fn_attrs(static_id).clone());
|
||||||
|
feed.eval_static_initializer(Ok(alloc));
|
||||||
|
feed.generics_of(tcx.generics_of(static_id).clone());
|
||||||
|
feed.def_ident_span(tcx.def_ident_span(static_id));
|
||||||
|
feed.explicit_predicates_of(tcx.explicit_predicates_of(static_id));
|
||||||
|
}
|
||||||
|
|
||||||
/// How a constant value should be interned.
|
/// How a constant value should be interned.
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Hash, Eq)]
|
#[derive(Copy, Clone, Debug, PartialEq, Hash, Eq)]
|
||||||
pub enum InternKind {
|
pub enum InternKind {
|
||||||
|
|
|
@ -15,6 +15,7 @@ use std::ptr;
|
||||||
|
|
||||||
use rustc_ast::Mutability;
|
use rustc_ast::Mutability;
|
||||||
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
|
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
|
||||||
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_middle::mir::display_allocation;
|
use rustc_middle::mir::display_allocation;
|
||||||
use rustc_middle::ty::{self, Instance, ParamEnv, Ty, TyCtxt};
|
use rustc_middle::ty::{self, Instance, ParamEnv, Ty, TyCtxt};
|
||||||
use rustc_target::abi::{Align, HasDataLayout, Size};
|
use rustc_target::abi::{Align, HasDataLayout, Size};
|
||||||
|
@ -761,11 +762,26 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
// be held throughout the match.
|
// be held throughout the match.
|
||||||
match self.tcx.try_get_global_alloc(id) {
|
match self.tcx.try_get_global_alloc(id) {
|
||||||
Some(GlobalAlloc::Static(def_id)) => {
|
Some(GlobalAlloc::Static(def_id)) => {
|
||||||
assert!(self.tcx.is_static(def_id));
|
|
||||||
// Thread-local statics do not have a constant address. They *must* be accessed via
|
// Thread-local statics do not have a constant address. They *must* be accessed via
|
||||||
// `ThreadLocalRef`; we can never have a pointer to them as a regular constant value.
|
// `ThreadLocalRef`; we can never have a pointer to them as a regular constant value.
|
||||||
assert!(!self.tcx.is_thread_local_static(def_id));
|
assert!(!self.tcx.is_thread_local_static(def_id));
|
||||||
// Use size and align of the type.
|
|
||||||
|
let DefKind::Static { nested, .. } = self.tcx.def_kind(def_id) else {
|
||||||
|
bug!("GlobalAlloc::Static is not a static")
|
||||||
|
};
|
||||||
|
|
||||||
|
let (size, align) = if nested {
|
||||||
|
// Nested anonymous statics are untyped, so let's get their
|
||||||
|
// size and alignment from the allocaiton itself. This always
|
||||||
|
// succeeds, as the query is fed at DefId creation time, so no
|
||||||
|
// evaluation actually occurs.
|
||||||
|
let alloc = self.tcx.eval_static_initializer(def_id).unwrap();
|
||||||
|
(alloc.0.size(), alloc.0.align)
|
||||||
|
} else {
|
||||||
|
// Use size and align of the type for everything else. We need
|
||||||
|
// to do that to
|
||||||
|
// * avoid cycle errors in case of self-referential statics,
|
||||||
|
// * be able to get information on extern statics.
|
||||||
let ty = self
|
let ty = self
|
||||||
.tcx
|
.tcx
|
||||||
.type_of(def_id)
|
.type_of(def_id)
|
||||||
|
@ -773,7 +789,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
.expect("statics should not have generic parameters");
|
.expect("statics should not have generic parameters");
|
||||||
let layout = self.tcx.layout_of(ParamEnv::empty().and(ty)).unwrap();
|
let layout = self.tcx.layout_of(ParamEnv::empty().and(ty)).unwrap();
|
||||||
assert!(layout.is_sized());
|
assert!(layout.is_sized());
|
||||||
(layout.size, layout.align.abi, AllocKind::LiveData)
|
(layout.size, layout.align.abi)
|
||||||
|
};
|
||||||
|
(size, align, AllocKind::LiveData)
|
||||||
}
|
}
|
||||||
Some(GlobalAlloc::Memory(alloc)) => {
|
Some(GlobalAlloc::Memory(alloc)) => {
|
||||||
// Need to duplicate the logic here, because the global allocations have
|
// Need to duplicate the logic here, because the global allocations have
|
||||||
|
|
|
@ -22,7 +22,7 @@ pub use rustc_middle::mir::interpret::*; // have all the `interpret` symbols in
|
||||||
|
|
||||||
pub use self::eval_context::{format_interp_error, Frame, FrameInfo, InterpCx, StackPopCleanup};
|
pub use self::eval_context::{format_interp_error, Frame, FrameInfo, InterpCx, StackPopCleanup};
|
||||||
pub use self::intern::{
|
pub use self::intern::{
|
||||||
intern_const_alloc_for_constprop, intern_const_alloc_recursive, InternKind,
|
intern_const_alloc_for_constprop, intern_const_alloc_recursive, HasStaticRootDefId, InternKind,
|
||||||
};
|
};
|
||||||
pub use self::machine::{compile_time_machine, AllocMap, Machine, MayLeak, StackPopJump};
|
pub use self::machine::{compile_time_machine, AllocMap, Machine, MayLeak, StackPopJump};
|
||||||
pub use self::memory::{AllocKind, AllocRef, AllocRefMut, FnVal, Memory, MemoryKind};
|
pub use self::memory::{AllocKind, AllocRef, AllocRefMut, FnVal, Memory, MemoryKind};
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
use crate::const_eval::CompileTimeEvalContext;
|
use crate::const_eval::CompileTimeEvalContext;
|
||||||
use crate::interpret::{MemPlaceMeta, MemoryKind};
|
use crate::interpret::{MemPlaceMeta, MemoryKind};
|
||||||
|
use rustc_hir::def_id::LocalDefId;
|
||||||
use rustc_middle::mir::interpret::{AllocId, Allocation, InterpResult, Pointer};
|
use rustc_middle::mir::interpret::{AllocId, Allocation, InterpResult, Pointer};
|
||||||
use rustc_middle::ty::layout::TyAndLayout;
|
use rustc_middle::ty::layout::TyAndLayout;
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
|
self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
|
||||||
};
|
};
|
||||||
use rustc_span::def_id::DefId;
|
|
||||||
use std::ops::ControlFlow;
|
use std::ops::ControlFlow;
|
||||||
|
|
||||||
use super::MPlaceTy;
|
use super::MPlaceTy;
|
||||||
|
@ -89,13 +89,13 @@ pub(crate) fn take_static_root_alloc<'mir, 'tcx: 'mir>(
|
||||||
|
|
||||||
pub(crate) fn create_static_alloc<'mir, 'tcx: 'mir>(
|
pub(crate) fn create_static_alloc<'mir, 'tcx: 'mir>(
|
||||||
ecx: &mut CompileTimeEvalContext<'mir, 'tcx>,
|
ecx: &mut CompileTimeEvalContext<'mir, 'tcx>,
|
||||||
static_def_id: DefId,
|
static_def_id: LocalDefId,
|
||||||
layout: TyAndLayout<'tcx>,
|
layout: TyAndLayout<'tcx>,
|
||||||
) -> InterpResult<'tcx, MPlaceTy<'tcx>> {
|
) -> InterpResult<'tcx, MPlaceTy<'tcx>> {
|
||||||
let alloc = Allocation::try_uninit(layout.size, layout.align.abi)?;
|
let alloc = Allocation::try_uninit(layout.size, layout.align.abi)?;
|
||||||
let alloc_id = ecx.tcx.reserve_and_set_static_alloc(static_def_id);
|
let alloc_id = ecx.tcx.reserve_and_set_static_alloc(static_def_id.into());
|
||||||
assert_eq!(ecx.machine.static_root_alloc_id, None);
|
assert_eq!(ecx.machine.static_root_ids, None);
|
||||||
ecx.machine.static_root_alloc_id = Some(alloc_id);
|
ecx.machine.static_root_ids = Some((alloc_id, static_def_id));
|
||||||
assert!(ecx.memory.alloc_map.insert(alloc_id, (MemoryKind::Stack, alloc)).is_none());
|
assert!(ecx.memory.alloc_map.insert(alloc_id, (MemoryKind::Stack, alloc)).is_none());
|
||||||
Ok(ecx.ptr_with_meta_to_mplace(Pointer::from(alloc_id).into(), MemPlaceMeta::None, layout))
|
Ok(ecx.ptr_with_meta_to_mplace(Pointer::from(alloc_id).into(), MemPlaceMeta::None, layout))
|
||||||
}
|
}
|
||||||
|
|
|
@ -457,15 +457,6 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
|
||||||
// Special handling for pointers to statics (irrespective of their type).
|
// Special handling for pointers to statics (irrespective of their type).
|
||||||
assert!(!self.ecx.tcx.is_thread_local_static(did));
|
assert!(!self.ecx.tcx.is_thread_local_static(did));
|
||||||
assert!(self.ecx.tcx.is_static(did));
|
assert!(self.ecx.tcx.is_static(did));
|
||||||
let is_mut =
|
|
||||||
matches!(self.ecx.tcx.def_kind(did), DefKind::Static(Mutability::Mut))
|
|
||||||
|| !self
|
|
||||||
.ecx
|
|
||||||
.tcx
|
|
||||||
.type_of(did)
|
|
||||||
.no_bound_vars()
|
|
||||||
.expect("statics should not have generic parameters")
|
|
||||||
.is_freeze(*self.ecx.tcx, ty::ParamEnv::reveal_all());
|
|
||||||
// Mode-specific checks
|
// Mode-specific checks
|
||||||
match self.ctfe_mode {
|
match self.ctfe_mode {
|
||||||
Some(
|
Some(
|
||||||
|
@ -490,8 +481,28 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
|
||||||
}
|
}
|
||||||
None => {}
|
None => {}
|
||||||
}
|
}
|
||||||
// Return alloc mutability
|
// Return alloc mutability. For "root" statics we look at the type to account for interior
|
||||||
if is_mut { Mutability::Mut } else { Mutability::Not }
|
// mutability; for nested statics we have no type and directly use the annotated mutability.
|
||||||
|
let DefKind::Static { mutability, nested } = self.ecx.tcx.def_kind(did)
|
||||||
|
else {
|
||||||
|
bug!()
|
||||||
|
};
|
||||||
|
match (mutability, nested) {
|
||||||
|
(Mutability::Mut, _) => Mutability::Mut,
|
||||||
|
(Mutability::Not, true) => Mutability::Not,
|
||||||
|
(Mutability::Not, false)
|
||||||
|
if !self
|
||||||
|
.ecx
|
||||||
|
.tcx
|
||||||
|
.type_of(did)
|
||||||
|
.no_bound_vars()
|
||||||
|
.expect("statics should not have generic parameters")
|
||||||
|
.is_freeze(*self.ecx.tcx, ty::ParamEnv::reveal_all()) =>
|
||||||
|
{
|
||||||
|
Mutability::Mut
|
||||||
|
}
|
||||||
|
(Mutability::Not, false) => Mutability::Not,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
GlobalAlloc::Memory(alloc) => alloc.inner().mutability,
|
GlobalAlloc::Memory(alloc) => alloc.inner().mutability,
|
||||||
GlobalAlloc::Function(..) | GlobalAlloc::VTable(..) => {
|
GlobalAlloc::Function(..) | GlobalAlloc::VTable(..) => {
|
||||||
|
|
|
@ -75,7 +75,12 @@ pub enum DefKind {
|
||||||
Const,
|
Const,
|
||||||
/// Constant generic parameter: `struct Foo<const N: usize> { ... }`
|
/// Constant generic parameter: `struct Foo<const N: usize> { ... }`
|
||||||
ConstParam,
|
ConstParam,
|
||||||
Static(ast::Mutability),
|
Static {
|
||||||
|
/// Whether it's a `static mut` or just a `static`.
|
||||||
|
mutability: ast::Mutability,
|
||||||
|
/// Whether it's an anonymous static generated for nested allocations.
|
||||||
|
nested: bool,
|
||||||
|
},
|
||||||
/// Refers to the struct or enum variant's constructor.
|
/// Refers to the struct or enum variant's constructor.
|
||||||
///
|
///
|
||||||
/// The reason `Ctor` exists in addition to [`DefKind::Struct`] and
|
/// The reason `Ctor` exists in addition to [`DefKind::Struct`] and
|
||||||
|
@ -136,7 +141,7 @@ impl DefKind {
|
||||||
DefKind::Fn => "function",
|
DefKind::Fn => "function",
|
||||||
DefKind::Mod if def_id.is_crate_root() && !def_id.is_local() => "crate",
|
DefKind::Mod if def_id.is_crate_root() && !def_id.is_local() => "crate",
|
||||||
DefKind::Mod => "module",
|
DefKind::Mod => "module",
|
||||||
DefKind::Static(..) => "static",
|
DefKind::Static { .. } => "static",
|
||||||
DefKind::Enum => "enum",
|
DefKind::Enum => "enum",
|
||||||
DefKind::Variant => "variant",
|
DefKind::Variant => "variant",
|
||||||
DefKind::Ctor(CtorOf::Variant, CtorKind::Fn) => "tuple variant",
|
DefKind::Ctor(CtorOf::Variant, CtorKind::Fn) => "tuple variant",
|
||||||
|
@ -209,7 +214,7 @@ impl DefKind {
|
||||||
DefKind::Fn
|
DefKind::Fn
|
||||||
| DefKind::Const
|
| DefKind::Const
|
||||||
| DefKind::ConstParam
|
| DefKind::ConstParam
|
||||||
| DefKind::Static(..)
|
| DefKind::Static { .. }
|
||||||
| DefKind::Ctor(..)
|
| DefKind::Ctor(..)
|
||||||
| DefKind::AssocFn
|
| DefKind::AssocFn
|
||||||
| DefKind::AssocConst => Some(Namespace::ValueNS),
|
| DefKind::AssocConst => Some(Namespace::ValueNS),
|
||||||
|
@ -245,10 +250,13 @@ impl DefKind {
|
||||||
| DefKind::AssocTy
|
| DefKind::AssocTy
|
||||||
| DefKind::TyParam
|
| DefKind::TyParam
|
||||||
| DefKind::ExternCrate => DefPathData::TypeNs(name),
|
| DefKind::ExternCrate => DefPathData::TypeNs(name),
|
||||||
|
// It's not exactly an anon const, but wrt DefPathData, there
|
||||||
|
// is no difference.
|
||||||
|
DefKind::Static { nested: true, .. } => DefPathData::AnonConst,
|
||||||
DefKind::Fn
|
DefKind::Fn
|
||||||
| DefKind::Const
|
| DefKind::Const
|
||||||
| DefKind::ConstParam
|
| DefKind::ConstParam
|
||||||
| DefKind::Static(..)
|
| DefKind::Static { .. }
|
||||||
| DefKind::AssocFn
|
| DefKind::AssocFn
|
||||||
| DefKind::AssocConst
|
| DefKind::AssocConst
|
||||||
| DefKind::Field => DefPathData::ValueNs(name),
|
| DefKind::Field => DefPathData::ValueNs(name),
|
||||||
|
@ -278,7 +286,7 @@ impl DefKind {
|
||||||
| DefKind::AssocFn
|
| DefKind::AssocFn
|
||||||
| DefKind::Ctor(..)
|
| DefKind::Ctor(..)
|
||||||
| DefKind::Closure
|
| DefKind::Closure
|
||||||
| DefKind::Static(_) => true,
|
| DefKind::Static { .. } => true,
|
||||||
DefKind::Mod
|
DefKind::Mod
|
||||||
| DefKind::Struct
|
| DefKind::Struct
|
||||||
| DefKind::Union
|
| DefKind::Union
|
||||||
|
|
|
@ -1616,7 +1616,7 @@ impl Expr<'_> {
|
||||||
pub fn is_place_expr(&self, mut allow_projections_from: impl FnMut(&Self) -> bool) -> bool {
|
pub fn is_place_expr(&self, mut allow_projections_from: impl FnMut(&Self) -> bool) -> bool {
|
||||||
match self.kind {
|
match self.kind {
|
||||||
ExprKind::Path(QPath::Resolved(_, ref path)) => {
|
ExprKind::Path(QPath::Resolved(_, ref path)) => {
|
||||||
matches!(path.res, Res::Local(..) | Res::Def(DefKind::Static(_), _) | Res::Err)
|
matches!(path.res, Res::Local(..) | Res::Def(DefKind::Static { .. }, _) | Res::Err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Type ascription inherits its place expression kind from its
|
// Type ascription inherits its place expression kind from its
|
||||||
|
|
|
@ -107,7 +107,7 @@ impl Target {
|
||||||
match item.kind {
|
match item.kind {
|
||||||
ItemKind::ExternCrate(..) => Target::ExternCrate,
|
ItemKind::ExternCrate(..) => Target::ExternCrate,
|
||||||
ItemKind::Use(..) => Target::Use,
|
ItemKind::Use(..) => Target::Use,
|
||||||
ItemKind::Static(..) => Target::Static,
|
ItemKind::Static { .. } => Target::Static,
|
||||||
ItemKind::Const(..) => Target::Const,
|
ItemKind::Const(..) => Target::Const,
|
||||||
ItemKind::Fn(..) => Target::Fn,
|
ItemKind::Fn(..) => Target::Fn,
|
||||||
ItemKind::Macro(..) => Target::MacroDef,
|
ItemKind::Macro(..) => Target::MacroDef,
|
||||||
|
@ -130,7 +130,7 @@ impl Target {
|
||||||
match def_kind {
|
match def_kind {
|
||||||
DefKind::ExternCrate => Target::ExternCrate,
|
DefKind::ExternCrate => Target::ExternCrate,
|
||||||
DefKind::Use => Target::Use,
|
DefKind::Use => Target::Use,
|
||||||
DefKind::Static(..) => Target::Static,
|
DefKind::Static { .. } => Target::Static,
|
||||||
DefKind::Const => Target::Const,
|
DefKind::Const => Target::Const,
|
||||||
DefKind::Fn => Target::Fn,
|
DefKind::Fn => Target::Fn,
|
||||||
DefKind::Macro(..) => Target::MacroDef,
|
DefKind::Macro(..) => Target::MacroDef,
|
||||||
|
|
|
@ -1934,7 +1934,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Case 3. Reference to a top-level value.
|
// Case 3. Reference to a top-level value.
|
||||||
DefKind::Fn | DefKind::Const | DefKind::ConstParam | DefKind::Static(_) => {
|
DefKind::Fn | DefKind::Const | DefKind::ConstParam | DefKind::Static { .. } => {
|
||||||
path_segs.push(PathSeg(def_id, last));
|
path_segs.push(PathSeg(def_id, last));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -226,7 +226,7 @@ fn check_static_inhabited(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
||||||
Ok(l) => l,
|
Ok(l) => l,
|
||||||
// Foreign statics that overflow their allowed size should emit an error
|
// Foreign statics that overflow their allowed size should emit an error
|
||||||
Err(LayoutError::SizeOverflow(_))
|
Err(LayoutError::SizeOverflow(_))
|
||||||
if matches!(tcx.def_kind(def_id), DefKind::Static(_)
|
if matches!(tcx.def_kind(def_id), DefKind::Static{ .. }
|
||||||
if tcx.def_kind(tcx.local_parent(def_id)) == DefKind::ForeignMod) =>
|
if tcx.def_kind(tcx.local_parent(def_id)) == DefKind::ForeignMod) =>
|
||||||
{
|
{
|
||||||
tcx.dcx().emit_err(errors::TooLargeStatic { span });
|
tcx.dcx().emit_err(errors::TooLargeStatic { span });
|
||||||
|
@ -505,7 +505,7 @@ fn check_static_linkage(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
||||||
pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
||||||
let _indenter = indenter();
|
let _indenter = indenter();
|
||||||
match tcx.def_kind(def_id) {
|
match tcx.def_kind(def_id) {
|
||||||
DefKind::Static(..) => {
|
DefKind::Static { .. } => {
|
||||||
tcx.ensure().typeck(def_id);
|
tcx.ensure().typeck(def_id);
|
||||||
maybe_check_static_with_link_section(tcx, def_id);
|
maybe_check_static_with_link_section(tcx, def_id);
|
||||||
check_static_inhabited(tcx, def_id);
|
check_static_inhabited(tcx, def_id);
|
||||||
|
|
|
@ -48,8 +48,7 @@ fn is_path_static_mut(expr: hir::Expr<'_>) -> Option<String> {
|
||||||
if let hir::ExprKind::Path(qpath) = expr.kind
|
if let hir::ExprKind::Path(qpath) = expr.kind
|
||||||
&& let hir::QPath::Resolved(_, path) = qpath
|
&& let hir::QPath::Resolved(_, path) = qpath
|
||||||
&& let hir::def::Res::Def(def_kind, _) = path.res
|
&& let hir::def::Res::Def(def_kind, _) = path.res
|
||||||
&& let hir::def::DefKind::Static(mt) = def_kind
|
&& let hir::def::DefKind::Static { mutability: Mutability::Mut, nested: false } = def_kind
|
||||||
&& matches!(mt, Mutability::Mut)
|
|
||||||
{
|
{
|
||||||
return Some(qpath_to_string(&qpath));
|
return Some(qpath_to_string(&qpath));
|
||||||
}
|
}
|
||||||
|
|
|
@ -182,7 +182,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
|
||||||
tcx.hir().par_body_owners(|item_def_id| {
|
tcx.hir().par_body_owners(|item_def_id| {
|
||||||
let def_kind = tcx.def_kind(item_def_id);
|
let def_kind = tcx.def_kind(item_def_id);
|
||||||
match def_kind {
|
match def_kind {
|
||||||
DefKind::Static(_) => tcx.ensure().eval_static_initializer(item_def_id),
|
DefKind::Static { .. } => tcx.ensure().eval_static_initializer(item_def_id),
|
||||||
DefKind::Const => tcx.ensure().const_eval_poly(item_def_id.into()),
|
DefKind::Const => tcx.ensure().const_eval_poly(item_def_id.into()),
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
|
|
@ -699,7 +699,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
hir::Path {
|
hir::Path {
|
||||||
res:
|
res:
|
||||||
hir::def::Res::Def(
|
hir::def::Res::Def(
|
||||||
hir::def::DefKind::Static(_) | hir::def::DefKind::Const,
|
hir::def::DefKind::Static { .. } | hir::def::DefKind::Const,
|
||||||
def_id,
|
def_id,
|
||||||
),
|
),
|
||||||
..
|
..
|
||||||
|
|
|
@ -398,7 +398,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
|
||||||
)
|
)
|
||||||
| Res::SelfCtor(..) => Ok(self.cat_rvalue(hir_id, expr_ty)),
|
| Res::SelfCtor(..) => Ok(self.cat_rvalue(hir_id, expr_ty)),
|
||||||
|
|
||||||
Res::Def(DefKind::Static(_), _) => {
|
Res::Def(DefKind::Static { .. }, _) => {
|
||||||
Ok(PlaceWithHirId::new(hir_id, expr_ty, PlaceBase::StaticItem, Vec::new()))
|
Ok(PlaceWithHirId::new(hir_id, expr_ty, PlaceBase::StaticItem, Vec::new()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -372,7 +372,7 @@ impl<T> Trait<T> for X {
|
||||||
&& matches!(
|
&& matches!(
|
||||||
tcx.def_kind(body_owner_def_id),
|
tcx.def_kind(body_owner_def_id),
|
||||||
DefKind::Fn
|
DefKind::Fn
|
||||||
| DefKind::Static(_)
|
| DefKind::Static { .. }
|
||||||
| DefKind::Const
|
| DefKind::Const
|
||||||
| DefKind::AssocFn
|
| DefKind::AssocFn
|
||||||
| DefKind::AssocConst
|
| DefKind::AssocConst
|
||||||
|
|
|
@ -863,7 +863,7 @@ fn should_encode_span(def_kind: DefKind) -> bool {
|
||||||
| DefKind::LifetimeParam
|
| DefKind::LifetimeParam
|
||||||
| DefKind::Fn
|
| DefKind::Fn
|
||||||
| DefKind::Const
|
| DefKind::Const
|
||||||
| DefKind::Static(_)
|
| DefKind::Static { .. }
|
||||||
| DefKind::Ctor(..)
|
| DefKind::Ctor(..)
|
||||||
| DefKind::AssocFn
|
| DefKind::AssocFn
|
||||||
| DefKind::AssocConst
|
| DefKind::AssocConst
|
||||||
|
@ -894,7 +894,7 @@ fn should_encode_attrs(def_kind: DefKind) -> bool {
|
||||||
| DefKind::AssocTy
|
| DefKind::AssocTy
|
||||||
| DefKind::Fn
|
| DefKind::Fn
|
||||||
| DefKind::Const
|
| DefKind::Const
|
||||||
| DefKind::Static(_)
|
| DefKind::Static { nested: false, .. }
|
||||||
| DefKind::AssocFn
|
| DefKind::AssocFn
|
||||||
| DefKind::AssocConst
|
| DefKind::AssocConst
|
||||||
| DefKind::Macro(_)
|
| DefKind::Macro(_)
|
||||||
|
@ -915,6 +915,7 @@ fn should_encode_attrs(def_kind: DefKind) -> bool {
|
||||||
| DefKind::InlineConst
|
| DefKind::InlineConst
|
||||||
| DefKind::OpaqueTy
|
| DefKind::OpaqueTy
|
||||||
| DefKind::LifetimeParam
|
| DefKind::LifetimeParam
|
||||||
|
| DefKind::Static { nested: true, .. }
|
||||||
| DefKind::GlobalAsm => false,
|
| DefKind::GlobalAsm => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -936,7 +937,7 @@ fn should_encode_expn_that_defined(def_kind: DefKind) -> bool {
|
||||||
| DefKind::Fn
|
| DefKind::Fn
|
||||||
| DefKind::Const
|
| DefKind::Const
|
||||||
| DefKind::ConstParam
|
| DefKind::ConstParam
|
||||||
| DefKind::Static(_)
|
| DefKind::Static { .. }
|
||||||
| DefKind::Ctor(..)
|
| DefKind::Ctor(..)
|
||||||
| DefKind::AssocFn
|
| DefKind::AssocFn
|
||||||
| DefKind::AssocConst
|
| DefKind::AssocConst
|
||||||
|
@ -968,7 +969,7 @@ fn should_encode_visibility(def_kind: DefKind) -> bool {
|
||||||
| DefKind::AssocTy
|
| DefKind::AssocTy
|
||||||
| DefKind::Fn
|
| DefKind::Fn
|
||||||
| DefKind::Const
|
| DefKind::Const
|
||||||
| DefKind::Static(..)
|
| DefKind::Static { nested: false, .. }
|
||||||
| DefKind::Ctor(..)
|
| DefKind::Ctor(..)
|
||||||
| DefKind::AssocFn
|
| DefKind::AssocFn
|
||||||
| DefKind::AssocConst
|
| DefKind::AssocConst
|
||||||
|
@ -981,6 +982,7 @@ fn should_encode_visibility(def_kind: DefKind) -> bool {
|
||||||
| DefKind::LifetimeParam
|
| DefKind::LifetimeParam
|
||||||
| DefKind::AnonConst
|
| DefKind::AnonConst
|
||||||
| DefKind::InlineConst
|
| DefKind::InlineConst
|
||||||
|
| DefKind::Static { nested: true, .. }
|
||||||
| DefKind::OpaqueTy
|
| DefKind::OpaqueTy
|
||||||
| DefKind::GlobalAsm
|
| DefKind::GlobalAsm
|
||||||
| DefKind::Impl { .. }
|
| DefKind::Impl { .. }
|
||||||
|
@ -1001,7 +1003,7 @@ fn should_encode_stability(def_kind: DefKind) -> bool {
|
||||||
| DefKind::AssocConst
|
| DefKind::AssocConst
|
||||||
| DefKind::TyParam
|
| DefKind::TyParam
|
||||||
| DefKind::ConstParam
|
| DefKind::ConstParam
|
||||||
| DefKind::Static(..)
|
| DefKind::Static { .. }
|
||||||
| DefKind::Const
|
| DefKind::Const
|
||||||
| DefKind::Fn
|
| DefKind::Fn
|
||||||
| DefKind::ForeignMod
|
| DefKind::ForeignMod
|
||||||
|
@ -1099,7 +1101,7 @@ fn should_encode_variances<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, def_kind: Def
|
||||||
| DefKind::AssocConst
|
| DefKind::AssocConst
|
||||||
| DefKind::TyParam
|
| DefKind::TyParam
|
||||||
| DefKind::ConstParam
|
| DefKind::ConstParam
|
||||||
| DefKind::Static(..)
|
| DefKind::Static { .. }
|
||||||
| DefKind::Const
|
| DefKind::Const
|
||||||
| DefKind::ForeignMod
|
| DefKind::ForeignMod
|
||||||
| DefKind::Impl { .. }
|
| DefKind::Impl { .. }
|
||||||
|
@ -1131,7 +1133,7 @@ fn should_encode_generics(def_kind: DefKind) -> bool {
|
||||||
| DefKind::AssocTy
|
| DefKind::AssocTy
|
||||||
| DefKind::Fn
|
| DefKind::Fn
|
||||||
| DefKind::Const
|
| DefKind::Const
|
||||||
| DefKind::Static(..)
|
| DefKind::Static { .. }
|
||||||
| DefKind::Ctor(..)
|
| DefKind::Ctor(..)
|
||||||
| DefKind::AssocFn
|
| DefKind::AssocFn
|
||||||
| DefKind::AssocConst
|
| DefKind::AssocConst
|
||||||
|
@ -1163,7 +1165,7 @@ fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) ->
|
||||||
| DefKind::Field
|
| DefKind::Field
|
||||||
| DefKind::Fn
|
| DefKind::Fn
|
||||||
| DefKind::Const
|
| DefKind::Const
|
||||||
| DefKind::Static(..)
|
| DefKind::Static { nested: false, .. }
|
||||||
| DefKind::TyAlias
|
| DefKind::TyAlias
|
||||||
| DefKind::ForeignTy
|
| DefKind::ForeignTy
|
||||||
| DefKind::Impl { .. }
|
| DefKind::Impl { .. }
|
||||||
|
@ -1205,6 +1207,7 @@ fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) ->
|
||||||
| DefKind::Mod
|
| DefKind::Mod
|
||||||
| DefKind::ForeignMod
|
| DefKind::ForeignMod
|
||||||
| DefKind::Macro(..)
|
| DefKind::Macro(..)
|
||||||
|
| DefKind::Static { nested: true, .. }
|
||||||
| DefKind::Use
|
| DefKind::Use
|
||||||
| DefKind::LifetimeParam
|
| DefKind::LifetimeParam
|
||||||
| DefKind::GlobalAsm
|
| DefKind::GlobalAsm
|
||||||
|
@ -1222,7 +1225,7 @@ fn should_encode_fn_sig(def_kind: DefKind) -> bool {
|
||||||
| DefKind::Variant
|
| DefKind::Variant
|
||||||
| DefKind::Field
|
| DefKind::Field
|
||||||
| DefKind::Const
|
| DefKind::Const
|
||||||
| DefKind::Static(..)
|
| DefKind::Static { .. }
|
||||||
| DefKind::Ctor(..)
|
| DefKind::Ctor(..)
|
||||||
| DefKind::TyAlias
|
| DefKind::TyAlias
|
||||||
| DefKind::OpaqueTy
|
| DefKind::OpaqueTy
|
||||||
|
@ -1263,7 +1266,7 @@ fn should_encode_constness(def_kind: DefKind) -> bool {
|
||||||
| DefKind::Const
|
| DefKind::Const
|
||||||
| DefKind::AssocConst
|
| DefKind::AssocConst
|
||||||
| DefKind::AnonConst
|
| DefKind::AnonConst
|
||||||
| DefKind::Static(..)
|
| DefKind::Static { .. }
|
||||||
| DefKind::TyAlias
|
| DefKind::TyAlias
|
||||||
| DefKind::OpaqueTy
|
| DefKind::OpaqueTy
|
||||||
| DefKind::Impl { of_trait: false }
|
| DefKind::Impl { of_trait: false }
|
||||||
|
@ -1295,7 +1298,7 @@ fn should_encode_const(def_kind: DefKind) -> bool {
|
||||||
| DefKind::Ctor(..)
|
| DefKind::Ctor(..)
|
||||||
| DefKind::Field
|
| DefKind::Field
|
||||||
| DefKind::Fn
|
| DefKind::Fn
|
||||||
| DefKind::Static(..)
|
| DefKind::Static { .. }
|
||||||
| DefKind::TyAlias
|
| DefKind::TyAlias
|
||||||
| DefKind::OpaqueTy
|
| DefKind::OpaqueTy
|
||||||
| DefKind::ForeignTy
|
| DefKind::ForeignTy
|
||||||
|
@ -1469,7 +1472,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||||
.coroutine_for_closure
|
.coroutine_for_closure
|
||||||
.set_some(def_id.index, self.tcx.coroutine_for_closure(def_id).into());
|
.set_some(def_id.index, self.tcx.coroutine_for_closure(def_id).into());
|
||||||
}
|
}
|
||||||
if let DefKind::Static(_) = def_kind {
|
if let DefKind::Static { .. } = def_kind {
|
||||||
if !self.tcx.is_foreign_item(def_id) {
|
if !self.tcx.is_foreign_item(def_id) {
|
||||||
let data = self.tcx.eval_static_initializer(def_id).unwrap();
|
let data = self.tcx.eval_static_initializer(def_id).unwrap();
|
||||||
record!(self.tables.eval_static_initializer[def_id] <- data);
|
record!(self.tables.eval_static_initializer[def_id] <- data);
|
||||||
|
|
|
@ -155,8 +155,10 @@ fixed_size_enum! {
|
||||||
( Impl { of_trait: false } )
|
( Impl { of_trait: false } )
|
||||||
( Impl { of_trait: true } )
|
( Impl { of_trait: true } )
|
||||||
( Closure )
|
( Closure )
|
||||||
( Static(ast::Mutability::Not) )
|
( Static { mutability: ast::Mutability::Not, nested: false } )
|
||||||
( Static(ast::Mutability::Mut) )
|
( Static { mutability: ast::Mutability::Mut, nested: false } )
|
||||||
|
( Static { mutability: ast::Mutability::Not, nested: true } )
|
||||||
|
( Static { mutability: ast::Mutability::Mut, nested: true } )
|
||||||
( Ctor(CtorOf::Struct, CtorKind::Fn) )
|
( Ctor(CtorOf::Struct, CtorKind::Fn) )
|
||||||
( Ctor(CtorOf::Struct, CtorKind::Const) )
|
( Ctor(CtorOf::Struct, CtorKind::Const) )
|
||||||
( Ctor(CtorOf::Variant, CtorKind::Fn) )
|
( Ctor(CtorOf::Variant, CtorKind::Fn) )
|
||||||
|
|
|
@ -343,7 +343,7 @@ impl<'hir> Map<'hir> {
|
||||||
DefKind::InlineConst => BodyOwnerKind::Const { inline: true },
|
DefKind::InlineConst => BodyOwnerKind::Const { inline: true },
|
||||||
DefKind::Ctor(..) | DefKind::Fn | DefKind::AssocFn => BodyOwnerKind::Fn,
|
DefKind::Ctor(..) | DefKind::Fn | DefKind::AssocFn => BodyOwnerKind::Fn,
|
||||||
DefKind::Closure => BodyOwnerKind::Closure,
|
DefKind::Closure => BodyOwnerKind::Closure,
|
||||||
DefKind::Static(mt) => BodyOwnerKind::Static(mt),
|
DefKind::Static { mutability, nested: false } => BodyOwnerKind::Static(mutability),
|
||||||
dk => bug!("{:?} is not a body node: {:?}", def_id, dk),
|
dk => bug!("{:?} is not a body node: {:?}", def_id, dk),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -359,7 +359,7 @@ impl<'hir> Map<'hir> {
|
||||||
let def_id = def_id.into();
|
let def_id = def_id.into();
|
||||||
let ccx = match self.body_owner_kind(def_id) {
|
let ccx = match self.body_owner_kind(def_id) {
|
||||||
BodyOwnerKind::Const { inline } => ConstContext::Const { inline },
|
BodyOwnerKind::Const { inline } => ConstContext::Const { inline },
|
||||||
BodyOwnerKind::Static(mt) => ConstContext::Static(mt),
|
BodyOwnerKind::Static(mutability) => ConstContext::Static(mutability),
|
||||||
|
|
||||||
BodyOwnerKind::Fn if self.tcx.is_constructor(def_id) => return None,
|
BodyOwnerKind::Fn if self.tcx.is_constructor(def_id) => return None,
|
||||||
BodyOwnerKind::Fn | BodyOwnerKind::Closure if self.tcx.is_const_fn_raw(def_id) => {
|
BodyOwnerKind::Fn | BodyOwnerKind::Closure if self.tcx.is_const_fn_raw(def_id) => {
|
||||||
|
|
|
@ -130,7 +130,7 @@ use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_data_structures::sync::{HashMapExt, Lock};
|
use rustc_data_structures::sync::{HashMapExt, Lock};
|
||||||
use rustc_data_structures::tiny_list::TinyList;
|
use rustc_data_structures::tiny_list::TinyList;
|
||||||
use rustc_errors::ErrorGuaranteed;
|
use rustc_errors::ErrorGuaranteed;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||||
use rustc_macros::HashStable;
|
use rustc_macros::HashStable;
|
||||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||||
use rustc_serialize::{Decodable, Encodable};
|
use rustc_serialize::{Decodable, Encodable};
|
||||||
|
@ -627,6 +627,16 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Freezes an `AllocId` created with `reserve` by pointing it at a static item. Trying to
|
||||||
|
/// call this function twice, even with the same `DefId` will ICE the compiler.
|
||||||
|
pub fn set_nested_alloc_id_static(self, id: AllocId, def_id: LocalDefId) {
|
||||||
|
if let Some(old) =
|
||||||
|
self.alloc_map.lock().alloc_map.insert(id, GlobalAlloc::Static(def_id.to_def_id()))
|
||||||
|
{
|
||||||
|
bug!("tried to set allocation ID {id:?}, but it was already existing as {old:#?}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Freezes an `AllocId` created with `reserve` by pointing it at an `Allocation`. May be called
|
/// Freezes an `AllocId` created with `reserve` by pointing it at an `Allocation`. May be called
|
||||||
/// twice for the same `(AllocId, Allocation)` pair.
|
/// twice for the same `(AllocId, Allocation)` pair.
|
||||||
fn set_alloc_id_same_memory(self, id: AllocId, mem: ConstAllocation<'tcx>) {
|
fn set_alloc_id_same_memory(self, id: AllocId, mem: ConstAllocation<'tcx>) {
|
||||||
|
|
|
@ -498,8 +498,12 @@ fn write_mir_sig(tcx: TyCtxt<'_>, body: &Body<'_>, w: &mut dyn io::Write) -> io:
|
||||||
match (kind, body.source.promoted) {
|
match (kind, body.source.promoted) {
|
||||||
(_, Some(_)) => write!(w, "const ")?, // promoteds are the closest to consts
|
(_, Some(_)) => write!(w, "const ")?, // promoteds are the closest to consts
|
||||||
(DefKind::Const | DefKind::AssocConst, _) => write!(w, "const ")?,
|
(DefKind::Const | DefKind::AssocConst, _) => write!(w, "const ")?,
|
||||||
(DefKind::Static(hir::Mutability::Not), _) => write!(w, "static ")?,
|
(DefKind::Static { mutability: hir::Mutability::Not, nested: false }, _) => {
|
||||||
(DefKind::Static(hir::Mutability::Mut), _) => write!(w, "static mut ")?,
|
write!(w, "static ")?
|
||||||
|
}
|
||||||
|
(DefKind::Static { mutability: hir::Mutability::Mut, nested: false }, _) => {
|
||||||
|
write!(w, "static mut ")?
|
||||||
|
}
|
||||||
(_, _) if is_function => write!(w, "fn ")?,
|
(_, _) if is_function => write!(w, "fn ")?,
|
||||||
(DefKind::AnonConst | DefKind::InlineConst, _) => {} // things like anon const, not an item
|
(DefKind::AnonConst | DefKind::InlineConst, _) => {} // things like anon const, not an item
|
||||||
_ => bug!("Unexpected def kind {:?}", kind),
|
_ => bug!("Unexpected def kind {:?}", kind),
|
||||||
|
|
|
@ -1062,6 +1062,7 @@ rustc_queries! {
|
||||||
}
|
}
|
||||||
cache_on_disk_if { key.is_local() }
|
cache_on_disk_if { key.is_local() }
|
||||||
separate_provide_extern
|
separate_provide_extern
|
||||||
|
feedable
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Evaluates const items or anonymous constants
|
/// Evaluates const items or anonymous constants
|
||||||
|
@ -1220,6 +1221,7 @@ rustc_queries! {
|
||||||
arena_cache
|
arena_cache
|
||||||
cache_on_disk_if { def_id.is_local() }
|
cache_on_disk_if { def_id.is_local() }
|
||||||
separate_provide_extern
|
separate_provide_extern
|
||||||
|
feedable
|
||||||
}
|
}
|
||||||
|
|
||||||
query asm_target_features(def_id: DefId) -> &'tcx FxIndexSet<Symbol> {
|
query asm_target_features(def_id: DefId) -> &'tcx FxIndexSet<Symbol> {
|
||||||
|
|
|
@ -1708,7 +1708,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
debug!("returned from def_kind: {:?}", def_kind);
|
debug!("returned from def_kind: {:?}", def_kind);
|
||||||
match def_kind {
|
match def_kind {
|
||||||
DefKind::Const
|
DefKind::Const
|
||||||
| DefKind::Static(..)
|
| DefKind::Static { .. }
|
||||||
| DefKind::AssocConst
|
| DefKind::AssocConst
|
||||||
| DefKind::Ctor(..)
|
| DefKind::Ctor(..)
|
||||||
| DefKind::AnonConst
|
| DefKind::AnonConst
|
||||||
|
|
|
@ -359,7 +359,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
||||||
| DefKind::TyAlias
|
| DefKind::TyAlias
|
||||||
| DefKind::Fn
|
| DefKind::Fn
|
||||||
| DefKind::Const
|
| DefKind::Const
|
||||||
| DefKind::Static(_) = kind
|
| DefKind::Static { .. } = kind
|
||||||
{
|
{
|
||||||
} else {
|
} else {
|
||||||
// If not covered above, like for example items out of `impl` blocks, fallback.
|
// If not covered above, like for example items out of `impl` blocks, fallback.
|
||||||
|
|
|
@ -616,12 +616,16 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
/// Returns `true` if the node pointed to by `def_id` is a `static` item.
|
/// Returns `true` if the node pointed to by `def_id` is a `static` item.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_static(self, def_id: DefId) -> bool {
|
pub fn is_static(self, def_id: DefId) -> bool {
|
||||||
matches!(self.def_kind(def_id), DefKind::Static(_))
|
matches!(self.def_kind(def_id), DefKind::Static { .. })
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn static_mutability(self, def_id: DefId) -> Option<hir::Mutability> {
|
pub fn static_mutability(self, def_id: DefId) -> Option<hir::Mutability> {
|
||||||
if let DefKind::Static(mt) = self.def_kind(def_id) { Some(mt) } else { None }
|
if let DefKind::Static { mutability, .. } = self.def_kind(def_id) {
|
||||||
|
Some(mutability)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if this is a `static` item with the `#[thread_local]` attribute.
|
/// Returns `true` if this is a `static` item with the `#[thread_local]` attribute.
|
||||||
|
|
|
@ -631,7 +631,7 @@ fn construct_error(tcx: TyCtxt<'_>, def_id: LocalDefId, guar: ErrorGuaranteed) -
|
||||||
| DefKind::AssocConst
|
| DefKind::AssocConst
|
||||||
| DefKind::AnonConst
|
| DefKind::AnonConst
|
||||||
| DefKind::InlineConst
|
| DefKind::InlineConst
|
||||||
| DefKind::Static(_) => (vec![], tcx.type_of(def_id).instantiate_identity(), None),
|
| DefKind::Static { .. } => (vec![], tcx.type_of(def_id).instantiate_identity(), None),
|
||||||
DefKind::Ctor(..) | DefKind::Fn | DefKind::AssocFn => {
|
DefKind::Ctor(..) | DefKind::Fn | DefKind::AssocFn => {
|
||||||
let sig = tcx.liberate_late_bound_regions(
|
let sig = tcx.liberate_late_bound_regions(
|
||||||
def_id.to_def_id(),
|
def_id.to_def_id(),
|
||||||
|
|
|
@ -942,7 +942,7 @@ impl<'tcx> Cx<'tcx> {
|
||||||
|
|
||||||
// We encode uses of statics as a `*&STATIC` where the `&STATIC` part is
|
// We encode uses of statics as a `*&STATIC` where the `&STATIC` part is
|
||||||
// a constant reference (or constant raw pointer for `static mut`) in MIR
|
// a constant reference (or constant raw pointer for `static mut`) in MIR
|
||||||
Res::Def(DefKind::Static(_), id) => {
|
Res::Def(DefKind::Static { .. }, id) => {
|
||||||
let ty = self.tcx.static_ptr_ty(id);
|
let ty = self.tcx.static_ptr_ty(id);
|
||||||
let temp_lifetime = self
|
let temp_lifetime = self
|
||||||
.rvalue_scopes
|
.rvalue_scopes
|
||||||
|
|
|
@ -453,7 +453,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
||||||
Res::Def(DefKind::ConstParam, _) => {
|
Res::Def(DefKind::ConstParam, _) => {
|
||||||
self.tcx.dcx().emit_err(ConstParamInPattern { span })
|
self.tcx.dcx().emit_err(ConstParamInPattern { span })
|
||||||
}
|
}
|
||||||
Res::Def(DefKind::Static(_), _) => {
|
Res::Def(DefKind::Static { .. }, _) => {
|
||||||
self.tcx.dcx().emit_err(StaticInPattern { span })
|
self.tcx.dcx().emit_err(StaticInPattern { span })
|
||||||
}
|
}
|
||||||
_ => self.tcx.dcx().emit_err(NonConstPath { span }),
|
_ => self.tcx.dcx().emit_err(NonConstPath { span }),
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
//! Currently, this pass only propagates scalar values.
|
//! Currently, this pass only propagates scalar values.
|
||||||
|
|
||||||
use rustc_const_eval::interpret::{
|
use rustc_const_eval::interpret::{
|
||||||
ImmTy, Immediate, InterpCx, OpTy, PlaceTy, PointerArithmetic, Projectable,
|
HasStaticRootDefId, ImmTy, Immediate, InterpCx, OpTy, PlaceTy, PointerArithmetic, Projectable,
|
||||||
};
|
};
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_hir::def::DefKind;
|
use rustc_hir::def::DefKind;
|
||||||
|
@ -889,6 +889,12 @@ impl<'tcx> Visitor<'tcx> for OperandCollector<'tcx, '_, '_, '_> {
|
||||||
|
|
||||||
pub(crate) struct DummyMachine;
|
pub(crate) struct DummyMachine;
|
||||||
|
|
||||||
|
impl HasStaticRootDefId for DummyMachine {
|
||||||
|
fn static_def_id(&self) -> Option<rustc_hir::def_id::LocalDefId> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'mir, 'tcx: 'mir> rustc_const_eval::interpret::Machine<'mir, 'tcx> for DummyMachine {
|
impl<'mir, 'tcx: 'mir> rustc_const_eval::interpret::Machine<'mir, 'tcx> for DummyMachine {
|
||||||
rustc_const_eval::interpret::compile_time_machine!(<'mir, 'tcx>);
|
rustc_const_eval::interpret::compile_time_machine!(<'mir, 'tcx>);
|
||||||
type MemoryKind = !;
|
type MemoryKind = !;
|
||||||
|
|
|
@ -333,7 +333,7 @@ fn mir_promoted(
|
||||||
}
|
}
|
||||||
DefKind::AssocConst
|
DefKind::AssocConst
|
||||||
| DefKind::Const
|
| DefKind::Const
|
||||||
| DefKind::Static(_)
|
| DefKind::Static { .. }
|
||||||
| DefKind::InlineConst
|
| DefKind::InlineConst
|
||||||
| DefKind::AnonConst => tcx.mir_const_qualif(def),
|
| DefKind::AnonConst => tcx.mir_const_qualif(def),
|
||||||
_ => ConstQualifs::default(),
|
_ => ConstQualifs::default(),
|
||||||
|
|
|
@ -380,8 +380,12 @@ fn collect_items_rec<'tcx>(
|
||||||
// Sanity check whether this ended up being collected accidentally
|
// Sanity check whether this ended up being collected accidentally
|
||||||
debug_assert!(should_codegen_locally(tcx, &instance));
|
debug_assert!(should_codegen_locally(tcx, &instance));
|
||||||
|
|
||||||
|
let DefKind::Static { nested, .. } = tcx.def_kind(def_id) else { bug!() };
|
||||||
|
// Nested statics have no type.
|
||||||
|
if !nested {
|
||||||
let ty = instance.ty(tcx, ty::ParamEnv::reveal_all());
|
let ty = instance.ty(tcx, ty::ParamEnv::reveal_all());
|
||||||
visit_drop_use(tcx, ty, true, starting_item.span, &mut used_items);
|
visit_drop_use(tcx, ty, true, starting_item.span, &mut used_items);
|
||||||
|
}
|
||||||
|
|
||||||
recursion_depth_reset = None;
|
recursion_depth_reset = None;
|
||||||
|
|
||||||
|
@ -1037,7 +1041,7 @@ fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx>) ->
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let DefKind::Static(_) = tcx.def_kind(def_id) {
|
if let DefKind::Static { .. } = tcx.def_kind(def_id) {
|
||||||
// We cannot monomorphize statics from upstream crates.
|
// We cannot monomorphize statics from upstream crates.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1254,7 +1258,7 @@ impl<'v> RootCollector<'_, 'v> {
|
||||||
);
|
);
|
||||||
self.output.push(dummy_spanned(MonoItem::GlobalAsm(id)));
|
self.output.push(dummy_spanned(MonoItem::GlobalAsm(id)));
|
||||||
}
|
}
|
||||||
DefKind::Static(..) => {
|
DefKind::Static { .. } => {
|
||||||
let def_id = id.owner_id.to_def_id();
|
let def_id = id.owner_id.to_def_id();
|
||||||
debug!("RootCollector: ItemKind::Static({})", self.tcx.def_path_str(def_id));
|
debug!("RootCollector: ItemKind::Static({})", self.tcx.def_path_str(def_id));
|
||||||
self.output.push(dummy_spanned(MonoItem::Static(def_id)));
|
self.output.push(dummy_spanned(MonoItem::Static(def_id)));
|
||||||
|
|
|
@ -150,7 +150,7 @@ fn mark_used_by_default_parameters<'tcx>(
|
||||||
| DefKind::Fn
|
| DefKind::Fn
|
||||||
| DefKind::Const
|
| DefKind::Const
|
||||||
| DefKind::ConstParam
|
| DefKind::ConstParam
|
||||||
| DefKind::Static(_)
|
| DefKind::Static { .. }
|
||||||
| DefKind::Ctor(_, _)
|
| DefKind::Ctor(_, _)
|
||||||
| DefKind::AssocFn
|
| DefKind::AssocFn
|
||||||
| DefKind::AssocConst
|
| DefKind::AssocConst
|
||||||
|
|
|
@ -801,7 +801,7 @@ fn check_foreign_item(
|
||||||
worklist: &mut Vec<(LocalDefId, ComesFromAllowExpect)>,
|
worklist: &mut Vec<(LocalDefId, ComesFromAllowExpect)>,
|
||||||
id: hir::ForeignItemId,
|
id: hir::ForeignItemId,
|
||||||
) {
|
) {
|
||||||
if matches!(tcx.def_kind(id.owner_id), DefKind::Static(_) | DefKind::Fn)
|
if matches!(tcx.def_kind(id.owner_id), DefKind::Static { .. } | DefKind::Fn)
|
||||||
&& let Some(comes_from_allow) = has_allow_dead_code_or_lang_attr(tcx, id.owner_id.def_id)
|
&& let Some(comes_from_allow) = has_allow_dead_code_or_lang_attr(tcx, id.owner_id.def_id)
|
||||||
{
|
{
|
||||||
worklist.push((id.owner_id.def_id, comes_from_allow));
|
worklist.push((id.owner_id.def_id, comes_from_allow));
|
||||||
|
@ -1058,7 +1058,7 @@ impl<'tcx> DeadVisitor<'tcx> {
|
||||||
DefKind::AssocConst
|
DefKind::AssocConst
|
||||||
| DefKind::AssocFn
|
| DefKind::AssocFn
|
||||||
| DefKind::Fn
|
| DefKind::Fn
|
||||||
| DefKind::Static(_)
|
| DefKind::Static { .. }
|
||||||
| DefKind::Const
|
| DefKind::Const
|
||||||
| DefKind::TyAlias
|
| DefKind::TyAlias
|
||||||
| DefKind::Enum
|
| DefKind::Enum
|
||||||
|
|
|
@ -13,6 +13,7 @@ use rustc_hir::intravisit::{self, Visitor};
|
||||||
use rustc_hir::Node;
|
use rustc_hir::Node;
|
||||||
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
|
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
|
||||||
use rustc_middle::middle::privacy::{self, Level};
|
use rustc_middle::middle::privacy::{self, Level};
|
||||||
|
use rustc_middle::mir::interpret::{ConstAllocation, GlobalAlloc};
|
||||||
use rustc_middle::query::Providers;
|
use rustc_middle::query::Providers;
|
||||||
use rustc_middle::ty::{self, TyCtxt};
|
use rustc_middle::ty::{self, TyCtxt};
|
||||||
use rustc_session::config::CrateType;
|
use rustc_session::config::CrateType;
|
||||||
|
@ -73,7 +74,7 @@ impl<'tcx> Visitor<'tcx> for ReachableContext<'tcx> {
|
||||||
match res {
|
match res {
|
||||||
// Reachable constants and reachable statics can have their contents inlined
|
// Reachable constants and reachable statics can have their contents inlined
|
||||||
// into other crates. Mark them as reachable and recurse into their body.
|
// into other crates. Mark them as reachable and recurse into their body.
|
||||||
Res::Def(DefKind::Const | DefKind::AssocConst | DefKind::Static(_), _) => {
|
Res::Def(DefKind::Const | DefKind::AssocConst | DefKind::Static { .. }, _) => {
|
||||||
self.worklist.push(def_id);
|
self.worklist.push(def_id);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -197,10 +198,23 @@ impl<'tcx> ReachableContext<'tcx> {
|
||||||
// Reachable constants will be inlined into other crates
|
// Reachable constants will be inlined into other crates
|
||||||
// unconditionally, so we need to make sure that their
|
// unconditionally, so we need to make sure that their
|
||||||
// contents are also reachable.
|
// contents are also reachable.
|
||||||
hir::ItemKind::Const(_, _, init) | hir::ItemKind::Static(_, _, init) => {
|
hir::ItemKind::Const(_, _, init) => {
|
||||||
self.visit_nested_body(init);
|
self.visit_nested_body(init);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reachable statics are inlined if read from another constant or static
|
||||||
|
// in other crates. Additionally anonymous nested statics may be created
|
||||||
|
// when evaluating a static, so preserve those, too.
|
||||||
|
hir::ItemKind::Static(_, _, init) => {
|
||||||
|
// FIXME(oli-obk): remove this body walking and instead walk the evaluated initializer
|
||||||
|
// to find nested items that end up in the final value instead of also marking symbols
|
||||||
|
// as reachable that are only needed for evaluation.
|
||||||
|
self.visit_nested_body(init);
|
||||||
|
if let Ok(alloc) = self.tcx.eval_static_initializer(item.owner_id.def_id) {
|
||||||
|
self.propagate_statics_from_alloc(item.owner_id.def_id, alloc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// These are normal, nothing reachable about these
|
// These are normal, nothing reachable about these
|
||||||
// inherently and their children are already in the
|
// inherently and their children are already in the
|
||||||
// worklist, as determined by the privacy pass
|
// worklist, as determined by the privacy pass
|
||||||
|
@ -266,6 +280,29 @@ impl<'tcx> ReachableContext<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Finds anonymous nested statics created for nested allocations and adds them to `reachable_symbols`.
|
||||||
|
fn propagate_statics_from_alloc(&mut self, root: LocalDefId, alloc: ConstAllocation<'tcx>) {
|
||||||
|
if !self.any_library {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (_, prov) in alloc.0.provenance().ptrs().iter() {
|
||||||
|
match self.tcx.global_alloc(prov.alloc_id()) {
|
||||||
|
GlobalAlloc::Static(def_id) => {
|
||||||
|
if let Some(def_id) = def_id.as_local()
|
||||||
|
&& self.tcx.local_parent(def_id) == root
|
||||||
|
// This is the main purpose of this function: add the def_id we find
|
||||||
|
// to `reachable_symbols`.
|
||||||
|
&& self.reachable_symbols.insert(def_id)
|
||||||
|
&& let Ok(alloc) = self.tcx.eval_static_initializer(def_id)
|
||||||
|
{
|
||||||
|
self.propagate_statics_from_alloc(root, alloc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GlobalAlloc::Function(_) | GlobalAlloc::VTable(_, _) | GlobalAlloc::Memory(_) => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_item<'tcx>(
|
fn check_item<'tcx>(
|
||||||
|
|
|
@ -549,7 +549,7 @@ impl<'tcx> EmbargoVisitor<'tcx> {
|
||||||
self.update(def_id, macro_ev, Level::Reachable);
|
self.update(def_id, macro_ev, Level::Reachable);
|
||||||
match def_kind {
|
match def_kind {
|
||||||
// No type privacy, so can be directly marked as reachable.
|
// No type privacy, so can be directly marked as reachable.
|
||||||
DefKind::Const | DefKind::Static(_) | DefKind::TraitAlias | DefKind::TyAlias => {
|
DefKind::Const | DefKind::Static { .. } | DefKind::TraitAlias | DefKind::TyAlias => {
|
||||||
if vis.is_accessible_from(module, self.tcx) {
|
if vis.is_accessible_from(module, self.tcx) {
|
||||||
self.update(def_id, macro_ev, Level::Reachable);
|
self.update(def_id, macro_ev, Level::Reachable);
|
||||||
}
|
}
|
||||||
|
@ -1170,12 +1170,12 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
|
||||||
let def = def.filter(|(kind, _)| {
|
let def = def.filter(|(kind, _)| {
|
||||||
matches!(
|
matches!(
|
||||||
kind,
|
kind,
|
||||||
DefKind::AssocFn | DefKind::AssocConst | DefKind::AssocTy | DefKind::Static(_)
|
DefKind::AssocFn | DefKind::AssocConst | DefKind::AssocTy | DefKind::Static { .. }
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
if let Some((kind, def_id)) = def {
|
if let Some((kind, def_id)) = def {
|
||||||
let is_local_static =
|
let is_local_static =
|
||||||
if let DefKind::Static(_) = kind { def_id.is_local() } else { false };
|
if let DefKind::Static { .. } = kind { def_id.is_local() } else { false };
|
||||||
if !self.item_is_accessible(def_id) && !is_local_static {
|
if !self.item_is_accessible(def_id) && !is_local_static {
|
||||||
let name = match *qpath {
|
let name = match *qpath {
|
||||||
hir::QPath::LangItem(it, ..) => {
|
hir::QPath::LangItem(it, ..) => {
|
||||||
|
@ -1496,7 +1496,7 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx, '_> {
|
||||||
let def_kind = tcx.def_kind(def_id);
|
let def_kind = tcx.def_kind(def_id);
|
||||||
|
|
||||||
match def_kind {
|
match def_kind {
|
||||||
DefKind::Const | DefKind::Static(_) | DefKind::Fn | DefKind::TyAlias => {
|
DefKind::Const | DefKind::Static { .. } | DefKind::Fn | DefKind::TyAlias => {
|
||||||
if let DefKind::TyAlias = def_kind {
|
if let DefKind::TyAlias = def_kind {
|
||||||
self.check_unnameable(def_id, effective_vis);
|
self.check_unnameable(def_id, effective_vis);
|
||||||
}
|
}
|
||||||
|
|
|
@ -990,7 +990,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
|
||||||
Res::Def(
|
Res::Def(
|
||||||
DefKind::Fn
|
DefKind::Fn
|
||||||
| DefKind::AssocFn
|
| DefKind::AssocFn
|
||||||
| DefKind::Static(_)
|
| DefKind::Static { .. }
|
||||||
| DefKind::Const
|
| DefKind::Const
|
||||||
| DefKind::AssocConst
|
| DefKind::AssocConst
|
||||||
| DefKind::Ctor(..),
|
| DefKind::Ctor(..),
|
||||||
|
|
|
@ -127,7 +127,7 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
|
||||||
ItemKind::Union(..) => DefKind::Union,
|
ItemKind::Union(..) => DefKind::Union,
|
||||||
ItemKind::ExternCrate(..) => DefKind::ExternCrate,
|
ItemKind::ExternCrate(..) => DefKind::ExternCrate,
|
||||||
ItemKind::TyAlias(..) => DefKind::TyAlias,
|
ItemKind::TyAlias(..) => DefKind::TyAlias,
|
||||||
ItemKind::Static(s) => DefKind::Static(s.mutability),
|
ItemKind::Static(s) => DefKind::Static { mutability: s.mutability, nested: false },
|
||||||
ItemKind::Const(..) => DefKind::Const,
|
ItemKind::Const(..) => DefKind::Const,
|
||||||
ItemKind::Fn(..) | ItemKind::Delegation(..) => DefKind::Fn,
|
ItemKind::Fn(..) | ItemKind::Delegation(..) => DefKind::Fn,
|
||||||
ItemKind::MacroDef(..) => {
|
ItemKind::MacroDef(..) => {
|
||||||
|
@ -214,7 +214,9 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
|
||||||
|
|
||||||
fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
|
fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
|
||||||
let def_kind = match fi.kind {
|
let def_kind = match fi.kind {
|
||||||
ForeignItemKind::Static(_, mt, _) => DefKind::Static(mt),
|
ForeignItemKind::Static(_, mutability, _) => {
|
||||||
|
DefKind::Static { mutability, nested: false }
|
||||||
|
}
|
||||||
ForeignItemKind::Fn(_) => DefKind::Fn,
|
ForeignItemKind::Fn(_) => DefKind::Fn,
|
||||||
ForeignItemKind::TyAlias(_) => DefKind::ForeignTy,
|
ForeignItemKind::TyAlias(_) => DefKind::ForeignTy,
|
||||||
ForeignItemKind::MacCall(_) => return self.visit_macro_invoc(fi.id),
|
ForeignItemKind::MacCall(_) => return self.visit_macro_invoc(fi.id),
|
||||||
|
|
|
@ -574,7 +574,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||||
ResolutionError::GenericParamsFromOuterItem(outer_res, has_generic_params, def_kind) => {
|
ResolutionError::GenericParamsFromOuterItem(outer_res, has_generic_params, def_kind) => {
|
||||||
use errs::GenericParamsFromOuterItemLabel as Label;
|
use errs::GenericParamsFromOuterItemLabel as Label;
|
||||||
let static_or_const = match def_kind {
|
let static_or_const = match def_kind {
|
||||||
DefKind::Static(_) => Some(errs::GenericParamsFromOuterItemStaticOrConst::Static),
|
DefKind::Static{ .. } => Some(errs::GenericParamsFromOuterItemStaticOrConst::Static),
|
||||||
DefKind::Const => Some(errs::GenericParamsFromOuterItemStaticOrConst::Const),
|
DefKind::Const => Some(errs::GenericParamsFromOuterItemStaticOrConst::Const),
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
|
|
|
@ -500,7 +500,7 @@ impl<'a> PathSource<'a> {
|
||||||
Res::Def(
|
Res::Def(
|
||||||
DefKind::Ctor(_, CtorKind::Const | CtorKind::Fn)
|
DefKind::Ctor(_, CtorKind::Const | CtorKind::Fn)
|
||||||
| DefKind::Const
|
| DefKind::Const
|
||||||
| DefKind::Static(_)
|
| DefKind::Static { .. }
|
||||||
| DefKind::Fn
|
| DefKind::Fn
|
||||||
| DefKind::AssocFn
|
| DefKind::AssocFn
|
||||||
| DefKind::AssocConst
|
| DefKind::AssocConst
|
||||||
|
@ -3645,7 +3645,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
||||||
}
|
}
|
||||||
Some(res)
|
Some(res)
|
||||||
}
|
}
|
||||||
Res::Def(DefKind::Ctor(..) | DefKind::Const | DefKind::Static(_), _) => {
|
Res::Def(DefKind::Ctor(..) | DefKind::Const | DefKind::Static { .. }, _) => {
|
||||||
// This is unambiguously a fresh binding, either syntactically
|
// This is unambiguously a fresh binding, either syntactically
|
||||||
// (e.g., `IDENT @ PAT` or `ref IDENT`) or because `IDENT` resolves
|
// (e.g., `IDENT @ PAT` or `ref IDENT`) or because `IDENT` resolves
|
||||||
// to something unusable as a pattern (e.g., constructor function),
|
// to something unusable as a pattern (e.g., constructor function),
|
||||||
|
|
|
@ -264,7 +264,7 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
|
||||||
use rustc_hir::def::DefKind;
|
use rustc_hir::def::DefKind;
|
||||||
match tcx.def_kind(def_id) {
|
match tcx.def_kind(def_id) {
|
||||||
DefKind::Fn => ForeignItemKind::Fn(tables.fn_def(def_id)),
|
DefKind::Fn => ForeignItemKind::Fn(tables.fn_def(def_id)),
|
||||||
DefKind::Static(..) => ForeignItemKind::Static(tables.static_def(def_id)),
|
DefKind::Static { .. } => ForeignItemKind::Static(tables.static_def(def_id)),
|
||||||
DefKind::ForeignTy => ForeignItemKind::Type(
|
DefKind::ForeignTy => ForeignItemKind::Type(
|
||||||
tables.intern_ty(rustc_middle::ty::Ty::new_foreign(tcx, def_id)),
|
tables.intern_ty(rustc_middle::ty::Ty::new_foreign(tcx, def_id)),
|
||||||
),
|
),
|
||||||
|
|
|
@ -95,7 +95,7 @@ pub(crate) fn new_item_kind(kind: DefKind) -> ItemKind {
|
||||||
DefKind::Const | DefKind::InlineConst | DefKind::AssocConst | DefKind::AnonConst => {
|
DefKind::Const | DefKind::InlineConst | DefKind::AssocConst | DefKind::AnonConst => {
|
||||||
ItemKind::Const
|
ItemKind::Const
|
||||||
}
|
}
|
||||||
DefKind::Static(_) => ItemKind::Static,
|
DefKind::Static { .. } => ItemKind::Static,
|
||||||
DefKind::Ctor(_, rustc_hir::def::CtorKind::Const) => ItemKind::Ctor(CtorKind::Const),
|
DefKind::Ctor(_, rustc_hir::def::CtorKind::Const) => ItemKind::Ctor(CtorKind::Const),
|
||||||
DefKind::Ctor(_, rustc_hir::def::CtorKind::Fn) => ItemKind::Ctor(CtorKind::Fn),
|
DefKind::Ctor(_, rustc_hir::def::CtorKind::Fn) => ItemKind::Ctor(CtorKind::Fn),
|
||||||
}
|
}
|
||||||
|
|
|
@ -1205,6 +1205,7 @@ symbols! {
|
||||||
negative_bounds,
|
negative_bounds,
|
||||||
negative_impls,
|
negative_impls,
|
||||||
neon,
|
neon,
|
||||||
|
nested,
|
||||||
never,
|
never,
|
||||||
never_patterns,
|
never_patterns,
|
||||||
never_type,
|
never_type,
|
||||||
|
|
|
@ -134,7 +134,7 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<'
|
||||||
| DefKind::TyParam
|
| DefKind::TyParam
|
||||||
| DefKind::Const
|
| DefKind::Const
|
||||||
| DefKind::ConstParam
|
| DefKind::ConstParam
|
||||||
| DefKind::Static(_)
|
| DefKind::Static { .. }
|
||||||
| DefKind::Ctor(_, _)
|
| DefKind::Ctor(_, _)
|
||||||
| DefKind::Macro(_)
|
| DefKind::Macro(_)
|
||||||
| DefKind::ExternCrate
|
| DefKind::ExternCrate
|
||||||
|
|
|
@ -318,7 +318,7 @@ fn opaque_types_defined_by<'tcx>(
|
||||||
match kind {
|
match kind {
|
||||||
DefKind::AssocFn
|
DefKind::AssocFn
|
||||||
| DefKind::Fn
|
| DefKind::Fn
|
||||||
| DefKind::Static(_)
|
| DefKind::Static { .. }
|
||||||
| DefKind::Const
|
| DefKind::Const
|
||||||
| DefKind::AssocConst
|
| DefKind::AssocConst
|
||||||
| DefKind::AnonConst => {
|
| DefKind::AnonConst => {
|
||||||
|
|
|
@ -43,7 +43,7 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>(
|
||||||
// Walk over the type behind the alias
|
// Walk over the type behind the alias
|
||||||
DefKind::TyAlias { .. } | DefKind::AssocTy |
|
DefKind::TyAlias { .. } | DefKind::AssocTy |
|
||||||
// Walk over the type of the item
|
// Walk over the type of the item
|
||||||
DefKind::Static(_) | DefKind::Const | DefKind::AssocConst | DefKind::AnonConst => {
|
DefKind::Static { .. } | DefKind::Const | DefKind::AssocConst | DefKind::AnonConst => {
|
||||||
if let Some(ty) = tcx.hir_node_by_def_id(item).ty() {
|
if let Some(ty) = tcx.hir_node_by_def_id(item).ty() {
|
||||||
// If the type of the item uses `_`, we're gonna error out anyway, but
|
// If the type of the item uses `_`, we're gonna error out anyway, but
|
||||||
// typeck (which type_of invokes below), will call back into opaque_types_defined_by
|
// typeck (which type_of invokes below), will call back into opaque_types_defined_by
|
||||||
|
|
|
@ -120,7 +120,7 @@ pub(crate) fn try_inline(
|
||||||
record_extern_fqn(cx, did, ItemType::Module);
|
record_extern_fqn(cx, did, ItemType::Module);
|
||||||
clean::ModuleItem(build_module(cx, did, visited))
|
clean::ModuleItem(build_module(cx, did, visited))
|
||||||
}
|
}
|
||||||
Res::Def(DefKind::Static(_), did) => {
|
Res::Def(DefKind::Static { .. }, did) => {
|
||||||
record_extern_fqn(cx, did, ItemType::Static);
|
record_extern_fqn(cx, did, ItemType::Static);
|
||||||
cx.with_param_env(did, |cx| {
|
cx.with_param_env(did, |cx| {
|
||||||
clean::StaticItem(build_static(cx, did, cx.tcx.is_mutable_static(did)))
|
clean::StaticItem(build_static(cx, did, cx.tcx.is_mutable_static(did)))
|
||||||
|
|
|
@ -526,7 +526,7 @@ pub(crate) fn register_res(cx: &mut DocContext<'_>, res: Res) -> DefId {
|
||||||
| Mod
|
| Mod
|
||||||
| ForeignTy
|
| ForeignTy
|
||||||
| Const
|
| Const
|
||||||
| Static(_)
|
| Static { .. }
|
||||||
| Macro(..)
|
| Macro(..)
|
||||||
| TraitAlias),
|
| TraitAlias),
|
||||||
did,
|
did,
|
||||||
|
|
|
@ -128,7 +128,7 @@ impl ItemType {
|
||||||
DefKind::Fn => Self::Function,
|
DefKind::Fn => Self::Function,
|
||||||
DefKind::Mod => Self::Module,
|
DefKind::Mod => Self::Module,
|
||||||
DefKind::Const => Self::Constant,
|
DefKind::Const => Self::Constant,
|
||||||
DefKind::Static(_) => Self::Static,
|
DefKind::Static { .. } => Self::Static,
|
||||||
DefKind::Struct => Self::Struct,
|
DefKind::Struct => Self::Struct,
|
||||||
DefKind::Union => Self::Union,
|
DefKind::Union => Self::Union,
|
||||||
DefKind::Trait => Self::Trait,
|
DefKind::Trait => Self::Trait,
|
||||||
|
|
|
@ -123,7 +123,7 @@ impl Res {
|
||||||
DefKind::Const | DefKind::ConstParam | DefKind::AssocConst | DefKind::AnonConst => {
|
DefKind::Const | DefKind::ConstParam | DefKind::AssocConst | DefKind::AnonConst => {
|
||||||
"const"
|
"const"
|
||||||
}
|
}
|
||||||
DefKind::Static(_) => "static",
|
DefKind::Static { .. } => "static",
|
||||||
// Now handle things that don't have a specific disambiguator
|
// Now handle things that don't have a specific disambiguator
|
||||||
_ => match kind
|
_ => match kind
|
||||||
.ns()
|
.ns()
|
||||||
|
@ -1514,7 +1514,7 @@ impl Disambiguator {
|
||||||
"union" => Kind(DefKind::Union),
|
"union" => Kind(DefKind::Union),
|
||||||
"module" | "mod" => Kind(DefKind::Mod),
|
"module" | "mod" => Kind(DefKind::Mod),
|
||||||
"const" | "constant" => Kind(DefKind::Const),
|
"const" | "constant" => Kind(DefKind::Const),
|
||||||
"static" => Kind(DefKind::Static(Mutability::Not)),
|
"static" => Kind(DefKind::Static { mutability: Mutability::Not, nested: false }),
|
||||||
"function" | "fn" | "method" => Kind(DefKind::Fn),
|
"function" | "fn" | "method" => Kind(DefKind::Fn),
|
||||||
"derive" => Kind(DefKind::Macro(MacroKind::Derive)),
|
"derive" => Kind(DefKind::Macro(MacroKind::Derive)),
|
||||||
"type" => NS(Namespace::TypeNS),
|
"type" => NS(Namespace::TypeNS),
|
||||||
|
@ -1926,7 +1926,7 @@ fn resolution_failure(
|
||||||
| OpaqueTy
|
| OpaqueTy
|
||||||
| TraitAlias
|
| TraitAlias
|
||||||
| TyParam
|
| TyParam
|
||||||
| Static(_) => "associated item",
|
| Static { .. } => "associated item",
|
||||||
Impl { .. } | GlobalAsm => unreachable!("not a path"),
|
Impl { .. } | GlobalAsm => unreachable!("not a path"),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -273,7 +273,7 @@ impl<'a, 'tcx> VarVisitor<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
return false; // no need to walk further *on the variable*
|
return false; // no need to walk further *on the variable*
|
||||||
},
|
},
|
||||||
Res::Def(DefKind::Static(_) | DefKind::Const, ..) => {
|
Res::Def(DefKind::Static{..} | DefKind::Const, ..) => {
|
||||||
if index_used_directly {
|
if index_used_directly {
|
||||||
self.indexed_directly.insert(
|
self.indexed_directly.insert(
|
||||||
seqvar.segments[0].ident.name,
|
seqvar.segments[0].ident.name,
|
||||||
|
|
|
@ -101,7 +101,7 @@ impl<'a, 'tcx> VarCollectorVisitor<'a, 'tcx> {
|
||||||
Res::Local(hir_id) => {
|
Res::Local(hir_id) => {
|
||||||
self.ids.insert(hir_id);
|
self.ids.insert(hir_id);
|
||||||
},
|
},
|
||||||
Res::Def(DefKind::Static(_), def_id) => {
|
Res::Def(DefKind::Static{..}, def_id) => {
|
||||||
let mutable = self.cx.tcx.is_mutable_static(def_id);
|
let mutable = self.cx.tcx.is_mutable_static(def_id);
|
||||||
self.def_ids.insert(def_id, mutable);
|
self.def_ids.insert(def_id, mutable);
|
||||||
},
|
},
|
||||||
|
|
|
@ -91,7 +91,7 @@ pub(super) fn check<'tcx>(
|
||||||
},
|
},
|
||||||
hir::ExprKind::Path(ref p) => matches!(
|
hir::ExprKind::Path(ref p) => matches!(
|
||||||
cx.qpath_res(p, arg.hir_id),
|
cx.qpath_res(p, arg.hir_id),
|
||||||
hir::def::Res::Def(hir::def::DefKind::Const | hir::def::DefKind::Static(_), _)
|
hir::def::Res::Def(hir::def::DefKind::Const | hir::def::DefKind::Static{..}, _)
|
||||||
),
|
),
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,7 +109,7 @@ fn collect_unsafe_exprs<'tcx>(
|
||||||
ExprKind::Path(QPath::Resolved(
|
ExprKind::Path(QPath::Resolved(
|
||||||
_,
|
_,
|
||||||
hir::Path {
|
hir::Path {
|
||||||
res: Res::Def(DefKind::Static(Mutability::Mut), _),
|
res: Res::Def(DefKind::Static{mutability:Mutability::Mut, ..}, _),
|
||||||
..
|
..
|
||||||
},
|
},
|
||||||
)) => {
|
)) => {
|
||||||
|
@ -149,7 +149,7 @@ fn collect_unsafe_exprs<'tcx>(
|
||||||
ExprKind::Path(QPath::Resolved(
|
ExprKind::Path(QPath::Resolved(
|
||||||
_,
|
_,
|
||||||
hir::Path {
|
hir::Path {
|
||||||
res: Res::Def(DefKind::Static(Mutability::Mut), _),
|
res: Res::Def(DefKind::Static{mutability:Mutability::Mut, ..}, _),
|
||||||
..
|
..
|
||||||
}
|
}
|
||||||
))
|
))
|
||||||
|
|
23
tests/ui/consts/auxiliary/const_mut_refs_crate.rs
Normal file
23
tests/ui/consts/auxiliary/const_mut_refs_crate.rs
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
// This is a support file for ../const-mut-refs-crate.rs
|
||||||
|
|
||||||
|
// This is to test that static inners from an external
|
||||||
|
// crate like this one, still preserves the alloc.
|
||||||
|
// That is, the address from the standpoint of rustc+llvm
|
||||||
|
// is the same.
|
||||||
|
// The need for this test originated from the GH issue
|
||||||
|
// https://github.com/rust-lang/rust/issues/57349
|
||||||
|
|
||||||
|
// See also ../const-mut-refs-crate.rs for more details
|
||||||
|
// about this test.
|
||||||
|
|
||||||
|
#![feature(const_mut_refs)]
|
||||||
|
|
||||||
|
// if we used immutable references here, then promotion would
|
||||||
|
// turn the `&42` into a promoted, which gets duplicated arbitrarily.
|
||||||
|
pub static mut FOO: &'static mut i32 = &mut 42;
|
||||||
|
pub static mut BAR: &'static mut i32 = unsafe { FOO };
|
||||||
|
|
||||||
|
pub mod inner {
|
||||||
|
pub static INNER_MOD_FOO: &'static i32 = &43;
|
||||||
|
pub static INNER_MOD_BAR: &'static i32 = INNER_MOD_FOO;
|
||||||
|
}
|
37
tests/ui/consts/const-mut-refs-crate.rs
Normal file
37
tests/ui/consts/const-mut-refs-crate.rs
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
//@ run-pass
|
||||||
|
//@ aux-build:const_mut_refs_crate.rs
|
||||||
|
|
||||||
|
#![feature(const_mut_refs)]
|
||||||
|
|
||||||
|
//! Regression test for https://github.com/rust-lang/rust/issues/79738
|
||||||
|
//! Show how we are not duplicating allocations anymore. Statics that
|
||||||
|
//! copy their value from another static used to also duplicate
|
||||||
|
//! memory behind references.
|
||||||
|
|
||||||
|
extern crate const_mut_refs_crate as other;
|
||||||
|
|
||||||
|
use other::{
|
||||||
|
inner::{INNER_MOD_BAR, INNER_MOD_FOO},
|
||||||
|
BAR, FOO,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub static LOCAL_FOO: &'static i32 = &41;
|
||||||
|
pub static LOCAL_BAR: &'static i32 = LOCAL_FOO;
|
||||||
|
pub static mut COPY_OF_REMOTE_FOO: &'static mut i32 = unsafe { FOO };
|
||||||
|
|
||||||
|
static DOUBLE_REF: &&i32 = &&99;
|
||||||
|
static ONE_STEP_ABOVE: &i32 = *DOUBLE_REF;
|
||||||
|
static mut DOUBLE_REF_MUT: &mut &mut i32 = &mut &mut 99;
|
||||||
|
static mut ONE_STEP_ABOVE_MUT: &mut i32 = unsafe { *DOUBLE_REF_MUT };
|
||||||
|
|
||||||
|
pub fn main() {
|
||||||
|
unsafe {
|
||||||
|
assert_eq!(FOO as *const i32, BAR as *const i32);
|
||||||
|
assert_eq!(INNER_MOD_FOO as *const i32, INNER_MOD_BAR as *const i32);
|
||||||
|
assert_eq!(LOCAL_FOO as *const i32, LOCAL_BAR as *const i32);
|
||||||
|
assert_eq!(*DOUBLE_REF as *const i32, ONE_STEP_ABOVE as *const i32);
|
||||||
|
assert_eq!(*DOUBLE_REF_MUT as *mut i32, ONE_STEP_ABOVE_MUT as *mut i32);
|
||||||
|
|
||||||
|
assert_eq!(FOO as *const i32, COPY_OF_REMOTE_FOO as *const i32);
|
||||||
|
}
|
||||||
|
}
|
24
tests/ui/statics/nested_struct.rs
Normal file
24
tests/ui/statics/nested_struct.rs
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
//@ check-pass
|
||||||
|
/// oli-obk added this test after messing up the interner logic
|
||||||
|
/// around mutability of nested allocations. This was not caught
|
||||||
|
/// by the test suite, but by trying to build stage2 rustc.
|
||||||
|
/// There is no real explanation for this test, as it was just
|
||||||
|
/// a bug during a refactoring.
|
||||||
|
|
||||||
|
pub struct Lint {
|
||||||
|
pub name: &'static str,
|
||||||
|
pub desc: &'static str,
|
||||||
|
pub report_in_external_macro: bool,
|
||||||
|
pub is_loaded: bool,
|
||||||
|
pub crate_level_only: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
static FOO: &Lint = &Lint {
|
||||||
|
name: &"foo",
|
||||||
|
desc: "desc",
|
||||||
|
report_in_external_macro: false,
|
||||||
|
is_loaded: true,
|
||||||
|
crate_level_only: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
fn main() {}
|
Loading…
Add table
Add a link
Reference in a new issue