From 888efe74a3b1f54fcb34e5c8c4f17dd2a381989f Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Fri, 18 Oct 2024 00:00:23 -0700 Subject: cg_llvm: Switch `llvm::add_global` to `&CStr` --- compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs | 2 +- compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs | 12 +++++++----- compiler/rustc_codegen_llvm/src/llvm/mod.rs | 3 +-- 3 files changed, 9 insertions(+), 8 deletions(-) (limited to 'compiler/rustc_codegen_llvm/src') diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index c2c261da79b..4075849323a 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -132,7 +132,7 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) { .collect::>(); let initializer = cx.const_array(cx.type_ptr(), &name_globals); - let array = llvm::add_global(cx.llmod, cx.val_ty(initializer), "__llvm_coverage_names"); + let array = llvm::add_global(cx.llmod, cx.val_ty(initializer), c"__llvm_coverage_names"); llvm::set_global_constant(array, true); llvm::set_linkage(array, llvm::Linkage::InternalLinkage); llvm::set_initializer(array, initializer); diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs index d7d29eebf85..4192dc39de0 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs @@ -1,4 +1,5 @@ use std::cell::RefCell; +use std::ffi::CString; use libc::c_uint; use rustc_codegen_ssa::traits::{ @@ -284,10 +285,10 @@ pub(crate) fn save_cov_data_to_mod<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, cov_data_val: &'ll llvm::Value, ) { - let covmap_var_name = llvm::build_string(|s| unsafe { + let covmap_var_name = CString::new(llvm::build_byte_buffer(|s| unsafe { llvm::LLVMRustCoverageWriteMappingVarNameToString(s); - }) - .expect("Rust Coverage Mapping var name failed UTF-8 conversion"); + })) + .unwrap(); debug!("covmap var name: {:?}", covmap_var_name); let covmap_section_name = llvm::build_string(|s| unsafe { @@ -322,7 +323,8 @@ pub(crate) fn save_func_record_to_mod<'ll, 'tcx>( // of descriptions play distinct roles in LLVM IR; therefore, assign them different names (by // appending "u" to the end of the function record var name, to prevent `linkonce_odr` merging. let func_record_var_name = - format!("__covrec_{:X}{}", func_name_hash, if is_used { "u" } else { "" }); + CString::new(format!("__covrec_{:X}{}", func_name_hash, if is_used { "u" } else { "" })) + .unwrap(); debug!("function record var name: {:?}", func_record_var_name); debug!("function record section name: {:?}", covfun_section_name); @@ -334,7 +336,7 @@ pub(crate) fn save_func_record_to_mod<'ll, 'tcx>( llvm::set_section(llglobal, covfun_section_name); // LLVM's coverage mapping format specifies 8-byte alignment for items in this section. llvm::set_alignment(llglobal, Align::EIGHT); - llvm::set_comdat(cx.llmod, llglobal, &func_record_var_name); + llvm::set_comdat(cx.llmod, llglobal, func_record_var_name.to_str().unwrap()); cx.add_used_global(llglobal); } diff --git a/compiler/rustc_codegen_llvm/src/llvm/mod.rs b/compiler/rustc_codegen_llvm/src/llvm/mod.rs index d0db350a149..e790c6696fa 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/mod.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/mod.rs @@ -217,8 +217,7 @@ pub fn set_section(llglobal: &Value, section_name: &str) { } } -pub fn add_global<'a>(llmod: &'a Module, ty: &'a Type, name: &str) -> &'a Value { - let name_cstr = CString::new(name).expect("unexpected CString error"); +pub fn add_global<'a>(llmod: &'a Module, ty: &'a Type, name_cstr: &CStr) -> &'a Value { unsafe { LLVMAddGlobal(llmod, ty, name_cstr.as_ptr()) } } -- cgit 1.4.1-3-g733a5 From 45d61b0d2654373405e2a8d44289e883847873e4 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Fri, 18 Oct 2024 00:31:28 -0700 Subject: cg_llvm: Reuse LLVM-C Comdat support Migrate `llvm::set_comdat` and `llvm::SetUniqueComdat` to LLVM-C FFI. Note, now we can call `llvm::set_comdat` only when the target actually supports adding comdat. As this has no convenient LLVM-C API, we implement this as `TargetOptions::supports_comdat`. Co-authored-by: Stuart Cook --- compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs | 5 ++++- compiler/rustc_codegen_llvm/src/intrinsic.rs | 4 +++- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 5 ++++- compiler/rustc_codegen_llvm/src/llvm/mod.rs | 17 +++++++++++------ compiler/rustc_codegen_llvm/src/mono_item.rs | 4 +++- compiler/rustc_target/src/spec/mod.rs | 7 +++++++ 6 files changed, 32 insertions(+), 10 deletions(-) (limited to 'compiler/rustc_codegen_llvm/src') diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs index 4192dc39de0..4f93e6ab1e5 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs @@ -13,6 +13,7 @@ use rustc_middle::mir::coverage::CoverageKind; use rustc_middle::ty::Instance; use rustc_middle::ty::layout::HasTyCtxt; use rustc_target::abi::{Align, Size}; +use rustc_target::spec::HasTargetSpec; use tracing::{debug, instrument}; use crate::builder::Builder; @@ -336,7 +337,9 @@ pub(crate) fn save_func_record_to_mod<'ll, 'tcx>( llvm::set_section(llglobal, covfun_section_name); // LLVM's coverage mapping format specifies 8-byte alignment for items in this section. llvm::set_alignment(llglobal, Align::EIGHT); - llvm::set_comdat(cx.llmod, llglobal, func_record_var_name.to_str().unwrap()); + if cx.target_spec().supports_comdat() { + llvm::set_comdat(cx.llmod, llglobal, &func_record_var_name); + } cx.add_used_global(llglobal); } diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index bfe623e7fc3..64f1d21b438 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -787,7 +787,9 @@ fn codegen_msvc_try<'ll>( let tydesc = bx.declare_global("__rust_panic_type_info", bx.val_ty(type_info)); unsafe { llvm::LLVMRustSetLinkage(tydesc, llvm::Linkage::LinkOnceODRLinkage); - llvm::SetUniqueComdat(bx.llmod, tydesc); + if bx.cx.tcx.sess.target.supports_comdat() { + llvm::SetUniqueComdat(bx.llmod, tydesc); + } llvm::LLVMSetInitializer(tydesc, type_info); } diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 661debbb9f1..d0034de06c7 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -646,6 +646,7 @@ unsafe extern "C" { pub type Attribute; pub type Metadata; pub type BasicBlock; + pub type Comdat; } #[repr(C)] pub struct Builder<'a>(InvariantOpaque<'a>); @@ -1490,6 +1491,9 @@ unsafe extern "C" { pub fn LLVMSetUnnamedAddress(Global: &Value, UnnamedAddr: UnnamedAddr); pub fn LLVMIsAConstantInt(value_ref: &Value) -> Option<&ConstantInt>; + + pub fn LLVMGetOrInsertComdat(M: &Module, Name: *const c_char) -> &Comdat; + pub fn LLVMSetComdat(V: &Value, C: &Comdat); } #[link(name = "llvm-wrapper", kind = "static")] @@ -2320,7 +2324,6 @@ unsafe extern "C" { pub fn LLVMRustPositionBuilderAtStart<'a>(B: &Builder<'a>, BB: &'a BasicBlock); - pub fn LLVMRustSetComdat<'a>(M: &'a Module, V: &'a Value, Name: *const c_char, NameLen: size_t); pub fn LLVMRustSetModulePICLevel(M: &Module); pub fn LLVMRustSetModulePIELevel(M: &Module); pub fn LLVMRustSetModuleCodeModel(M: &Module, Model: CodeModel); diff --git a/compiler/rustc_codegen_llvm/src/llvm/mod.rs b/compiler/rustc_codegen_llvm/src/llvm/mod.rs index e790c6696fa..b306396e15a 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/mod.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/mod.rs @@ -178,10 +178,10 @@ pub fn SetFunctionCallConv(fn_: &Value, cc: CallConv) { // function. // For more details on COMDAT sections see e.g., https://www.airs.com/blog/archives/52 pub fn SetUniqueComdat(llmod: &Module, val: &Value) { - unsafe { - let name = get_value_name(val); - LLVMRustSetComdat(llmod, val, name.as_ptr().cast(), name.len()); - } + let name_buf = get_value_name(val).to_vec(); + let name = + CString::from_vec_with_nul(name_buf).or_else(|buf| CString::new(buf.into_bytes())).unwrap(); + set_comdat(llmod, val, &name); } pub fn SetUnnamedAddress(global: &Value, unnamed: UnnamedAddr) { @@ -251,9 +251,14 @@ pub fn set_alignment(llglobal: &Value, align: Align) { } } -pub fn set_comdat(llmod: &Module, llglobal: &Value, name: &str) { +/// Get the `name`d comdat from `llmod` and assign it to `llglobal`. +/// +/// Inserts the comdat into `llmod` if it does not exist. +/// It is an error to call this if the target does not support comdat. +pub fn set_comdat(llmod: &Module, llglobal: &Value, name: &CStr) { unsafe { - LLVMRustSetComdat(llmod, llglobal, name.as_ptr().cast(), name.len()); + let comdat = LLVMGetOrInsertComdat(llmod, name.as_ptr()); + LLVMSetComdat(llglobal, comdat); } } diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs index 02e1995620b..bf6ef219873 100644 --- a/compiler/rustc_codegen_llvm/src/mono_item.rs +++ b/compiler/rustc_codegen_llvm/src/mono_item.rs @@ -64,7 +64,9 @@ impl<'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> { unsafe { llvm::LLVMRustSetLinkage(lldecl, base::linkage_to_llvm(linkage)) }; let attrs = self.tcx.codegen_fn_attrs(instance.def_id()); base::set_link_section(lldecl, attrs); - if linkage == Linkage::LinkOnceODR || linkage == Linkage::WeakODR { + if (linkage == Linkage::LinkOnceODR || linkage == Linkage::WeakODR) + && self.tcx.sess.target.supports_comdat() + { llvm::SetUniqueComdat(self.llmod, lldecl); } diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 82e11a3afce..f4b45a08195 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -2514,6 +2514,13 @@ fn add_link_args(link_args: &mut LinkArgs, flavor: LinkerFlavor, args: &[&'stati add_link_args_iter(link_args, flavor, args.iter().copied().map(Cow::Borrowed)) } +impl TargetOptions { + pub fn supports_comdat(&self) -> bool { + // XCOFF and MachO don't support COMDAT. + !self.is_like_aix && !self.is_like_osx + } +} + impl TargetOptions { fn link_args(flavor: LinkerFlavor, args: &[&'static str]) -> LinkArgs { let mut link_args = LinkArgs::new(); -- cgit 1.4.1-3-g733a5 From e83e4e81123ea2babc04238d5aca01ec4bf3e763 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 27 Sep 2024 12:56:51 -0400 Subject: Get rid of const eval_* and try_eval_* helpers --- compiler/rustc_borrowck/src/lib.rs | 4 +- compiler/rustc_borrowck/src/type_check/mod.rs | 3 +- compiler/rustc_codegen_llvm/src/intrinsic.rs | 19 ++- .../rustc_codegen_ssa/src/debuginfo/type_names.rs | 18 +-- compiler/rustc_const_eval/src/const_eval/mod.rs | 2 +- compiler/rustc_const_eval/src/interpret/cast.rs | 4 +- compiler/rustc_hir_analysis/src/check/check.rs | 6 +- .../rustc_hir_analysis/src/check/intrinsicck.rs | 4 +- compiler/rustc_lint/src/builtin.rs | 2 +- compiler/rustc_lint/src/unused.rs | 2 +- compiler/rustc_middle/src/mir/consts.rs | 11 +- compiler/rustc_middle/src/mir/tcx.rs | 7 +- compiler/rustc_middle/src/ty/consts.rs | 132 +++++---------------- .../src/ty/inhabitedness/inhabited_predicate.rs | 2 +- compiler/rustc_middle/src/ty/layout.rs | 2 +- compiler/rustc_middle/src/ty/sty.rs | 7 +- compiler/rustc_mir_dataflow/src/elaborate_drops.rs | 2 +- .../rustc_mir_dataflow/src/move_paths/builder.rs | 16 +-- compiler/rustc_mir_dataflow/src/move_paths/mod.rs | 5 +- compiler/rustc_mir_dataflow/src/rustc_peek.rs | 3 +- compiler/rustc_mir_transform/src/coroutine.rs | 3 +- .../rustc_mir_transform/src/elaborate_drops.rs | 3 +- .../rustc_mir_transform/src/known_panics_lint.rs | 2 +- compiler/rustc_mir_transform/src/promote_consts.rs | 4 +- .../rustc_mir_transform/src/remove_uninit_drops.rs | 3 +- .../src/cfi/typeid/itanium_cxx_abi/encode.rs | 8 +- compiler/rustc_smir/src/rustc_smir/context.rs | 2 +- compiler/rustc_symbol_mangling/src/v0.rs | 4 +- .../src/error_reporting/traits/on_unimplemented.rs | 2 +- compiler/rustc_transmute/src/lib.rs | 3 +- compiler/rustc_ty_utils/src/layout.rs | 6 +- 31 files changed, 119 insertions(+), 172 deletions(-) (limited to 'compiler/rustc_codegen_llvm/src') diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index cbf8aa313c5..698fdafc936 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -187,10 +187,10 @@ fn do_mir_borrowck<'tcx>( let location_table = LocationTable::new(body); - let move_data = MoveData::gather_moves(body, tcx, param_env, |_| true); + let move_data = MoveData::gather_moves(body, tcx, |_| true); let promoted_move_data = promoted .iter_enumerated() - .map(|(idx, body)| (idx, MoveData::gather_moves(body, tcx, param_env, |_| true))); + .map(|(idx, body)| (idx, MoveData::gather_moves(body, tcx, |_| true))); let mut flow_inits = MaybeInitializedPlaces::new(tcx, body, &move_data) .into_engine(tcx, body) diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 238d7d0749a..7b60a632c30 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1128,7 +1128,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } let projected_ty = curr_projected_ty.projection_ty_core( tcx, - self.param_env, proj, |this, field, ()| { let ty = this.field_ty(tcx, field); @@ -1919,7 +1918,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // than 1. // If the length is larger than 1, the repeat expression will need to copy the // element, so we require the `Copy` trait. - if len.try_eval_target_usize(tcx, self.param_env).map_or(true, |len| len > 1) { + if len.try_to_target_usize(tcx).is_none_or(|len| len > 1) { match operand { Operand::Copy(..) | Operand::Constant(..) => { // These are always okay: direct use of a const, or a value that can evidently be copied. diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index bfe623e7fc3..e896e14d650 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -1177,8 +1177,10 @@ fn generic_simd_intrinsic<'ll, 'tcx>( ty::Uint(i) if i.bit_width() == Some(expected_int_bits) => args[0].immediate(), ty::Array(elem, len) if matches!(elem.kind(), ty::Uint(ty::UintTy::U8)) - && len.try_eval_target_usize(bx.tcx, ty::ParamEnv::reveal_all()) - == Some(expected_bytes) => + && len + .try_to_target_usize(bx.tcx) + .expect("expected monomorphic const in codegen") + == expected_bytes => { let place = PlaceRef::alloca(bx, args[0].layout); args[0].val.store(bx, place); @@ -1243,12 +1245,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>( } if name == sym::simd_shuffle_generic { - let idx = fn_args[2] - .expect_const() - .eval(tcx, ty::ParamEnv::reveal_all(), span) - .unwrap() - .1 - .unwrap_branch(); + let idx = fn_args[2].expect_const().try_to_valtree().unwrap().0.unwrap_branch(); let n = idx.len() as u64; let (out_len, out_ty) = require_simd!(ret_ty, SimdReturn); @@ -1467,8 +1464,10 @@ fn generic_simd_intrinsic<'ll, 'tcx>( } ty::Array(elem, len) if matches!(elem.kind(), ty::Uint(ty::UintTy::U8)) - && len.try_eval_target_usize(bx.tcx, ty::ParamEnv::reveal_all()) - == Some(expected_bytes) => + && len + .try_to_target_usize(bx.tcx) + .expect("expected monomorphic const in codegen") + == expected_bytes => { // Zero-extend iN to the array length: let ze = bx.zext(i_, bx.type_ix(expected_bytes * 8)); diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index 369ab387bea..526d2b86d48 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -23,7 +23,6 @@ use rustc_middle::ty::layout::{IntegerExt, TyAndLayout}; use rustc_middle::ty::{ self, ExistentialProjection, GenericArgKind, GenericArgsRef, ParamEnv, Ty, TyCtxt, }; -use rustc_span::DUMMY_SP; use rustc_target::abi::Integer; use smallvec::SmallVec; @@ -685,21 +684,25 @@ 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, _) => { + ty::ConstKind::Value(ty, valtree) => { match 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.eval_bits(tcx, ty::ParamEnv::reveal_all()); + let bits = ct + .try_to_bits(tcx, ty::ParamEnv::reveal_all()) + .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.eval_bits(tcx, ty::ParamEnv::reveal_all()); + let val = ct + .try_to_bits(tcx, ty::ParamEnv::reveal_all()) + .expect("expected monomorphic const in codegen"); write!(output, "{val}") } ty::Bool => { - let val = ct.try_eval_bool(tcx, ty::ParamEnv::reveal_all()).unwrap(); + let val = ct.try_to_bool().expect("expected monomorphic const in codegen"); write!(output, "{val}") } _ => { @@ -711,8 +714,9 @@ 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(); - let ct = ct.eval(tcx, ty::ParamEnv::reveal_all(), DUMMY_SP).unwrap(); - hcx.while_hashing_spans(false, |hcx| ct.hash_stable(hcx, &mut hasher)); + hcx.while_hashing_spans(false, |hcx| { + (ty, valtree).hash_stable(hcx, &mut hasher) + }); hasher.finish::() }); diff --git a/compiler/rustc_const_eval/src/const_eval/mod.rs b/compiler/rustc_const_eval/src/const_eval/mod.rs index ba19f642795..e2e4754a45c 100644 --- a/compiler/rustc_const_eval/src/const_eval/mod.rs +++ b/compiler/rustc_const_eval/src/const_eval/mod.rs @@ -43,7 +43,7 @@ pub(crate) fn try_destructure_mir_constant_for_user_output<'tcx>( // We go to `usize` as we cannot allocate anything bigger anyway. let (field_count, variant, down) = match ty.kind() { - ty::Array(_, len) => (len.eval_target_usize(tcx.tcx, param_env) as usize, None, op), + ty::Array(_, len) => (len.try_to_target_usize(tcx.tcx)? as usize, None, op), ty::Adt(def, _) if def.variants().is_empty() => { return None; } diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index 1def3d08328..64b15611316 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -391,7 +391,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let ptr = self.read_pointer(src)?; let val = Immediate::new_slice( ptr, - length.eval_target_usize(*self.tcx, self.param_env), + length + .try_to_target_usize(*self.tcx) + .expect("expected monomorphic const in const eval"), self, ); self.write_immediate(val, dest) diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 94da3d4ea84..34f596271aa 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -1037,7 +1037,11 @@ fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) { return; } - if let Some(len) = len_const.try_eval_target_usize(tcx, tcx.param_env(def.did())) { + // FIXME(repr_simd): This check is nice, but perhaps unnecessary due to the fact + // we do not expect users to implement their own `repr(simd)` types. If they could, + // this check is easily side-steppable by hiding the const behind normalization. + // The consequence is that the error is, in general, only observable post-mono. + if let Some(len) = len_const.try_to_target_usize(tcx) { if len == 0 { struct_span_code_err!(tcx.dcx(), sp, E0075, "SIMD vector cannot be empty").emit(); return; diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs index 71eb368185e..bbff00cd3b3 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs @@ -76,9 +76,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { let (size, ty) = match elem_ty.kind() { ty::Array(ty, len) => { - if let Some(len) = - len.try_eval_target_usize(self.tcx, self.tcx.param_env(adt.did())) - { + if let Some(len) = len.try_to_target_usize(self.tcx) { (len, *ty) } else { return None; diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 8bd9c899a62..ef8100da9e2 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -2601,7 +2601,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue { ty.tuple_fields().iter().find_map(|field| ty_find_init_error(cx, field, init)) } Array(ty, len) => { - if matches!(len.try_eval_target_usize(cx.tcx, cx.param_env), Some(v) if v > 0) { + if matches!(len.try_to_target_usize(cx.tcx), Some(v) if v > 0) { // Array length known at array non-empty -- recurse. ty_find_init_error(cx, *ty, init) } else { diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 1a007250961..ddc18c755a8 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -346,7 +346,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { None } } - ty::Array(ty, len) => match len.try_eval_target_usize(cx.tcx, cx.param_env) { + ty::Array(ty, len) => match len.try_to_target_usize(cx.tcx) { // If the array is empty we don't lint, to avoid false positives Some(0) | None => None, // If the array is definitely non-empty, we can do `#[must_use]` checking. diff --git a/compiler/rustc_middle/src/mir/consts.rs b/compiler/rustc_middle/src/mir/consts.rs index 4262460d928..1be2f6b9bb5 100644 --- a/compiler/rustc_middle/src/mir/consts.rs +++ b/compiler/rustc_middle/src/mir/consts.rs @@ -6,6 +6,7 @@ use rustc_session::RemapFileNameExt; use rustc_session::config::RemapPathScopeComponents; use rustc_span::{DUMMY_SP, Span}; use rustc_target::abi::{HasDataLayout, Size}; +use either::Either; use crate::mir::interpret::{AllocId, ConstAllocation, ErrorHandled, Scalar, alloc_range}; use crate::mir::{Promoted, pretty_print_const_value}; @@ -320,8 +321,14 @@ impl<'tcx> Const<'tcx> { Const::Ty(_, c) => { // We want to consistently have a "clean" value for type system constants (i.e., no // data hidden in the padding), so we always go through a valtree here. - let (ty, val) = c.eval(tcx, param_env, span)?; - Ok(tcx.valtree_to_const_val((ty, val))) + match c.eval_valtree(tcx, param_env, span) { + Ok((ty, val)) => Ok(tcx.valtree_to_const_val((ty, val))), + Err(Either::Left(_bad_ty)) => Err(tcx + .dcx() + .delayed_bug("`mir::Const::eval` called on a non-valtree-compatible type") + .into()), + Err(Either::Right(e)) => Err(e), + } } Const::Unevaluated(uneval, _) => { // FIXME: We might want to have a `try_eval`-like function on `Unevaluated` diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs index 8d57d0d8654..476e352ed92 100644 --- a/compiler/rustc_middle/src/mir/tcx.rs +++ b/compiler/rustc_middle/src/mir/tcx.rs @@ -55,7 +55,7 @@ impl<'tcx> PlaceTy<'tcx> { /// `PlaceElem`, where we can just use the `Ty` that is already /// stored inline on field projection elems. pub fn projection_ty(self, tcx: TyCtxt<'tcx>, elem: PlaceElem<'tcx>) -> PlaceTy<'tcx> { - self.projection_ty_core(tcx, ty::ParamEnv::empty(), &elem, |_, _, ty| ty, |_, ty| ty) + self.projection_ty_core(tcx, &elem, |_, _, ty| ty, |_, ty| ty) } /// `place_ty.projection_ty_core(tcx, elem, |...| { ... })` @@ -66,7 +66,6 @@ impl<'tcx> PlaceTy<'tcx> { pub fn projection_ty_core( self, tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, elem: &ProjectionElem, mut handle_field: impl FnMut(&Self, FieldIdx, T) -> Ty<'tcx>, mut handle_opaque_cast_and_subtype: impl FnMut(&Self, T) -> Ty<'tcx>, @@ -93,7 +92,9 @@ impl<'tcx> PlaceTy<'tcx> { ty::Slice(..) => self.ty, ty::Array(inner, _) if !from_end => Ty::new_array(tcx, *inner, to - from), ty::Array(inner, size) if from_end => { - let size = size.eval_target_usize(tcx, param_env); + let size = size + .try_to_target_usize(tcx) + .expect("expected subslice projection on fixed-size array"); let len = size - from - to; Ty::new_array(tcx, *inner, len) } diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 389d20f315f..c0cd79e9ef2 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -398,133 +398,65 @@ impl<'tcx> Const<'tcx> { } } - /// Returns the evaluated constant - #[inline] - pub fn eval( - self, - tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, - span: Span, - ) -> Result<(Ty<'tcx>, ValTree<'tcx>), ErrorHandled> { - self.eval_valtree(tcx, param_env, span).map_err(|err| { - match err { - Either::Right(err) => err, - Either::Left(_bad_ty) => { - // This can happen when we run on ill-typed code. - let e = tcx.dcx().span_delayed_bug( - span, - "`ty::Const::eval` called on a non-valtree-compatible type", - ); - e.into() - } - } - }) - } - /// Normalizes the constant to a value or an error if possible. #[inline] pub fn normalize(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Self { - match self.eval(tcx, param_env, DUMMY_SP) { + match self.eval_valtree(tcx, param_env, DUMMY_SP) { Ok((ty, val)) => Self::new_value(tcx, val, ty), - Err(ErrorHandled::Reported(r, _span)) => Self::new_error(tcx, r.into()), - Err(ErrorHandled::TooGeneric(_span)) => self, + Err(Either::Left(_bad_ty)) => { + // This can happen when we run on ill-typed code. + Self::new_error( + tcx, + tcx.dcx() + .delayed_bug("`ty::Const::eval` called on a non-valtree-compatible type"), + ) + } + Err(Either::Right(ErrorHandled::Reported(r, _span))) => Self::new_error(tcx, r.into()), + Err(Either::Right(ErrorHandled::TooGeneric(_span))) => self, } } - #[inline] - pub fn try_eval_scalar( - self, - tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, - ) -> Option<(Ty<'tcx>, Scalar)> { - let (ty, val) = self.eval(tcx, param_env, DUMMY_SP).ok()?; - let val = val.try_to_scalar()?; - Some((ty, val)) - } - - #[inline] - /// 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). - pub fn try_eval_scalar_int( - self, - tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, - ) -> Option<(Ty<'tcx>, ScalarInt)> { - let (ty, scalar) = self.try_eval_scalar(tcx, param_env)?; - let val = scalar.try_to_scalar_int().ok()?; - Some((ty, val)) - } - - #[inline] - /// 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). - pub fn try_eval_bits(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option { - let (ty, scalar) = self.try_eval_scalar_int(tcx, param_env)?; - let size = tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size; - // if `ty` does not depend on generic parameters, use an empty param_env - Some(scalar.to_bits(size)) - } - - #[inline] - /// Panics if the value cannot be evaluated or doesn't contain a valid integer of the given type. - pub fn eval_bits(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> u128 { - self.try_eval_bits(tcx, param_env) - .unwrap_or_else(|| bug!("failed to evalate {:#?} to bits", self)) - } - - #[inline] - pub fn try_eval_target_usize( - self, - tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, - ) -> Option { - let (_, scalar) = self.try_eval_scalar_int(tcx, param_env)?; - Some(scalar.to_target_usize(tcx)) - } - - #[inline] - pub fn try_eval_bool(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option { - let (_, scalar) = self.try_eval_scalar_int(tcx, param_env)?; - scalar.try_into().ok() - } - - #[inline] - /// Panics if the value cannot be evaluated or doesn't contain a valid `usize`. - pub fn eval_target_usize(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> u64 { - self.try_eval_target_usize(tcx, param_env) - .unwrap_or_else(|| bug!("expected usize, got {:#?}", self)) - } - /// Panics if self.kind != ty::ConstKind::Value - pub fn to_valtree(self) -> ty::ValTree<'tcx> { + pub fn to_valtree(self) -> (ty::ValTree<'tcx>, Ty<'tcx>) { match self.kind() { - ty::ConstKind::Value(_, valtree) => valtree, + ty::ConstKind::Value(ty, valtree) => (valtree, ty), _ => bug!("expected ConstKind::Value, got {:?}", self.kind()), } } /// Attempts to convert to a `ValTree` - pub fn try_to_valtree(self) -> Option> { + pub fn try_to_valtree(self) -> Option<(ty::ValTree<'tcx>, Ty<'tcx>)> { match self.kind() { - ty::ConstKind::Value(_, valtree) => Some(valtree), + ty::ConstKind::Value(ty, valtree) => Some((valtree, ty)), _ => None, } } #[inline] - pub fn try_to_scalar(self) -> Option { - self.try_to_valtree()?.try_to_scalar() + 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()?.try_to_scalar_int()?.try_to_bool().ok() + self.try_to_valtree()?.0.try_to_scalar_int()?.try_to_bool().ok() } #[inline] pub fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option { - self.try_to_valtree()?.try_to_target_usize(tcx) + self.try_to_valtree()?.0.try_to_target_usize(tcx) + } + + #[inline] + /// 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). + pub fn try_to_bits(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option { + let (scalar, ty) = self.try_to_scalar()?; + let scalar = scalar.try_to_scalar_int().ok()?; + let size = tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size; + // if `ty` does not depend on generic parameters, use an empty param_env + Some(scalar.to_bits(size)) } pub fn is_ct_infer(self) -> bool { diff --git a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs index 54b8507babf..bf741f63a3d 100644 --- a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs +++ b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs @@ -85,7 +85,7 @@ impl<'tcx> InhabitedPredicate<'tcx> { match self { Self::False => Ok(false), Self::True => Ok(true), - Self::ConstIsZero(const_) => match const_.try_eval_target_usize(tcx, param_env) { + Self::ConstIsZero(const_) => match const_.try_to_target_usize(tcx) { None | Some(0) => Ok(true), Some(1..) => Ok(false), }, diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 6c12b691c26..3670b6bbc77 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -397,7 +397,7 @@ impl<'tcx> SizeSkeleton<'tcx> { } } ty::Array(inner, len) if tcx.features().transmute_generic_consts => { - let len_eval = len.try_eval_target_usize(tcx, param_env); + let len_eval = len.try_to_target_usize(tcx); if len_eval == Some(0) { return Ok(SizeSkeleton::Known(Size::from_bytes(0), None)); } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 3f00458d195..74de378c4d7 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1117,7 +1117,12 @@ impl<'tcx> Ty<'tcx> { // The way we evaluate the `N` in `[T; N]` here only works since we use // `simd_size_and_type` post-monomorphization. It will probably start to ICE // if we use it in generic code. See the `simd-array-trait` ui test. - (f0_len.eval_target_usize(tcx, ParamEnv::empty()), *f0_elem_ty) + ( + f0_len + .try_to_target_usize(tcx) + .expect("expected SIMD field to have definite array size"), + *f0_elem_ty, + ) } #[inline] diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs index a3b117a3f19..7f2a07e2f5e 100644 --- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs +++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs @@ -863,7 +863,7 @@ where ty::Adt(def, args) => self.open_drop_for_adt(*def, args), ty::Dynamic(..) => self.complete_drop(self.succ, self.unwind), ty::Array(ety, size) => { - let size = size.try_eval_target_usize(self.tcx(), self.elaborator.param_env()); + let size = size.try_to_target_usize(self.tcx()); self.open_drop_for_array(*ety, size) } ty::Slice(ety) => self.drop_loop_pair(*ety), diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs index 162245cb950..fd8e403ebc2 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs @@ -18,18 +18,12 @@ struct MoveDataBuilder<'a, 'tcx, F> { body: &'a Body<'tcx>, loc: Location, tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, data: MoveData<'tcx>, filter: F, } impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> { - fn new( - body: &'a Body<'tcx>, - tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, - filter: F, - ) -> Self { + fn new(body: &'a Body<'tcx>, tcx: TyCtxt<'tcx>, filter: F) -> Self { let mut move_paths = IndexVec::new(); let mut path_map = IndexVec::new(); let mut init_path_map = IndexVec::new(); @@ -59,7 +53,6 @@ impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> { body, loc: Location::START, tcx, - param_env, data: MoveData { moves: IndexVec::new(), loc_map: LocationMap::new(body), @@ -308,10 +301,9 @@ impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> { pub(super) fn gather_moves<'tcx>( body: &Body<'tcx>, tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, filter: impl Fn(Ty<'tcx>) -> bool, ) -> MoveData<'tcx> { - let mut builder = MoveDataBuilder::new(body, tcx, param_env, filter); + let mut builder = MoveDataBuilder::new(body, tcx, filter); builder.gather_args(); @@ -550,7 +542,9 @@ impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> { }; let base_ty = base_place.ty(self.body, self.tcx).ty; let len: u64 = match base_ty.kind() { - ty::Array(_, size) => size.eval_target_usize(self.tcx, self.param_env), + ty::Array(_, size) => size + .try_to_target_usize(self.tcx) + .expect("expected subslice projection on fixed-size array"), _ => bug!("from_end: false slice pattern of non-array type"), }; for offset in from..to { diff --git a/compiler/rustc_mir_dataflow/src/move_paths/mod.rs b/compiler/rustc_mir_dataflow/src/move_paths/mod.rs index bc1177976b5..926bd187431 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/mod.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/mod.rs @@ -4,7 +4,7 @@ use std::ops::{Index, IndexMut}; use rustc_data_structures::fx::FxHashMap; use rustc_index::{IndexSlice, IndexVec}; use rustc_middle::mir::*; -use rustc_middle::ty::{ParamEnv, Ty, TyCtxt}; +use rustc_middle::ty::{Ty, TyCtxt}; use rustc_span::Span; use smallvec::SmallVec; @@ -352,10 +352,9 @@ impl<'tcx> MoveData<'tcx> { pub fn gather_moves( body: &Body<'tcx>, tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, filter: impl Fn(Ty<'tcx>) -> bool, ) -> MoveData<'tcx> { - builder::gather_moves(body, tcx, param_env, filter) + builder::gather_moves(body, tcx, filter) } /// For the move path `mpi`, returns the root local variable that starts the path. diff --git a/compiler/rustc_mir_dataflow/src/rustc_peek.rs b/compiler/rustc_mir_dataflow/src/rustc_peek.rs index 75732b19cd0..5727517bd61 100644 --- a/compiler/rustc_mir_dataflow/src/rustc_peek.rs +++ b/compiler/rustc_mir_dataflow/src/rustc_peek.rs @@ -40,8 +40,7 @@ pub fn sanity_check<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { debug!("running rustc_peek::SanityCheck on {}", tcx.def_path_str(def_id)); } - let param_env = tcx.param_env(def_id); - let move_data = MoveData::gather_moves(body, tcx, param_env, |_| true); + let move_data = MoveData::gather_moves(body, tcx, |_| true); if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_maybe_init).is_some() { let flow_inits = MaybeInitializedPlaces::new(tcx, body, &move_data) diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index 8f032728f6b..0a413d68020 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -1957,7 +1957,8 @@ fn check_must_not_suspend_ty<'tcx>( let descr_pre = &format!("{}array{} of ", data.descr_pre, plural_suffix); check_must_not_suspend_ty(tcx, ty, hir_id, param_env, SuspendCheckData { descr_pre, - plural_len: len.try_eval_target_usize(tcx, param_env).unwrap_or(0) as usize + 1, + // FIXME(must_not_suspend): This is wrong. We should handle printing unevaluated consts. + plural_len: len.try_to_target_usize(tcx).unwrap_or(0) as usize + 1, ..data }) } diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs index f4ac4d9fee6..30e1ac05e03 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drops.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs @@ -58,8 +58,7 @@ impl<'tcx> crate::MirPass<'tcx> for ElaborateDrops { let param_env = tcx.param_env_reveal_all_normalized(def_id); // For types that do not need dropping, the behaviour is trivial. So we only need to track // init/uninit for types that do need dropping. - let move_data = - MoveData::gather_moves(body, tcx, param_env, |ty| ty.needs_drop(tcx, param_env)); + let move_data = MoveData::gather_moves(body, tcx, |ty| ty.needs_drop(tcx, param_env)); let elaborate_patch = { let env = MoveDataParamEnv { move_data, param_env }; diff --git a/compiler/rustc_mir_transform/src/known_panics_lint.rs b/compiler/rustc_mir_transform/src/known_panics_lint.rs index 8f490094d60..7f38d533f50 100644 --- a/compiler/rustc_mir_transform/src/known_panics_lint.rs +++ b/compiler/rustc_mir_transform/src/known_panics_lint.rs @@ -602,7 +602,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { Len(place) => { let len = if let ty::Array(_, n) = place.ty(self.local_decls(), self.tcx).ty.kind() { - n.try_eval_target_usize(self.tcx, self.param_env)? + n.try_to_target_usize(self.tcx)? } else { match self.get_const(place)? { Value::Immediate(src) => src.len(&self.ecx).discard_err()?, diff --git a/compiler/rustc_mir_transform/src/promote_consts.rs b/compiler/rustc_mir_transform/src/promote_consts.rs index d963ca5c485..86c4b241a2b 100644 --- a/compiler/rustc_mir_transform/src/promote_consts.rs +++ b/compiler/rustc_mir_transform/src/promote_consts.rs @@ -329,7 +329,7 @@ impl<'tcx> Validator<'_, 'tcx> { // Determine the type of the thing we are indexing. && let ty::Array(_, len) = place_base.ty(self.body, self.tcx).ty.kind() // It's an array; determine its length. - && let Some(len) = len.try_eval_target_usize(self.tcx, self.param_env) + && let Some(len) = len.try_to_target_usize(self.tcx) // If the index is in-bounds, go ahead. && idx < len { @@ -407,7 +407,7 @@ impl<'tcx> Validator<'_, 'tcx> { // mutably without consequences. However, only &mut [] // is allowed right now. if let ty::Array(_, len) = ty.kind() { - match len.try_eval_target_usize(self.tcx, self.param_env) { + match len.try_to_target_usize(self.tcx) { Some(0) => {} _ => return Err(Unpromotable), } diff --git a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs index e6647edf3f5..09969a4c7cc 100644 --- a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs +++ b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs @@ -19,8 +19,7 @@ pub(super) struct RemoveUninitDrops; impl<'tcx> crate::MirPass<'tcx> for RemoveUninitDrops { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let param_env = tcx.param_env(body.source.def_id()); - let move_data = - MoveData::gather_moves(body, tcx, param_env, |ty| ty.needs_drop(tcx, param_env)); + let move_data = MoveData::gather_moves(body, tcx, |ty| ty.needs_drop(tcx, param_env)); let mut maybe_inits = MaybeInitializedPlaces::new(tcx, body, &move_data) .into_engine(tcx, body) 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 53834198f63..ca75952fe3d 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 @@ -133,7 +133,9 @@ fn encode_const<'tcx>( // bool value false is encoded as 0 and true as 1. match ct_ty.kind() { ty::Int(ity) => { - let bits = c.eval_bits(tcx, ty::ParamEnv::reveal_all()); + let bits = c + .try_to_bits(tcx, ty::ParamEnv::reveal_all()) + .expect("expected monomorphic const in cfi"); let val = Integer::from_int_ty(&tcx, *ity).size().sign_extend(bits) as i128; if val < 0 { s.push('n'); @@ -141,7 +143,9 @@ fn encode_const<'tcx>( let _ = write!(s, "{val}"); } ty::Uint(_) => { - let val = c.eval_bits(tcx, ty::ParamEnv::reveal_all()); + let val = c + .try_to_bits(tcx, ty::ParamEnv::reveal_all()) + .expect("expected monomorphic const in cfi"); let _ = write!(s, "{val}"); } ty::Bool => { diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs index ed5d2d1e799..8fa8f2ac402 100644 --- a/compiler/rustc_smir/src/rustc_smir/context.rs +++ b/compiler/rustc_smir/src/rustc_smir/context.rs @@ -406,7 +406,7 @@ impl<'tcx> Context for TablesWrapper<'tcx> { let tcx = tables.tcx; let mir_const = cnst.internal(&mut *tables, tcx); mir_const - .try_eval_target_usize(tables.tcx, ParamEnv::empty()) + .try_to_target_usize(tables.tcx) .ok_or_else(|| Error::new(format!("Const `{cnst:?}` cannot be encoded as u64"))) } diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index f3da7ff1ca7..649b2145b8b 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -592,7 +592,9 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { ty::Uint(_) | ty::Int(_) | ty::Bool | ty::Char => { ct_ty.print(self)?; - let mut bits = ct.eval_bits(self.tcx, ty::ParamEnv::reveal_all()); + let mut bits = ct + .try_to_bits(self.tcx, ty::ParamEnv::reveal_all()) + .expect("expected const to be monomorphic"); // Negative integer values are mangled using `n` as a "sign prefix". if let ty::Int(ity) = ct_ty.kind() { diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs index cd41ab9fa6c..7f42c932fcf 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs @@ -231,7 +231,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { // Arrays give us `[]`, `[{ty}; _]` and `[{ty}; N]` if let ty::Array(aty, len) = self_ty.kind() { flags.push((sym::_Self, Some("[]".to_string()))); - let len = len.try_to_valtree().and_then(|v| v.try_to_target_usize(self.tcx)); + let len = len.try_to_target_usize(self.tcx); flags.push((sym::_Self, Some(format!("[{aty}; _]")))); if let Some(n) = len { flags.push((sym::_Self, Some(format!("[{aty}; {n}]")))); diff --git a/compiler/rustc_transmute/src/lib.rs b/compiler/rustc_transmute/src/lib.rs index c1d0b704ab2..7796ab9d691 100644 --- a/compiler/rustc_transmute/src/lib.rs +++ b/compiler/rustc_transmute/src/lib.rs @@ -85,7 +85,6 @@ mod rustc { use rustc_macros::TypeVisitable; use rustc_middle::traits::ObligationCause; use rustc_middle::ty::{Const, ParamEnv, Ty, TyCtxt, ValTree}; - use rustc_span::DUMMY_SP; use super::*; @@ -134,7 +133,7 @@ mod rustc { use rustc_middle::ty::ScalarInt; use rustc_span::symbol::sym; - let Ok((ty, cv)) = c.eval(tcx, param_env, DUMMY_SP) else { + let Some((cv, ty)) = c.try_to_valtree() else { return Some(Self { alignment: true, lifetimes: true, diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index afdfa2e80c1..efe3c31924e 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -170,12 +170,12 @@ fn layout_of_uncached<'tcx>( if let Abi::Scalar(scalar) | Abi::ScalarPair(scalar, _) = &mut layout.abi { if let Some(start) = start { scalar.valid_range_mut().start = start - .try_eval_bits(tcx, param_env) + .try_to_bits(tcx, param_env) .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?; } if let Some(end) = end { let mut end = end - .try_eval_bits(tcx, param_env) + .try_to_bits(tcx, param_env) .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?; if !include_end { end = end.wrapping_sub(1); @@ -315,7 +315,7 @@ fn layout_of_uncached<'tcx>( } let count = count - .try_eval_target_usize(tcx, param_env) + .try_to_target_usize(tcx) .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?; let element = cx.layout_of(element)?; let size = element -- cgit 1.4.1-3-g733a5 From 3310419d35c51b4da14c2fee9c0dcfab6b66ea0d Mon Sep 17 00:00:00 2001 From: Zalathar Date: Fri, 18 Oct 2024 21:43:37 +1100 Subject: Make `llvm::set_section` take a `&CStr` --- compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs | 4 +++- compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs | 18 +++++++++--------- compiler/rustc_codegen_llvm/src/llvm/mod.rs | 5 ++--- 3 files changed, 14 insertions(+), 13 deletions(-) (limited to 'compiler/rustc_codegen_llvm/src') diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index 4075849323a..cee704a9c22 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -1,3 +1,5 @@ +use std::ffi::CStr; + use itertools::Itertools as _; use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, ConstCodegenMethods}; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; @@ -305,7 +307,7 @@ fn generate_coverage_map<'ll>( /// specific, well-known section and name. fn save_function_record( cx: &CodegenCx<'_, '_>, - covfun_section_name: &str, + covfun_section_name: &CStr, mangled_function_name: &str, source_hash: u64, filenames_ref: u64, diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs index 4f93e6ab1e5..484a4d00c13 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs @@ -1,5 +1,5 @@ use std::cell::RefCell; -use std::ffi::CString; +use std::ffi::{CStr, CString}; use libc::c_uint; use rustc_codegen_ssa::traits::{ @@ -292,10 +292,10 @@ pub(crate) fn save_cov_data_to_mod<'ll, 'tcx>( .unwrap(); debug!("covmap var name: {:?}", covmap_var_name); - let covmap_section_name = llvm::build_string(|s| unsafe { + let covmap_section_name = CString::new(llvm::build_byte_buffer(|s| unsafe { llvm::LLVMRustCoverageWriteMapSectionNameToString(cx.llmod, s); - }) - .expect("Rust Coverage section name failed UTF-8 conversion"); + })) + .expect("covmap section name should not contain NUL"); debug!("covmap section name: {:?}", covmap_section_name); let llglobal = llvm::add_global(cx.llmod, cx.val_ty(cov_data_val), &covmap_var_name); @@ -310,7 +310,7 @@ pub(crate) fn save_cov_data_to_mod<'ll, 'tcx>( pub(crate) fn save_func_record_to_mod<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, - covfun_section_name: &str, + covfun_section_name: &CStr, func_name_hash: u64, func_record_val: &'ll llvm::Value, is_used: bool, @@ -354,9 +354,9 @@ pub(crate) fn save_func_record_to_mod<'ll, 'tcx>( /// - `__llvm_covfun` on Linux /// - `__LLVM_COV,__llvm_covfun` on macOS (includes `__LLVM_COV,` segment prefix) /// - `.lcovfun$M` on Windows (includes `$M` sorting suffix) -pub(crate) fn covfun_section_name(cx: &CodegenCx<'_, '_>) -> String { - llvm::build_string(|s| unsafe { +pub(crate) fn covfun_section_name(cx: &CodegenCx<'_, '_>) -> CString { + CString::new(llvm::build_byte_buffer(|s| unsafe { llvm::LLVMRustCoverageWriteFuncSectionNameToString(cx.llmod, s); - }) - .expect("Rust Coverage function record section name failed UTF-8 conversion") + })) + .expect("covfun section name should not contain NUL") } diff --git a/compiler/rustc_codegen_llvm/src/llvm/mod.rs b/compiler/rustc_codegen_llvm/src/llvm/mod.rs index b306396e15a..e837022044e 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/mod.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/mod.rs @@ -210,10 +210,9 @@ impl MemoryEffects { } } -pub fn set_section(llglobal: &Value, section_name: &str) { - let section_name_cstr = CString::new(section_name).expect("unexpected CString error"); +pub fn set_section(llglobal: &Value, section_name: &CStr) { unsafe { - LLVMSetSection(llglobal, section_name_cstr.as_ptr()); + LLVMSetSection(llglobal, section_name.as_ptr()); } } -- cgit 1.4.1-3-g733a5