diff --git a/Cargo.lock b/Cargo.lock index 636f07cf41e21..755e1a643cc2d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -291,6 +291,12 @@ version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + [[package]] name = "basic-toml" version = "0.1.10" @@ -1753,6 +1759,12 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hifijson" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "242402749acf71e6f32f5857598b7002c4058a4e3c3b22b4c7d51cab9aea754e" + [[package]] name = "home" version = "0.5.12" @@ -2132,6 +2144,54 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +[[package]] +name = "jaq-core" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7561783b20275a6c9cb576e39208b0c635f34ef14357f1f05a2927a774f3adec" +dependencies = [ + "dyn-clone", + "once_cell", + "typed-arena", +] + +[[package]] +name = "jaq-json" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4ec9aaad7340e6990c6c1878ef3b46dbec624e535d7f786cc9ddcf94f773d33" +dependencies = [ + "bstr", + "bytes", + "foldhash 0.1.5", + "hifijson", + "indexmap", + "jaq-core", + "jaq-std", + "num-bigint", + "num-traits", + "ryu", + "self_cell", + "serde_core", +] + +[[package]] +name = "jaq-std" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bdc5a74b0feeb5e6a1dc2dd08c34280a61e37668d10a6a3b27ad69d0fb9ce2e" +dependencies = [ + "aho-corasick", + "base64 0.22.1", + "bstr", + "jaq-core", + "jiff", + "libm", + "log", + "regex-bites", + "urlencoding", +] + [[package]] name = "jiff" version = "0.2.16" @@ -2139,10 +2199,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49cce2b81f2098e7e3efc35bc2e0a6b7abec9d34128283d7a26fa8f32a6dbb35" dependencies = [ "jiff-static", + "jiff-tzdb-platform", "log", "portable-atomic", "portable-atomic-util", "serde_core", + "windows-sys 0.61.2", ] [[package]] @@ -2156,6 +2218,21 @@ dependencies = [ "syn", ] +[[package]] +name = "jiff-tzdb" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c900ef84826f1338a557697dc8fc601df9ca9af4ac137c7fb61d4c6f2dfd3076" + +[[package]] +name = "jiff-tzdb-platform" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "875a5a69ac2bab1a891711cf5eccbec1ce0341ea805560dcd90b7a2e925132e8" +dependencies = [ + "jiff-tzdb", +] + [[package]] name = "jobserver" version = "0.1.34" @@ -2182,6 +2259,9 @@ version = "0.1.0" dependencies = [ "fs-err", "getopts", + "jaq-core", + "jaq-json", + "jaq-std", "jsonpath-rust", "regex", "serde_json", @@ -3382,6 +3462,12 @@ dependencies = [ "regex-syntax", ] +[[package]] +name = "regex-bites" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6a15a2fa0bfda9361941c45550896ae87b15cc6c8c939ea350079670332e211" + [[package]] name = "regex-lite" version = "0.1.8" @@ -4916,7 +5002,7 @@ version = "0.0.0" dependencies = [ "arrayvec", "askama", - "base64", + "base64 0.21.7", "expect-test", "indexmap", "itertools 0.15.0", @@ -5912,6 +5998,12 @@ dependencies = [ "rustc-hash 2.1.1", ] +[[package]] +name = "typed-arena" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a" + [[package]] name = "typeid" version = "1.0.3" diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index d54b9385f7f6d..4fbc311fcfb1e 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -2916,7 +2916,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // Do not use lower_anon_const_to_const_arg, as that attempts to represent the body // directly. Instead, force an anon const. let def_id = self.local_def_id(anon_const.id); - assert_eq!(DefKind::InlineConst, self.tcx.def_kind(def_id)); + assert_eq!(DefKind::AnonConst, self.tcx.def_kind(def_id)); let lowered_anon = self.lower_anon_const_to_anon_const(anon_const, span); ConstArg { hir_id: self.lower_node_id(node_id), diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 33c45ebfdde4c..6de1588e74f1f 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1709,7 +1709,9 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { if uv.promoted.is_none() { let tcx = self.tcx(); let def_id = uv.def; - if tcx.def_kind(def_id) == DefKind::InlineConst { + if tcx.def_kind(def_id) == DefKind::AnonConst + && tcx.anon_const_kind(def_id) == ty::AnonConstKind::NonTypeSystemInline + { let def_id = def_id.expect_local(); let predicates = self.prove_closure_bounds(tcx, def_id, uv.args, location); self.normalize_and_prove_instantiated_predicates( @@ -2653,7 +2655,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // length as the `typeck_root_args`. &args[..typeck_root_args.len()] } - DefKind::InlineConst => args.as_inline_const().parent_args(), + DefKind::AnonConst + if tcx.anon_const_kind(def_id) == ty::AnonConstKind::NonTypeSystemInline => + { + args.as_inline_const().parent_args() + } other => bug!("unexpected item {:?}", other), }; let parent_args = tcx.mk_args(parent_args); diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index b0adbcd6db4ef..8999ccb42f388 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -615,7 +615,10 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { BodyOwnerKind::Const { .. } | BodyOwnerKind::Static(..) => { match tcx.def_kind(self.mir_def) { - DefKind::InlineConst if !tcx.is_type_system_inline_const(self.mir_def) => { + DefKind::AnonConst + if tcx.anon_const_kind(self.mir_def) + == ty::AnonConstKind::NonTypeSystemInline => + { // This is required for `AscribeUserType` canonical query, which will call // `type_of(inline_const_def_id)`. That `type_of` would inject erased lifetimes // into borrowck, which is ICE #78174. diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index e56bc8ed7e82a..45c9495570ed2 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -26,7 +26,7 @@ use rustc_lint_defs::builtin::LINKER_INFO; use rustc_macros::Diagnostic; use rustc_metadata::fs::{METADATA_FILENAME, copy_to_stdout, emit_wrapper_file}; use rustc_metadata::{ - EncodedMetadata, NativeLibSearchFallback, find_native_static_library, + EncodedMetadata, NativeLibSearchFallback, find_bundled_library, find_native_static_library, walk_native_lib_search_dirs, }; use rustc_middle::bug; @@ -396,8 +396,25 @@ fn link_rlib<'a>( .map(|obj| obj.file_name().unwrap().to_str().unwrap().to_string()) .collect(); + let native_lib_filenames: Vec> = crate_info + .used_libraries + .iter() + .map(|lib| { + find_bundled_library( + lib.name, + Some(lib.verbatim), + lib.kind, + lib.cfg.is_some(), + sess, + &crate_info.crate_types, + ) + }) + .collect(); + let metadata_link_file = if matches!(flavor, RlibFlavor::Normal) { - let metadata_link = rmeta_link::RmetaLink { rust_object_files }; + let native_lib_filenames: Vec> = + native_lib_filenames.iter().map(|f| f.map(|s| s.to_string())).collect(); + let metadata_link = rmeta_link::RmetaLink { rust_object_files, native_lib_filenames }; let metadata_link_data = metadata_link.encode(); let (wrapper, _) = create_wrapper_file(sess, rmeta_link::SECTION.to_string(), &metadata_link_data); @@ -480,12 +497,12 @@ fn link_rlib<'a>( // feature then we'll need to figure out how to record what objects were // loaded from the libraries found here and then encode that into the // metadata of the rlib we're generating somehow. - for lib in crate_info.used_libraries.iter() { + for (i, lib) in crate_info.used_libraries.iter().enumerate() { let NativeLibKind::Static { bundle: None | Some(true), .. } = lib.kind else { continue; }; if flavor == RlibFlavor::Normal - && let Some(filename) = lib.filename + && let Some(filename) = native_lib_filenames[i] { let path = find_native_static_library(filename.as_str(), true, sess); let src = read(path) @@ -599,11 +616,21 @@ fn link_staticlib( let lto = are_upstream_rust_objects_already_included(sess) && !ignored_for_lto(sess, crate_info, cnum); - let native_libs = crate_info.native_libraries[&cnum].iter(); - let relevant = native_libs.clone().filter(|lib| relevant_lib(sess, lib)); - let relevant_libs: FxIndexSet<_> = relevant.filter_map(|lib| lib.filename).collect(); + let native_libs = &crate_info.native_libraries[&cnum]; + let bundled_filenames = + rmeta_link_cache.native_lib_filenames(&sess.target, path, native_libs); + let relevant_libs: FxIndexSet<_> = native_libs + .iter() + .enumerate() + .filter(|(_, lib)| relevant_lib(sess, lib)) + .filter_map(|(i, _)| bundled_filenames.get(i).copied().flatten()) + .collect(); - let bundled_libs: FxIndexSet<_> = native_libs.filter_map(|lib| lib.filename).collect(); + let bundled_libs: FxIndexSet<_> = native_libs + .iter() + .enumerate() + .filter_map(|(i, _)| bundled_filenames.get(i).copied().flatten()) + .collect(); ab.add_archive( path, AddArchiveKind::Rlib(rmeta_link_cache, &|fname: &str, entry_kind| { @@ -2804,6 +2831,7 @@ fn linker_with_args( cmd, sess, archive_builder_builder, + rmeta_link_cache, crate_info, tmpdir, link_output_kind, @@ -2826,6 +2854,7 @@ fn linker_with_args( cmd, sess, archive_builder_builder, + rmeta_link_cache, crate_info, tmpdir, link_output_kind, @@ -3125,6 +3154,7 @@ fn add_native_libs_from_crate( cmd: &mut dyn Linker, sess: &Session, archive_builder_builder: &dyn ArchiveBuilderBuilder, + rmeta_link_cache: &mut RmetaLinkCache, crate_info: &CrateInfo, tmpdir: &Path, bundled_libs: &FxIndexSet, @@ -3148,13 +3178,38 @@ fn add_native_libs_from_crate( .unwrap_or_else(|e| sess.dcx().emit_fatal(e)); } - let native_libs = match cnum { - LOCAL_CRATE => &crate_info.used_libraries, - _ => &crate_info.native_libraries[&cnum], + let (native_libs, bundled_filenames): (&Vec, Vec>) = match cnum { + LOCAL_CRATE => { + let libs = &crate_info.used_libraries; + let filenames = libs + .iter() + .map(|lib| { + find_bundled_library( + lib.name, + Some(lib.verbatim), + lib.kind, + lib.cfg.is_some(), + sess, + &crate_info.crate_types, + ) + }) + .collect(); + (libs, filenames) + } + _ => { + let native_libs = &crate_info.native_libraries[&cnum]; + let filenames = + if let Some(rlib_path) = crate_info.used_crate_source[&cnum].rlib.as_ref() { + rmeta_link_cache.native_lib_filenames(&sess.target, rlib_path, native_libs) + } else { + Vec::new() + }; + (native_libs, filenames) + } }; let mut last = (None, NativeLibKind::Unspecified, false); - for lib in native_libs { + for (i, lib) in native_libs.iter().enumerate() { if !relevant_lib(sess, lib) { continue; } @@ -3174,7 +3229,7 @@ fn add_native_libs_from_crate( let bundle = bundle.unwrap_or(true); let whole_archive = whole_archive == Some(true); if bundle && cnum != LOCAL_CRATE { - if let Some(filename) = lib.filename { + if let Some(filename) = bundled_filenames.get(i).copied().flatten() { // If rlib contains native libs as archives, they are unpacked to tmpdir. let path = tmpdir.join(filename.as_str()); cmd.link_staticlib_by_path(&path, whole_archive); @@ -3226,6 +3281,7 @@ fn add_local_native_libraries( cmd: &mut dyn Linker, sess: &Session, archive_builder_builder: &dyn ArchiveBuilderBuilder, + rmeta_link_cache: &mut RmetaLinkCache, crate_info: &CrateInfo, tmpdir: &Path, link_output_kind: LinkOutputKind, @@ -3237,6 +3293,7 @@ fn add_local_native_libraries( cmd, sess, archive_builder_builder, + rmeta_link_cache, crate_info, tmpdir, &Default::default(), @@ -3296,10 +3353,17 @@ fn add_upstream_rust_crates( match linkage { Linkage::Static | Linkage::IncludedFromDylib | Linkage::NotLinked => { if link_static_crate { - bundled_libs = crate_info.native_libraries[&cnum] - .iter() - .filter_map(|lib| lib.filename) - .collect(); + if let Some(rlib_path) = crate_info.used_crate_source[&cnum].rlib.as_ref() { + bundled_libs = rmeta_link_cache + .native_lib_filenames( + &sess.target, + rlib_path, + &crate_info.native_libraries[&cnum], + ) + .into_iter() + .flatten() + .collect(); + } add_static_crate( cmd, sess, @@ -3333,6 +3397,7 @@ fn add_upstream_rust_crates( cmd, sess, archive_builder_builder, + rmeta_link_cache, crate_info, tmpdir, &bundled_libs, @@ -3348,6 +3413,7 @@ fn add_upstream_native_libraries( cmd: &mut dyn Linker, sess: &Session, archive_builder_builder: &dyn ArchiveBuilderBuilder, + rmeta_link_cache: &mut RmetaLinkCache, crate_info: &CrateInfo, tmpdir: &Path, link_output_kind: LinkOutputKind, @@ -3371,6 +3437,7 @@ fn add_upstream_native_libraries( cmd, sess, archive_builder_builder, + rmeta_link_cache, crate_info, tmpdir, &Default::default(), diff --git a/compiler/rustc_codegen_ssa/src/back/rmeta_link.rs b/compiler/rustc_codegen_ssa/src/back/rmeta_link.rs index 58da783277dfe..69ec3788ac632 100644 --- a/compiler/rustc_codegen_ssa/src/back/rmeta_link.rs +++ b/compiler/rustc_codegen_ssa/src/back/rmeta_link.rs @@ -2,27 +2,38 @@ //! and potentially other data collected and used when building or linking a rlib. //! See . +use std::fs::File; use std::path::{Path, PathBuf}; use object::read::archive::ArchiveFile; use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::memmap::Mmap; +use rustc_hir::attrs::NativeLibKind; use rustc_serialize::opaque::mem_encoder::MemEncoder; use rustc_serialize::opaque::{MAGIC_END_BYTES, MemDecoder}; use rustc_serialize::{Decodable, Encodable}; +use rustc_span::Symbol; +use rustc_target::spec::Target; +use tracing::debug; -use super::metadata::search_for_section; +use super::metadata::{get_metadata_xcoff, search_for_section}; +use crate::NativeLib; pub(crate) const FILENAME: &str = "lib.rmeta-link"; pub(crate) const SECTION: &str = ".rmeta-link"; pub struct RmetaLink { pub rust_object_files: Vec, + /// Positionally aligned with `native_libraries` in regular metadata: index `i` is the + /// bundled filename for native library `i`, or `None` if that library needs no bundling. + pub native_lib_filenames: Vec>, } impl RmetaLink { pub(crate) fn encode(&self) -> Vec { let mut encoder = MemEncoder::new(); self.rust_object_files.encode(&mut encoder); + self.native_lib_filenames.encode(&mut encoder); let mut data = encoder.finish(); data.extend_from_slice(MAGIC_END_BYTES); data @@ -31,7 +42,8 @@ impl RmetaLink { pub(crate) fn decode(data: &[u8]) -> Option { let mut decoder = MemDecoder::new(data, 0).ok()?; let rust_object_files = Vec::::decode(&mut decoder); - Some(RmetaLink { rust_object_files }) + let native_lib_filenames = Vec::>::decode(&mut decoder); + Some(RmetaLink { rust_object_files, native_lib_filenames }) } } @@ -69,4 +81,52 @@ impl RmetaLinkCache { ) -> Option<&RmetaLink> { self.cache.entry(rlib_path.to_path_buf()).or_insert_with(load).as_ref() } + + pub fn native_lib_filenames( + &mut self, + target: &Target, + rlib_path: &Path, + native_libs: &[NativeLib], + ) -> Vec> { + if !crate_may_have_bundled_libs(native_libs) { + return Vec::new(); + } + self.get_or_insert_with(rlib_path, || read_from_path(target, rlib_path)) + .map(|rl| { + rl.native_lib_filenames.iter().map(|f| f.as_deref().map(Symbol::intern)).collect() + }) + .unwrap_or_default() + } +} + +fn crate_may_have_bundled_libs(libs: &[NativeLib]) -> bool { + libs.iter() + .any(|lib| matches!(lib.kind, NativeLibKind::Static { bundle: Some(true) | None, .. })) +} + +// FIXME: this is mostly a copy-paste of `DefaultMetadataLoader::get_rlib_metadata`. +fn read_from_path(target: &Target, path: &Path) -> Option { + let Ok(file) = File::open(path) else { + debug!("failed to open rlib for rmeta-link: {}", path.display()); + return None; + }; + let Ok(mmap) = (unsafe { Mmap::map(file) }) else { + debug!("failed to mmap rlib for rmeta-link: {}", path.display()); + return None; + }; + + if target.is_like_aix { + let archive = ArchiveFile::parse(&*mmap).ok()?; + for entry in archive.members() { + let entry = entry.ok()?; + if entry.name() == FILENAME.as_bytes() { + let member_data = entry.data(&*mmap).ok()?; + let section_data = get_metadata_xcoff(path, member_data).ok()?; + return RmetaLink::decode(section_data); + } + } + return None; + } + + read_from_data(&mmap, path) } diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 3bb8b7de88c02..3608f18345ed0 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -3,11 +3,11 @@ #![feature(file_buffered)] #![feature(negative_impls)] #![feature(option_into_flat_iter)] -#![feature(string_from_utf8_lossy_owned)] #![feature(trait_alias)] #![feature(try_blocks)] #![recursion_limit = "256"] // tidy-alphabetical-end +#![cfg_attr(bootstrap, feature(string_from_utf8_lossy_owned))] //! This crate contains codegen code that is used by all codegen backends (LLVM and others). //! The backend-agnostic functions of this crate use functions defined in various traits that @@ -216,7 +216,6 @@ bitflags::bitflags! { pub struct NativeLib { pub kind: NativeLibKind, pub name: Symbol, - pub filename: Option, pub cfg: Option, pub verbatim: bool, pub dll_imports: Vec, @@ -226,7 +225,6 @@ impl From<&cstore::NativeLib> for NativeLib { fn from(lib: &cstore::NativeLib) -> Self { NativeLib { kind: lib.kind, - filename: lib.filename, name: lib.name, cfg: lib.cfg.clone(), verbatim: lib.verbatim.unwrap_or(false), diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index f417dfba746f1..b002d7554b36e 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -1,5 +1,6 @@ use itertools::Itertools as _; use rustc_abi::{self as abi, BackendRepr, FIRST_VARIANT}; +use rustc_index::IndexVec; use rustc_middle::ty::adjustment::PointerCoercion; use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutOf, TyAndLayout}; use rustc_middle::ty::{self, Instance, Mutability, Ty, TyCtxt}; @@ -15,6 +16,79 @@ use crate::traits::*; use crate::{MemFlags, base}; impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { + fn try_codegen_const_aggregate_as_immediate( + &mut self, + bx: &mut Bx, + dest: PlaceRef<'tcx, Bx::Value>, + kind: &mir::AggregateKind<'tcx>, + operands: &IndexVec>, + ) -> bool { + // Keep this allowlist limited to aggregate kinds with direct codegen coverage. + // Extract the variant index at the same time so we can verify it against + // the layout below. Tuples always use `FIRST_VARIANT` (index 0); the + // `None` in the `Adt` arm excludes unions (which carry an active field). + let variant_index = match kind { + mir::AggregateKind::Tuple => FIRST_VARIANT, + mir::AggregateKind::Adt(_, variant_index, _, _, None) => *variant_index, + _ => return false, + }; + if !matches!(dest.layout.fields, abi::FieldsShape::Arbitrary { .. }) { + return false; + } + // `dest.layout` is the layout of the *overall* type, not a specific + // variant. When the layout is `Variants::Single { index: M }`, the + // field offsets and counts below all refer to variant M. If the MIR + // aggregate is constructing a different variant N (e.g. because N is + // uninhabited and the layout collapsed to M), using `dest.layout` + // directly would read the wrong field metadata. Bail out and let the + // normal codegen path handle it via `project_downcast`. + if !matches!(dest.layout.variants, abi::Variants::Single { index } if index == variant_index) + { + return false; + } + // Now that the variant indices are known to match, the operand count + // and the layout field count must agree. + debug_assert_eq!(operands.len(), dest.layout.fields.count()); + + let size = dest.layout.size.bytes(); + let llty = match size { + 1 => bx.cx().type_i8(), + 2 => bx.cx().type_i16(), + 4 => bx.cx().type_i32(), + 8 => bx.cx().type_i64(), + 16 => bx.cx().type_i128(), + _ => return false, + }; + + let mut value = 0u128; + for (field_idx, operand) in operands.iter_enumerated() { + let field_layout = dest.layout.field(bx.cx(), field_idx.as_usize()); + if field_layout.is_zst() { + continue; + } + let mir::Operand::Constant(constant) = operand else { + return false; + }; + let Some(field_value) = self.eval_mir_constant(constant).try_to_bits(field_layout.size) + else { + return false; + }; + + let field_size = field_layout.size.bytes(); + let field_offset = dest.layout.fields.offset(field_idx.as_usize()).bytes(); + debug_assert!(field_offset + field_size <= size); + let shift = match bx.tcx().data_layout.endian { + abi::Endian::Little => field_offset * 8, + abi::Endian::Big => (size - field_offset - field_size) * 8, + }; + value |= field_value << shift; + } + + let value = bx.cx().const_uint_big(llty, value); + bx.store_to_place(value, dest.val); + true + } + #[instrument(level = "trace", skip(self, bx))] pub(crate) fn codegen_rvalue( &mut self, @@ -179,6 +253,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mir::Rvalue::Aggregate(ref kind, ref operands) if !matches!(**kind, mir::AggregateKind::RawPtr(..)) => { + if self.try_codegen_const_aggregate_as_immediate(bx, dest, kind, operands) { + return; + } + let (variant_index, variant_dest, active_field_index) = match **kind { mir::AggregateKind::Adt(_, variant_index, _, _, active_field_index) => { let variant_dest = dest.project_downcast(bx, variant_index); diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index 3ee11c3f5fbdd..9a8e95c0bea3c 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -64,7 +64,6 @@ fn setup_for_eval<'tcx>( | DefKind::Static { .. } | DefKind::ConstParam | DefKind::AnonConst - | DefKind::InlineConst | DefKind::AssocConst { .. } ), "Unexpected DefKind: {:?}", diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 4aec60c74739f..256af69b55f13 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -530,6 +530,27 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { self.typed_swap_nonoverlapping_intrinsic(&args[0], &args[1])?; } + sym::volatile_load => { + let [ptr] = args else { + span_bug!(self.cur_span(), "invalid `volatile_load` call") + }; + let place = self.deref_pointer(ptr)?; + self.copy_op(&place, dest)?; + } + sym::volatile_store => { + let [ptr, val] = args else { + span_bug!(self.cur_span(), "invalid `volatile_store` call") + }; + let place = self.deref_pointer(ptr)?; + self.copy_op(val, &place)?; + } + sym::volatile_set_memory => { + let [ptr, val_byte, count] = args else { + span_bug!(self.cur_span(), "invalid `volatile_set_memory` call") + }; + self.write_bytes_intrinsic(ptr, val_byte, count, "volatile_set_memory")?; + } + sym::vtable_size => { let ptr = self.read_pointer(&args[0])?; // `None` because we don't know which trait to expect here; any vtable is okay. diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index d0300d63d1213..9d1cf7046f4b0 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -165,7 +165,8 @@ pub enum DefKind { Use, /// An `extern` block. ForeignMod, - /// Anonymous constant, e.g. the `1 + 2` in `[u8; 1 + 2]`. + /// Anonymous constant, e.g. the `1 + 2` in `[u8; 1 + 2]` or `enum E { A = 1 + 2 }`, or an + /// inline constant, e.g. `const { 1 + 2 }`. /// /// Not all anon-consts are actually still relevant in the HIR. We lower /// trivial const-arguments directly to `hir::ConstArgKind::Path`, at which @@ -176,8 +177,6 @@ pub enum DefKind { /// constants should only be reachable by iterating all definitions of a /// given crate, you should not have to worry about this. AnonConst, - /// An inline constant, e.g. `const { 1 + 2 }` - InlineConst, /// Opaque type, aka `impl Trait`. OpaqueTy, /// A field in a struct, enum or union. e.g. @@ -239,7 +238,6 @@ impl DefKind { DefKind::Use => "import", DefKind::ForeignMod => "foreign module", DefKind::AnonConst => "constant expression", - DefKind::InlineConst => "inline constant", DefKind::Field => "field", DefKind::Impl { .. } => "implementation", DefKind::Closure => "closure", @@ -263,7 +261,6 @@ impl DefKind { | DefKind::OpaqueTy | DefKind::Impl { .. } | DefKind::Use - | DefKind::InlineConst | DefKind::ExternCrate => "an", DefKind::Macro(kinds) => kinds.article(), _ => "a", @@ -296,7 +293,6 @@ impl DefKind { // Not namespaced. DefKind::AnonConst - | DefKind::InlineConst | DefKind::Field | DefKind::LifetimeParam | DefKind::ExternCrate @@ -343,7 +339,6 @@ impl DefKind { DefKind::Use => DefPathData::Use, DefKind::ForeignMod => DefPathData::ForeignMod, DefKind::AnonConst => DefPathData::AnonConst, - DefKind::InlineConst => DefPathData::AnonConst, DefKind::OpaqueTy => DefPathData::OpaqueTy, DefKind::GlobalAsm => DefPathData::GlobalAsm, DefKind::Impl { .. } => DefPathData::Impl, @@ -390,7 +385,6 @@ impl DefKind { | DefKind::Fn | DefKind::ForeignTy | DefKind::Impl { .. } - | DefKind::InlineConst | DefKind::OpaqueTy | DefKind::Static { .. } | DefKind::Struct @@ -443,7 +437,6 @@ impl DefKind { | DefKind::ConstParam | DefKind::LifetimeParam | DefKind::AnonConst - | DefKind::InlineConst | DefKind::GlobalAsm | DefKind::ExternCrate => false, } diff --git a/compiler/rustc_hir/src/weak_lang_items.rs b/compiler/rustc_hir/src/weak_lang_items.rs index f9d94bd505724..a2541089a530b 100644 --- a/compiler/rustc_hir/src/weak_lang_items.rs +++ b/compiler/rustc_hir/src/weak_lang_items.rs @@ -25,8 +25,6 @@ macro_rules! weak_lang_items { macro_rules! weak_only_lang_items { ($($item:ident,)*) => { - pub static WEAK_ONLY_LANG_ITEMS: &[LangItem] = &[$(LangItem::$item,)*]; - impl LangItem { pub fn is_weak_only(self) -> bool { matches!(self, $(LangItem::$item)|*) diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index c3dff49be9927..574a2ad6d47f4 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -1171,7 +1171,6 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), // These have no wf checks DefKind::AnonConst - | DefKind::InlineConst | DefKind::ExternCrate | DefKind::Macro(..) | DefKind::Use diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 81c33c0181cdf..c6308a2765084 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -2406,7 +2406,6 @@ fn lint_redundant_lifetimes<'tcx>( | DefKind::Use | DefKind::ForeignMod | DefKind::AnonConst - | DefKind::InlineConst | DefKind::OpaqueTy | DefKind::Field | DefKind::LifetimeParam diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index 4ff870b405e5a..ecc7b170818d2 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -34,44 +34,30 @@ pub(super) fn check_trait<'tcx>( impl_def_id: LocalDefId, impl_header: ty::ImplTraitHeader<'tcx>, ) -> Result<(), ErrorGuaranteed> { - let lang_items = tcx.lang_items(); - let checker = Checker { tcx, trait_def_id, impl_def_id, impl_header }; - checker.check(lang_items.drop_trait(), visit_implementation_of_drop)?; - checker.check(lang_items.async_drop_trait(), visit_implementation_of_drop)?; - checker.check(lang_items.copy_trait(), visit_implementation_of_copy)?; - checker.check(lang_items.unpin_trait(), visit_implementation_of_unpin)?; - checker.check(lang_items.const_param_ty_trait(), |checker| { - visit_implementation_of_const_param_ty(checker) - })?; - checker.check(lang_items.coerce_unsized_trait(), visit_implementation_of_coerce_unsized)?; - checker.check(lang_items.reborrow(), visit_implementation_of_reborrow)?; - checker.check(lang_items.coerce_shared(), visit_implementation_of_coerce_shared)?; - checker - .check(lang_items.dispatch_from_dyn_trait(), visit_implementation_of_dispatch_from_dyn)?; - checker.check( - lang_items.coerce_pointee_validated_trait(), - visit_implementation_of_coerce_pointee_validity, - )?; - Ok(()) + let checker = Checker { tcx, impl_def_id, impl_header }; + match tcx.as_lang_item(trait_def_id) { + Some(LangItem::Drop) => visit_implementation_of_drop(&checker), + Some(LangItem::AsyncDrop) => visit_implementation_of_drop(&checker), + Some(LangItem::Copy) => visit_implementation_of_copy(&checker), + Some(LangItem::Unpin) => visit_implementation_of_unpin(&checker), + Some(LangItem::ConstParamTy) => visit_implementation_of_const_param_ty(&checker), + Some(LangItem::CoerceUnsized) => visit_implementation_of_coerce_unsized(&checker), + Some(LangItem::Reborrow) => visit_implementation_of_reborrow(&checker), + Some(LangItem::CoerceShared) => visit_implementation_of_coerce_shared(&checker), + Some(LangItem::DispatchFromDyn) => visit_implementation_of_dispatch_from_dyn(&checker), + Some(LangItem::CoercePointeeValidated) => { + visit_implementation_of_coerce_pointee_validity(&checker) + } + _ => Ok(()), + } } struct Checker<'tcx> { tcx: TyCtxt<'tcx>, - trait_def_id: DefId, impl_def_id: LocalDefId, impl_header: ty::ImplTraitHeader<'tcx>, } -impl<'tcx> Checker<'tcx> { - fn check( - &self, - trait_def_id: Option, - f: impl FnOnce(&Self) -> Result<(), ErrorGuaranteed>, - ) -> Result<(), ErrorGuaranteed> { - if Some(self.trait_def_id) == trait_def_id { f(self) } else { Ok(()) } - } -} - fn visit_implementation_of_drop(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> { let tcx = checker.tcx; let impl_did = checker.impl_def_id; diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 05648bf7c2ece..376fa8ee621f3 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1635,13 +1635,12 @@ fn const_param_default<'tcx>( } fn anon_const_kind<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> ty::AnonConstKind { - debug_assert_matches!(tcx.def_kind(def), DefKind::AnonConst | DefKind::InlineConst); + debug_assert_matches!(tcx.def_kind(def), DefKind::AnonConst); let hir_id = tcx.local_def_id_to_hir_id(def); - let const_arg_id = tcx.parent_hir_id(hir_id); - match tcx.hir_node(const_arg_id) { + let parent_node_id = tcx.parent_hir_id(hir_id); + match tcx.hir_node(parent_node_id) { hir::Node::ConstArg(const_arg) => { debug_assert_matches!(const_arg.kind, hir::ConstArgKind::Anon(hir::AnonConst { def_id, .. }) if *def_id == def); - let parent_hir_node = tcx.hir_node(tcx.parent_hir_id(const_arg_id)); if tcx.features().generic_const_exprs() { ty::AnonConstKind::GCE } else if tcx.features().min_generic_const_args() { @@ -1649,15 +1648,19 @@ fn anon_const_kind<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> ty::AnonConstKin } else if let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Repeat(_, repeat_count), .. - }) = parent_hir_node - && repeat_count.hir_id == const_arg_id + }) = tcx.parent_hir_node(parent_node_id) + && repeat_count.hir_id == parent_node_id { ty::AnonConstKind::RepeatExprCount } else { ty::AnonConstKind::MCG } } - _ => ty::AnonConstKind::NonTypeSystem, + hir::Node::Expr(hir::Expr { + kind: hir::ExprKind::ConstBlock(..) | hir::ExprKind::InlineAsm(..), + .. + }) => ty::AnonConstKind::NonTypeSystemInline, + _ => ty::AnonConstKind::NonTypeSystemAnon, } } diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index d6a5db4c22f24..cf7f026208ff2 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -162,13 +162,17 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { ty::AnonConstKind::GCE => Some(parent_did), // Field defaults are allowed to use generic parameters, e.g. `field: u32 = /*defid: N + 1*/` - ty::AnonConstKind::NonTypeSystem + ty::AnonConstKind::NonTypeSystemAnon if matches!(tcx.parent_hir_node(hir_id), Node::TyPat(_) | Node::Field(_)) => { Some(parent_did) } // Default to no generic parameters for other kinds of anon consts - ty::AnonConstKind::NonTypeSystem => None, + ty::AnonConstKind::NonTypeSystemAnon => None, + ty::AnonConstKind::NonTypeSystemInline => span_bug!( + tcx.def_span(def_id), + "a DefKind::AnonConst with a HIR parent of hir::Node::AnonConst should never be an AnonConstKind::NonTypeSystemInline" + ), } } Node::ConstBlock(_) diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 3c7cc160a4b3d..abef0d52f8ac9 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -1956,7 +1956,6 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { | DefKind::ForeignTy | DefKind::GlobalAsm | DefKind::Impl { .. } - | DefKind::InlineConst | DefKind::LifetimeParam | DefKind::Macro(_) | DefKind::Mod diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 79197c846071d..941762e5de6af 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -509,22 +509,20 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { /// contains params). Those cases are handled by `check_param_uses_if_mcg`. fn anon_const_forbids_generic_params(&self) -> Option { let tcx = self.tcx(); - let parent_def_id = self.item_def_id(); + let item_def_id = self.item_def_id(); // Inline consts and closures can be nested inside anon consts that forbid generic // params (e.g. an enum discriminant). Walk up the def parent chain to find the // nearest enclosing AnonConst and use that to determine the context. - let parent_def_id = tcx.typeck_root_def_id(parent_def_id.into()); + let anon_const_def_id = tcx.typeck_root_def_id_local(item_def_id); - let anon_const_def_id = match tcx.def_kind(parent_def_id) { - DefKind::AnonConst => parent_def_id, - DefKind::InlineConst if tcx.is_type_system_inline_const(parent_def_id) => parent_def_id, - _ => return None, - }; + if tcx.def_kind(anon_const_def_id) != DefKind::AnonConst { + return None; + } match tcx.anon_const_kind(anon_const_def_id) { ty::AnonConstKind::MCG => Some(ForbidParamContext::ConstArgument), - ty::AnonConstKind::NonTypeSystem => { + ty::AnonConstKind::NonTypeSystemAnon => { // NonTypeSystem anon consts only have accessible generic parameters in specific // positions (ty patterns and field defaults — see `generics_of`). In all other // positions (e.g. enum discriminants) generic parameters are not in scope. @@ -534,7 +532,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { None } } - ty::AnonConstKind::GCE | ty::AnonConstKind::RepeatExprCount => None, + ty::AnonConstKind::NonTypeSystemInline + | ty::AnonConstKind::GCE + | ty::AnonConstKind::RepeatExprCount => None, } } @@ -2975,7 +2975,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { | DefKind::Use | DefKind::ForeignMod | DefKind::AnonConst - | DefKind::InlineConst | DefKind::Field | DefKind::Impl { .. } | DefKind::Closure diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index a6f55eb8dea72..464d17fc22bb1 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -191,7 +191,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) { // `feed_anon_const_type`. // Also skip items for which typeck forwards to parent typeck. if !(def_kind == DefKind::AnonConst - || def_kind == DefKind::InlineConst && tcx.is_type_system_inline_const(item_def_id) + && tcx.anon_const_kind(item_def_id) != ty::AnonConstKind::NonTypeSystemInline || tcx.is_typeck_child(item_def_id.to_def_id())) { tcx.ensure_ok().typeck(item_def_id); diff --git a/compiler/rustc_hir_typeck/src/loops.rs b/compiler/rustc_hir_typeck/src/loops.rs index ebd8842bd753f..21aad64f58d38 100644 --- a/compiler/rustc_hir_typeck/src/loops.rs +++ b/compiler/rustc_hir_typeck/src/loops.rs @@ -84,11 +84,6 @@ pub(crate) fn check<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId, body: &'tcx hir CheckLoopVisitor { tcx, cx_stack: vec![Normal], block_breaks: Default::default() }; let cx = match tcx.def_kind(def_id) { DefKind::AnonConst => AnonConst, - DefKind::InlineConst => { - // only type system inline consts are typeck roots - debug_assert!(tcx.is_type_system_inline_const(def_id)); - ConstBlock - } _ => Fn, }; check.with_context(cx, |v| v.visit_body(body)); diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs index 9ef9422a9e5a0..0a22f468d974e 100644 --- a/compiler/rustc_metadata/src/lib.rs +++ b/compiler/rustc_metadata/src/lib.rs @@ -30,7 +30,7 @@ pub mod locator; pub use fs::{METADATA_FILENAME, emit_wrapper_file}; pub use host_dylib::{DylibError, load_symbol_from_dylib}; pub use native_libs::{ - NativeLibSearchFallback, find_native_static_library, try_find_native_dynamic_library, - try_find_native_static_library, walk_native_lib_search_dirs, + NativeLibSearchFallback, find_bundled_library, find_native_static_library, + try_find_native_dynamic_library, try_find_native_static_library, walk_native_lib_search_dirs, }; pub use rmeta::{EncodedMetadata, METADATA_HEADER, ProcMacroKind, encode_metadata, rendered_const}; diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index b2cfc2f079e89..796538963ec3d 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -168,16 +168,16 @@ pub fn find_native_static_library(name: &str, verbatim: bool, sess: &Session) -> }) } -fn find_bundled_library( +pub fn find_bundled_library( name: Symbol, verbatim: Option, kind: NativeLibKind, has_cfg: bool, - tcx: TyCtxt<'_>, + sess: &Session, + crate_types: &[CrateType], ) -> Option { - let sess = tcx.sess; if let NativeLibKind::Static { bundle: Some(true) | None, whole_archive, .. } = kind - && tcx.crate_types().iter().any(|t| matches!(t, &CrateType::Rlib | CrateType::StaticLib)) + && crate_types.iter().any(|t| matches!(t, &CrateType::Rlib | CrateType::StaticLib)) && (sess.opts.unstable_opts.packed_bundled_libs || has_cfg || whole_archive == Some(true)) { let verbatim = verbatim.unwrap_or(false); @@ -273,16 +273,8 @@ impl<'tcx> Collector<'tcx> { } }; - let filename = find_bundled_library( - attr.name, - attr.verbatim, - attr.kind, - attr.cfg.is_some(), - self.tcx, - ); self.libs.push(NativeLib { name: attr.name, - filename, kind: attr.kind, cfg: attr.cfg.clone(), foreign_module: Some(def_id.to_def_id()), @@ -364,16 +356,8 @@ impl<'tcx> Collector<'tcx> { // Add if not found let new_name: Option<&str> = passed_lib.new_name.as_deref(); let name = Symbol::intern(new_name.unwrap_or(&passed_lib.name)); - let filename = find_bundled_library( - name, - passed_lib.verbatim, - passed_lib.kind, - false, - self.tcx, - ); self.libs.push(NativeLib { name, - filename, kind: passed_lib.kind, cfg: None, foreign_module: None, diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index b2abd34d6d6e9..cd5e343e08d1a 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -916,7 +916,6 @@ fn should_encode_span(def_kind: DefKind) -> bool { | DefKind::ExternCrate | DefKind::Use | DefKind::AnonConst - | DefKind::InlineConst | DefKind::OpaqueTy | DefKind::Field | DefKind::Impl { .. } @@ -962,7 +961,6 @@ fn should_encode_attrs(def_kind: DefKind) -> bool { | DefKind::ExternCrate | DefKind::ForeignMod | DefKind::AnonConst - | DefKind::InlineConst | DefKind::OpaqueTy | DefKind::LifetimeParam | DefKind::Static { nested: true, .. } @@ -996,7 +994,6 @@ fn should_encode_expn_that_defined(def_kind: DefKind) -> bool { | DefKind::Use | DefKind::ForeignMod | DefKind::AnonConst - | DefKind::InlineConst | DefKind::OpaqueTy | DefKind::Field | DefKind::LifetimeParam @@ -1032,7 +1029,6 @@ fn should_encode_visibility(def_kind: DefKind) -> bool { | DefKind::ConstParam | DefKind::LifetimeParam | DefKind::AnonConst - | DefKind::InlineConst | DefKind::Static { nested: true, .. } | DefKind::OpaqueTy | DefKind::GlobalAsm @@ -1071,7 +1067,6 @@ fn should_encode_stability(def_kind: DefKind) -> bool { DefKind::Use | DefKind::LifetimeParam | DefKind::AnonConst - | DefKind::InlineConst | DefKind::GlobalAsm | DefKind::Closure | DefKind::ExternCrate @@ -1108,10 +1103,7 @@ fn should_encode_mir( // instance_mir uses mir_for_ctfe rather than optimized_mir for constructors DefKind::Ctor(_, _) => (true, false), // Constants - DefKind::AnonConst - | DefKind::InlineConst - | DefKind::AssocConst { .. } - | DefKind::Const { .. } => (true, false), + DefKind::AnonConst | DefKind::AssocConst { .. } | DefKind::Const { .. } => (true, false), // Coroutines require optimized MIR to compute layout. DefKind::Closure if tcx.is_coroutine(def_id.to_def_id()) => (false, true), DefKind::SyntheticCoroutineBody => (false, true), @@ -1165,7 +1157,6 @@ fn should_encode_variances<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, def_kind: Def | DefKind::Use | DefKind::LifetimeParam | DefKind::AnonConst - | DefKind::InlineConst | DefKind::GlobalAsm | DefKind::Closure | DefKind::ExternCrate @@ -1191,7 +1182,6 @@ fn should_encode_generics(def_kind: DefKind) -> bool { | DefKind::AssocFn | DefKind::AssocConst { .. } | DefKind::AnonConst - | DefKind::InlineConst | DefKind::OpaqueTy | DefKind::Impl { .. } | DefKind::Field @@ -1228,7 +1218,6 @@ fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) -> | DefKind::Closure | DefKind::ConstParam | DefKind::AnonConst - | DefKind::InlineConst | DefKind::SyntheticCoroutineBody => true, DefKind::OpaqueTy => { @@ -1290,7 +1279,6 @@ fn should_encode_fn_sig(def_kind: DefKind) -> bool { | DefKind::Closure | DefKind::ConstParam | DefKind::AnonConst - | DefKind::InlineConst | DefKind::AssocTy | DefKind::TyParam | DefKind::Trait @@ -1327,7 +1315,6 @@ fn should_encode_constness(def_kind: DefKind) -> bool { | DefKind::Impl { .. } | DefKind::ForeignTy | DefKind::ConstParam - | DefKind::InlineConst | DefKind::AssocTy | DefKind::TyParam | DefKind::Trait @@ -1348,10 +1335,7 @@ fn should_encode_constness(def_kind: DefKind) -> bool { fn should_encode_const(def_kind: DefKind) -> bool { match def_kind { // FIXME(mgca): should we remove Const and AssocConst here? - DefKind::Const { .. } - | DefKind::AssocConst { .. } - | DefKind::AnonConst - | DefKind::InlineConst => true, + DefKind::Const { .. } | DefKind::AssocConst { .. } | DefKind::AnonConst => true, DefKind::Struct | DefKind::Union @@ -1624,7 +1608,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { ty::AssocContainer::TraitImpl(_) => {} } } - if let DefKind::AnonConst | DefKind::InlineConst = def_kind { + if let DefKind::AnonConst = def_kind { record!(self.tables.anon_const_kind[def_id] <- self.tcx.anon_const_kind(def_id)); } if should_encode_const_of_item(self.tcx, def_id, def_kind) { diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs index 119978d469855..6f9ec9dbb0d20 100644 --- a/compiler/rustc_metadata/src/rmeta/table.rs +++ b/compiler/rustc_metadata/src/rmeta/table.rs @@ -175,7 +175,6 @@ fixed_size_enum! { ( Use ) ( ForeignMod ) ( AnonConst ) - ( InlineConst ) ( OpaqueTy ) ( Field ) ( LifetimeParam ) diff --git a/compiler/rustc_middle/src/hir/map.rs b/compiler/rustc_middle/src/hir/map.rs index 6a97327504721..82c0503d5468b 100644 --- a/compiler/rustc_middle/src/hir/map.rs +++ b/compiler/rustc_middle/src/hir/map.rs @@ -322,10 +322,12 @@ impl<'tcx> TyCtxt<'tcx> { pub fn hir_body_owner_kind(self, def_id: impl Into) -> BodyOwnerKind { let def_id = def_id.into(); match self.def_kind(def_id) { - DefKind::Const { .. } | DefKind::AssocConst { .. } | DefKind::AnonConst => { + DefKind::Const { .. } | DefKind::AssocConst { .. } => { BodyOwnerKind::Const { inline: false } } - DefKind::InlineConst => BodyOwnerKind::Const { inline: true }, + DefKind::AnonConst => BodyOwnerKind::Const { + inline: self.anon_const_kind(def_id) == ty::AnonConstKind::NonTypeSystemInline, + }, DefKind::Ctor(..) | DefKind::Fn | DefKind::AssocFn => BodyOwnerKind::Fn, DefKind::Closure | DefKind::SyntheticCoroutineBody => BodyOwnerKind::Closure, DefKind::Static { safety: _, mutability, nested: false } => { @@ -1108,12 +1110,6 @@ impl<'tcx> TyCtxt<'tcx> { } } - pub fn is_type_system_inline_const(self, def_id: impl IntoQueryKey) -> bool { - let def_id = def_id.into_query_key(); - debug_assert_eq!(self.def_kind(def_id), DefKind::InlineConst); - self.anon_const_kind(def_id) != ty::AnonConstKind::NonTypeSystem - } - pub fn hir_maybe_get_struct_pattern_shorthand_field(self, expr: &Expr<'_>) -> Option { let local = match expr { Expr { diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 8e83d44fbb78b..a9a903190900e 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -693,8 +693,8 @@ fn write_mir_sig(tcx: TyCtxt<'_>, body: &Body<'_>, w: &mut dyn io::Write) -> io: write!(w, "static mut ")? } (_, _) if is_function => write!(w, "fn ")?, - // things like anon const, not an item - (DefKind::AnonConst | DefKind::InlineConst, _) => {} + // anon consts are not an item and have no sig + (DefKind::AnonConst, _) => {} // `global_asm!` have fake bodies, which we may dump after mir-build (DefKind::GlobalAsm, _) => {} _ => bug!("Unexpected def kind {:?}", kind), diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 8bbb5e9244c2e..17f0098070c5c 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -601,14 +601,8 @@ impl<'tcx> TyCtxt<'tcx> { /// effect. However, we do not want this as a general capability, so this interface restricts /// to the only allowed case. pub fn feed_anon_const_type(self, key: LocalDefId, value: ty::EarlyBinder<'tcx, Ty<'tcx>>) { - if cfg!(debug_assertions) { - match self.def_kind(key) { - DefKind::AnonConst => (), - DefKind::InlineConst => assert!(self.is_type_system_inline_const(key)), - def_kind => bug!("unexpected DefKind in feed_anon_const_type: {def_kind:?}"), - } - } - + debug_assert_eq!(self.def_kind(key), DefKind::AnonConst); + debug_assert!(self.anon_const_kind(key) != ty::AnonConstKind::NonTypeSystemInline); TyCtxtFeed { tcx: self, key }.type_of(value) } @@ -855,7 +849,6 @@ impl<'tcx> TyCtxt<'tcx> { DefKind::AnonConst | DefKind::AssocConst { .. } | DefKind::Const { .. } - | DefKind::InlineConst | DefKind::GlobalAsm ) { CodegenFnAttrs::EMPTY diff --git a/compiler/rustc_middle/src/ty/context/impl_interner.rs b/compiler/rustc_middle/src/ty/context/impl_interner.rs index ada3298a6ca6e..3b1a64a7e80bb 100644 --- a/compiler/rustc_middle/src/ty/context/impl_interner.rs +++ b/compiler/rustc_middle/src/ty/context/impl_interner.rs @@ -218,7 +218,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> { } } DefKind::Const { .. } => ty::AliasConstKind::Free { def_id }, - DefKind::AnonConst | DefKind::InlineConst | DefKind::Ctor(_, CtorKind::Const) => { + DefKind::AnonConst | DefKind::Ctor(_, CtorKind::Const) => { ty::AliasConstKind::Anon { def_id } } kind => bug!("unexpected DefKind in AliasConst: {kind:?}"), @@ -244,7 +244,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> { DefKind::OpaqueTy => ty::AliasTermKind::OpaqueTy { def_id }, DefKind::TyAlias => ty::AliasTermKind::FreeTy { def_id }, DefKind::Const { .. } => ty::AliasTermKind::FreeConst { def_id }, - DefKind::AnonConst | DefKind::InlineConst | DefKind::Ctor(_, CtorKind::Const) => { + DefKind::AnonConst | DefKind::Ctor(_, CtorKind::Const) => { ty::AliasTermKind::AnonConst { def_id } } kind => bug!("unexpected DefKind in AliasTy: {kind:?}"), diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index c4cccecec6548..c59e71b19be78 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -557,7 +557,6 @@ impl<'tcx> Instance<'tcx> { | DefKind::Const { .. } | DefKind::AssocConst { .. } | DefKind::AnonConst - | DefKind::InlineConst | DefKind::Static { .. } | DefKind::Ctor(_, CtorKind::Fn) | DefKind::Closure diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 01c5b87eda0d5..c482e6bb87345 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1819,8 +1819,7 @@ impl<'tcx> TyCtxt<'tcx> { | DefKind::Static { .. } | DefKind::AssocConst { .. } | DefKind::Ctor(..) - | DefKind::AnonConst - | DefKind::InlineConst => self.mir_for_ctfe(def), + | DefKind::AnonConst => self.mir_for_ctfe(def), DefKind::Fn | DefKind::AssocFn if matches!( self.constness(def), @@ -2260,7 +2259,6 @@ impl<'tcx> TyCtxt<'tcx> { | DefKind::Use | DefKind::ForeignMod | DefKind::AnonConst - | DefKind::InlineConst | DefKind::Field | DefKind::LifetimeParam | DefKind::GlobalAsm diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index ad3b8e009320d..c427ed0552d91 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -681,7 +681,6 @@ impl<'tcx> Ty<'tcx> { | DefKind::Use | DefKind::ForeignMod | DefKind::AnonConst - | DefKind::InlineConst | DefKind::OpaqueTy | DefKind::Field | DefKind::LifetimeParam diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 2c91555e3835f..701508d0b1a69 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -598,7 +598,9 @@ impl<'tcx> TyCtxt<'tcx> { /// type-checking context, i.e. closure, coroutine or inline const. pub fn is_typeck_child(self, def_id: DefId) -> bool { match self.def_kind(def_id) { - DefKind::InlineConst => !self.is_type_system_inline_const(def_id), + DefKind::AnonConst => { + self.anon_const_kind(def_id) == ty::AnonConstKind::NonTypeSystemInline + } DefKind::Closure | DefKind::SyntheticCoroutineBody => true, DefKind::Mod | DefKind::Struct @@ -622,7 +624,6 @@ impl<'tcx> TyCtxt<'tcx> { | DefKind::ExternCrate | DefKind::Use | DefKind::ForeignMod - | DefKind::AnonConst | DefKind::OpaqueTy | DefKind::Field | DefKind::LifetimeParam diff --git a/compiler/rustc_mir_build/src/builder/mod.rs b/compiler/rustc_mir_build/src/builder/mod.rs index 4d63aaf0b1892..5efe62c3ebc21 100644 --- a/compiler/rustc_mir_build/src/builder/mod.rs +++ b/compiler/rustc_mir_build/src/builder/mod.rs @@ -627,7 +627,6 @@ fn construct_error(tcx: TyCtxt<'_>, def_id: LocalDefId, guar: ErrorGuaranteed) - DefKind::Const { .. } | DefKind::AssocConst { .. } | DefKind::AnonConst - | DefKind::InlineConst | DefKind::Static { .. } | DefKind::GlobalAsm => { (vec![], tcx.type_of(def_id).instantiate_identity().skip_norm_wip(), None) diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 2bb14589db36a..1baef208b9880 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -448,7 +448,6 @@ fn mir_promoted( DefKind::AssocConst { .. } | DefKind::Const { .. } | DefKind::Static { .. } - | DefKind::InlineConst | DefKind::AnonConst => tcx.mir_const_qualif(def), _ => ConstQualifs::default(), }; diff --git a/compiler/rustc_mir_transform/src/promote_consts.rs b/compiler/rustc_mir_transform/src/promote_consts.rs index 721245be07629..b88b5bf9a8d6a 100644 --- a/compiler/rustc_mir_transform/src/promote_consts.rs +++ b/compiler/rustc_mir_transform/src/promote_consts.rs @@ -704,7 +704,10 @@ impl<'tcx> Validator<'_, 'tcx> { // const function that uses that constant, again requiring evaluation of the constant. // However, this form of cycle renders both the constant and function unusable in // general, so we don't need to special-case it here. - Const::Unevaluated(uc, _) => self.tcx.def_kind(uc.def) != DefKind::InlineConst, + Const::Unevaluated(uc, _) => { + self.tcx.def_kind(uc.def) != DefKind::AnonConst + || self.tcx.anon_const_kind(uc.def) != ty::AnonConstKind::NonTypeSystemInline + } } } } diff --git a/compiler/rustc_mir_transform/src/trivial_const.rs b/compiler/rustc_mir_transform/src/trivial_const.rs index 4b66c757729d3..e517d29d19320 100644 --- a/compiler/rustc_mir_transform/src/trivial_const.rs +++ b/compiler/rustc_mir_transform/src/trivial_const.rs @@ -6,7 +6,7 @@ use rustc_middle::mir::{ Body, Const, ConstValue, Operand, Place, RETURN_PLACE, Rvalue, START_BLOCK, StatementKind, TerminatorKind, UnevaluatedConst, }; -use rustc_middle::ty::{Ty, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{AnonConstKind, Ty, TyCtxt, TypeVisitableExt}; /// If the given def is a trivial const, returns the value and type the const evaluates to. /// @@ -53,8 +53,8 @@ where B: Deref>, { match tcx.def_kind(def) { - DefKind::AssocConst { .. } | DefKind::Const { .. } | DefKind::AnonConst => (), - DefKind::InlineConst if tcx.is_type_system_inline_const(def) => (), + DefKind::AssocConst { .. } | DefKind::Const { .. } => (), + DefKind::AnonConst if tcx.anon_const_kind(def) != AnonConstKind::NonTypeSystemInline => (), _ => return None, } diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs index db1a8228c43cb..5dd42b8f1154b 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -1095,8 +1095,8 @@ where if let ty::Alias(is_rigid, alias_ty) = ty.kind() && let Some(opaque_ty) = alias_ty.try_to_opaque() { - debug_assert_eq!(is_rigid, ty::IsRigid::No); if opaque_ty == self.opaque_ty { + debug_assert_eq!(is_rigid, ty::IsRigid::No); return self.self_ty; } } diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index e5c1a7ecbdfec..221aca2ec0c95 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -56,7 +56,6 @@ fn should_explore(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { | DefKind::Impl { .. } | DefKind::OpaqueTy | DefKind::AnonConst - | DefKind::InlineConst | DefKind::ExternCrate | DefKind::Use | DefKind::Ctor(..) diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 76af497c1d063..46d6445711175 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -712,7 +712,6 @@ impl<'tcx> EmbargoVisitor<'tcx> { | DefKind::AssocConst { .. } | DefKind::TyParam | DefKind::AnonConst - | DefKind::InlineConst | DefKind::OpaqueTy | DefKind::Closure | DefKind::SyntheticCoroutineBody @@ -814,7 +813,6 @@ impl ReachEverythingInTheInterfaceVisitor<'_, '_> { | DefKind::Macro(_) | DefKind::TyParam | DefKind::AnonConst - | DefKind::InlineConst | DefKind::OpaqueTy | DefKind::SyntheticCoroutineBody | DefKind::ConstParam diff --git a/compiler/rustc_public/src/unstable/mod.rs b/compiler/rustc_public/src/unstable/mod.rs index 8c20a54018553..fee72691117fa 100644 --- a/compiler/rustc_public/src/unstable/mod.rs +++ b/compiler/rustc_public/src/unstable/mod.rs @@ -126,10 +126,7 @@ pub(crate) fn new_item_kind(kind: DefKind) -> ItemKind { DefKind::Closure | DefKind::AssocFn | DefKind::Fn | DefKind::SyntheticCoroutineBody => { ItemKind::Fn } - DefKind::Const { .. } - | DefKind::InlineConst - | DefKind::AssocConst { .. } - | DefKind::AnonConst => ItemKind::Const, + DefKind::Const { .. } | DefKind::AssocConst { .. } | DefKind::AnonConst => ItemKind::Const, DefKind::Static { .. } => ItemKind::Static, DefKind::Ctor(_, rustc_hir::def::CtorKind::Const) => ItemKind::Ctor(CtorKind::Const), DefKind::Ctor(_, rustc_hir::def::CtorKind::Fn) => ItemKind::Ctor(CtorKind::Fn), diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index c35dc02fb1de1..9a2da48ce0298 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -443,7 +443,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { | DefKind::Use | DefKind::ForeignMod | DefKind::AnonConst - | DefKind::InlineConst | DefKind::Field | DefKind::LifetimeParam | DefKind::GlobalAsm diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index 81c6db6a9d6d7..adf936c204f42 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -423,8 +423,6 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { } fn visit_anon_const(&mut self, constant: &'a AnonConst) { - // Note that `visit_anon_const` is skipped for AnonConst nodes wrapped in an - // ExprKind::ConstBlock - these are handled in visit_expr, and are DefKind::InlineConst. let parent = self.create_def(constant.id, None, DefKind::AnonConst, constant.value.span).def_id(); self.with_parent(parent, |this| visit::walk_anon_const(this, constant)); @@ -443,17 +441,6 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { let def = self.create_def(expr.id, None, DefKind::Closure, expr.span).def_id(); self.with_parent(def, |this| visit::walk_expr(this, expr)); } - ExprKind::ConstBlock(constant) => { - for attr in &expr.attrs { - visit::walk_attribute(self, attr); - } - - let def = self - .create_def(constant.id, None, DefKind::InlineConst, constant.value.span) - .def_id(); - // use specifically walk_anon_const, not walk_expr, to skip self.visit_anon_const - self.with_parent(def, |this| visit::walk_anon_const(this, constant)); - } _ => visit::walk_expr(self, expr), } } @@ -606,12 +593,7 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { } InlineAsmOperand::Const { anon_const } => { let def = self - .create_def( - anon_const.id, - None, - DefKind::InlineConst, - anon_const.value.span, - ) + .create_def(anon_const.id, None, DefKind::AnonConst, anon_const.value.span) .def_id(); self.with_parent(def, |this| visit::walk_anon_const(this, anon_const)); } diff --git a/compiler/rustc_session/src/cstore.rs b/compiler/rustc_session/src/cstore.rs index 94237132bd393..c2b517824a058 100644 --- a/compiler/rustc_session/src/cstore.rs +++ b/compiler/rustc_session/src/cstore.rs @@ -68,8 +68,6 @@ pub enum LinkagePreference { pub struct NativeLib { pub kind: NativeLibKind, pub name: Symbol, - /// If packed_bundled_libs enabled, actual filename of library is stored. - pub filename: Option, pub cfg: Option, pub foreign_module: Option, pub verbatim: Option, diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 1d3bd53571f72..003a950095e4d 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -670,8 +670,12 @@ pub fn try_evaluate_const<'tcx>( (args, typing_env) } - Some((_, ty::AnonConstKind::MCG)) - | Some((_, ty::AnonConstKind::NonTypeSystem)) + Some(( + _, + ty::AnonConstKind::MCG + | ty::AnonConstKind::NonTypeSystemAnon + | ty::AnonConstKind::NonTypeSystemInline, + )) | None => { // We are only dealing with "truly" generic/uninferred constants here: // - GCEConsts have been handled separately diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs index 6f7a17c1e4a92..5c7eeb3e2591e 100644 --- a/compiler/rustc_ty_utils/src/consts.rs +++ b/compiler/rustc_ty_utils/src/consts.rs @@ -367,7 +367,7 @@ fn thir_abstract_const<'tcx>( // we want to look into them or treat them as opaque projections. // // Right now we do neither of that and simply always fail to unify them. - DefKind::AnonConst | DefKind::InlineConst => (), + DefKind::AnonConst => (), _ => return Ok(None), } diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs index 174f1c50964a9..30b64cd60e876 100644 --- a/compiler/rustc_ty_utils/src/implied_bounds.rs +++ b/compiler/rustc_ty_utils/src/implied_bounds.rs @@ -130,7 +130,6 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<' DefKind::Static { .. } | DefKind::Const { .. } | DefKind::AnonConst - | DefKind::InlineConst | DefKind::Struct | DefKind::Union | DefKind::Enum diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs index bac5d47e98676..9594252b87db0 100644 --- a/compiler/rustc_ty_utils/src/opaque_types.rs +++ b/compiler/rustc_ty_utils/src/opaque_types.rs @@ -336,10 +336,12 @@ fn opaque_types_defined_by<'tcx>( | DefKind::Static { .. } | DefKind::Const { .. } | DefKind::AssocConst { .. } - | DefKind::AnonConst - | DefKind::InlineConst => { + | DefKind::AnonConst => { // Non-type-system inline consts should be caught by `if tcx.is_typeck_child` above - debug_assert!(kind != DefKind::InlineConst || tcx.is_type_system_inline_const(item)); + debug_assert!( + kind != DefKind::AnonConst + || tcx.anon_const_kind(item) != ty::AnonConstKind::NonTypeSystemInline + ); collector.collect_taits_declared_in_body(); } diff --git a/compiler/rustc_ty_utils/src/sig_types.rs b/compiler/rustc_ty_utils/src/sig_types.rs index f60a03fa71b26..d46a280875f96 100644 --- a/compiler/rustc_ty_utils/src/sig_types.rs +++ b/compiler/rustc_ty_utils/src/sig_types.rs @@ -64,9 +64,16 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( | DefKind::AssocTy | DefKind::Static { .. } | DefKind::Const { .. } - | DefKind::AssocConst { .. } - | DefKind::AnonConst => return visit_alias(), - DefKind::InlineConst if tcx.is_type_system_inline_const(item) => return visit_alias(), + | DefKind::AssocConst { .. } => return visit_alias(), + DefKind::AnonConst + if tcx.anon_const_kind(item) != ty::AnonConstKind::NonTypeSystemInline => + { + return visit_alias(); + } + // These are not part of a public API, they can only appear as hidden types, and there + // the interesting parts are solely in the signature of the containing item's opaque type + // or dyn type. + DefKind::AnonConst | DefKind::Closure | DefKind::SyntheticCoroutineBody => {} DefKind::OpaqueTy => { for (pred, span) in tcx .explicit_item_bounds(item) @@ -93,10 +100,6 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( try_visit!(visitor.visit(span, pred.skip_norm_wip())); } } - // These are not part of a public API, they can only appear as hidden types, and there - // the interesting parts are solely in the signature of the containing item's opaque type - // or dyn type. - DefKind::InlineConst | DefKind::Closure | DefKind::SyntheticCoroutineBody => {} DefKind::Impl { of_trait } => { if of_trait { let span = tcx diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs index 0645839ef0263..29c65974d8b28 100644 --- a/compiler/rustc_type_ir/src/const_kind.rs +++ b/compiler/rustc_type_ir/src/const_kind.rs @@ -266,10 +266,15 @@ pub enum AnonConstKind { /// `feature(generic_const_exprs)` anon consts are allowed to use arbitrary generic parameters in scope GCE, /// stable `min_const_generics` anon consts are not allowed to use any generic parameters + /// + /// under `feature(min_generic_const_args)`, these may be inline consts as well, and should be + /// treated the same as anon consts. MCG, /// anon consts used as the length of a repeat expr are syntactically allowed to use generic parameters /// but must not depend on the actual instantiation. See #76200 for more information RepeatExprCount, /// anon consts outside of the type system, e.g. enum discriminants - NonTypeSystem, + NonTypeSystemAnon, + /// inline consts outside of the type system + NonTypeSystemInline, } diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index eb00db4568b63..499b26b2fc444 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -668,7 +668,6 @@ impl String { /// Basic usage: /// /// ``` - /// #![feature(string_from_utf8_lossy_owned)] /// // some bytes, in a vector /// let sparkle_heart = vec![240, 159, 146, 150]; /// @@ -680,7 +679,6 @@ impl String { /// Incorrect bytes: /// /// ``` - /// #![feature(string_from_utf8_lossy_owned)] /// // some invalid bytes /// let input: Vec = b"Hello \xF0\x90\x80World".into(); /// let output = String::from_utf8_lossy_owned(input); @@ -689,7 +687,7 @@ impl String { /// ``` #[must_use] #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "string_from_utf8_lossy_owned", issue = "129436")] + #[stable(feature = "string_from_utf8_lossy_owned", since = "CURRENT_RUSTC_VERSION")] pub fn from_utf8_lossy_owned(v: Vec) -> String { if let Cow::Owned(string) = String::from_utf8_lossy(&v) { string @@ -2252,7 +2250,6 @@ impl FromUtf8Error { /// # Examples /// /// ``` - /// #![feature(string_from_utf8_lossy_owned)] /// // some invalid bytes /// let input: Vec = b"Hello \xF0\x90\x80World".into(); /// @@ -2269,7 +2266,7 @@ impl FromUtf8Error { /// ``` #[must_use] #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "string_from_utf8_lossy_owned", issue = "129436")] + #[stable(feature = "string_from_utf8_lossy_owned", since = "CURRENT_RUSTC_VERSION")] pub fn into_utf8_lossy(self) -> String { const REPLACEMENT: &str = "\u{FFFD}"; diff --git a/library/alloctests/tests/lib.rs b/library/alloctests/tests/lib.rs index 2ede9730d12dc..e5b3646f14a58 100644 --- a/library/alloctests/tests/lib.rs +++ b/library/alloctests/tests/lib.rs @@ -25,7 +25,6 @@ #![feature(iter_advance_by)] #![feature(iter_next_chunk)] #![feature(slice_partition_dedup)] -#![feature(string_from_utf8_lossy_owned)] #![feature(string_remove_matches)] #![feature(const_btree_len)] #![feature(const_trait_impl)] diff --git a/library/core/src/alloc/global.rs b/library/core/src/alloc/global.rs index e97398aa5dc4a..44a8ab6e54196 100644 --- a/library/core/src/alloc/global.rs +++ b/library/core/src/alloc/global.rs @@ -1,4 +1,7 @@ +use super::{AllocError, GlobalAllocator}; use crate::alloc::Layout; +use crate::hint::assert_unchecked; +use crate::ptr::NonNull; use crate::{cmp, ptr}; /// A memory allocator that can be registered as the standard library’s default @@ -301,3 +304,72 @@ pub unsafe trait GlobalAlloc { new_ptr } } + +/// Allows all [`GlobalAllocator`]s to be used with the legacy [`GlobalAlloc`] interface. +#[stable(feature = "global_alloc", since = "1.28.0")] +unsafe impl GlobalAlloc for A +where + A: GlobalAllocator + ?Sized, +{ + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + // SAFETY: guaranteed by the caller. + // This might lead to the removal of zero-size checks inside the + // `Allocator` implementation. + unsafe { assert_unchecked(layout.size() != 0) }; + match self.allocate(layout) { + Ok(ptr) => ptr.cast().as_ptr(), + Err(AllocError) => ptr::null_mut(), + } + } + + unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { + // SAFETY: guaranteed by the caller. + unsafe { assert_unchecked(layout.size() != 0) }; + // SAFETY: only non-null pointers can be currently allocated. + let ptr = unsafe { NonNull::new_unchecked(ptr) }; + // SAFETY: guaranteed by caller. + unsafe { self.deallocate(ptr, layout) }; + } + + unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { + // SAFETY: guaranteed by the caller. + unsafe { assert_unchecked(layout.size() != 0) }; + match self.allocate_zeroed(layout) { + Ok(ptr) => ptr.cast().as_ptr(), + Err(AllocError) => ptr::null_mut(), + } + } + + unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { + // SAFETY: guaranteed by the caller. + unsafe { assert_unchecked(layout.size() != 0) }; + // SAFETY: guaranteed by the caller. + unsafe { assert_unchecked(new_size != 0) }; + + // SAFETY: only non-null pointers can be currently allocated. + let ptr = unsafe { NonNull::new_unchecked(ptr) }; + let alignment = layout.alignment(); + // SAFETY: the caller must ensure that the `new_size` does not overflow + // when rounded up to the next multiple of `alignment`. + let new_layout = unsafe { Layout::from_size_alignment_unchecked(new_size, alignment) }; + + // SAFETY: + // Two preconditions are guaranteed by the caller: + // * `ptr` is currently allocated with this allocator. + // * `layout` fits the block of memory. + // The size precondition is upheld by selecting between `grow` and `shrink` + // based on the size. + let ptr = unsafe { + if new_size >= layout.size() { + self.grow(ptr, layout, new_layout) + } else { + self.shrink(ptr, layout, new_layout) + } + }; + + match ptr { + Ok(ptr) => ptr.cast().as_ptr(), + Err(AllocError) => ptr::null_mut(), + } + } +} diff --git a/library/core/src/alloc/mod.rs b/library/core/src/alloc/mod.rs index 806f67728efb8..339bc310c0b61 100644 --- a/library/core/src/alloc/mod.rs +++ b/library/core/src/alloc/mod.rs @@ -447,6 +447,96 @@ pub const unsafe trait Allocator { } } +/// An [`Allocator`] that can be registered as the standard library’s default +/// through the `#[global_allocator]` attribute. +/// +/// Types implementing this trait can be used as the default allocator for +/// memory allocations through `Box`, `Vec` and the collection types. For +/// instance, the `System` allocator implements this trait, and thus can be +/// explicitly set as the default like so: +/// ``` +/// use std::alloc::System; +/// +/// #[global_allocator] +/// static ALLOCATOR: System = System; +/// ``` +/// +/// The `Global` allocator forwards all memory allocation requests to the +/// `static` annotated with `#[global_allocator]`. Hence, `Global` does not +/// implement `GlobalAllocator` itself, as that would lead to infinite recursion. +/// +/// # Note to implementors +/// +/// This trait is used to prevent the infinite recursion that would occur if the +/// default allocator were to attempt to allocate memory through `Global` (and +/// thus from itself). +/// +/// When to implement this trait: +/// * for custom global allocators that only use system memory allocation +/// services. +/// * for allocators that wrap another allocator that implements `GlobalAllocator`. +/// +/// When **not** to implement this trait: +/// * for wrappers of arbitrary allocators (which might end up being `Global`, +/// leading to infinite recursion). +/// +/// # Safety +/// +/// In addition to the safety requirements of `Allocator`, global allocators are +/// subject to some additional constraints: +/// +/// * It's undefined behavior if global allocators unwind. This restriction may +/// be lifted in the future, but currently a panic from any of these +/// functions may lead to memory unsafety. +/// +/// * You must not rely on allocations actually happening, even if there are explicit +/// heap allocations in the source. The optimizer may detect unused allocations that it can either +/// eliminate entirely or move to the stack and thus never invoke the allocator. The +/// optimizer may further assume that allocation is infallible, so code that used to fail due +/// to allocator failures may now suddenly work because the optimizer worked around the +/// need for an allocation. More concretely, the following code example is unsound, irrespective +/// of whether your custom allocator allows counting how many allocations have happened. +/// +/// ```rust,ignore (unsound and has placeholders) +/// drop(Box::new(42)); +/// let number_of_heap_allocs = /* call private allocator API */; +/// unsafe { std::hint::assert_unchecked(number_of_heap_allocs > 0); } +/// ``` +/// +/// Note that the optimizations mentioned above are not the only +/// optimization that can be applied. You may generally not rely on heap allocations +/// happening if they can be removed without changing program behavior. +/// Whether allocations happen or not is not part of the program behavior, even if it +/// could be detected via an allocator that tracks allocations by printing or otherwise +/// having side effects. +/// +/// # Re-entrance +/// +/// When implementing a global allocator, one has to be careful not to create an infinitely recursive +/// implementation by accident, as many constructs in the Rust standard library may allocate in +/// their implementation. For example, on some platforms, [`std::sync::Mutex`] may allocate, so using +/// it is highly problematic in a global allocator. +/// +/// For this reason, one should generally stick to library features available through +/// [`core`], and avoid using [`std`] in a global allocator. A few features from [`std`] are +/// guaranteed to not use `#[global_allocator]` to allocate: +/// +/// - [`std::thread_local`], +/// - [`std::thread::current`], +/// - [`std::thread::park`] and [`std::thread::Thread`]'s [`unpark`] method and +/// [`Clone`] implementation. +/// +/// [`std`]: ../../std/index.html +/// [`std::sync::Mutex`]: ../../std/sync/struct.Mutex.html +/// [`std::thread_local`]: ../../std/macro.thread_local.html +/// [`std::thread::current`]: ../../std/thread/fn.current.html +/// [`std::thread::park`]: ../../std/thread/fn.park.html +/// [`std::thread::Thread`]: ../../std/thread/struct.Thread.html +/// [`unpark`]: ../../std/thread/struct.Thread.html#method.unpark +#[unstable(feature = "allocator_api", issue = "32838")] +#[expect(multiple_supertrait_upcastable)] +pub unsafe trait GlobalAllocator: Allocator + Sync + 'static {} + #[unstable(feature = "allocator_api", issue = "32838")] #[rustc_const_unstable(feature = "const_heap", issue = "79597")] const unsafe impl Allocator for &A diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index b812b9eb2afc1..58c68408e6a80 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -990,20 +990,20 @@ pub unsafe fn volatile_copy_memory(dst: *mut T, src: *const T, count: usize); /// [`write_bytes`]: ptr::write_bytes #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn volatile_set_memory(dst: *mut T, val: u8, count: usize); +pub const unsafe fn volatile_set_memory(dst: *mut T, val: u8, count: usize); /// Performs a volatile load from the `src` pointer. /// /// The stabilized version of this intrinsic is [`core::ptr::read_volatile`]. #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn volatile_load(src: *const T) -> T; +pub const unsafe fn volatile_load(src: *const T) -> T; /// Performs a volatile store to the `dst` pointer. /// /// The stabilized version of this intrinsic is [`core::ptr::write_volatile`]. #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn volatile_store(dst: *mut T, val: T); +pub const unsafe fn volatile_store(dst: *mut T, val: T); /// Performs a volatile load from the `src` pointer /// The pointer is not required to be aligned. diff --git a/library/core/src/io/error.rs b/library/core/src/io/error.rs index eac7396bcfd83..61abdb16d07da 100644 --- a/library/core/src/io/error.rs +++ b/library/core/src/io/error.rs @@ -951,6 +951,14 @@ pub enum ErrorKind { #[unstable(feature = "io_error_too_many_open_files", issue = "158319")] TooManyOpenFiles, + /// A low-level input/output error. + /// + /// This usually indicates a hardware or device-level failure, such as a bad + /// disk sector or a removed device, but the operating system may also report + /// it for other low-level I/O conditions. + #[unstable(feature = "io_error_input_output_error", issue = "159066")] + InputOutputError, + // "Unusual" error kinds which do not correspond simply to (sets // of) OS error codes, should be added just above this comment. // `Other` and `Uncategorized` should remain at the end: @@ -1001,6 +1009,7 @@ impl ErrorKind { FilesystemLoop => "filesystem loop or indirection limit (e.g. symlink loop)", HostUnreachable => "host unreachable", InProgress => "in progress", + InputOutputError => "input/output error", Interrupted => "operation interrupted", InvalidData => "invalid data", InvalidFilename => "invalid filename", @@ -1093,6 +1102,7 @@ impl ErrorKind { OutOfMemory, InProgress, TooManyOpenFiles, + InputOutputError, Uncategorized, }) } diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 56f6a561f4bb9..f905bef3bc004 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -1164,9 +1164,10 @@ impl *const T { /// /// [`ptr::read_volatile`]: crate::ptr::read_volatile() #[stable(feature = "pointer_methods", since = "1.26.0")] + #[rustc_const_unstable(feature = "const_volatile", issue = "159094")] #[inline] #[track_caller] - pub unsafe fn read_volatile(self) -> T + pub const unsafe fn read_volatile(self) -> T where T: Sized, { diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 4f3b27ec5c837..f458b3e6b68aa 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -2061,6 +2061,9 @@ pub const unsafe fn write_unaligned(dst: *mut T, src: T) { /// /// Note that volatile memory operations where T is a zero-sized type are noops and may be ignored. /// +/// When invoked during const evaluation, this behaves like a regular read. In particular, such +/// reads must always follow the first of the two cases above. +/// /// [allocation]: crate::ptr#allocated-object /// [atomic]: crate::sync::atomic#memory-model-for-atomic-accesses /// @@ -2116,9 +2119,10 @@ pub const unsafe fn write_unaligned(dst: *mut T, src: T) { /// ``` #[inline] #[stable(feature = "volatile", since = "1.9.0")] +#[rustc_const_unstable(feature = "const_volatile", issue = "159094")] #[track_caller] #[rustc_diagnostic_item = "ptr_read_volatile"] -pub unsafe fn read_volatile(src: *const T) -> T { +pub const unsafe fn read_volatile(src: *const T) -> T { // SAFETY: the caller must uphold the safety contract for `volatile_load`. unsafe { ub_checks::assert_unsafe_precondition!( @@ -2169,6 +2173,9 @@ pub unsafe fn read_volatile(src: *const T) -> T { /// dropped when operating on Rust memory. Additionally, it does not drop `src`. Semantically, `src` /// is moved into the location pointed to by `dst`. /// +/// When invoked during const evaluation, this behaves like a regular write. In particular, such +/// reads must always follow the first of the two cases above. +/// /// [allocation]: crate::ptr#allocated-object /// [atomic]: crate::sync::atomic#memory-model-for-atomic-accesses /// @@ -2218,9 +2225,10 @@ pub unsafe fn read_volatile(src: *const T) -> T { /// ``` #[inline] #[stable(feature = "volatile", since = "1.9.0")] +#[rustc_const_unstable(feature = "const_volatile", issue = "159094")] #[rustc_diagnostic_item = "ptr_write_volatile"] #[track_caller] -pub unsafe fn write_volatile(dst: *mut T, src: T) { +pub const unsafe fn write_volatile(dst: *mut T, src: T) { // SAFETY: the caller must uphold the safety contract for `volatile_store`. unsafe { ub_checks::assert_unsafe_precondition!( diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index b333f8217b2c0..a3383d406e440 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -1256,9 +1256,10 @@ impl *mut T { /// /// [`ptr::read_volatile`]: crate::ptr::read_volatile() #[stable(feature = "pointer_methods", since = "1.26.0")] + #[rustc_const_unstable(feature = "const_volatile", issue = "159094")] #[inline(always)] #[track_caller] - pub unsafe fn read_volatile(self) -> T + pub const unsafe fn read_volatile(self) -> T where T: Sized, { @@ -1430,9 +1431,10 @@ impl *mut T { /// /// [`ptr::write_volatile`]: crate::ptr::write_volatile() #[stable(feature = "pointer_methods", since = "1.26.0")] + #[rustc_const_unstable(feature = "const_volatile", issue = "159094")] #[inline(always)] #[track_caller] - pub unsafe fn write_volatile(self, val: T) + pub const unsafe fn write_volatile(self, val: T) where T: Sized, { diff --git a/library/std/src/alloc.rs b/library/std/src/alloc.rs index 7a576e083df7c..753ca5aba561c 100644 --- a/library/std/src/alloc.rs +++ b/library/std/src/alloc.rs @@ -63,14 +63,15 @@ #![deny(unsafe_op_in_unsafe_fn)] #![stable(feature = "alloc_module", since = "1.28.0")] -use core::ptr::NonNull; -use core::sync::atomic::{AtomicBool, AtomicPtr, Ordering}; -use core::{hint, mem, ptr}; - #[stable(feature = "alloc_module", since = "1.28.0")] #[doc(inline)] pub use alloc_crate::alloc::*; +use crate::ptr::NonNull; +use crate::sync::atomic::{AtomicBool, AtomicPtr, Ordering}; +use crate::sys::alloc as imp; +use crate::{hint, mem, ptr}; + /// The default memory allocator provided by the operating system. /// /// This is based on `malloc` on Unix platforms and `HeapAlloc` on Windows, @@ -145,11 +146,7 @@ impl System { 0 => Ok(layout.dangling_ptr().cast_slice(0)), // SAFETY: `layout` is non-zero in size, size => unsafe { - let raw_ptr = if zeroed { - GlobalAlloc::alloc_zeroed(self, layout) - } else { - GlobalAlloc::alloc(self, layout) - }; + let raw_ptr = if zeroed { imp::alloc_zeroed(layout) } else { imp::alloc(layout) }; let ptr = NonNull::new(raw_ptr).ok_or(AllocError)?; Ok(ptr.cast_slice(size)) }, @@ -182,7 +179,7 @@ impl System { // `realloc` probably checks for `new_size >= old_layout.size()` or something similar. hint::assert_unchecked(new_size >= old_layout.size()); - let raw_ptr = GlobalAlloc::realloc(self, ptr.as_ptr(), old_layout, new_size); + let raw_ptr = imp::realloc(ptr.as_ptr(), old_layout, new_size); let ptr = NonNull::new(raw_ptr).ok_or(AllocError)?; if zeroed { raw_ptr.add(old_size).write_bytes(0, new_size - old_size); @@ -205,8 +202,8 @@ impl System { } } -// The Allocator impl checks the layout size to be non-zero and forwards to the GlobalAlloc impl, -// which is in `std::sys::*::alloc`. +// The Allocator impl checks the layout size to be non-zero and forwards to the +// platform functions in `std::sys::*::alloc`. #[unstable(feature = "allocator_api", issue = "32838")] unsafe impl Allocator for System { #[inline] @@ -224,7 +221,7 @@ unsafe impl Allocator for System { if layout.size() != 0 { // SAFETY: `layout` is non-zero in size, // other conditions must be upheld by the caller - unsafe { GlobalAlloc::dealloc(self, ptr.as_ptr(), layout) } + unsafe { imp::dealloc(ptr.as_ptr(), layout) } } } @@ -274,7 +271,7 @@ unsafe impl Allocator for System { // `realloc` probably checks for `new_size <= old_layout.size()` or something similar. hint::assert_unchecked(new_size <= old_layout.size()); - let raw_ptr = GlobalAlloc::realloc(self, ptr.as_ptr(), old_layout, new_size); + let raw_ptr = imp::realloc(ptr.as_ptr(), old_layout, new_size); let ptr = NonNull::new(raw_ptr).ok_or(AllocError)?; Ok(ptr.cast_slice(new_size)) }, @@ -294,6 +291,9 @@ unsafe impl Allocator for System { } } +#[unstable(feature = "allocator_api", issue = "32838")] +unsafe impl GlobalAllocator for System {} + static HOOK: AtomicPtr<()> = AtomicPtr::new(ptr::null_mut()); /// Registers a custom allocation error hook, replacing any that was previously registered. @@ -435,7 +435,12 @@ pub fn rust_oom(layout: Layout) -> ! { #[allow(unused_attributes)] #[unstable(feature = "alloc_internals", issue = "none")] pub mod __default_lib_allocator { - use super::{GlobalAlloc, Layout, System}; + use super::Layout; + // We call the system functions directly to avoid any overheads introduced + // by the roundtrip through `impl Allocator for System` and + // `impl GlobalAlloc for A`. + use crate::sys::alloc as imp; + // These magic symbol names are used as a fallback for implementing the // `__rust_alloc` etc symbols (see `src/liballoc/alloc.rs`) when there is // no `#[global_allocator]` attribute. @@ -452,7 +457,7 @@ pub mod __default_lib_allocator { // `GlobalAlloc::alloc`. unsafe { let layout = Layout::from_size_align_unchecked(size, align); - System.alloc(layout) + imp::alloc(layout) } } @@ -460,7 +465,7 @@ pub mod __default_lib_allocator { pub unsafe extern "C" fn __rdl_dealloc(ptr: *mut u8, size: usize, align: usize) { // SAFETY: see the guarantees expected by `Layout::from_size_align` and // `GlobalAlloc::dealloc`. - unsafe { System.dealloc(ptr, Layout::from_size_align_unchecked(size, align)) } + unsafe { imp::dealloc(ptr, Layout::from_size_align_unchecked(size, align)) } } #[rustc_std_internal_symbol] @@ -474,7 +479,7 @@ pub mod __default_lib_allocator { // `GlobalAlloc::realloc`. unsafe { let old_layout = Layout::from_size_align_unchecked(old_size, align); - System.realloc(ptr, old_layout, new_size) + imp::realloc(ptr, old_layout, new_size) } } @@ -484,7 +489,7 @@ pub mod __default_lib_allocator { // `GlobalAlloc::alloc_zeroed`. unsafe { let layout = Layout::from_size_align_unchecked(size, align); - System.alloc_zeroed(layout) + imp::alloc_zeroed(layout) } } } diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 7cf576ecd8803..9c5b487d1cbf0 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -356,6 +356,7 @@ #![feature(hint_must_use)] #![feature(int_from_ascii)] #![feature(io_error_inprogress)] +#![feature(io_error_input_output_error)] #![feature(io_error_more)] #![feature(io_error_too_many_open_files)] #![feature(io_error_uncategorized)] diff --git a/library/std/src/sys/alloc/hermit.rs b/library/std/src/sys/alloc/hermit.rs index 77f8200a70a64..9afcb315f4ab5 100644 --- a/library/std/src/sys/alloc/hermit.rs +++ b/library/std/src/sys/alloc/hermit.rs @@ -1,27 +1,24 @@ -use crate::alloc::{GlobalAlloc, Layout, System}; +use crate::alloc::Layout; -#[stable(feature = "alloc_system_type", since = "1.28.0")] -unsafe impl GlobalAlloc for System { - #[inline] - unsafe fn alloc(&self, layout: Layout) -> *mut u8 { - let size = layout.size(); - let align = layout.align(); - unsafe { hermit_abi::malloc(size, align) } - } +#[inline] +pub unsafe fn alloc(layout: Layout) -> *mut u8 { + let size = layout.size(); + let align = layout.align(); + unsafe { hermit_abi::malloc(size, align) } +} - #[inline] - unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { - let size = layout.size(); - let align = layout.align(); - unsafe { - hermit_abi::free(ptr, size, align); - } +#[inline] +pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) { + let size = layout.size(); + let align = layout.align(); + unsafe { + hermit_abi::free(ptr, size, align); } +} - #[inline] - unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { - let size = layout.size(); - let align = layout.align(); - unsafe { hermit_abi::realloc(ptr, size, align, new_size) } - } +#[inline] +pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { + let size = layout.size(); + let align = layout.align(); + unsafe { hermit_abi::realloc(ptr, size, align, new_size) } } diff --git a/library/std/src/sys/alloc/mod.rs b/library/std/src/sys/alloc/mod.rs index f2f1d1c7feceb..73d35781f09bf 100644 --- a/library/std/src/sys/alloc/mod.rs +++ b/library/std/src/sys/alloc/mod.rs @@ -1,6 +1,6 @@ #![forbid(unsafe_op_in_unsafe_fn)] -use crate::alloc::{GlobalAlloc, Layout, System}; +use crate::alloc::Layout; use crate::ptr; // The minimum alignment guaranteed by the architecture. This value is used to @@ -47,21 +47,16 @@ const MIN_ALIGN: usize = if cfg!(any( }; #[allow(dead_code)] -unsafe fn realloc_fallback( - alloc: &System, - ptr: *mut u8, - old_layout: Layout, - new_size: usize, -) -> *mut u8 { +unsafe fn realloc_fallback(ptr: *mut u8, old_layout: Layout, new_size: usize) -> *mut u8 { // SAFETY: Docs for GlobalAlloc::realloc require this to be valid unsafe { let new_layout = Layout::from_size_align_unchecked(new_size, old_layout.align()); - let new_ptr = GlobalAlloc::alloc(alloc, new_layout); + let new_ptr = alloc(new_layout); if !new_ptr.is_null() { let size = usize::min(old_layout.size(), new_size); ptr::copy_nonoverlapping(ptr, new_ptr, size); - GlobalAlloc::dealloc(alloc, ptr, old_layout); + dealloc(ptr, old_layout); } new_ptr @@ -76,35 +71,69 @@ cfg_select! { target_os = "trusty", ) => { mod unix; + use unix as imp; } target_os = "windows" => { mod windows; + use windows as imp; } target_os = "hermit" => { mod hermit; + use hermit as imp; } target_os = "motor" => { mod motor; + use motor as imp; } all(target_vendor = "fortanix", target_env = "sgx") => { mod sgx; + use sgx as imp; } target_os = "solid_asp3" => { mod solid; + use solid as imp; } target_os = "uefi" => { mod uefi; + use uefi as imp; } target_os = "vexos" => { mod vexos; + use vexos as imp; } target_family = "wasm" => { mod wasm; + use wasm as imp; } target_os = "xous" => { mod xous; + use xous as imp; } target_os = "zkvm" => { mod zkvm; + use zkvm as imp; + } +} + +pub use imp::{alloc, dealloc, realloc}; + +cfg_select! { + any( + target_os = "hermit", + target_os = "solid_asp3", + target_os = "uefi", + target_os = "zkvm", + ) => { + #[inline] + pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 { + let ptr = unsafe { alloc(layout) }; + if !ptr.is_null() { + unsafe { ptr.write_bytes(0, layout.size()) }; + } + ptr + } + } + _ => { + pub use imp::alloc_zeroed; } } diff --git a/library/std/src/sys/alloc/motor.rs b/library/std/src/sys/alloc/motor.rs index 271e3c40c26ae..090dc198bb500 100644 --- a/library/std/src/sys/alloc/motor.rs +++ b/library/std/src/sys/alloc/motor.rs @@ -1,28 +1,13 @@ -use crate::alloc::{GlobalAlloc, Layout, System}; +use crate::alloc::Layout; -#[stable(feature = "alloc_system_type", since = "1.28.0")] -unsafe impl GlobalAlloc for System { - #[inline] - unsafe fn alloc(&self, layout: Layout) -> *mut u8 { - // SAFETY: same requirements as in GlobalAlloc::alloc. - moto_rt::alloc::alloc(layout) - } - - #[inline] - unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { - // SAFETY: same requirements as in GlobalAlloc::alloc_zeroed. - moto_rt::alloc::alloc_zeroed(layout) - } - - #[inline] - unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { - // SAFETY: same requirements as in GlobalAlloc::dealloc. - unsafe { moto_rt::alloc::dealloc(ptr, layout) } - } +#[inline] +pub unsafe fn alloc(layout: Layout) -> *mut u8 { + moto_rt::alloc::alloc(layout) +} - #[inline] - unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { - // SAFETY: same requirements as in GlobalAlloc::realloc. - unsafe { moto_rt::alloc::realloc(ptr, layout, new_size) } - } +#[inline] +pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 { + moto_rt::alloc::alloc_zeroed(layout) } + +pub use moto_rt::alloc::{dealloc, realloc}; diff --git a/library/std/src/sys/alloc/sgx.rs b/library/std/src/sys/alloc/sgx.rs index afdef7a5cb647..c20761259048e 100644 --- a/library/std/src/sys/alloc/sgx.rs +++ b/library/std/src/sys/alloc/sgx.rs @@ -1,4 +1,4 @@ -use crate::alloc::{GlobalAlloc, Layout, System}; +use crate::alloc::Layout; use crate::ptr; use crate::sync::atomic::{Atomic, AtomicBool, Ordering}; use crate::sys::pal::abi::mem as sgx_mem; @@ -57,31 +57,28 @@ unsafe impl dlmalloc::Allocator for Sgx { } } -#[stable(feature = "alloc_system_type", since = "1.28.0")] -unsafe impl GlobalAlloc for System { - #[inline] - unsafe fn alloc(&self, layout: Layout) -> *mut u8 { - // SAFETY: the caller must uphold the safety contract for `malloc` - unsafe { DLMALLOC.lock().malloc(layout.size(), layout.align()) } - } +#[inline] +pub unsafe fn alloc(layout: Layout) -> *mut u8 { + // SAFETY: the caller must uphold the safety contract for `malloc` + unsafe { DLMALLOC.lock().malloc(layout.size(), layout.align()) } +} - #[inline] - unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { - // SAFETY: the caller must uphold the safety contract for `malloc` - unsafe { DLMALLOC.lock().calloc(layout.size(), layout.align()) } - } +#[inline] +pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 { + // SAFETY: the caller must uphold the safety contract for `malloc` + unsafe { DLMALLOC.lock().calloc(layout.size(), layout.align()) } +} - #[inline] - unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { - // SAFETY: the caller must uphold the safety contract for `malloc` - unsafe { DLMALLOC.lock().free(ptr, layout.size(), layout.align()) } - } +#[inline] +pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) { + // SAFETY: the caller must uphold the safety contract for `malloc` + unsafe { DLMALLOC.lock().free(ptr, layout.size(), layout.align()) } +} - #[inline] - unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { - // SAFETY: the caller must uphold the safety contract for `malloc` - unsafe { DLMALLOC.lock().realloc(ptr, layout.size(), layout.align(), new_size) } - } +#[inline] +pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { + // SAFETY: the caller must uphold the safety contract for `malloc` + unsafe { DLMALLOC.lock().realloc(ptr, layout.size(), layout.align(), new_size) } } // The following functions are needed by libunwind. These symbols are named diff --git a/library/std/src/sys/alloc/solid.rs b/library/std/src/sys/alloc/solid.rs index 47cfa2eb1162b..5d3f396f0dd11 100644 --- a/library/std/src/sys/alloc/solid.rs +++ b/library/std/src/sys/alloc/solid.rs @@ -1,30 +1,27 @@ use super::{MIN_ALIGN, realloc_fallback}; -use crate::alloc::{GlobalAlloc, Layout, System}; +use crate::alloc::Layout; -#[stable(feature = "alloc_system_type", since = "1.28.0")] -unsafe impl GlobalAlloc for System { - #[inline] - unsafe fn alloc(&self, layout: Layout) -> *mut u8 { - if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() { - unsafe { libc::malloc(layout.size()) as *mut u8 } - } else { - unsafe { libc::memalign(layout.align(), layout.size()) as *mut u8 } - } +#[inline] +pub unsafe fn alloc(layout: Layout) -> *mut u8 { + if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() { + unsafe { libc::malloc(layout.size()) as *mut u8 } + } else { + unsafe { libc::memalign(layout.align(), layout.size()) as *mut u8 } } +} - #[inline] - unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) { - unsafe { libc::free(ptr as *mut libc::c_void) } - } +#[inline] +pub unsafe fn dealloc(ptr: *mut u8, _layout: Layout) { + unsafe { libc::free(ptr as *mut libc::c_void) } +} - #[inline] - unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { - unsafe { - if layout.align() <= MIN_ALIGN && layout.align() <= new_size { - libc::realloc(ptr as *mut libc::c_void, new_size) as *mut u8 - } else { - realloc_fallback(self, ptr, layout, new_size) - } +#[inline] +pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { + unsafe { + if layout.align() <= MIN_ALIGN && layout.align() <= new_size { + libc::realloc(ptr as *mut libc::c_void, new_size) as *mut u8 + } else { + realloc_fallback(ptr, layout, new_size) } } } diff --git a/library/std/src/sys/alloc/uefi.rs b/library/std/src/sys/alloc/uefi.rs index 5221876e90866..aa7fcc9fe110c 100644 --- a/library/std/src/sys/alloc/uefi.rs +++ b/library/std/src/sys/alloc/uefi.rs @@ -3,47 +3,48 @@ use r_efi::protocols::loaded_image; -use crate::alloc::{GlobalAlloc, Layout, System}; +use crate::alloc::Layout; use crate::sync::OnceLock; use crate::sys::pal::helpers; -#[stable(feature = "alloc_system_type", since = "1.28.0")] -unsafe impl GlobalAlloc for System { - unsafe fn alloc(&self, layout: Layout) -> *mut u8 { - static EFI_MEMORY_TYPE: OnceLock = OnceLock::new(); - - // Return null pointer if boot services are not available - if crate::os::uefi::env::boot_services().is_none() { - return crate::ptr::null_mut(); - } - - // If boot services is valid then SystemTable is not null. - let system_table = crate::os::uefi::env::system_table().as_ptr().cast(); - - // Each loaded image has an image handle that supports `EFI_LOADED_IMAGE_PROTOCOL`. Thus, this - // will never fail. - let mem_type = EFI_MEMORY_TYPE.get_or_init(|| { - let protocol = helpers::image_handle_protocol::( - loaded_image::PROTOCOL_GUID, - ) - .unwrap(); - // Gives allocations the memory type that the data sections were loaded as. - unsafe { (*protocol.as_ptr()).image_data_type } - }); - - // The caller must ensure non-0 layout - unsafe { r_efi_alloc::raw::alloc(system_table, layout, *mem_type) } +pub unsafe fn alloc(layout: Layout) -> *mut u8 { + static EFI_MEMORY_TYPE: OnceLock = OnceLock::new(); + + // Return null pointer if boot services are not available + if crate::os::uefi::env::boot_services().is_none() { + return crate::ptr::null_mut(); } - unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { - // Do nothing if boot services are not available - if crate::os::uefi::env::boot_services().is_none() { - return; - } + // If boot services is valid then SystemTable is not null. + let system_table = crate::os::uefi::env::system_table().as_ptr().cast(); + + // Each loaded image has an image handle that supports `EFI_LOADED_IMAGE_PROTOCOL`. Thus, this + // will never fail. + let mem_type = EFI_MEMORY_TYPE.get_or_init(|| { + let protocol = + helpers::image_handle_protocol::(loaded_image::PROTOCOL_GUID) + .unwrap(); + // Gives allocations the memory type that the data sections were loaded as. + unsafe { (*protocol.as_ptr()).image_data_type } + }); + + // The caller must ensure non-0 layout + unsafe { r_efi_alloc::raw::alloc(system_table, layout, *mem_type) } +} - // If boot services is valid then SystemTable is not null. - let system_table = crate::os::uefi::env::system_table().as_ptr().cast(); - // The caller must ensure non-0 layout - unsafe { r_efi_alloc::raw::dealloc(system_table, ptr, layout) } +pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) { + // Do nothing if boot services are not available + if crate::os::uefi::env::boot_services().is_none() { + return; } + + // If boot services is valid then SystemTable is not null. + let system_table = crate::os::uefi::env::system_table().as_ptr().cast(); + // The caller must ensure non-0 layout + unsafe { r_efi_alloc::raw::dealloc(system_table, ptr, layout) } +} + +pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { + // SAFETY: this is just a `pub` wrapper. + unsafe { super::realloc_fallback(ptr, layout, new_size) } } diff --git a/library/std/src/sys/alloc/unix.rs b/library/std/src/sys/alloc/unix.rs index 3d369b08abc77..d6de8bf28c44c 100644 --- a/library/std/src/sys/alloc/unix.rs +++ b/library/std/src/sys/alloc/unix.rs @@ -1,60 +1,57 @@ use super::{MIN_ALIGN, realloc_fallback}; -use crate::alloc::{GlobalAlloc, Layout, System}; +use crate::alloc::Layout; use crate::ptr; -#[stable(feature = "alloc_system_type", since = "1.28.0")] -unsafe impl GlobalAlloc for System { - #[inline] - unsafe fn alloc(&self, layout: Layout) -> *mut u8 { - // jemalloc provides alignment less than MIN_ALIGN for small allocations. - // So only rely on MIN_ALIGN if size >= align. - // Also see and - // . - if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() { - unsafe { libc::malloc(layout.size()) as *mut u8 } - } else { - // `posix_memalign` returns a non-aligned value if supplied a very - // large alignment on older versions of Apple's platforms (unknown - // exactly which version range, but the issue is definitely - // present in macOS 10.14 and iOS 13.3). - // - // - #[cfg(target_vendor = "apple")] - { - if layout.align() > (1 << 31) { - return ptr::null_mut(); - } +#[inline] +pub unsafe fn alloc(layout: Layout) -> *mut u8 { + // jemalloc provides alignment less than MIN_ALIGN for small allocations. + // So only rely on MIN_ALIGN if size >= align. + // Also see and + // . + if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() { + unsafe { libc::malloc(layout.size()) as *mut u8 } + } else { + // `posix_memalign` returns a non-aligned value if supplied a very + // large alignment on older versions of Apple's platforms (unknown + // exactly which version range, but the issue is definitely + // present in macOS 10.14 and iOS 13.3). + // + // + #[cfg(target_vendor = "apple")] + { + if layout.align() > (1 << 31) { + return ptr::null_mut(); } - unsafe { aligned_malloc(&layout) } } + unsafe { aligned_malloc(&layout) } } +} - #[inline] - unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { - // See the comment above in `alloc` for why this check looks the way it does. - if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() { - unsafe { libc::calloc(layout.size(), 1) as *mut u8 } - } else { - let ptr = unsafe { self.alloc(layout) }; - if !ptr.is_null() { - unsafe { ptr::write_bytes(ptr, 0, layout.size()) }; - } - ptr +#[inline] +pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 { + // See the comment above in `alloc` for why this check looks the way it does. + if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() { + unsafe { libc::calloc(layout.size(), 1) as *mut u8 } + } else { + let ptr = unsafe { alloc(layout) }; + if !ptr.is_null() { + unsafe { ptr::write_bytes(ptr, 0, layout.size()) }; } + ptr } +} - #[inline] - unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) { - unsafe { libc::free(ptr as *mut libc::c_void) } - } +#[inline] +pub unsafe fn dealloc(ptr: *mut u8, _layout: Layout) { + unsafe { libc::free(ptr as *mut libc::c_void) } +} - #[inline] - unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { - if layout.align() <= MIN_ALIGN && layout.align() <= new_size { - unsafe { libc::realloc(ptr as *mut libc::c_void, new_size) as *mut u8 } - } else { - unsafe { realloc_fallback(self, ptr, layout, new_size) } - } +#[inline] +pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { + if layout.align() <= MIN_ALIGN && layout.align() <= new_size { + unsafe { libc::realloc(ptr as *mut libc::c_void, new_size) as *mut u8 } + } else { + unsafe { realloc_fallback(ptr, layout, new_size) } } } diff --git a/library/std/src/sys/alloc/vexos.rs b/library/std/src/sys/alloc/vexos.rs index 5ccf6625ed626..6aba6dc474911 100644 --- a/library/std/src/sys/alloc/vexos.rs +++ b/library/std/src/sys/alloc/vexos.rs @@ -1,7 +1,7 @@ // FIXME(static_mut_refs): use raw pointers instead of references #![allow(static_mut_refs)] -use crate::alloc::{GlobalAlloc, Layout, System}; +use crate::alloc::Layout; use crate::ptr; use crate::sync::atomic::{AtomicBool, Ordering}; @@ -60,37 +60,34 @@ unsafe impl dlmalloc::Allocator for Vexos { } } -#[stable(feature = "alloc_system_type", since = "1.28.0")] -unsafe impl GlobalAlloc for System { - #[inline] - unsafe fn alloc(&self, layout: Layout) -> *mut u8 { - // SAFETY: DLMALLOC access is guaranteed to be safe because we are a single-threaded target, which - // guarantees unique and non-reentrant access to the allocator. As such, no allocator lock is used. - // Calling malloc() is safe because preconditions on this function match the trait method preconditions. - unsafe { DLMALLOC.malloc(layout.size(), layout.align()) } - } +#[inline] +pub unsafe fn alloc(layout: Layout) -> *mut u8 { + // SAFETY: DLMALLOC access is guaranteed to be safe because we are a single-threaded target, which + // guarantees unique and non-reentrant access to the allocator. As such, no allocator lock is used. + // Calling malloc() is safe because preconditions on this function match the trait method preconditions. + unsafe { DLMALLOC.malloc(layout.size(), layout.align()) } +} - #[inline] - unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { - // SAFETY: DLMALLOC access is guaranteed to be safe because we are a single-threaded target, which - // guarantees unique and non-reentrant access to the allocator. As such, no allocator lock is used. - // Calling calloc() is safe because preconditions on this function match the trait method preconditions. - unsafe { DLMALLOC.calloc(layout.size(), layout.align()) } - } +#[inline] +pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 { + // SAFETY: DLMALLOC access is guaranteed to be safe because we are a single-threaded target, which + // guarantees unique and non-reentrant access to the allocator. As such, no allocator lock is used. + // Calling calloc() is safe because preconditions on this function match the trait method preconditions. + unsafe { DLMALLOC.calloc(layout.size(), layout.align()) } +} - #[inline] - unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { - // SAFETY: DLMALLOC access is guaranteed to be safe because we are a single-threaded target, which - // guarantees unique and non-reentrant access to the allocator. As such, no allocator lock is used. - // Calling free() is safe because preconditions on this function match the trait method preconditions. - unsafe { DLMALLOC.free(ptr, layout.size(), layout.align()) } - } +#[inline] +pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) { + // SAFETY: DLMALLOC access is guaranteed to be safe because we are a single-threaded target, which + // guarantees unique and non-reentrant access to the allocator. As such, no allocator lock is used. + // Calling free() is safe because preconditions on this function match the trait method preconditions. + unsafe { DLMALLOC.free(ptr, layout.size(), layout.align()) } +} - #[inline] - unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { - // SAFETY: DLMALLOC access is guaranteed to be safe because we are a single-threaded target, which - // guarantees unique and non-reentrant access to the allocator. As such, no allocator lock is used. - // Calling realloc() is safe because preconditions on this function match the trait method preconditions. - unsafe { DLMALLOC.realloc(ptr, layout.size(), layout.align(), new_size) } - } +#[inline] +pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { + // SAFETY: DLMALLOC access is guaranteed to be safe because we are a single-threaded target, which + // guarantees unique and non-reentrant access to the allocator. As such, no allocator lock is used. + // Calling realloc() is safe because preconditions on this function match the trait method preconditions. + unsafe { DLMALLOC.realloc(ptr, layout.size(), layout.align(), new_size) } } diff --git a/library/std/src/sys/alloc/wasm.rs b/library/std/src/sys/alloc/wasm.rs index 48e2fdd4eccec..995230aebaa01 100644 --- a/library/std/src/sys/alloc/wasm.rs +++ b/library/std/src/sys/alloc/wasm.rs @@ -18,7 +18,7 @@ use core::cell::SyncUnsafeCell; -use crate::alloc::{GlobalAlloc, Layout, System}; +use crate::alloc::Layout; struct SyncDlmalloc(dlmalloc::Dlmalloc); unsafe impl Sync for SyncDlmalloc {} @@ -26,39 +26,36 @@ unsafe impl Sync for SyncDlmalloc {} static DLMALLOC: SyncUnsafeCell = SyncUnsafeCell::new(SyncDlmalloc(dlmalloc::Dlmalloc::new())); -#[stable(feature = "alloc_system_type", since = "1.28.0")] -unsafe impl GlobalAlloc for System { - #[inline] - unsafe fn alloc(&self, layout: Layout) -> *mut u8 { - // SAFETY: DLMALLOC access is guaranteed to be safe because the lock gives us unique and non-reentrant access. - // Calling malloc() is safe because preconditions on this function match the trait method preconditions. - let _lock = lock::lock(); - unsafe { (*DLMALLOC.get()).0.malloc(layout.size(), layout.align()) } - } +#[inline] +pub unsafe fn alloc(layout: Layout) -> *mut u8 { + // SAFETY: DLMALLOC access is guaranteed to be safe because the lock gives us unique and non-reentrant access. + // Calling malloc() is safe because preconditions on this function match the trait method preconditions. + let _lock = lock::lock(); + unsafe { (*DLMALLOC.get()).0.malloc(layout.size(), layout.align()) } +} - #[inline] - unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { - // SAFETY: DLMALLOC access is guaranteed to be safe because the lock gives us unique and non-reentrant access. - // Calling calloc() is safe because preconditions on this function match the trait method preconditions. - let _lock = lock::lock(); - unsafe { (*DLMALLOC.get()).0.calloc(layout.size(), layout.align()) } - } +#[inline] +pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 { + // SAFETY: DLMALLOC access is guaranteed to be safe because the lock gives us unique and non-reentrant access. + // Calling calloc() is safe because preconditions on this function match the trait method preconditions. + let _lock = lock::lock(); + unsafe { (*DLMALLOC.get()).0.calloc(layout.size(), layout.align()) } +} - #[inline] - unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { - // SAFETY: DLMALLOC access is guaranteed to be safe because the lock gives us unique and non-reentrant access. - // Calling free() is safe because preconditions on this function match the trait method preconditions. - let _lock = lock::lock(); - unsafe { (*DLMALLOC.get()).0.free(ptr, layout.size(), layout.align()) } - } +#[inline] +pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) { + // SAFETY: DLMALLOC access is guaranteed to be safe because the lock gives us unique and non-reentrant access. + // Calling free() is safe because preconditions on this function match the trait method preconditions. + let _lock = lock::lock(); + unsafe { (*DLMALLOC.get()).0.free(ptr, layout.size(), layout.align()) } +} - #[inline] - unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { - // SAFETY: DLMALLOC access is guaranteed to be safe because the lock gives us unique and non-reentrant access. - // Calling realloc() is safe because preconditions on this function match the trait method preconditions. - let _lock = lock::lock(); - unsafe { (*DLMALLOC.get()).0.realloc(ptr, layout.size(), layout.align(), new_size) } - } +#[inline] +pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { + // SAFETY: DLMALLOC access is guaranteed to be safe because the lock gives us unique and non-reentrant access. + // Calling realloc() is safe because preconditions on this function match the trait method preconditions. + let _lock = lock::lock(); + unsafe { (*DLMALLOC.get()).0.realloc(ptr, layout.size(), layout.align(), new_size) } } #[cfg(target_feature = "atomics")] diff --git a/library/std/src/sys/alloc/windows.rs b/library/std/src/sys/alloc/windows.rs index 9336a6ec085aa..1d75cbd9d54f1 100644 --- a/library/std/src/sys/alloc/windows.rs +++ b/library/std/src/sys/alloc/windows.rs @@ -1,5 +1,18 @@ +//! Implements `System` on Windows. +//! +//! All pointers returned by this allocator have, in addition to the guarantees of `GlobalAlloc`, the +//! following properties: +//! +//! If the pointer was allocated or reallocated with a `layout` specifying an alignment <= `MIN_ALIGN` +//! the pointer will be aligned to at least `MIN_ALIGN` and point to the start of the allocated block. +//! +//! If the pointer was allocated or reallocated with a `layout` specifying an alignment > `MIN_ALIGN` +//! the pointer will be aligned to the specified alignment and not point to the start of the allocated block. +//! Instead there will be a header readable directly before the returned pointer, containing the actual +//! location of the start of the block. + use super::{MIN_ALIGN, realloc_fallback}; -use crate::alloc::{GlobalAlloc, Layout, System}; +use crate::alloc::Layout; use crate::ffi::c_void; use crate::mem::MaybeUninit; use crate::ptr; @@ -150,70 +163,56 @@ unsafe fn allocate(layout: Layout, zeroed: bool) -> *mut u8 { } } -// All pointers returned by this allocator have, in addition to the guarantees of `GlobalAlloc`, the -// following properties: -// -// If the pointer was allocated or reallocated with a `layout` specifying an alignment <= `MIN_ALIGN` -// the pointer will be aligned to at least `MIN_ALIGN` and point to the start of the allocated block. -// -// If the pointer was allocated or reallocated with a `layout` specifying an alignment > `MIN_ALIGN` -// the pointer will be aligned to the specified alignment and not point to the start of the allocated block. -// Instead there will be a header readable directly before the returned pointer, containing the actual -// location of the start of the block. -#[stable(feature = "alloc_system_type", since = "1.28.0")] -unsafe impl GlobalAlloc for System { - #[inline] - unsafe fn alloc(&self, layout: Layout) -> *mut u8 { - // SAFETY: Pointers returned by `allocate` satisfy the guarantees of `System` - let zeroed = false; - unsafe { allocate(layout, zeroed) } - } +pub unsafe fn alloc(layout: Layout) -> *mut u8 { + // SAFETY: Pointers returned by `allocate` satisfy the guarantees of `System` + let zeroed = false; + unsafe { allocate(layout, zeroed) } +} - #[inline] - unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { - // SAFETY: Pointers returned by `allocate` satisfy the guarantees of `System` - let zeroed = true; - unsafe { allocate(layout, zeroed) } - } +#[inline] +pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 { + // SAFETY: Pointers returned by `allocate` satisfy the guarantees of `System` + let zeroed = true; + unsafe { allocate(layout, zeroed) } +} - #[inline] - unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { - let block = { - if layout.align() <= MIN_ALIGN { - ptr - } else { - // The location of the start of the block is stored in the padding before `ptr`. +#[inline] +pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) { + let block = { + if layout.align() <= MIN_ALIGN { + ptr + } else { + // The location of the start of the block is stored in the padding before `ptr`. - // SAFETY: Because of the contract of `System`, `ptr` is guaranteed to be non-null - // and have a header readable directly before it. - unsafe { ptr::read((ptr as *mut Header).sub(1)).0 } - } - }; + // SAFETY: Because of the contract of `System`, `ptr` is guaranteed to be non-null + // and have a header readable directly before it. + unsafe { ptr::read((ptr as *mut Header).sub(1)).0 } + } + }; + // because `ptr` has been successfully allocated with this allocator, + // there must be a valid process heap. + let heap = get_process_heap(); + + // SAFETY: `heap` is a non-null handle returned by `GetProcessHeap`, + // `block` is a pointer to the start of an allocated block. + unsafe { HeapFree(heap, 0, block.cast::()) }; +} + +#[inline] +pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { + if layout.align() <= MIN_ALIGN { // because `ptr` has been successfully allocated with this allocator, // there must be a valid process heap. let heap = get_process_heap(); // SAFETY: `heap` is a non-null handle returned by `GetProcessHeap`, - // `block` is a pointer to the start of an allocated block. - unsafe { HeapFree(heap, 0, block.cast::()) }; - } - - #[inline] - unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { - if layout.align() <= MIN_ALIGN { - // because `ptr` has been successfully allocated with this allocator, - // there must be a valid process heap. - let heap = get_process_heap(); - - // SAFETY: `heap` is a non-null handle returned by `GetProcessHeap`, - // `ptr` is a pointer to the start of an allocated block. - // The returned pointer points to the start of an allocated block. - unsafe { HeapReAlloc(heap, 0, ptr.cast::(), new_size).cast::() } - } else { - // SAFETY: `realloc_fallback` is implemented using `dealloc` and `alloc`, which will - // correctly handle `ptr` and return a pointer satisfying the guarantees of `System` - unsafe { realloc_fallback(self, ptr, layout, new_size) } - } + // `ptr` is a pointer to the start of an allocated block. + // The returned pointer points to the start of an allocated block. + unsafe { HeapReAlloc(heap, 0, ptr.cast::(), new_size).cast::() } + } else { + // SAFETY: `realloc_fallback` is implemented using `dealloc` and `alloc`, which will + // correctly handle `ptr` and return a pointer satisfying the guarantees of `System` + unsafe { realloc_fallback(ptr, layout, new_size) } } } diff --git a/library/std/src/sys/alloc/xous.rs b/library/std/src/sys/alloc/xous.rs index af2dcabc1a23b..74229351f6d22 100644 --- a/library/std/src/sys/alloc/xous.rs +++ b/library/std/src/sys/alloc/xous.rs @@ -1,7 +1,7 @@ // FIXME(static_mut_refs): use raw pointers instead of references #![allow(static_mut_refs)] -use crate::alloc::{GlobalAlloc, Layout, System}; +use crate::alloc::Layout; #[cfg(not(test))] #[unsafe(export_name = "_ZN16__rust_internals3std3sys4xous5alloc8DLMALLOCE")] @@ -13,39 +13,36 @@ unsafe extern "Rust" { static mut DLMALLOC: dlmalloc::Dlmalloc; } -#[stable(feature = "alloc_system_type", since = "1.28.0")] -unsafe impl GlobalAlloc for System { - #[inline] - unsafe fn alloc(&self, layout: Layout) -> *mut u8 { - // SAFETY: DLMALLOC access is guaranteed to be safe because the lock gives us unique and non-reentrant access. - // Calling malloc() is safe because preconditions on this function match the trait method preconditions. - let _lock = lock::lock(); - unsafe { DLMALLOC.malloc(layout.size(), layout.align()) } - } +#[inline] +pub unsafe fn alloc(layout: Layout) -> *mut u8 { + // SAFETY: DLMALLOC access is guaranteed to be safe because the lock gives us unique and non-reentrant access. + // Calling malloc() is safe because preconditions on this function match the trait method preconditions. + let _lock = lock::lock(); + unsafe { DLMALLOC.malloc(layout.size(), layout.align()) } +} - #[inline] - unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { - // SAFETY: DLMALLOC access is guaranteed to be safe because the lock gives us unique and non-reentrant access. - // Calling calloc() is safe because preconditions on this function match the trait method preconditions. - let _lock = lock::lock(); - unsafe { DLMALLOC.calloc(layout.size(), layout.align()) } - } +#[inline] +pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 { + // SAFETY: DLMALLOC access is guaranteed to be safe because the lock gives us unique and non-reentrant access. + // Calling calloc() is safe because preconditions on this function match the trait method preconditions. + let _lock = lock::lock(); + unsafe { DLMALLOC.calloc(layout.size(), layout.align()) } +} - #[inline] - unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { - // SAFETY: DLMALLOC access is guaranteed to be safe because the lock gives us unique and non-reentrant access. - // Calling free() is safe because preconditions on this function match the trait method preconditions. - let _lock = lock::lock(); - unsafe { DLMALLOC.free(ptr, layout.size(), layout.align()) } - } +#[inline] +pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) { + // SAFETY: DLMALLOC access is guaranteed to be safe because the lock gives us unique and non-reentrant access. + // Calling free() is safe because preconditions on this function match the trait method preconditions. + let _lock = lock::lock(); + unsafe { DLMALLOC.free(ptr, layout.size(), layout.align()) } +} - #[inline] - unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { - // SAFETY: DLMALLOC access is guaranteed to be safe because the lock gives us unique and non-reentrant access. - // Calling realloc() is safe because preconditions on this function match the trait method preconditions. - let _lock = lock::lock(); - unsafe { DLMALLOC.realloc(ptr, layout.size(), layout.align(), new_size) } - } +#[inline] +pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { + // SAFETY: DLMALLOC access is guaranteed to be safe because the lock gives us unique and non-reentrant access. + // Calling realloc() is safe because preconditions on this function match the trait method preconditions. + let _lock = lock::lock(); + unsafe { DLMALLOC.realloc(ptr, layout.size(), layout.align(), new_size) } } mod lock { diff --git a/library/std/src/sys/alloc/zkvm.rs b/library/std/src/sys/alloc/zkvm.rs index a600cfa2220dd..7f39d7fed777e 100644 --- a/library/std/src/sys/alloc/zkvm.rs +++ b/library/std/src/sys/alloc/zkvm.rs @@ -1,15 +1,18 @@ -use crate::alloc::{GlobalAlloc, Layout, System}; +use crate::alloc::Layout; use crate::sys::pal::abi; -#[stable(feature = "alloc_system_type", since = "1.28.0")] -unsafe impl GlobalAlloc for System { - #[inline] - unsafe fn alloc(&self, layout: Layout) -> *mut u8 { - unsafe { abi::sys_alloc_aligned(layout.size(), layout.align()) } - } +#[inline] +pub unsafe fn alloc(layout: Layout) -> *mut u8 { + unsafe { abi::sys_alloc_aligned(layout.size(), layout.align()) } +} + +#[inline] +pub unsafe fn dealloc(_ptr: *mut u8, _layout: Layout) { + // this allocator never deallocates memory +} - #[inline] - unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) { - // this allocator never deallocates memory - } +#[inline] +pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { + // SAFETY: this is just a `pub` wrapper. + unsafe { super::realloc_fallback(ptr, layout, new_size) } } diff --git a/library/std/src/sys/fs/vexos.rs b/library/std/src/sys/fs/vexos.rs index d13b28d2abffa..595296bd85c8a 100644 --- a/library/std/src/sys/fs/vexos.rs +++ b/library/std/src/sys/fs/vexos.rs @@ -545,7 +545,7 @@ fn map_fresult(fresult: vex_sdk::FRESULT) -> io::Result<()> { match fresult { vex_sdk::FRESULT::FR_OK => Ok(()), vex_sdk::FRESULT::FR_DISK_ERR => Err(io::const_error!( - io::ErrorKind::Uncategorized, + io::ErrorKind::InputOutputError, "internal function reported an unrecoverable hard error", )), vex_sdk::FRESULT::FR_INT_ERR => Err(io::const_error!( diff --git a/library/std/src/sys/io/error/unix.rs b/library/std/src/sys/io/error/unix.rs index 2feeefa2530c8..c545558c3867e 100644 --- a/library/std/src/sys/io/error/unix.rs +++ b/library/std/src/sys/io/error/unix.rs @@ -177,6 +177,7 @@ pub fn decode_error_kind(errno: i32) -> io::ErrorKind { libc::EINPROGRESS => InProgress, libc::EMFILE | libc::ENFILE => TooManyOpenFiles, libc::EOPNOTSUPP => Unsupported, + libc::EIO => InputOutputError, libc::EACCES | libc::EPERM => PermissionDenied, diff --git a/library/std/src/sys/io/error/windows.rs b/library/std/src/sys/io/error/windows.rs index 9af11588fe322..3e6e281c61a75 100644 --- a/library/std/src/sys/io/error/windows.rs +++ b/library/std/src/sys/io/error/windows.rs @@ -64,6 +64,7 @@ pub fn decode_error_kind(errno: i32) -> io::ErrorKind { c::ERROR_TOO_MANY_OPEN_FILES => return TooManyOpenFiles, c::ERROR_FILENAME_EXCED_RANGE => return InvalidFilename, c::ERROR_CANT_RESOLVE_FILENAME => return FilesystemLoop, + c::ERROR_IO_DEVICE => return InputOutputError, _ => {} } diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs index fe0c103952414..58c8dc43e12ae 100644 --- a/library/std/src/sys/mod.rs +++ b/library/std/src/sys/mod.rs @@ -1,11 +1,11 @@ #![allow(unsafe_op_in_unsafe_fn)] -mod alloc; mod configure_builtins; mod helpers; mod pal; mod personality; +pub mod alloc; pub mod args; pub mod backtrace; pub mod cmath; diff --git a/src/librustdoc/formats/item_type.rs b/src/librustdoc/formats/item_type.rs index d13dbe7eb0490..e7d7cc2104b17 100644 --- a/src/librustdoc/formats/item_type.rs +++ b/src/librustdoc/formats/item_type.rs @@ -192,7 +192,6 @@ impl ItemType { | DefKind::Use | DefKind::ForeignMod | DefKind::AnonConst - | DefKind::InlineConst | DefKind::OpaqueTy | DefKind::LifetimeParam | DefKind::GlobalAsm diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index abf017174b547..4a3e6ac218a67 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -2208,8 +2208,7 @@ fn resolution_failure( | Use | LifetimeParam | Ctor(_, _) - | AnonConst - | InlineConst => { + | AnonConst => { let note = assoc_item_not_allowed(res); if let Some(span) = sp { diag.span_label(span, note); diff --git a/src/llvm-project b/src/llvm-project index a04c1eced55f2..52ed14fcd56af 160000 --- a/src/llvm-project +++ b/src/llvm-project @@ -1 +1 @@ -Subproject commit a04c1eced55f2f3ea8dbd3d17db0b6df271c0809 +Subproject commit 52ed14fcd56afc30f9cccd8ca8ce237c2eef7e04 diff --git a/src/tools/clippy/clippy_lints/src/manual_float_methods.rs b/src/tools/clippy/clippy_lints/src/manual_float_methods.rs index acd47fcd279db..de8edc03191fe 100644 --- a/src/tools/clippy/clippy_lints/src/manual_float_methods.rs +++ b/src/tools/clippy/clippy_lints/src/manual_float_methods.rs @@ -122,7 +122,6 @@ fn is_not_const(tcx: TyCtxt<'_>, def_id: DefId) -> bool { | DefKind::TyParam => true, DefKind::AnonConst - | DefKind::InlineConst | DefKind::Const { .. } | DefKind::ConstParam | DefKind::Static { .. } diff --git a/src/tools/clippy/clippy_lints/src/matches/match_wild_enum.rs b/src/tools/clippy/clippy_lints/src/matches/match_wild_enum.rs index 98530b7808076..69288e693e4b4 100644 --- a/src/tools/clippy/clippy_lints/src/matches/match_wild_enum.rs +++ b/src/tools/clippy/clippy_lints/src/matches/match_wild_enum.rs @@ -67,10 +67,7 @@ pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>]) { }) => { // FIXME(clippy): don't you want to use the hir id of the peeled pat? let id = match cx.qpath_res(path, *hir_id) { - Res::Def( - DefKind::Const { .. } | DefKind::ConstParam | DefKind::AnonConst | DefKind::InlineConst, - _, - ) => return, + Res::Def(DefKind::Const { .. } | DefKind::ConstParam | DefKind::AnonConst, _) => return, Res::Def(_, id) => id, _ => return, }; diff --git a/src/tools/compiletest/src/directives/directive_names.rs b/src/tools/compiletest/src/directives/directive_names.rs index 70901f5b84c56..058047cd07548 100644 --- a/src/tools/compiletest/src/directives/directive_names.rs +++ b/src/tools/compiletest/src/directives/directive_names.rs @@ -327,5 +327,23 @@ pub(crate) const KNOWN_HTMLDOCCK_DIRECTIVE_NAMES: &[&str] = &[ "!snapshot", ]; -pub(crate) const KNOWN_JSONDOCCK_DIRECTIVE_NAMES: &[&str] = - &["count", "!count", "has", "!has", "is", "!is", "ismany", "!ismany", "set", "!set"]; +pub(crate) const KNOWN_JSONDOCCK_DIRECTIVE_NAMES: &[&str] = &[ + "count", + "!count", + "has", + "!has", + "is", + "!is", + "ismany", + "!ismany", + "set", + "jq_count", + "!jq_count", + "jq_has", + "!jq_has", + "jq_is", + "!jq_is", + "jq_ismany", + "!jq_ismany", + "jq_set", +]; diff --git a/src/tools/jsondocck/Cargo.toml b/src/tools/jsondocck/Cargo.toml index f2ae68f7fbd69..c7707caa2b3b0 100644 --- a/src/tools/jsondocck/Cargo.toml +++ b/src/tools/jsondocck/Cargo.toml @@ -10,3 +10,6 @@ regex = "1.4" shlex = "1.0" serde_json = "1.0" fs-err = "2.5.0" +jaq-core = "3" +jaq-std = { version = "3", default-features = false } +jaq-json = { version = "2", features = ["serde"] } diff --git a/src/tools/jsondocck/src/cache.rs b/src/tools/jsondocck/src/cache.rs index 1369c8ded0070..8d9273e2ceb67 100644 --- a/src/tools/jsondocck/src/cache.rs +++ b/src/tools/jsondocck/src/cache.rs @@ -2,12 +2,17 @@ use std::collections::HashMap; use std::path::Path; use fs_err as fs; +use jaq_core::load::{Arena, File, Loader}; +use jaq_core::{Ctx, Vars, data, unwrap_valr}; +use jaq_json::Val; use serde_json::Value; use crate::config::Config; #[derive(Debug)] pub struct Cache { + jq_value: Val, + pub jq_variables: HashMap, value: Value, pub variables: HashMap, } @@ -23,6 +28,8 @@ impl Cache { let content = fs::read_to_string(&file_path).expect("failed to read JSON file"); Cache { + jq_value: serde_json::from_str::(&content).expect("failed to convert from JSON"), + jq_variables: HashMap::from([("FILE".to_owned(), config.template.clone().into())]), value: serde_json::from_str::(&content).expect("failed to convert from JSON"), variables: HashMap::from([("FILE".to_owned(), config.template.clone().into())]), } @@ -32,4 +39,31 @@ impl Cache { pub fn select(&self, path: &str) -> Vec<&Value> { jsonpath_rust::query::js_path_vals(path, &self.value).unwrap() } + + pub fn jq_select(&self, filter_src: &str) -> Vec { + let program = File { code: filter_src, path: () }; + + let defs = jaq_core::defs().chain(jaq_std::defs()).chain(jaq_json::defs()); + let funs = jaq_core::funs().chain(jaq_std::funs()).chain(jaq_json::funs()); + + let loader = Loader::new(defs); + let arena = Arena::default(); + + let modules = loader.load(&arena, program).unwrap(); + + let vars = self.jq_variables.iter().map(|t| (format!("${}", t.0), t.1)).collect::>(); + + let filter = jaq_core::Compiler::default() + .with_funs(funs) + .with_global_vars(vars.clone().iter().map(|t| t.0.as_str())) + .compile(modules) + .unwrap(); + + let ctx = Ctx::>::new( + &filter.lut, + Vars::new(vars.iter().map(|t| t.1.clone())), + ); + + filter.id.run((ctx, self.jq_value.clone())).map(unwrap_valr).map(Result::unwrap).collect() + } } diff --git a/src/tools/jsondocck/src/directive.rs b/src/tools/jsondocck/src/directive.rs index c52c16866608d..6154374b48fde 100644 --- a/src/tools/jsondocck/src/directive.rs +++ b/src/tools/jsondocck/src/directive.rs @@ -1,5 +1,7 @@ use std::borrow::Cow; +use std::fmt::Debug; +use jaq_json::Val; use serde_json::Value; use crate::cache::Cache; @@ -13,6 +15,12 @@ pub struct Directive { #[derive(Debug)] pub enum DirectiveKind { + JsonPath(JsonPathDirective), + Jq(JqDirective), +} + +#[derive(Debug)] +pub enum JsonPathDirective { /// `//@ has ` /// /// Checks the path exists. @@ -57,6 +65,42 @@ pub enum DirectiveKind { Set { variable: String }, } +#[derive(Debug)] +pub enum JqDirective { + /// `//@ jq_has ` + /// + /// Check one thing at the path is equal to the value. + HasValue { value: String }, + + /// `//@ !jq_has ` + /// + /// Checks the path exists, but doesn't have the given value. + HasNotValue { value: String }, + + /// `//@ jq_is ` + /// + /// Check the path is the given value. + Is { value: String }, + + /// `//@ jq_is ...` + /// + /// Check that the path matches to exactly every given value. + IsMany { values: Vec }, + + /// `//@ !jq_is ` + /// + /// Check the path isn't the given value. + IsNot { value: String }, + + /// `//@ jq_count ` + /// + /// Check the path has the expected number of matches. + CountIs { expected: usize }, + + /// `//@ jq_set = ` + Set { variable: String }, +} + impl DirectiveKind { /// Returns both the kind and the path. /// @@ -66,45 +110,84 @@ impl DirectiveKind { negated: bool, args: &'a [String], ) -> Option<(Self, &'a str)> { + // FIXME(lolbinarycat): refactor this parsing into something more compact with better error reporting. let kind = match (directive_name, negated) { + // jsonpath ("count", false) => { assert_eq!(args.len(), 2); let expected = args[1].parse().expect("invalid number for `count`"); - Self::CountIs { expected } + Self::JsonPath(JsonPathDirective::CountIs { expected }) } - ("ismany", false) => { - // FIXME: Make this >= 3, and migrate len(values)==1 cases to @is + // FIXME: Make this >= 3, and migrate len(values)==1 cases to `is` assert!(args.len() >= 2, "Not enough args to `ismany`"); let values = args[1..].to_owned(); - Self::IsMany { values } + Self::JsonPath(JsonPathDirective::IsMany { values }) } - ("is", false) => { assert_eq!(args.len(), 2); - Self::Is { value: args[1].clone() } + Self::JsonPath(JsonPathDirective::Is { value: args[1].clone() }) } ("is", true) => { assert_eq!(args.len(), 2); - Self::IsNot { value: args[1].clone() } + Self::JsonPath(JsonPathDirective::IsNot { value: args[1].clone() }) } - ("set", false) => { assert_eq!(args.len(), 3); assert_eq!(args[1], "="); - return Some((Self::Set { variable: args[0].clone() }, &args[2])); + return Some(( + Self::JsonPath(JsonPathDirective::Set { variable: args[0].clone() }), + &args[2], + )); } - ("has", false) => match args { - [_path] => Self::HasPath, - [_path, value] => Self::HasValue { value: value.clone() }, + [_path] => Self::JsonPath(JsonPathDirective::HasPath), + [_path, value] => { + Self::JsonPath(JsonPathDirective::HasValue { value: value.clone() }) + } _ => panic!("`//@ has` must have 2 or 3 arguments, but got {args:?}"), }, ("has", true) => match args { - [_path] => Self::HasNotPath, - [_path, value] => Self::HasNotValue { value: value.clone() }, + [_path] => Self::JsonPath(JsonPathDirective::HasNotPath), + [_path, value] => { + Self::JsonPath(JsonPathDirective::HasNotValue { value: value.clone() }) + } _ => panic!("`//@ !has` must have 2 or 3 arguments, but got {args:?}"), }, + + // jq + ("jq_count", false) => { + assert_eq!(args.len(), 2); + let expected = args[1].parse().expect("invalid number for `jq_count`"); + Self::Jq(JqDirective::CountIs { expected }) + } + ("jq_ismany", false) => { + // FIXME: Make this >= 3, and migrate len(values)==1 cases to `jq_is` + assert!(args.len() >= 2, "Not enough args to `jq_ismany`"); + let values = args[1..].to_owned(); + Self::Jq(JqDirective::IsMany { values }) + } + ("jq_is", false) => { + assert_eq!(args.len(), 2); + Self::Jq(JqDirective::Is { value: args[1].clone() }) + } + ("jq_is", true) => { + assert_eq!(args.len(), 2); + Self::Jq(JqDirective::IsNot { value: args[1].clone() }) + } + ("jq_has", false) => { + assert_eq!(args.len(), 2); + Self::Jq(JqDirective::HasValue { value: args[1].clone() }) + } + ("jq_has", true) => { + assert_eq!(args.len(), 2); + Self::Jq(JqDirective::HasNotValue { value: args[1].clone() }) + } + ("jq_set", false) => { + assert_eq!(args.len(), 3); + assert_eq!(args[1], "="); + return Some((Self::Jq(JqDirective::Set { variable: args[0].clone() }), &args[2])); + } // Ignore unknown directives as they might be compiletest directives // since they share the same `//@` prefix by convention. In any case, // compiletest rejects unknown directives for us. @@ -118,94 +201,188 @@ impl DirectiveKind { impl Directive { /// Performs the actual work of ensuring a directive passes. pub fn check(&self, cache: &mut Cache) -> Result<(), String> { - let matches = cache.select(&self.path); match &self.kind { - DirectiveKind::HasPath => { - if matches.is_empty() { - return Err("matched to no values".to_owned()); - } - } - DirectiveKind::HasNotPath => { - if !matches.is_empty() { - return Err(format!("matched to {matches:?}, but wanted no matches")); - } - } - DirectiveKind::HasValue { value } => { - let want_value = string_to_value(value, cache); - if !matches.contains(&want_value.as_ref()) { - return Err(format!( - "matched to {matches:?}, which didn't contain {want_value:?}" - )); - } - } - DirectiveKind::HasNotValue { value } => { - let wantnt_value = string_to_value(value, cache); - if matches.contains(&wantnt_value.as_ref()) { - return Err(format!( - "matched to {matches:?}, which contains unwanted {wantnt_value:?}" - )); - } else if matches.is_empty() { - return Err(format!( - "got no matches, but expected some matched (not containing {wantnt_value:?}" - )); - } - } + DirectiveKind::JsonPath(d) => { + let matches = cache.select(&self.path); + match d { + JsonPathDirective::HasPath => { + if matches.is_empty() { + return Err("matched to no values".to_owned()); + } + } + JsonPathDirective::HasNotPath => { + if !matches.is_empty() { + return Err(format!("matched to {matches:?}, but expected no matches")); + } + } + JsonPathDirective::HasValue { value } => { + let want_value = string_to_value(value, cache); + if !matches.contains(&want_value.as_ref()) { + return Err(format!( + "matched to {matches:?}, which didn't contain {want_value:?}" + )); + } + } + JsonPathDirective::HasNotValue { value } => { + let unwanted_value = string_to_value(value, cache); + if matches.contains(&unwanted_value.as_ref()) { + return Err(format!( + "matched to {matches:?}, which contains unwanted {unwanted_value:?}" + )); + } else if matches.is_empty() { + return Err(format!( + "got no matches, but expected some matched (not containing {unwanted_value:?}" + )); + } + } - DirectiveKind::Is { value } => { - let want_value = string_to_value(value, cache); - let matched = get_one(&matches)?; - if matched != want_value.as_ref() { - return Err(format!("matched to {matched:?} but want {want_value:?}")); - } - } - DirectiveKind::IsNot { value } => { - let wantnt_value = string_to_value(value, cache); - let matched = get_one(&matches)?; - if matched == wantnt_value.as_ref() { - return Err(format!("got value {wantnt_value:?}, but want anything else")); - } - } + JsonPathDirective::Is { value } => { + let want_value = string_to_value(value, cache); + let matched = get_one(&matches)?; + if matched != want_value.as_ref() { + return Err(format!("matched to {matched:?} but want {want_value:?}")); + } + } + JsonPathDirective::IsNot { value } => { + let unwanted_value = string_to_value(value, cache); + let matched = get_one(&matches)?; + if matched == unwanted_value.as_ref() { + return Err(format!( + "got value {unwanted_value:?}, but want anything else" + )); + } + } - DirectiveKind::IsMany { values } => { - // Serde json doesn't implement Ord or Hash for Value, so we must - // use a Vec here. While in theory that makes setwize equality - // O(n^2), in practice n will never be large enough to matter. - let expected_values = - values.iter().map(|v| string_to_value(v, cache)).collect::>(); - if expected_values.len() != matches.len() { - return Err(format!( - "Expected {} values, but matched to {} values ({:?})", - expected_values.len(), - matches.len(), - matches - )); - }; - for got_value in matches { - if !expected_values.iter().any(|exp| &**exp == got_value) { - return Err(format!("has match {got_value:?}, which was not expected",)); + JsonPathDirective::IsMany { values } => { + let expected_values = + values.iter().map(|v| string_to_value(v, cache)).collect::>(); + if expected_values.len() != matches.len() { + return Err(format!( + "Expected {} values, but matched to {} values ({:?})", + expected_values.len(), + matches.len(), + matches + )); + }; + for got_value in matches { + if !expected_values.iter().any(|exp| &**exp == got_value) { + return Err(format!( + "has match {got_value:?}, which was not expected", + )); + } + } + } + JsonPathDirective::CountIs { expected } => { + if *expected != matches.len() { + return Err(format!( + "matched to `{matches:?}` with length {}, but expected length {expected}", + matches.len(), + )); + } + } + JsonPathDirective::Set { variable } => { + let value = get_one(&matches)?; + // this should never fail since `Val` is a superset of `Value` + let val = serde_json::from_value(value.to_owned()).unwrap(); + let vars = cache.variables.insert(variable.to_owned(), value.clone()); + let jq_vars = cache.jq_variables.insert(variable.to_owned(), val); + assert!( + vars.is_none() && jq_vars.is_none(), + "name collision: {variable:?} is duplicated" + ); } } } - DirectiveKind::CountIs { expected } => { - if *expected != matches.len() { - return Err(format!( - "matched to `{matches:?}` with length {}, but expected length {expected}", - matches.len(), - )); + DirectiveKind::Jq(d) => { + let matches = cache.jq_select(&self.path); + match d { + JqDirective::HasValue { value } => { + let want_value = string_to_val(value, cache); + if !matches.contains(&want_value.as_ref()) { + return Err(format!( + "matched to {matches:?}, which didn't contain {want_value:?}" + )); + } + } + JqDirective::HasNotValue { value } => { + let unwanted_value = string_to_val(value, cache); + if matches.contains(&unwanted_value.as_ref()) { + return Err(format!( + "matched to {matches:?}, which contains unwanted {unwanted_value:?}" + )); + } else if matches.is_empty() { + return Err(format!( + "got no matches, but expected some matched (not containing {unwanted_value:?}" + )); + } + } + + JqDirective::Is { value } => { + let want_value = string_to_val(value, cache); + let matched = get_one(&matches.iter().collect::>())?; + if matched != want_value.as_ref() { + return Err(format!( + "matched to {matched:?} but expected {want_value:?}" + )); + } + } + JqDirective::IsNot { value } => { + let unwanted_value = string_to_val(value, cache); + let matched = get_one(&matches.iter().collect::>())?; + if matched == unwanted_value.as_ref() { + return Err(format!( + "got value {unwanted_value:?}, but expected anything else" + )); + } + } + + JqDirective::IsMany { values } => { + let expected_values = + values.iter().map(|v| string_to_val(v, cache)).collect::>(); + if expected_values.len() != matches.len() { + return Err(format!( + "Expected {} values, but matched to {} values ({:?})", + expected_values.len(), + matches.len(), + matches + )); + }; + for got_value in matches { + if !expected_values.iter().any(|exp| **exp == got_value) { + return Err(format!( + "has match {got_value:?}, which was not expected", + )); + } + } + } + JqDirective::CountIs { expected } => { + if *expected != matches.len() { + return Err(format!( + "matched to `{matches:?}` with length {}, but expected length {expected}", + matches.len(), + )); + } + } + JqDirective::Set { variable } => { + let val = get_one(&matches.iter().collect::>())?; + // this might fail but only if value contains binary data or non-string object keys which are never needed + let value = serde_json::to_value(val.to_string()).unwrap(); + let vars = cache.variables.insert(variable.to_owned(), value); + let jq_vars = cache.jq_variables.insert(variable.to_owned(), val.clone()); + assert!( + jq_vars.is_none() && vars.is_none(), + "name collision: {variable:?} is duplicated" + ); + } } } - DirectiveKind::Set { variable } => { - let value = get_one(&matches)?; - let r = cache.variables.insert(variable.to_owned(), value.clone()); - assert!(r.is_none(), "name collision: {variable:?} is duplicated"); - } } Ok(()) } } -fn get_one<'a>(matches: &[&'a Value]) -> Result<&'a Value, String> { +fn get_one<'a, T: Debug>(matches: &[&'a T]) -> Result<&'a T, String> { match matches { [] => Err("matched to no values".to_owned()), [matched] => Ok(matched), @@ -223,3 +400,14 @@ fn string_to_value<'a>(s: &str, cache: &'a Cache) -> Cow<'a, Value> { Cow::Owned(serde_json::from_str(s).expect(&format!("Cannot convert `{}` to json", s))) } } + +fn string_to_val<'a>(s: &str, cache: &'a Cache) -> Cow<'a, Val> { + if s.starts_with("$") { + Cow::Borrowed(&cache.jq_variables.get(&s[1..]).unwrap_or_else(|| { + // FIXME(adotinthevoid): Show line number + panic!("No variable: `{}`. Current state: `{:?}`", &s[1..], cache.jq_variables) + })) + } else { + Cow::Owned(serde_json::from_str(s).expect(&format!("Cannot convert `{}` to json", s))) + } +} diff --git a/src/tools/miri/src/intrinsics/mod.rs b/src/tools/miri/src/intrinsics/mod.rs index a8eed1b8e0c4e..ab4d19a85acc2 100644 --- a/src/tools/miri/src/intrinsics/mod.rs +++ b/src/tools/miri/src/intrinsics/mod.rs @@ -135,23 +135,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { return interp_ok(EmulateItemResult::AlreadyJumped); } - // Raw memory accesses - "volatile_load" => { - let [place] = check_intrinsic_arg_count(args)?; - let place = this.deref_pointer(place)?; - this.copy_op(&place, dest)?; - } - "volatile_store" => { - let [place, dest] = check_intrinsic_arg_count(args)?; - let place = this.deref_pointer(place)?; - this.copy_op(dest, &place)?; - } - - "volatile_set_memory" => { - let [ptr, val_byte, count] = check_intrinsic_arg_count(args)?; - this.write_bytes_intrinsic(ptr, val_byte, count, "volatile_set_memory")?; - } - // Memory model / provenance manipulation "ptr_mask" => { let [ptr, mask] = check_intrinsic_arg_count(args)?; diff --git a/src/tools/miri/tests/fail/alloc/global_system_mixup.stderr b/src/tools/miri/tests/fail/alloc/global_system_mixup.stderr index 1e9d859b5cf81..1853ecbf43c70 100644 --- a/src/tools/miri/tests/fail/alloc/global_system_mixup.stderr +++ b/src/tools/miri/tests/fail/alloc/global_system_mixup.stderr @@ -1,13 +1,13 @@ error: Undefined Behavior: deallocating ALLOC, which is Rust heap memory, using PLATFORM heap deallocation operation --> RUSTLIB/std/src/sys/alloc/PLATFORM.rs:LL:CC | -LL | FREE(); +LL | FREE(); | ^ Undefined Behavior occurred here | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = note: stack backtrace: - 0: std::sys::alloc::PLATFORM::::dealloc + 0: std::sys::alloc::PLATFORM::dealloc at RUSTLIB/std/src/sys/alloc/PLATFORM.rs:LL:CC 1: ::deallocate at RUSTLIB/std/src/alloc.rs:LL:CC diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index ebe3c04ea4cc4..60b321641ad76 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -363,6 +363,8 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "itoa", "jiff", "jiff-static", + "jiff-tzdb", + "jiff-tzdb-platform", "jobserver", "lazy_static", "leb128", diff --git a/tests/codegen-llvm/aggregate-padding-zero.rs b/tests/codegen-llvm/aggregate-padding-zero.rs new file mode 100644 index 0000000000000..8455b1d8583a5 --- /dev/null +++ b/tests/codegen-llvm/aggregate-padding-zero.rs @@ -0,0 +1,244 @@ +//@ add-minicore +//@ compile-flags: -Copt-level=3 -Cno-prepopulate-passes -Z merge-functions=disabled -Z randomize-layout=no +//@ revisions: powerpc64 x86_64 +//@[powerpc64] compile-flags: --target powerpc64-unknown-linux-gnu +//@[powerpc64] needs-llvm-components: powerpc +//@[x86_64] compile-flags: --target x86_64-unknown-linux-gnu +//@[x86_64] needs-llvm-components: x86 + +// Regression test for . +// +// These cases specifically exercise direct codegen of small non-zero constant +// aggregates as a single integer store. They are chosen so they fail without +// `try_codegen_const_aggregate_as_immediate`. + +#![crate_type = "lib"] +#![feature(no_core, lang_items)] +#![no_core] + +extern crate minicore; + +use minicore::*; + +#[inline(always)] +unsafe fn ptr_write(dest: *mut T, value: T) { + *dest = value; +} + +trait MaybeUninitExt { + fn as_mut_ptr(&mut self) -> *mut T; + fn write(&mut self, value: T); +} + +impl MaybeUninitExt for MaybeUninit { + fn as_mut_ptr(&mut self) -> *mut T { + self as *mut _ as *mut T + } + + fn write(&mut self, value: T) { + unsafe { + ptr_write(self.as_mut_ptr(), value); + } + } +} + +// Inner padding between b (offset 2, size 1) and c (offset 4, size 4). +#[repr(C)] +pub struct InnerPadded { + a: u16, + b: u8, + c: u32, +} + +#[repr(transparent)] +pub struct Nested1(InnerPadded); + +#[repr(transparent)] +pub struct Nested2(Nested1); + +// PR 157690's original ptr::write entry point, checked against the current +// aggregate-immediate codegen shape. +// CHECK-LABEL: @via_ptr_write( +#[no_mangle] +pub fn via_ptr_write(dest: &mut MaybeUninit) { + let val = InnerPadded { a: 0, b: 0, c: 0 }; + // CHECK: %val = alloca [8 x i8], align 4 + // CHECK-NEXT: call void @llvm.lifetime.start.p0({{(i64 8, )?}}ptr %val) + // CHECK-NEXT: store i64 0, ptr %val, align 4 + // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %val, i64 8, i1 false) + unsafe { + ptr_write(dest.as_mut_ptr(), val); + } +} + +// PR 157690's original MaybeUninit::write entry point. +// CHECK-LABEL: @via_maybe_uninit_write( +#[no_mangle] +pub fn via_maybe_uninit_write(dest: &mut MaybeUninit) { + let val = InnerPadded { a: 0, b: 0, c: 0 }; + // CHECK: %val = alloca [8 x i8], align 4 + // CHECK-NEXT: call void @llvm.lifetime.start.p0({{(i64 8, )?}}ptr %val) + // CHECK-NEXT: store i64 0, ptr %val, align 4 + // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %{{.*}}, i64 8, i1 false) + dest.write(val); +} + +// Constant non-zero initialization: emitted as a single store including zero padding. +// CHECK-LABEL: @const_init_non_zero( +#[no_mangle] +pub fn const_init_non_zero(dest: *mut InnerPadded) { + let val = InnerPadded { a: 0, b: 1, c: 0 }; + // CHECK: %val = alloca [8 x i8], align 4 + // CHECK-NEXT: call void @llvm.lifetime.start.p0({{(i64 8, )?}}ptr %val) + // x86_64-NEXT: store i64 65536, ptr %val, align 4 + // powerpc64-NEXT: store i64 1099511627776, ptr %val, align 4 + // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %val, i64 8, i1 false) + unsafe { + ptr_write(dest, val); + } +} + +// From issue #157373: nesting wrapper structs used to change the lowering +// shape enough that LLVM would sometimes find the wide store only in the +// nested case. +// CHECK-LABEL: @bad( +#[no_mangle] +pub fn bad(a: &mut InnerPadded) { + let x = InnerPadded { a: 0, b: 1, c: 0 }; + // x86_64: store i64 65536, ptr %x, align 4 + // powerpc64: store i64 1099511627776, ptr %x, align 4 + *a = x; +} + +// CHECK-LABEL: @good( +#[no_mangle] +pub fn good(a: &mut Nested2) { + let x = InnerPadded { a: 0, b: 1, c: 0 }; + // x86_64: store i64 65536, ptr %x, align 4 + // powerpc64: store i64 1099511627776, ptr %x, align 4 + *a = Nested2(Nested1(x)); +} + +// The same direct constant aggregate packing should apply through ptr::write on MaybeUninit. +// CHECK-LABEL: @via_ptr_write_non_zero( +#[no_mangle] +pub fn via_ptr_write_non_zero(dest: &mut MaybeUninit) { + let val = InnerPadded { a: 0, b: 1, c: 0 }; + // CHECK: %val = alloca [8 x i8], align 4 + // CHECK-NEXT: call void @llvm.lifetime.start.p0({{(i64 8, )?}}ptr %val) + // x86_64-NEXT: store i64 65536, ptr %val, align 4 + // powerpc64-NEXT: store i64 1099511627776, ptr %val, align 4 + // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %val, i64 8, i1 false) + unsafe { + ptr_write(dest.as_mut_ptr(), val); + } +} + +// The same direct constant aggregate packing should apply through MaybeUninit::write. +// CHECK-LABEL: @via_maybe_uninit_write_non_zero( +#[no_mangle] +pub fn via_maybe_uninit_write_non_zero(dest: &mut MaybeUninit) { + let val = InnerPadded { a: 0, b: 1, c: 0 }; + // CHECK: %val = alloca [8 x i8], align 4 + // CHECK-NEXT: call void @llvm.lifetime.start.p0({{(i64 8, )?}}ptr %val) + // x86_64-NEXT: store i64 65536, ptr %val, align 4 + // powerpc64-NEXT: store i64 1099511627776, ptr %val, align 4 + // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %{{.*}}, i64 8, i1 false) + dest.write(val); +} + +// CHECK-LABEL: @bad_non_zero( +#[no_mangle] +pub fn bad_non_zero(a: &mut InnerPadded) { + let x = InnerPadded { a: 0, b: 1, c: 0 }; + // CHECK: %x = alloca [8 x i8], align 4 + // CHECK-NEXT: call void @llvm.lifetime.start.p0({{(i64 8, )?}}ptr %x) + // x86_64-NEXT: store i64 65536, ptr %x, align 4 + // powerpc64-NEXT: store i64 1099511627776, ptr %x, align 4 + // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %a, ptr align 4 %x, i64 8, i1 false) + *a = x; +} + +// CHECK-LABEL: @good_non_zero( +#[no_mangle] +pub fn good_non_zero(a: &mut Nested2) { + let x = InnerPadded { a: 0, b: 1, c: 0 }; + // CHECK: %x = alloca [8 x i8], align 4 + // CHECK-NEXT: call void @llvm.lifetime.start.p0({{(i64 8, )?}}ptr %x) + // x86_64-NEXT: store i64 65536, ptr %x, align 4 + // powerpc64-NEXT: store i64 1099511627776, ptr %x, align 4 + // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %a, ptr align 4 %{{.*}}, i64 8, i1 false) + *a = Nested2(Nested1(x)); +} + +// Trailing padding only (no inter-field padding): a (offset 0, size 4), +// b (offset 4, size 2), c (offset 6, size 1), trailing pad (offset 7, size 1). +#[repr(C)] +pub struct TailOnly { + a: u32, + b: u16, + c: u8, +} + +type TupleTailOnly = (u32, u16, u8); + +// PR 157690's trailing-padding-only entry point. +// CHECK-LABEL: @tail_only_write( +#[no_mangle] +pub fn tail_only_write(dest: &mut MaybeUninit) { + let val = TailOnly { a: 0, b: 0, c: 0 }; + // CHECK: %val = alloca [8 x i8], align 4 + // CHECK-NEXT: call void @llvm.lifetime.start.p0({{(i64 8, )?}}ptr %val) + // CHECK-NEXT: store i64 0, ptr %val, align 4 + // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %val, i64 8, i1 false) + unsafe { + ptr_write(dest.as_mut_ptr(), val); + } +} + +// Tuple aggregates should use the same const-packing path as structs when the +// whole tuple is constant and small enough to fit in an integer store. +// CHECK-LABEL: @tuple_tail_only_non_zero( +#[no_mangle] +pub fn tuple_tail_only_non_zero(dest: *mut TupleTailOnly) { + let val: TupleTailOnly = (0, 1, 0); + // CHECK: %val = alloca [8 x i8], align 4 + // CHECK-NEXT: call void @llvm.lifetime.start.p0({{(i64 8, )?}}ptr %val) + // x86_64-NEXT: store i64 4294967296, ptr %val, align 4 + // powerpc64-NEXT: store i64 65536, ptr %val, align 4 + // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dest, ptr align 4 %val, i64 8, i1 false) + unsafe { + ptr_write(dest, val); + } +} + +// Regression test for the debug assertion failure in +// `try_codegen_const_aggregate_as_immediate` when the MIR aggregate's +// variant index doesn't match the layout's `Variants::Single { index }`. +// +// When `Data(Void)` is uninhabited, the layout of `E` collapses to +// `Variants::Single { index: 0 }` (only `Empty`). But generic code +// monomorphized with `T = Void` still contains an aggregate for `Data(x)` +// with 1 operand. The optimization must bail out gracefully instead of +// asserting `operands.len() == dest.layout.fields.count()` (1 == 0). +// +// See . +enum Void {} + +enum E { + Empty, + Data(T), +} + +#[inline(never)] +fn make_data(x: T) -> E { + E::Data(x) +} + +// Force codegen of `make_data::`. Without the variant index check, +// this triggers: assertion `left == right` failed (left: 1, right: 0). +// CHECK-LABEL: @force_variant_mismatch( +#[no_mangle] +pub fn force_variant_mismatch() -> fn(Void) -> E { + make_data:: +} diff --git a/tests/codegen-llvm/issues/result-is-ok-unwrap.rs b/tests/codegen-llvm/issues/result-is-ok-unwrap.rs new file mode 100644 index 0000000000000..ffcbb0ae142d9 --- /dev/null +++ b/tests/codegen-llvm/issues/result-is-ok-unwrap.rs @@ -0,0 +1,20 @@ +// Checking `Result::is_ok()` should make a following `unwrap()` branch-free. + +//@ compile-flags: -Copt-level=3 + +#![crate_type = "lib"] + +use std::hint::black_box; + +// CHECK-LABEL: @unwrap_after_is_ok +#[no_mangle] +pub fn unwrap_after_is_ok(arg: Result) { + // CHECK-NOT: unwrap_failed + // CHECK-NOT: panic + if arg.is_ok() { + let value = arg.unwrap(); + if value == 42 { + black_box(value); + } + } +} diff --git a/tests/rustdoc-json/attrs/cold.rs b/tests/rustdoc-json/attrs/cold.rs index ec1926e894e4f..9433a9c05f807 100644 --- a/tests/rustdoc-json/attrs/cold.rs +++ b/tests/rustdoc-json/attrs/cold.rs @@ -1,3 +1,3 @@ -//@ is "$.index[?(@.name=='cold_fn')].attrs" '[{"other": "#[attr = Cold]"}]' +//@ jq_is '.index[] | select(.name == "cold_fn").attrs.[0].other' '"#[attr = Cold]"' #[cold] pub fn cold_fn() {} diff --git a/tests/rustdoc-json/blanket_impls.rs b/tests/rustdoc-json/blanket_impls.rs index d500bf5af6bd7..2def2c2c5a956 100644 --- a/tests/rustdoc-json/blanket_impls.rs +++ b/tests/rustdoc-json/blanket_impls.rs @@ -2,7 +2,6 @@ #![no_std] -//@ has "$.index[?(@.name=='Error')].inner.assoc_type" -//@ has "$.index[?(@.name=='Error')].inner.assoc_type.type.resolved_path" -//@ has "$.index[?(@.name=='Error')].inner.assoc_type.type.resolved_path.path" \"Infallible\" +//@ jq_is '[.index[] | select(.name == "Error").inner | has("assoc_type")]' '[true, true]' +//@ jq_has '.index[] | select(.name == "Error").inner.assoc_type.type.resolved_path.path' '"Infallible"' pub struct ForBlanketTryFromImpl; diff --git a/tests/rustdoc-json/enums/discriminant/struct.rs b/tests/rustdoc-json/enums/discriminant/struct.rs index fed0e545798af..cb28b80cc238b 100644 --- a/tests/rustdoc-json/enums/discriminant/struct.rs +++ b/tests/rustdoc-json/enums/discriminant/struct.rs @@ -1,13 +1,17 @@ #[repr(i32)] -//@ is "$.index[?(@.name=='Foo')].attrs[*].repr.int" '"i32"' +//@ jq_is '.index[] | select(.name == "Foo").attrs[0].repr.int' '"i32"' pub enum Foo { - //@ is "$.index[?(@.name=='Struct')].inner.variant.discriminant" null - //@ count "$.index[?(@.name=='Struct')].inner.variant.kind.struct.fields[*]" 0 + //@ jq_set struct = '.index[] | select(.name == "Struct").inner.variant' + //@ jq_is '$struct | has("discriminant")' 'true' + //@ jq_is '$struct.discriminant?' 'null' + //@ jq_count '$struct.kind?.struct.fields[]' 0 Struct {}, - //@ is "$.index[?(@.name=='StructWithDiscr')].inner.variant.discriminant" '{"expr": "42", "value": "42"}' - //@ count "$.index[?(@.name=='StructWithDiscr')].inner.variant.kind.struct.fields[*]" 1 + //@ jq_set struct_with_discr = '.index[] | select(.name == "StructWithDiscr").inner.variant' + //@ jq_is '$struct_with_discr.discriminant?' '{"expr": "42", "value": "42"}' + //@ jq_count '$struct_with_discr.kind?.struct.fields' 1 StructWithDiscr { x: i32 } = 42, - //@ is "$.index[?(@.name=='StructWithHexDiscr')].inner.variant.discriminant" '{"expr": "0x42", "value": "66"}' - //@ count "$.index[?(@.name=='StructWithHexDiscr')].inner.variant.kind.struct.fields[*]" 2 + //@ jq_set struct_with_hex_discr = '.index[] | select(.name == "StructWithHexDiscr").inner.variant' + //@ jq_is '$struct_with_hex_discr.discriminant?' '{"expr": "0x42", "value": "66"}' + //@ jq_count '$struct_with_hex_discr.kind?.struct.fields[]' 2 StructWithHexDiscr { x: i32, y: bool } = 0x42, } diff --git a/tests/rustdoc-json/enums/doc_link_to_foreign_variant.rs b/tests/rustdoc-json/enums/doc_link_to_foreign_variant.rs index 6ecd98fadf5b8..42f5acd0c2521 100644 --- a/tests/rustdoc-json/enums/doc_link_to_foreign_variant.rs +++ b/tests/rustdoc-json/enums/doc_link_to_foreign_variant.rs @@ -5,7 +5,5 @@ extern crate color; use color::Color::Red; -//@ set red = "$.index[?(@.inner.module.is_crate)].links.Red" - -//@ !has "$.index[?(@.name == 'Red')]" -//@ !has "$.index[?(@.name == 'Color')]" +//@ jq_is '.index["\(.root)"].links | has("Red")' true +//@ jq_count '[.index[] | select(.name == "Red" or .name == "Color")][]' 0 diff --git a/tests/rustdoc-json/enums/use_glob.rs b/tests/rustdoc-json/enums/use_glob.rs index 18f21ff090334..388c62de34e0b 100644 --- a/tests/rustdoc-json/enums/use_glob.rs +++ b/tests/rustdoc-json/enums/use_glob.rs @@ -1,15 +1,15 @@ // Regression test for -//@ set Color = "$.index[?(@.name == 'Color')].id" +//@ jq_set color = '.index[] | select(.name == "Color").id' pub enum Color { Red, Green, Blue, } -//@ set use_Color = "$.index[?(@.inner.use)].id" -//@ is "$.index[?(@.inner.use)].inner.use.id" $Color -//@ is "$.index[?(@.inner.use)].inner.use.is_glob" true +//@ jq_set use_color = '.index[] | select(.inner.use).id' +//@ jq_is '.index[] | select(.inner.use).inner.use.id' $color +//@ jq_is '.index[] | select(.inner.use).inner.use.is_glob' true pub use Color::*; -//@ ismany "$.index[?(@.name == 'use_glob')].inner.module.items[*]" $Color $use_Color +//@ jq_ismany '.index[] | select(.name == "use_glob").inner.module.items[]' $color $use_color diff --git a/tests/rustdoc-json/pub_mod_in_private_mod.rs b/tests/rustdoc-json/pub_mod_in_private_mod.rs index 8b31ad0bcfe28..bc5a1df27906b 100644 --- a/tests/rustdoc-json/pub_mod_in_private_mod.rs +++ b/tests/rustdoc-json/pub_mod_in_private_mod.rs @@ -1,6 +1,6 @@ // See https://github.com/rust-lang/rust/issues/101105 -//@ !has "$.index[?(@.name=='nucleus')]" +//@ jq_count '.index[] | select(.name == "nucleus")' 0 mod corpus { pub mod nucleus {} } diff --git a/tests/rustdoc-json/reexport/simple_private.rs b/tests/rustdoc-json/reexport/simple_private.rs index 40be1708dc69d..a31c6fc44a998 100644 --- a/tests/rustdoc-json/reexport/simple_private.rs +++ b/tests/rustdoc-json/reexport/simple_private.rs @@ -1,20 +1,20 @@ //@ edition:2018 -//@ !has "$.index[?(@.name=='inner')]" +//@ jq_count '.index[] | select(.name == "inner")' 0 mod inner { - //@ set pub_id = "$.index[?(@.name=='Public')].id" + //@ jq_set pub_id = '.index[] | select(.name == "Public").id' pub struct Public; } -//@ is "$.index[?(@.inner.use)].inner.use.name" \"Public\" -//@ is "$.index[?(@.inner.use)].inner.use.id" $pub_id -//@ set use_id = "$.index[?(@.inner.use)].id" +//@ jq_is '.index[] | select(.inner.use).inner.use.name' '"Public"' +//@ jq_is '.index[] | select(.inner.use).inner.use.id' $pub_id +//@ jq_set use_id = '.index[] | select(.inner.use).id' pub use inner::Public; -//@ ismany "$.index[?(@.name=='simple_private')].inner.module.items[*]" $use_id +//@ jq_ismany '.index[] | select(.name == "simple_private").inner.module.items[]' $use_id // Test for https://github.com/rust-lang/rust/issues/135309 -//@ has "$.paths[?(@.kind=='module')].path" '["simple_private"]' -//@ !has "$.paths[*].path" '["simple_private", "inner"]' -//@ has "$.paths[?(@.kind=='struct')].path" '["simple_private", "inner", "Public"]' -//@ !has "$.paths[*].path" '["simple_private", "Public"]' +//@ jq_has '.paths[] | select(.kind == "module").path' '["simple_private"]' +//@ !jq_has '.paths[].path' '["simple_private", "inner"]' +//@ jq_has '.paths[] | select(.kind == "struct").path' '["simple_private", "inner", "Public"]' +//@ !jq_has '.paths[].path' '["simple_private", "Public"]' diff --git a/tests/rustdoc-json/type_alias.rs b/tests/rustdoc-json/type_alias.rs index 7fd23a48040d1..007f0863d4e59 100644 --- a/tests/rustdoc-json/type_alias.rs +++ b/tests/rustdoc-json/type_alias.rs @@ -1,15 +1,15 @@ -//@ set IntVec = "$.index[?(@.name=='IntVec')].id" -//@ is "$.index[?(@.name=='IntVec')].visibility" \"public\" -//@ has "$.index[?(@.name=='IntVec')].inner.type_alias" -//@ is "$.index[?(@.name=='IntVec')].span.filename" $FILE +//@ jq_set IntVec = '.index[] | select(.name == "IntVec").id' +//@ jq_is '.index[] | select(.name == "IntVec").visibility' '"public"' +//@ jq_is '.index[] | select(.name == "IntVec").inner | has("type_alias")' true +//@ jq_is '.index[] | select(.name == "IntVec").span.filename' $FILE pub type IntVec = Vec; -//@ is "$.index[?(@.name=='f')].inner.function.sig.output.resolved_path.id" $IntVec +//@ jq_is '.index[] | select(.name == "f").inner.function.sig.output.resolved_path.id' $IntVec pub fn f() -> IntVec { vec![0; 32] } -//@ !is "$.index[?(@.name=='g')].inner.function.sig.output.resolved_path.id" $IntVec +//@ !jq_is '.index[] | select(.name == "g").inner.function.sig.output.resolved_path.id' $IntVec pub fn g() -> Vec { vec![0; 32] } diff --git a/tests/ui/allocator/not-an-allocator.rs b/tests/ui/allocator/not-an-allocator.rs index d5062c9414199..4a538d4d0a0d8 100644 --- a/tests/ui/allocator/not-an-allocator.rs +++ b/tests/ui/allocator/not-an-allocator.rs @@ -1,6 +1,3 @@ -//@ revisions: u w -//@[u] only-unix -//@[w] only-windows #[global_allocator] static A: usize = 0; //~^ ERROR E0277 diff --git a/tests/ui/allocator/not-an-allocator.stderr b/tests/ui/allocator/not-an-allocator.stderr new file mode 100644 index 0000000000000..70d8c166f3502 --- /dev/null +++ b/tests/ui/allocator/not-an-allocator.stderr @@ -0,0 +1,54 @@ +error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied + --> $DIR/not-an-allocator.rs:2:11 + | +LL | #[global_allocator] + | ------------------- in this attribute macro expansion +LL | static A: usize = 0; + | ^^^^^ the nightly-only, unstable trait `GlobalAllocator` is not implemented for `usize` + | +help: the trait `GlobalAllocator` is implemented for `System` + --> $SRC_DIR/std/src/alloc.rs:LL:COL + = note: required for `usize` to implement `GlobalAlloc` + +error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied + --> $DIR/not-an-allocator.rs:2:11 + | +LL | #[global_allocator] + | ------------------- in this attribute macro expansion +LL | static A: usize = 0; + | ^^^^^ the nightly-only, unstable trait `GlobalAllocator` is not implemented for `usize` + | +help: the trait `GlobalAllocator` is implemented for `System` + --> $SRC_DIR/std/src/alloc.rs:LL:COL + = note: required for `usize` to implement `GlobalAlloc` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied + --> $DIR/not-an-allocator.rs:2:11 + | +LL | #[global_allocator] + | ------------------- in this attribute macro expansion +LL | static A: usize = 0; + | ^^^^^ the nightly-only, unstable trait `GlobalAllocator` is not implemented for `usize` + | +help: the trait `GlobalAllocator` is implemented for `System` + --> $SRC_DIR/std/src/alloc.rs:LL:COL + = note: required for `usize` to implement `GlobalAlloc` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied + --> $DIR/not-an-allocator.rs:2:11 + | +LL | #[global_allocator] + | ------------------- in this attribute macro expansion +LL | static A: usize = 0; + | ^^^^^ the nightly-only, unstable trait `GlobalAllocator` is not implemented for `usize` + | +help: the trait `GlobalAllocator` is implemented for `System` + --> $SRC_DIR/std/src/alloc.rs:LL:COL + = note: required for `usize` to implement `GlobalAlloc` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/allocator/not-an-allocator.u.stderr b/tests/ui/allocator/not-an-allocator.u.stderr deleted file mode 100644 index f7400d16b1fd1..0000000000000 --- a/tests/ui/allocator/not-an-allocator.u.stderr +++ /dev/null @@ -1,50 +0,0 @@ -error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied - --> $DIR/not-an-allocator.rs:5:11 - | -LL | #[global_allocator] - | ------------------- in this attribute macro expansion -LL | static A: usize = 0; - | ^^^^^ the trait `GlobalAlloc` is not implemented for `usize` - | -help: the trait `GlobalAlloc` is implemented for `System` - --> $SRC_DIR/std/src/sys/alloc/unix.rs:LL:COL - -error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied - --> $DIR/not-an-allocator.rs:5:11 - | -LL | #[global_allocator] - | ------------------- in this attribute macro expansion -LL | static A: usize = 0; - | ^^^^^ the trait `GlobalAlloc` is not implemented for `usize` - | -help: the trait `GlobalAlloc` is implemented for `System` - --> $SRC_DIR/std/src/sys/alloc/unix.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied - --> $DIR/not-an-allocator.rs:5:11 - | -LL | #[global_allocator] - | ------------------- in this attribute macro expansion -LL | static A: usize = 0; - | ^^^^^ the trait `GlobalAlloc` is not implemented for `usize` - | -help: the trait `GlobalAlloc` is implemented for `System` - --> $SRC_DIR/std/src/sys/alloc/unix.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied - --> $DIR/not-an-allocator.rs:5:11 - | -LL | #[global_allocator] - | ------------------- in this attribute macro expansion -LL | static A: usize = 0; - | ^^^^^ the trait `GlobalAlloc` is not implemented for `usize` - | -help: the trait `GlobalAlloc` is implemented for `System` - --> $SRC_DIR/std/src/sys/alloc/unix.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 4 previous errors - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/allocator/not-an-allocator.w.stderr b/tests/ui/allocator/not-an-allocator.w.stderr deleted file mode 100644 index d86aadc745967..0000000000000 --- a/tests/ui/allocator/not-an-allocator.w.stderr +++ /dev/null @@ -1,50 +0,0 @@ -error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied - --> $DIR/not-an-allocator.rs:5:11 - | -LL | #[global_allocator] - | ------------------- in this attribute macro expansion -LL | static A: usize = 0; - | ^^^^^ the trait `GlobalAlloc` is not implemented for `usize` - | -help: the trait `GlobalAlloc` is implemented for `System` - --> $SRC_DIR/std/src/sys/alloc/windows.rs:LL:COL - -error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied - --> $DIR/not-an-allocator.rs:5:11 - | -LL | #[global_allocator] - | ------------------- in this attribute macro expansion -LL | static A: usize = 0; - | ^^^^^ the trait `GlobalAlloc` is not implemented for `usize` - | -help: the trait `GlobalAlloc` is implemented for `System` - --> $SRC_DIR/std/src/sys/alloc/windows.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied - --> $DIR/not-an-allocator.rs:5:11 - | -LL | #[global_allocator] - | ------------------- in this attribute macro expansion -LL | static A: usize = 0; - | ^^^^^ the trait `GlobalAlloc` is not implemented for `usize` - | -help: the trait `GlobalAlloc` is implemented for `System` - --> $SRC_DIR/std/src/sys/alloc/windows.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied - --> $DIR/not-an-allocator.rs:5:11 - | -LL | #[global_allocator] - | ------------------- in this attribute macro expansion -LL | static A: usize = 0; - | ^^^^^ the trait `GlobalAlloc` is not implemented for `usize` - | -help: the trait `GlobalAlloc` is implemented for `System` - --> $SRC_DIR/std/src/sys/alloc/windows.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 4 previous errors - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-35139.rs b/tests/ui/associated-types/unconstrained-dyn-assoc-type-lifetime.rs similarity index 85% rename from tests/ui/issues/issue-35139.rs rename to tests/ui/associated-types/unconstrained-dyn-assoc-type-lifetime.rs index e462f35437358..bce0a3729a820 100644 --- a/tests/ui/issues/issue-35139.rs +++ b/tests/ui/associated-types/unconstrained-dyn-assoc-type-lifetime.rs @@ -1,3 +1,5 @@ +//! Regression test for . + use std::fmt; pub trait MethodType { diff --git a/tests/ui/issues/issue-35139.stderr b/tests/ui/associated-types/unconstrained-dyn-assoc-type-lifetime.stderr similarity index 89% rename from tests/ui/issues/issue-35139.stderr rename to tests/ui/associated-types/unconstrained-dyn-assoc-type-lifetime.stderr index 4568b9b70f412..73663e85ef37c 100644 --- a/tests/ui/issues/issue-35139.stderr +++ b/tests/ui/associated-types/unconstrained-dyn-assoc-type-lifetime.stderr @@ -1,5 +1,5 @@ error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates - --> $DIR/issue-35139.rs:9:6 + --> $DIR/unconstrained-dyn-assoc-type-lifetime.rs:11:6 | LL | impl<'a> MethodType for MTFn { | ^^ unconstrained lifetime parameter diff --git a/tests/ui/issues/issue-34334.rs b/tests/ui/binding/tuple-binder-on-err-ty.rs similarity index 64% rename from tests/ui/issues/issue-34334.rs rename to tests/ui/binding/tuple-binder-on-err-ty.rs index 51486bc40de0c..3357dd42f4e35 100644 --- a/tests/ui/issues/issue-34334.rs +++ b/tests/ui/binding/tuple-binder-on-err-ty.rs @@ -1,3 +1,6 @@ +//! Regression test for . +//! Test tuple pattern syntax doesn't ICE on erroneous type. + fn main () { let sr: Vec<(u32, _, _) = vec![]; //~^ ERROR expected one of diff --git a/tests/ui/issues/issue-34334.stderr b/tests/ui/binding/tuple-binder-on-err-ty.stderr similarity index 93% rename from tests/ui/issues/issue-34334.stderr rename to tests/ui/binding/tuple-binder-on-err-ty.stderr index 6bf6732311fcf..f8f9cd73035d6 100644 --- a/tests/ui/issues/issue-34334.stderr +++ b/tests/ui/binding/tuple-binder-on-err-ty.stderr @@ -1,5 +1,5 @@ error: expected one of `,`, `:`, or `>`, found `=` - --> $DIR/issue-34334.rs:2:29 + --> $DIR/tuple-binder-on-err-ty.rs:5:29 | LL | let sr: Vec<(u32, _, _) = vec![]; | - ^ expected one of `,`, `:`, or `>` @@ -12,7 +12,7 @@ LL | let sr: Vec<(u32, _, _)> = vec![]; | + error[E0277]: a value of type `Vec<(u32, _, _)>` cannot be built from an iterator over elements of type `()` - --> $DIR/issue-34334.rs:5:87 + --> $DIR/tuple-binder-on-err-ty.rs:8:87 | LL | let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_receiver)| {}).collect(); | ^^^^^^^ value of type `Vec<(u32, _, _)>` cannot be built from `std::iter::Iterator` @@ -22,7 +22,7 @@ help: the trait `FromIterator<()>` is not implemented for `Vec<(u32, _, _)>` --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL = help: for that trait implementation, expected `(u32, _, _)`, found `()` note: the method call chain might not have had the expected associated types - --> $DIR/issue-34334.rs:5:43 + --> $DIR/tuple-binder-on-err-ty.rs:8:43 | LL | let sr: Vec<(u32, _, _) = vec![]; | ------ this expression has type `Vec<(_, _, _)>` diff --git a/tests/ui/issues/issue-36474.rs b/tests/ui/codegen/slice-iter-enumerate-opt.rs similarity index 75% rename from tests/ui/issues/issue-36474.rs rename to tests/ui/codegen/slice-iter-enumerate-opt.rs index ddfa1829e3afc..21cb530953eaf 100644 --- a/tests/ui/issues/issue-36474.rs +++ b/tests/ui/codegen/slice-iter-enumerate-opt.rs @@ -1,4 +1,8 @@ +//! Regression test for . +//! This used to trigger LLVM assertion when compiled with opt level 3. +//@ compile-flags: -Copt-level=3 //@ run-pass + fn main() { remove_axis(&3, 0); } diff --git a/tests/ui/issues/issue-3559.rs b/tests/ui/collections/hashmap/hashmap-debug-format.rs similarity index 81% rename from tests/ui/issues/issue-3559.rs rename to tests/ui/collections/hashmap/hashmap-debug-format.rs index ffb937cf5d253..97e81db94c49c 100644 --- a/tests/ui/issues/issue-3559.rs +++ b/tests/ui/collections/hashmap/hashmap-debug-format.rs @@ -1,4 +1,7 @@ +//! Regression test for . +//! Test hashmap debug format doesn't ICE. //@ run-pass + use std::collections::HashMap; fn check_strs(actual: &str, expected: &str) -> bool { diff --git a/tests/ui/consts/const-eval/volatile.rs b/tests/ui/consts/const-eval/volatile.rs new file mode 100644 index 0000000000000..ded8be1381b4a --- /dev/null +++ b/tests/ui/consts/const-eval/volatile.rs @@ -0,0 +1,16 @@ +//@ check-pass +#![feature(const_volatile)] + +const _READ: () = unsafe { + let x = 42i32; + let y = (&x as *const i32).read_volatile(); + assert!(x == y); +}; + +const _WRITE: () = unsafe { + let mut x = 42i32; + (&mut x as *mut i32).write_volatile(13); + assert!(x == 13); +}; + +fn main() {} diff --git a/tests/ui/derived-errors/no-spurious-unconstrained-param.rs b/tests/ui/derived-errors/no-spurious-unconstrained-param.rs new file mode 100644 index 0000000000000..d56245a6ac83c --- /dev/null +++ b/tests/ui/derived-errors/no-spurious-unconstrained-param.rs @@ -0,0 +1,16 @@ +//! Regression test for . +//! Previously, in addition to the real cause of the problem as seen below, +//! the compiler would tell the user: +//! +//! ``` +//! error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or +//! predicates +//! ``` +//! +//! With this test, we check that only the relevant error is emitted. + +trait Foo {} + +impl Foo for Bar {} //~ ERROR cannot find type `Bar` in this scope + +fn main() {} diff --git a/tests/ui/issues/issue-36836.stderr b/tests/ui/derived-errors/no-spurious-unconstrained-param.stderr similarity index 82% rename from tests/ui/issues/issue-36836.stderr rename to tests/ui/derived-errors/no-spurious-unconstrained-param.stderr index 2d9a97df90520..0dde8afbc1c00 100644 --- a/tests/ui/issues/issue-36836.stderr +++ b/tests/ui/derived-errors/no-spurious-unconstrained-param.stderr @@ -1,5 +1,5 @@ error[E0425]: cannot find type `Bar` in this scope - --> $DIR/issue-36836.rs:13:17 + --> $DIR/no-spurious-unconstrained-param.rs:14:17 | LL | impl Foo for Bar {} | ^^^ not found in this scope diff --git a/tests/ui/errors/error-count.rs b/tests/ui/errors/error-count.rs new file mode 100644 index 0000000000000..08eb56bc2040d --- /dev/null +++ b/tests/ui/errors/error-count.rs @@ -0,0 +1,9 @@ +//! Regression test for . +//! Test rustc emits right error count. +//! (this used to return `aborting due to 2 previous errors`) + +fn main() { + a; //~ ERROR cannot find value `a` + "".lorem; //~ ERROR no field + "".ipsum; //~ ERROR no field +} diff --git a/tests/ui/issues/issue-33525.stderr b/tests/ui/errors/error-count.stderr similarity index 84% rename from tests/ui/issues/issue-33525.stderr rename to tests/ui/errors/error-count.stderr index ee9f4d4c3016d..e53c2c5882c47 100644 --- a/tests/ui/issues/issue-33525.stderr +++ b/tests/ui/errors/error-count.stderr @@ -1,17 +1,17 @@ error[E0425]: cannot find value `a` in this scope - --> $DIR/issue-33525.rs:2:5 + --> $DIR/error-count.rs:6:5 | LL | a; | ^ not found in this scope error[E0609]: no field `lorem` on type `&'static str` - --> $DIR/issue-33525.rs:3:8 + --> $DIR/error-count.rs:7:8 | LL | "".lorem; | ^^^^^ unknown field error[E0609]: no field `ipsum` on type `&'static str` - --> $DIR/issue-33525.rs:4:8 + --> $DIR/error-count.rs:8:8 | LL | "".ipsum; | ^^^^^ unknown field diff --git a/tests/ui/issues/issue-34373.rs b/tests/ui/generics/cyclic-default-type-param-via-alias.rs similarity index 64% rename from tests/ui/issues/issue-34373.rs rename to tests/ui/generics/cyclic-default-type-param-via-alias.rs index 02e1048e5a330..ae83dfc7c6f74 100644 --- a/tests/ui/issues/issue-34373.rs +++ b/tests/ui/generics/cyclic-default-type-param-via-alias.rs @@ -1,3 +1,6 @@ +//! Regression test for . +//! Test cyclic default type param through alias doesn't ICE. + #![allow(warnings)] //@ ignore-parallel-frontend query cycle trait Trait { diff --git a/tests/ui/issues/issue-34373.stderr b/tests/ui/generics/cyclic-default-type-param-via-alias.stderr similarity index 82% rename from tests/ui/issues/issue-34373.stderr rename to tests/ui/generics/cyclic-default-type-param-via-alias.stderr index 9f85e4d5e5a93..4d05d45286529 100644 --- a/tests/ui/issues/issue-34373.stderr +++ b/tests/ui/generics/cyclic-default-type-param-via-alias.stderr @@ -1,17 +1,17 @@ error[E0391]: cycle detected when computing type of `Foo::T` - --> $DIR/issue-34373.rs:7:34 + --> $DIR/cyclic-default-type-param-via-alias.rs:10:34 | LL | pub struct Foo>>; | ^^^^^^^^^^ | note: ...which requires expanding type alias `DefaultFoo`... - --> $DIR/issue-34373.rs:9:19 + --> $DIR/cyclic-default-type-param-via-alias.rs:12:19 | LL | type DefaultFoo = Foo; | ^^^ = note: ...which again requires computing type of `Foo::T`, completing the cycle note: cycle used when checking that `Foo` is well-formed - --> $DIR/issue-34373.rs:7:1 + --> $DIR/cyclic-default-type-param-via-alias.rs:10:1 | LL | pub struct Foo>>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/issues/issue-36299.rs b/tests/ui/generics/unused-type-and-lifetime-param.rs similarity index 54% rename from tests/ui/issues/issue-36299.rs rename to tests/ui/generics/unused-type-and-lifetime-param.rs index 7b68420b71cb2..0ad7b087ceeee 100644 --- a/tests/ui/issues/issue-36299.rs +++ b/tests/ui/generics/unused-type-and-lifetime-param.rs @@ -1,3 +1,6 @@ +//! Regression test for . +//! This used to ICE. + struct Foo<'a, A> {} //~^ ERROR parameter `'a` is never used //~| ERROR parameter `A` is never used diff --git a/tests/ui/issues/issue-36299.stderr b/tests/ui/generics/unused-type-and-lifetime-param.stderr similarity index 86% rename from tests/ui/issues/issue-36299.stderr rename to tests/ui/generics/unused-type-and-lifetime-param.stderr index 29e8d7ca59a24..d21c44ec1fc87 100644 --- a/tests/ui/issues/issue-36299.stderr +++ b/tests/ui/generics/unused-type-and-lifetime-param.stderr @@ -1,5 +1,5 @@ error[E0392]: lifetime parameter `'a` is never used - --> $DIR/issue-36299.rs:1:12 + --> $DIR/unused-type-and-lifetime-param.rs:4:12 | LL | struct Foo<'a, A> {} | ^^ unused lifetime parameter @@ -7,7 +7,7 @@ LL | struct Foo<'a, A> {} = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` error[E0392]: type parameter `A` is never used - --> $DIR/issue-36299.rs:1:16 + --> $DIR/unused-type-and-lifetime-param.rs:4:16 | LL | struct Foo<'a, A> {} | ^ unused type parameter diff --git a/tests/ui/issues/issue-35570.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/assoc-type-projection-in-dyn-and-fn.rs similarity index 74% rename from tests/ui/issues/issue-35570.rs rename to tests/ui/higher-ranked/trait-bounds/normalize-under-binder/assoc-type-projection-in-dyn-and-fn.rs index a2b0222d4f395..da83fe0a7ba04 100644 --- a/tests/ui/issues/issue-35570.rs +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/assoc-type-projection-in-dyn-and-fn.rs @@ -1,3 +1,7 @@ +//! Regression test for . +//! Test associated type projection under `for<'a>` binder in the return +//! type of fn parameter and inside trait object doesn't ICE. + use std::mem; trait Trait1 {} diff --git a/tests/ui/issues/issue-35570.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/assoc-type-projection-in-dyn-and-fn.stderr similarity index 80% rename from tests/ui/issues/issue-35570.stderr rename to tests/ui/higher-ranked/trait-bounds/normalize-under-binder/assoc-type-projection-in-dyn-and-fn.stderr index b39b15fdf4b10..2aeca47b2ebb9 100644 --- a/tests/ui/issues/issue-35570.stderr +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/assoc-type-projection-in-dyn-and-fn.stderr @@ -1,23 +1,23 @@ error[E0277]: the trait bound `for<'a> (): Trait2<'a>` is not satisfied - --> $DIR/issue-35570.rs:8:40 + --> $DIR/assoc-type-projection-in-dyn-and-fn.rs:12:40 | LL | fn _ice(param: Box Trait1<<() as Trait2<'a>>::Ty>>) { | ^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> Trait2<'a>` is not implemented for `()` | help: this trait has no implementations, consider adding one - --> $DIR/issue-35570.rs:4:1 + --> $DIR/assoc-type-projection-in-dyn-and-fn.rs:8:1 | LL | trait Trait2<'a> { | ^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `for<'a> (): Trait2<'a>` is not satisfied - --> $DIR/issue-35570.rs:8:16 + --> $DIR/assoc-type-projection-in-dyn-and-fn.rs:12:16 | LL | fn _ice(param: Box Trait1<<() as Trait2<'a>>::Ty>>) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> Trait2<'a>` is not implemented for `()` | help: this trait has no implementations, consider adding one - --> $DIR/issue-35570.rs:4:1 + --> $DIR/assoc-type-projection-in-dyn-and-fn.rs:8:1 | LL | trait Trait2<'a> { | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/issues/issue-33504.rs b/tests/ui/issues/issue-33504.rs deleted file mode 100644 index 89cc06ede5e48..0000000000000 --- a/tests/ui/issues/issue-33504.rs +++ /dev/null @@ -1,9 +0,0 @@ -// Shadowing a unit-like enum in a closure - -struct Test; - -fn main() { - || { - let Test = 1; //~ ERROR mismatched types - }; -} diff --git a/tests/ui/issues/issue-33525.rs b/tests/ui/issues/issue-33525.rs deleted file mode 100644 index 74f21eff20f69..0000000000000 --- a/tests/ui/issues/issue-33525.rs +++ /dev/null @@ -1,5 +0,0 @@ -fn main() { - a; //~ ERROR cannot find value `a` - "".lorem; //~ ERROR no field - "".ipsum; //~ ERROR no field -} diff --git a/tests/ui/issues/issue-34751.rs b/tests/ui/issues/issue-34751.rs deleted file mode 100644 index 1e842049b14c1..0000000000000 --- a/tests/ui/issues/issue-34751.rs +++ /dev/null @@ -1,11 +0,0 @@ -//@ check-pass -#![allow(dead_code)] -// #34751 ICE: 'rustc' panicked at 'assertion failed: !substs.has_regions_escaping_depth(0)' - -#[allow(dead_code)] - -use std::marker::PhantomData; - -fn f<'a>(PhantomData::<&'a u8>: PhantomData<&'a u8>) {} - -fn main() {} diff --git a/tests/ui/issues/issue-36816.rs b/tests/ui/issues/issue-36816.rs deleted file mode 100644 index d15a9c7abe15b..0000000000000 --- a/tests/ui/issues/issue-36816.rs +++ /dev/null @@ -1,7 +0,0 @@ -//@ run-pass -macro_rules! m { () => { 1 } } -macro_rules! n { () => { 1 + m!() } } - -fn main() { - let _: [u32; n!()] = [0, 0]; -} diff --git a/tests/ui/issues/issue-36836.rs b/tests/ui/issues/issue-36836.rs deleted file mode 100644 index 99c56213153e4..0000000000000 --- a/tests/ui/issues/issue-36836.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Previously, in addition to the real cause of the problem as seen below, -// the compiler would tell the user: -// -// ``` -// error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or -// predicates -// ``` -// -// With this test, we check that only the relevant error is emitted. - -trait Foo {} - -impl Foo for Bar {} //~ ERROR cannot find type `Bar` in this scope - -fn main() {} diff --git a/tests/ui/issues/issue-33941.next.stderr b/tests/ui/iterators/cloned-hashmap-iter-type-mismatch-diag.current.stderr similarity index 88% rename from tests/ui/issues/issue-33941.next.stderr rename to tests/ui/iterators/cloned-hashmap-iter-type-mismatch-diag.current.stderr index d653bbd327427..9ceacdc7bfbdd 100644 --- a/tests/ui/issues/issue-33941.next.stderr +++ b/tests/ui/iterators/cloned-hashmap-iter-type-mismatch-diag.current.stderr @@ -1,5 +1,5 @@ error[E0271]: expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)` - --> $DIR/issue-33941.rs:9:36 + --> $DIR/cloned-hashmap-iter-type-mismatch-diag.rs:12:36 | LL | for _ in HashMap::new().iter().cloned() {} | ^^^^^^ expected `&_`, found `(&_, &_)` @@ -7,7 +7,7 @@ LL | for _ in HashMap::new().iter().cloned() {} = note: expected reference `&_` found tuple `(&_, &_)` note: the method call chain might not have had the expected associated types - --> $DIR/issue-33941.rs:9:29 + --> $DIR/cloned-hashmap-iter-type-mismatch-diag.rs:12:29 | LL | for _ in HashMap::new().iter().cloned() {} | -------------- ^^^^^^ `Iterator::Item` is `(&_, &_)` here @@ -17,7 +17,7 @@ note: required by a bound in `cloned` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL error[E0271]: expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)` - --> $DIR/issue-33941.rs:9:14 + --> $DIR/cloned-hashmap-iter-type-mismatch-diag.rs:12:14 | LL | for _ in HashMap::new().iter().cloned() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&_`, found `(&_, &_)` diff --git a/tests/ui/issues/issue-33941.current.stderr b/tests/ui/iterators/cloned-hashmap-iter-type-mismatch-diag.next.stderr similarity index 88% rename from tests/ui/issues/issue-33941.current.stderr rename to tests/ui/iterators/cloned-hashmap-iter-type-mismatch-diag.next.stderr index d653bbd327427..9ceacdc7bfbdd 100644 --- a/tests/ui/issues/issue-33941.current.stderr +++ b/tests/ui/iterators/cloned-hashmap-iter-type-mismatch-diag.next.stderr @@ -1,5 +1,5 @@ error[E0271]: expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)` - --> $DIR/issue-33941.rs:9:36 + --> $DIR/cloned-hashmap-iter-type-mismatch-diag.rs:12:36 | LL | for _ in HashMap::new().iter().cloned() {} | ^^^^^^ expected `&_`, found `(&_, &_)` @@ -7,7 +7,7 @@ LL | for _ in HashMap::new().iter().cloned() {} = note: expected reference `&_` found tuple `(&_, &_)` note: the method call chain might not have had the expected associated types - --> $DIR/issue-33941.rs:9:29 + --> $DIR/cloned-hashmap-iter-type-mismatch-diag.rs:12:29 | LL | for _ in HashMap::new().iter().cloned() {} | -------------- ^^^^^^ `Iterator::Item` is `(&_, &_)` here @@ -17,7 +17,7 @@ note: required by a bound in `cloned` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL error[E0271]: expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)` - --> $DIR/issue-33941.rs:9:14 + --> $DIR/cloned-hashmap-iter-type-mismatch-diag.rs:12:14 | LL | for _ in HashMap::new().iter().cloned() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&_`, found `(&_, &_)` diff --git a/tests/ui/issues/issue-33941.rs b/tests/ui/iterators/cloned-hashmap-iter-type-mismatch-diag.rs similarity index 77% rename from tests/ui/issues/issue-33941.rs rename to tests/ui/iterators/cloned-hashmap-iter-type-mismatch-diag.rs index e49efc3bfd496..de402fbb7fba5 100644 --- a/tests/ui/issues/issue-33941.rs +++ b/tests/ui/iterators/cloned-hashmap-iter-type-mismatch-diag.rs @@ -1,3 +1,6 @@ +//! Regression test for . +//! Test iterator type mismatch prints pretty error message. +//! This used to emit many duplicated, unhelpful error messages. //@ revisions: current next //@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver diff --git a/tests/ui/lifetimes/lifetime-in-unit-struct-pattern.rs b/tests/ui/lifetimes/lifetime-in-unit-struct-pattern.rs new file mode 100644 index 0000000000000..b9eebc8dac0f2 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-in-unit-struct-pattern.rs @@ -0,0 +1,12 @@ +//! Regression test for . +//! This used to ICE with +//! `assertion failed: !substs.has_regions_escaping_depth(0)`. +//@ check-pass + +#![allow(dead_code)] + +use std::marker::PhantomData; + +fn f<'a>(PhantomData::<&'a u8>: PhantomData<&'a u8>) {} + +fn main() {} diff --git a/tests/ui/issues/issue-36744-bitcast-args-if-needed.rs b/tests/ui/lifetimes/lifetime-param-in-fn-coercion.rs similarity index 55% rename from tests/ui/issues/issue-36744-bitcast-args-if-needed.rs rename to tests/ui/lifetimes/lifetime-param-in-fn-coercion.rs index 8fcd0c3f41c9a..7f8af7e6b49d4 100644 --- a/tests/ui/issues/issue-36744-bitcast-args-if-needed.rs +++ b/tests/ui/lifetimes/lifetime-param-in-fn-coercion.rs @@ -1,7 +1,8 @@ +//! Regression test for . +//! This tests for an ICE (and, if ignored, subsequent LLVM abort) when +//! a lifetime-parametric fn is passed into a context whose expected +//! type has a differing lifetime parameterization. //@ run-pass -// This tests for an ICE (and, if ignored, subsequent LLVM abort) when -// a lifetime-parametric fn is passed into a context whose expected -// type has a differing lifetime parameterization. struct A<'a> { _a: &'a i32, diff --git a/tests/ui/lint/non-local-defs/consts.stderr b/tests/ui/lint/non-local-defs/consts.stderr index 077837f4a6b27..fc5ce85ac613f 100644 --- a/tests/ui/lint/non-local-defs/consts.stderr +++ b/tests/ui/lint/non-local-defs/consts.stderr @@ -71,7 +71,7 @@ LL | | fn hoo() {} ... | LL | | 1 LL | | }; - | |_____- move the `impl` block outside of this inline constant `` and up 2 bodies + | |_____- move the `impl` block outside of this constant expression `` and up 2 bodies | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` diff --git a/tests/ui/macros/macro-in-array-len-expr.rs b/tests/ui/macros/macro-in-array-len-expr.rs new file mode 100644 index 0000000000000..272ee7f90cecc --- /dev/null +++ b/tests/ui/macros/macro-in-array-len-expr.rs @@ -0,0 +1,10 @@ +//! Regression test for . +//! Macro invocation in len position in arrays used to ICE. +//@ run-pass + +macro_rules! m { () => { 1 } } +macro_rules! n { () => { 1 + m!() } } + +fn main() { + let _: [u32; n!()] = [0, 0]; +} diff --git a/tests/ui/issues/issue-3574.rs b/tests/ui/match/match-borrowed-str.rs similarity index 60% rename from tests/ui/issues/issue-3574.rs rename to tests/ui/match/match-borrowed-str.rs index 36c1e2ad93ee8..48597ed2c18f1 100644 --- a/tests/ui/issues/issue-3574.rs +++ b/tests/ui/match/match-borrowed-str.rs @@ -1,6 +1,6 @@ +//! Regression test for . +//! Test pattern-matching on `&str` doesn't ICE. //@ run-pass -// rustc --test match_borrowed_str.rs.rs && ./match_borrowed_str.rs - fn compare(x: &str, y: &str) -> bool { match x { diff --git a/tests/ui/issues/issue-35423.rs b/tests/ui/match/range-arm-and-ref-arm.rs similarity index 70% rename from tests/ui/issues/issue-35423.rs rename to tests/ui/match/range-arm-and-ref-arm.rs index c43d35fea7837..d5a797aa1aaeb 100644 --- a/tests/ui/issues/issue-35423.rs +++ b/tests/ui/match/range-arm-and-ref-arm.rs @@ -1,4 +1,7 @@ +//! Regression test for . +//! This used to ICE. //@ run-pass + fn main () { let x = 4; match x { diff --git a/tests/ui/shadowed/shadow-unit-struct-in-closure.rs b/tests/ui/shadowed/shadow-unit-struct-in-closure.rs new file mode 100644 index 0000000000000..355c5f3c9f8d7 --- /dev/null +++ b/tests/ui/shadowed/shadow-unit-struct-in-closure.rs @@ -0,0 +1,10 @@ +//! Regression test for . +//! Test shadowing a unit-like struct in a closure doesn't cause ICE. + +struct Test; + +fn main() { + || { + let Test = 1; //~ ERROR mismatched types + }; +} diff --git a/tests/ui/issues/issue-33504.stderr b/tests/ui/shadowed/shadow-unit-struct-in-closure.stderr similarity index 91% rename from tests/ui/issues/issue-33504.stderr rename to tests/ui/shadowed/shadow-unit-struct-in-closure.stderr index e5a2eea751d0e..44845135c1deb 100644 --- a/tests/ui/issues/issue-33504.stderr +++ b/tests/ui/shadowed/shadow-unit-struct-in-closure.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/issue-33504.rs:7:13 + --> $DIR/shadow-unit-struct-in-closure.rs:8:13 | LL | struct Test; | ----------- unit struct defined here diff --git a/tests/ui/issues/issue-3447.rs b/tests/ui/structs-enums/generic-recursive-list-struct.rs similarity index 84% rename from tests/ui/issues/issue-3447.rs rename to tests/ui/structs-enums/generic-recursive-list-struct.rs index ab844b0bb9061..f91cffecaa675 100644 --- a/tests/ui/issues/issue-3447.rs +++ b/tests/ui/structs-enums/generic-recursive-list-struct.rs @@ -1,4 +1,7 @@ +//! Regression test for . +//! This used to overflow stack. //@ run-pass + #![allow(dead_code)] #![allow(non_snake_case)] #![allow(non_camel_case_types)] diff --git a/tests/ui/issues/issue-35976.rs b/tests/ui/suggestions/trait-object-import-suggestion-on-method.rs similarity index 73% rename from tests/ui/issues/issue-35976.rs rename to tests/ui/suggestions/trait-object-import-suggestion-on-method.rs index 03d4a187f5557..d3600188e822d 100644 --- a/tests/ui/issues/issue-35976.rs +++ b/tests/ui/suggestions/trait-object-import-suggestion-on-method.rs @@ -1,3 +1,6 @@ +//! Regression test for . +//! This used to emit spurious `Sized` bound unsatisfied error when trait +//! was not imported, instead of suggestion to import it. //@ edition:2015 //@ revisions: imported unimported //@[imported] check-pass diff --git a/tests/ui/issues/issue-35976.unimported.stderr b/tests/ui/suggestions/trait-object-import-suggestion-on-method.unimported.stderr similarity index 87% rename from tests/ui/issues/issue-35976.unimported.stderr rename to tests/ui/suggestions/trait-object-import-suggestion-on-method.unimported.stderr index db2973d902efb..5f5e4b7f47294 100644 --- a/tests/ui/issues/issue-35976.unimported.stderr +++ b/tests/ui/suggestions/trait-object-import-suggestion-on-method.unimported.stderr @@ -1,5 +1,5 @@ error: the `wait` method cannot be invoked on a trait object - --> $DIR/issue-35976.rs:21:9 + --> $DIR/trait-object-import-suggestion-on-method.rs:24:9 | LL | fn wait(&self) where Self: Sized; | ----- this has a `Sized` requirement diff --git a/tests/ui/issues/issue-33770.rs b/tests/ui/threads-sendsync/no-double-lock-same-thread.rs similarity index 84% rename from tests/ui/issues/issue-33770.rs rename to tests/ui/threads-sendsync/no-double-lock-same-thread.rs index 814e8f371765e..278ff0242950e 100644 --- a/tests/ui/issues/issue-33770.rs +++ b/tests/ui/threads-sendsync/no-double-lock-same-thread.rs @@ -1,3 +1,13 @@ +//! Regression test for . +//! Ensure both `Mutex` and `RwLock` cannot be locked twice on same +//! thread. +//! +//! This was possible as mutexes were initialized with `PTHREAD_MUTEX_DEFAULT` +//! for which attempt to relock from the same thread is considered undefined +//! behaviour, and during glibc's lock-elision transaction lock appeared +//! unlocked, which allowed to lock it again from the same thread. +//! +//! This resulted in ability to aquire 2 mutable references at the same time. //@ run-pass //@ needs-subprocess diff --git a/tests/ui/traits/next-solver/opaques/dont-ice-replacing-non-rigid-opaque.rs b/tests/ui/traits/next-solver/opaques/dont-ice-replacing-non-rigid-opaque.rs new file mode 100644 index 0000000000000..69c53efa14c5c --- /dev/null +++ b/tests/ui/traits/next-solver/opaques/dont-ice-replacing-non-rigid-opaque.rs @@ -0,0 +1,25 @@ +//@ compile-flags: -Znext-solver +//@ check-pass + +// Regression test for #158784 +// +// We should assert that only opaque types that is to be replaced +// are non-rigid. We can have rigid opaque types elsewhere. + +#![feature(type_alias_impl_trait)] +type Rigid = impl Sized; +#[define_opaque(Rigid)] +fn define_rigid() -> Rigid {} + +type MyIter = impl Iterator; + +#[define_opaque(MyIter)] +fn define_my_iter(a: T) -> MyIter { + if false { + // `Rigid` being rigid is totally fine here. + let _: MyIter = std::iter::once(define_rigid()); + } + std::iter::once(a) +} + +fn main() {} diff --git a/tests/ui/issues/issue-34503.rs b/tests/ui/where-clauses/obligation-error-propagation.rs similarity index 59% rename from tests/ui/issues/issue-34503.rs rename to tests/ui/where-clauses/obligation-error-propagation.rs index 68d84bae3d859..501d89e6162d4 100644 --- a/tests/ui/issues/issue-34503.rs +++ b/tests/ui/where-clauses/obligation-error-propagation.rs @@ -1,4 +1,8 @@ +//! Regression test for . +//! `(T, Option)` falsly marked Option as proved when T failed, +//! this made use of invalid Option bound possible anywhere. //@ run-pass + fn main() { struct X; trait Foo { diff --git a/tests/ui/issues/issue-34503.stderr b/tests/ui/where-clauses/obligation-error-propagation.stderr similarity index 88% rename from tests/ui/issues/issue-34503.stderr rename to tests/ui/where-clauses/obligation-error-propagation.stderr index 1877e20bbc14d..a796002caf951 100644 --- a/tests/ui/issues/issue-34503.stderr +++ b/tests/ui/where-clauses/obligation-error-propagation.stderr @@ -1,5 +1,5 @@ warning: methods `foo` and `bar` are never used - --> $DIR/issue-34503.rs:5:12 + --> $DIR/obligation-error-propagation.rs:9:12 | LL | trait Foo { | --- methods in this trait