diff --git a/compiler/rustc/Cargo.toml b/compiler/rustc/Cargo.toml index 8cef9e0644bb0..e3e94e440f694 100644 --- a/compiler/rustc/Cargo.toml +++ b/compiler/rustc/Cargo.toml @@ -37,7 +37,6 @@ features = ['override_allocator_on_supported_platforms'] check_only = ['rustc_driver_impl/check_only'] jemalloc = ['dep:tikv-jemalloc-sys'] llvm = ['rustc_driver_impl/llvm'] -llvm_enzyme = ['rustc_driver_impl/llvm_enzyme'] llvm_offload = ['rustc_driver_impl/llvm_offload'] max_level_info = ['rustc_driver_impl/max_level_info'] rustc_randomized_layouts = ['rustc_driver_impl/rustc_randomized_layouts'] diff --git a/compiler/rustc_builtin_macros/Cargo.toml b/compiler/rustc_builtin_macros/Cargo.toml index 624f4ffea6ffc..8f265bad9728e 100644 --- a/compiler/rustc_builtin_macros/Cargo.toml +++ b/compiler/rustc_builtin_macros/Cargo.toml @@ -35,5 +35,4 @@ tracing = "0.1" [features] # tidy-alphabetical-start -llvm_enzyme = [] # tidy-alphabetical-end diff --git a/compiler/rustc_codegen_llvm/Cargo.toml b/compiler/rustc_codegen_llvm/Cargo.toml index c42ad17498136..8beb69f7b37d1 100644 --- a/compiler/rustc_codegen_llvm/Cargo.toml +++ b/compiler/rustc_codegen_llvm/Cargo.toml @@ -43,7 +43,6 @@ tracing = "0.1" [features] # tidy-alphabetical-start check_only = ["rustc_llvm/check_only"] -llvm_enzyme = [] llvm_offload = [] # tidy-alphabetical-end diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs index b2d22876c1858..70d48def59e91 100644 --- a/compiler/rustc_codegen_llvm/src/back/lto.rs +++ b/compiler/rustc_codegen_llvm/src/back/lto.rs @@ -617,7 +617,7 @@ pub(crate) fn run_pass_manager( ); } - if cfg!(feature = "llvm_enzyme") && enable_ad && !thin { + if enable_ad && !thin { let opt_stage = llvm::OptStage::FatLTO; let stage = write::AutodiffStage::PostAD; if !config.autodiff.contains(&config::AutoDiff::NoPostopt) diff --git a/compiler/rustc_codegen_llvm/src/typetree.rs b/compiler/rustc_codegen_llvm/src/typetree.rs index 7c2e09227e46b..9988ccfaee052 100644 --- a/compiler/rustc_codegen_llvm/src/typetree.rs +++ b/compiler/rustc_codegen_llvm/src/typetree.rs @@ -75,15 +75,9 @@ enum TTLocation { Callsite, } -#[cfg_attr(not(feature = "llvm_enzyme"), allow(unused))] pub(crate) fn add_tt<'tcx, 'll>(cx: &FullCx<'ll, 'tcx>, fn_def: &'ll Value, tt: FncTree) { - // TypeTree processing uses functions from Enzyme, which we might not have available if we did - // not build this compiler with `llvm_enzyme`. This feature is not strictly necessary, but - // skipping this function increases the chance that Enzyme fails to compile some code. - // FIXME(autodiff): In the future we should conditionally run this function even without the - // `llvm_enzyme` feature, in case that libEnzyme was provided via rustup. - #[cfg(not(feature = "llvm_enzyme"))] - return; + // TypeTree processing uses functions from Enzyme. This feature is not strictly necessary, + // but skipping this function increases the chance that Enzyme fails to compile some code. let tcx = cx.tcx; if !tcx.sess.opts.unstable_opts.autodiff.contains(&rustc_session::config::AutoDiff::Enable) { diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml index aeb2063e76960..c7d3e4fae3fc5 100644 --- a/compiler/rustc_driver_impl/Cargo.toml +++ b/compiler/rustc_driver_impl/Cargo.toml @@ -58,7 +58,6 @@ ctrlc = "3.4.4" # tidy-alphabetical-start check_only = ['rustc_interface/check_only'] llvm = ['rustc_interface/llvm'] -llvm_enzyme = ['rustc_interface/llvm_enzyme'] llvm_offload = ['rustc_interface/llvm_offload'] max_level_info = ['rustc_log/max_level_info'] rustc_randomized_layouts = [ diff --git a/compiler/rustc_interface/Cargo.toml b/compiler/rustc_interface/Cargo.toml index 9c115736a3d4f..4a272867046b4 100644 --- a/compiler/rustc_interface/Cargo.toml +++ b/compiler/rustc_interface/Cargo.toml @@ -57,6 +57,5 @@ rustc_abi = { path = "../rustc_abi" } # tidy-alphabetical-start check_only = ['rustc_codegen_llvm?/check_only'] llvm = ['dep:rustc_codegen_llvm'] -llvm_enzyme = ['rustc_builtin_macros/llvm_enzyme', 'rustc_codegen_llvm/llvm_enzyme'] llvm_offload = ['rustc_codegen_llvm/llvm_offload'] # tidy-alphabetical-end diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 22b643e74e582..4aa9f4d2eb1b0 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -828,6 +828,7 @@ fn test_unstable_options_tracking_hash() { tracked!(function_sections, Some(false)); tracked!(hint_mostly_unused, true); tracked!(human_readable_cgu_names, true); + tracked!(implicit_sysroot_deps, false); tracked!(incremental_ignore_spans, true); tracked!(indirect_branch_cs_prefix, true); tracked!(inline_mir, Some(true)); diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs index f55ceb6ffa6f2..350718b4f077a 100644 --- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs +++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs @@ -129,34 +129,8 @@ fn encode_const<'tcx>( // Element type s.push_str(&encode_ty(tcx, cv.ty, dict, options)); - // The only allowed types of const values are bool, u8, u16, u32, - // u64, u128, usize i8, i16, i32, i64, i128, isize, and char. The - // bool value false is encoded as 0 and true as 1. - match cv.ty.kind() { - ty::Int(ity) => { - let bits = cv - .try_to_bits(tcx, ty::TypingEnv::fully_monomorphized()) - .expect("expected monomorphic const in cfi"); - let val = Integer::from_int_ty(&tcx, *ity).size().sign_extend(bits) as i128; - if val < 0 { - s.push('n'); - } - let _ = write!(s, "{val}"); - } - ty::Uint(_) => { - let val = cv - .try_to_bits(tcx, ty::TypingEnv::fully_monomorphized()) - .expect("expected monomorphic const in cfi"); - let _ = write!(s, "{val}"); - } - ty::Bool => { - let val = cv.try_to_bool().expect("expected monomorphic const in cfi"); - let _ = write!(s, "{val}"); - } - _ => { - bug!("encode_const: unexpected type `{:?}`", cv.ty); - } - } + // Element value + s.push_str(&encode_const_value(tcx, cv, dict, options)); } _ => { @@ -172,6 +146,127 @@ fn encode_const<'tcx>( s } +/// Encodes a const value using the Itanium C++ ABI as the element value of a literal argument (see +/// ). +fn encode_const_value<'tcx>( + tcx: TyCtxt<'tcx>, + cv: ty::Value<'tcx>, + dict: &mut FxHashMap, usize>, + options: EncodeTyOptions, +) -> String { + let mut s = String::new(); + + match cv.ty.kind() { + // Primitive types + + // The bool value false is encoded as 0 and true as 1. + ty::Bool => { + let val = cv.try_to_bool().expect("expected monomorphic const in cfi"); + s.push(if val { '1' } else { '0' }); + } + + // Integer values are encoded as their decimal values, with negative values preceded by n. + ty::Int(ity) => { + let bits = cv + .try_to_bits(tcx, ty::TypingEnv::fully_monomorphized()) + .expect("expected monomorphic const in cfi"); + let val = Integer::from_int_ty(&tcx, *ity).size().sign_extend(bits) as i128; + if val < 0 { + s.push('n'); + } + let _ = write!(s, "{}", val.unsigned_abs()); + } + + ty::Uint(..) => { + let val = cv + .try_to_bits(tcx, ty::TypingEnv::fully_monomorphized()) + .expect("expected monomorphic const in cfi"); + let _ = write!(s, "{val}"); + } + + // char values are encoded as their Unicode scalar values (i.e., as their decimal u32 + // values). + ty::Char => { + let val = cv + .try_to_bits(tcx, ty::TypingEnv::fully_monomorphized()) + .expect("expected monomorphic const in cfi"); + let _ = write!(s, "{val}"); + } + + // str values are encoded as their UTF-8 encodings in hexadecimal. + ty::Str => { + // Hide the str type behind a reference for try_to_raw_bytes (i.e., the valtree of a + // str value is the valtree of its reference). + let ref_ty = Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, cv.ty); + let cv = ty::Value { ty: ref_ty, valtree: cv.valtree }; + let bytes = cv.try_to_raw_bytes(tcx).expect("expected monomorphic const in cfi"); + for byte in bytes { + let _ = write!(s, "{byte:02x}"); + } + } + + // Sequence types + // Array, slice, and tuple values are encoded as their element values as literal arguments. + ty::Array(..) | ty::Slice(..) | ty::Tuple(..) => { + for field in cv.to_branch() { + let ty::ConstKind::Value(field_cv) = field.kind() else { + bug!("encode_const_value: unexpected kind `{:?}`", field.kind()); + }; + s.push_str(&encode_const(tcx, *field, field_cv.ty, dict, options)); + } + } + + // User-defined types + // Struct and enum values are encoded as their field values as literal arguments, preceded + // by V for enum values. + ty::Adt(adt_def, ..) => { + let contents = cv.destructure_adt_const(); + if adt_def.is_enum() { + let _ = write!(s, "V{}", contents.variant.as_u32()); + } + for field in contents.fields { + let ty::ConstKind::Value(field_cv) = field.kind() else { + bug!("encode_const_value: unexpected kind `{:?}`", field.kind()); + }; + s.push_str(&encode_const(tcx, *field, field_cv.ty, dict, options)); + } + } + + // Pointer types + // Reference values are encoded as the values of their referents (i.e., the valtree of a + // reference value is the valtree of its referent). + ty::Ref(_, ty0, ..) => { + let cv = ty::Value { ty: *ty0, valtree: cv.valtree }; + s.push_str(&encode_const_value(tcx, cv, dict, options)); + } + + // Unexpected types + ty::Float(..) + | ty::Never + | ty::Foreign(..) + | ty::Pat(..) + | ty::FnDef(..) + | ty::FnPtr(..) + | ty::RawPtr(..) + | ty::Closure(..) + | ty::CoroutineClosure(..) + | ty::Coroutine(..) + | ty::CoroutineWitness(..) + | ty::Dynamic(..) + | ty::UnsafeBinder(..) + | ty::Param(..) + | ty::Alias(..) + | ty::Bound(..) + | ty::Error(..) + | ty::Infer(..) + | ty::Placeholder(..) => { + bug!("encode_const_value: unexpected type `{:?}`", cv.ty); + } + } + + s +} + /// Encodes a FnSig using the Itanium C++ ABI with vendor extended type qualifiers and types for /// Rust types that are not used at the FFI boundary. fn encode_fnsig<'tcx>( diff --git a/compiler/rustc_session/src/filesearch.rs b/compiler/rustc_session/src/filesearch.rs index bf1e1f5f12811..b2290f92aae12 100644 --- a/compiler/rustc_session/src/filesearch.rs +++ b/compiler/rustc_session/src/filesearch.rs @@ -12,6 +12,7 @@ use crate::search_paths::{PathKind, SearchPath}; pub struct FileSearch { cli_search_paths: Vec, tlib_path: SearchPath, + use_implicit_sysroot_deps: bool, } impl FileSearch { @@ -20,16 +21,27 @@ impl FileSearch { } pub fn search_paths<'b>(&'b self, kind: PathKind) -> impl Iterator { + // If the crate is `PathKind::Crate` (a top level dependency) + // and `-Z implicit-sysroot-deps=false`, then don't include the sysroot in the search paths. + let exclude_sysroot = kind.matches(PathKind::Crate) && !self.use_implicit_sysroot_deps; + let maybe_tlib = (!exclude_sysroot).then_some(&self.tlib_path); + self.cli_search_paths .iter() .filter(move |sp| sp.kind.matches(kind)) - .chain(std::iter::once(&self.tlib_path)) + .chain(maybe_tlib.into_iter()) } - pub fn new(cli_search_paths: &[SearchPath], tlib_path: &SearchPath, target: &Target) -> Self { + pub fn new( + cli_search_paths: &[SearchPath], + tlib_path: &SearchPath, + target: &Target, + use_implicit_sysroot_deps: bool, + ) -> Self { let this = FileSearch { cli_search_paths: cli_search_paths.to_owned(), tlib_path: tlib_path.clone(), + use_implicit_sysroot_deps, }; this.refine(&["lib", &target.staticlib_prefix, &target.dll_prefix]) } diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 5b71c0435185a..ecfff0e64baf1 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -2531,6 +2531,8 @@ options! { "display unnamed regions as `'`, using a non-ident unique id (default: no)"), ignore_directory_in_diagnostics_source_blocks: Vec = (Vec::new(), parse_string_push, [UNTRACKED], "do not display the source code block in diagnostics for files in the directory"), + implicit_sysroot_deps: bool = (true, parse_bool, [TRACKED], + "allows rust to search sysroot for a crate's dependencies (default: yes)"), incremental_ignore_spans: bool = (false, parse_bool, [TRACKED], "ignore spans during ICH computation -- used for testing (default: no)"), incremental_info: bool = (false, parse_bool, [UNTRACKED], diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index eebead6fc1f47..e7f335e01d2f1 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -1335,9 +1335,18 @@ pub fn build_session( }); let asm_arch = if target.allow_asm { InlineAsmArch::from_arch(&target.arch) } else { None }; - let target_filesearch = - filesearch::FileSearch::new(&sopts.search_paths, &target_tlib_path, &target); - let host_filesearch = filesearch::FileSearch::new(&sopts.search_paths, &host_tlib_path, &host); + let target_filesearch = filesearch::FileSearch::new( + &sopts.search_paths, + &target_tlib_path, + &target, + sopts.unstable_opts.implicit_sysroot_deps, + ); + let host_filesearch = filesearch::FileSearch::new( + &sopts.search_paths, + &host_tlib_path, + &host, + sopts.unstable_opts.implicit_sysroot_deps, + ); let timings = TimingSectionHandler::new(sopts.json_timings); diff --git a/library/core/Cargo.toml b/library/core/Cargo.toml index 5421b1d2a2652..3f5f9f454a99d 100644 --- a/library/core/Cargo.toml +++ b/library/core/Cargo.toml @@ -23,7 +23,6 @@ optimize_for_size = [] # Make `RefCell` store additional debugging information, which is printed out when # a borrow error occurs debug_refcell = [] -llvm_enzyme = [] [lints.rust.unexpected_cfgs] level = "warn" @@ -39,7 +38,6 @@ check-cfg = [ 'cfg(target_has_reliable_f16_math)', 'cfg(target_has_reliable_f128)', 'cfg(target_has_reliable_f128_math)', - 'cfg(llvm_enzyme)', # Prevents use of a static variable for providing platform specific RawOsError # functionality 'cfg(no_io_statics)', diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 38340cd6aba73..424587bf75566 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -125,8 +125,6 @@ optimize_for_size = ["core/optimize_for_size", "alloc/optimize_for_size"] # a borrow error occurs debug_refcell = ["core/debug_refcell"] -llvm_enzyme = ["core/llvm_enzyme"] - # Enable using raw-dylib for Windows imports. # This will eventually be the default. windows_raw_dylib = ["windows-link/windows_raw_dylib"] diff --git a/library/sysroot/Cargo.toml b/library/sysroot/Cargo.toml index b2069ef6a613b..10562389d62d3 100644 --- a/library/sysroot/Cargo.toml +++ b/library/sysroot/Cargo.toml @@ -32,4 +32,3 @@ optimize_for_size = ["std/optimize_for_size"] panic-unwind = ["std/panic-unwind"] profiler = ["dep:profiler_builtins"] windows_raw_dylib = ["std/windows_raw_dylib"] -llvm_enzyme = ["std/llvm_enzyme"] diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 57d7518792926..a2184f75487fe 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -13,6 +13,8 @@ use std::path::{Path, PathBuf}; use std::process::Command; use std::{env, fs, iter}; +use build_helper::git::get_closest_upstream_commit; + use crate::core::build_steps::compile::{ArtifactKeepMode, Std, run_cargo}; use crate::core::build_steps::doc::{DocumentationFormat, prepare_doc_compiler}; use crate::core::build_steps::gcc::{Gcc, GccTargetPair, add_cg_gcc_cargo_flags}; @@ -4613,3 +4615,90 @@ impl CommandLineStep for RemoteTestClientTests { ); } } + +fn check_if_cargo_semver_checks_is_installed(builder: &Builder<'_>) -> bool { + command("cargo") + .allow_failure() + .arg("semver-checks") + .arg("--version") + // Cache the output to avoid running this command more than once (per builder). + .cached() + .run_capture_stdout(builder) + .is_success() +} + +/// Run cargo-semver-checks on the standard library and compare its API +/// versus a previous baseline, using rustdoc JSON data. +/// +/// Fails if a semver-breaking change is detected. +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct StdSemverCheck { + build_compiler: Compiler, + target: TargetSelection, + /// The baseline commit that we are comparing the local stdlib API against. + commit: String, +} + +impl CommandLineStep for StdSemverCheck { + type Output = (); + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + run.alias("std-semver-check") + } + + fn make_run(run: RunConfig<'_>) { + if !check_if_cargo_semver_checks_is_installed(run.builder) { + panic!("cargo-semver-checks was not found, please install it"); + } + + let baseline_commit = match get_closest_upstream_commit( + Some(&run.builder.config.src), + &run.builder.config.git_config(), + run.builder.config.ci_env, + ) { + Ok(Some(commit)) => commit, + Ok(None) => { + panic!("No baseline parent commit found for std-semver-check"); + } + Err(error) => { + panic!("Cannot get baseline parent commit for std-semver-check: {error:?}"); + } + }; + + run.builder.ensure(Self { + build_compiler: run.builder.compiler_for_std(run.builder.top_stage), + target: run.target, + commit: baseline_commit, + }); + } + + fn run(self, builder: &Builder<'_>) { + let Some(docs_dir) = builder.config.download_std_json_docs(self.target, &self.commit) + else { + return; + }; + + let directory = builder.ensure(crate::core::build_steps::doc::Std::from_build_compiler( + self.build_compiler, + self.target, + DocumentationFormat::Json, + )); + let baseline_dir = docs_dir.join("share").join("doc").join("rust").join("json"); + + for library in ["core", "alloc", "std"] { + println!("Checking semver compatibility of {library}"); + let mut cmd = command("cargo"); + cmd.arg("semver-checks") + .arg("-Z") + .arg("unstable-options") + .arg("--stability-aware") + .arg("--release-type") + .arg("minor") + .arg("--current-rustdoc") + .arg(directory.join(format!("{library}.json"))) + .arg("--baseline-rustdoc") + .arg(baseline_dir.join(format!("{library}.json"))); + cmd.run(builder); + } + } +} diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_semver_check.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_semver_check.snap new file mode 100644 index 0000000000000..0a2720e55b785 --- /dev/null +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_semver_check.snap @@ -0,0 +1,7 @@ +--- +source: src/bootstrap/src/core/builder/cli_paths/tests.rs +expression: test std-semver-check +--- +[Test] test::StdSemverCheck + targets: [aarch64-unknown-linux-gnu] + - Set({test::std-semver-check}) diff --git a/src/bootstrap/src/core/builder/cli_paths/tests.rs b/src/bootstrap/src/core/builder/cli_paths/tests.rs index 465a370ad69f8..45655b71e611a 100644 --- a/src/bootstrap/src/core/builder/cli_paths/tests.rs +++ b/src/bootstrap/src/core/builder/cli_paths/tests.rs @@ -170,6 +170,7 @@ declare_tests!( (x_test_librustdoc_rustdoc_html, "test librustdoc rustdoc-html"), (x_test_rustdoc, "test rustdoc"), (x_test_rustdoc_html, "test rustdoc-html"), + (x_test_semver_check, "test std-semver-check"), (x_test_skip_coverage, "test --skip=coverage"), (x_test_skip_coverage_map, "test --skip=coverage-map"), (x_test_skip_coverage_run, "test --skip=coverage-run"), diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs index 50188887a5314..ce476883c8839 100644 --- a/src/bootstrap/src/core/builder/mod.rs +++ b/src/bootstrap/src/core/builder/mod.rs @@ -974,6 +974,7 @@ impl<'a> Builder<'a> { test::RunMake, test::RunMakeCargo, test::BuildStd, + test::StdSemverCheck, test::IntrinsicTest, ), Kind::Miri => describe!(test::Crate), diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs index e6d55fd530adb..d3bc5718b171e 100644 --- a/src/bootstrap/src/core/download.rs +++ b/src/bootstrap/src/core/download.rs @@ -173,6 +173,30 @@ impl Config { ); } + pub(crate) fn download_std_json_docs( + &self, + target: TargetSelection, + commit: &str, + ) -> Option { + if self.dry_run() { + return None; + } + + self.do_if_verbose(|| println!("using downloaded std json docs from CI (commit {commit})")); + + let version = self.artifact_version_part(commit); + download_component( + DownloadContext::from(self), + &self.out, + DownloadSource::CI, + format!("rust-docs-json-{version}-{target}.tar.xz"), + "rust-docs-json-preview", + // When using DownloadSource::CI, the key is assumed to end with -llvm-assertions + &format!("{commit}-{}", self.llvm_assertions), + "ci-docs-json", + ) + } + fn download_toolchain( &self, version: &str, @@ -785,11 +809,11 @@ fn download_component<'a>( prefix: &str, key: &str, destination: &str, -) { +) -> Option { let dwn_ctx = dwn_ctx.as_ref(); if dwn_ctx.exec_ctx.dry_run() { - return; + return None; } let cache_dst = @@ -834,8 +858,7 @@ fn download_component<'a>( let sha256 = dwn_ctx.stage0_metadata.checksums_sha256.get(&url).expect(&error); if tarball.exists() { if verify(dwn_ctx.exec_ctx, &tarball, sha256) { - unpack(dwn_ctx.exec_ctx, &tarball, &bin_root, prefix); - return; + return Some(unpack(dwn_ctx.exec_ctx, &tarball, &bin_root, prefix)); } else { dwn_ctx.exec_ctx.do_if_verbose(|| { println!( @@ -848,8 +871,7 @@ fn download_component<'a>( } Some(sha256) } else if tarball.exists() { - unpack(dwn_ctx.exec_ctx, &tarball, &bin_root, prefix); - return; + return Some(unpack(dwn_ctx.exec_ctx, &tarball, &bin_root, prefix)); } else { None }; @@ -872,7 +894,7 @@ download-rustc = false panic!("failed to verify {}", tarball.display()); } - unpack(dwn_ctx.exec_ctx, &tarball, &bin_root, prefix); + Some(unpack(dwn_ctx.exec_ctx, &tarball, &bin_root, prefix)) } pub(crate) fn verify(exec_ctx: &ExecutionContext, path: &Path, expected: &str) -> bool { @@ -916,7 +938,7 @@ pub(crate) fn verify(exec_ctx: &ExecutionContext, path: &Path, expected: &str) - verified } -fn unpack(exec_ctx: &ExecutionContext, tarball: &Path, dst: &Path, pattern: &str) { +fn unpack(exec_ctx: &ExecutionContext, tarball: &Path, dst: &Path, pattern: &str) -> PathBuf { eprintln!("extracting {} to {}", tarball.display(), dst.display()); if !dst.exists() { t!(fs::create_dir_all(dst)); @@ -979,6 +1001,7 @@ fn unpack(exec_ctx: &ExecutionContext, tarball: &Path, dst: &Path, pattern: &str if dst_dir.exists() { t!(fs::remove_dir_all(&dst_dir), format!("failed to remove {}", dst_dir.display())); } + dst.to_path_buf() } fn download_file<'a>( diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index df35face8b5d8..3babca128d471 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -848,10 +848,6 @@ impl Build { features.insert("compiler-builtins-mem"); } - if self.config.llvm_enzyme { - features.insert("llvm_enzyme"); - } - features.into_iter().collect::>().join(" ") } @@ -874,9 +870,6 @@ impl Build { if (self.config.llvm_enabled(target) || kind == Kind::Check) && check("llvm") { features.push("llvm"); } - if self.config.llvm_enzyme { - features.push("llvm_enzyme"); - } if self.config.llvm_offload { features.push("llvm_offload"); } diff --git a/src/ci/citool/Cargo.lock b/src/ci/citool/Cargo.lock index a208de47256ca..185eecbde1a02 100644 --- a/src/ci/citool/Cargo.lock +++ b/src/ci/citool/Cargo.lock @@ -66,9 +66,9 @@ checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" [[package]] name = "askama" -version = "0.15.4" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08e1676b346cadfec169374f949d7490fd80a24193d37d2afce0c047cf695e57" +checksum = "f1bf825125edd887a019d0a3a837dcc5499a68b0d034cc3eb594070c3e18addc" dependencies = [ "askama_macros", "itoa", @@ -79,12 +79,13 @@ dependencies = [ [[package]] name = "askama_derive" -version = "0.15.4" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7661ff56517787343f376f75db037426facd7c8d3049cef8911f1e75016f3a37" +checksum = "e1c7065972a130eafa84215f21352ae15b4a7393da48c1f5e103904490736738" dependencies = [ "askama_parser", "basic-toml", + "glob", "memchr", "proc-macro2", "quote", @@ -96,18 +97,18 @@ dependencies = [ [[package]] name = "askama_macros" -version = "0.15.4" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "713ee4dbfd1eb719c2dab859465b01fa1d21cb566684614a713a6b7a99a4e47b" +checksum = "0e23b1d2c4bd39a41971f6124cef4cc6fd0540913ecb90919b69ab3bbe44ae1a" dependencies = [ "askama_derive", ] [[package]] name = "askama_parser" -version = "0.15.4" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d62d674238a526418b30c0def480d5beadb9d8964e7f38d635b03bf639c704c" +checksum = "7db09fde9143e7ac4513358fb32ee32847125b63b18ea715afd487956da715da" dependencies = [ "rustc-hash", "serde", @@ -380,6 +381,12 @@ dependencies = [ "wasi", ] +[[package]] +name = "glob" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4eba85ea1d0a966a983acd07deee566e67395d2d96b6fb39e62b5a833f1eb0b" + [[package]] name = "glob-match" version = "0.2.1" @@ -1105,9 +1112,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.7.6" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63d3fcd9bba44b03821e7d699eeee959f3126dcc4aa8e4ae18ec617c2a5cea10" +checksum = "23b97319f7b8343df12cc98938e5c3eb436064524c8d2b4e30a1d3a36eecdf81" dependencies = [ "memchr", ] diff --git a/src/ci/citool/src/test_dashboard.rs b/src/ci/citool/src/test_dashboard.rs index c9de38852e5a8..bfcb2ba790e3e 100644 --- a/src/ci/citool/src/test_dashboard.rs +++ b/src/ci/citool/src/test_dashboard.rs @@ -1,4 +1,4 @@ -use std::collections::{BTreeMap, HashMap}; +use std::collections::{BTreeMap, HashMap, HashSet}; use std::fs::File; use std::io::BufWriter; use std::path::{Path, PathBuf}; @@ -17,12 +17,14 @@ pub fn generate_test_dashboard( output_dir: &Path, ) -> anyhow::Result<()> { let metrics = download_auto_job_metrics(&db, None, current)?; - let suites = gather_test_suites(&metrics); + let mut suites = gather_test_suites(&metrics); std::fs::create_dir_all(output_dir)?; + let jobsets = assign_jobsets(&mut suites); + let test_count = suites.test_count(); - write_page(output_dir, "index.html", &TestSuitesPage { suites, test_count })?; + write_page(output_dir, "index.html", &TestSuitesPage { suites, test_count, jobsets })?; Ok(()) } @@ -33,6 +35,45 @@ fn write_page(dir: &Path, name: &str, template: &T) -> anyhow::Resu Ok(()) } +struct JobSets { + sets: Vec<(u32, Vec)>, +} + +fn assign_jobsets(suites: &mut TestSuites) -> JobSets { + let mut jobsets: HashMap, u32> = HashMap::new(); + + fn visit(jobsets: &mut HashMap, u32>, group: &mut TestGroup) { + for (_, test) in &mut group.root_tests { + for (_, results) in &mut test.revisions { + let mut jobset: HashSet = HashSet::new(); + for test in &results.passed { + jobset.insert(test.job.to_string()); + } + let mut jobset: Vec = jobset.into_iter().collect(); + jobset.sort(); + + let jobset_count = jobsets.len() as u32; + let jobset_id = jobsets.entry(jobset).or_insert_with(|| jobset_count); + results.passed_jobset = Some(*jobset_id); + } + } + for (_, group) in &mut group.groups { + visit(jobsets, group); + } + } + for suite in &mut suites.suites { + visit(&mut jobsets, &mut suite.group); + } + + let mut jobsets: Vec<(u32, Vec)> = jobsets.into_iter().map(|(k, v)| (v, k)).collect(); + jobsets.sort_unstable_by(|a, b| a.0.cmp(&b.0)); + for (_, set) in &mut jobsets { + set.sort_unstable(); + } + + JobSets { sets: jobsets } +} + fn gather_test_suites(job_metrics: &HashMap) -> TestSuites<'_> { struct CoarseTestSuite<'a> { tests: BTreeMap>, @@ -68,10 +109,9 @@ fn gather_test_suites(job_metrics: &HashMap) -> TestSuites< .tests .entry(test_name.clone()) .or_insert_with(|| Test { revisions: Default::default() }); - let variant_entry = test_entry - .revisions - .entry(variant_name) - .or_insert_with(|| TestResults { passed: vec![], ignored: vec![] }); + let variant_entry = test_entry.revisions.entry(variant_name).or_insert_with(|| { + TestResults { passed: vec![], passed_jobset: None, ignored: vec![] } + }); match test.outcome { TestOutcome::Passed => { @@ -161,6 +201,8 @@ struct TestSuite<'a> { struct TestResults<'a> { passed: Vec>, + /// An id representing a set of jobs on which this test has passed. + passed_jobset: Option, ignored: Vec>, } @@ -213,4 +255,5 @@ impl<'a> TestGroup<'a> { struct TestSuitesPage<'a> { suites: TestSuites<'a>, test_count: u64, + jobsets: JobSets, } diff --git a/src/ci/citool/templates/test_group.askama b/src/ci/citool/templates/test_group.askama index 1a72c47d3788a..2e9a8327c8537 100644 --- a/src/ci/citool/templates/test_group.askama +++ b/src/ci/citool/templates/test_group.askama @@ -1,5 +1,5 @@ -{% macro test_result(r) -%} -passed: {{ r.passed.len() }}, ignored: {{ r.ignored.len() }} +{% macro test_result(r, jobset) -%} +passed: {{ r.passed.len() }}, ignored: {{ r.ignored.len() }} {%- endmacro %}
  • @@ -24,12 +24,12 @@ passed: {{ r.passed.len() }}, ignored: {{ r.ignored.len() }} {% for (name, test) in root_tests %}
  • {% if let Some(result) = test.single_test() %} - {{ name }} ({% call test_result(result) %}{% endcall %}) + {{ name }} ({% call test_result(result, result.passed_jobset.as_ref().unwrap()) %}{% endcall %}) {% else %} {{ name }} ({{ test.revisions.len() }} revision{{ test.revisions.len() | pluralize }})
      {% for (revision, result) in test.revisions %} -
    • #{{ revision }} ({% call test_result(result) %}{% endcall %})
    • +
    • #{{ revision }} ({% call test_result(result, result.passed_jobset.as_ref().unwrap()) %}{% endcall %})
    • {% endfor %}
    {% endif %} diff --git a/src/ci/citool/templates/test_suites.askama b/src/ci/citool/templates/test_suites.askama index 4997f6a3f1c9a..59ba2b7e86916 100644 --- a/src/ci/citool/templates/test_suites.askama +++ b/src/ci/citool/templates/test_suites.askama @@ -20,11 +20,26 @@ the count includes all combinations of "stage" x "target" x "CI job where the te -
      +
        {% for suite in suites.suites %} {{ suite.group|safe }} {% endfor %}
      +
      +

      Job sets

      +
      + {% for (id, jobs) in jobsets.sets %} + {% if !jobs.is_empty() %} +
      J{{ id }}
      +
        + {% for job in jobs %} +
      • {{ job }}
      • + {% endfor %} +
      + {% endif %} + {% endfor %} +
      +
      {% endblock %} @@ -34,6 +49,9 @@ h1 { color: #333333; margin-bottom: 30px; } +a:visited { + color: blue; +} .summary { display: flex; @@ -55,10 +73,14 @@ ul { padding-left: 0; } -li { +.tests li { list-style: none; padding-left: 20px; } +.jobsets li { + margin-left: 30px; +} + summary { margin-bottom: 5px; padding: 6px; diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index aeaea8ca9bb5b..342743d21340f 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -38,6 +38,7 @@ macro_rules! location { #[rustfmt::skip] const LICENSES: &[&str] = &[ // tidy-alphabetical-start + "(MIT OR Apache-2.0) AND MIT", "0BSD OR MIT OR Apache-2.0", // adler2 license "Apache-2.0 / MIT", "Apache-2.0 OR ISC OR MIT", diff --git a/tests/codegen-llvm/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-const-generics.rs b/tests/codegen-llvm/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-const-generics.rs index cf26c17af1ed3..98591b0d4f1d2 100644 --- a/tests/codegen-llvm/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-const-generics.rs +++ b/tests/codegen-llvm/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-const-generics.rs @@ -5,10 +5,15 @@ //@ compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Copt-level=0 -C unsafe-allow-abi-mismatch=sanitizer #![crate_type = "lib"] +#![feature(adt_const_params)] #![feature(type_alias_impl_trait)] +#![feature(unsized_const_params)] +#![allow(incomplete_features)] extern crate core; +use std::marker::ConstParamTy; + pub type Type1 = impl Send; #[define_opaque(Type1)] @@ -27,6 +32,52 @@ pub fn foo2(_: Type1, _: Type1) {} pub fn foo3(_: Type1, _: Type1, _: Type1) {} // CHECK: define{{.*}}4foo3{{.*}}!type ![[TYPE3:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} +#[derive(PartialEq, Eq, ConstParamTy)] +pub struct Struct1 { + pub x: u16, + pub y: u16, +} + +#[derive(PartialEq, Eq, ConstParamTy)] +pub enum Enum1 { + Variant1, + Variant2(u8), +} + +pub struct BoolHolder; +pub struct IntHolder; +pub struct CharHolder; +pub struct StrHolder; +pub struct StructHolder; +pub struct EnumHolder; +pub struct ArrayHolder; +pub struct TupleHolder; + +pub fn foo4(_: &BoolHolder) {} +// CHECK: define{{.*}}4foo4{{.*}}!type ![[TYPE4:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} +pub fn foo5(_: &IntHolder<-1>) {} +// CHECK: define{{.*}}4foo5{{.*}}!type ![[TYPE5:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} +pub fn foo6(_: &CharHolder<'x'>) {} +// CHECK: define{{.*}}4foo6{{.*}}!type ![[TYPE6:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} +pub fn foo7(_: &StrHolder<"hello">) {} +// CHECK: define{{.*}}4foo7{{.*}}!type ![[TYPE7:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} +pub fn foo8(_: &StructHolder<{ Struct1 { x: 1, y: 2 } }>) {} +// CHECK: define{{.*}}4foo8{{.*}}!type ![[TYPE8:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} +pub fn foo9(_: &EnumHolder<{ Enum1::Variant2(5) }>) {} +// CHECK: define{{.*}}4foo9{{.*}}!type ![[TYPE9:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} +pub fn foo10(_: &ArrayHolder<{ [3, 4] }>) {} +// CHECK: define{{.*}}5foo10{{.*}}!type ![[TYPE10:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} +pub fn foo11(_: &TupleHolder<{ (6, true) }>) {} +// CHECK: define{{.*}}5foo11{{.*}}!type ![[TYPE11:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} + // CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo3FooIu3i32Lu5usize32EEE"} // CHECK: ![[TYPE2]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo3FooIu3i32Lu5usize32EES2_E"} // CHECK: ![[TYPE3]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo3FooIu3i32Lu5usize32EES2_S2_E"} +// CHECK: ![[TYPE4]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtC{{[[:print:]]+}}_{{[[:print:]]+}}10BoolHolderILb1EEEE"} +// CHECK: ![[TYPE5]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtC{{[[:print:]]+}}_{{[[:print:]]+}}9IntHolderILu3i32n1EEEE"} +// CHECK: ![[TYPE6]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtC{{[[:print:]]+}}_{{[[:print:]]+}}10CharHolderILu4char120EEEE"} +// CHECK: ![[TYPE7]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtC{{[[:print:]]+}}_{{[[:print:]]+}}9StrHolderILu3refIu3strE68656c6c6fEEEE"} +// CHECK: ![[TYPE8]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtC{{[[:print:]]+}}_{{[[:print:]]+}}12StructHolderILu{{[0-9]+}}NtC{{[[:print:]]+}}_{{[[:print:]]+}}7Struct1Lu3u161ELS0_2EEEEE"} +// CHECK: ![[TYPE9]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtC{{[[:print:]]+}}_{{[[:print:]]+}}10EnumHolderILu{{[0-9]+}}NtC{{[[:print:]]+}}_{{[[:print:]]+}}5Enum1V1Lu2u85EEEEE"} +// CHECK: ![[TYPE10]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtC{{[[:print:]]+}}_{{[[:print:]]+}}11ArrayHolderILA2u3u16LS_3ELS_4EEEEE"} +// CHECK: ![[TYPE11]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtC{{[[:print:]]+}}_{{[[:print:]]+}}11TupleHolderILu5tupleIu3u16bELS_6ELb1EEEEE"} diff --git a/tests/run-make/implicit-sysroot-deps/bar.rs b/tests/run-make/implicit-sysroot-deps/bar.rs new file mode 100644 index 0000000000000..ececc69fe9514 --- /dev/null +++ b/tests/run-make/implicit-sysroot-deps/bar.rs @@ -0,0 +1,4 @@ +#![feature(no_core)] +#![no_core] +#![no_std] +extern crate baz; diff --git a/tests/run-make/implicit-sysroot-deps/baz.rs b/tests/run-make/implicit-sysroot-deps/baz.rs new file mode 100644 index 0000000000000..ef13d56b7d4f0 --- /dev/null +++ b/tests/run-make/implicit-sysroot-deps/baz.rs @@ -0,0 +1,3 @@ +#![feature(no_core)] +#![no_core] +#![no_std] diff --git a/tests/run-make/implicit-sysroot-deps/foo.rs b/tests/run-make/implicit-sysroot-deps/foo.rs new file mode 100644 index 0000000000000..90d13bd02b1db --- /dev/null +++ b/tests/run-make/implicit-sysroot-deps/foo.rs @@ -0,0 +1,4 @@ +#![feature(no_core)] +#![no_core] +#![no_std] +extern crate bar; diff --git a/tests/run-make/implicit-sysroot-deps/rmake.rs b/tests/run-make/implicit-sysroot-deps/rmake.rs new file mode 100644 index 0000000000000..a748bda4db271 --- /dev/null +++ b/tests/run-make/implicit-sysroot-deps/rmake.rs @@ -0,0 +1,38 @@ +use run_make_support::rfs::create_dir_all; +use run_make_support::{rust_lib_name, rustc, target}; + +// Tests `-Zimplicit-sysroot-deps=false` with arbitrary crates passed via `--extern` +// See `tests/ui/crate-loading` for tests with the standard library + +fn main() { + // Create test sysroot + let test_sysroot = format!("./testsysroot/lib/rustlib/{}/lib/", target()); + create_dir_all(&test_sysroot); + + // Layout: + // - Foo depends directly on Bar + // - Bar depends directly on Baz + // - Baz can be found in the sysroot. + + // 1) Depending transitively on a lib in the sysroot resolves + // fine with `-Zimplicit-sysroot-deps=false` + rustc().input("baz.rs").crate_type("lib").out_dir(test_sysroot).run(); + rustc().input("bar.rs").crate_type("lib").sysroot("./testsysroot").run(); + rustc() + .input("foo.rs") + .crate_type("lib") + .extern_("bar", rust_lib_name("bar")) + .sysroot("./testsysroot") + .arg("-Zimplicit-sysroot-deps=false") + .run(); + + // 2) Depending directly on a lib in the sysroot does not resolve + // implicitly with `-Zimplicit-sysroot-deps=false` + rustc() + .input("bar.rs") + .crate_type("lib") + .sysroot("./testsysroot") + .arg("-Zimplicit-sysroot-deps=false") + .run_fail() + .assert_stderr_contains("can't find crate for `baz`"); +} diff --git a/tests/ui/crate-loading/auxiliary/crate-dep-std.rs b/tests/ui/crate-loading/auxiliary/crate-dep-std.rs new file mode 100644 index 0000000000000..5eec10bfc3e4a --- /dev/null +++ b/tests/ui/crate-loading/auxiliary/crate-dep-std.rs @@ -0,0 +1,3 @@ +pub fn bar() { + println!("I depend on std."); +} diff --git a/tests/ui/crate-loading/no-implicit-sysroot-deps-pass.rs b/tests/ui/crate-loading/no-implicit-sysroot-deps-pass.rs new file mode 100644 index 0000000000000..a2ce18597e0b8 --- /dev/null +++ b/tests/ui/crate-loading/no-implicit-sysroot-deps-pass.rs @@ -0,0 +1,16 @@ +//@ check-pass +//@ aux-build:crate-dep-std.rs +//@ compile-flags: --crate-type=lib -Zimplicit-sysroot-deps=false -Cpanic=abort + +// This test ensures that `-Zimplicit-sysroot-deps=false` allows loading transitive +// dependencies from the sysroot when required. + +#![feature(no_core)] +#![no_std] +#![no_core] + +extern crate crate_dep_std as foo; +use foo::bar; +pub fn bark() { + bar(); +} diff --git a/tests/ui/crate-loading/no-implicit-sysroot-deps.rs b/tests/ui/crate-loading/no-implicit-sysroot-deps.rs new file mode 100644 index 0000000000000..9a280cc681571 --- /dev/null +++ b/tests/ui/crate-loading/no-implicit-sysroot-deps.rs @@ -0,0 +1,14 @@ +//~ ERROR can't find crate for `std` +//~| NOTE can't find crate +//~| NOTE target may not be installed +//~| HELP consider building the standard library from source with `cargo build -Zbuild-std` +//~| HELP consider downloading the target with + +//@ compile-flags: --target x86_64-unknown-linux-gnu -Z implicit-sysroot-deps=false +//@ needs-llvm-components: x86 + +// This program has an implicit dependency on std, injected by rust. This test ensures that rustc +// does not search in the sysroot for it when `-Zimplicit-sysroot-deps` is false, and that an +// error is thrown when std is not available on any other search paths. + +fn main() {} diff --git a/tests/ui/crate-loading/no-implicit-sysroot-deps.stderr b/tests/ui/crate-loading/no-implicit-sysroot-deps.stderr new file mode 100644 index 0000000000000..688664cad9596 --- /dev/null +++ b/tests/ui/crate-loading/no-implicit-sysroot-deps.stderr @@ -0,0 +1,9 @@ +error[E0463]: can't find crate for `std` + | + = note: the `x86_64-unknown-linux-gnu` target may not be installed + = help: consider downloading the target with `rustup target add x86_64-unknown-linux-gnu` + = help: consider building the standard library from source with `cargo build -Zbuild-std` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0463`. diff --git a/tests/ui/sanitizer/cfi/const-generics.rs b/tests/ui/sanitizer/cfi/const-generics.rs new file mode 100644 index 0000000000000..42fff233dd84b --- /dev/null +++ b/tests/ui/sanitizer/cfi/const-generics.rs @@ -0,0 +1,110 @@ +// Verifies that functions with types with const generics as argument types can +// be called through function pointers. +// +//@ needs-sanitizer-cfi +// FIXME(#122848) Remove only-linux once OSX CFI binaries work +//@ only-linux +//@ ignore-backends: gcc +//@ compile-flags: -Ctarget-feature=-crt-static -Ccodegen-units=1 -Clto -Cprefer-dynamic=off -Copt-level=0 -Zsanitizer=cfi -Cunsafe-allow-abi-mismatch=sanitizer +//@ run-pass + +#![feature(adt_const_params)] +#![feature(unsized_const_params)] +#![allow(incomplete_features)] + +use std::marker::ConstParamTy; + +#[derive(PartialEq, Eq, ConstParamTy)] +struct Struct2 { + x: u16, + y: u16, +} + +#[derive(PartialEq, Eq, ConstParamTy)] +enum Enum1 { + Variant1, + Variant2(u8), +} + +struct Struct1([i32; N]); +struct BoolHolder(bool); +struct IntHolder(i32); +struct CharHolder(char); +struct StrHolder(&'static str); +struct StructHolder(Struct2); +struct EnumHolder(Enum1); +struct ArrayHolder([u16; 2]); +struct TupleHolder((u16, bool)); + +fn foo1(x: Struct1<2>) { + assert_eq!(x.0, [1, 2]); +} + +fn foo2(x: &Struct1<4>) { + assert_eq!(x.0, [1, 2, 3, 4]); +} + +fn foo3(x: BoolHolder) { + assert!(x.0); +} + +fn foo4(x: IntHolder<-1>) { + assert_eq!(x.0, -1); +} + +fn foo5(x: CharHolder<'x'>) { + assert_eq!(x.0, 'x'); +} + +fn foo6(x: StrHolder<"hello">) { + assert_eq!(x.0, "hello"); +} + +fn foo7(x: StructHolder<{ Struct2 { x: 1, y: 2 } }>) { + assert_eq!(x.0.x, 1); + assert_eq!(x.0.y, 2); +} + +fn foo8(x: EnumHolder<{ Enum1::Variant1 }>) { + assert!(matches!(x.0, Enum1::Variant1)); +} + +fn foo9(x: EnumHolder<{ Enum1::Variant2(5) }>) { + match x.0 { + Enum1::Variant1 => unreachable!(), + Enum1::Variant2(v) => assert_eq!(v, 5), + } +} + +fn foo10(x: ArrayHolder<{ [3, 4] }>) { + assert_eq!(x.0, [3, 4]); +} + +fn foo11(x: TupleHolder<{ (6, true) }>) { + assert_eq!(x.0, (6, true)); +} + +fn main() { + let f: fn(Struct1<2>) = foo1; + f(Struct1([1, 2])); + let f: fn(&Struct1<4>) = foo2; + f(&Struct1([1, 2, 3, 4])); + let f: fn(BoolHolder) = foo3; + f(BoolHolder(true)); + let f: fn(IntHolder<-1>) = foo4; + f(IntHolder(-1)); + let f: fn(CharHolder<'x'>) = foo5; + f(CharHolder('x')); + let f: fn(StrHolder<"hello">) = foo6; + f(StrHolder("hello")); + let f: fn(StructHolder<{ Struct2 { x: 1, y: 2 } }>) = foo7; + f(StructHolder(Struct2 { x: 1, y: 2 })); + let f: fn(EnumHolder<{ Enum1::Variant1 }>) = foo8; + f(EnumHolder(Enum1::Variant1)); + let f: fn(EnumHolder<{ Enum1::Variant2(5) }>) = foo9; + f(EnumHolder(Enum1::Variant2(5))); + let f: fn(ArrayHolder<{ [3, 4] }>) = foo10; + f(ArrayHolder([3, 4])); + let f: fn(TupleHolder<{ (6, true) }>) = foo11; + f(TupleHolder((6, true))); +} diff --git a/tests/ui/sanitizer/kcfi/const-generics.rs b/tests/ui/sanitizer/kcfi/const-generics.rs new file mode 100644 index 0000000000000..86f487bb9ea1e --- /dev/null +++ b/tests/ui/sanitizer/kcfi/const-generics.rs @@ -0,0 +1,109 @@ +// Verifies that functions with types with const generics as argument types can +// be called through function pointers. +// +//@ needs-sanitizer-kcfi +//@ only-linux +//@ ignore-backends: gcc +//@ compile-flags: -Ctarget-feature=-crt-static -Cpanic=abort -Cprefer-dynamic=off -Copt-level=0 -Zsanitizer=kcfi -Cunsafe-allow-abi-mismatch=sanitizer +//@ run-pass + +#![feature(adt_const_params)] +#![feature(unsized_const_params)] +#![allow(incomplete_features)] + +use std::marker::ConstParamTy; + +#[derive(PartialEq, Eq, ConstParamTy)] +struct Struct2 { + x: u16, + y: u16, +} + +#[derive(PartialEq, Eq, ConstParamTy)] +enum Enum1 { + Variant1, + Variant2(u8), +} + +struct Struct1([i32; N]); +struct BoolHolder(bool); +struct IntHolder(i32); +struct CharHolder(char); +struct StrHolder(&'static str); +struct StructHolder(Struct2); +struct EnumHolder(Enum1); +struct ArrayHolder([u16; 2]); +struct TupleHolder((u16, bool)); + +fn foo1(x: Struct1<2>) { + assert_eq!(x.0, [1, 2]); +} + +fn foo2(x: &Struct1<4>) { + assert_eq!(x.0, [1, 2, 3, 4]); +} + +fn foo3(x: BoolHolder) { + assert!(x.0); +} + +fn foo4(x: IntHolder<-1>) { + assert_eq!(x.0, -1); +} + +fn foo5(x: CharHolder<'x'>) { + assert_eq!(x.0, 'x'); +} + +fn foo6(x: StrHolder<"hello">) { + assert_eq!(x.0, "hello"); +} + +fn foo7(x: StructHolder<{ Struct2 { x: 1, y: 2 } }>) { + assert_eq!(x.0.x, 1); + assert_eq!(x.0.y, 2); +} + +fn foo8(x: EnumHolder<{ Enum1::Variant1 }>) { + assert!(matches!(x.0, Enum1::Variant1)); +} + +fn foo9(x: EnumHolder<{ Enum1::Variant2(5) }>) { + match x.0 { + Enum1::Variant1 => unreachable!(), + Enum1::Variant2(v) => assert_eq!(v, 5), + } +} + +fn foo10(x: ArrayHolder<{ [3, 4] }>) { + assert_eq!(x.0, [3, 4]); +} + +fn foo11(x: TupleHolder<{ (6, true) }>) { + assert_eq!(x.0, (6, true)); +} + +fn main() { + let f: fn(Struct1<2>) = foo1; + f(Struct1([1, 2])); + let f: fn(&Struct1<4>) = foo2; + f(&Struct1([1, 2, 3, 4])); + let f: fn(BoolHolder) = foo3; + f(BoolHolder(true)); + let f: fn(IntHolder<-1>) = foo4; + f(IntHolder(-1)); + let f: fn(CharHolder<'x'>) = foo5; + f(CharHolder('x')); + let f: fn(StrHolder<"hello">) = foo6; + f(StrHolder("hello")); + let f: fn(StructHolder<{ Struct2 { x: 1, y: 2 } }>) = foo7; + f(StructHolder(Struct2 { x: 1, y: 2 })); + let f: fn(EnumHolder<{ Enum1::Variant1 }>) = foo8; + f(EnumHolder(Enum1::Variant1)); + let f: fn(EnumHolder<{ Enum1::Variant2(5) }>) = foo9; + f(EnumHolder(Enum1::Variant2(5))); + let f: fn(ArrayHolder<{ [3, 4] }>) = foo10; + f(ArrayHolder([3, 4])); + let f: fn(TupleHolder<{ (6, true) }>) = foo11; + f(TupleHolder((6, true))); +}