diff --git a/RELEASES.md b/RELEASES.md
index 2da6ed3f10060..e0175db7ec881 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -1,3 +1,18 @@
+Version 1.84.1 (2025-01-30)
+==========================
+
+
+
+- [Fix ICE 132920 in duplicate-crate diagnostics.](https://github.com/rust-lang/rust/pull/133304/)
+- [Fix errors for overlapping impls in incremental rebuilds.](https://github.com/rust-lang/rust/pull/133828/)
+- [Fix slow compilation related to the next-generation trait solver.](https://github.com/rust-lang/rust/pull/135618/)
+- [Fix debuginfo when LLVM's location discriminator value limit is exceeded.](https://github.com/rust-lang/rust/pull/135643/)
+- Fixes for building Rust from source:
+ - [Only try to distribute `llvm-objcopy` if llvm tools are enabled.](https://github.com/rust-lang/rust/pull/134240/)
+ - [Add Profile Override for Non-Git Sources.](https://github.com/rust-lang/rust/pull/135433/)
+ - [Resolve symlinks of LLVM tool binaries before copying them.](https://github.com/rust-lang/rust/pull/135585/)
+ - [Make it possible to use ci-rustc on tarball sources.](https://github.com/rust-lang/rust/pull/135722/)
+
Version 1.84.0 (2025-01-09)
==========================
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
index 6d71b8e8abab4..d682efd19aaa5 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
@@ -129,12 +129,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
return;
}
- let idx = generic_args[2]
- .expect_const()
- .try_to_valtree()
- .expect("expected monomorphic const in codegen")
- .0
- .unwrap_branch();
+ let idx = generic_args[2].expect_const().to_value().valtree.unwrap_branch();
assert_eq!(x.layout(), y.layout());
let layout = x.layout();
diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs
index d2de62b17f04d..2d007416263fa 100644
--- a/compiler/rustc_codegen_llvm/src/builder.rs
+++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -1325,7 +1325,9 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
impl<'ll> StaticBuilderMethods for Builder<'_, 'll, '_> {
fn get_static(&mut self, def_id: DefId) -> &'ll Value {
// Forward to the `get_static` method of `CodegenCx`
- self.cx().get_static(def_id)
+ let s = self.cx().get_static(def_id);
+ // Cast to default address space if globals are in a different addrspace
+ self.cx().const_pointercast(s, self.type_ptr())
}
}
diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs
index b4e9b9f44f4ab..f8b30cb507a23 100644
--- a/compiler/rustc_codegen_llvm/src/common.rs
+++ b/compiler/rustc_codegen_llvm/src/common.rs
@@ -225,6 +225,8 @@ impl<'ll, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
llvm::LLVMSetUnnamedAddress(g, llvm::UnnamedAddr::Global);
}
llvm::set_linkage(g, llvm::Linkage::InternalLinkage);
+ // Cast to default address space if globals are in a different addrspace
+ let g = self.const_pointercast(g, self.type_ptr());
(s.to_owned(), g)
})
.1;
@@ -289,7 +291,7 @@ impl<'ll, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
let alloc = alloc.inner();
let value = match alloc.mutability {
Mutability::Mut => self.static_addr_of_mut(init, alloc.align, None),
- _ => self.static_addr_of(init, alloc.align, None),
+ _ => self.static_addr_of_impl(init, alloc.align, None),
};
if !self.sess().fewer_names() && llvm::get_value_name(value).is_empty()
{
@@ -315,7 +317,7 @@ impl<'ll, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
.global_alloc(self.tcx.vtable_allocation((ty, dyn_ty.principal())))
.unwrap_memory();
let init = const_alloc_to_llvm(self, alloc, /*static*/ false);
- let value = self.static_addr_of(init, alloc.inner().align, None);
+ let value = self.static_addr_of_impl(init, alloc.inner().align, None);
(value, AddressSpace::DATA)
}
GlobalAlloc::Static(def_id) => {
@@ -327,7 +329,8 @@ impl<'ll, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
let llval = unsafe {
llvm::LLVMConstInBoundsGEP2(
self.type_i8(),
- self.const_bitcast(base_addr, self.type_ptr_ext(base_addr_space)),
+ // Cast to the required address space if necessary
+ self.const_pointercast(base_addr, self.type_ptr_ext(base_addr_space)),
&self.const_usize(offset.bytes()),
1,
)
diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs
index c7114480d8bdf..771ebf2057f9a 100644
--- a/compiler/rustc_codegen_llvm/src/consts.rs
+++ b/compiler/rustc_codegen_llvm/src/consts.rs
@@ -210,6 +210,14 @@ impl<'ll> CodegenCx<'ll, '_> {
unsafe { llvm::LLVMConstBitCast(val, ty) }
}
+ pub(crate) fn const_pointercast(&self, val: &'ll Value, ty: &'ll Type) -> &'ll Value {
+ unsafe { llvm::LLVMConstPointerCast(val, ty) }
+ }
+
+ /// Create a global variable.
+ ///
+ /// The returned global variable is a pointer in the default address space for globals.
+ /// Fails if a symbol with the given name already exists.
pub(crate) fn static_addr_of_mut(
&self,
cv: &'ll Value,
@@ -233,6 +241,34 @@ impl<'ll> CodegenCx<'ll, '_> {
gv
}
+ /// Create a global constant.
+ ///
+ /// The returned global variable is a pointer in the default address space for globals.
+ pub(crate) fn static_addr_of_impl(
+ &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
+ }
+
#[instrument(level = "debug", skip(self))]
pub(crate) fn get_static(&self, def_id: DefId) -> &'ll Value {
let instance = Instance::mono(self.tcx, def_id);
@@ -505,24 +541,15 @@ impl<'ll> CodegenCx<'ll, '_> {
}
impl<'ll> StaticCodegenMethods for CodegenCx<'ll, '_> {
+ /// Get a pointer to a global variable.
+ ///
+ /// The pointer will always be in the default address space. If global variables default to a
+ /// different address space, an addrspacecast is inserted.
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
+ let gv = self.static_addr_of_impl(cv, align, kind);
+ // static_addr_of_impl returns the bare global variable, which might not be in the default
+ // address space. Cast to the default address space if necessary.
+ self.const_pointercast(gv, self.type_ptr())
}
fn codegen_static(&self, def_id: DefId) {
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
index 8d782a618fc07..d7b42481e1aa1 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
@@ -1488,6 +1488,26 @@ fn build_vtable_type_di_node<'ll, 'tcx>(
.di_node
}
+/// Get the global variable for the vtable.
+///
+/// When using global variables, we may have created an addrspacecast to get a pointer to the
+/// default address space if global variables are created in a different address space.
+/// For modifying the vtable, we need the real global variable. This function accepts either a
+/// global variable (which is simply returned), or an addrspacecast constant expression.
+/// If the given value is an addrspacecast, the cast is removed and the global variable behind
+/// the cast is returned.
+fn find_vtable_behind_cast<'ll>(vtable: &'ll Value) -> &'ll Value {
+ // The vtable is a global variable, which may be behind an addrspacecast.
+ unsafe {
+ if let Some(c) = llvm::LLVMIsAConstantExpr(vtable) {
+ if llvm::LLVMGetConstOpcode(c) == llvm::Opcode::AddrSpaceCast {
+ return llvm::LLVMGetOperand(c, 0).unwrap();
+ }
+ }
+ }
+ vtable
+}
+
pub(crate) fn apply_vcall_visibility_metadata<'ll, 'tcx>(
cx: &CodegenCx<'ll, 'tcx>,
ty: Ty<'tcx>,
@@ -1508,6 +1528,8 @@ pub(crate) fn apply_vcall_visibility_metadata<'ll, 'tcx>(
let Some(trait_ref) = trait_ref else { return };
+ // Unwrap potential addrspacecast
+ let vtable = find_vtable_behind_cast(vtable);
let trait_ref_self = trait_ref.with_self_ty(cx.tcx, ty);
let trait_ref_self = cx.tcx.erase_regions(trait_ref_self);
let trait_def_id = trait_ref_self.def_id();
@@ -1581,6 +1603,9 @@ pub(crate) fn create_vtable_di_node<'ll, 'tcx>(
return;
}
+ // Unwrap potential addrspacecast
+ let vtable = find_vtable_behind_cast(vtable);
+
// When full debuginfo is enabled, we want to try and prevent vtables from being
// merged. Otherwise debuggers will have a hard time mapping from dyn pointer
// to concrete type.
diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs
index eab4a9f30c9dc..43d6ccfcb4a28 100644
--- a/compiler/rustc_codegen_llvm/src/intrinsic.rs
+++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs
@@ -1329,7 +1329,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
}
if name == sym::simd_shuffle_generic {
- let idx = fn_args[2].expect_const().try_to_valtree().unwrap().0.unwrap_branch();
+ let idx = fn_args[2].expect_const().to_value().valtree.unwrap_branch();
let n = idx.len() as u64;
let (out_len, out_ty) = require_simd!(ret_ty, SimdReturn);
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index 009d15a932f7a..cc7c5231aca58 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -661,6 +661,79 @@ pub enum MemoryEffects {
InaccessibleMemOnly,
}
+/// LLVMOpcode
+#[derive(Copy, Clone, PartialEq, Eq)]
+#[repr(C)]
+pub enum Opcode {
+ Ret = 1,
+ Br = 2,
+ Switch = 3,
+ IndirectBr = 4,
+ Invoke = 5,
+ Unreachable = 7,
+ CallBr = 67,
+ FNeg = 66,
+ Add = 8,
+ FAdd = 9,
+ Sub = 10,
+ FSub = 11,
+ Mul = 12,
+ FMul = 13,
+ UDiv = 14,
+ SDiv = 15,
+ FDiv = 16,
+ URem = 17,
+ SRem = 18,
+ FRem = 19,
+ Shl = 20,
+ LShr = 21,
+ AShr = 22,
+ And = 23,
+ Or = 24,
+ Xor = 25,
+ Alloca = 26,
+ Load = 27,
+ Store = 28,
+ GetElementPtr = 29,
+ Trunc = 30,
+ ZExt = 31,
+ SExt = 32,
+ FPToUI = 33,
+ FPToSI = 34,
+ UIToFP = 35,
+ SIToFP = 36,
+ FPTrunc = 37,
+ FPExt = 38,
+ PtrToInt = 39,
+ IntToPtr = 40,
+ BitCast = 41,
+ AddrSpaceCast = 60,
+ ICmp = 42,
+ FCmp = 43,
+ PHI = 44,
+ Call = 45,
+ Select = 46,
+ UserOp1 = 47,
+ UserOp2 = 48,
+ VAArg = 49,
+ ExtractElement = 50,
+ InsertElement = 51,
+ ShuffleVector = 52,
+ ExtractValue = 53,
+ InsertValue = 54,
+ Freeze = 68,
+ Fence = 55,
+ AtomicCmpXchg = 56,
+ AtomicRMW = 57,
+ Resume = 58,
+ LandingPad = 59,
+ CleanupRet = 61,
+ CatchRet = 62,
+ CatchPad = 63,
+ CleanupPad = 64,
+ CatchSwitch = 65,
+}
+
unsafe extern "C" {
type Opaque;
}
@@ -991,7 +1064,10 @@ unsafe extern "C" {
pub fn LLVMConstPtrToInt<'a>(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value;
pub fn LLVMConstIntToPtr<'a>(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value;
pub fn LLVMConstBitCast<'a>(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value;
+ pub fn LLVMConstPointerCast<'a>(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value;
pub fn LLVMGetAggregateElement(ConstantVal: &Value, Idx: c_uint) -> Option<&Value>;
+ pub fn LLVMGetConstOpcode(ConstantVal: &Value) -> Opcode;
+ pub fn LLVMIsAConstantExpr(Val: &Value) -> Option<&Value>;
// Operations on global variables, functions, and aliases (globals)
pub fn LLVMIsDeclaration(Global: &Value) -> Bool;
@@ -1048,6 +1124,7 @@ unsafe extern "C" {
// Operations on instructions
pub fn LLVMIsAInstruction(Val: &Value) -> Option<&Value>;
pub fn LLVMGetFirstBasicBlock(Fn: &Value) -> &BasicBlock;
+ pub fn LLVMGetOperand(Val: &Value, Index: c_uint) -> Option<&Value>;
// Operations on call sites
pub fn LLVMSetInstructionCallConv(Instr: &Value, CC: c_uint);
diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
index 869798d8be194..d766ae37e5b34 100644
--- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
+++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
@@ -673,25 +673,23 @@ fn push_const_param<'tcx>(tcx: TyCtxt<'tcx>, ct: ty::Const<'tcx>, output: &mut S
ty::ConstKind::Param(param) => {
write!(output, "{}", param.name)
}
- ty::ConstKind::Value(ty, valtree) => {
- match ty.kind() {
+ ty::ConstKind::Value(cv) => {
+ match cv.ty.kind() {
ty::Int(ity) => {
- // FIXME: directly extract the bits from a valtree instead of evaluating an
- // already evaluated `Const` in order to get the bits.
- let bits = ct
+ let bits = cv
.try_to_bits(tcx, ty::TypingEnv::fully_monomorphized())
.expect("expected monomorphic const in codegen");
let val = Integer::from_int_ty(&tcx, *ity).size().sign_extend(bits) as i128;
write!(output, "{val}")
}
ty::Uint(_) => {
- let val = ct
+ let val = cv
.try_to_bits(tcx, ty::TypingEnv::fully_monomorphized())
.expect("expected monomorphic const in codegen");
write!(output, "{val}")
}
ty::Bool => {
- let val = ct.try_to_bool().expect("expected monomorphic const in codegen");
+ let val = cv.try_to_bool().expect("expected monomorphic const in codegen");
write!(output, "{val}")
}
_ => {
@@ -703,9 +701,7 @@ fn push_const_param<'tcx>(tcx: TyCtxt<'tcx>, ct: ty::Const<'tcx>, output: &mut S
// avoiding collisions and will make the emitted type names shorter.
let hash_short = tcx.with_stable_hashing_context(|mut hcx| {
let mut hasher = StableHasher::new();
- hcx.while_hashing_spans(false, |hcx| {
- (ty, valtree).hash_stable(hcx, &mut hasher)
- });
+ hcx.while_hashing_spans(false, |hcx| cv.hash_stable(hcx, &mut hasher));
hasher.finish::()
});
diff --git a/compiler/rustc_codegen_ssa/src/mir/constant.rs b/compiler/rustc_codegen_ssa/src/mir/constant.rs
index 7676e1e171aac..eafc551501c13 100644
--- a/compiler/rustc_codegen_ssa/src/mir/constant.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/constant.rs
@@ -43,7 +43,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
mir::Const::Ty(_, c) => match c.kind() {
// A constant that came from a const generic but was then used as an argument to
// old-style simd_shuffle (passing as argument instead of as a generic param).
- rustc_type_ir::ConstKind::Value(_, valtree) => return Ok(Ok(valtree)),
+ rustc_type_ir::ConstKind::Value(cv) => return Ok(Ok(cv.valtree)),
other => span_bug!(constant.span, "{other:#?}"),
},
// We should never encounter `Const::Val` unless MIR opts (like const prop) evaluate
diff --git a/compiler/rustc_const_eval/src/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/check_consts/qualifs.rs
index e244b50a4b5d9..5d368b600a024 100644
--- a/compiler/rustc_const_eval/src/check_consts/qualifs.rs
+++ b/compiler/rustc_const_eval/src/check_consts/qualifs.rs
@@ -345,7 +345,7 @@ where
Const::Ty(_, ct)
if matches!(
ct.kind(),
- ty::ConstKind::Param(_) | ty::ConstKind::Error(_) | ty::ConstKind::Value(_, _)
+ ty::ConstKind::Param(_) | ty::ConstKind::Error(_) | ty::ConstKind::Value(_)
) =>
{
None
diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs
index 4ff8aa9a3b418..4d625f76aba2a 100644
--- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs
+++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs
@@ -272,7 +272,8 @@ pub(crate) fn eval_to_valtree<'tcx>(
/// Converts a `ValTree` to a `ConstValue`, which is needed after mir
/// construction has finished.
-// FIXME Merge `valtree_to_const_value` and `valtree_into_mplace` into one function
+// FIXME(valtrees): Merge `valtree_to_const_value` and `valtree_into_mplace` into one function
+// FIXME(valtrees): Accept `ty::Value` instead of `Ty` and `ty::ValTree` separately.
#[instrument(skip(tcx), level = "debug", ret)]
pub fn valtree_to_const_value<'tcx>(
tcx: TyCtxt<'tcx>,
diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs
index b5adf06b30018..ecf9745b77945 100644
--- a/compiler/rustc_const_eval/src/lib.rs
+++ b/compiler/rustc_const_eval/src/lib.rs
@@ -46,8 +46,13 @@ pub fn provide(providers: &mut Providers) {
};
providers.hooks.try_destructure_mir_constant_for_user_output =
const_eval::try_destructure_mir_constant_for_user_output;
- providers.valtree_to_const_val = |tcx, (ty, valtree)| {
- const_eval::valtree_to_const_value(tcx, ty::TypingEnv::fully_monomorphized(), ty, valtree)
+ providers.valtree_to_const_val = |tcx, cv| {
+ const_eval::valtree_to_const_value(
+ tcx,
+ ty::TypingEnv::fully_monomorphized(),
+ cv.ty,
+ cv.valtree,
+ )
};
providers.check_validity_requirement = |tcx, (init_kind, param_env_and_ty)| {
util::check_validity_requirement(tcx, init_kind, param_env_and_ty)
diff --git a/compiler/rustc_infer/src/infer/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs
index 28eac5b7496dd..74c8b463fc899 100644
--- a/compiler/rustc_infer/src/infer/freshen.rs
+++ b/compiler/rustc_infer/src/infer/freshen.rs
@@ -170,7 +170,7 @@ impl<'a, 'tcx> TypeFolder> for TypeFreshener<'a, 'tcx> {
}
ty::ConstKind::Param(_)
- | ty::ConstKind::Value(_, _)
+ | ty::ConstKind::Value(_)
| ty::ConstKind::Unevaluated(..)
| ty::ConstKind::Expr(..)
| ty::ConstKind::Error(_) => ct.super_fold_with(self),
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 283ebdfa236be..515c9c3409856 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -1055,7 +1055,7 @@ impl<'tcx> InferCtxt<'tcx> {
| ty::ConstKind::Bound(_, _)
| ty::ConstKind::Placeholder(_)
| ty::ConstKind::Unevaluated(_)
- | ty::ConstKind::Value(_, _)
+ | ty::ConstKind::Value(_)
| ty::ConstKind::Error(_)
| ty::ConstKind::Expr(_) => ct,
}
diff --git a/compiler/rustc_middle/src/mir/consts.rs b/compiler/rustc_middle/src/mir/consts.rs
index 66d97fda43332..923160cc0cc85 100644
--- a/compiler/rustc_middle/src/mir/consts.rs
+++ b/compiler/rustc_middle/src/mir/consts.rs
@@ -250,7 +250,7 @@ impl<'tcx> Const<'tcx> {
// Dont use the outer ty as on invalid code we can wind up with them not being the same.
// this then results in allowing const eval to add `1_i64 + 1_usize` in cases where the mir
// was originally `({N: usize} + 1_usize)` under `generic_const_exprs`.
- ty::ConstKind::Value(ty, _) => ty,
+ ty::ConstKind::Value(cv) => cv.ty,
_ => *ty,
}
}
@@ -264,7 +264,7 @@ impl<'tcx> Const<'tcx> {
pub fn is_required_const(&self) -> bool {
match self {
Const::Ty(_, c) => match c.kind() {
- ty::ConstKind::Value(_, _) => false, // already a value, cannot error
+ ty::ConstKind::Value(_) => false, // already a value, cannot error
_ => true,
},
Const::Val(..) => false, // already a value, cannot error
@@ -276,11 +276,11 @@ impl<'tcx> Const<'tcx> {
pub fn try_to_scalar(self) -> Option {
match self {
Const::Ty(_, c) => match c.kind() {
- ty::ConstKind::Value(ty, valtree) if ty.is_primitive() => {
+ ty::ConstKind::Value(cv) if cv.ty.is_primitive() => {
// A valtree of a type where leaves directly represent the scalar const value.
// Just checking whether it is a leaf is insufficient as e.g. references are leafs
// but the leaf value is the value they point to, not the reference itself!
- Some(valtree.unwrap_leaf().into())
+ Some(cv.valtree.unwrap_leaf().into())
}
_ => None,
},
@@ -295,9 +295,7 @@ impl<'tcx> Const<'tcx> {
match self {
Const::Val(ConstValue::Scalar(Scalar::Int(x)), _) => Some(x),
Const::Ty(_, c) => match c.kind() {
- ty::ConstKind::Value(ty, valtree) if ty.is_primitive() => {
- Some(valtree.unwrap_leaf())
- }
+ ty::ConstKind::Value(cv) if cv.ty.is_primitive() => Some(cv.valtree.unwrap_leaf()),
_ => None,
},
_ => None,
@@ -328,7 +326,7 @@ impl<'tcx> Const<'tcx> {
}
match c.kind() {
- ConstKind::Value(ty, val) => Ok(tcx.valtree_to_const_val((ty, val))),
+ ConstKind::Value(cv) => Ok(tcx.valtree_to_const_val(cv)),
ConstKind::Expr(_) => {
bug!("Normalization of `ty::ConstKind::Expr` is unimplemented")
}
@@ -353,13 +351,13 @@ impl<'tcx> Const<'tcx> {
typing_env: ty::TypingEnv<'tcx>,
) -> Option {
if let Const::Ty(_, c) = self
- && let ty::ConstKind::Value(ty, val) = c.kind()
- && ty.is_primitive()
+ && let ty::ConstKind::Value(cv) = c.kind()
+ && cv.ty.is_primitive()
{
// Avoid the `valtree_to_const_val` query. Can only be done on primitive types that
// are valtree leaves, and *not* on references. (References should return the
// pointer here, which valtrees don't represent.)
- Some(val.unwrap_leaf().into())
+ Some(cv.valtree.unwrap_leaf().into())
} else {
self.eval(tcx, typing_env, DUMMY_SP).ok()?.try_to_scalar()
}
@@ -473,7 +471,7 @@ impl<'tcx> Const<'tcx> {
// A valtree may be a reference. Valtree references correspond to a
// different allocation each time they are evaluated. Valtrees for primitive
// types are fine though.
- ty::ConstKind::Value(ty, _) => ty.is_primitive(),
+ ty::ConstKind::Value(cv) => cv.ty.is_primitive(),
ty::ConstKind::Unevaluated(..) | ty::ConstKind::Expr(..) => false,
// This can happen if evaluation of a constant failed. The result does not matter
// much since compilation is doomed.
diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs
index 3b4fba97e60b9..a318bacb866d1 100644
--- a/compiler/rustc_middle/src/mir/pretty.rs
+++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -1441,7 +1441,9 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> {
ty::ConstKind::Unevaluated(uv) => {
format!("ty::Unevaluated({}, {:?})", self.tcx.def_path_str(uv.def), uv.args,)
}
- ty::ConstKind::Value(_, val) => format!("ty::Valtree({})", fmt_valtree(&val)),
+ ty::ConstKind::Value(cv) => {
+ format!("ty::Valtree({})", fmt_valtree(&cv.valtree))
+ }
// No `ty::` prefix since we also use this to represent errors from `mir::Unevaluated`.
ty::ConstKind::Error(_) => "Error".to_string(),
// These variants shouldn't exist in the MIR.
diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs
index e243425c0b7ba..f7090fa69e2ed 100644
--- a/compiler/rustc_middle/src/query/keys.rs
+++ b/compiler/rustc_middle/src/query/keys.rs
@@ -550,7 +550,7 @@ impl<'tcx> Key for (ty::Instance<'tcx>, &'tcx ty::List>) {
}
}
-impl<'tcx> Key for (Ty<'tcx>, ty::ValTree<'tcx>) {
+impl<'tcx> Key for ty::Value<'tcx> {
type Cache = DefaultCache;
fn default_span(&self, _: TyCtxt<'_>) -> Span {
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index d83bc19a6a2f5..560e3bf3adeb2 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -1256,9 +1256,9 @@ rustc_queries! {
desc { "evaluating type-level constant" }
}
- /// Converts a type level constant value into `ConstValue`
- query valtree_to_const_val(key: (Ty<'tcx>, ty::ValTree<'tcx>)) -> mir::ConstValue<'tcx> {
- desc { "converting type-level constant value to mir constant value"}
+ /// Converts a type-level constant value into a MIR constant value.
+ query valtree_to_const_val(key: ty::Value<'tcx>) -> mir::ConstValue<'tcx> {
+ desc { "converting type-level constant value to MIR constant value"}
}
/// Destructures array, ADT or tuple constants into the constants
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index 310552764224e..d77fb1cc91e82 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -5,7 +5,6 @@ use rustc_error_messages::MultiSpan;
use rustc_macros::HashStable;
use rustc_type_ir::{self as ir, TypeFlags, WithCachedTypeInfo};
-use crate::mir::interpret::Scalar;
use crate::ty::{self, Ty, TyCtxt};
mod int;
@@ -110,8 +109,8 @@ impl<'tcx> Const<'tcx> {
}
#[inline]
- pub fn new_value(tcx: TyCtxt<'tcx>, val: ty::ValTree<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> {
- Const::new(tcx, ty::ConstKind::Value(ty, val))
+ pub fn new_value(tcx: TyCtxt<'tcx>, valtree: ty::ValTree<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> {
+ Const::new(tcx, ty::ConstKind::Value(ty::Value { ty, valtree }))
}
#[inline]
@@ -214,47 +213,31 @@ impl<'tcx> Const<'tcx> {
Self::from_bits(tcx, n as u128, ty::TypingEnv::fully_monomorphized(), tcx.types.usize)
}
- /// Panics if self.kind != ty::ConstKind::Value
- pub fn to_valtree(self) -> (ty::ValTree<'tcx>, Ty<'tcx>) {
+ /// Panics if `self.kind != ty::ConstKind::Value`.
+ pub fn to_value(self) -> ty::Value<'tcx> {
match self.kind() {
- ty::ConstKind::Value(ty, valtree) => (valtree, ty),
+ ty::ConstKind::Value(cv) => cv,
_ => bug!("expected ConstKind::Value, got {:?}", self.kind()),
}
}
- /// Attempts to convert to a `ValTree`
- pub fn try_to_valtree(self) -> Option<(ty::ValTree<'tcx>, Ty<'tcx>)> {
+ /// Attempts to convert to a value.
+ ///
+ /// Note that this does not evaluate the constant.
+ pub fn try_to_value(self) -> Option> {
match self.kind() {
- ty::ConstKind::Value(ty, valtree) => Some((valtree, ty)),
+ ty::ConstKind::Value(cv) => Some(cv),
_ => None,
}
}
- #[inline]
- pub fn try_to_scalar(self) -> Option<(Scalar, Ty<'tcx>)> {
- let (valtree, ty) = self.try_to_valtree()?;
- Some((valtree.try_to_scalar()?, ty))
- }
-
- pub fn try_to_bool(self) -> Option {
- self.try_to_valtree()?.0.try_to_scalar_int()?.try_to_bool().ok()
- }
-
+ /// Convenience method to extract the value of a usize constant,
+ /// useful to get the length of an array type.
+ ///
+ /// Note that this does not evaluate the constant.
#[inline]
pub fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option {
- self.try_to_valtree()?.0.try_to_target_usize(tcx)
- }
-
- /// Attempts to evaluate the given constant to bits. Can fail to evaluate in the presence of
- /// generics (or erroneous code) or if the value can't be represented as bits (e.g. because it
- /// contains const generic parameters or pointers).
- #[inline]
- pub fn try_to_bits(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> Option {
- let (scalar, ty) = self.try_to_scalar()?;
- let scalar = scalar.try_to_scalar_int().ok()?;
- let input = typing_env.with_post_analysis_normalized(tcx).as_query_input(ty);
- let size = tcx.layout_of(input).ok()?.size;
- Some(scalar.to_bits(size))
+ self.try_to_value()?.try_to_target_usize(tcx)
}
pub fn is_ct_infer(self) -> bool {
diff --git a/compiler/rustc_middle/src/ty/consts/valtree.rs b/compiler/rustc_middle/src/ty/consts/valtree.rs
index 9f9bf41c3355a..d914b7576dc49 100644
--- a/compiler/rustc_middle/src/ty/consts/valtree.rs
+++ b/compiler/rustc_middle/src/ty/consts/valtree.rs
@@ -1,11 +1,9 @@
-use rustc_macros::{HashStable, TyDecodable, TyEncodable};
+use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
use super::ScalarInt;
use crate::mir::interpret::Scalar;
use crate::ty::{self, Ty, TyCtxt};
-#[derive(Copy, Clone, Debug, Hash, TyEncodable, TyDecodable, Eq, PartialEq)]
-#[derive(HashStable)]
/// This datastructure is used to represent the value of constants used in the type system.
///
/// We explicitly choose a different datastructure from the way values are processed within
@@ -18,6 +16,8 @@ use crate::ty::{self, Ty, TyCtxt};
///
/// `ValTree` does not have this problem with representation, as it only contains integers or
/// lists of (nested) `ValTree`.
+#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
+#[derive(HashStable, TyEncodable, TyDecodable)]
pub enum ValTree<'tcx> {
/// integers, `bool`, `char` are represented as scalars.
/// See the `ScalarInt` documentation for how `ScalarInt` guarantees that equal values
@@ -79,10 +79,6 @@ impl<'tcx> ValTree<'tcx> {
}
}
- pub fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option {
- self.try_to_scalar_int().map(|s| s.to_target_usize(tcx))
- }
-
/// Get the values inside the ValTree as a slice of bytes. This only works for
/// constants with types &str, &[u8], or [u8; _].
pub fn try_to_raw_bytes(self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option<&'tcx [u8]> {
@@ -107,3 +103,54 @@ impl<'tcx> ValTree<'tcx> {
)
}
}
+
+/// A type-level constant value.
+///
+/// Represents a typed, fully evaluated constant.
+#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
+#[derive(HashStable, TyEncodable, TyDecodable, TypeFoldable, TypeVisitable)]
+pub struct Value<'tcx> {
+ pub ty: Ty<'tcx>,
+ pub valtree: ValTree<'tcx>,
+}
+
+impl<'tcx> Value<'tcx> {
+ /// Attempts to extract the raw bits from the constant.
+ ///
+ /// Fails if the value can't be represented as bits (e.g. because it is a reference
+ /// or an aggregate).
+ #[inline]
+ pub fn try_to_bits(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> Option {
+ let (ty::Bool | ty::Char | ty::Uint(_) | ty::Int(_) | ty::Float(_)) = self.ty.kind() else {
+ return None;
+ };
+ let scalar = self.valtree.try_to_scalar_int()?;
+ let input = typing_env.with_post_analysis_normalized(tcx).as_query_input(self.ty);
+ let size = tcx.layout_of(input).ok()?.size;
+ Some(scalar.to_bits(size))
+ }
+
+ pub fn try_to_bool(self) -> Option {
+ if !self.ty.is_bool() {
+ return None;
+ }
+ self.valtree.try_to_scalar_int()?.try_to_bool().ok()
+ }
+
+ pub fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option {
+ if !self.ty.is_usize() {
+ return None;
+ }
+ self.valtree.try_to_scalar_int().map(|s| s.to_target_usize(tcx))
+ }
+}
+
+impl<'tcx> rustc_type_ir::inherent::ValueConst> for Value<'tcx> {
+ fn ty(self) -> Ty<'tcx> {
+ self.ty
+ }
+
+ fn valtree(self) -> ValTree<'tcx> {
+ self.valtree
+ }
+}
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 0c22c056dab5f..69f6fc0ad8a66 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -142,10 +142,11 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
type ParamConst = ty::ParamConst;
type BoundConst = ty::BoundVar;
- type ValueConst = ty::ValTree<'tcx>;
+ type ValueConst = ty::Value<'tcx>;
type ExprConst = ty::Expr<'tcx>;
- type Region = Region<'tcx>;
+ type ValTree = ty::ValTree<'tcx>;
+ type Region = Region<'tcx>;
type EarlyParamRegion = ty::EarlyParamRegion;
type LateParamRegion = ty::LateParamRegion;
type BoundRegion = ty::BoundRegion;
@@ -1118,15 +1119,18 @@ impl<'tcx> CommonConsts<'tcx> {
};
CommonConsts {
- unit: mk_const(ty::ConstKind::Value(types.unit, ty::ValTree::zst())),
- true_: mk_const(ty::ConstKind::Value(
- types.bool,
- ty::ValTree::Leaf(ty::ScalarInt::TRUE),
- )),
- false_: mk_const(ty::ConstKind::Value(
- types.bool,
- ty::ValTree::Leaf(ty::ScalarInt::FALSE),
- )),
+ unit: mk_const(ty::ConstKind::Value(ty::Value {
+ ty: types.unit,
+ valtree: ty::ValTree::zst(),
+ })),
+ true_: mk_const(ty::ConstKind::Value(ty::Value {
+ ty: types.bool,
+ valtree: ty::ValTree::Leaf(ty::ScalarInt::TRUE),
+ })),
+ false_: mk_const(ty::ConstKind::Value(ty::Value {
+ ty: types.bool,
+ valtree: ty::ValTree::Leaf(ty::ScalarInt::FALSE),
+ })),
}
}
}
diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs
index 0af57f636aaab..ec0498b168c01 100644
--- a/compiler/rustc_middle/src/ty/flags.rs
+++ b/compiler/rustc_middle/src/ty/flags.rs
@@ -381,7 +381,7 @@ impl FlagComputation {
self.add_flags(TypeFlags::HAS_CT_PLACEHOLDER);
self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
}
- ty::ConstKind::Value(ty, _) => self.add_ty(ty),
+ ty::ConstKind::Value(cv) => self.add_ty(cv.ty),
ty::ConstKind::Expr(e) => self.add_args(e.args()),
ty::ConstKind::Error(_) => self.add_flags(TypeFlags::HAS_ERROR),
}
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 8cd632790a8ae..88eea6101b5fc 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -60,7 +60,7 @@ pub use self::closure::{
place_to_string_for_capture,
};
pub use self::consts::{
- Const, ConstInt, ConstKind, Expr, ExprKind, ScalarInt, UnevaluatedConst, ValTree,
+ Const, ConstInt, ConstKind, Expr, ExprKind, ScalarInt, UnevaluatedConst, ValTree, Value,
};
pub use self::context::{
CtxtInterners, CurrentGcx, DeducedParamAttrs, Feed, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt,
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 027a4315b4bf3..018fcc66aeed4 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -1484,8 +1484,8 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
_ => write!(self, "_")?,
},
ty::ConstKind::Param(ParamConst { name, .. }) => p!(write("{}", name)),
- ty::ConstKind::Value(ty, value) => {
- return self.pretty_print_const_valtree(value, ty, print_ty);
+ ty::ConstKind::Value(cv) => {
+ return self.pretty_print_const_valtree(cv.valtree, cv.ty, print_ty);
}
ty::ConstKind::Bound(debruijn, bound_var) => {
@@ -1637,33 +1637,32 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
match ty.kind() {
// Byte strings (&[u8; N])
ty::Ref(_, inner, _) => {
- if let ty::Array(elem, len) = inner.kind() {
- if let ty::Uint(ty::UintTy::U8) = elem.kind() {
- if let ty::ConstKind::Value(_, ty::ValTree::Leaf(int)) = len.kind() {
- match self.tcx().try_get_global_alloc(prov.alloc_id()) {
- Some(GlobalAlloc::Memory(alloc)) => {
- let len = int.to_bits(self.tcx().data_layout.pointer_size);
- let range =
- AllocRange { start: offset, size: Size::from_bytes(len) };
- if let Ok(byte_str) =
- alloc.inner().get_bytes_strip_provenance(&self.tcx(), range)
- {
- p!(pretty_print_byte_str(byte_str))
- } else {
- p!("")
- }
- }
- // FIXME: for statics, vtables, and functions, we could in principle print more detail.
- Some(GlobalAlloc::Static(def_id)) => {
- p!(write("", def_id))
- }
- Some(GlobalAlloc::Function { .. }) => p!(""),
- Some(GlobalAlloc::VTable(..)) => p!(""),
- None => p!(""),
+ if let ty::Array(elem, len) = inner.kind()
+ && let ty::Uint(ty::UintTy::U8) = elem.kind()
+ && let ty::ConstKind::Value(cv) = len.kind()
+ && let ty::ValTree::Leaf(int) = cv.valtree
+ {
+ match self.tcx().try_get_global_alloc(prov.alloc_id()) {
+ Some(GlobalAlloc::Memory(alloc)) => {
+ let len = int.to_bits(self.tcx().data_layout.pointer_size);
+ let range = AllocRange { start: offset, size: Size::from_bytes(len) };
+ if let Ok(byte_str) =
+ alloc.inner().get_bytes_strip_provenance(&self.tcx(), range)
+ {
+ p!(pretty_print_byte_str(byte_str))
+ } else {
+ p!("")
}
- return Ok(());
}
+ // FIXME: for statics, vtables, and functions, we could in principle print more detail.
+ Some(GlobalAlloc::Static(def_id)) => {
+ p!(write("", def_id))
+ }
+ Some(GlobalAlloc::Function { .. }) => p!(""),
+ Some(GlobalAlloc::VTable(..)) => p!(""),
+ None => p!(""),
}
+ return Ok(());
}
}
ty::FnPtr(..) => {
@@ -1786,6 +1785,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
Ok(())
}
+ // FIXME(valtrees): Accept `ty::Value` instead of `Ty` and `ty::ValTree` separately.
fn pretty_print_const_valtree(
&mut self,
valtree: ty::ValTree<'tcx>,
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index 68cb56f35837d..9e9de4fb06443 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -162,16 +162,15 @@ impl<'tcx> fmt::Debug for ty::consts::Expr<'tcx> {
impl<'tcx> fmt::Debug for ty::Const<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// If this is a value, we spend some effort to make it look nice.
- if let ConstKind::Value(_, _) = self.kind() {
+ if let ConstKind::Value(_) = self.kind() {
return ty::tls::with(move |tcx| {
- // Somehow trying to lift the valtree results in lifetime errors, so we lift the
- // entire constant.
+ // ValTrees aren't interned, so we lift the entire constant.
let lifted = tcx.lift(*self).unwrap();
- let ConstKind::Value(ty, valtree) = lifted.kind() else {
+ let ConstKind::Value(cv) = lifted.kind() else {
bug!("we checked that this is a valtree")
};
let mut cx = FmtPrinter::new(tcx, Namespace::ValueNS);
- cx.pretty_print_const_valtree(valtree, ty, /*print_ty*/ true)?;
+ cx.pretty_print_const_valtree(cv.valtree, cv.ty, /*print_ty*/ true)?;
f.write_str(&cx.into_buffer())
});
}
@@ -589,9 +588,7 @@ impl<'tcx> TypeSuperFoldable> for ty::Const<'tcx> {
}
ConstKind::Placeholder(p) => ConstKind::Placeholder(p.try_fold_with(folder)?),
ConstKind::Unevaluated(uv) => ConstKind::Unevaluated(uv.try_fold_with(folder)?),
- ConstKind::Value(t, v) => {
- ConstKind::Value(t.try_fold_with(folder)?, v.try_fold_with(folder)?)
- }
+ ConstKind::Value(v) => ConstKind::Value(v.try_fold_with(folder)?),
ConstKind::Error(e) => ConstKind::Error(e.try_fold_with(folder)?),
ConstKind::Expr(e) => ConstKind::Expr(e.try_fold_with(folder)?),
};
@@ -610,10 +607,7 @@ impl<'tcx> TypeSuperVisitable> for ty::Const<'tcx> {
}
ConstKind::Placeholder(p) => p.visit_with(visitor),
ConstKind::Unevaluated(uv) => uv.visit_with(visitor),
- ConstKind::Value(t, v) => {
- try_visit!(t.visit_with(visitor));
- v.visit_with(visitor)
- }
+ ConstKind::Value(v) => v.visit_with(visitor),
ConstKind::Error(e) => e.visit_with(visitor),
ConstKind::Expr(e) => e.visit_with(visitor),
}
diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs
index 2dcba8c2f82c4..3e8a3d1a28923 100644
--- a/compiler/rustc_middle/src/ty/walk.rs
+++ b/compiler/rustc_middle/src/ty/walk.rs
@@ -206,7 +206,7 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>)
| ty::ConstKind::Bound(..)
| ty::ConstKind::Error(_) => {}
- ty::ConstKind::Value(ty, _) => stack.push(ty.into()),
+ ty::ConstKind::Value(cv) => stack.push(cv.ty.into()),
ty::ConstKind::Expr(expr) => stack.extend(expr.args().iter().rev()),
ty::ConstKind::Unevaluated(ct) => {
diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
index 3853b95f78b4c..cc6d69710e4c2 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
@@ -46,7 +46,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
match c.kind() {
ty::ConstKind::Unevaluated(uv) => convert.unevaluated_to_pat(uv, ty),
- ty::ConstKind::Value(_, val) => convert.valtree_to_pat(val, ty),
+ ty::ConstKind::Value(cv) => convert.valtree_to_pat(cv.valtree, cv.ty),
_ => span_bug!(span, "Invalid `ConstKind` for `const_to_pat`: {:?}", c),
}
}
@@ -214,6 +214,7 @@ impl<'tcx> ConstToPat<'tcx> {
}
// Recursive helper for `to_pat`; invoke that (instead of calling this directly).
+ // FIXME(valtrees): Accept `ty::Value` instead of `Ty` and `ty::ValTree` separately.
#[instrument(skip(self), level = "debug")]
fn valtree_to_pat(&self, cv: ValTree<'tcx>, ty: Ty<'tcx>) -> Box> {
let span = self.span;
diff --git a/compiler/rustc_next_trait_solver/src/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonicalizer.rs
index 62a7c84bc2807..7eeed721d5a0f 100644
--- a/compiler/rustc_next_trait_solver/src/canonicalizer.rs
+++ b/compiler/rustc_next_trait_solver/src/canonicalizer.rs
@@ -522,7 +522,7 @@ impl, I: Interner> TypeFolder for Canonicaliz
// FIXME: See comment above -- we could fold the region separately or something.
ty::ConstKind::Bound(_, _)
| ty::ConstKind::Unevaluated(_)
- | ty::ConstKind::Value(_, _)
+ | ty::ConstKind::Value(_)
| ty::ConstKind::Error(_)
| ty::ConstKind::Expr(_) => return c.super_fold_with(self),
};
diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs
index 8d1194ee53980..1fa35b60304cf 100644
--- a/compiler/rustc_next_trait_solver/src/solve/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs
@@ -160,9 +160,7 @@ where
ty::ConstKind::Infer(_) => {
self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
}
- ty::ConstKind::Placeholder(_)
- | ty::ConstKind::Value(_, _)
- | ty::ConstKind::Error(_) => {
+ ty::ConstKind::Placeholder(_) | ty::ConstKind::Value(_) | ty::ConstKind::Error(_) => {
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
}
// We can freely ICE here as:
@@ -199,7 +197,7 @@ where
unreachable!("`ConstKind::Param` should have been canonicalized to `Placeholder`")
}
ty::ConstKind::Bound(_, _) => panic!("escaping bound vars in {:?}", ct),
- ty::ConstKind::Value(ty, _) => ty,
+ ty::ConstKind::Value(cv) => cv.ty(),
ty::ConstKind::Placeholder(placeholder) => {
self.cx().find_const_ty_from_env(goal.param_env, placeholder)
}
diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs
index 09648e28df471..5f0c1afdf6420 100644
--- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs
+++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs
@@ -103,7 +103,7 @@ fn encode_args<'tcx>(
/// ).
fn encode_const<'tcx>(
tcx: TyCtxt<'tcx>,
- c: Const<'tcx>,
+ ct: Const<'tcx>,
ct_ty: Ty<'tcx>,
dict: &mut FxHashMap, usize>,
options: EncodeTyOptions,
@@ -111,7 +111,7 @@ fn encode_const<'tcx>(
// L[n][]E as literal argument
let mut s = String::from('L');
- match c.kind() {
+ match ct.kind() {
// Const parameters
ty::ConstKind::Param(..) => {
// LE as literal argument
@@ -121,18 +121,18 @@ fn encode_const<'tcx>(
}
// Literal arguments
- ty::ConstKind::Value(ct_ty, ..) => {
+ ty::ConstKind::Value(cv) => {
// L[n]E as literal argument
// Element type
- s.push_str(&encode_ty(tcx, ct_ty, dict, options));
+ s.push_str(&encode_ty(tcx, cv.ty, dict, options));
// The only allowed types of const values are bool, u8, u16, u32,
// u64, u128, usize i8, i16, i32, i64, i128, isize, and char. The
// bool value false is encoded as 0 and true as 1.
- match ct_ty.kind() {
+ match cv.ty.kind() {
ty::Int(ity) => {
- let bits = c
+ let bits = cv
.try_to_bits(tcx, ty::TypingEnv::fully_monomorphized())
.expect("expected monomorphic const in cfi");
let val = Integer::from_int_ty(&tcx, *ity).size().sign_extend(bits) as i128;
@@ -142,30 +142,30 @@ fn encode_const<'tcx>(
let _ = write!(s, "{val}");
}
ty::Uint(_) => {
- let val = c
+ let val = cv
.try_to_bits(tcx, ty::TypingEnv::fully_monomorphized())
.expect("expected monomorphic const in cfi");
let _ = write!(s, "{val}");
}
ty::Bool => {
- let val = c.try_to_bool().expect("expected monomorphic const in cfi");
+ let val = cv.try_to_bool().expect("expected monomorphic const in cfi");
let _ = write!(s, "{val}");
}
_ => {
- bug!("encode_const: unexpected type `{:?}`", ct_ty);
+ bug!("encode_const: unexpected type `{:?}`", cv.ty);
}
}
}
_ => {
- bug!("encode_const: unexpected kind `{:?}`", c.kind());
+ bug!("encode_const: unexpected kind `{:?}`", ct.kind());
}
}
// Close the "L..E" pair
s.push('E');
- compress(dict, DictKey::Const(c), &mut s);
+ compress(dict, DictKey::Const(ct), &mut s);
s
}
diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs
index 9c6186d688284..b711c238d594b 100644
--- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs
+++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs
@@ -51,8 +51,7 @@ impl<'tcx> TypeFolder> for TransformTy<'tcx> {
// Transforms a ty:Ty for being encoded and used in the substitution dictionary.
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
match t.kind() {
- ty::Array(..)
- | ty::Closure(..)
+ ty::Closure(..)
| ty::Coroutine(..)
| ty::CoroutineClosure(..)
| ty::CoroutineWitness(..)
@@ -67,6 +66,13 @@ impl<'tcx> TypeFolder> for TransformTy<'tcx> {
| ty::Tuple(..)
| ty::UnsafeBinder(_) => t.super_fold_with(self),
+ // Don't transform the type of the array length and keep it as `usize`.
+ // This is required for `try_to_target_usize` to work correctly.
+ &ty::Array(inner, len) => {
+ let inner = self.fold_ty(inner);
+ Ty::new_array_with_const_len(self.tcx, inner, len)
+ }
+
ty::Bool => {
if self.options.contains(EncodeTyOptions::NORMALIZE_INTEGERS) {
// Note: on all platforms that Rust's currently supports, its size and alignment
diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs
index 31c7e6c3eb446..8d4e55dc036dd 100644
--- a/compiler/rustc_smir/src/rustc_smir/context.rs
+++ b/compiler/rustc_smir/src/rustc_smir/context.rs
@@ -450,8 +450,9 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
let tcx = tables.tcx;
let ty = ty::Ty::new_static_str(tcx);
let bytes = value.as_bytes();
- let val_tree = ty::ValTree::from_raw_bytes(tcx, bytes);
- let val = tcx.valtree_to_const_val((ty, val_tree));
+ let valtree = ty::ValTree::from_raw_bytes(tcx, bytes);
+ let cv = ty::Value { ty, valtree };
+ let val = tcx.valtree_to_const_val(cv);
mir::Const::from_value(val, ty).stable(&mut tables)
}
diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
index ff452eea23d2b..a2d95f0f693aa 100644
--- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
+++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
@@ -418,23 +418,16 @@ impl<'tcx> Stable<'tcx> for ty::Const<'tcx> {
type T = stable_mir::ty::TyConst;
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
- let kind = match self.kind() {
- ty::ConstKind::Value(ty, val) => {
- let val = match val {
- ty::ValTree::Leaf(scalar) => ty::ValTree::Leaf(scalar),
- ty::ValTree::Branch(branch) => {
- ty::ValTree::Branch(tables.tcx.lift(branch).unwrap())
- }
- };
-
- let ty = tables.tcx.lift(ty).unwrap();
- let const_val = tables.tcx.valtree_to_const_val((ty, val));
+ let ct = tables.tcx.lift(*self).unwrap();
+ let kind = match ct.kind() {
+ ty::ConstKind::Value(cv) => {
+ let const_val = tables.tcx.valtree_to_const_val(cv);
if matches!(const_val, mir::ConstValue::ZeroSized) {
- stable_mir::ty::TyConstKind::ZSTValue(ty.stable(tables))
+ stable_mir::ty::TyConstKind::ZSTValue(cv.ty.stable(tables))
} else {
stable_mir::ty::TyConstKind::Value(
- ty.stable(tables),
- alloc::new_allocation(ty, const_val, tables),
+ cv.ty.stable(tables),
+ alloc::new_allocation(cv.ty, const_val, tables),
)
}
}
@@ -449,7 +442,7 @@ impl<'tcx> Stable<'tcx> for ty::Const<'tcx> {
ty::ConstKind::Placeholder(_) => unimplemented!(),
ty::ConstKind::Expr(_) => unimplemented!(),
};
- let id = tables.intern_ty_const(tables.tcx.lift(*self).unwrap());
+ let id = tables.intern_ty_const(ct);
stable_mir::ty::TyConst::new(kind, id)
}
}
diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs
index 879f3fac21fb4..8ae35572d012d 100644
--- a/compiler/rustc_symbol_mangling/src/legacy.rs
+++ b/compiler/rustc_symbol_mangling/src/legacy.rs
@@ -274,14 +274,15 @@ impl<'tcx> Printer<'tcx> for SymbolPrinter<'tcx> {
fn print_const(&mut self, ct: ty::Const<'tcx>) -> Result<(), PrintError> {
// only print integers
match ct.kind() {
- ty::ConstKind::Value(ty, ty::ValTree::Leaf(scalar)) if ty.is_integral() => {
+ ty::ConstKind::Value(cv) if cv.ty.is_integral() => {
// The `pretty_print_const` formatting depends on -Zverbose-internals
// flag, so we cannot reuse it here.
- let signed = matches!(ty.kind(), ty::Int(_));
+ let scalar = cv.valtree.unwrap_leaf();
+ let signed = matches!(cv.ty.kind(), ty::Int(_));
write!(
self,
"{:#?}",
- ty::ConstInt::new(scalar, signed, ty.is_ptr_sized_integral())
+ ty::ConstInt::new(scalar, signed, cv.ty.is_ptr_sized_integral())
)?;
}
_ => self.write_str("_")?,
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index 4ddf530a00d4a..5b3272feecdbb 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -590,8 +590,8 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
fn print_const(&mut self, ct: ty::Const<'tcx>) -> Result<(), PrintError> {
// We only mangle a typed value if the const can be evaluated.
- let (ct_ty, valtree) = match ct.kind() {
- ty::ConstKind::Value(ty, val) => (ty, val),
+ let cv = match ct.kind() {
+ ty::ConstKind::Value(cv) => cv,
// Should only be encountered within the identity-substituted
// impl header of an item nested within an impl item.
@@ -619,13 +619,14 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
return Ok(());
}
+ let ty::Value { ty: ct_ty, valtree } = cv;
let start = self.out.len();
match ct_ty.kind() {
ty::Uint(_) | ty::Int(_) | ty::Bool | ty::Char => {
ct_ty.print(self)?;
- let mut bits = ct
+ let mut bits = cv
.try_to_bits(self.tcx, ty::TypingEnv::fully_monomorphized())
.expect("expected const to be monomorphic");
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
index 9eacd377361a7..117b6a7642575 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
@@ -2023,14 +2023,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
_ => None,
};
if let Some(tykind) = tykind
- && let hir::TyKind::Array(_, length) = tykind
- && let Some((scalar, ty)) = sz.found.try_to_scalar()
- && ty == self.tcx.types.usize
+ && let hir::TyKind::Array(_, length_arg) = tykind
+ && let Some(length_val) = sz.found.try_to_target_usize(self.tcx)
{
- let span = length.span();
Some(TypeErrorAdditionalDiags::ConsiderSpecifyingLength {
- span,
- length: scalar.to_target_usize(&self.tcx).unwrap(),
+ span: length_arg.span(),
+ length: length_val,
})
} else {
None
diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs
index 2b7da4bc5ff07..c8ae977b5ad60 100644
--- a/compiler/rustc_trait_selection/src/solve/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs
@@ -264,7 +264,7 @@ fn fulfillment_error_for_no_solution<'tcx>(
infcx.tcx.type_of(uv.def).instantiate(infcx.tcx, uv.args)
}
ty::ConstKind::Param(param_ct) => param_ct.find_ty_from_env(obligation.param_env),
- ty::ConstKind::Value(ty, _) => ty,
+ ty::ConstKind::Value(cv) => cv.ty,
kind => span_bug!(
obligation.cause.span,
"ConstArgHasWrongType failed but we don't know how to compute type for {kind:?}"
diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
index 446f9eaa348c0..bdee6ca2afe54 100644
--- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
+++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
@@ -35,7 +35,7 @@ pub fn is_const_evaluatable<'tcx>(
ty::ConstKind::Param(_)
| ty::ConstKind::Bound(_, _)
| ty::ConstKind::Placeholder(_)
- | ty::ConstKind::Value(_, _)
+ | ty::ConstKind::Value(_)
| ty::ConstKind::Error(_) => return Ok(()),
ty::ConstKind::Infer(_) => return Err(NotConstEvaluatable::MentionsInfer),
};
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index 7529ee128f5e4..f2d2dd2f3ce59 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -479,7 +479,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
ty::ConstKind::Error(_) => {
return ProcessResult::Changed(PendingPredicateObligations::new());
}
- ty::ConstKind::Value(ty, _) => ty,
+ ty::ConstKind::Value(cv) => cv.ty,
ty::ConstKind::Unevaluated(uv) => {
infcx.tcx.type_of(uv.def).instantiate(infcx.tcx, uv.args)
}
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 6b6e0b32385c4..99ce1fd9fb480 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -962,7 +962,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
return Ok(EvaluatedToAmbig);
}
ty::ConstKind::Error(_) => return Ok(EvaluatedToOk),
- ty::ConstKind::Value(ty, _) => ty,
+ ty::ConstKind::Value(cv) => cv.ty,
ty::ConstKind::Unevaluated(uv) => {
self.tcx().type_of(uv.def).instantiate(self.tcx(), uv.args)
}
diff --git a/compiler/rustc_transmute/src/lib.rs b/compiler/rustc_transmute/src/lib.rs
index ad86813c87e29..a50cc8f593251 100644
--- a/compiler/rustc_transmute/src/lib.rs
+++ b/compiler/rustc_transmute/src/lib.rs
@@ -128,16 +128,16 @@ mod rustc {
pub fn from_const<'tcx>(
tcx: TyCtxt<'tcx>,
param_env: ParamEnv<'tcx>,
- c: Const<'tcx>,
+ ct: Const<'tcx>,
) -> Option {
use rustc_middle::ty::ScalarInt;
use rustc_span::sym;
- let Some((cv, ty)) = c.try_to_valtree() else {
+ let Some(cv) = ct.try_to_value() else {
return None;
};
- let adt_def = ty.ty_adt_def()?;
+ let adt_def = cv.ty.ty_adt_def()?;
assert_eq!(
tcx.require_lang_item(LangItem::TransmuteOpts, None),
@@ -147,7 +147,7 @@ mod rustc {
);
let variant = adt_def.non_enum_variant();
- let fields = match cv {
+ let fields = match cv.valtree {
ValTree::Branch(branch) => branch,
_ => {
return Some(Self {
diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs
index 51a7c976f600c..931c36137ee5f 100644
--- a/compiler/rustc_ty_utils/src/consts.rs
+++ b/compiler/rustc_ty_utils/src/consts.rs
@@ -22,16 +22,16 @@ fn destructure_const<'tcx>(
tcx: TyCtxt<'tcx>,
const_: ty::Const<'tcx>,
) -> ty::DestructuredConst<'tcx> {
- let ty::ConstKind::Value(ct_ty, valtree) = const_.kind() else {
+ let ty::ConstKind::Value(cv) = const_.kind() else {
bug!("cannot destructure constant {:?}", const_)
};
- let branches = match valtree {
+ let branches = match cv.valtree {
ty::ValTree::Branch(b) => b,
_ => bug!("cannot destructure constant {:?}", const_),
};
- let (fields, variant) = match ct_ty.kind() {
+ let (fields, variant) = match cv.ty.kind() {
ty::Array(inner_ty, _) | ty::Slice(inner_ty) => {
// construct the consts for the elements of the array/slice
let field_consts = branches
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index a04c753611831..2f258b23f2df4 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -144,13 +144,13 @@ fn univariant_uninterned<'tcx>(
cx.calc.univariant(fields, repr, kind).map_err(|err| map_error(cx, ty, err))
}
-fn validate_const_with_value<'tcx>(
+fn extract_const_value<'tcx>(
const_: ty::Const<'tcx>,
ty: Ty<'tcx>,
cx: &LayoutCx<'tcx>,
-) -> Result, &'tcx LayoutError<'tcx>> {
+) -> Result, &'tcx LayoutError<'tcx>> {
match const_.kind() {
- ty::ConstKind::Value(..) => Ok(const_),
+ ty::ConstKind::Value(cv) => Ok(cv),
ty::ConstKind::Error(guar) => {
return Err(error(cx, LayoutError::ReferencesError(guar)));
}
@@ -209,13 +209,12 @@ fn layout_of_uncached<'tcx>(
&mut layout.backend_repr
{
if let Some(start) = start {
- scalar.valid_range_mut().start =
- validate_const_with_value(start, ty, cx)?
- .try_to_bits(tcx, cx.typing_env)
- .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
+ scalar.valid_range_mut().start = extract_const_value(start, ty, cx)?
+ .try_to_bits(tcx, cx.typing_env)
+ .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
}
if let Some(end) = end {
- let mut end = validate_const_with_value(end, ty, cx)?
+ let mut end = extract_const_value(end, ty, cx)?
.try_to_bits(tcx, cx.typing_env)
.ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
if !include_end {
@@ -348,9 +347,7 @@ fn layout_of_uncached<'tcx>(
// Arrays and slices.
ty::Array(element, count) => {
- let count = validate_const_with_value(count, ty, cx)?
- .to_valtree()
- .0
+ let count = extract_const_value(count, ty, cx)?
.try_to_target_usize(tcx)
.ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs
index 03dfe547cedd4..aafc0907ae156 100644
--- a/compiler/rustc_type_ir/src/const_kind.rs
+++ b/compiler/rustc_type_ir/src/const_kind.rs
@@ -31,7 +31,7 @@ pub enum ConstKind {
Unevaluated(ty::UnevaluatedConst),
/// Used to hold computed value.
- Value(I::Ty, I::ValueConst),
+ Value(I::ValueConst),
/// A placeholder for a const which could not be computed; this is
/// propagated to avoid useless error messages.
@@ -52,7 +52,7 @@ impl fmt::Debug for ConstKind {
Bound(debruijn, var) => crate::debug_bound_var(f, *debruijn, var),
Placeholder(placeholder) => write!(f, "{placeholder:?}"),
Unevaluated(uv) => write!(f, "{uv:?}"),
- Value(ty, valtree) => write!(f, "({valtree:?}: {ty:?})"),
+ Value(val) => write!(f, "{val:?}"),
Error(_) => write!(f, "{{const error}}"),
Expr(expr) => write!(f, "{expr:?}"),
}
diff --git a/compiler/rustc_type_ir/src/fast_reject.rs b/compiler/rustc_type_ir/src/fast_reject.rs
index 9b3ff14d507ac..9955e92b55a5c 100644
--- a/compiler/rustc_type_ir/src/fast_reject.rs
+++ b/compiler/rustc_type_ir/src/fast_reject.rs
@@ -483,8 +483,8 @@ impl match rhs.kind() {
- ty::ConstKind::Value(_, rhs_val) => lhs_val == rhs_val,
+ ty::ConstKind::Value(lhs_val) => match rhs.kind() {
+ ty::ConstKind::Value(rhs_val) => lhs_val.valtree() == rhs_val.valtree(),
_ => false,
},
diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs
index 872cf6680185b..4e6d645e6fae2 100644
--- a/compiler/rustc_type_ir/src/inherent.rs
+++ b/compiler/rustc_type_ir/src/inherent.rs
@@ -286,6 +286,11 @@ pub trait Const>:
}
}
+pub trait ValueConst>: Copy + Debug + Hash + Eq {
+ fn ty(self) -> I::Ty;
+ fn valtree(self) -> I::ValTree;
+}
+
pub trait ExprConst>: Copy + Debug + Hash + Eq + Relate {
fn args(self) -> I::GenericArgs;
}
diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs
index 0c3b0758f0f95..a6c72da0c564a 100644
--- a/compiler/rustc_type_ir/src/interner.rs
+++ b/compiler/rustc_type_ir/src/interner.rs
@@ -112,8 +112,9 @@ pub trait Interner:
type PlaceholderConst: PlaceholderLike;
type ParamConst: Copy + Debug + Hash + Eq + ParamLike;
type BoundConst: Copy + Debug + Hash + Eq + BoundVarLike;
- type ValueConst: Copy + Debug + Hash + Eq;
+ type ValueConst: ValueConst;
type ExprConst: ExprConst;
+ type ValTree: Copy + Debug + Hash + Eq;
// Kinds of regions
type Region: Region;
diff --git a/compiler/rustc_type_ir/src/relate.rs b/compiler/rustc_type_ir/src/relate.rs
index e628b66d2f086..5b696ee5ed400 100644
--- a/compiler/rustc_type_ir/src/relate.rs
+++ b/compiler/rustc_type_ir/src/relate.rs
@@ -606,7 +606,9 @@ pub fn structurally_relate_consts>(
true
}
(ty::ConstKind::Placeholder(p1), ty::ConstKind::Placeholder(p2)) => p1 == p2,
- (ty::ConstKind::Value(_, a_val), ty::ConstKind::Value(_, b_val)) => a_val == b_val,
+ (ty::ConstKind::Value(a_val), ty::ConstKind::Value(b_val)) => {
+ a_val.valtree() == b_val.valtree()
+ }
// While this is slightly incorrect, it shouldn't matter for `min_const_generics`
// and is the better alternative to waiting until `generic_const_exprs` can
diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs
index ac5307a671d20..0d8c3ef906bf0 100644
--- a/library/core/src/mem/maybe_uninit.rs
+++ b/library/core/src/mem/maybe_uninit.rs
@@ -276,10 +276,9 @@ impl Clone for MaybeUninit {
impl fmt::Debug for MaybeUninit {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// NB: there is no `.pad_fmt` so we can't use a simpler `format_args!("MaybeUninit<{..}>").
- // This needs to be adjusted if `MaybeUninit` moves modules.
let full_name = type_name::();
- let short_name = full_name.split_once("mem::maybe_uninit::").unwrap().1;
- f.pad(short_name)
+ let prefix_len = full_name.find("MaybeUninit").unwrap();
+ f.pad(&full_name[prefix_len..])
}
}
diff --git a/library/core/src/prelude/common.rs b/library/core/src/prelude/common.rs
index e38ef1e147c76..8b116cecb5295 100644
--- a/library/core/src/prelude/common.rs
+++ b/library/core/src/prelude/common.rs
@@ -12,6 +12,9 @@ pub use crate::marker::{Copy, Send, Sized, Sync, Unpin};
#[stable(feature = "core_prelude", since = "1.4.0")]
#[doc(no_inline)]
pub use crate::ops::{Drop, Fn, FnMut, FnOnce};
+#[stable(feature = "async_closure", since = "1.85.0")]
+#[doc(no_inline)]
+pub use crate::ops::{AsyncFn, AsyncFnMut, AsyncFnOnce};
// Re-exported functions
#[stable(feature = "core_prelude", since = "1.4.0")]
diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs
index 1f8aac48a9a8b..a5b0111adfb4a 100644
--- a/library/std/src/fs.rs
+++ b/library/std/src/fs.rs
@@ -629,9 +629,9 @@ impl File {
/// This acquires an exclusive advisory lock; no other file handle to this file may acquire
/// another lock.
///
- /// If this file handle, or a clone of it, already holds an advisory lock the exact behavior is
- /// unspecified and platform dependent, including the possibility that it will deadlock.
- /// However, if this method returns, then an exclusive lock is held.
+ /// If this file handle/descriptor, or a clone of it, already holds an advisory lock the exact
+ /// behavior is unspecified and platform dependent, including the possibility that it will
+ /// deadlock. However, if this method returns, then an exclusive lock is held.
///
/// If the file not open for writing, it is unspecified whether this function returns an error.
///
@@ -639,6 +639,9 @@ impl File {
/// [`try_lock_shared`], and [`unlock`]. Its interactions with other methods, such as [`read`]
/// and [`write`] are platform specific, and it may or may not cause non-lockholders to block.
///
+ /// The lock will be released when this file (along with any other file descriptors/handles
+ /// duplicated or inherited from it) is closed, or if the [`unlock`] method is called.
+ ///
/// # Platform-specific behavior
///
/// This function currently corresponds to the `flock` function on Unix with the `LOCK_EX` flag,
@@ -671,19 +674,22 @@ impl File {
self.inner.lock()
}
- /// Acquire a shared advisory lock on the file. Blocks until the lock can be acquired.
+ /// Acquire a shared (non-exclusive) advisory lock on the file. Blocks until the lock can be acquired.
///
/// This acquires a shared advisory lock; more than one file handle may hold a shared lock, but
- /// none may hold an exclusive lock.
+ /// none may hold an exclusive lock at the same time.
///
- /// If this file handle, or a clone of it, already holds an advisory lock, the exact behavior is
- /// unspecified and platform dependent, including the possibility that it will deadlock.
- /// However, if this method returns, then a shared lock is held.
+ /// If this file handle/descriptor, or a clone of it, already holds an advisory lock, the exact
+ /// behavior is unspecified and platform dependent, including the possibility that it will
+ /// deadlock. However, if this method returns, then a shared lock is held.
///
/// Note, this is an advisory lock meant to interact with [`lock`], [`try_lock`],
/// [`try_lock_shared`], and [`unlock`]. Its interactions with other methods, such as [`read`]
/// and [`write`] are platform specific, and it may or may not cause non-lockholders to block.
///
+ /// The lock will be released when this file (along with any other file descriptors/handles
+ /// duplicated or inherited from it) is closed, or if the [`unlock`] method is called.
+ ///
/// # Platform-specific behavior
///
/// This function currently corresponds to the `flock` function on Unix with the `LOCK_SH` flag,
@@ -716,14 +722,18 @@ impl File {
self.inner.lock_shared()
}
- /// Acquire an exclusive advisory lock on the file. Returns `Ok(false)` if the file is locked.
+ /// Try to acquire an exclusive advisory lock on the file.
+ ///
+ /// Returns `Ok(false)` if a different lock is already held on this file (via another
+ /// handle/descriptor).
///
/// This acquires an exclusive advisory lock; no other file handle to this file may acquire
/// another lock.
///
- /// If this file handle, or a clone of it, already holds an advisory lock, the exact behavior is
- /// unspecified and platform dependent, including the possibility that it will deadlock.
- /// However, if this method returns, then an exclusive lock is held.
+ /// If this file handle/descriptor, or a clone of it, already holds an advisory lock, the exact
+ /// behavior is unspecified and platform dependent, including the possibility that it will
+ /// deadlock. However, if this method returns `Ok(true)`, then it has acquired an exclusive
+ /// lock.
///
/// If the file not open for writing, it is unspecified whether this function returns an error.
///
@@ -731,6 +741,9 @@ impl File {
/// [`try_lock_shared`], and [`unlock`]. Its interactions with other methods, such as [`read`]
/// and [`write`] are platform specific, and it may or may not cause non-lockholders to block.
///
+ /// The lock will be released when this file (along with any other file descriptors/handles
+ /// duplicated or inherited from it) is closed, or if the [`unlock`] method is called.
+ ///
/// # Platform-specific behavior
///
/// This function currently corresponds to the `flock` function on Unix with the `LOCK_EX` and
@@ -764,20 +777,25 @@ impl File {
self.inner.try_lock()
}
- /// Acquire a shared advisory lock on the file.
- /// Returns `Ok(false)` if the file is exclusively locked.
+ /// Try to acquire a shared (non-exclusive) advisory lock on the file.
+ ///
+ /// Returns `Ok(false)` if an exclusive lock is already held on this file (via another
+ /// handle/descriptor).
///
/// This acquires a shared advisory lock; more than one file handle may hold a shared lock, but
- /// none may hold an exclusive lock.
+ /// none may hold an exclusive lock at the same time.
///
/// If this file handle, or a clone of it, already holds an advisory lock, the exact behavior is
/// unspecified and platform dependent, including the possibility that it will deadlock.
- /// However, if this method returns, then a shared lock is held.
+ /// However, if this method returns `Ok(true)`, then it has acquired a shared lock.
///
/// Note, this is an advisory lock meant to interact with [`lock`], [`try_lock`],
/// [`try_lock`], and [`unlock`]. Its interactions with other methods, such as [`read`]
/// and [`write`] are platform specific, and it may or may not cause non-lockholders to block.
///
+ /// The lock will be released when this file (along with any other file descriptors/handles
+ /// duplicated or inherited from it) is closed, or if the [`unlock`] method is called.
+ ///
/// # Platform-specific behavior
///
/// This function currently corresponds to the `flock` function on Unix with the `LOCK_SH` and
@@ -813,7 +831,12 @@ impl File {
/// Release all locks on the file.
///
- /// All remaining locks are released when the file handle, and all clones of it, are dropped.
+ /// All locks are released when the file (along with any other file descriptors/handles
+ /// duplicated or inherited from it) is closed. This method allows releasing locks without
+ /// closing the file.
+ ///
+ /// If no lock is currently held via this file descriptor/handle, this method may return an
+ /// error, or may return successfully without taking any action.
///
/// # Platform-specific behavior
///
diff --git a/library/std/src/sys/pal/uefi/helpers.rs b/library/std/src/sys/pal/uefi/helpers.rs
index 7504a0f7ad7f5..dccc137d6f561 100644
--- a/library/std/src/sys/pal/uefi/helpers.rs
+++ b/library/std/src/sys/pal/uefi/helpers.rs
@@ -14,10 +14,12 @@ use r_efi::protocols::{device_path, device_path_to_text, shell};
use crate::ffi::{OsStr, OsString};
use crate::io::{self, const_error};
+use crate::marker::PhantomData;
use crate::mem::{MaybeUninit, size_of};
use crate::os::uefi::env::boot_services;
use crate::os::uefi::ffi::{OsStrExt, OsStringExt};
use crate::os::uefi::{self};
+use crate::path::Path;
use crate::ptr::NonNull;
use crate::slice;
use crate::sync::atomic::{AtomicPtr, Ordering};
@@ -278,6 +280,10 @@ impl OwnedDevicePath {
pub(crate) const fn as_ptr(&self) -> *mut r_efi::protocols::device_path::Protocol {
self.0.as_ptr()
}
+
+ pub(crate) const fn borrow<'a>(&'a self) -> BorrowedDevicePath<'a> {
+ BorrowedDevicePath::new(self.0)
+ }
}
impl Drop for OwnedDevicePath {
@@ -293,13 +299,37 @@ impl Drop for OwnedDevicePath {
impl crate::fmt::Debug for OwnedDevicePath {
fn fmt(&self, f: &mut crate::fmt::Formatter<'_>) -> crate::fmt::Result {
- match device_path_to_text(self.0) {
+ match self.borrow().to_text() {
Ok(p) => p.fmt(f),
Err(_) => f.debug_struct("OwnedDevicePath").finish_non_exhaustive(),
}
}
}
+pub(crate) struct BorrowedDevicePath<'a> {
+ protocol: NonNull,
+ phantom: PhantomData<&'a r_efi::protocols::device_path::Protocol>,
+}
+
+impl<'a> BorrowedDevicePath<'a> {
+ pub(crate) const fn new(protocol: NonNull) -> Self {
+ Self { protocol, phantom: PhantomData }
+ }
+
+ pub(crate) fn to_text(&self) -> io::Result {
+ device_path_to_text(self.protocol)
+ }
+}
+
+impl<'a> crate::fmt::Debug for BorrowedDevicePath<'a> {
+ fn fmt(&self, f: &mut crate::fmt::Formatter<'_>) -> crate::fmt::Result {
+ match self.to_text() {
+ Ok(p) => p.fmt(f),
+ Err(_) => f.debug_struct("BorrowedDevicePath").finish_non_exhaustive(),
+ }
+ }
+}
+
pub(crate) struct OwnedProtocol {
guid: r_efi::efi::Guid,
handle: NonNull,
@@ -452,3 +482,21 @@ pub(crate) fn open_shell() -> Option> {
None
}
+
+/// Get device path protocol associated with shell mapping.
+///
+/// returns None in case no such mapping is exists
+pub(crate) fn get_device_path_from_map(map: &Path) -> io::Result> {
+ let shell =
+ open_shell().ok_or(io::const_error!(io::ErrorKind::NotFound, "UEFI Shell not found"))?;
+ let mut path = os_string_to_raw(map.as_os_str())
+ .ok_or(io::const_error!(io::ErrorKind::InvalidFilename, "Invalid UEFI shell mapping"))?;
+
+ // The Device Path Protocol pointer returned by UEFI shell is owned by the shell and is not
+ // freed throughout it's lifetime. So it has a 'static lifetime.
+ let protocol = unsafe { ((*shell.as_ptr()).get_device_path_from_map)(path.as_mut_ptr()) };
+ let protocol = NonNull::new(protocol)
+ .ok_or(io::const_error!(io::ErrorKind::NotFound, "UEFI Shell mapping not found"))?;
+
+ Ok(BorrowedDevicePath::new(protocol))
+}
diff --git a/library/std/src/sys/path/mod.rs b/library/std/src/sys/path/mod.rs
index 24a94ec782824..1fa4e80d6780c 100644
--- a/library/std/src/sys/path/mod.rs
+++ b/library/std/src/sys/path/mod.rs
@@ -5,12 +5,12 @@ cfg_if::cfg_if! {
} else if #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] {
mod sgx;
pub use sgx::*;
- } else if #[cfg(any(
- target_os = "uefi",
- target_os = "solid_asp3",
- ))] {
+ } else if #[cfg(target_os = "solid_asp3")] {
mod unsupported_backslash;
pub use unsupported_backslash::*;
+ } else if #[cfg(target_os = "uefi")] {
+ mod uefi;
+ pub use uefi::*;
} else {
mod unix;
pub use unix::*;
diff --git a/library/std/src/sys/path/uefi.rs b/library/std/src/sys/path/uefi.rs
new file mode 100644
index 0000000000000..a3f4a3bfe1b67
--- /dev/null
+++ b/library/std/src/sys/path/uefi.rs
@@ -0,0 +1,105 @@
+#![forbid(unsafe_op_in_unsafe_fn)]
+use crate::ffi::OsStr;
+use crate::io;
+use crate::path::{Path, PathBuf, Prefix};
+use crate::sys::{helpers, unsupported_err};
+
+const FORWARD_SLASH: u8 = b'/';
+const COLON: u8 = b':';
+
+#[inline]
+pub fn is_sep_byte(b: u8) -> bool {
+ b == b'\\'
+}
+
+#[inline]
+pub fn is_verbatim_sep(b: u8) -> bool {
+ b == b'\\'
+}
+
+pub fn parse_prefix(_: &OsStr) -> Option> {
+ None
+}
+
+pub const MAIN_SEP_STR: &str = "\\";
+pub const MAIN_SEP: char = '\\';
+
+/// UEFI paths can be of 4 types:
+///
+/// 1. Absolute Shell Path: Uses shell mappings (eg: `FS0:`). Does not exist if UEFI shell not present.
+/// It can be identified with `:`.
+/// Eg: FS0:\abc\run.efi
+///
+/// 2. Absolute Device Path: this is what we want
+/// It can be identified with `/`.
+/// Eg: PciRoot(0x0)/Pci(0x1,0x1)/Ata(Secondary,Slave,0x0)/\abc\run.efi
+///
+/// 3: Relative root: path relative to the current volume.
+/// It will start with `\`.
+/// Eg: \abc\run.efi
+///
+/// 4: Relative
+/// Eg: run.efi
+///
+/// The algorithm is mostly taken from edk2 UEFI shell implementation and is
+/// somewhat simple. Check for the path type in order.
+///
+/// The volume mapping in Absolute Shell Path (not the rest of the path) can be converted to Device
+/// Path Protocol using `EFI_SHELL->GetDevicePathFromMap`. The rest of the path (Relative root
+/// path), can just be appended to the remaining path.
+///
+/// For Relative root, we get the current volume (either in Shell Mapping, or Device Path Protocol
+/// form) and join it with the relative root path. We then recurse the function to resolve the Shell
+/// Mapping if present.
+///
+/// For Relative paths, we use the current working directory to construct
+/// the new path and recurse the function to resolve the Shell mapping if present.
+///
+/// Finally, at the end, we get the 2nd form, i.e. Absolute Device Path, which can be used in the
+/// normal UEFI APIs such as file, process, etc.
+/// Eg: PciRoot(0x0)/Pci(0x1,0x1)/Ata(Secondary,Slave,0x0)/\abc\run.efi
+pub(crate) fn absolute(path: &Path) -> io::Result {
+ // Absolute Shell Path
+ if path.as_os_str().as_encoded_bytes().contains(&COLON) {
+ let mut path_components = path.components();
+ // Since path is not empty, it has at least one Component
+ let prefix = path_components.next().unwrap();
+
+ let dev_path = helpers::get_device_path_from_map(prefix.as_ref())?;
+ let mut dev_path_text = dev_path.to_text().map_err(|_| unsupported_err())?;
+
+ // UEFI Shell does not seem to end device path with `/`
+ if *dev_path_text.as_encoded_bytes().last().unwrap() != FORWARD_SLASH {
+ dev_path_text.push("/");
+ }
+
+ let mut ans = PathBuf::from(dev_path_text);
+ ans.push(path_components);
+
+ return Ok(ans);
+ }
+
+ // Absolute Device Path
+ if path.as_os_str().as_encoded_bytes().contains(&FORWARD_SLASH) {
+ return Ok(path.to_path_buf());
+ }
+
+ // cur_dir() always returns something
+ let cur_dir = crate::env::current_dir().unwrap();
+ let mut path_components = path.components();
+
+ // Relative Root
+ if path_components.next().unwrap() == crate::path::Component::RootDir {
+ let mut ans = PathBuf::new();
+ ans.push(cur_dir.components().next().unwrap());
+ ans.push(path_components);
+ return absolute(&ans);
+ }
+
+ absolute(&cur_dir.join(path))
+}
+
+pub(crate) fn is_absolute(path: &Path) -> bool {
+ let temp = path.as_os_str().as_encoded_bytes();
+ temp.contains(&COLON) || temp.contains(&FORWARD_SLASH)
+}
diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs
index 5e250d18ce6aa..825e5452f0e6a 100644
--- a/src/bootstrap/src/core/build_steps/test.rs
+++ b/src/bootstrap/src/core/build_steps/test.rs
@@ -86,6 +86,7 @@ impl Step for CrateBootstrap {
SourceType::InTree,
&[],
);
+
let crate_name = path.rsplit_once('/').unwrap().1;
run_cargo_test(cargo, &[], &[], crate_name, crate_name, bootstrap_host, builder);
}
@@ -3106,6 +3107,8 @@ impl Step for Bootstrap {
&[],
);
+ cargo.release_build(false);
+
cargo
.rustflag("-Cdebuginfo=2")
.env("CARGO_TARGET_DIR", builder.out.join("bootstrap"))
diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs
index 1b413dcb07efb..f6a03a386d170 100644
--- a/src/bootstrap/src/core/builder/cargo.rs
+++ b/src/bootstrap/src/core/builder/cargo.rs
@@ -88,12 +88,14 @@ impl HostFlags {
#[derive(Debug)]
pub struct Cargo {
command: BootstrapCommand,
+ args: Vec,
compiler: Compiler,
target: TargetSelection,
rustflags: Rustflags,
rustdocflags: Rustflags,
hostflags: HostFlags,
allow_features: String,
+ release_build: bool,
}
impl Cargo {
@@ -121,6 +123,10 @@ impl Cargo {
cargo
}
+ pub fn release_build(&mut self, release_build: bool) {
+ self.release_build = release_build;
+ }
+
pub fn compiler(&self) -> Compiler {
self.compiler
}
@@ -153,7 +159,7 @@ impl Cargo {
}
pub fn arg(&mut self, arg: impl AsRef) -> &mut Cargo {
- self.command.arg(arg.as_ref());
+ self.args.push(arg.as_ref().into());
self
}
@@ -342,6 +348,12 @@ impl Cargo {
impl From for BootstrapCommand {
fn from(mut cargo: Cargo) -> BootstrapCommand {
+ if cargo.release_build {
+ cargo.args.insert(0, "--release".into());
+ }
+
+ cargo.command.args(cargo.args);
+
let rustflags = &cargo.rustflags.0;
if !rustflags.is_empty() {
cargo.command.env("RUSTFLAGS", rustflags);
@@ -360,6 +372,7 @@ impl From for BootstrapCommand {
if !cargo.allow_features.is_empty() {
cargo.command.env("RUSTC_ALLOW_FEATURES", cargo.allow_features);
}
+
cargo.command
}
}
@@ -429,13 +442,6 @@ impl Builder<'_> {
assert_eq!(target, compiler.host);
}
- if self.config.rust_optimize.is_release() &&
- // cargo bench/install do not accept `--release` and miri doesn't want it
- !matches!(cmd_kind, Kind::Bench | Kind::Install | Kind::Miri | Kind::MiriSetup | Kind::MiriTest)
- {
- cargo.arg("--release");
- }
-
// Remove make-related flags to ensure Cargo can correctly set things up
cargo.env_remove("MAKEFLAGS");
cargo.env_remove("MFLAGS");
@@ -1218,14 +1224,20 @@ impl Builder<'_> {
rustflags.arg("-Zmir_strip_debuginfo=locals-in-tiny-functions");
}
+ let release_build = self.config.rust_optimize.is_release() &&
+ // cargo bench/install do not accept `--release` and miri doesn't want it
+ !matches!(cmd_kind, Kind::Bench | Kind::Install | Kind::Miri | Kind::MiriSetup | Kind::MiriTest);
+
Cargo {
command: cargo,
+ args: vec![],
compiler,
target,
rustflags,
rustdocflags,
hostflags,
allow_features,
+ release_build,
}
}
}
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index 77040aeb94d77..0b4fd9c22589c 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -344,10 +344,8 @@ pub(crate) fn print_const(cx: &DocContext<'_>, n: ty::Const<'_>) -> String {
s
}
// array lengths are obviously usize
- ty::ConstKind::Value(ty, ty::ValTree::Leaf(scalar))
- if *ty.kind() == ty::Uint(ty::UintTy::Usize) =>
- {
- scalar.to_string()
+ ty::ConstKind::Value(cv) if *cv.ty.kind() == ty::Uint(ty::UintTy::Usize) => {
+ cv.valtree.unwrap_leaf().to_string()
}
_ => n.to_string(),
}
diff --git a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs
index 623b6b4fcc145..cabf10b7e0ea9 100644
--- a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs
+++ b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs
@@ -56,9 +56,8 @@ impl<'tcx> LateLintPass<'tcx> for LargeConstArrays {
&& !item.span.from_expansion()
&& let ty = cx.tcx.type_of(item.owner_id).instantiate_identity()
&& let ty::Array(element_type, cst) = ty.kind()
- && let Some((ty::ValTree::Leaf(element_count), _)) = cx.tcx
- .try_normalize_erasing_regions(cx.typing_env(), *cst).unwrap_or(*cst).try_to_valtree()
- && let element_count = element_count.to_target_usize(cx.tcx)
+ && let Some(element_count) = cx.tcx
+ .try_normalize_erasing_regions(cx.typing_env(), *cst).unwrap_or(*cst).try_to_target_usize(cx.tcx)
&& let Ok(element_size) = cx.layout_of(*element_type).map(|l| l.size.bytes())
&& u128::from(self.maximum_allowed_size) < u128::from(element_count) * u128::from(element_size)
{
diff --git a/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs b/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs
index 46d7df6995a9e..6f5c5d6b3ea3f 100644
--- a/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs
+++ b/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs
@@ -8,7 +8,7 @@ use clippy_utils::source::snippet;
use rustc_hir::{Expr, ExprKind, Item, ItemKind, Node};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::layout::LayoutOf;
-use rustc_middle::ty::{self, ConstKind};
+use rustc_middle::ty;
use rustc_session::impl_lint_pass;
use rustc_span::{Span, sym};
@@ -81,8 +81,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeStackArrays {
&& let ExprKind::Repeat(_, _) | ExprKind::Array(_) = expr.kind
&& !self.is_from_vec_macro(cx, expr.span)
&& let ty::Array(element_type, cst) = cx.typeck_results().expr_ty(expr).kind()
- && let ConstKind::Value(_, ty::ValTree::Leaf(element_count)) = cst.kind()
- && let element_count = element_count.to_target_usize(cx.tcx)
+ && let Some(element_count) = cst.try_to_target_usize(cx.tcx)
&& let Ok(element_size) = cx.layout_of(*element_type).map(|l| l.size.bytes())
&& !cx.tcx.hir().parent_iter(expr.hir_id).any(|(_, node)| {
matches!(
diff --git a/src/tools/miri/src/intrinsics/simd.rs b/src/tools/miri/src/intrinsics/simd.rs
index 54bdd3f02c2c2..63a61dcd14878 100644
--- a/src/tools/miri/src/intrinsics/simd.rs
+++ b/src/tools/miri/src/intrinsics/simd.rs
@@ -640,7 +640,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
let (dest, dest_len) = this.project_to_simd(dest)?;
let index =
- generic_args[2].expect_const().try_to_valtree().unwrap().0.unwrap_branch();
+ generic_args[2].expect_const().to_value().valtree.unwrap_branch();
let index_len = index.len();
assert_eq!(left_len, right_len);
diff --git a/src/tools/opt-dist/src/main.rs b/src/tools/opt-dist/src/main.rs
index 04de3493ea29c..565721a909344 100644
--- a/src/tools/opt-dist/src/main.rs
+++ b/src/tools/opt-dist/src/main.rs
@@ -148,16 +148,6 @@ fn create_environment(args: Args) -> anyhow::Result<(Environment, Vec)>
let is_aarch64 = target_triple.starts_with("aarch64");
- let skip_tests = if is_aarch64 {
- vec![
- // Those tests fail only inside of Docker on aarch64, as of December 2024
- "tests/ui/consts/promoted_running_out_of_memory_issue-130687.rs".to_string(),
- "tests/ui/consts/large_const_alloc.rs".to_string(),
- ]
- } else {
- vec![]
- };
-
let checkout_dir = Utf8PathBuf::from("/checkout");
let env = EnvironmentBuilder::default()
.host_tuple(target_triple)
@@ -169,7 +159,7 @@ fn create_environment(args: Args) -> anyhow::Result<(Environment, Vec)>
.shared_llvm(true)
// FIXME: Enable bolt for aarch64 once it's fixed upstream. Broken as of December 2024.
.use_bolt(!is_aarch64)
- .skipped_tests(skip_tests)
+ .skipped_tests(vec![])
.build()?;
(env, shared.build_args)
diff --git a/tests/crashes/131102.rs b/tests/crashes/131102.rs
deleted file mode 100644
index 12b35f8d1b2ac..0000000000000
--- a/tests/crashes/131102.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-//@ known-bug: #131102
-pub struct Blorb([String; N]);
-pub struct Wrap(Blorb<0>);
-pub const fn i(_: Wrap) {}
diff --git a/tests/ui/consts/bad-array-size-in-type-err.rs b/tests/ui/consts/bad-array-size-in-type-err.rs
index cb02ad3205db6..0490a9d3620ee 100644
--- a/tests/ui/consts/bad-array-size-in-type-err.rs
+++ b/tests/ui/consts/bad-array-size-in-type-err.rs
@@ -8,3 +8,14 @@ fn main() {
//~^ ERROR mismatched types
//~| ERROR the constant `2` is not of type `usize`
}
+
+fn iter(val: BadArraySize::<2>) {
+ for _ in val.arr {}
+ //~^ ERROR the constant `2` is not of type `usize`
+ //~| ERROR `[i32; 2]` is not an iterator
+}
+
+// issue #131102
+pub struct Blorb([String; N]); //~ ERROR the constant `N` is not of type `usize`
+pub struct Wrap(Blorb<0>);
+pub const fn i(_: Wrap) {} //~ ERROR destructor of `Wrap` cannot be evaluated at compile-time
diff --git a/tests/ui/consts/bad-array-size-in-type-err.stderr b/tests/ui/consts/bad-array-size-in-type-err.stderr
index c3ff216432eeb..84e16f8d931ea 100644
--- a/tests/ui/consts/bad-array-size-in-type-err.stderr
+++ b/tests/ui/consts/bad-array-size-in-type-err.stderr
@@ -6,6 +6,14 @@ LL | arr: [i32; N],
|
= note: the length of array `[i32; N]` must be type `usize`
+error: the constant `N` is not of type `usize`
+ --> $DIR/bad-array-size-in-type-err.rs:19:32
+ |
+LL | pub struct Blorb([String; N]);
+ | ^^^^^^^^^^^ expected `usize`, found `u16`
+ |
+ = note: the length of array `[String; N]` must be type `usize`
+
error[E0308]: mismatched types
--> $DIR/bad-array-size-in-type-err.rs:7:38
|
@@ -20,6 +28,37 @@ LL | let _ = BadArraySize::<2> { arr: [0, 0, 0] };
|
= note: the length of array `[i32; 2]` must be type `usize`
-error: aborting due to 3 previous errors
+error: the constant `2` is not of type `usize`
+ --> $DIR/bad-array-size-in-type-err.rs:13:14
+ |
+LL | for _ in val.arr {}
+ | ^^^^^^^ expected `usize`, found `u8`
+ |
+ = note: the length of array `[i32; 2]` must be type `usize`
+
+error[E0277]: `[i32; 2]` is not an iterator
+ --> $DIR/bad-array-size-in-type-err.rs:13:14
+ |
+LL | for _ in val.arr {}
+ | ^^^^^^^ `[i32; 2]` is not an iterator; try calling `.into_iter()` or `.iter()`
+ |
+ = help: the trait `IntoIterator` is not implemented for `[i32; 2]`
+ = help: the following other types implement trait `IntoIterator`:
+ &[T; N]
+ &[T]
+ &mut [T; N]
+ &mut [T]
+ [T; N]
+
+error[E0493]: destructor of `Wrap` cannot be evaluated at compile-time
+ --> $DIR/bad-array-size-in-type-err.rs:21:16
+ |
+LL | pub const fn i(_: Wrap) {}
+ | ^ - value is dropped here
+ | |
+ | the destructor for this type cannot be evaluated in constant functions
+
+error: aborting due to 7 previous errors
-For more information about this error, try `rustc --explain E0308`.
+Some errors have detailed explanations: E0277, E0308, E0493.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/consts/large_const_alloc.rs b/tests/ui/consts/large_const_alloc.rs
index 61a22216ae526..14edc1bb69610 100644
--- a/tests/ui/consts/large_const_alloc.rs
+++ b/tests/ui/consts/large_const_alloc.rs
@@ -1,5 +1,7 @@
//@ only-64bit
// on 32bit and 16bit platforms it is plausible that the maximum allocation size will succeed
+// FIXME (#135952) In some cases on AArch64 Linux the diagnostic does not trigger
+//@ ignore-aarch64-unknown-linux-gnu
const FOO: () = {
// 128 TiB, unlikely anyone has that much RAM
diff --git a/tests/ui/consts/large_const_alloc.stderr b/tests/ui/consts/large_const_alloc.stderr
index 25d660f1217f4..fa7d5977a9567 100644
--- a/tests/ui/consts/large_const_alloc.stderr
+++ b/tests/ui/consts/large_const_alloc.stderr
@@ -1,11 +1,11 @@
error[E0080]: evaluation of constant value failed
- --> $DIR/large_const_alloc.rs:6:13
+ --> $DIR/large_const_alloc.rs:8:13
|
LL | let x = [0_u8; (1 << 47) - 1];
| ^^^^^^^^^^^^^^^^^^^^^ tried to allocate more memory than available to compiler
error[E0080]: could not evaluate static initializer
- --> $DIR/large_const_alloc.rs:11:13
+ --> $DIR/large_const_alloc.rs:13:13
|
LL | let x = [0_u8; (1 << 47) - 1];
| ^^^^^^^^^^^^^^^^^^^^^ tried to allocate more memory than available to compiler
diff --git a/tests/ui/consts/promoted_running_out_of_memory_issue-130687.rs b/tests/ui/consts/promoted_running_out_of_memory_issue-130687.rs
index b923a768cbfe5..53618e2e86acd 100644
--- a/tests/ui/consts/promoted_running_out_of_memory_issue-130687.rs
+++ b/tests/ui/consts/promoted_running_out_of_memory_issue-130687.rs
@@ -3,6 +3,8 @@
// Needs the max type size to be much bigger than the RAM people typically have.
//@ only-64bit
+// FIXME (#135952) In some cases on AArch64 Linux the diagnostic does not trigger
+//@ ignore-aarch64-unknown-linux-gnu
pub struct Data([u8; (1 << 47) - 1]);
const _: &'static Data = &Data([0; (1 << 47) - 1]);
diff --git a/tests/ui/consts/promoted_running_out_of_memory_issue-130687.stderr b/tests/ui/consts/promoted_running_out_of_memory_issue-130687.stderr
index f5d767efceb76..aac805dbd8c79 100644
--- a/tests/ui/consts/promoted_running_out_of_memory_issue-130687.stderr
+++ b/tests/ui/consts/promoted_running_out_of_memory_issue-130687.stderr
@@ -1,5 +1,5 @@
error[E0080]: evaluation of constant value failed
- --> $DIR/promoted_running_out_of_memory_issue-130687.rs:8:32
+ --> $DIR/promoted_running_out_of_memory_issue-130687.rs:10:32
|
LL | const _: &'static Data = &Data([0; (1 << 47) - 1]);
| ^^^^^^^^^^^^^^^^^^ tried to allocate more memory than available to compiler