From 9f8a6be22188b1ac666bae83fc6aaf7f84ba4522 Mon Sep 17 00:00:00 2001 From: Zalathar <Zalathar@users.noreply.github.com> Date: Thu, 24 Oct 2024 22:47:45 +1100 Subject: [PATCH 01/13] coverage: Consolidate creation of covmap/covfun records There is no need for this code to be split across multiple functions in multiple files. --- .../src/coverageinfo/mapgen.rs | 83 ++++++++++++++----- .../src/coverageinfo/mod.rs | 69 +-------------- 2 files changed, 64 insertions(+), 88 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index 61e474031bb08..b69ca62341340 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -1,7 +1,10 @@ -use std::ffi::CStr; +use std::ffi::{CStr, CString}; use itertools::Itertools as _; -use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, ConstCodegenMethods}; +use rustc_abi::Align; +use rustc_codegen_ssa::traits::{ + BaseTypeCodegenMethods, ConstCodegenMethods, StaticCodegenMethods, +}; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_index::IndexVec; @@ -10,6 +13,7 @@ use rustc_middle::ty::{self, TyCtxt}; use rustc_middle::{bug, mir}; use rustc_span::Symbol; use rustc_span::def_id::DefIdSet; +use rustc_target::spec::HasTargetSpec; use tracing::debug; use crate::common::CodegenCx; @@ -78,8 +82,7 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) { // Generate the coverage map header, which contains the filenames used by // this CGU's coverage mappings, and store it in a well-known global. - let cov_data_val = generate_coverage_map(cx, covmap_version, filenames_size, filenames_val); - coverageinfo::save_cov_data_to_mod(cx, cov_data_val); + generate_covmap_record(cx, covmap_version, filenames_size, filenames_val); let mut unused_function_names = Vec::new(); let covfun_section_name = coverageinfo::covfun_section_name(cx); @@ -111,7 +114,7 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) { unused_function_names.push(mangled_function_name); } - save_function_record( + generate_covfun_record( cx, &covfun_section_name, mangled_function_name, @@ -308,15 +311,15 @@ fn encode_mappings_for_function( }) } -/// Construct coverage map header and the array of function records, and combine them into the -/// coverage map. Save the coverage map data into the LLVM IR as a static global using a -/// specific, well-known section and name. -fn generate_coverage_map<'ll>( +/// Generates the contents of the covmap record for this CGU, which mostly +/// consists of a header and a list of filenames. The record is then stored +/// as a global variable in the `__llvm_covmap` section. +fn generate_covmap_record<'ll>( cx: &CodegenCx<'ll, '_>, version: u32, filenames_size: usize, filenames_val: &'ll llvm::Value, -) -> &'ll llvm::Value { +) { debug!("cov map: filenames_size = {}, 0-based version = {}", filenames_size, version); // Create the coverage data header (Note, fields 0 and 2 are now always zero, @@ -331,13 +334,35 @@ fn generate_coverage_map<'ll>( ); // Create the complete LLVM coverage data value to add to the LLVM IR - cx.const_struct(&[cov_data_header_val, filenames_val], /*packed=*/ false) + let covmap_data = + cx.const_struct(&[cov_data_header_val, filenames_val], /*packed=*/ false); + + let covmap_var_name = CString::new(llvm::build_byte_buffer(|s| unsafe { + llvm::LLVMRustCoverageWriteMappingVarNameToString(s); + })) + .unwrap(); + debug!("covmap var name: {:?}", covmap_var_name); + + let covmap_section_name = CString::new(llvm::build_byte_buffer(|s| unsafe { + llvm::LLVMRustCoverageWriteMapSectionNameToString(cx.llmod, s); + })) + .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(covmap_data), &covmap_var_name); + llvm::set_initializer(llglobal, covmap_data); + llvm::set_global_constant(llglobal, true); + llvm::set_linkage(llglobal, llvm::Linkage::PrivateLinkage); + llvm::set_section(llglobal, &covmap_section_name); + // LLVM's coverage mapping format specifies 8-byte alignment for items in this section. + llvm::set_alignment(llglobal, Align::EIGHT); + cx.add_used_global(llglobal); } -/// Construct a function record and combine it with the function's coverage mapping data. -/// Save the function record into the LLVM IR as a static global using a -/// specific, well-known section and name. -fn save_function_record( +/// Generates the contents of the covfun record for this function, which +/// contains the function's coverage mapping data. The record is then stored +/// as a global variable in the `__llvm_covfun` section. +fn generate_covfun_record( cx: &CodegenCx<'_, '_>, covfun_section_name: &CStr, mangled_function_name: &str, @@ -366,13 +391,27 @@ fn save_function_record( /*packed=*/ true, ); - coverageinfo::save_func_record_to_mod( - cx, - covfun_section_name, - func_name_hash, - func_record_val, - is_used, - ); + // Choose a variable name to hold this function's covfun data. + // Functions that are used have a suffix ("u") to distinguish them from + // unused copies of the same function (from different CGUs), so that if a + // linker sees both it won't discard the used copy's data. + let func_record_var_name = + CString::new(format!("__covrec_{:X}{}", func_name_hash, if is_used { "u" } else { "" })) + .unwrap(); + debug!("function record var name: {:?}", func_record_var_name); + + let llglobal = llvm::add_global(cx.llmod, cx.val_ty(func_record_val), &func_record_var_name); + llvm::set_initializer(llglobal, func_record_val); + llvm::set_global_constant(llglobal, true); + llvm::set_linkage(llglobal, llvm::Linkage::LinkOnceODRLinkage); + llvm::set_visibility(llglobal, llvm::Visibility::Hidden); + 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); + if cx.target_spec().supports_comdat() { + llvm::set_comdat(cx.llmod, llglobal, &func_record_var_name); + } + cx.add_used_global(llglobal); } /// Each CGU will normally only emit coverage metadata for the functions that it actually generates. diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs index b2956945911b1..58607ce7497ff 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs @@ -1,10 +1,9 @@ use std::cell::RefCell; -use std::ffi::{CStr, CString}; +use std::ffi::CString; use libc::c_uint; use rustc_codegen_ssa::traits::{ - BaseTypeCodegenMethods, BuilderMethods, ConstCodegenMethods, CoverageInfoBuilderMethods, - MiscCodegenMethods, StaticCodegenMethods, + BuilderMethods, ConstCodegenMethods, CoverageInfoBuilderMethods, MiscCodegenMethods, }; use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_llvm::RustString; @@ -12,8 +11,7 @@ use rustc_middle::bug; 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 rustc_target::abi::Size; use tracing::{debug, instrument}; use crate::builder::Builder; @@ -290,67 +288,6 @@ pub(crate) fn mapping_version() -> u32 { unsafe { llvm::LLVMRustCoverageMappingVersion() } } -pub(crate) fn save_cov_data_to_mod<'ll, 'tcx>( - cx: &CodegenCx<'ll, 'tcx>, - cov_data_val: &'ll llvm::Value, -) { - let covmap_var_name = CString::new(llvm::build_byte_buffer(|s| unsafe { - llvm::LLVMRustCoverageWriteMappingVarNameToString(s); - })) - .unwrap(); - debug!("covmap var name: {:?}", covmap_var_name); - - let covmap_section_name = CString::new(llvm::build_byte_buffer(|s| unsafe { - llvm::LLVMRustCoverageWriteMapSectionNameToString(cx.llmod, s); - })) - .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); - llvm::set_initializer(llglobal, cov_data_val); - llvm::set_global_constant(llglobal, true); - llvm::set_linkage(llglobal, llvm::Linkage::PrivateLinkage); - llvm::set_section(llglobal, &covmap_section_name); - // LLVM's coverage mapping format specifies 8-byte alignment for items in this section. - llvm::set_alignment(llglobal, Align::EIGHT); - cx.add_used_global(llglobal); -} - -pub(crate) fn save_func_record_to_mod<'ll, 'tcx>( - cx: &CodegenCx<'ll, 'tcx>, - covfun_section_name: &CStr, - func_name_hash: u64, - func_record_val: &'ll llvm::Value, - is_used: bool, -) { - // Assign a name to the function record. This is used to merge duplicates. - // - // In LLVM, a "translation unit" (effectively, a `Crate` in Rust) can describe functions that - // are included-but-not-used. If (or when) Rust generates functions that are - // included-but-not-used, note that a dummy description for a function included-but-not-used - // in a Crate can be replaced by full description provided by a different Crate. The two kinds - // 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 = - 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); - - let llglobal = llvm::add_global(cx.llmod, cx.val_ty(func_record_val), &func_record_var_name); - llvm::set_initializer(llglobal, func_record_val); - llvm::set_global_constant(llglobal, true); - llvm::set_linkage(llglobal, llvm::Linkage::LinkOnceODRLinkage); - llvm::set_visibility(llglobal, llvm::Visibility::Hidden); - 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); - if cx.target_spec().supports_comdat() { - llvm::set_comdat(cx.llmod, llglobal, &func_record_var_name); - } - cx.add_used_global(llglobal); -} - /// Returns the section name string to pass through to the linker when embedding /// per-function coverage information in the object file, according to the target /// platform's object file format. From 0a96176533ad5c0f8dc3b42c64bf907fb9c27f0b Mon Sep 17 00:00:00 2001 From: Zalathar <Zalathar@users.noreply.github.com> Date: Thu, 24 Oct 2024 22:23:13 +1100 Subject: [PATCH 02/13] coverage: Make obtaining the codegen coverage context infallible In all the situations where this context is needed, it should always be available. --- compiler/rustc_codegen_llvm/src/context.rs | 8 ++--- .../src/coverageinfo/mapgen.rs | 12 ++------ .../src/coverageinfo/mod.rs | 29 +++++++------------ 3 files changed, 16 insertions(+), 33 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 2f830d6f941e7..7faa005abd29b 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -80,6 +80,7 @@ pub(crate) struct CodegenCx<'ll, 'tcx> { pub isize_ty: &'ll Type, + /// Extra codegen state needed when coverage instrumentation is enabled. pub coverage_cx: Option<coverageinfo::CrateCoverageContext<'ll, 'tcx>>, pub dbg_cx: Option<debuginfo::CodegenUnitDebugContext<'ll, 'tcx>>, @@ -592,11 +593,10 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { &self.statics_to_rauw } + /// Extra state that is only available when coverage instrumentation is enabled. #[inline] - pub(crate) fn coverage_context( - &self, - ) -> Option<&coverageinfo::CrateCoverageContext<'ll, 'tcx>> { - self.coverage_cx.as_ref() + pub(crate) fn coverage_cx(&self) -> &coverageinfo::CrateCoverageContext<'ll, 'tcx> { + self.coverage_cx.as_ref().expect("only called when coverage instrumentation is enabled") } pub(crate) fn create_used_variable_impl(&self, name: &'static CStr, values: &[&'ll Value]) { diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index b69ca62341340..7a2a802eb4eb0 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -54,11 +54,7 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) { add_unused_functions(cx); } - let function_coverage_map = match cx.coverage_context() { - Some(ctx) => ctx.take_function_coverage_map(), - None => return, - }; - + let function_coverage_map = cx.coverage_cx().take_function_coverage_map(); if function_coverage_map.is_empty() { // This module has no functions with coverage instrumentation return; @@ -543,9 +539,5 @@ fn add_unused_function_coverage<'tcx>( // zero, because none of its counters/expressions are marked as seen. let function_coverage = FunctionCoverageCollector::unused(instance, function_coverage_info); - if let Some(coverage_context) = cx.coverage_context() { - coverage_context.function_coverage_map.borrow_mut().insert(instance, function_coverage); - } else { - bug!("Could not get the `coverage_context`"); - } + cx.coverage_cx().function_coverage_map.borrow_mut().insert(instance, function_coverage); } diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs index 58607ce7497ff..eaf720cc769ec 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs @@ -7,7 +7,6 @@ use rustc_codegen_ssa::traits::{ }; use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_llvm::RustString; -use rustc_middle::bug; use rustc_middle::mir::coverage::CoverageKind; use rustc_middle::ty::Instance; use rustc_middle::ty::layout::HasTyCtxt; @@ -76,15 +75,11 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { /// `instrprof.increment()`. The `Value` is only created once per instance. /// Multiple invocations with the same instance return the same `Value`. fn get_pgo_func_name_var(&self, instance: Instance<'tcx>) -> &'ll llvm::Value { - if let Some(coverage_context) = self.coverage_context() { - debug!("getting pgo_func_name_var for instance={:?}", instance); - let mut pgo_func_name_var_map = coverage_context.pgo_func_name_var_map.borrow_mut(); - pgo_func_name_var_map - .entry(instance) - .or_insert_with(|| create_pgo_func_name_var(self, instance)) - } else { - bug!("Could not get the `coverage_context`"); - } + debug!("getting pgo_func_name_var for instance={:?}", instance); + let mut pgo_func_name_var_map = self.coverage_cx().pgo_func_name_var_map.borrow_mut(); + pgo_func_name_var_map + .entry(instance) + .or_insert_with(|| create_pgo_func_name_var(self, instance)) } } @@ -118,11 +113,7 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { cond_bitmaps.push(cond_bitmap); } - self.coverage_context() - .expect("always present when coverage is enabled") - .mcdc_condition_bitmap_map - .borrow_mut() - .insert(instance, cond_bitmaps); + self.coverage_cx().mcdc_condition_bitmap_map.borrow_mut().insert(instance, cond_bitmaps); } #[instrument(level = "debug", skip(self))] @@ -143,8 +134,7 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { return; }; - let Some(coverage_context) = bx.coverage_context() else { return }; - let mut coverage_map = coverage_context.function_coverage_map.borrow_mut(); + let mut coverage_map = bx.coverage_cx().function_coverage_map.borrow_mut(); let func_coverage = coverage_map .entry(instance) .or_insert_with(|| FunctionCoverageCollector::new(instance, function_coverage_info)); @@ -186,7 +176,8 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { } CoverageKind::CondBitmapUpdate { index, decision_depth } => { drop(coverage_map); - let cond_bitmap = coverage_context + let cond_bitmap = bx + .coverage_cx() .try_get_mcdc_condition_bitmap(&instance, decision_depth) .expect("mcdc cond bitmap should have been allocated for updating"); let cond_index = bx.const_i32(index as i32); @@ -194,7 +185,7 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { } CoverageKind::TestVectorBitmapUpdate { bitmap_idx, decision_depth } => { drop(coverage_map); - let cond_bitmap = coverage_context + let cond_bitmap = bx.coverage_cx() .try_get_mcdc_condition_bitmap(&instance, decision_depth) .expect("mcdc cond bitmap should have been allocated for merging into the global bitmap"); assert!( From 0356908cf5e5ead075608709663a38b51c584872 Mon Sep 17 00:00:00 2001 From: Zalathar <Zalathar@users.noreply.github.com> Date: Thu, 24 Oct 2024 22:05:42 +1100 Subject: [PATCH 03/13] coverage: Store `covfun_section_name` in the codegen context Adding an extra `OnceCell` to `CrateCoverageContext` is much nicer than trying to thread this string through multiple layers of function calls that already have access to the context. --- .../src/coverageinfo/mapgen.rs | 7 +-- .../src/coverageinfo/mod.rs | 44 +++++++++---------- 2 files changed, 24 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index 7a2a802eb4eb0..5b39d078e0d7e 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -1,4 +1,4 @@ -use std::ffi::{CStr, CString}; +use std::ffi::CString; use itertools::Itertools as _; use rustc_abi::Align; @@ -81,7 +81,6 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) { generate_covmap_record(cx, covmap_version, filenames_size, filenames_val); let mut unused_function_names = Vec::new(); - let covfun_section_name = coverageinfo::covfun_section_name(cx); // Encode coverage mappings and generate function records for (instance, function_coverage) in function_coverage_entries { @@ -112,7 +111,6 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) { generate_covfun_record( cx, - &covfun_section_name, mangled_function_name, source_hash, filenames_ref, @@ -360,7 +358,6 @@ fn generate_covmap_record<'ll>( /// as a global variable in the `__llvm_covfun` section. fn generate_covfun_record( cx: &CodegenCx<'_, '_>, - covfun_section_name: &CStr, mangled_function_name: &str, source_hash: u64, filenames_ref: u64, @@ -401,7 +398,7 @@ fn generate_covfun_record( llvm::set_global_constant(llglobal, true); llvm::set_linkage(llglobal, llvm::Linkage::LinkOnceODRLinkage); llvm::set_visibility(llglobal, llvm::Visibility::Hidden); - llvm::set_section(llglobal, covfun_section_name); + llvm::set_section(llglobal, cx.covfun_section_name()); // LLVM's coverage mapping format specifies 8-byte alignment for items in this section. llvm::set_alignment(llglobal, Align::EIGHT); if cx.target_spec().supports_comdat() { diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs index eaf720cc769ec..e4f78dd877e9f 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::cell::{OnceCell, RefCell}; +use std::ffi::{CStr, CString}; use libc::c_uint; use rustc_codegen_ssa::traits::{ @@ -29,6 +29,8 @@ pub(crate) struct CrateCoverageContext<'ll, 'tcx> { RefCell<FxIndexMap<Instance<'tcx>, FunctionCoverageCollector<'tcx>>>, pub(crate) pgo_func_name_var_map: RefCell<FxHashMap<Instance<'tcx>, &'ll llvm::Value>>, pub(crate) mcdc_condition_bitmap_map: RefCell<FxHashMap<Instance<'tcx>, Vec<&'ll llvm::Value>>>, + + covfun_section_name: OnceCell<CString>, } impl<'ll, 'tcx> CrateCoverageContext<'ll, 'tcx> { @@ -37,6 +39,7 @@ impl<'ll, 'tcx> CrateCoverageContext<'ll, 'tcx> { function_coverage_map: Default::default(), pgo_func_name_var_map: Default::default(), mcdc_condition_bitmap_map: Default::default(), + covfun_section_name: Default::default(), } } @@ -63,13 +66,28 @@ impl<'ll, 'tcx> CrateCoverageContext<'ll, 'tcx> { } } -// These methods used to be part of trait `CoverageInfoMethods`, which no longer -// exists after most coverage code was moved out of SSA. impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { pub(crate) fn coverageinfo_finalize(&self) { mapgen::finalize(self) } + /// Returns the section name to use when embedding per-function coverage information + /// in the object file, according to the target's object file format. LLVM's coverage + /// tools use information from this section when producing coverage reports. + /// + /// Typical values are: + /// - `__llvm_covfun` on Linux + /// - `__LLVM_COV,__llvm_covfun` on macOS (includes `__LLVM_COV,` segment prefix) + /// - `.lcovfun$M` on Windows (includes `$M` sorting suffix) + fn covfun_section_name(&self) -> &CStr { + self.coverage_cx().covfun_section_name.get_or_init(|| { + CString::new(llvm::build_byte_buffer(|s| unsafe { + llvm::LLVMRustCoverageWriteFuncSectionNameToString(self.llmod, s); + })) + .expect("covfun section name should not contain NUL") + }) + } + /// For LLVM codegen, returns a function-specific `Value` for a global /// string, to hold the function name passed to LLVM intrinsic /// `instrprof.increment()`. The `Value` is only created once per instance. @@ -278,21 +296,3 @@ pub(crate) fn hash_bytes(bytes: &[u8]) -> u64 { pub(crate) fn mapping_version() -> u32 { unsafe { llvm::LLVMRustCoverageMappingVersion() } } - -/// Returns the section name string to pass through to the linker when embedding -/// per-function coverage information in the object file, according to the target -/// platform's object file format. -/// -/// LLVM's coverage tools read coverage mapping details from this section when -/// producing coverage reports. -/// -/// Typical values are: -/// - `__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<'_, '_>) -> CString { - CString::new(llvm::build_byte_buffer(|s| unsafe { - llvm::LLVMRustCoverageWriteFuncSectionNameToString(cx.llmod, s); - })) - .expect("covfun section name should not contain NUL") -} From e2d3f5aaec941850479e16e89ebfb70824e65a45 Mon Sep 17 00:00:00 2001 From: Manuel Drehwald <git@manuel.drehwald.info> Date: Sat, 12 Oct 2024 00:16:39 +0200 Subject: [PATCH 04/13] Allow building rustc's LLVM with Offload support --- config.example.toml | 3 +++ src/bootstrap/configure.py | 1 + src/bootstrap/src/core/build_steps/llvm.rs | 15 +++++++++++++++ src/bootstrap/src/core/config/config.rs | 9 +++++++++ src/bootstrap/src/utils/change_tracker.rs | 5 +++++ 5 files changed, 33 insertions(+) diff --git a/config.example.toml b/config.example.toml index a52968e9a414d..d5b904ebf3d59 100644 --- a/config.example.toml +++ b/config.example.toml @@ -84,6 +84,9 @@ # Wheter to build Enzyme as AutoDiff backend. #enzyme = false +# Whether to build LLVM with support for it's gpu offload runtime. +#offload = false + # Indicates whether ccache is used when building LLVM. Set to `true` to use the first `ccache` in # PATH, or set an absolute path to use a specific version. #ccache = false diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index 15137fbb2b5c2..2e173c9e6df48 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -72,6 +72,7 @@ def v(*args): o("optimize-llvm", "llvm.optimize", "build optimized LLVM") o("llvm-assertions", "llvm.assertions", "build LLVM with assertions") o("llvm-enzyme", "llvm.enzyme", "build LLVM with enzyme") +o("llvm-offload", "llvm.offload", "build LLVM with gpu offload support") o("llvm-plugins", "llvm.plugins", "build LLVM with plugin interface") o("debug-assertions", "rust.debug-assertions", "build with debugging assertions") o("debug-assertions-std", "rust.debug-assertions-std", "build the standard library with debugging assertions") diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index a2d40f6fbd891..ffb7d9a9e0e74 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -472,6 +472,21 @@ impl Step for Llvm { cfg.define("LLVM_ENABLE_PROJECTS", enabled_llvm_projects.join(";")); } + let mut enabled_llvm_runtimes = Vec::new(); + + if builder.config.llvm_offload { + enabled_llvm_runtimes.push("offload"); + //FIXME(ZuseZ4): LLVM intends to drop the offload dependency on openmp. + //Remove this line once they achieved it. + enabled_llvm_runtimes.push("openmp"); + } + + if !enabled_llvm_runtimes.is_empty() { + enabled_llvm_runtimes.sort(); + enabled_llvm_runtimes.dedup(); + cfg.define("LLVM_ENABLE_RUNTIMES", enabled_llvm_runtimes.join(";")); + } + if let Some(num_linkers) = builder.config.llvm_link_jobs { if num_linkers > 0 { cfg.define("LLVM_PARALLEL_LINK_JOBS", num_linkers.to_string()); diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 444c97a2048e3..087dde0d9c6b2 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -224,6 +224,7 @@ pub struct Config { pub llvm_assertions: bool, pub llvm_tests: bool, pub llvm_enzyme: bool, + pub llvm_offload: bool, pub llvm_plugins: bool, pub llvm_optimize: bool, pub llvm_thin_lto: bool, @@ -938,6 +939,7 @@ define_config! { use_libcxx: Option<bool> = "use-libcxx", use_linker: Option<String> = "use-linker", allow_old_toolchain: Option<bool> = "allow-old-toolchain", + offload: Option<bool> = "offload", polly: Option<bool> = "polly", clang: Option<bool> = "clang", enable_warnings: Option<bool> = "enable-warnings", @@ -1647,6 +1649,7 @@ impl Config { // we'll infer default values for them later let mut llvm_tests = None; let mut llvm_enzyme = None; + let mut llvm_offload = None; let mut llvm_plugins = None; let mut debug = None; let mut debug_assertions = None; @@ -1884,6 +1887,7 @@ impl Config { use_libcxx, use_linker, allow_old_toolchain, + offload, polly, clang, enable_warnings, @@ -1900,6 +1904,7 @@ impl Config { set(&mut config.ninja_in_file, ninja); llvm_tests = tests; llvm_enzyme = enzyme; + llvm_offload = offload; llvm_plugins = plugins; set(&mut config.llvm_optimize, optimize_toml); set(&mut config.llvm_thin_lto, thin_lto); @@ -1921,6 +1926,7 @@ impl Config { set(&mut config.llvm_use_libcxx, use_libcxx); config.llvm_use_linker.clone_from(&use_linker); config.llvm_allow_old_toolchain = allow_old_toolchain.unwrap_or(false); + config.llvm_offload = offload.unwrap_or(false); config.llvm_polly = polly.unwrap_or(false); config.llvm_clang = clang.unwrap_or(false); config.llvm_enable_warnings = enable_warnings.unwrap_or(false); @@ -2097,6 +2103,7 @@ impl Config { config.llvm_tests = llvm_tests.unwrap_or(false); config.llvm_enzyme = llvm_enzyme.unwrap_or(false); + config.llvm_offload = llvm_offload.unwrap_or(false); config.llvm_plugins = llvm_plugins.unwrap_or(false); config.rust_optimize = optimize.unwrap_or(RustOptimize::Bool(true)); @@ -2963,6 +2970,7 @@ pub(crate) fn check_incompatible_options_for_ci_llvm( use_libcxx, use_linker, allow_old_toolchain, + offload, polly, clang, enable_warnings, @@ -2985,6 +2993,7 @@ pub(crate) fn check_incompatible_options_for_ci_llvm( err!(current_llvm_config.use_libcxx, use_libcxx); err!(current_llvm_config.use_linker, use_linker); err!(current_llvm_config.allow_old_toolchain, allow_old_toolchain); + err!(current_llvm_config.offload, offload); err!(current_llvm_config.polly, polly); err!(current_llvm_config.clang, clang); err!(current_llvm_config.build_config, build_config); diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs index fac24572a878c..b9cf8f0531698 100644 --- a/src/bootstrap/src/utils/change_tracker.rs +++ b/src/bootstrap/src/utils/change_tracker.rs @@ -285,4 +285,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[ severity: ChangeSeverity::Info, summary: "New option `build.compiletest-diff-tool` that adds support for a custom differ for compiletest", }, + ChangeInfo { + change_id: 131513, + severity: ChangeSeverity::Info, + summary: "New option `llvm.offload` to control whether the llvm offload runtime for GPU support is built. Implicitly enables the openmp runtime as dependency.", + }, ]; From aa14cb896b789a0e0b20dd44999888b75ed5f7bb Mon Sep 17 00:00:00 2001 From: Zalathar <Zalathar@users.noreply.github.com> Date: Fri, 25 Oct 2024 18:22:03 +1100 Subject: [PATCH 05/13] Add a macro that derives `TryFrom<u32>` for fieldless enums --- compiler/rustc_macros/src/lib.rs | 10 ++++ compiler/rustc_macros/src/try_from.rs | 53 ++++++++++++++++++++ tests/ui-fulldeps/try-from-u32/errors.rs | 24 +++++++++ tests/ui-fulldeps/try-from-u32/errors.stderr | 32 ++++++++++++ tests/ui-fulldeps/try-from-u32/hygiene.rs | 32 ++++++++++++ tests/ui-fulldeps/try-from-u32/values.rs | 36 +++++++++++++ 6 files changed, 187 insertions(+) create mode 100644 compiler/rustc_macros/src/try_from.rs create mode 100644 tests/ui-fulldeps/try-from-u32/errors.rs create mode 100644 tests/ui-fulldeps/try-from-u32/errors.stderr create mode 100644 tests/ui-fulldeps/try-from-u32/hygiene.rs create mode 100644 tests/ui-fulldeps/try-from-u32/values.rs diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs index f46c795b9565c..0df674eb4c909 100644 --- a/compiler/rustc_macros/src/lib.rs +++ b/compiler/rustc_macros/src/lib.rs @@ -20,6 +20,7 @@ mod lift; mod query; mod serialize; mod symbols; +mod try_from; mod type_foldable; mod type_visitable; @@ -165,3 +166,12 @@ decl_derive!( suggestion_part, applicability)] => diagnostics::subdiagnostic_derive ); + +decl_derive! { + [TryFromU32] => + /// Derives `TryFrom<u32>` for the annotated `enum`, which must have no fields. + /// Each variant maps to the value it would produce under an `as u32` cast. + /// + /// The error type is `u32`. + try_from::try_from_u32 +} diff --git a/compiler/rustc_macros/src/try_from.rs b/compiler/rustc_macros/src/try_from.rs new file mode 100644 index 0000000000000..fde7c8f620400 --- /dev/null +++ b/compiler/rustc_macros/src/try_from.rs @@ -0,0 +1,53 @@ +use proc_macro2::TokenStream; +use quote::{quote, quote_spanned}; +use syn::Data; +use syn::spanned::Spanned; +use synstructure::Structure; + +pub(crate) fn try_from_u32(s: Structure<'_>) -> TokenStream { + let span_error = |span, message: &str| { + quote_spanned! { span => const _: () = ::core::compile_error!(#message); } + }; + + // Must be applied to an enum type. + if let Some(span) = match &s.ast().data { + Data::Enum(_) => None, + Data::Struct(s) => Some(s.struct_token.span()), + Data::Union(u) => Some(u.union_token.span()), + } { + return span_error(span, "type is not an enum (TryFromU32)"); + } + + // The enum's variants must not have fields. + let variant_field_errors = s + .variants() + .iter() + .filter_map(|v| v.ast().fields.iter().map(|f| f.span()).next()) + .map(|span| span_error(span, "enum variant cannot have fields (TryFromU32)")) + .collect::<TokenStream>(); + if !variant_field_errors.is_empty() { + return variant_field_errors; + } + + let ctor = s + .variants() + .iter() + .map(|v| v.construct(|_, _| -> TokenStream { unreachable!() })) + .collect::<Vec<_>>(); + s.gen_impl(quote! { + // The surrounding code might have shadowed these identifiers. + use ::core::convert::TryFrom; + use ::core::primitive::u32; + use ::core::result::Result::{self, Ok, Err}; + + gen impl TryFrom<u32> for @Self { + type Error = u32; + + #[allow(deprecated)] // Don't warn about deprecated variants. + fn try_from(value: u32) -> Result<Self, Self::Error> { + #( if value == const { #ctor as u32 } { return Ok(#ctor) } )* + Err(value) + } + } + }) +} diff --git a/tests/ui-fulldeps/try-from-u32/errors.rs b/tests/ui-fulldeps/try-from-u32/errors.rs new file mode 100644 index 0000000000000..0470063312cb2 --- /dev/null +++ b/tests/ui-fulldeps/try-from-u32/errors.rs @@ -0,0 +1,24 @@ +#![feature(rustc_private)] +//@ edition: 2021 + +// Checks the error messages produced by `#[derive(TryFromU32)]`. + +extern crate rustc_macros; + +use rustc_macros::TryFromU32; + +#[derive(TryFromU32)] +struct MyStruct {} //~ type is not an enum + +#[derive(TryFromU32)] +enum NonTrivial { + A, + B(), + C {}, + D(bool), //~ enum variant cannot have fields + E(bool, bool), //~ enum variant cannot have fields + F { x: bool }, //~ enum variant cannot have fields + G { x: bool, y: bool }, //~ enum variant cannot have fields +} + +fn main() {} diff --git a/tests/ui-fulldeps/try-from-u32/errors.stderr b/tests/ui-fulldeps/try-from-u32/errors.stderr new file mode 100644 index 0000000000000..d20567061d7bb --- /dev/null +++ b/tests/ui-fulldeps/try-from-u32/errors.stderr @@ -0,0 +1,32 @@ +error: type is not an enum (TryFromU32) + --> $DIR/errors.rs:11:1 + | +LL | struct MyStruct {} + | ^^^^^^ + +error: enum variant cannot have fields (TryFromU32) + --> $DIR/errors.rs:18:7 + | +LL | D(bool), + | ^^^^ + +error: enum variant cannot have fields (TryFromU32) + --> $DIR/errors.rs:19:7 + | +LL | E(bool, bool), + | ^^^^ + +error: enum variant cannot have fields (TryFromU32) + --> $DIR/errors.rs:20:9 + | +LL | F { x: bool }, + | ^ + +error: enum variant cannot have fields (TryFromU32) + --> $DIR/errors.rs:21:9 + | +LL | G { x: bool, y: bool }, + | ^ + +error: aborting due to 5 previous errors + diff --git a/tests/ui-fulldeps/try-from-u32/hygiene.rs b/tests/ui-fulldeps/try-from-u32/hygiene.rs new file mode 100644 index 0000000000000..e0655a64a64db --- /dev/null +++ b/tests/ui-fulldeps/try-from-u32/hygiene.rs @@ -0,0 +1,32 @@ +#![feature(rustc_private)] +//@ edition: 2021 +//@ check-pass + +// Checks that the derive macro still works even if the surrounding code has +// shadowed the relevant library types. + +extern crate rustc_macros; + +mod submod { + use rustc_macros::TryFromU32; + + struct Result; + trait TryFrom {} + #[allow(non_camel_case_types)] + struct u32; + struct Ok; + struct Err; + mod core {} + mod std {} + + #[derive(TryFromU32)] + pub(crate) enum MyEnum { + Zero, + One, + } +} + +fn main() { + use submod::MyEnum; + let _: Result<MyEnum, u32> = MyEnum::try_from(1u32); +} diff --git a/tests/ui-fulldeps/try-from-u32/values.rs b/tests/ui-fulldeps/try-from-u32/values.rs new file mode 100644 index 0000000000000..180a8f2beb75b --- /dev/null +++ b/tests/ui-fulldeps/try-from-u32/values.rs @@ -0,0 +1,36 @@ +#![feature(assert_matches)] +#![feature(rustc_private)] +//@ edition: 2021 +//@ run-pass + +// Checks the values accepted by the `TryFrom<u32>` impl produced by `#[derive(TryFromU32)]`. + +extern crate rustc_macros; + +use core::assert_matches::assert_matches; +use rustc_macros::TryFromU32; + +#[derive(TryFromU32, Debug, PartialEq)] +#[repr(u32)] +enum Repr { + Zero, + One(), + Seven = 7, +} + +#[derive(TryFromU32, Debug)] +enum NoRepr { + Zero, + One, +} + +fn main() { + assert_eq!(Repr::try_from(0u32), Ok(Repr::Zero)); + assert_eq!(Repr::try_from(1u32), Ok(Repr::One())); + assert_eq!(Repr::try_from(2u32), Err(2)); + assert_eq!(Repr::try_from(7u32), Ok(Repr::Seven)); + + assert_matches!(NoRepr::try_from(0u32), Ok(NoRepr::Zero)); + assert_matches!(NoRepr::try_from(1u32), Ok(NoRepr::One)); + assert_matches!(NoRepr::try_from(2u32), Err(2)); +} From ce87180e9f80f0f83c46295319b3dd66ddc06ed8 Mon Sep 17 00:00:00 2001 From: Zalathar <Zalathar@users.noreply.github.com> Date: Fri, 25 Oct 2024 21:40:38 +1100 Subject: [PATCH 06/13] Use safe wrappers `get_linkage` and `set_linkage` --- compiler/rustc_codegen_llvm/src/back/write.rs | 8 +- compiler/rustc_codegen_llvm/src/callee.rs | 4 +- compiler/rustc_codegen_llvm/src/common.rs | 2 +- compiler/rustc_codegen_llvm/src/consts.rs | 80 +++++++++---------- compiler/rustc_codegen_llvm/src/context.rs | 2 +- .../rustc_codegen_llvm/src/debuginfo/gdb.rs | 2 +- compiler/rustc_codegen_llvm/src/intrinsic.rs | 13 ++- compiler/rustc_codegen_llvm/src/llvm/mod.rs | 4 + compiler/rustc_codegen_llvm/src/mono_item.rs | 6 +- 9 files changed, 60 insertions(+), 61 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index afdd2b581b86e..bf77fc56d08c9 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -1043,7 +1043,7 @@ unsafe fn embed_bitcode( let section = bitcode_section_name(cgcx); llvm::LLVMSetSection(llglobal, section.as_ptr().cast()); - llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage); + llvm::set_linkage(llglobal, llvm::Linkage::PrivateLinkage); llvm::LLVMSetGlobalConstant(llglobal, llvm::True); let llconst = common::bytes_in_context(llcx, cmdline.as_bytes()); @@ -1061,7 +1061,7 @@ unsafe fn embed_bitcode( c".llvmcmd" }; llvm::LLVMSetSection(llglobal, section.as_ptr()); - llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage); + llvm::set_linkage(llglobal, llvm::Linkage::PrivateLinkage); } else { // We need custom section flags, so emit module-level inline assembly. let section_flags = if cgcx.is_pe_coff { "n" } else { "e" }; @@ -1096,7 +1096,7 @@ fn create_msvc_imps( let ptr_ty = Type::ptr_llcx(llcx); let globals = base::iter_globals(llmod) .filter(|&val| { - llvm::LLVMRustGetLinkage(val) == llvm::Linkage::ExternalLinkage + llvm::get_linkage(val) == llvm::Linkage::ExternalLinkage && llvm::LLVMIsDeclaration(val) == 0 }) .filter_map(|val| { @@ -1115,7 +1115,7 @@ fn create_msvc_imps( for (imp_name, val) in globals { let imp = llvm::LLVMAddGlobal(llmod, ptr_ty, imp_name.as_ptr()); llvm::LLVMSetInitializer(imp, val); - llvm::LLVMRustSetLinkage(imp, llvm::Linkage::ExternalLinkage); + llvm::set_linkage(imp, llvm::Linkage::ExternalLinkage); } } diff --git a/compiler/rustc_codegen_llvm/src/callee.rs b/compiler/rustc_codegen_llvm/src/callee.rs index 206a706979204..5edc1c7138a24 100644 --- a/compiler/rustc_codegen_llvm/src/callee.rs +++ b/compiler/rustc_codegen_llvm/src/callee.rs @@ -95,9 +95,9 @@ pub(crate) fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'t // whether we are sharing generics or not. The important thing here is // that the visibility we apply to the declaration is the same one that // has been applied to the definition (wherever that definition may be). - unsafe { - llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::ExternalLinkage); + llvm::set_linkage(llfn, llvm::Linkage::ExternalLinkage); + unsafe { let is_generic = instance.args.non_erasable_generics(tcx, instance.def_id()).next().is_some(); diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs index 0ced37b53a841..ff47eb944dd4a 100644 --- a/compiler/rustc_codegen_llvm/src/common.rs +++ b/compiler/rustc_codegen_llvm/src/common.rs @@ -219,8 +219,8 @@ impl<'ll, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> { llvm::LLVMSetInitializer(g, sc); llvm::LLVMSetGlobalConstant(g, True); llvm::LLVMSetUnnamedAddress(g, llvm::UnnamedAddr::Global); - llvm::LLVMRustSetLinkage(g, llvm::Linkage::InternalLinkage); } + llvm::set_linkage(g, llvm::Linkage::InternalLinkage); (s.to_owned(), g) }) .1; diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index 33a85adeb8781..0bfd433418ac0 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -172,29 +172,27 @@ fn check_and_apply_linkage<'ll, 'tcx>( if let Some(linkage) = attrs.import_linkage { debug!("get_static: sym={} linkage={:?}", sym, linkage); - unsafe { - // Declare a symbol `foo` with the desired linkage. - let g1 = cx.declare_global(sym, cx.type_i8()); - llvm::LLVMRustSetLinkage(g1, base::linkage_to_llvm(linkage)); - - // Declare an internal global `extern_with_linkage_foo` which - // is initialized with the address of `foo`. If `foo` is - // discarded during linking (for example, if `foo` has weak - // linkage and there are no definitions), then - // `extern_with_linkage_foo` will instead be initialized to - // zero. - let mut real_name = "_rust_extern_with_linkage_".to_string(); - real_name.push_str(sym); - let g2 = cx.define_global(&real_name, llty).unwrap_or_else(|| { - cx.sess().dcx().emit_fatal(SymbolAlreadyDefined { - span: cx.tcx.def_span(def_id), - symbol_name: sym, - }) - }); - llvm::LLVMRustSetLinkage(g2, llvm::Linkage::InternalLinkage); - llvm::LLVMSetInitializer(g2, g1); - g2 - } + // Declare a symbol `foo` with the desired linkage. + let g1 = cx.declare_global(sym, cx.type_i8()); + llvm::set_linkage(g1, base::linkage_to_llvm(linkage)); + + // Declare an internal global `extern_with_linkage_foo` which + // is initialized with the address of `foo`. If `foo` is + // discarded during linking (for example, if `foo` has weak + // linkage and there are no definitions), then + // `extern_with_linkage_foo` will instead be initialized to + // zero. + let mut real_name = "_rust_extern_with_linkage_".to_string(); + real_name.push_str(sym); + let g2 = cx.define_global(&real_name, llty).unwrap_or_else(|| { + cx.sess().dcx().emit_fatal(SymbolAlreadyDefined { + span: cx.tcx.def_span(def_id), + symbol_name: sym, + }) + }); + llvm::set_linkage(g2, llvm::Linkage::InternalLinkage); + unsafe { llvm::LLVMSetInitializer(g2, g1) }; + g2 } else if cx.tcx.sess.target.arch == "x86" && let Some(dllimport) = crate::common::get_dllimport(cx.tcx, def_id, sym) { @@ -224,23 +222,21 @@ impl<'ll> CodegenCx<'ll, '_> { align: Align, kind: Option<&str>, ) -> &'ll Value { - unsafe { - let gv = match kind { - Some(kind) if !self.tcx.sess.fewer_names() => { - let name = self.generate_local_symbol_name(kind); - let gv = self.define_global(&name, self.val_ty(cv)).unwrap_or_else(|| { - bug!("symbol `{}` is already defined", name); - }); - llvm::LLVMRustSetLinkage(gv, llvm::Linkage::PrivateLinkage); - gv - } - _ => self.define_private_global(self.val_ty(cv)), - }; - llvm::LLVMSetInitializer(gv, cv); - set_global_alignment(self, gv, align); - llvm::SetUnnamedAddress(gv, llvm::UnnamedAddr::Global); - gv - } + let gv = match kind { + Some(kind) if !self.tcx.sess.fewer_names() => { + let name = self.generate_local_symbol_name(kind); + let gv = self.define_global(&name, self.val_ty(cv)).unwrap_or_else(|| { + bug!("symbol `{}` is already defined", name); + }); + llvm::set_linkage(gv, llvm::Linkage::PrivateLinkage); + gv + } + _ => self.define_private_global(self.val_ty(cv)), + }; + unsafe { llvm::LLVMSetInitializer(gv, cv) }; + set_global_alignment(self, gv, align); + llvm::SetUnnamedAddress(gv, llvm::UnnamedAddr::Global); + gv } #[instrument(level = "debug", skip(self))] @@ -401,7 +397,7 @@ impl<'ll> CodegenCx<'ll, '_> { let name = llvm::get_value_name(g).to_vec(); llvm::set_value_name(g, b""); - let linkage = llvm::LLVMRustGetLinkage(g); + let linkage = llvm::get_linkage(g); let visibility = llvm::LLVMRustGetVisibility(g); let new_g = llvm::LLVMRustGetOrInsertGlobal( @@ -411,7 +407,7 @@ impl<'ll> CodegenCx<'ll, '_> { val_llty, ); - llvm::LLVMRustSetLinkage(new_g, linkage); + llvm::set_linkage(new_g, linkage); llvm::LLVMRustSetVisibility(new_g, visibility); // The old global has had its name removed but is returned by diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index fb845c0087b1f..b5985a6aa1ea7 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -605,7 +605,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { unsafe { let g = llvm::LLVMAddGlobal(self.llmod, self.val_ty(array), name.as_ptr()); llvm::LLVMSetInitializer(g, array); - llvm::LLVMRustSetLinkage(g, llvm::Linkage::AppendingLinkage); + llvm::set_linkage(g, llvm::Linkage::AppendingLinkage); llvm::LLVMSetSection(g, c"llvm.metadata".as_ptr()); } } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs index f93d3e40b2051..7947c9c8c8efd 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs @@ -76,7 +76,7 @@ pub(crate) fn get_or_insert_gdb_debug_scripts_section_global<'ll>( llvm::LLVMSetInitializer(section_var, cx.const_bytes(section_contents)); llvm::LLVMSetGlobalConstant(section_var, llvm::True); llvm::LLVMSetUnnamedAddress(section_var, llvm::UnnamedAddr::Global); - llvm::LLVMRustSetLinkage(section_var, llvm::Linkage::LinkOnceODRLinkage); + llvm::set_linkage(section_var, llvm::Linkage::LinkOnceODRLinkage); // This should make sure that the whole section is not larger than // the string it contains. Otherwise we get a warning from GDB. llvm::LLVMSetAlignment(section_var, 1); diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index c9a17c9852dbc..d04b525761942 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -785,13 +785,12 @@ fn codegen_msvc_try<'ll>( let type_info = bx.const_struct(&[type_info_vtable, bx.const_null(bx.type_ptr()), type_name], false); let tydesc = bx.declare_global("__rust_panic_type_info", bx.val_ty(type_info)); - unsafe { - llvm::LLVMRustSetLinkage(tydesc, llvm::Linkage::LinkOnceODRLinkage); - if bx.cx.tcx.sess.target.supports_comdat() { - llvm::SetUniqueComdat(bx.llmod, tydesc); - } - llvm::LLVMSetInitializer(tydesc, type_info); + + llvm::set_linkage(tydesc, llvm::Linkage::LinkOnceODRLinkage); + if bx.cx.tcx.sess.target.supports_comdat() { + llvm::SetUniqueComdat(bx.llmod, tydesc); } + unsafe { llvm::LLVMSetInitializer(tydesc, type_info) }; // The flag value of 8 indicates that we are catching the exception by // reference instead of by value. We can't use catch by value because @@ -1064,7 +1063,7 @@ fn gen_fn<'ll, 'tcx>( cx.set_frame_pointer_type(llfn); cx.apply_target_cpu_attr(llfn); // FIXME(eddyb) find a nicer way to do this. - unsafe { llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::InternalLinkage) }; + llvm::set_linkage(llfn, llvm::Linkage::InternalLinkage); let llbb = Builder::append_block(cx, llfn, "entry-block"); let bx = Builder::build(cx, llbb); codegen(bx); diff --git a/compiler/rustc_codegen_llvm/src/llvm/mod.rs b/compiler/rustc_codegen_llvm/src/llvm/mod.rs index e837022044ee0..9900742d592fb 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/mod.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/mod.rs @@ -232,6 +232,10 @@ pub fn set_global_constant(llglobal: &Value, is_constant: bool) { } } +pub fn get_linkage(llglobal: &Value) -> Linkage { + unsafe { LLVMRustGetLinkage(llglobal) } +} + pub fn set_linkage(llglobal: &Value, linkage: Linkage) { unsafe { LLVMRustSetLinkage(llglobal, linkage); diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs index bf6ef219873a5..cd41e60522886 100644 --- a/compiler/rustc_codegen_llvm/src/mono_item.rs +++ b/compiler/rustc_codegen_llvm/src/mono_item.rs @@ -39,8 +39,8 @@ impl<'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> { .emit_fatal(SymbolAlreadyDefined { span: self.tcx.def_span(def_id), symbol_name }) }); + llvm::set_linkage(g, base::linkage_to_llvm(linkage)); unsafe { - llvm::LLVMRustSetLinkage(g, base::linkage_to_llvm(linkage)); llvm::LLVMRustSetVisibility(g, base::visibility_to_llvm(visibility)); if self.should_assume_dso_local(g, false) { llvm::LLVMRustSetDSOLocal(g, true); @@ -61,7 +61,7 @@ impl<'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> { let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty()); let lldecl = self.declare_fn(symbol_name, fn_abi, Some(instance)); - unsafe { llvm::LLVMRustSetLinkage(lldecl, base::linkage_to_llvm(linkage)) }; + llvm::set_linkage(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) @@ -107,7 +107,7 @@ impl CodegenCx<'_, '_> { llval: &llvm::Value, is_declaration: bool, ) -> bool { - let linkage = unsafe { llvm::LLVMRustGetLinkage(llval) }; + let linkage = llvm::get_linkage(llval); let visibility = unsafe { llvm::LLVMRustGetVisibility(llval) }; if matches!(linkage, llvm::Linkage::InternalLinkage | llvm::Linkage::PrivateLinkage) { From 62ffe3d911386cc5ca9b4e70a2fe652b1f626159 Mon Sep 17 00:00:00 2001 From: Zalathar <Zalathar@users.noreply.github.com> Date: Sat, 19 Oct 2024 12:17:33 +1100 Subject: [PATCH 07/13] Use safe wrappers `get_visibility` and `set_visibility` --- compiler/rustc_codegen_llvm/src/allocator.rs | 17 ++++------------- compiler/rustc_codegen_llvm/src/callee.rs | 2 +- compiler/rustc_codegen_llvm/src/consts.rs | 10 ++++------ compiler/rustc_codegen_llvm/src/llvm/mod.rs | 4 ++++ compiler/rustc_codegen_llvm/src/mono_item.rs | 20 +++++++------------- 5 files changed, 20 insertions(+), 33 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/allocator.rs b/compiler/rustc_codegen_llvm/src/allocator.rs index 89f5305840b94..55ee6dcdf8784 100644 --- a/compiler/rustc_codegen_llvm/src/allocator.rs +++ b/compiler/rustc_codegen_llvm/src/allocator.rs @@ -77,20 +77,14 @@ pub(crate) unsafe fn codegen( // __rust_alloc_error_handler_should_panic let name = OomStrategy::SYMBOL; let ll_g = llvm::LLVMRustGetOrInsertGlobal(llmod, name.as_ptr().cast(), name.len(), i8); - llvm::LLVMRustSetVisibility( - ll_g, - llvm::Visibility::from_generic(tcx.sess.default_visibility()), - ); + llvm::set_visibility(ll_g, llvm::Visibility::from_generic(tcx.sess.default_visibility())); let val = tcx.sess.opts.unstable_opts.oom.should_panic(); let llval = llvm::LLVMConstInt(i8, val as u64, False); llvm::LLVMSetInitializer(ll_g, llval); let name = NO_ALLOC_SHIM_IS_UNSTABLE; let ll_g = llvm::LLVMRustGetOrInsertGlobal(llmod, name.as_ptr().cast(), name.len(), i8); - llvm::LLVMRustSetVisibility( - ll_g, - llvm::Visibility::from_generic(tcx.sess.default_visibility()), - ); + llvm::set_visibility(ll_g, llvm::Visibility::from_generic(tcx.sess.default_visibility())); let llval = llvm::LLVMConstInt(i8, 0, False); llvm::LLVMSetInitializer(ll_g, llval); } @@ -134,10 +128,7 @@ fn create_wrapper_function( None }; - llvm::LLVMRustSetVisibility( - llfn, - llvm::Visibility::from_generic(tcx.sess.default_visibility()), - ); + llvm::set_visibility(llfn, llvm::Visibility::from_generic(tcx.sess.default_visibility())); if tcx.sess.must_emit_unwind_tables() { let uwtable = @@ -151,7 +142,7 @@ fn create_wrapper_function( // -> ! DIFlagNoReturn attributes::apply_to_llfn(callee, llvm::AttributePlace::Function, &[no_return]); } - llvm::LLVMRustSetVisibility(callee, llvm::Visibility::Hidden); + llvm::set_visibility(callee, llvm::Visibility::Hidden); let llbb = llvm::LLVMAppendBasicBlockInContext(llcx, llfn, c"entry".as_ptr()); diff --git a/compiler/rustc_codegen_llvm/src/callee.rs b/compiler/rustc_codegen_llvm/src/callee.rs index 5edc1c7138a24..975b1f4dc2e12 100644 --- a/compiler/rustc_codegen_llvm/src/callee.rs +++ b/compiler/rustc_codegen_llvm/src/callee.rs @@ -136,7 +136,7 @@ pub(crate) fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'t || !cx.tcx.is_reachable_non_generic(instance_def_id)) }; if is_hidden { - llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden); + llvm::set_visibility(llfn, llvm::Visibility::Hidden); } // MinGW: For backward compatibility we rely on the linker to decide whether it diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index 0bfd433418ac0..1e3abcfd1af44 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -288,9 +288,7 @@ impl<'ll> CodegenCx<'ll, '_> { let g = self.declare_global(sym, llty); if !self.tcx.is_reachable_non_generic(def_id) { - unsafe { - llvm::LLVMRustSetVisibility(g, llvm::Visibility::Hidden); - } + llvm::set_visibility(g, llvm::Visibility::Hidden); } g @@ -308,7 +306,7 @@ impl<'ll> CodegenCx<'ll, '_> { llvm::set_thread_local_mode(g, self.tls_model); } - let dso_local = unsafe { self.should_assume_dso_local(g, true) }; + let dso_local = self.should_assume_dso_local(g, true); if dso_local { unsafe { llvm::LLVMRustSetDSOLocal(g, true); @@ -398,7 +396,7 @@ impl<'ll> CodegenCx<'ll, '_> { llvm::set_value_name(g, b""); let linkage = llvm::get_linkage(g); - let visibility = llvm::LLVMRustGetVisibility(g); + let visibility = llvm::get_visibility(g); let new_g = llvm::LLVMRustGetOrInsertGlobal( self.llmod, @@ -408,7 +406,7 @@ impl<'ll> CodegenCx<'ll, '_> { ); llvm::set_linkage(new_g, linkage); - llvm::LLVMRustSetVisibility(new_g, visibility); + llvm::set_visibility(new_g, visibility); // The old global has had its name removed but is returned by // get_static since it is in the instance cache. Provide an diff --git a/compiler/rustc_codegen_llvm/src/llvm/mod.rs b/compiler/rustc_codegen_llvm/src/llvm/mod.rs index 9900742d592fb..235b5794b8c54 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/mod.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/mod.rs @@ -242,6 +242,10 @@ pub fn set_linkage(llglobal: &Value, linkage: Linkage) { } } +pub fn get_visibility(llglobal: &Value) -> Visibility { + unsafe { LLVMRustGetVisibility(llglobal) } +} + pub fn set_visibility(llglobal: &Value, visibility: Visibility) { unsafe { LLVMRustSetVisibility(llglobal, visibility); diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs index cd41e60522886..ea8857b4739c1 100644 --- a/compiler/rustc_codegen_llvm/src/mono_item.rs +++ b/compiler/rustc_codegen_llvm/src/mono_item.rs @@ -40,8 +40,8 @@ impl<'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> { }); llvm::set_linkage(g, base::linkage_to_llvm(linkage)); + llvm::set_visibility(g, base::visibility_to_llvm(visibility)); unsafe { - llvm::LLVMRustSetVisibility(g, base::visibility_to_llvm(visibility)); if self.should_assume_dso_local(g, false) { llvm::LLVMRustSetDSOLocal(g, true); } @@ -78,21 +78,15 @@ impl<'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> { && linkage != Linkage::Private && self.tcx.is_compiler_builtins(LOCAL_CRATE) { - unsafe { - llvm::LLVMRustSetVisibility(lldecl, llvm::Visibility::Hidden); - } + llvm::set_visibility(lldecl, llvm::Visibility::Hidden); } else { - unsafe { - llvm::LLVMRustSetVisibility(lldecl, base::visibility_to_llvm(visibility)); - } + llvm::set_visibility(lldecl, base::visibility_to_llvm(visibility)); } debug!("predefine_fn: instance = {:?}", instance); - unsafe { - if self.should_assume_dso_local(lldecl, false) { - llvm::LLVMRustSetDSOLocal(lldecl, true); - } + if self.should_assume_dso_local(lldecl, false) { + unsafe { llvm::LLVMRustSetDSOLocal(lldecl, true) }; } self.instances.borrow_mut().insert(instance, lldecl); @@ -102,13 +96,13 @@ impl<'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> { impl CodegenCx<'_, '_> { /// Whether a definition or declaration can be assumed to be local to a group of /// libraries that form a single DSO or executable. - pub(crate) unsafe fn should_assume_dso_local( + pub(crate) fn should_assume_dso_local( &self, llval: &llvm::Value, is_declaration: bool, ) -> bool { let linkage = llvm::get_linkage(llval); - let visibility = unsafe { llvm::LLVMRustGetVisibility(llval) }; + let visibility = llvm::get_visibility(llval); if matches!(linkage, llvm::Linkage::InternalLinkage | llvm::Linkage::PrivateLinkage) { return true; From f2f67232a53b79b44c5b87fe5757ef1f18f4b590 Mon Sep 17 00:00:00 2001 From: Deadbeef <ent3rm4n@gmail.com> Date: Sat, 26 Oct 2024 11:35:16 +0800 Subject: [PATCH 08/13] Deny calls to non-`#[const_trait]` methods in MIR constck --- .../src/check_consts/check.rs | 29 ++++++--- .../unify-op-with-fn-call.stderr | 30 ++++++--- tests/ui/const-generics/issue-93647.stderr | 4 -- .../const-generics/issues/issue-90318.stderr | 8 --- tests/ui/consts/closure-in-foreign-crate.rs | 6 +- tests/ui/consts/const-fn-error.stderr | 8 --- tests/ui/consts/const-for-feature-gate.stderr | 8 --- tests/ui/consts/const-for.stderr | 8 --- tests/ui/consts/const-try-feature-gate.stderr | 8 --- tests/ui/consts/const-try.rs | 2 + tests/ui/consts/const-try.stderr | 19 +++++- tests/ui/consts/const_cmp_type_id.rs | 7 ++- tests/ui/consts/const_cmp_type_id.stderr | 34 ++++++++++ tests/ui/consts/control-flow/loop.stderr | 16 ----- tests/ui/consts/control-flow/try.stderr | 8 --- tests/ui/consts/fn_trait_refs.stderr | 20 ------ .../invalid-inline-const-in-match-arm.stderr | 4 -- tests/ui/consts/issue-28113.stderr | 4 -- tests/ui/consts/issue-56164.stderr | 4 -- .../issue-68542-closure-in-array-len.stderr | 4 -- .../ui/consts/issue-73976-monomorphic.stderr | 4 -- tests/ui/consts/issue-90870.rs | 3 - tests/ui/consts/issue-90870.stderr | 18 +----- tests/ui/consts/issue-94675.stderr | 4 -- tests/ui/consts/try-operator.stderr | 16 ----- .../unstable-const-fn-in-libcore.stderr | 4 -- .../impl-trait/normalize-tait-in-const.stderr | 4 -- tests/ui/issues/issue-25901.stderr | 4 -- tests/ui/never_type/issue-52443.stderr | 8 --- .../issue-35813-postfix-after-cast.stderr | 4 -- tests/ui/resolve/issue-39559-2.stderr | 8 --- ...bitrary-self-from-method-substs-ice.stderr | 4 -- .../statics/check-values-constraints.stderr | 4 -- .../call-const-trait-method-pass.stderr | 8 --- .../const-traits/call-generic-in-impl.stderr | 4 -- .../call-generic-method-chain.stderr | 23 ++++++- .../call-generic-method-dup-bound.stderr | 35 ++++++++++- .../const-traits/call-generic-method-fail.rs | 4 +- .../call-generic-method-fail.stderr | 15 +++++ .../call-generic-method-pass.stderr | 23 ++++++- tests/ui/traits/const-traits/call.rs | 3 +- tests/ui/traits/const-traits/call.stderr | 12 ++++ .../const-closure-trait-method-fail.stderr | 4 -- .../const-closure-trait-method.stderr | 4 -- .../traits/const-traits/const-closures.stderr | 12 ---- .../derive-const-non-const-type.stderr | 14 ++++- .../const_derives/derive-const-use.stderr | 62 +++++++++++++++---- .../derive-const-with-params.stderr | 22 ++++++- ...nst_closure-const_trait_impl-ice-113381.rs | 5 +- ...closure-const_trait_impl-ice-113381.stderr | 11 ++++ .../ice-112822-expected-type-for-param.rs | 1 + .../ice-112822-expected-type-for-param.stderr | 11 +++- .../traits/const-traits/generic-bound.stderr | 4 -- .../ui/traits/const-traits/hir-const-check.rs | 2 + .../const-traits/hir-const-check.stderr | 25 +++++++- .../ice-126148-failed-to-normalize.rs | 2 + .../ice-126148-failed-to-normalize.stderr | 21 ++++++- .../inline-incorrect-early-bound-in-ctfe.rs | 1 + ...nline-incorrect-early-bound-in-ctfe.stderr | 13 +++- .../traits/const-traits/issue-102985.stderr | 4 -- .../ui/traits/const-traits/issue-88155.stderr | 4 -- .../match-non-const-eq.gated.stderr | 4 -- .../match-non-const-eq.stock.stderr | 4 -- ...st-op-const-closure-non-const-outer.stderr | 4 -- .../non-const-op-in-closure-in-const.stderr | 4 -- .../const-traits/std-impl-gate.gated.stderr | 4 -- .../const-traits/std-impl-gate.stock.stderr | 4 -- .../super-traits-fail-2.nn.stderr | 11 +++- .../super-traits-fail-2.ny.stderr | 11 +++- .../const-traits/super-traits-fail-2.rs | 1 + .../super-traits-fail-3.nn.stderr | 11 +++- .../super-traits-fail-3.ny.stderr | 11 +++- .../const-traits/super-traits-fail-3.rs | 1 + .../trait-default-body-stability.stderr | 19 +++++- .../typeck_type_placeholder_item.stderr | 8 --- 75 files changed, 438 insertions(+), 324 deletions(-) create mode 100644 tests/ui/consts/const_cmp_type_id.stderr create mode 100644 tests/ui/traits/const-traits/call-generic-method-fail.stderr create mode 100644 tests/ui/traits/const-traits/call.stderr create mode 100644 tests/ui/traits/const-traits/effects/const_closure-const_trait_impl-ice-113381.stderr diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs index 8f1a887a96144..004fb12419f11 100644 --- a/compiler/rustc_const_eval/src/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/check_consts/check.rs @@ -616,14 +616,16 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { let mut is_trait = false; // Attempting to call a trait method? - if tcx.trait_of_item(callee).is_some() { + if let Some(trait_did) = tcx.trait_of_item(callee) { trace!("attempting to call a trait method"); + + let trait_is_const = tcx.is_const_trait(trait_did); // trait method calls are only permitted when `effects` is enabled. - // we don't error, since that is handled by typeck. We try to resolve - // the trait into the concrete method, and uses that for const stability - // checks. + // typeck ensures the conditions for calling a const trait method are met, + // so we only error if the trait isn't const. We try to resolve the trait + // into the concrete method, and uses that for const stability checks. // FIXME(effects) we might consider moving const stability checks to typeck as well. - if tcx.features().effects() { + if tcx.features().effects() && trait_is_const { // This skips the check below that ensures we only call `const fn`. is_trait = true; @@ -638,17 +640,24 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { callee = def; } } else { + // if the trait is const but the user has not enabled the feature(s), + // suggest them. + let feature = if trait_is_const { + Some(if tcx.features().const_trait_impl() { + sym::effects + } else { + sym::const_trait_impl + }) + } else { + None + }; self.check_op(ops::FnCallNonConst { caller, callee, args: fn_args, span: *fn_span, call_source, - feature: Some(if tcx.features().const_trait_impl() { - sym::effects - } else { - sym::const_trait_impl - }), + feature, }); // If we allowed this, we're in miri-unleashed mode, so we might // as well skip the remaining checks. diff --git a/tests/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.stderr b/tests/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.stderr index bae8249845c02..b8d7c94bddc80 100644 --- a/tests/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.stderr +++ b/tests/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.stderr @@ -27,11 +27,13 @@ LL + #[derive(ConstParamTy)] LL | struct Foo(u8); | -error[E0284]: type annotations needed: cannot normalize `foo<N>::{constant#0}` - --> $DIR/unify-op-with-fn-call.rs:20:25 +error[E0015]: cannot call non-const operator in constants + --> $DIR/unify-op-with-fn-call.rs:20:39 | LL | fn foo<const N: Foo>(a: Evaluatable<{ N + N }>) { - | ^^^^^^^^^^^^^^^^^^^^^^ cannot normalize `foo<N>::{constant#0}` + | ^^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants error[E0741]: `Foo` must implement `ConstParamTy` to be used as the type of a const generic parameter --> $DIR/unify-op-with-fn-call.rs:20:17 @@ -63,11 +65,21 @@ error[E0284]: type annotations needed: cannot normalize `foo2<N>::{constant#0}` LL | fn foo2<const N: usize>(a: Evaluatable2<{ N + N }>) { | ^^^^^^^^^^^^^^^^^^^^^^^ cannot normalize `foo2<N>::{constant#0}` -error[E0284]: type annotations needed: cannot normalize `foo<N>::{constant#0}` - --> $DIR/unify-op-with-fn-call.rs:21:11 +error[E0015]: cannot call non-const fn `<Foo as Add>::add` in constants + --> $DIR/unify-op-with-fn-call.rs:21:13 | LL | bar::<{ std::ops::Add::add(N, N) }>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot normalize `foo<N>::{constant#0}` + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + +error[E0015]: cannot call non-const fn `<usize as Add>::add` in constants + --> $DIR/unify-op-with-fn-call.rs:30:14 + | +LL | bar2::<{ std::ops::Add::add(N, N) }>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants error[E0284]: type annotations needed: cannot normalize `foo2<N>::{constant#0}` --> $DIR/unify-op-with-fn-call.rs:30:12 @@ -75,7 +87,7 @@ error[E0284]: type annotations needed: cannot normalize `foo2<N>::{constant#0}` LL | bar2::<{ std::ops::Add::add(N, N) }>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot normalize `foo2<N>::{constant#0}` -error: aborting due to 9 previous errors +error: aborting due to 10 previous errors -Some errors have detailed explanations: E0284, E0741. -For more information about an error, try `rustc --explain E0284`. +Some errors have detailed explanations: E0015, E0284, E0741. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/const-generics/issue-93647.stderr b/tests/ui/const-generics/issue-93647.stderr index 81f50a1b51724..38fb3d79459fb 100644 --- a/tests/ui/const-generics/issue-93647.stderr +++ b/tests/ui/const-generics/issue-93647.stderr @@ -6,10 +6,6 @@ LL | (||1usize)() | = note: closures need an RFC before allowed to be called in constants = note: calls in constants are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(const_trait_impl)]` to the crate attributes to enable - | -LL + #![feature(const_trait_impl)] - | error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/issues/issue-90318.stderr b/tests/ui/const-generics/issues/issue-90318.stderr index a534e8f8d44f8..9c7cb5ceb58c0 100644 --- a/tests/ui/const-generics/issues/issue-90318.stderr +++ b/tests/ui/const-generics/issues/issue-90318.stderr @@ -29,10 +29,6 @@ LL | If<{ TypeId::of::<T>() != TypeId::of::<()>() }>: True, note: impl defined here, but it is not `const` --> $SRC_DIR/core/src/any.rs:LL:COL = note: calls in constants are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(const_trait_impl)]` to the crate attributes to enable - | -LL + #![feature(const_trait_impl)] - | error[E0015]: cannot call non-const operator in constants --> $DIR/issue-90318.rs:22:10 @@ -43,10 +39,6 @@ LL | If<{ TypeId::of::<T>() != TypeId::of::<()>() }>: True, note: impl defined here, but it is not `const` --> $SRC_DIR/core/src/any.rs:LL:COL = note: calls in constants are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(const_trait_impl)]` to the crate attributes to enable - | -LL + #![feature(const_trait_impl)] - | error: aborting due to 4 previous errors diff --git a/tests/ui/consts/closure-in-foreign-crate.rs b/tests/ui/consts/closure-in-foreign-crate.rs index 701cf0910450d..94e40fcf1e418 100644 --- a/tests/ui/consts/closure-in-foreign-crate.rs +++ b/tests/ui/consts/closure-in-foreign-crate.rs @@ -1,8 +1,8 @@ -//@ aux-build:closure-in-foreign-crate.rs +// FIXME(effects) aux-build:closure-in-foreign-crate.rs //@ build-pass -extern crate closure_in_foreign_crate; +// FIXME(effects) extern crate closure_in_foreign_crate; -const _: () = closure_in_foreign_crate::test(); +// FIXME(effects) const _: () = closure_in_foreign_crate::test(); fn main() {} diff --git a/tests/ui/consts/const-fn-error.stderr b/tests/ui/consts/const-fn-error.stderr index e886a0b4fe44c..42a6f2704c9e7 100644 --- a/tests/ui/consts/const-fn-error.stderr +++ b/tests/ui/consts/const-fn-error.stderr @@ -22,10 +22,6 @@ LL | for i in 0..x { note: impl defined here, but it is not `const` --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(const_trait_impl)]` to the crate attributes to enable - | -LL + #![feature(const_trait_impl)] - | error[E0015]: cannot call non-const fn `<std::ops::Range<usize> as Iterator>::next` in constant functions --> $DIR/const-fn-error.rs:5:14 @@ -34,10 +30,6 @@ LL | for i in 0..x { | ^^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(const_trait_impl)]` to the crate attributes to enable - | -LL + #![feature(const_trait_impl)] - | error: aborting due to 3 previous errors diff --git a/tests/ui/consts/const-for-feature-gate.stderr b/tests/ui/consts/const-for-feature-gate.stderr index 3344611a60ca8..6e099a3159d9d 100644 --- a/tests/ui/consts/const-for-feature-gate.stderr +++ b/tests/ui/consts/const-for-feature-gate.stderr @@ -17,10 +17,6 @@ LL | for _ in 0..5 {} note: impl defined here, but it is not `const` --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL = note: calls in constants are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(const_trait_impl)]` to the crate attributes to enable - | -LL + #![feature(const_trait_impl)] - | error[E0015]: cannot call non-const fn `<std::ops::Range<i32> as Iterator>::next` in constants --> $DIR/const-for-feature-gate.rs:4:14 @@ -29,10 +25,6 @@ LL | for _ in 0..5 {} | ^^^^ | = note: calls in constants are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(const_trait_impl)]` to the crate attributes to enable - | -LL + #![feature(const_trait_impl)] - | error: aborting due to 3 previous errors diff --git a/tests/ui/consts/const-for.stderr b/tests/ui/consts/const-for.stderr index 2b817c2d20c8e..78336dc93e857 100644 --- a/tests/ui/consts/const-for.stderr +++ b/tests/ui/consts/const-for.stderr @@ -7,10 +7,6 @@ LL | for _ in 0..5 {} note: impl defined here, but it is not `const` --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL = note: calls in constants are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(const_trait_impl)]` to the crate attributes to enable - | -LL + #![feature(const_trait_impl)] - | error[E0015]: cannot call non-const fn `<std::ops::Range<i32> as Iterator>::next` in constants --> $DIR/const-for.rs:4:14 @@ -19,10 +15,6 @@ LL | for _ in 0..5 {} | ^^^^ | = note: calls in constants are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(const_trait_impl)]` to the crate attributes to enable - | -LL + #![feature(const_trait_impl)] - | error: aborting due to 2 previous errors diff --git a/tests/ui/consts/const-try-feature-gate.stderr b/tests/ui/consts/const-try-feature-gate.stderr index 0c4c16fc56ac0..dc1dabc2f4f65 100644 --- a/tests/ui/consts/const-try-feature-gate.stderr +++ b/tests/ui/consts/const-try-feature-gate.stderr @@ -17,10 +17,6 @@ LL | Some(())?; note: impl defined here, but it is not `const` --> $SRC_DIR/core/src/option.rs:LL:COL = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(const_trait_impl)]` to the crate attributes to enable - | -LL + #![feature(const_trait_impl)] - | error[E0015]: `?` cannot convert from residual of `Option<()>` in constant functions --> $DIR/const-try-feature-gate.rs:4:5 @@ -31,10 +27,6 @@ LL | Some(())?; note: impl defined here, but it is not `const` --> $SRC_DIR/core/src/option.rs:LL:COL = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(const_trait_impl)]` to the crate attributes to enable - | -LL + #![feature(const_trait_impl)] - | error: aborting due to 3 previous errors diff --git a/tests/ui/consts/const-try.rs b/tests/ui/consts/const-try.rs index 2862b6ffb17bf..758c4dd1e8c41 100644 --- a/tests/ui/consts/const-try.rs +++ b/tests/ui/consts/const-try.rs @@ -34,6 +34,8 @@ impl const Try for TryMe { const fn t() -> TryMe { TryMe?; + //~^ ERROR `?` cannot determine the branch of `TryMe` in constant functions + //~| ERROR `?` cannot convert from residual of `TryMe` in constant functions TryMe } diff --git a/tests/ui/consts/const-try.stderr b/tests/ui/consts/const-try.stderr index ba9da2421073f..abb1a921cfa46 100644 --- a/tests/ui/consts/const-try.stderr +++ b/tests/ui/consts/const-try.stderr @@ -16,5 +16,22 @@ LL | impl const Try for TryMe { = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` = note: adding a non-const method body in the future would be a breaking change -error: aborting due to 2 previous errors +error[E0015]: `?` cannot determine the branch of `TryMe` in constant functions + --> $DIR/const-try.rs:36:5 + | +LL | TryMe?; + | ^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error[E0015]: `?` cannot convert from residual of `TryMe` in constant functions + --> $DIR/const-try.rs:36:5 + | +LL | TryMe?; + | ^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error: aborting due to 4 previous errors +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/const_cmp_type_id.rs b/tests/ui/consts/const_cmp_type_id.rs index 77482007be48a..3a54764f422f7 100644 --- a/tests/ui/consts/const_cmp_type_id.rs +++ b/tests/ui/consts/const_cmp_type_id.rs @@ -1,4 +1,3 @@ -//@ check-pass //@ compile-flags: -Znext-solver #![feature(const_type_id, const_trait_impl, effects)] #![allow(incomplete_features)] @@ -7,11 +6,13 @@ use std::any::TypeId; fn main() { const { - // FIXME(effects) this isn't supposed to pass (right now) but it did. - // revisit binops typeck please. assert!(TypeId::of::<u8>() == TypeId::of::<u8>()); + //~^ ERROR cannot call non-const operator in constants assert!(TypeId::of::<()>() != TypeId::of::<u8>()); + //~^ ERROR cannot call non-const operator in constants let _a = TypeId::of::<u8>() < TypeId::of::<u16>(); + //~^ ERROR cannot call non-const operator in constants // can't assert `_a` because it is not deterministic + // FIXME(effects) make it pass } } diff --git a/tests/ui/consts/const_cmp_type_id.stderr b/tests/ui/consts/const_cmp_type_id.stderr new file mode 100644 index 0000000000000..12f35361b808a --- /dev/null +++ b/tests/ui/consts/const_cmp_type_id.stderr @@ -0,0 +1,34 @@ +error[E0015]: cannot call non-const operator in constants + --> $DIR/const_cmp_type_id.rs:9:17 + | +LL | assert!(TypeId::of::<u8>() == TypeId::of::<u8>()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: impl defined here, but it is not `const` + --> $SRC_DIR/core/src/any.rs:LL:COL + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + +error[E0015]: cannot call non-const operator in constants + --> $DIR/const_cmp_type_id.rs:11:17 + | +LL | assert!(TypeId::of::<()>() != TypeId::of::<u8>()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: impl defined here, but it is not `const` + --> $SRC_DIR/core/src/any.rs:LL:COL + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + +error[E0015]: cannot call non-const operator in constants + --> $DIR/const_cmp_type_id.rs:13:18 + | +LL | let _a = TypeId::of::<u8>() < TypeId::of::<u16>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: impl defined here, but it is not `const` + --> $SRC_DIR/core/src/any.rs:LL:COL + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/control-flow/loop.stderr b/tests/ui/consts/control-flow/loop.stderr index 13d5d3e0b55c8..5e43c70e9dfbe 100644 --- a/tests/ui/consts/control-flow/loop.stderr +++ b/tests/ui/consts/control-flow/loop.stderr @@ -35,10 +35,6 @@ LL | for i in 0..4 { note: impl defined here, but it is not `const` --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL = note: calls in constants are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(const_trait_impl)]` to the crate attributes to enable - | -LL + #![feature(const_trait_impl)] - | error[E0015]: cannot call non-const fn `<std::ops::Range<i32> as Iterator>::next` in constants --> $DIR/loop.rs:53:14 @@ -47,10 +43,6 @@ LL | for i in 0..4 { | ^^^^ | = note: calls in constants are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(const_trait_impl)]` to the crate attributes to enable - | -LL + #![feature(const_trait_impl)] - | error[E0015]: cannot convert `std::ops::Range<i32>` into an iterator in constants --> $DIR/loop.rs:59:14 @@ -61,10 +53,6 @@ LL | for i in 0..4 { note: impl defined here, but it is not `const` --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL = note: calls in constants are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(const_trait_impl)]` to the crate attributes to enable - | -LL + #![feature(const_trait_impl)] - | error[E0015]: cannot call non-const fn `<std::ops::Range<i32> as Iterator>::next` in constants --> $DIR/loop.rs:59:14 @@ -73,10 +61,6 @@ LL | for i in 0..4 { | ^^^^ | = note: calls in constants are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(const_trait_impl)]` to the crate attributes to enable - | -LL + #![feature(const_trait_impl)] - | error: aborting due to 6 previous errors diff --git a/tests/ui/consts/control-flow/try.stderr b/tests/ui/consts/control-flow/try.stderr index e08f52369faaa..5e2c77318e782 100644 --- a/tests/ui/consts/control-flow/try.stderr +++ b/tests/ui/consts/control-flow/try.stderr @@ -17,10 +17,6 @@ LL | x?; note: impl defined here, but it is not `const` --> $SRC_DIR/core/src/option.rs:LL:COL = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(const_trait_impl)]` to the crate attributes to enable - | -LL + #![feature(const_trait_impl)] - | error[E0015]: `?` cannot convert from residual of `Option<i32>` in constant functions --> $DIR/try.rs:6:5 @@ -31,10 +27,6 @@ LL | x?; note: impl defined here, but it is not `const` --> $SRC_DIR/core/src/option.rs:LL:COL = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(const_trait_impl)]` to the crate attributes to enable - | -LL + #![feature(const_trait_impl)] - | error: aborting due to 3 previous errors diff --git a/tests/ui/consts/fn_trait_refs.stderr b/tests/ui/consts/fn_trait_refs.stderr index 2b012432afd41..82b2b87c4a5ad 100644 --- a/tests/ui/consts/fn_trait_refs.stderr +++ b/tests/ui/consts/fn_trait_refs.stderr @@ -183,10 +183,6 @@ LL | assert!(test_one == (1, 1, 1)); | ^^^^^^^^^^^^^^^^^^^^^ | = note: calls in constants are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(effects)]` to the crate attributes to enable - | -LL + #![feature(effects)] - | error[E0015]: cannot call non-const operator in constants --> $DIR/fn_trait_refs.rs:73:17 @@ -195,10 +191,6 @@ LL | assert!(test_two == (2, 2)); | ^^^^^^^^^^^^^^^^^^ | = note: calls in constants are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(effects)]` to the crate attributes to enable - | -LL + #![feature(effects)] - | error[E0015]: cannot call non-const closure in constant functions --> $DIR/fn_trait_refs.rs:15:5 @@ -211,10 +203,6 @@ help: consider further restricting this bound | LL | T: ~const Fn<()> + ~const Destruct + ~const Fn(), | +++++++++++++ -help: add `#![feature(effects)]` to the crate attributes to enable - | -LL + #![feature(effects)] - | error[E0493]: destructor of `T` cannot be evaluated at compile-time --> $DIR/fn_trait_refs.rs:11:23 @@ -236,10 +224,6 @@ help: consider further restricting this bound | LL | T: ~const FnMut<()> + ~const Destruct + ~const FnMut(), | ++++++++++++++++ -help: add `#![feature(effects)]` to the crate attributes to enable - | -LL + #![feature(effects)] - | error[E0493]: destructor of `T` cannot be evaluated at compile-time --> $DIR/fn_trait_refs.rs:18:27 @@ -261,10 +245,6 @@ help: consider further restricting this bound | LL | T: ~const FnOnce<()> + ~const FnOnce(), | +++++++++++++++++ -help: add `#![feature(effects)]` to the crate attributes to enable - | -LL + #![feature(effects)] - | error[E0493]: destructor of `T` cannot be evaluated at compile-time --> $DIR/fn_trait_refs.rs:32:21 diff --git a/tests/ui/consts/invalid-inline-const-in-match-arm.stderr b/tests/ui/consts/invalid-inline-const-in-match-arm.stderr index 0e41053a29df0..2e48837bdcdcb 100644 --- a/tests/ui/consts/invalid-inline-const-in-match-arm.stderr +++ b/tests/ui/consts/invalid-inline-const-in-match-arm.stderr @@ -6,10 +6,6 @@ LL | const { (|| {})() } => {} | = note: closures need an RFC before allowed to be called in constants = note: calls in constants are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(const_trait_impl)]` to the crate attributes to enable - | -LL + #![feature(const_trait_impl)] - | error: could not evaluate constant pattern --> $DIR/invalid-inline-const-in-match-arm.rs:5:9 diff --git a/tests/ui/consts/issue-28113.stderr b/tests/ui/consts/issue-28113.stderr index c2f53870173a3..401536c1353ea 100644 --- a/tests/ui/consts/issue-28113.stderr +++ b/tests/ui/consts/issue-28113.stderr @@ -6,10 +6,6 @@ LL | || -> u8 { 5 }() | = note: closures need an RFC before allowed to be called in constants = note: calls in constants are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(const_trait_impl)]` to the crate attributes to enable - | -LL + #![feature(const_trait_impl)] - | error: aborting due to 1 previous error diff --git a/tests/ui/consts/issue-56164.stderr b/tests/ui/consts/issue-56164.stderr index 6ec4ce0fbd70e..de5a53c9ad264 100644 --- a/tests/ui/consts/issue-56164.stderr +++ b/tests/ui/consts/issue-56164.stderr @@ -6,10 +6,6 @@ LL | const fn foo() { (||{})() } | = note: closures need an RFC before allowed to be called in constant functions = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(const_trait_impl)]` to the crate attributes to enable - | -LL + #![feature(const_trait_impl)] - | error: function pointer calls are not allowed in constant functions --> $DIR/issue-56164.rs:5:5 diff --git a/tests/ui/consts/issue-68542-closure-in-array-len.stderr b/tests/ui/consts/issue-68542-closure-in-array-len.stderr index b414a6e0dba0e..9f323b2259f8f 100644 --- a/tests/ui/consts/issue-68542-closure-in-array-len.stderr +++ b/tests/ui/consts/issue-68542-closure-in-array-len.stderr @@ -6,10 +6,6 @@ LL | a: [(); (|| { 0 })()] | = note: closures need an RFC before allowed to be called in constants = note: calls in constants are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(const_trait_impl)]` to the crate attributes to enable - | -LL + #![feature(const_trait_impl)] - | error: aborting due to 1 previous error diff --git a/tests/ui/consts/issue-73976-monomorphic.stderr b/tests/ui/consts/issue-73976-monomorphic.stderr index 79dbed4bea82f..ef754b23ff06e 100644 --- a/tests/ui/consts/issue-73976-monomorphic.stderr +++ b/tests/ui/consts/issue-73976-monomorphic.stderr @@ -7,10 +7,6 @@ LL | GetTypeId::<T>::VALUE == GetTypeId::<usize>::VALUE note: impl defined here, but it is not `const` --> $SRC_DIR/core/src/any.rs:LL:COL = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(effects)]` to the crate attributes to enable - | -LL + #![feature(effects)] - | error: aborting due to 1 previous error diff --git a/tests/ui/consts/issue-90870.rs b/tests/ui/consts/issue-90870.rs index e1929c68c70a1..b62769a33f8e2 100644 --- a/tests/ui/consts/issue-90870.rs +++ b/tests/ui/consts/issue-90870.rs @@ -3,9 +3,6 @@ #![allow(dead_code)] const fn f(a: &u8, b: &u8) -> bool { -//~^ HELP: add `#![feature(const_trait_impl)]` -//~| HELP: add `#![feature(const_trait_impl)]` -//~| HELP: add `#![feature(const_trait_impl)]` a == b //~^ ERROR: cannot call non-const operator in constant functions [E0015] //~| HELP: consider dereferencing here diff --git a/tests/ui/consts/issue-90870.stderr b/tests/ui/consts/issue-90870.stderr index df88a0c95cc5b..ea987920d7d33 100644 --- a/tests/ui/consts/issue-90870.stderr +++ b/tests/ui/consts/issue-90870.stderr @@ -1,5 +1,5 @@ error[E0015]: cannot call non-const operator in constant functions - --> $DIR/issue-90870.rs:9:5 + --> $DIR/issue-90870.rs:6:5 | LL | a == b | ^^^^^^ @@ -9,13 +9,9 @@ help: consider dereferencing here | LL | *a == *b | + + -help: add `#![feature(const_trait_impl)]` to the crate attributes to enable - | -LL + #![feature(const_trait_impl)] - | error[E0015]: cannot call non-const operator in constant functions - --> $DIR/issue-90870.rs:15:5 + --> $DIR/issue-90870.rs:12:5 | LL | a == b | ^^^^^^ @@ -25,13 +21,9 @@ help: consider dereferencing here | LL | ****a == ****b | ++++ ++++ -help: add `#![feature(const_trait_impl)]` to the crate attributes to enable - | -LL + #![feature(const_trait_impl)] - | error[E0015]: cannot call non-const operator in constant functions - --> $DIR/issue-90870.rs:22:12 + --> $DIR/issue-90870.rs:19:12 | LL | if l == r { | ^^^^^^ @@ -41,10 +33,6 @@ help: consider dereferencing here | LL | if *l == *r { | + + -help: add `#![feature(const_trait_impl)]` to the crate attributes to enable - | -LL + #![feature(const_trait_impl)] - | error: aborting due to 3 previous errors diff --git a/tests/ui/consts/issue-94675.stderr b/tests/ui/consts/issue-94675.stderr index a85c5e10374f8..8cad13724f20e 100644 --- a/tests/ui/consts/issue-94675.stderr +++ b/tests/ui/consts/issue-94675.stderr @@ -7,10 +7,6 @@ LL | self.bar[0] = baz.len(); note: impl defined here, but it is not `const` --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(effects)]` to the crate attributes to enable - | -LL + #![feature(effects)] - | error: aborting due to 1 previous error diff --git a/tests/ui/consts/try-operator.stderr b/tests/ui/consts/try-operator.stderr index 2c8b4c7fcd9cb..40d96ed3a1005 100644 --- a/tests/ui/consts/try-operator.stderr +++ b/tests/ui/consts/try-operator.stderr @@ -13,10 +13,6 @@ LL | Err(())?; note: impl defined here, but it is not `const` --> $SRC_DIR/core/src/result.rs:LL:COL = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(effects)]` to the crate attributes to enable - | -LL + #![feature(effects)] - | error[E0015]: `?` cannot convert from residual of `Result<bool, ()>` in constant functions --> $DIR/try-operator.rs:10:9 @@ -27,10 +23,6 @@ LL | Err(())?; note: impl defined here, but it is not `const` --> $SRC_DIR/core/src/result.rs:LL:COL = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(effects)]` to the crate attributes to enable - | -LL + #![feature(effects)] - | error[E0015]: `?` cannot determine the branch of `Option<()>` in constant functions --> $DIR/try-operator.rs:18:9 @@ -41,10 +33,6 @@ LL | None?; note: impl defined here, but it is not `const` --> $SRC_DIR/core/src/option.rs:LL:COL = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(effects)]` to the crate attributes to enable - | -LL + #![feature(effects)] - | error[E0015]: `?` cannot convert from residual of `Option<()>` in constant functions --> $DIR/try-operator.rs:18:9 @@ -55,10 +43,6 @@ LL | None?; note: impl defined here, but it is not `const` --> $SRC_DIR/core/src/option.rs:LL:COL = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(effects)]` to the crate attributes to enable - | -LL + #![feature(effects)] - | error: aborting due to 5 previous errors diff --git a/tests/ui/consts/unstable-const-fn-in-libcore.stderr b/tests/ui/consts/unstable-const-fn-in-libcore.stderr index 59476f9860321..e546694070dd9 100644 --- a/tests/ui/consts/unstable-const-fn-in-libcore.stderr +++ b/tests/ui/consts/unstable-const-fn-in-libcore.stderr @@ -23,10 +23,6 @@ help: consider further restricting this bound | LL | const fn unwrap_or_else<F: ~const FnOnce() -> T + ~const FnOnce()>(self, f: F) -> T { | +++++++++++++++++ -help: add `#![feature(effects)]` to the crate attributes to enable - | -LL + #![feature(effects)] - | error[E0493]: destructor of `F` cannot be evaluated at compile-time --> $DIR/unstable-const-fn-in-libcore.rs:19:60 diff --git a/tests/ui/impl-trait/normalize-tait-in-const.stderr b/tests/ui/impl-trait/normalize-tait-in-const.stderr index f1e6207ed817d..b370a5d7eb116 100644 --- a/tests/ui/impl-trait/normalize-tait-in-const.stderr +++ b/tests/ui/impl-trait/normalize-tait-in-const.stderr @@ -37,10 +37,6 @@ help: consider further restricting this bound | LL | const fn with_positive<F: for<'a> ~const Fn(&'a Alias<'a>) + ~const Destruct + ~const Fn(&foo::Alias<'_>)>(fun: F) { | ++++++++++++++++++++++++++++ -help: add `#![feature(effects)]` to the crate attributes to enable - | -LL + #![feature(effects)] - | error[E0493]: destructor of `F` cannot be evaluated at compile-time --> $DIR/normalize-tait-in-const.rs:26:79 diff --git a/tests/ui/issues/issue-25901.stderr b/tests/ui/issues/issue-25901.stderr index 3fedfd9641702..bcbc805908ffd 100644 --- a/tests/ui/issues/issue-25901.stderr +++ b/tests/ui/issues/issue-25901.stderr @@ -17,10 +17,6 @@ LL | impl Deref for A { | ^^^^^^^^^^^^^^^^ = note: calls in statics are limited to constant functions, tuple structs and tuple variants = note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)` -help: add `#![feature(const_trait_impl)]` to the crate attributes to enable - | -LL + #![feature(const_trait_impl)] - | error: aborting due to 1 previous error diff --git a/tests/ui/never_type/issue-52443.stderr b/tests/ui/never_type/issue-52443.stderr index adcff6637b0d9..2207ceb503367 100644 --- a/tests/ui/never_type/issue-52443.stderr +++ b/tests/ui/never_type/issue-52443.stderr @@ -50,10 +50,6 @@ LL | [(); { for _ in 0usize.. {}; 0}]; note: impl defined here, but it is not `const` --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL = note: calls in constants are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(const_trait_impl)]` to the crate attributes to enable - | -LL + #![feature(const_trait_impl)] - | error[E0015]: cannot call non-const fn `<RangeFrom<usize> as Iterator>::next` in constants --> $DIR/issue-52443.rs:9:21 @@ -62,10 +58,6 @@ LL | [(); { for _ in 0usize.. {}; 0}]; | ^^^^^^^^ | = note: calls in constants are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(const_trait_impl)]` to the crate attributes to enable - | -LL + #![feature(const_trait_impl)] - | error: aborting due to 5 previous errors; 1 warning emitted diff --git a/tests/ui/parser/issues/issue-35813-postfix-after-cast.stderr b/tests/ui/parser/issues/issue-35813-postfix-after-cast.stderr index 66b57c772d546..e34371be3d262 100644 --- a/tests/ui/parser/issues/issue-35813-postfix-after-cast.stderr +++ b/tests/ui/parser/issues/issue-35813-postfix-after-cast.stderr @@ -353,10 +353,6 @@ LL | static bar: &[i32] = &(&[1,2,3] as &[i32][0..1]); | = note: calls in statics are limited to constant functions, tuple structs and tuple variants = note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)` -help: add `#![feature(const_trait_impl)]` to the crate attributes to enable - | -LL + #![feature(const_trait_impl)] - | error: aborting due to 40 previous errors diff --git a/tests/ui/resolve/issue-39559-2.stderr b/tests/ui/resolve/issue-39559-2.stderr index 7f51357a56f44..ea27e7bd2508f 100644 --- a/tests/ui/resolve/issue-39559-2.stderr +++ b/tests/ui/resolve/issue-39559-2.stderr @@ -5,10 +5,6 @@ LL | let array: [usize; Dim3::dim()] | ^^^^^^^^^^^ | = note: calls in constants are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(const_trait_impl)]` to the crate attributes to enable - | -LL + #![feature(const_trait_impl)] - | error[E0015]: cannot call non-const fn `<Dim3 as Dim>::dim` in constants --> $DIR/issue-39559-2.rs:16:15 @@ -17,10 +13,6 @@ LL | = [0; Dim3::dim()]; | ^^^^^^^^^^^ | = note: calls in constants are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(const_trait_impl)]` to the crate attributes to enable - | -LL + #![feature(const_trait_impl)] - | error: aborting due to 2 previous errors diff --git a/tests/ui/self/arbitrary-self-from-method-substs-ice.stderr b/tests/ui/self/arbitrary-self-from-method-substs-ice.stderr index 505b0a173fada..6ae60e7af47d8 100644 --- a/tests/ui/self/arbitrary-self-from-method-substs-ice.stderr +++ b/tests/ui/self/arbitrary-self-from-method-substs-ice.stderr @@ -5,10 +5,6 @@ LL | self.0 | ^^^^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(const_trait_impl)]` to the crate attributes to enable - | -LL + #![feature(const_trait_impl)] - | error[E0493]: destructor of `R` cannot be evaluated at compile-time --> $DIR/arbitrary-self-from-method-substs-ice.rs:10:43 diff --git a/tests/ui/statics/check-values-constraints.stderr b/tests/ui/statics/check-values-constraints.stderr index 24763c175fc89..b4ee34530d3bd 100644 --- a/tests/ui/statics/check-values-constraints.stderr +++ b/tests/ui/statics/check-values-constraints.stderr @@ -37,10 +37,6 @@ LL | field2: SafeEnum::Variant4("str".to_string()), | = note: calls in statics are limited to constant functions, tuple structs and tuple variants = note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)` -help: add `#![feature(const_trait_impl)]` to the crate attributes to enable - | -LL + #![feature(const_trait_impl)] - | error[E0010]: allocations are not allowed in statics --> $DIR/check-values-constraints.rs:96:5 diff --git a/tests/ui/traits/const-traits/call-const-trait-method-pass.stderr b/tests/ui/traits/const-traits/call-const-trait-method-pass.stderr index c1cead542163e..32f53137a00e6 100644 --- a/tests/ui/traits/const-traits/call-const-trait-method-pass.stderr +++ b/tests/ui/traits/const-traits/call-const-trait-method-pass.stderr @@ -23,10 +23,6 @@ LL | const ADD_INT: Int = Int(1i32) + Int(2i32); | ^^^^^^^^^^^^^^^^^^^^^ | = note: calls in constants are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(effects)]` to the crate attributes to enable - | -LL + #![feature(effects)] - | error[E0015]: cannot call non-const fn `<i32 as Plus>::plus` in constant functions --> $DIR/call-const-trait-method-pass.rs:11:20 @@ -47,10 +43,6 @@ LL | !self.eq(other) | ^^^^^^^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(effects)]` to the crate attributes to enable - | -LL + #![feature(effects)] - | error[E0015]: cannot call non-const fn `<i32 as Plus>::plus` in constant functions --> $DIR/call-const-trait-method-pass.rs:36:7 diff --git a/tests/ui/traits/const-traits/call-generic-in-impl.stderr b/tests/ui/traits/const-traits/call-generic-in-impl.stderr index 368c22675e7f6..971e77e372b81 100644 --- a/tests/ui/traits/const-traits/call-generic-in-impl.stderr +++ b/tests/ui/traits/const-traits/call-generic-in-impl.stderr @@ -19,10 +19,6 @@ LL | PartialEq::eq(self, other) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(effects)]` to the crate attributes to enable - | -LL + #![feature(effects)] - | error: aborting due to 3 previous errors diff --git a/tests/ui/traits/const-traits/call-generic-method-chain.stderr b/tests/ui/traits/const-traits/call-generic-method-chain.stderr index 62eed0f14f9cb..aa90305c64826 100644 --- a/tests/ui/traits/const-traits/call-generic-method-chain.stderr +++ b/tests/ui/traits/const-traits/call-generic-method-chain.stderr @@ -44,5 +44,26 @@ LL | const fn equals_self_wrapper<T: ~const PartialEq>(t: &T) -> bool { | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 5 previous errors; 1 warning emitted +error[E0015]: cannot call non-const operator in constant functions + --> $DIR/call-generic-method-chain.rs:21:5 + | +LL | *t == *t + | ^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +help: consider further restricting this bound + | +LL | const fn equals_self<T: ~const PartialEq + ~const std::cmp::PartialEq>(t: &T) -> bool { + | ++++++++++++++++++++++++++++ + +error[E0015]: cannot call non-const fn `<S as PartialEq>::eq` in constant functions + --> $DIR/call-generic-method-chain.rs:16:15 + | +LL | !self.eq(other) + | ^^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error: aborting due to 7 previous errors; 1 warning emitted +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/call-generic-method-dup-bound.stderr b/tests/ui/traits/const-traits/call-generic-method-dup-bound.stderr index 3f9dce919d05f..029915b7646d8 100644 --- a/tests/ui/traits/const-traits/call-generic-method-dup-bound.stderr +++ b/tests/ui/traits/const-traits/call-generic-method-dup-bound.stderr @@ -44,5 +44,38 @@ LL | const fn equals_self2<T: A + ~const PartialEq>(t: &T) -> bool { | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 5 previous errors; 1 warning emitted +error[E0015]: cannot call non-const operator in constant functions + --> $DIR/call-generic-method-dup-bound.rs:21:5 + | +LL | *t == *t + | ^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +help: consider further restricting this bound + | +LL | const fn equals_self<T: PartialEq + ~const PartialEq + ~const std::cmp::PartialEq>(t: &T) -> bool { + | ++++++++++++++++++++++++++++ + +error[E0015]: cannot call non-const fn `<S as PartialEq>::eq` in constant functions + --> $DIR/call-generic-method-dup-bound.rs:14:15 + | +LL | !self.eq(other) + | ^^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error[E0015]: cannot call non-const operator in constant functions + --> $DIR/call-generic-method-dup-bound.rs:28:5 + | +LL | *t == *t + | ^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +help: consider further restricting this bound + | +LL | const fn equals_self2<T: A + ~const PartialEq + ~const std::cmp::PartialEq>(t: &T) -> bool { + | ++++++++++++++++++++++++++++ + +error: aborting due to 8 previous errors; 1 warning emitted +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/call-generic-method-fail.rs b/tests/ui/traits/const-traits/call-generic-method-fail.rs index 86e0eae61c9ce..6bfbbef6f762e 100644 --- a/tests/ui/traits/const-traits/call-generic-method-fail.rs +++ b/tests/ui/traits/const-traits/call-generic-method-fail.rs @@ -1,12 +1,10 @@ -//@ check-pass //@ compile-flags: -Znext-solver #![allow(incomplete_features)] #![feature(const_trait_impl, effects)] pub const fn equals_self<T: PartialEq>(t: &T) -> bool { *t == *t - // FIXME(effects) ~^ ERROR mismatched types - // FIXME(effects): diagnostic + //~^ ERROR cannot call non-const operator in constant functions } fn main() {} diff --git a/tests/ui/traits/const-traits/call-generic-method-fail.stderr b/tests/ui/traits/const-traits/call-generic-method-fail.stderr new file mode 100644 index 0000000000000..5cd4216dce11e --- /dev/null +++ b/tests/ui/traits/const-traits/call-generic-method-fail.stderr @@ -0,0 +1,15 @@ +error[E0015]: cannot call non-const operator in constant functions + --> $DIR/call-generic-method-fail.rs:6:5 + | +LL | *t == *t + | ^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +help: consider further restricting this bound + | +LL | pub const fn equals_self<T: PartialEq + ~const std::cmp::PartialEq>(t: &T) -> bool { + | ++++++++++++++++++++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/call-generic-method-pass.stderr b/tests/ui/traits/const-traits/call-generic-method-pass.stderr index e35de48ed6062..97ce7fe1c2a8a 100644 --- a/tests/ui/traits/const-traits/call-generic-method-pass.stderr +++ b/tests/ui/traits/const-traits/call-generic-method-pass.stderr @@ -30,5 +30,26 @@ LL | const fn equals_self<T: ~const PartialEq>(t: &T) -> bool { | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 3 previous errors; 1 warning emitted +error[E0015]: cannot call non-const operator in constant functions + --> $DIR/call-generic-method-pass.rs:21:5 + | +LL | *t == *t + | ^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +help: consider further restricting this bound + | +LL | const fn equals_self<T: ~const PartialEq + ~const std::cmp::PartialEq>(t: &T) -> bool { + | ++++++++++++++++++++++++++++ + +error[E0015]: cannot call non-const fn `<S as PartialEq>::eq` in constant functions + --> $DIR/call-generic-method-pass.rs:16:15 + | +LL | !self.eq(other) + | ^^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error: aborting due to 5 previous errors; 1 warning emitted +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/call.rs b/tests/ui/traits/const-traits/call.rs index af2f7caf88c75..f96fb614ac2f9 100644 --- a/tests/ui/traits/const-traits/call.rs +++ b/tests/ui/traits/const-traits/call.rs @@ -1,10 +1,11 @@ -//@ check-pass +// FIXME(effects) check-pass //@ compile-flags: -Znext-solver #![feature(const_closures, const_trait_impl, effects)] #![allow(incomplete_features)] pub const _: () = { assert!((const || true)()); + //~^ ERROR cannot call non-const closure in constants }; fn main() {} diff --git a/tests/ui/traits/const-traits/call.stderr b/tests/ui/traits/const-traits/call.stderr new file mode 100644 index 0000000000000..e9bf64092f3b7 --- /dev/null +++ b/tests/ui/traits/const-traits/call.stderr @@ -0,0 +1,12 @@ +error[E0015]: cannot call non-const closure in constants + --> $DIR/call.rs:7:13 + | +LL | assert!((const || true)()); + | ^^^^^^^^^^^^^^^^^ + | + = note: closures need an RFC before allowed to be called in constants + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/const-closure-trait-method-fail.stderr b/tests/ui/traits/const-traits/const-closure-trait-method-fail.stderr index 4e6707bba51ce..f0f033bceef44 100644 --- a/tests/ui/traits/const-traits/const-closure-trait-method-fail.stderr +++ b/tests/ui/traits/const-traits/const-closure-trait-method-fail.stderr @@ -23,10 +23,6 @@ help: consider further restricting this bound | LL | const fn need_const_closure<T: ~const FnOnce(()) -> i32 + ~const FnOnce(())>(x: T) -> i32 { | +++++++++++++++++++ -help: add `#![feature(effects)]` to the crate attributes to enable - | -LL + #![feature(effects)] - | error: aborting due to 3 previous errors diff --git a/tests/ui/traits/const-traits/const-closure-trait-method.stderr b/tests/ui/traits/const-traits/const-closure-trait-method.stderr index 0f0cd73cc102c..4c5a4d0cdf41b 100644 --- a/tests/ui/traits/const-traits/const-closure-trait-method.stderr +++ b/tests/ui/traits/const-traits/const-closure-trait-method.stderr @@ -23,10 +23,6 @@ help: consider further restricting this bound | LL | const fn need_const_closure<T: ~const FnOnce(()) -> i32 + ~const FnOnce(())>(x: T) -> i32 { | +++++++++++++++++++ -help: add `#![feature(effects)]` to the crate attributes to enable - | -LL + #![feature(effects)] - | error: aborting due to 3 previous errors diff --git a/tests/ui/traits/const-traits/const-closures.stderr b/tests/ui/traits/const-traits/const-closures.stderr index 4d354cb281fea..a81804a50dc21 100644 --- a/tests/ui/traits/const-traits/const-closures.stderr +++ b/tests/ui/traits/const-traits/const-closures.stderr @@ -65,10 +65,6 @@ help: consider further restricting this bound | LL | const fn answer<F: ~const Fn() -> u8 + ~const Fn()>(f: &F) -> u8 { | +++++++++++++ -help: add `#![feature(effects)]` to the crate attributes to enable - | -LL + #![feature(effects)] - | error[E0015]: cannot call non-const closure in constant functions --> $DIR/const-closures.rs:24:11 @@ -81,10 +77,6 @@ help: consider further restricting this bound | LL | const fn answer<F: ~const Fn() -> u8 + ~const Fn()>(f: &F) -> u8 { | +++++++++++++ -help: add `#![feature(effects)]` to the crate attributes to enable - | -LL + #![feature(effects)] - | error[E0015]: cannot call non-const closure in constant functions --> $DIR/const-closures.rs:12:5 @@ -97,10 +89,6 @@ help: consider further restricting this bound | LL | F: ~const FnOnce() -> u8 + ~const Fn(), | +++++++++++++ -help: add `#![feature(effects)]` to the crate attributes to enable - | -LL + #![feature(effects)] - | error: aborting due to 11 previous errors diff --git a/tests/ui/traits/const-traits/const_derives/derive-const-non-const-type.stderr b/tests/ui/traits/const-traits/const_derives/derive-const-non-const-type.stderr index 777b3313da6b2..4bcc17952e620 100644 --- a/tests/ui/traits/const-traits/const_derives/derive-const-non-const-type.stderr +++ b/tests/ui/traits/const-traits/const_derives/derive-const-non-const-type.stderr @@ -22,5 +22,17 @@ LL | #[derive_const(Default)] = note: adding a non-const method body in the future would be a breaking change = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 2 previous errors; 1 warning emitted +error[E0015]: cannot call non-const fn `<A as Default>::default` in constant functions + --> $DIR/derive-const-non-const-type.rs:11:14 + | +LL | #[derive_const(Default)] + | ------- in this derive macro expansion +LL | pub struct S(A); + | ^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 3 previous errors; 1 warning emitted +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/const_derives/derive-const-use.stderr b/tests/ui/traits/const-traits/const_derives/derive-const-use.stderr index ad727fc36cd76..d471a8253ba53 100644 --- a/tests/ui/traits/const-traits/const_derives/derive-const-use.stderr +++ b/tests/ui/traits/const-traits/const_derives/derive-const-use.stderr @@ -62,29 +62,67 @@ LL | #[derive_const(Default, PartialEq)] = note: adding a non-const method body in the future would be a breaking change = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0080]: evaluation of constant value failed +error[E0015]: cannot call non-const fn `<S as Default>::default` in constants + --> $DIR/derive-const-use.rs:18:35 + | +LL | const _: () = assert!(S((), A) == S::default()); + | ^^^^^^^^^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + +error[E0015]: cannot call non-const operator in constants + --> $DIR/derive-const-use.rs:18:23 + | +LL | const _: () = assert!(S((), A) == S::default()); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + +error[E0015]: cannot call non-const fn `<() as Default>::default` in constant functions --> $DIR/derive-const-use.rs:16:14 | LL | #[derive_const(Default, PartialEq)] | ------- in this derive macro expansion LL | pub struct S((), A); - | ^^ calling non-const function `<() as Default>::default` + | ^^ | -note: inside `<S as Default>::default` - --> $DIR/derive-const-use.rs:16:14 + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0015]: cannot call non-const fn `<A as Default>::default` in constant functions + --> $DIR/derive-const-use.rs:16:18 | LL | #[derive_const(Default, PartialEq)] | ------- in this derive macro expansion LL | pub struct S((), A); - | ^^ -note: inside `_` - --> $DIR/derive-const-use.rs:18:35 + | ^ | -LL | const _: () = assert!(S((), A) == S::default()); - | ^^^^^^^^^^^^ + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 8 previous errors; 1 warning emitted +error[E0015]: cannot call non-const operator in constant functions + --> $DIR/derive-const-use.rs:16:14 + | +LL | #[derive_const(Default, PartialEq)] + | --------- in this derive macro expansion +LL | pub struct S((), A); + | ^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0015]: cannot call non-const operator in constant functions + --> $DIR/derive-const-use.rs:16:18 + | +LL | #[derive_const(Default, PartialEq)] + | --------- in this derive macro expansion +LL | pub struct S((), A); + | ^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 13 previous errors; 1 warning emitted -Some errors have detailed explanations: E0080, E0635. -For more information about an error, try `rustc --explain E0080`. +Some errors have detailed explanations: E0015, E0635. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/const_derives/derive-const-with-params.stderr b/tests/ui/traits/const-traits/const_derives/derive-const-with-params.stderr index addce8dcd6c75..33e7e08bb2358 100644 --- a/tests/ui/traits/const-traits/const_derives/derive-const-with-params.stderr +++ b/tests/ui/traits/const-traits/const_derives/derive-const-with-params.stderr @@ -30,5 +30,25 @@ LL | #[derive_const(PartialEq)] | = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 3 previous errors; 1 warning emitted +error[E0015]: cannot call non-const operator in constant functions + --> $DIR/derive-const-with-params.rs:8:23 + | +LL | #[derive_const(PartialEq)] + | --------- in this derive macro expansion +LL | pub struct Reverse<T>(T); + | ^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0015]: cannot call non-const operator in constant functions + --> $DIR/derive-const-with-params.rs:11:5 + | +LL | a == b + | ^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error: aborting due to 5 previous errors; 1 warning emitted +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/effects/const_closure-const_trait_impl-ice-113381.rs b/tests/ui/traits/const-traits/effects/const_closure-const_trait_impl-ice-113381.rs index 3debc22098afc..8f8e9f065845e 100644 --- a/tests/ui/traits/const-traits/effects/const_closure-const_trait_impl-ice-113381.rs +++ b/tests/ui/traits/const-traits/effects/const_closure-const_trait_impl-ice-113381.rs @@ -1,5 +1,3 @@ -//@ check-pass -// FIXME(effects) this shouldn't pass //@ compile-flags: -Znext-solver #![feature(const_closures, const_trait_impl, effects)] #![allow(incomplete_features)] @@ -14,5 +12,6 @@ impl Foo for () { fn main() { (const || { (()).foo() })(); - // FIXME(effects) ~^ ERROR: cannot call non-const fn + //~^ ERROR: cannot call non-const fn `<() as Foo>::foo` in constant functions + // FIXME(effects) this should probably say constant closures } diff --git a/tests/ui/traits/const-traits/effects/const_closure-const_trait_impl-ice-113381.stderr b/tests/ui/traits/const-traits/effects/const_closure-const_trait_impl-ice-113381.stderr new file mode 100644 index 0000000000000..243e94087bbdd --- /dev/null +++ b/tests/ui/traits/const-traits/effects/const_closure-const_trait_impl-ice-113381.stderr @@ -0,0 +1,11 @@ +error[E0015]: cannot call non-const fn `<() as Foo>::foo` in constant functions + --> $DIR/const_closure-const_trait_impl-ice-113381.rs:14:22 + | +LL | (const || { (()).foo() })(); + | ^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/effects/ice-112822-expected-type-for-param.rs b/tests/ui/traits/const-traits/effects/ice-112822-expected-type-for-param.rs index 9a9016de3a0d9..ab530b109e158 100644 --- a/tests/ui/traits/const-traits/effects/ice-112822-expected-type-for-param.rs +++ b/tests/ui/traits/const-traits/effects/ice-112822-expected-type-for-param.rs @@ -10,6 +10,7 @@ const fn test() -> impl ~const Fn() { [first, remainder @ ..] => { assert_eq!(first, &b'f'); //~^ ERROR cannot call non-const fn + //~| ERROR cannot call non-const operator } [] => panic!(), } diff --git a/tests/ui/traits/const-traits/effects/ice-112822-expected-type-for-param.stderr b/tests/ui/traits/const-traits/effects/ice-112822-expected-type-for-param.stderr index 526746eec7346..edfdf8b5f7813 100644 --- a/tests/ui/traits/const-traits/effects/ice-112822-expected-type-for-param.stderr +++ b/tests/ui/traits/const-traits/effects/ice-112822-expected-type-for-param.stderr @@ -36,6 +36,15 @@ LL | const fn test() -> impl ~const Fn() { | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +error[E0015]: cannot call non-const operator in constant functions + --> $DIR/ice-112822-expected-type-for-param.rs:11:17 + | +LL | assert_eq!(first, &b'f'); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + error[E0015]: cannot call non-const fn `core::panicking::assert_failed::<&u8, &u8>` in constant functions --> $DIR/ice-112822-expected-type-for-param.rs:11:17 | @@ -45,7 +54,7 @@ LL | assert_eq!(first, &b'f'); = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 5 previous errors; 1 warning emitted +error: aborting due to 6 previous errors; 1 warning emitted Some errors have detailed explanations: E0015, E0658. For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/generic-bound.stderr b/tests/ui/traits/const-traits/generic-bound.stderr index 2baac1d2a168e..0444c3195773e 100644 --- a/tests/ui/traits/const-traits/generic-bound.stderr +++ b/tests/ui/traits/const-traits/generic-bound.stderr @@ -14,10 +14,6 @@ LL | arg + arg | ^^^^^^^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(effects)]` to the crate attributes to enable - | -LL + #![feature(effects)] - | error: aborting due to 2 previous errors diff --git a/tests/ui/traits/const-traits/hir-const-check.rs b/tests/ui/traits/const-traits/hir-const-check.rs index b3df6495afc97..0ffd60682b0c7 100644 --- a/tests/ui/traits/const-traits/hir-const-check.rs +++ b/tests/ui/traits/const-traits/hir-const-check.rs @@ -12,6 +12,8 @@ pub trait MyTrait { impl const MyTrait for () { fn method(&self) -> Option<()> { Some(())?; //~ ERROR `?` is not allowed in a `const fn` + //~^ ERROR `?` cannot determine the branch of `Option<()>` in constant functions + //~| ERROR `?` cannot convert from residual of `Option<()>` in constant functions None } } diff --git a/tests/ui/traits/const-traits/hir-const-check.stderr b/tests/ui/traits/const-traits/hir-const-check.stderr index 19ea734efb777..a22ac2c973979 100644 --- a/tests/ui/traits/const-traits/hir-const-check.stderr +++ b/tests/ui/traits/const-traits/hir-const-check.stderr @@ -17,6 +17,27 @@ LL | Some(())?; = help: add `#![feature(const_try)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 1 previous error; 1 warning emitted +error[E0015]: `?` cannot determine the branch of `Option<()>` in constant functions + --> $DIR/hir-const-check.rs:14:9 + | +LL | Some(())?; + | ^^^^^^^^^ + | +note: impl defined here, but it is not `const` + --> $SRC_DIR/core/src/option.rs:LL:COL + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error[E0015]: `?` cannot convert from residual of `Option<()>` in constant functions + --> $DIR/hir-const-check.rs:14:9 + | +LL | Some(())?; + | ^^^^^^^^^ + | +note: impl defined here, but it is not `const` + --> $SRC_DIR/core/src/option.rs:LL:COL + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error: aborting due to 3 previous errors; 1 warning emitted -For more information about this error, try `rustc --explain E0658`. +Some errors have detailed explanations: E0015, E0658. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/ice-126148-failed-to-normalize.rs b/tests/ui/traits/const-traits/ice-126148-failed-to-normalize.rs index 717c0e7c08829..da97a0e70ed73 100644 --- a/tests/ui/traits/const-traits/ice-126148-failed-to-normalize.rs +++ b/tests/ui/traits/const-traits/ice-126148-failed-to-normalize.rs @@ -18,6 +18,8 @@ impl const Try for TryMe { const fn t() -> TryMe { TryMe?; + //~^ ERROR `?` cannot determine the branch of `TryMe` in constant functions + //~| ERROR `?` cannot convert from residual of `TryMe` in constant functions TryMe } diff --git a/tests/ui/traits/const-traits/ice-126148-failed-to-normalize.stderr b/tests/ui/traits/const-traits/ice-126148-failed-to-normalize.stderr index e49436c8f0f78..0ca16a1be409f 100644 --- a/tests/ui/traits/const-traits/ice-126148-failed-to-normalize.stderr +++ b/tests/ui/traits/const-traits/ice-126148-failed-to-normalize.stderr @@ -38,6 +38,23 @@ LL | impl const Try for TryMe { = help: implement the missing item: `fn from_output(_: <Self as Try>::Output) -> Self { todo!() }` = help: implement the missing item: `fn branch(self) -> ControlFlow<<Self as Try>::Residual, <Self as Try>::Output> { todo!() }` -error: aborting due to 5 previous errors +error[E0015]: `?` cannot determine the branch of `TryMe` in constant functions + --> $DIR/ice-126148-failed-to-normalize.rs:20:5 + | +LL | TryMe?; + | ^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error[E0015]: `?` cannot convert from residual of `TryMe` in constant functions + --> $DIR/ice-126148-failed-to-normalize.rs:20:5 + | +LL | TryMe?; + | ^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error: aborting due to 7 previous errors -For more information about this error, try `rustc --explain E0046`. +Some errors have detailed explanations: E0015, E0046. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/inline-incorrect-early-bound-in-ctfe.rs b/tests/ui/traits/const-traits/inline-incorrect-early-bound-in-ctfe.rs index e3adcce17b42c..8638c4bbd7f18 100644 --- a/tests/ui/traits/const-traits/inline-incorrect-early-bound-in-ctfe.rs +++ b/tests/ui/traits/const-traits/inline-incorrect-early-bound-in-ctfe.rs @@ -25,6 +25,7 @@ impl Trait for () { const fn foo() { ().foo(); + //~^ ERROR cannot call non-const fn `<() as Trait>::foo` in constant functions } const UWU: () = foo(); diff --git a/tests/ui/traits/const-traits/inline-incorrect-early-bound-in-ctfe.stderr b/tests/ui/traits/const-traits/inline-incorrect-early-bound-in-ctfe.stderr index 2e7801c0b8acd..096b00dd30293 100644 --- a/tests/ui/traits/const-traits/inline-incorrect-early-bound-in-ctfe.stderr +++ b/tests/ui/traits/const-traits/inline-incorrect-early-bound-in-ctfe.stderr @@ -16,6 +16,15 @@ LL | fn foo(self); LL | fn foo<T>(self) { | ^ found 1 type parameter -error: aborting due to 1 previous error; 1 warning emitted +error[E0015]: cannot call non-const fn `<() as Trait>::foo` in constant functions + --> $DIR/inline-incorrect-early-bound-in-ctfe.rs:27:8 + | +LL | ().foo(); + | ^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error: aborting due to 2 previous errors; 1 warning emitted -For more information about this error, try `rustc --explain E0049`. +Some errors have detailed explanations: E0015, E0049. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/issue-102985.stderr b/tests/ui/traits/const-traits/issue-102985.stderr index 8401d1bd4f6c3..7c5c5acf20799 100644 --- a/tests/ui/traits/const-traits/issue-102985.stderr +++ b/tests/ui/traits/const-traits/issue-102985.stderr @@ -6,10 +6,6 @@ LL | n => n(), | = note: closures need an RFC before allowed to be called in constants = note: calls in constants are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(effects)]` to the crate attributes to enable - | -LL + #![feature(effects)] - | error: aborting due to 1 previous error diff --git a/tests/ui/traits/const-traits/issue-88155.stderr b/tests/ui/traits/const-traits/issue-88155.stderr index afe1ea3b1b732..157b54214fa73 100644 --- a/tests/ui/traits/const-traits/issue-88155.stderr +++ b/tests/ui/traits/const-traits/issue-88155.stderr @@ -5,10 +5,6 @@ LL | T::assoc() | ^^^^^^^^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(effects)]` to the crate attributes to enable - | -LL + #![feature(effects)] - | error: aborting due to 1 previous error diff --git a/tests/ui/traits/const-traits/match-non-const-eq.gated.stderr b/tests/ui/traits/const-traits/match-non-const-eq.gated.stderr index c7d211516614a..89e59e5db6ed3 100644 --- a/tests/ui/traits/const-traits/match-non-const-eq.gated.stderr +++ b/tests/ui/traits/const-traits/match-non-const-eq.gated.stderr @@ -6,10 +6,6 @@ LL | "a" => (), //FIXME [gated]~ ERROR can't compare `str` with `str` in | = note: `str` cannot be compared in compile-time, and therefore cannot be used in `match`es = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(effects)]` to the crate attributes to enable - | -LL + #![feature(effects)] - | error: aborting due to 1 previous error diff --git a/tests/ui/traits/const-traits/match-non-const-eq.stock.stderr b/tests/ui/traits/const-traits/match-non-const-eq.stock.stderr index 0f5ecac3891e9..89e59e5db6ed3 100644 --- a/tests/ui/traits/const-traits/match-non-const-eq.stock.stderr +++ b/tests/ui/traits/const-traits/match-non-const-eq.stock.stderr @@ -6,10 +6,6 @@ LL | "a" => (), //FIXME [gated]~ ERROR can't compare `str` with `str` in | = note: `str` cannot be compared in compile-time, and therefore cannot be used in `match`es = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(const_trait_impl)]` to the crate attributes to enable - | -LL + #![feature(const_trait_impl)] - | error: aborting due to 1 previous error diff --git a/tests/ui/traits/const-traits/non-const-op-const-closure-non-const-outer.stderr b/tests/ui/traits/const-traits/non-const-op-const-closure-non-const-outer.stderr index c362a1077e339..97ad83130d444 100644 --- a/tests/ui/traits/const-traits/non-const-op-const-closure-non-const-outer.stderr +++ b/tests/ui/traits/const-traits/non-const-op-const-closure-non-const-outer.stderr @@ -5,10 +5,6 @@ LL | (const || { (()).foo() })(); | ^^^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(effects)]` to the crate attributes to enable - | -LL + #![feature(effects)] - | error: aborting due to 1 previous error diff --git a/tests/ui/traits/const-traits/non-const-op-in-closure-in-const.stderr b/tests/ui/traits/const-traits/non-const-op-in-closure-in-const.stderr index 2803c37646b14..08a40fe65bfae 100644 --- a/tests/ui/traits/const-traits/non-const-op-in-closure-in-const.stderr +++ b/tests/ui/traits/const-traits/non-const-op-in-closure-in-const.stderr @@ -19,10 +19,6 @@ LL | B::from(self) | ^^^^^^^^^^^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(effects)]` to the crate attributes to enable - | -LL + #![feature(effects)] - | error: aborting due to 3 previous errors diff --git a/tests/ui/traits/const-traits/std-impl-gate.gated.stderr b/tests/ui/traits/const-traits/std-impl-gate.gated.stderr index d761fdce4bf0a..f3b171307618d 100644 --- a/tests/ui/traits/const-traits/std-impl-gate.gated.stderr +++ b/tests/ui/traits/const-traits/std-impl-gate.gated.stderr @@ -11,10 +11,6 @@ LL | Default::default() | ^^^^^^^^^^^^^^^^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(effects)]` to the crate attributes to enable - | -LL + #![feature(effects)] - | error: aborting due to 2 previous errors diff --git a/tests/ui/traits/const-traits/std-impl-gate.stock.stderr b/tests/ui/traits/const-traits/std-impl-gate.stock.stderr index b63ea695fc22a..7240b5f4a94c2 100644 --- a/tests/ui/traits/const-traits/std-impl-gate.stock.stderr +++ b/tests/ui/traits/const-traits/std-impl-gate.stock.stderr @@ -5,10 +5,6 @@ LL | Default::default() | ^^^^^^^^^^^^^^^^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(const_trait_impl)]` to the crate attributes to enable - | -LL + #![feature(const_trait_impl)] - | error: aborting due to 1 previous error diff --git a/tests/ui/traits/const-traits/super-traits-fail-2.nn.stderr b/tests/ui/traits/const-traits/super-traits-fail-2.nn.stderr index 48bb1907be2eb..6277966b08e9b 100644 --- a/tests/ui/traits/const-traits/super-traits-fail-2.nn.stderr +++ b/tests/ui/traits/const-traits/super-traits-fail-2.nn.stderr @@ -32,5 +32,14 @@ LL | trait Bar: ~const Foo {} | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 4 previous errors +error[E0015]: cannot call non-const fn `<T as Foo>::a` in constant functions + --> $DIR/super-traits-fail-2.rs:21:7 + | +LL | x.a(); + | ^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error: aborting due to 5 previous errors +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/super-traits-fail-2.ny.stderr b/tests/ui/traits/const-traits/super-traits-fail-2.ny.stderr index a0848fe520e85..60660ecc2797d 100644 --- a/tests/ui/traits/const-traits/super-traits-fail-2.ny.stderr +++ b/tests/ui/traits/const-traits/super-traits-fail-2.ny.stderr @@ -36,5 +36,14 @@ LL | trait Bar: ~const Foo {} | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 5 previous errors +error[E0015]: cannot call non-const fn `<T as Foo>::a` in constant functions + --> $DIR/super-traits-fail-2.rs:21:7 + | +LL | x.a(); + | ^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error: aborting due to 6 previous errors +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/super-traits-fail-2.rs b/tests/ui/traits/const-traits/super-traits-fail-2.rs index 0ea61f4ae2001..1e41d709d6b32 100644 --- a/tests/ui/traits/const-traits/super-traits-fail-2.rs +++ b/tests/ui/traits/const-traits/super-traits-fail-2.rs @@ -20,6 +20,7 @@ trait Bar: ~const Foo {} const fn foo<T: Bar>(x: &T) { x.a(); //[yy,yn]~^ ERROR the trait bound `T: ~const Foo` + //[nn,ny]~^^ ERROR cannot call non-const fn `<T as Foo>::a` in constant functions } fn main() {} diff --git a/tests/ui/traits/const-traits/super-traits-fail-3.nn.stderr b/tests/ui/traits/const-traits/super-traits-fail-3.nn.stderr index 294545014bf5e..b39bf8d8e1588 100644 --- a/tests/ui/traits/const-traits/super-traits-fail-3.nn.stderr +++ b/tests/ui/traits/const-traits/super-traits-fail-3.nn.stderr @@ -46,5 +46,14 @@ LL | const fn foo<T: ~const Bar>(x: &T) { | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 6 previous errors +error[E0015]: cannot call non-const fn `<T as Foo>::a` in constant functions + --> $DIR/super-traits-fail-3.rs:25:7 + | +LL | x.a(); + | ^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error: aborting due to 7 previous errors +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/super-traits-fail-3.ny.stderr b/tests/ui/traits/const-traits/super-traits-fail-3.ny.stderr index 54bb6c5ca4418..187cd998d95a2 100644 --- a/tests/ui/traits/const-traits/super-traits-fail-3.ny.stderr +++ b/tests/ui/traits/const-traits/super-traits-fail-3.ny.stderr @@ -36,5 +36,14 @@ LL | trait Bar: ~const Foo {} | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 5 previous errors +error[E0015]: cannot call non-const fn `<T as Foo>::a` in constant functions + --> $DIR/super-traits-fail-3.rs:25:7 + | +LL | x.a(); + | ^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error: aborting due to 6 previous errors +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/super-traits-fail-3.rs b/tests/ui/traits/const-traits/super-traits-fail-3.rs index a9b08e6edcdc6..414337956e217 100644 --- a/tests/ui/traits/const-traits/super-traits-fail-3.rs +++ b/tests/ui/traits/const-traits/super-traits-fail-3.rs @@ -24,6 +24,7 @@ const fn foo<T: ~const Bar>(x: &T) { //[yn,nn]~| ERROR: `~const` can only be applied to `#[const_trait]` x.a(); //[yn]~^ ERROR: the trait bound `T: ~const Foo` is not satisfied + //[nn,ny]~^^ ERROR: cannot call non-const fn `<T as Foo>::a` in constant functions } fn main() {} diff --git a/tests/ui/traits/const-traits/trait-default-body-stability.stderr b/tests/ui/traits/const-traits/trait-default-body-stability.stderr index 49fbef9aaa29f..5806b6d6fd215 100644 --- a/tests/ui/traits/const-traits/trait-default-body-stability.stderr +++ b/tests/ui/traits/const-traits/trait-default-body-stability.stderr @@ -16,5 +16,22 @@ LL | impl const FromResidual for T { = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` = note: adding a non-const method body in the future would be a breaking change -error: aborting due to 2 previous errors +error[E0015]: `?` cannot determine the branch of `T` in constant functions + --> $DIR/trait-default-body-stability.rs:45:9 + | +LL | T? + | ^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error[E0015]: `?` cannot convert from residual of `T` in constant functions + --> $DIR/trait-default-body-stability.rs:45:9 + | +LL | T? + | ^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error: aborting due to 4 previous errors +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/typeck/typeck_type_placeholder_item.stderr b/tests/ui/typeck/typeck_type_placeholder_item.stderr index 8a765c21624e6..5e32d5c429ef0 100644 --- a/tests/ui/typeck/typeck_type_placeholder_item.stderr +++ b/tests/ui/typeck/typeck_type_placeholder_item.stderr @@ -675,10 +675,6 @@ LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x); | ^^^^^^^^^^^^^^^^^^^^^^ | = note: calls in constants are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(const_trait_impl)]` to the crate attributes to enable - | -LL + #![feature(const_trait_impl)] - | error[E0015]: cannot call non-const fn `<Filter<std::ops::Range<i32>, {closure@$DIR/typeck_type_placeholder_item.rs:230:29: 230:32}> as Iterator>::map::<i32, {closure@$DIR/typeck_type_placeholder_item.rs:230:49: 230:52}>` in constants --> $DIR/typeck_type_placeholder_item.rs:230:45 @@ -687,10 +683,6 @@ LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x); | ^^^^^^^^^^^^^^ | = note: calls in constants are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(const_trait_impl)]` to the crate attributes to enable - | -LL + #![feature(const_trait_impl)] - | error: aborting due to 74 previous errors From becd32c227fb6fd6b5e7f8a2dc51a648919b086a Mon Sep 17 00:00:00 2001 From: Zalathar <Zalathar@users.noreply.github.com> Date: Fri, 25 Oct 2024 23:34:10 +1100 Subject: [PATCH 09/13] Add a wrapper type for raw enum values returned by LLVM --- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 25 +++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 10e55a4f7f659..b295331f8ec38 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -1,6 +1,7 @@ #![allow(non_camel_case_types)] #![allow(non_upper_case_globals)] +use std::fmt::Debug; use std::marker::PhantomData; use libc::{c_char, c_int, c_uint, c_ulonglong, c_void, size_t}; @@ -19,6 +20,30 @@ pub type Bool = c_uint; pub const True: Bool = 1 as Bool; pub const False: Bool = 0 as Bool; +/// Wrapper for a raw enum value returned from LLVM's C APIs. +/// +/// For C enums returned by LLVM, it's risky to use a Rust enum as the return +/// type, because it would be UB if a later version of LLVM adds a new enum +/// value and returns it. Instead, return this raw wrapper, then convert to the +/// Rust-side enum explicitly. +#[repr(transparent)] +pub struct RawEnum<T> { + value: u32, + /// We don't own or consume a `T`, but we can produce one. + _rust_side_type: PhantomData<fn() -> T>, +} + +impl<T: TryFrom<u32>> RawEnum<T> { + #[track_caller] + pub(crate) fn to_rust(self) -> T + where + T::Error: Debug, + { + // If this fails, the Rust-side enum is out of sync with LLVM's enum. + T::try_from(self.value).expect("enum value returned by LLVM should be known") + } +} + #[derive(Copy, Clone, PartialEq)] #[repr(C)] #[allow(dead_code)] // Variants constructed by C++. From 1aed407d248417050d33f7f53ac9426fa682ca66 Mon Sep 17 00:00:00 2001 From: Zalathar <Zalathar@users.noreply.github.com> Date: Fri, 25 Oct 2024 22:06:29 +1100 Subject: [PATCH 10/13] Use LLVM-C APIs for getting/setting linkage --- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 33 +++++--- compiler/rustc_codegen_llvm/src/llvm/mod.rs | 4 +- .../rustc_llvm/llvm-wrapper/RustWrapper.cpp | 80 ------------------- 3 files changed, 24 insertions(+), 93 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index b295331f8ec38..3258a6c43cc62 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -5,6 +5,7 @@ use std::fmt::Debug; use std::marker::PhantomData; use libc::{c_char, c_int, c_uint, c_ulonglong, c_void, size_t}; +use rustc_macros::TryFromU32; use rustc_target::spec::SymbolVisibility; use super::RustString; @@ -133,21 +134,31 @@ pub enum CallConv { AvrInterrupt = 85, } -/// LLVMRustLinkage -#[derive(Copy, Clone, PartialEq)] +/// Must match the layout of `LLVMLinkage`. +#[derive(Copy, Clone, PartialEq, TryFromU32)] #[repr(C)] pub enum Linkage { ExternalLinkage = 0, AvailableExternallyLinkage = 1, LinkOnceAnyLinkage = 2, LinkOnceODRLinkage = 3, - WeakAnyLinkage = 4, - WeakODRLinkage = 5, - AppendingLinkage = 6, - InternalLinkage = 7, - PrivateLinkage = 8, - ExternalWeakLinkage = 9, - CommonLinkage = 10, + #[deprecated = "marked obsolete by LLVM"] + LinkOnceODRAutoHideLinkage = 4, + WeakAnyLinkage = 5, + WeakODRLinkage = 6, + AppendingLinkage = 7, + InternalLinkage = 8, + PrivateLinkage = 9, + #[deprecated = "marked obsolete by LLVM"] + DLLImportLinkage = 10, + #[deprecated = "marked obsolete by LLVM"] + DLLExportLinkage = 11, + ExternalWeakLinkage = 12, + #[deprecated = "marked obsolete by LLVM"] + GhostLinkage = 13, + CommonLinkage = 14, + LinkerPrivateLinkage = 15, + LinkerPrivateWeakLinkage = 16, } // LLVMRustVisibility @@ -970,6 +981,8 @@ unsafe extern "C" { // Operations on global variables, functions, and aliases (globals) pub fn LLVMIsDeclaration(Global: &Value) -> Bool; + pub fn LLVMGetLinkage(Global: &Value) -> RawEnum<Linkage>; + pub fn LLVMSetLinkage(Global: &Value, RustLinkage: Linkage); pub fn LLVMSetSection(Global: &Value, Section: *const c_char); pub fn LLVMGetAlignment(Global: &Value) -> c_uint; pub fn LLVMSetAlignment(Global: &Value, Bytes: c_uint); @@ -1546,8 +1559,6 @@ unsafe extern "C" { ) -> bool; // Operations on global variables, functions, and aliases (globals) - pub fn LLVMRustGetLinkage(Global: &Value) -> Linkage; - pub fn LLVMRustSetLinkage(Global: &Value, RustLinkage: Linkage); pub fn LLVMRustGetVisibility(Global: &Value) -> Visibility; pub fn LLVMRustSetVisibility(Global: &Value, Viz: Visibility); pub fn LLVMRustSetDSOLocal(Global: &Value, is_dso_local: bool); diff --git a/compiler/rustc_codegen_llvm/src/llvm/mod.rs b/compiler/rustc_codegen_llvm/src/llvm/mod.rs index 235b5794b8c54..3eef9e623614b 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/mod.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/mod.rs @@ -233,12 +233,12 @@ pub fn set_global_constant(llglobal: &Value, is_constant: bool) { } pub fn get_linkage(llglobal: &Value) -> Linkage { - unsafe { LLVMRustGetLinkage(llglobal) } + unsafe { LLVMGetLinkage(llglobal) }.to_rust() } pub fn set_linkage(llglobal: &Value, linkage: Linkage) { unsafe { - LLVMRustSetLinkage(llglobal, linkage); + LLVMSetLinkage(llglobal, linkage); } } diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index cb75888abd76d..6c3fa9622f3b8 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -1619,86 +1619,6 @@ extern "C" void LLVMRustPositionBuilderAtStart(LLVMBuilderRef B, unwrap(B)->SetInsertPoint(unwrap(BB), Point); } -enum class LLVMRustLinkage { - ExternalLinkage = 0, - AvailableExternallyLinkage = 1, - LinkOnceAnyLinkage = 2, - LinkOnceODRLinkage = 3, - WeakAnyLinkage = 4, - WeakODRLinkage = 5, - AppendingLinkage = 6, - InternalLinkage = 7, - PrivateLinkage = 8, - ExternalWeakLinkage = 9, - CommonLinkage = 10, -}; - -static LLVMRustLinkage toRust(LLVMLinkage Linkage) { - switch (Linkage) { - case LLVMExternalLinkage: - return LLVMRustLinkage::ExternalLinkage; - case LLVMAvailableExternallyLinkage: - return LLVMRustLinkage::AvailableExternallyLinkage; - case LLVMLinkOnceAnyLinkage: - return LLVMRustLinkage::LinkOnceAnyLinkage; - case LLVMLinkOnceODRLinkage: - return LLVMRustLinkage::LinkOnceODRLinkage; - case LLVMWeakAnyLinkage: - return LLVMRustLinkage::WeakAnyLinkage; - case LLVMWeakODRLinkage: - return LLVMRustLinkage::WeakODRLinkage; - case LLVMAppendingLinkage: - return LLVMRustLinkage::AppendingLinkage; - case LLVMInternalLinkage: - return LLVMRustLinkage::InternalLinkage; - case LLVMPrivateLinkage: - return LLVMRustLinkage::PrivateLinkage; - case LLVMExternalWeakLinkage: - return LLVMRustLinkage::ExternalWeakLinkage; - case LLVMCommonLinkage: - return LLVMRustLinkage::CommonLinkage; - default: - report_fatal_error("Invalid LLVMRustLinkage value!"); - } -} - -static LLVMLinkage fromRust(LLVMRustLinkage Linkage) { - switch (Linkage) { - case LLVMRustLinkage::ExternalLinkage: - return LLVMExternalLinkage; - case LLVMRustLinkage::AvailableExternallyLinkage: - return LLVMAvailableExternallyLinkage; - case LLVMRustLinkage::LinkOnceAnyLinkage: - return LLVMLinkOnceAnyLinkage; - case LLVMRustLinkage::LinkOnceODRLinkage: - return LLVMLinkOnceODRLinkage; - case LLVMRustLinkage::WeakAnyLinkage: - return LLVMWeakAnyLinkage; - case LLVMRustLinkage::WeakODRLinkage: - return LLVMWeakODRLinkage; - case LLVMRustLinkage::AppendingLinkage: - return LLVMAppendingLinkage; - case LLVMRustLinkage::InternalLinkage: - return LLVMInternalLinkage; - case LLVMRustLinkage::PrivateLinkage: - return LLVMPrivateLinkage; - case LLVMRustLinkage::ExternalWeakLinkage: - return LLVMExternalWeakLinkage; - case LLVMRustLinkage::CommonLinkage: - return LLVMCommonLinkage; - } - report_fatal_error("Invalid LLVMRustLinkage value!"); -} - -extern "C" LLVMRustLinkage LLVMRustGetLinkage(LLVMValueRef V) { - return toRust(LLVMGetLinkage(V)); -} - -extern "C" void LLVMRustSetLinkage(LLVMValueRef V, - LLVMRustLinkage RustLinkage) { - LLVMSetLinkage(V, fromRust(RustLinkage)); -} - extern "C" bool LLVMRustConstIntGetZExtValue(LLVMValueRef CV, uint64_t *value) { auto C = unwrap<llvm::ConstantInt>(CV); if (C->getBitWidth() > 64) From 3e51f6fcf8074f1bde43aa414056258fa174c37d Mon Sep 17 00:00:00 2001 From: Zalathar <Zalathar@users.noreply.github.com> Date: Fri, 25 Oct 2024 22:26:15 +1100 Subject: [PATCH 11/13] Use LLVM-C APIs for getting/setting visibility --- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 8 ++-- compiler/rustc_codegen_llvm/src/llvm/mod.rs | 4 +- .../rustc_llvm/llvm-wrapper/RustWrapper.cpp | 39 ------------------- 3 files changed, 6 insertions(+), 45 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 3258a6c43cc62..acc6607683396 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -161,9 +161,9 @@ pub enum Linkage { LinkerPrivateWeakLinkage = 16, } -// LLVMRustVisibility +/// Must match the layout of `LLVMVisibility`. #[repr(C)] -#[derive(Copy, Clone, PartialEq)] +#[derive(Copy, Clone, PartialEq, TryFromU32)] pub enum Visibility { Default = 0, Hidden = 1, @@ -984,6 +984,8 @@ unsafe extern "C" { pub fn LLVMGetLinkage(Global: &Value) -> RawEnum<Linkage>; pub fn LLVMSetLinkage(Global: &Value, RustLinkage: Linkage); pub fn LLVMSetSection(Global: &Value, Section: *const c_char); + pub fn LLVMGetVisibility(Global: &Value) -> RawEnum<Visibility>; + pub fn LLVMSetVisibility(Global: &Value, Viz: Visibility); pub fn LLVMGetAlignment(Global: &Value) -> c_uint; pub fn LLVMSetAlignment(Global: &Value, Bytes: c_uint); pub fn LLVMSetDLLStorageClass(V: &Value, C: DLLStorageClass); @@ -1559,8 +1561,6 @@ unsafe extern "C" { ) -> bool; // Operations on global variables, functions, and aliases (globals) - pub fn LLVMRustGetVisibility(Global: &Value) -> Visibility; - pub fn LLVMRustSetVisibility(Global: &Value, Viz: Visibility); pub fn LLVMRustSetDSOLocal(Global: &Value, is_dso_local: bool); // Operations on global variables diff --git a/compiler/rustc_codegen_llvm/src/llvm/mod.rs b/compiler/rustc_codegen_llvm/src/llvm/mod.rs index 3eef9e623614b..6aac2eea81d0a 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/mod.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/mod.rs @@ -243,12 +243,12 @@ pub fn set_linkage(llglobal: &Value, linkage: Linkage) { } pub fn get_visibility(llglobal: &Value) -> Visibility { - unsafe { LLVMRustGetVisibility(llglobal) } + unsafe { LLVMGetVisibility(llglobal) }.to_rust() } pub fn set_visibility(llglobal: &Value, visibility: Visibility) { unsafe { - LLVMRustSetVisibility(llglobal, visibility); + LLVMSetVisibility(llglobal, visibility); } } diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index 6c3fa9622f3b8..9f941637d8c17 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -1646,45 +1646,6 @@ extern "C" bool LLVMRustConstInt128Get(LLVMValueRef CV, bool sext, return true; } -enum class LLVMRustVisibility { - Default = 0, - Hidden = 1, - Protected = 2, -}; - -static LLVMRustVisibility toRust(LLVMVisibility Vis) { - switch (Vis) { - case LLVMDefaultVisibility: - return LLVMRustVisibility::Default; - case LLVMHiddenVisibility: - return LLVMRustVisibility::Hidden; - case LLVMProtectedVisibility: - return LLVMRustVisibility::Protected; - } - report_fatal_error("Invalid LLVMRustVisibility value!"); -} - -static LLVMVisibility fromRust(LLVMRustVisibility Vis) { - switch (Vis) { - case LLVMRustVisibility::Default: - return LLVMDefaultVisibility; - case LLVMRustVisibility::Hidden: - return LLVMHiddenVisibility; - case LLVMRustVisibility::Protected: - return LLVMProtectedVisibility; - } - report_fatal_error("Invalid LLVMRustVisibility value!"); -} - -extern "C" LLVMRustVisibility LLVMRustGetVisibility(LLVMValueRef V) { - return toRust(LLVMGetVisibility(V)); -} - -extern "C" void LLVMRustSetVisibility(LLVMValueRef V, - LLVMRustVisibility RustVisibility) { - LLVMSetVisibility(V, fromRust(RustVisibility)); -} - extern "C" void LLVMRustSetDSOLocal(LLVMValueRef Global, bool is_dso_local) { unwrap<GlobalValue>(Global)->setDSOLocal(is_dso_local); } From 0d653a5866720570b96260ab69b732d241ec346e Mon Sep 17 00:00:00 2001 From: Zalathar <Zalathar@users.noreply.github.com> Date: Sat, 26 Oct 2024 17:37:04 +1100 Subject: [PATCH 12/13] coverage: Add links to LLVM docs for the coverage mapping format --- compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index 5b39d078e0d7e..8edd788ee36ca 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -349,6 +349,7 @@ fn generate_covmap_record<'ll>( llvm::set_linkage(llglobal, llvm::Linkage::PrivateLinkage); llvm::set_section(llglobal, &covmap_section_name); // LLVM's coverage mapping format specifies 8-byte alignment for items in this section. + // <https://llvm.org/docs/CoverageMappingFormat.html> llvm::set_alignment(llglobal, Align::EIGHT); cx.add_used_global(llglobal); } @@ -400,6 +401,7 @@ fn generate_covfun_record( llvm::set_visibility(llglobal, llvm::Visibility::Hidden); llvm::set_section(llglobal, cx.covfun_section_name()); // LLVM's coverage mapping format specifies 8-byte alignment for items in this section. + // <https://llvm.org/docs/CoverageMappingFormat.html> llvm::set_alignment(llglobal, Align::EIGHT); if cx.target_spec().supports_comdat() { llvm::set_comdat(cx.llmod, llglobal, &func_record_var_name); From 867640e24d9a54b5a4251e2827c83131f4574bb5 Mon Sep 17 00:00:00 2001 From: Ralf Jung <post@ralfj.de> Date: Sat, 26 Oct 2024 09:48:39 +0200 Subject: [PATCH 13/13] x86 target features: make pclmulqdq imply sse2 --- compiler/rustc_target/src/target_features.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index e92366d5c5c3f..910cafbdf3bda 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -316,7 +316,7 @@ const X86_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("lahfsahf", Unstable(sym::lahfsahf_target_feature), &[]), ("lzcnt", Stable, &[]), ("movbe", Stable, &[]), - ("pclmulqdq", Stable, &[]), + ("pclmulqdq", Stable, &["sse2"]), ("popcnt", Stable, &[]), ("prfchw", Unstable(sym::prfchw_target_feature), &[]), ("rdrand", Stable, &[]),