diff options
494 files changed, 5367 insertions, 5245 deletions
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index c11103af476..b42c99e1a6d 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -1450,6 +1450,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { ty::Param(param_ty) => Ok(( generics.type_param(param_ty, tcx), predicate.trait_ref.print_trait_sugared().to_string(), + Some(predicate.trait_ref.def_id), )), _ => Err(()), } @@ -1463,9 +1464,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { tcx, hir_generics, err, - predicates - .iter() - .map(|(param, constraint)| (param.name.as_str(), &**constraint, None)), + predicates.iter().map(|(param, constraint, def_id)| { + (param.name.as_str(), &**constraint, *def_id) + }), None, ); } diff --git a/compiler/rustc_codegen_cranelift/Cargo.lock b/compiler/rustc_codegen_cranelift/Cargo.lock index e4f77472802..d81e7214961 100644 --- a/compiler/rustc_codegen_cranelift/Cargo.lock +++ b/compiler/rustc_codegen_cranelift/Cargo.lock @@ -46,24 +46,24 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cranelift-bforest" -version = "0.113.0" +version = "0.114.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea5e7afe85cadb55c4c1176268a2ac046fdff8dfaeca39e18581b9dc319ca9e" +checksum = "2ba4f80548f22dc9c43911907b5e322c5555544ee85f785115701e6a28c9abe1" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-bitset" -version = "0.113.0" +version = "0.114.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ab25ef3be935a80680e393183e1f94ef507e93a24a8369494d2c6818aedb3e3" +checksum = "005884e3649c3e5ff2dc79e8a94b138f11569cc08a91244a292714d2a86e9156" [[package]] name = "cranelift-codegen" -version = "0.113.0" +version = "0.114.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "900a19b84545924f1851cbfe386962edfc4ecbc3366a254825cf1ecbcda8ba08" +checksum = "fe4036255ec33ce9a37495dfbcfc4e1118fd34e693eff9a1e106336b7cd16a9b" dependencies = [ "bumpalo", "cranelift-bforest", @@ -78,48 +78,49 @@ dependencies = [ "log", "regalloc2", "rustc-hash", + "serde", "smallvec", "target-lexicon", ] [[package]] name = "cranelift-codegen-meta" -version = "0.113.0" +version = "0.114.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08c73b2395ffe9e7b4fdf7e2ebc052e7e27af13f68a964985346be4da477a5fc" +checksum = "f7ca74f4b68319da11d39e894437cb6e20ec7c2e11fbbda823c3bf207beedff7" dependencies = [ "cranelift-codegen-shared", ] [[package]] name = "cranelift-codegen-shared" -version = "0.113.0" +version = "0.114.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d9ed0854e96a4ff0879bff39d078de8dea7f002721c9494c1fdb4e1baa86ccc" +checksum = "897e54f433a0269c4187871aa06d452214d5515d228d5bdc22219585e9eef895" [[package]] name = "cranelift-control" -version = "0.113.0" +version = "0.114.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4aca921dd422e781409de0129c255768fec5dec1dae83239b497fb9138abb89" +checksum = "29cb4018f5bf59fb53f515fa9d80e6f8c5ce19f198dc538984ebd23ecf8965ec" dependencies = [ "arbitrary", ] [[package]] name = "cranelift-entity" -version = "0.113.0" +version = "0.114.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2d770e6605eccee15b49decdd82cd26f2b6404767802471459ea49c57379a98" +checksum = "305399fd781a2953ac78c1396f02ff53144f39c33eb7fc7789cf4e8936d13a96" dependencies = [ "cranelift-bitset", ] [[package]] name = "cranelift-frontend" -version = "0.113.0" +version = "0.114.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29268711cb889cb39215b10faf88b9087d4c9e1d2633581e4f722a2bf4bb4ef9" +checksum = "9230b460a128d53653456137751d27baf567947a3ab8c0c4d6e31fd08036d81e" dependencies = [ "cranelift-codegen", "log", @@ -129,15 +130,15 @@ dependencies = [ [[package]] name = "cranelift-isle" -version = "0.113.0" +version = "0.114.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc65156f010aed1985767ad1bff0eb8d186743b7b03e23d0c17604a253e3f356" +checksum = "b961e24ae3ec9813a24a15ae64bbd2a42e4de4d79a7f3225a412e3b94e78d1c8" [[package]] name = "cranelift-jit" -version = "0.113.0" +version = "0.114.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ba6b46367a4f466cfb1abe32793fa1a0f96d862251491b01a44726b8ed9445" +checksum = "62699329d4ced20fe281fbaef45e11b473b7ab310491b4bdebcd8b818a8ef7fe" dependencies = [ "anyhow", "cranelift-codegen", @@ -155,9 +156,9 @@ dependencies = [ [[package]] name = "cranelift-module" -version = "0.113.0" +version = "0.114.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "007607022a4883ebdffc46c0925e2e10babf2a565ae78518034ade722aa825d2" +checksum = "2f20b0b51ba962dac30fc7e812b86e4390d908acd4f59bcc8ac7610a8f3e0977" dependencies = [ "anyhow", "cranelift-codegen", @@ -166,9 +167,9 @@ dependencies = [ [[package]] name = "cranelift-native" -version = "0.113.0" +version = "0.114.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8bf9b361eaf5a7627647270fabf1dc910d993edbeaf272a652c107861ebe9c2" +checksum = "4d5bd76df6c9151188dfa428c863b33da5b34561b67f43c0cf3f24a794f9fa1f" dependencies = [ "cranelift-codegen", "libc", @@ -177,9 +178,9 @@ dependencies = [ [[package]] name = "cranelift-object" -version = "0.113.0" +version = "0.114.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30ca5c38fa00c0cd943035391bdcc84ed00748f17c66c682e410f5a62f234d44" +checksum = "ee231640a7ecceedd0f1f2782d9288db6a6908cc70675ed9427e3bf0ea6daacd" dependencies = [ "anyhow", "cranelift-codegen", @@ -364,6 +365,26 @@ dependencies = [ ] [[package]] +name = "serde" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] name = "slice-group-by" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -412,9 +433,9 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "wasmtime-jit-icache-coherence" -version = "26.0.0" +version = "27.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e458e6a1a010a53f86ac8d75837c0c6b2ce3e54b7503b2f1dc5629a4a541f5a" +checksum = "91b218a92866f74f35162f5d03a4e0f62cd0e1cc624285b1014275e5d4575fad" dependencies = [ "anyhow", "cfg-if", diff --git a/compiler/rustc_codegen_cranelift/Cargo.toml b/compiler/rustc_codegen_cranelift/Cargo.toml index f352ef72cb0..b2fed3c490e 100644 --- a/compiler/rustc_codegen_cranelift/Cargo.toml +++ b/compiler/rustc_codegen_cranelift/Cargo.toml @@ -8,12 +8,12 @@ crate-type = ["dylib"] [dependencies] # These have to be in sync with each other -cranelift-codegen = { version = "0.113.0", default-features = false, features = ["std", "unwind", "all-native-arch"] } -cranelift-frontend = { version = "0.113.0" } -cranelift-module = { version = "0.113.0" } -cranelift-native = { version = "0.113.0" } -cranelift-jit = { version = "0.113.0", optional = true } -cranelift-object = { version = "0.113.0" } +cranelift-codegen = { version = "0.114.0", default-features = false, features = ["std", "unwind", "all-native-arch"] } +cranelift-frontend = { version = "0.114.0" } +cranelift-module = { version = "0.114.0" } +cranelift-native = { version = "0.114.0" } +cranelift-jit = { version = "0.114.0", optional = true } +cranelift-object = { version = "0.114.0" } target-lexicon = "0.12.0" gimli = { version = "0.31", default-features = false, features = ["write"] } object = { version = "0.36", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } diff --git a/compiler/rustc_codegen_cranelift/build_system/abi_cafe.rs b/compiler/rustc_codegen_cranelift/build_system/abi_cafe.rs index 9292778806a..674acfbd309 100644 --- a/compiler/rustc_codegen_cranelift/build_system/abi_cafe.rs +++ b/compiler/rustc_codegen_cranelift/build_system/abi_cafe.rs @@ -1,4 +1,4 @@ -use crate::path::{Dirs, RelPath}; +use crate::path::Dirs; use crate::prepare::GitRepo; use crate::utils::{CargoProject, Compiler, spawn_and_wait}; use crate::{CodegenBackend, SysrootKind, build_sysroot}; @@ -20,7 +20,7 @@ pub(crate) fn run( rustup_toolchain_name: Option<&str>, bootstrap_host_compiler: &Compiler, ) { - RelPath::DOWNLOAD.ensure_exists(dirs); + std::fs::create_dir_all(&dirs.download_dir).unwrap(); ABI_CAFE_REPO.fetch(dirs); ABI_CAFE_REPO.patch(dirs); diff --git a/compiler/rustc_codegen_cranelift/build_system/bench.rs b/compiler/rustc_codegen_cranelift/build_system/bench.rs index ebeb6772250..73a0f325fc2 100644 --- a/compiler/rustc_codegen_cranelift/build_system/bench.rs +++ b/compiler/rustc_codegen_cranelift/build_system/bench.rs @@ -3,7 +3,7 @@ use std::io::Write; use std::path::Path; use std::process::Command; -use crate::path::{Dirs, RelPath}; +use crate::path::Dirs; use crate::prepare::GitRepo; use crate::rustc_info::get_file_name; use crate::utils::{Compiler, spawn_and_wait}; @@ -39,11 +39,11 @@ fn benchmark_simple_raytracer(dirs: &Dirs, bootstrap_host_compiler: &Compiler) { }; eprintln!("[BENCH COMPILE] ebobby/simple-raytracer"); - let cargo_clif = RelPath::DIST - .to_path(dirs) + let cargo_clif = dirs + .dist_dir .join(get_file_name(&bootstrap_host_compiler.rustc, "cargo_clif", "bin").replace('_', "-")); let manifest_path = SIMPLE_RAYTRACER_REPO.source_dir().to_path(dirs).join("Cargo.toml"); - let target_dir = RelPath::BUILD.join("simple_raytracer").to_path(dirs); + let target_dir = dirs.build_dir.join("simple_raytracer"); let clean_cmd = format!( "RUSTC=rustc cargo clean --manifest-path {manifest_path} --target-dir {target_dir}", @@ -68,7 +68,7 @@ fn benchmark_simple_raytracer(dirs: &Dirs, bootstrap_host_compiler: &Compiler) { target_dir = target_dir.display(), ); - let bench_compile_markdown = RelPath::DIST.to_path(dirs).join("bench_compile.md"); + let bench_compile_markdown = dirs.dist_dir.join("bench_compile.md"); let bench_compile = hyperfine_command( 1, @@ -92,7 +92,7 @@ fn benchmark_simple_raytracer(dirs: &Dirs, bootstrap_host_compiler: &Compiler) { eprintln!("[BENCH RUN] ebobby/simple-raytracer"); - let bench_run_markdown = RelPath::DIST.to_path(dirs).join("bench_run.md"); + let bench_run_markdown = dirs.dist_dir.join("bench_run.md"); let raytracer_cg_llvm = Path::new(".").join(get_file_name( &bootstrap_host_compiler.rustc, @@ -120,7 +120,7 @@ fn benchmark_simple_raytracer(dirs: &Dirs, bootstrap_host_compiler: &Compiler) { ], &bench_run_markdown, ); - bench_run.current_dir(RelPath::BUILD.to_path(dirs)); + bench_run.current_dir(&dirs.build_dir); spawn_and_wait(bench_run); if let Some(gha_step_summary) = gha_step_summary.as_mut() { diff --git a/compiler/rustc_codegen_cranelift/build_system/build_backend.rs b/compiler/rustc_codegen_cranelift/build_system/build_backend.rs index 02da89f737c..72bc422523d 100644 --- a/compiler/rustc_codegen_cranelift/build_system/build_backend.rs +++ b/compiler/rustc_codegen_cranelift/build_system/build_backend.rs @@ -6,7 +6,7 @@ use crate::rustc_info::get_file_name; use crate::shared_utils::{rustflags_from_env, rustflags_to_cmd_env}; use crate::utils::{CargoProject, Compiler, LogGroup}; -static CG_CLIF: CargoProject = CargoProject::new(&RelPath::SOURCE, "cg_clif"); +static CG_CLIF: CargoProject = CargoProject::new(&RelPath::source("."), "cg_clif"); pub(crate) fn build_backend( dirs: &Dirs, diff --git a/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs b/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs index f1f4489bcbc..e47e9829916 100644 --- a/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs +++ b/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs @@ -22,9 +22,9 @@ pub(crate) fn build_sysroot( eprintln!("[BUILD] sysroot {:?}", sysroot_kind); - let dist_dir = RelPath::DIST.to_path(dirs); + let dist_dir = &dirs.dist_dir; - ensure_empty_dir(&dist_dir); + ensure_empty_dir(dist_dir); fs::create_dir_all(dist_dir.join("bin")).unwrap(); fs::create_dir_all(dist_dir.join("lib")).unwrap(); @@ -55,7 +55,7 @@ pub(crate) fn build_sysroot( let mut build_cargo_wrapper_cmd = Command::new(&bootstrap_host_compiler.rustc); let wrapper_path = dist_dir.join(&wrapper_name); build_cargo_wrapper_cmd - .arg(RelPath::SCRIPTS.to_path(dirs).join(&format!("{wrapper}.rs"))) + .arg(dirs.source_dir.join("scripts").join(&format!("{wrapper}.rs"))) .arg("-o") .arg(&wrapper_path) .arg("-Cstrip=debuginfo"); @@ -85,7 +85,7 @@ pub(crate) fn build_sysroot( &cg_clif_dylib_path, sysroot_kind, ); - host.install_into_sysroot(&dist_dir); + host.install_into_sysroot(dist_dir); if !is_native { build_sysroot_for_triple( @@ -99,7 +99,7 @@ pub(crate) fn build_sysroot( &cg_clif_dylib_path, sysroot_kind, ) - .install_into_sysroot(&dist_dir); + .install_into_sysroot(dist_dir); } let mut target_compiler = { @@ -143,10 +143,10 @@ impl SysrootTarget { } } -static STDLIB_SRC: RelPath = RelPath::BUILD.join("stdlib"); +static STDLIB_SRC: RelPath = RelPath::build("stdlib"); static STANDARD_LIBRARY: CargoProject = - CargoProject::new(&STDLIB_SRC.join("library/sysroot"), "stdlib_target"); -static RTSTARTUP_SYSROOT: RelPath = RelPath::BUILD.join("rtstartup"); + CargoProject::new(&RelPath::build("stdlib/library/sysroot"), "stdlib_target"); +static RTSTARTUP_SYSROOT: RelPath = RelPath::build("rtstartup"); fn build_sysroot_for_triple( dirs: &Dirs, @@ -247,6 +247,7 @@ fn build_clif_sysroot_for_triple( let mut build_cmd = STANDARD_LIBRARY.build(&compiler, dirs); build_cmd.arg("--release"); build_cmd.arg("--features").arg("backtrace panic-unwind compiler-builtins-no-f16-f128"); + build_cmd.arg(format!("-Zroot-dir={}", STDLIB_SRC.to_path(dirs).display())); build_cmd.env("CARGO_PROFILE_RELEASE_DEBUG", "true"); build_cmd.env("__CARGO_DEFAULT_LIB_METADATA", "cg_clif"); if compiler.triple.contains("apple") { @@ -281,13 +282,14 @@ fn build_rtstartup(dirs: &Dirs, compiler: &Compiler) -> Option<SysrootTarget> { return None; } - RTSTARTUP_SYSROOT.ensure_fresh(dirs); + let rtstartup_sysroot = RTSTARTUP_SYSROOT.to_path(dirs); + ensure_empty_dir(&rtstartup_sysroot); let rtstartup_src = STDLIB_SRC.to_path(dirs).join("library").join("rtstartup"); let mut target_libs = SysrootTarget { triple: compiler.triple.clone(), libs: vec![] }; for file in ["rsbegin", "rsend"] { - let obj = RTSTARTUP_SYSROOT.to_path(dirs).join(format!("{file}.o")); + let obj = rtstartup_sysroot.join(format!("{file}.o")); let mut build_rtstartup_cmd = Command::new(&compiler.rustc); build_rtstartup_cmd .arg("--target") diff --git a/compiler/rustc_codegen_cranelift/build_system/main.rs b/compiler/rustc_codegen_cranelift/build_system/main.rs index b68ac7c0926..99e6146657f 100644 --- a/compiler/rustc_codegen_cranelift/build_system/main.rs +++ b/compiler/rustc_codegen_cranelift/build_system/main.rs @@ -185,12 +185,11 @@ fn main() { frozen, }; - path::RelPath::BUILD.ensure_exists(&dirs); + std::fs::create_dir_all(&dirs.build_dir).unwrap(); { // Make sure we always explicitly specify the target dir - let target = - path::RelPath::BUILD.join("target_dir_should_be_set_explicitly").to_path(&dirs); + let target = dirs.build_dir.join("target_dir_should_be_set_explicitly"); env::set_var("CARGO_TARGET_DIR", &target); let _ = std::fs::remove_file(&target); std::fs::File::create(target).unwrap(); diff --git a/compiler/rustc_codegen_cranelift/build_system/path.rs b/compiler/rustc_codegen_cranelift/build_system/path.rs index 35e7e81c528..20a81156b71 100644 --- a/compiler/rustc_codegen_cranelift/build_system/path.rs +++ b/compiler/rustc_codegen_cranelift/build_system/path.rs @@ -1,8 +1,5 @@ -use std::fs; use std::path::PathBuf; -use crate::utils::ensure_empty_dir; - #[derive(Debug, Clone)] pub(crate) struct Dirs { pub(crate) source_dir: PathBuf, @@ -16,54 +13,34 @@ pub(crate) struct Dirs { #[derive(Debug, Copy, Clone)] pub(crate) enum PathBase { Source, - Download, Build, - Dist, } impl PathBase { fn to_path(self, dirs: &Dirs) -> PathBuf { match self { PathBase::Source => dirs.source_dir.clone(), - PathBase::Download => dirs.download_dir.clone(), PathBase::Build => dirs.build_dir.clone(), - PathBase::Dist => dirs.dist_dir.clone(), } } } #[derive(Debug, Copy, Clone)] -pub(crate) enum RelPath { - Base(PathBase), - Join(&'static RelPath, &'static str), +pub(crate) struct RelPath { + base: PathBase, + suffix: &'static str, } impl RelPath { - pub(crate) const SOURCE: RelPath = RelPath::Base(PathBase::Source); - pub(crate) const DOWNLOAD: RelPath = RelPath::Base(PathBase::Download); - pub(crate) const BUILD: RelPath = RelPath::Base(PathBase::Build); - pub(crate) const DIST: RelPath = RelPath::Base(PathBase::Dist); - - pub(crate) const SCRIPTS: RelPath = RelPath::SOURCE.join("scripts"); - pub(crate) const PATCHES: RelPath = RelPath::SOURCE.join("patches"); - - pub(crate) const fn join(&'static self, suffix: &'static str) -> RelPath { - RelPath::Join(self, suffix) + pub(crate) const fn source(suffix: &'static str) -> RelPath { + RelPath { base: PathBase::Source, suffix } } - pub(crate) fn to_path(&self, dirs: &Dirs) -> PathBuf { - match self { - RelPath::Base(base) => base.to_path(dirs), - RelPath::Join(base, suffix) => base.to_path(dirs).join(suffix), - } - } - - pub(crate) fn ensure_exists(&self, dirs: &Dirs) { - fs::create_dir_all(self.to_path(dirs)).unwrap(); + pub(crate) const fn build(suffix: &'static str) -> RelPath { + RelPath { base: PathBase::Build, suffix } } - pub(crate) fn ensure_fresh(&self, dirs: &Dirs) { - let path = self.to_path(dirs); - ensure_empty_dir(&path); + pub(crate) fn to_path(&self, dirs: &Dirs) -> PathBuf { + self.base.to_path(dirs).join(self.suffix) } } diff --git a/compiler/rustc_codegen_cranelift/build_system/prepare.rs b/compiler/rustc_codegen_cranelift/build_system/prepare.rs index c6f979f0278..a4e9cb5f5c8 100644 --- a/compiler/rustc_codegen_cranelift/build_system/prepare.rs +++ b/compiler/rustc_codegen_cranelift/build_system/prepare.rs @@ -8,7 +8,7 @@ use crate::path::{Dirs, RelPath}; use crate::utils::{copy_dir_recursively, ensure_empty_dir, spawn_and_wait}; pub(crate) fn prepare(dirs: &Dirs) { - RelPath::DOWNLOAD.ensure_exists(dirs); + std::fs::create_dir_all(&dirs.download_dir).unwrap(); crate::tests::RAND_REPO.fetch(dirs); crate::tests::REGEX_REPO.fetch(dirs); } @@ -79,13 +79,13 @@ impl GitRepo { fn download_dir(&self, dirs: &Dirs) -> PathBuf { match self.url { - GitRepoUrl::Github { user: _, repo } => RelPath::DOWNLOAD.join(repo).to_path(dirs), + GitRepoUrl::Github { user: _, repo } => dirs.download_dir.join(repo), } } pub(crate) const fn source_dir(&self) -> RelPath { match self.url { - GitRepoUrl::Github { user: _, repo } => RelPath::BUILD.join(repo), + GitRepoUrl::Github { user: _, repo } => RelPath::build(repo), } } @@ -130,7 +130,7 @@ impl GitRepo { } let source_lockfile = - RelPath::PATCHES.to_path(dirs).join(format!("{}-lock.toml", self.patch_name)); + dirs.source_dir.join("patches").join(format!("{}-lock.toml", self.patch_name)); let target_lockfile = download_dir.join("Cargo.lock"); if source_lockfile.exists() { assert!(!target_lockfile.exists()); @@ -191,7 +191,7 @@ fn init_git_repo(repo_dir: &Path) { } fn get_patches(dirs: &Dirs, crate_name: &str) -> Vec<PathBuf> { - let mut patches: Vec<_> = fs::read_dir(RelPath::PATCHES.to_path(dirs)) + let mut patches: Vec<_> = fs::read_dir(dirs.source_dir.join("patches")) .unwrap() .map(|entry| entry.unwrap().path()) .filter(|path| path.extension() == Some(OsStr::new("patch"))) diff --git a/compiler/rustc_codegen_cranelift/build_system/tests.rs b/compiler/rustc_codegen_cranelift/build_system/tests.rs index fd94e80f631..08736db8ba0 100644 --- a/compiler/rustc_codegen_cranelift/build_system/tests.rs +++ b/compiler/rustc_codegen_cranelift/build_system/tests.rs @@ -7,10 +7,10 @@ use crate::path::{Dirs, RelPath}; use crate::prepare::{GitRepo, apply_patches}; use crate::rustc_info::get_default_sysroot; use crate::shared_utils::rustflags_from_env; -use crate::utils::{CargoProject, Compiler, LogGroup, spawn_and_wait}; +use crate::utils::{CargoProject, Compiler, LogGroup, ensure_empty_dir, spawn_and_wait}; use crate::{CodegenBackend, SysrootKind, build_sysroot, config}; -static BUILD_EXAMPLE_OUT_DIR: RelPath = RelPath::BUILD.join("example"); +static BUILD_EXAMPLE_OUT_DIR: RelPath = RelPath::build("example"); struct TestCase { config: &'static str, @@ -92,10 +92,6 @@ const BASE_SYSROOT_SUITE: &[TestCase] = &[ TestCase::build_bin_and_run("aot.mod_bench", "example/mod_bench.rs", &[]), TestCase::build_bin_and_run("aot.issue-72793", "example/issue-72793.rs", &[]), TestCase::build_bin("aot.issue-59326", "example/issue-59326.rs"), - TestCase::custom("aot.polymorphize_coroutine", &|runner| { - runner.run_rustc(&["example/polymorphize_coroutine.rs", "-Zpolymorphize"]); - runner.run_out_command("polymorphize_coroutine", &[]); - }), TestCase::build_bin_and_run("aot.neon", "example/neon.rs", &[]), TestCase::custom("aot.gen_block_iterate", &|runner| { runner.run_rustc([ @@ -129,11 +125,11 @@ pub(crate) static REGEX_REPO: GitRepo = GitRepo::github( static REGEX: CargoProject = CargoProject::new(®EX_REPO.source_dir(), "regex_target"); -static PORTABLE_SIMD_SRC: RelPath = RelPath::BUILD.join("portable-simd"); +static PORTABLE_SIMD_SRC: RelPath = RelPath::build("portable-simd"); static PORTABLE_SIMD: CargoProject = CargoProject::new(&PORTABLE_SIMD_SRC, "portable-simd_target"); -static LIBCORE_TESTS_SRC: RelPath = RelPath::BUILD.join("coretests"); +static LIBCORE_TESTS_SRC: RelPath = RelPath::build("coretests"); static LIBCORE_TESTS: CargoProject = CargoProject::new(&LIBCORE_TESTS_SRC, "coretests_target"); @@ -162,7 +158,7 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[ &LIBCORE_TESTS_SRC.to_path(&runner.dirs), ); - let source_lockfile = RelPath::PATCHES.to_path(&runner.dirs).join("coretests-lock.toml"); + let source_lockfile = runner.dirs.source_dir.join("patches/coretests-lock.toml"); let target_lockfile = LIBCORE_TESTS_SRC.to_path(&runner.dirs).join("Cargo.lock"); fs::copy(source_lockfile, target_lockfile).unwrap(); @@ -267,7 +263,9 @@ pub(crate) fn run_tests( stdlib_source.clone(), ); - BUILD_EXAMPLE_OUT_DIR.ensure_fresh(dirs); + let path = BUILD_EXAMPLE_OUT_DIR.to_path(dirs); + ensure_empty_dir(&path); + runner.run_testsuite(NO_SYSROOT_SUITE); } else { eprintln!("[SKIP] no_sysroot tests"); diff --git a/compiler/rustc_codegen_cranelift/build_system/utils.rs b/compiler/rustc_codegen_cranelift/build_system/utils.rs index 22a9487a202..c2114caf869 100644 --- a/compiler/rustc_codegen_cranelift/build_system/utils.rs +++ b/compiler/rustc_codegen_cranelift/build_system/utils.rs @@ -93,7 +93,7 @@ impl CargoProject { } pub(crate) fn target_dir(&self, dirs: &Dirs) -> PathBuf { - RelPath::BUILD.join(self.target).to_path(dirs) + dirs.build_dir.join(self.target) } #[must_use] diff --git a/compiler/rustc_codegen_cranelift/config.txt b/compiler/rustc_codegen_cranelift/config.txt index 527ec5303b6..b63597f60fc 100644 --- a/compiler/rustc_codegen_cranelift/config.txt +++ b/compiler/rustc_codegen_cranelift/config.txt @@ -42,7 +42,6 @@ aot.float-minmax-pass aot.mod_bench aot.issue-72793 aot.issue-59326 -aot.polymorphize_coroutine aot.neon aot.gen_block_iterate aot.raw-dylib diff --git a/compiler/rustc_codegen_cranelift/example/polymorphize_coroutine.rs b/compiler/rustc_codegen_cranelift/example/polymorphize_coroutine.rs deleted file mode 100644 index 407da94c0f0..00000000000 --- a/compiler/rustc_codegen_cranelift/example/polymorphize_coroutine.rs +++ /dev/null @@ -1,17 +0,0 @@ -#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] - -use std::ops::Coroutine; -use std::pin::Pin; - -fn main() { - run_coroutine::<i32>(); -} - -fn run_coroutine<T>() { - let mut coroutine = #[coroutine] - || { - yield; - return; - }; - Pin::new(&mut coroutine).resume(()); -} diff --git a/compiler/rustc_codegen_cranelift/example/std_example.rs b/compiler/rustc_codegen_cranelift/example/std_example.rs index 3078288c286..0b1d83c5630 100644 --- a/compiler/rustc_codegen_cranelift/example/std_example.rs +++ b/compiler/rustc_codegen_cranelift/example/std_example.rs @@ -8,6 +8,9 @@ unboxed_closures )] #![allow(internal_features)] +// FIXME once abi_unsupported_vector_types is a hard error disable the foo test when the respective +// target feature is not enabled. +#![allow(abi_unsupported_vector_types)] #[cfg(target_arch = "x86_64")] use std::arch::x86_64::*; diff --git a/compiler/rustc_codegen_cranelift/patches/0022-coretests-Disable-not-compiling-tests.patch b/compiler/rustc_codegen_cranelift/patches/0022-coretests-Disable-not-compiling-tests.patch index 1860810e7f3..161173d4765 100644 --- a/compiler/rustc_codegen_cranelift/patches/0022-coretests-Disable-not-compiling-tests.patch +++ b/compiler/rustc_codegen_cranelift/patches/0022-coretests-Disable-not-compiling-tests.patch @@ -38,7 +38,7 @@ index 42a26ae..5ac1042 100644 @@ -1,3 +1,4 @@ +#![cfg(test)] // tidy-alphabetical-start - #![cfg_attr(bootstrap, feature(const_three_way_compare))] - #![cfg_attr(bootstrap, feature(strict_provenance))] + #![cfg_attr(target_has_atomic = "128", feature(integer_atomics))] + #![cfg_attr(test, feature(cfg_match))] -- 2.21.0 (Apple Git-122) diff --git a/compiler/rustc_codegen_cranelift/patches/0027-coretests-128bit-atomic-operations.patch b/compiler/rustc_codegen_cranelift/patches/0027-coretests-128bit-atomic-operations.patch index 59653c6e875..06840624cef 100644 --- a/compiler/rustc_codegen_cranelift/patches/0027-coretests-128bit-atomic-operations.patch +++ b/compiler/rustc_codegen_cranelift/patches/0027-coretests-128bit-atomic-operations.patch @@ -14,10 +14,9 @@ diff --git a/lib.rs b/lib.rs index 1e336bf..35e6f54 100644 --- a/lib.rs +++ b/lib.rs -@@ -2,7 +2,6 @@ - #![cfg_attr(bootstrap, feature(const_three_way_compare))] - #![cfg_attr(bootstrap, feature(strict_provenance))] - #![cfg_attr(not(bootstrap), feature(strict_provenance_lints))] +@@ -2,6 +2,5 @@ + #![cfg(test)] + // tidy-alphabetical-start -#![cfg_attr(target_has_atomic = "128", feature(integer_atomics))] #![cfg_attr(test, feature(cfg_match))] #![feature(alloc_layout_extra)] diff --git a/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch b/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch index ada35145e29..6012af6a8dd 100644 --- a/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch +++ b/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch @@ -4,22 +4,23 @@ Date: Fri, 9 Aug 2024 15:44:51 +0000 Subject: [PATCH] Disable f16 and f128 in compiler-builtins --- - library/sysroot/Cargo.toml | 2 +- + library/liballoc/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) -diff --git a/library/sysroot/Cargo.toml b/library/sysroot/Cargo.toml +diff --git a/library/liballoc/Cargo.toml b/library/liballoc/Cargo.toml index 7165c3e48af..968552ad435 100644 ---- a/library/sysroot/Cargo.toml -+++ b/library/sysroot/Cargo.toml +--- a/library/alloc/Cargo.toml ++++ b/library/alloc/Cargo.toml @@ -11,7 +11,7 @@ test = { path = "../test" } + edition = "2021" - # Forward features to the `std` crate as necessary - [features] --default = ["std_detect_file_io", "std_detect_dlsym_getauxval", "panic-unwind"] -+default = ["std_detect_file_io", "std_detect_dlsym_getauxval", "panic-unwind", "compiler-builtins-no-f16-f128"] - backtrace = ["std/backtrace"] - compiler-builtins-c = ["std/compiler-builtins-c"] - compiler-builtins-mem = ["std/compiler-builtins-mem"] + [dependencies] + core = { path = "../core" } +-compiler_builtins = { version = "=0.1.138", features = ['rustc-dep-of-std'] } ++compiler_builtins = { version = "=0.1.138", features = ['rustc-dep-of-std', 'no-f16-f128'] } + + [dev-dependencies] + rand = { version = "0.8.5", default-features = false, features = ["alloc"] } -- 2.34.1 diff --git a/compiler/rustc_codegen_cranelift/rust-toolchain b/compiler/rustc_codegen_cranelift/rust-toolchain index a223cd7dbb8..8d935df4d1f 100644 --- a/compiler/rustc_codegen_cranelift/rust-toolchain +++ b/compiler/rustc_codegen_cranelift/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2024-11-09" +channel = "nightly-2024-12-06" components = ["rust-src", "rustc-dev", "llvm-tools"] profile = "minimal" diff --git a/compiler/rustc_codegen_cranelift/scripts/rustc-clif.rs b/compiler/rustc_codegen_cranelift/scripts/rustc-clif.rs index 92defd21cd9..a27b9983bf1 100644 --- a/compiler/rustc_codegen_cranelift/scripts/rustc-clif.rs +++ b/compiler/rustc_codegen_cranelift/scripts/rustc-clif.rs @@ -33,6 +33,11 @@ fn main() { args.push(OsString::from("--sysroot")); args.push(OsString::from(sysroot.to_str().unwrap())); } + if passed_args.is_empty() { + // Don't pass any arguments when the user didn't pass any arguments + // either to ensure the help message is shown. + args.clear(); + } args.extend(passed_args); let rustc = if let Some(rustc) = option_env!("RUSTC") { diff --git a/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh b/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh index 5b3f2a91207..54f6baff4fe 100644 --- a/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh +++ b/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh @@ -35,13 +35,14 @@ full-bootstrap = true local-rebuild = true [rust] +download-rustc = false codegen-backends = ["cranelift"] deny-warnings = false verbose-tests = false # The cg_clif sysroot doesn't contain llvm tools and unless llvm_tools is # disabled bootstrap will crash trying to copy llvm tools for the bootstrap # compiler. -llvm_tools = false +llvm-tools = false EOF popd diff --git a/compiler/rustc_codegen_cranelift/scripts/test_bootstrap.sh b/compiler/rustc_codegen_cranelift/scripts/test_bootstrap.sh index 770f2b6df6c..791d457993d 100755 --- a/compiler/rustc_codegen_cranelift/scripts/test_bootstrap.sh +++ b/compiler/rustc_codegen_cranelift/scripts/test_bootstrap.sh @@ -11,22 +11,5 @@ rm -r compiler/rustc_codegen_cranelift/{Cargo.*,src} cp ../Cargo.* compiler/rustc_codegen_cranelift/ cp -r ../src compiler/rustc_codegen_cranelift/src -# FIXME(rust-lang/rust#132719) remove once it doesn't break without this patch -cat <<EOF | git apply - -diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs -index 3394f2a84a0..cb980dd4d7c 100644 ---- a/src/bootstrap/src/core/build_steps/compile.rs -+++ b/src/bootstrap/src/core/build_steps/compile.rs -@@ -1976,7 +1976,7 @@ fn run(self, builder: &Builder<'_>) -> Compiler { - } - } - -- { -+ if builder.config.llvm_enabled(target_compiler.host) && builder.config.llvm_tools_enabled { - // \`llvm-strip\` is used by rustc, which is actually just a symlink to \`llvm-objcopy\`, - // so copy and rename \`llvm-objcopy\`. - let src_exe = exe("llvm-objcopy", target_compiler.host); -EOF - ./x.py build --stage 1 library/std popd diff --git a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh index a820da286f5..e291ec20464 100755 --- a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh +++ b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh @@ -57,6 +57,7 @@ rm tests/ui/asm/x86_64/issue-96797.rs # const and sym inline asm operands don't rm tests/ui/asm/x86_64/goto.rs # inline asm labels not supported rm tests/ui/simd/simd-bitmask-notpow2.rs # non-pow-of-2 simd vector sizes rm -r tests/run-make/embed-source-dwarf # embedding sources in debuginfo +rm tests/ui/simd-abi-checks.rs # vector types >128bits not yet supported # requires LTO rm -r tests/run-make/cdylib @@ -75,6 +76,8 @@ rm -r tests/ui/instrument-coverage/ rm tests/ui/half-open-range-patterns/half-open-range-pats-semantics.rs rm tests/ui/asm/aarch64/type-f16.rs rm tests/ui/float/conv-bits-runtime-const.rs +rm tests/ui/consts/const-eval/float_methods.rs +rm tests/ui/match/match-float.rs # optimization tests # ================== diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs index cab5b35c18d..2466bfe60c7 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs @@ -125,8 +125,9 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> { returns: Vec<AbiParam>, args: &[Value], ) -> Cow<'_, [Value]> { - if self.tcx.sess.target.is_like_windows { - let (mut params, mut args): (Vec<_>, Vec<_>) = params + // Pass i128 arguments by-ref on Windows. + let (params, args): (Vec<_>, Cow<'_, [_]>) = if self.tcx.sess.target.is_like_windows { + let (params, args): (Vec<_>, Vec<_>) = params .into_iter() .zip(args) .map(|(param, &arg)| { @@ -140,29 +141,42 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> { }) .unzip(); - let indirect_ret_val = returns.len() == 1 && returns[0].value_type == types::I128; + (params, args.into()) + } else { + (params, args.into()) + }; - if indirect_ret_val { - params.insert(0, AbiParam::new(self.pointer_type)); - let ret_ptr = self.create_stack_slot(16, 16); - args.insert(0, ret_ptr.get_addr(self)); - self.lib_call_unadjusted(name, params, vec![], &args); - return Cow::Owned(vec![ret_ptr.load(self, types::I128, MemFlags::trusted())]); + // Return i128 using a return area pointer on Windows and s390x. + let adjust_ret_param = + if self.tcx.sess.target.is_like_windows || self.tcx.sess.target.arch == "s390x" { + returns.len() == 1 && returns[0].value_type == types::I128 } else { - return self.lib_call_unadjusted(name, params, returns, &args); - } - } + false + }; + + if adjust_ret_param { + let mut params = params; + let mut args = args.to_vec(); + + params.insert(0, AbiParam::new(self.pointer_type)); + let ret_ptr = self.create_stack_slot(16, 16); + args.insert(0, ret_ptr.get_addr(self)); - self.lib_call_unadjusted(name, params, returns, args) + self.lib_call_unadjusted(name, params, vec![], &args); + + Cow::Owned(vec![ret_ptr.load(self, types::I128, MemFlags::trusted())]) + } else { + Cow::Borrowed(self.lib_call_unadjusted(name, params, returns, &args)) + } } - pub(crate) fn lib_call_unadjusted( + fn lib_call_unadjusted( &mut self, name: &str, params: Vec<AbiParam>, returns: Vec<AbiParam>, args: &[Value], - ) -> Cow<'_, [Value]> { + ) -> &[Value] { let sig = Signature { params, returns, call_conv: self.target_config.default_call_conv }; let func_id = self.module.declare_function(name, Linkage::Import, &sig).unwrap(); let func_ref = self.module.declare_func_in_func(func_id, &mut self.bcx.func); @@ -175,7 +189,7 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> { } let results = self.bcx.inst_results(call_inst); assert!(results.len() <= 2, "{}", results.len()); - Cow::Borrowed(results) + results } } @@ -380,8 +394,7 @@ pub(crate) fn codegen_terminator_call<'tcx>( def_id, fn_args, source_info.span, - ) - .polymorphize(fx.tcx); + ); if is_call_from_compiler_builtins_to_upstream_monomorphization(fx.tcx, instance) { if target.is_some() { @@ -684,7 +697,7 @@ pub(crate) fn codegen_drop<'tcx>( target: BasicBlock, ) { let ty = drop_place.layout().ty; - let drop_instance = Instance::resolve_drop_in_place(fx.tcx, ty).polymorphize(fx.tcx); + let drop_instance = Instance::resolve_drop_in_place(fx.tcx, ty); if let ty::InstanceKind::DropGlue(_, None) | ty::InstanceKind::AsyncDropGlueCtorShim(_, None) = drop_instance.def diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index 06cc5754894..34066eb83fc 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -6,6 +6,7 @@ use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext}; use cranelift_module::ModuleError; use rustc_ast::InlineAsmOptions; use rustc_codegen_ssa::base::is_call_from_compiler_builtins_to_upstream_monomorphization; +use rustc_data_structures::profiling::SelfProfilerRef; use rustc_index::IndexVec; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::InlineAsmMacro; @@ -16,6 +17,7 @@ use rustc_middle::ty::print::with_no_trimmed_paths; use crate::constant::ConstantCx; use crate::debuginfo::{FunctionDebugContext, TypeDebugContext}; +use crate::enable_verifier; use crate::inline_asm::codegen_naked_asm; use crate::prelude::*; use crate::pretty_clif::CommentWriter; @@ -169,12 +171,13 @@ pub(crate) fn codegen_fn<'tcx>( pub(crate) fn compile_fn( cx: &mut crate::CodegenCx, + profiler: &SelfProfilerRef, cached_context: &mut Context, module: &mut dyn Module, codegened_func: CodegenedFunction, ) { let _timer = - cx.profiler.generic_activity_with_arg("compile function", &*codegened_func.symbol_name); + profiler.generic_activity_with_arg("compile function", &*codegened_func.symbol_name); let clif_comments = codegened_func.clif_comments; @@ -212,7 +215,7 @@ pub(crate) fn compile_fn( }; // Define function - cx.profiler.generic_activity("define function").run(|| { + profiler.generic_activity("define function").run(|| { context.want_disasm = cx.should_write_ir; match module.define_function(codegened_func.func_id, context) { Ok(()) => {} @@ -253,7 +256,7 @@ pub(crate) fn compile_fn( // Define debuginfo for function let debug_context = &mut cx.debug_context; - cx.profiler.generic_activity("generate debug info").run(|| { + profiler.generic_activity("generate debug info").run(|| { if let Some(debug_context) = debug_context { codegened_func.func_debug_cx.unwrap().finalize( debug_context, @@ -264,11 +267,11 @@ pub(crate) fn compile_fn( }); } -pub(crate) fn verify_func( - tcx: TyCtxt<'_>, - writer: &crate::pretty_clif::CommentWriter, - func: &Function, -) { +fn verify_func(tcx: TyCtxt<'_>, writer: &crate::pretty_clif::CommentWriter, func: &Function) { + if !enable_verifier(tcx.sess) { + return; + } + tcx.prof.generic_activity("verify clif ir").run(|| { let flags = cranelift_codegen::settings::Flags::new(cranelift_codegen::settings::builder()); match cranelift_codegen::verify_function(&func, &flags) { @@ -670,8 +673,7 @@ fn codegen_stmt<'tcx>( def_id, args, ) - .unwrap() - .polymorphize(fx.tcx), + .unwrap(), ); let func_addr = fx.bcx.ins().func_addr(fx.pointer_type, func_ref); lval.write_cvalue(fx, CValue::by_val(func_addr, to_layout)); @@ -757,8 +759,7 @@ fn codegen_stmt<'tcx>( def_id, args, ty::ClosureKind::FnOnce, - ) - .polymorphize(fx.tcx); + ); let func_ref = fx.get_function_ref(instance); let func_addr = fx.bcx.ins().func_addr(fx.pointer_type, func_ref); lval.write_cvalue(fx, CValue::by_val(func_addr, lval.layout())); @@ -1084,7 +1085,7 @@ fn codegen_panic_inner<'tcx>( let def_id = fx.tcx.require_lang_item(lang_item, span); - let instance = Instance::mono(fx.tcx, def_id).polymorphize(fx.tcx); + let instance = Instance::mono(fx.tcx, def_id); if is_call_from_compiler_builtins_to_upstream_monomorphization(fx.tcx, instance) { fx.bcx.ins().trap(TrapCode::user(2).unwrap()); diff --git a/compiler/rustc_codegen_cranelift/src/codegen_i128.rs b/compiler/rustc_codegen_cranelift/src/codegen_i128.rs index b6a4769e031..734574338d0 100644 --- a/compiler/rustc_codegen_cranelift/src/codegen_i128.rs +++ b/compiler/rustc_codegen_cranelift/src/codegen_i128.rs @@ -81,26 +81,6 @@ pub(crate) fn maybe_codegen_checked<'tcx>( match bin_op { BinOp::BitAnd | BinOp::BitOr | BinOp::BitXor => unreachable!(), BinOp::Add | BinOp::Sub => None, - BinOp::Mul if is_signed => { - let out_ty = Ty::new_tup(fx.tcx, &[lhs.layout().ty, fx.tcx.types.bool]); - let oflow = CPlace::new_stack_slot(fx, fx.layout_of(fx.tcx.types.i32)); - let lhs = lhs.load_scalar(fx); - let rhs = rhs.load_scalar(fx); - let oflow_ptr = oflow.to_ptr().get_addr(fx); - let res = fx.lib_call_unadjusted( - "__muloti4", - vec![ - AbiParam::new(types::I128), - AbiParam::new(types::I128), - AbiParam::new(fx.pointer_type), - ], - vec![AbiParam::new(types::I128)], - &[lhs, rhs, oflow_ptr], - )[0]; - let oflow = oflow.to_cvalue(fx).load_scalar(fx); - let oflow = fx.bcx.ins().ireduce(types::I8, oflow); - Some(CValue::by_val_pair(res, oflow, fx.layout_of(out_ty))) - } BinOp::Mul => { let out_ty = Ty::new_tup(fx.tcx, &[lhs.layout().ty, fx.tcx.types.bool]); let out_place = CPlace::new_stack_slot(fx, fx.layout_of(out_ty)); @@ -110,7 +90,12 @@ pub(crate) fn maybe_codegen_checked<'tcx>( AbiParam::new(types::I128), ]; let args = [out_place.to_ptr().get_addr(fx), lhs.load_scalar(fx), rhs.load_scalar(fx)]; - fx.lib_call("__rust_u128_mulo", param_types, vec![], &args); + fx.lib_call( + if is_signed { "__rust_i128_mulo" } else { "__rust_u128_mulo" }, + param_types, + vec![], + &args, + ); Some(out_place.to_cvalue(fx)) } BinOp::AddUnchecked | BinOp::SubUnchecked | BinOp::MulUnchecked => unreachable!(), diff --git a/compiler/rustc_codegen_cranelift/src/config.rs b/compiler/rustc_codegen_cranelift/src/config.rs index 12bce680d9e..d784f6e9d9e 100644 --- a/compiler/rustc_codegen_cranelift/src/config.rs +++ b/compiler/rustc_codegen_cranelift/src/config.rs @@ -1,10 +1,3 @@ -use std::env; -use std::str::FromStr; - -fn bool_env_var(key: &str) -> bool { - env::var(key).as_deref() == Ok("1") -} - /// The mode to use for compilation. #[derive(Copy, Clone, Debug)] pub enum CodegenMode { @@ -16,19 +9,6 @@ pub enum CodegenMode { JitLazy, } -impl FromStr for CodegenMode { - type Err = String; - - fn from_str(s: &str) -> Result<Self, Self::Err> { - match s { - "aot" => Ok(CodegenMode::Aot), - "jit" => Ok(CodegenMode::Jit), - "jit-lazy" => Ok(CodegenMode::JitLazy), - _ => Err(format!("Unknown codegen mode `{}`", s)), - } - } -} - /// Configuration of cg_clif as passed in through `-Cllvm-args` and various env vars. #[derive(Clone, Debug)] pub struct BackendConfig { @@ -41,51 +21,22 @@ pub struct BackendConfig { /// /// Defaults to the value of `CG_CLIF_JIT_ARGS`. pub jit_args: Vec<String>, - - /// Enable the Cranelift ir verifier for all compilation passes. If not set it will only run - /// once before passing the clif ir to Cranelift for compilation. - /// - /// Defaults to true when the `CG_CLIF_ENABLE_VERIFIER` env var is set to 1 or when cg_clif is - /// compiled with debug assertions enabled or false otherwise. Can be set using - /// `-Cllvm-args=enable_verifier=...`. - pub enable_verifier: bool, - - /// Don't cache object files in the incremental cache. Useful during development of cg_clif - /// to make it possible to use incremental mode for all analyses performed by rustc without - /// caching object files when their content should have been changed by a change to cg_clif. - /// - /// Defaults to true when the `CG_CLIF_DISABLE_INCR_CACHE` env var is set to 1 or false - /// otherwise. Can be set using `-Cllvm-args=disable_incr_cache=...`. - pub disable_incr_cache: bool, -} - -impl Default for BackendConfig { - fn default() -> Self { - BackendConfig { - codegen_mode: CodegenMode::Aot, - jit_args: { - match std::env::var("CG_CLIF_JIT_ARGS") { - Ok(args) => args.split(' ').map(|arg| arg.to_string()).collect(), - Err(std::env::VarError::NotPresent) => vec![], - Err(std::env::VarError::NotUnicode(s)) => { - panic!("CG_CLIF_JIT_ARGS not unicode: {:?}", s); - } - } - }, - enable_verifier: cfg!(debug_assertions) || bool_env_var("CG_CLIF_ENABLE_VERIFIER"), - disable_incr_cache: bool_env_var("CG_CLIF_DISABLE_INCR_CACHE"), - } - } } impl BackendConfig { /// Parse the configuration passed in using `-Cllvm-args`. pub fn from_opts(opts: &[String]) -> Result<Self, String> { - fn parse_bool(name: &str, value: &str) -> Result<bool, String> { - value.parse().map_err(|_| format!("failed to parse value `{}` for {}", value, name)) - } + let mut config = BackendConfig { + codegen_mode: CodegenMode::Aot, + jit_args: match std::env::var("CG_CLIF_JIT_ARGS") { + Ok(args) => args.split(' ').map(|arg| arg.to_string()).collect(), + Err(std::env::VarError::NotPresent) => vec![], + Err(std::env::VarError::NotUnicode(s)) => { + panic!("CG_CLIF_JIT_ARGS not unicode: {:?}", s); + } + }, + }; - let mut config = BackendConfig::default(); for opt in opts { if opt.starts_with("-import-instr-limit") { // Silently ignore -import-instr-limit. It is set by rust's build system even when @@ -94,9 +45,14 @@ impl BackendConfig { } if let Some((name, value)) = opt.split_once('=') { match name { - "mode" => config.codegen_mode = value.parse()?, - "enable_verifier" => config.enable_verifier = parse_bool(name, value)?, - "disable_incr_cache" => config.disable_incr_cache = parse_bool(name, value)?, + "mode" => { + config.codegen_mode = match value { + "aot" => CodegenMode::Aot, + "jit" => CodegenMode::Jit, + "jit-lazy" => CodegenMode::JitLazy, + _ => return Err(format!("Unknown codegen mode `{}`", value)), + }; + } _ => return Err(format!("Unknown option `{}`", name)), } } else { diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index abe6085b04f..3e7b81a96b6 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -452,8 +452,7 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant let data_id = match reloc_target_alloc { GlobalAlloc::Function { instance, .. } => { assert_eq!(addend, 0); - let func_id = - crate::abi::import_function(tcx, module, instance.polymorphize(tcx)); + let func_id = crate::abi::import_function(tcx, module, instance); let local_func_id = module.declare_func_in_data(func_id, &mut data); data.write_function_addr(offset.bytes() as u32, local_func_id); continue; diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs index 8eab73ad5f9..5bbcfc2cda7 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs @@ -1,6 +1,7 @@ //! The AOT driver uses [`cranelift_object`] to write object files suitable for linking into a //! standalone executable. +use std::env; use std::fs::{self, File}; use std::io::BufWriter; use std::path::{Path, PathBuf}; @@ -25,13 +26,18 @@ use rustc_middle::mir::mono::{CodegenUnit, MonoItem}; use rustc_session::Session; use rustc_session::config::{DebugInfo, OutFileName, OutputFilenames, OutputType}; -use crate::BackendConfig; +use crate::CodegenCx; +use crate::base::CodegenedFunction; use crate::concurrency_limiter::{ConcurrencyLimiter, ConcurrencyLimiterToken}; use crate::debuginfo::TypeDebugContext; use crate::global_asm::GlobalAsmConfig; use crate::prelude::*; use crate::unwind_module::UnwindModule; +fn disable_incr_cache() -> bool { + env::var("CG_CLIF_DISABLE_INCR_CACHE").as_deref() == Ok("1") +} + struct ModuleCodegenResult { module_regular: CompiledModule, module_global_asm: Option<CompiledModule>, @@ -63,10 +69,10 @@ impl OngoingCodegen { self, sess: &Session, outputs: &OutputFilenames, - backend_config: &BackendConfig, ) -> (CodegenResults, FxIndexMap<WorkProductId, WorkProduct>) { let mut work_products = FxIndexMap::default(); let mut modules = vec![]; + let disable_incr_cache = disable_incr_cache(); for module_codegen in self.modules { let module_codegen_result = match module_codegen { @@ -87,7 +93,7 @@ impl OngoingCodegen { if let Some((work_product_id, work_product)) = existing_work_product { work_products.insert(work_product_id, work_product); } else { - let work_product = if backend_config.disable_incr_cache { + let work_product = if disable_incr_cache { None } else if let Some(module_global_asm) = &module_global_asm { rustc_incremental::copy_cgu_workproduct_to_incr_comp_cache_dir( @@ -322,12 +328,8 @@ fn produce_final_output_artifacts( // These are used in linking steps and will be cleaned up afterward. } -fn make_module( - sess: &Session, - backend_config: &BackendConfig, - name: String, -) -> UnwindModule<ObjectModule> { - let isa = crate::build_isa(sess, backend_config); +fn make_module(sess: &Session, name: String) -> UnwindModule<ObjectModule> { + let isa = crate::build_isa(sess); let mut builder = ObjectBuilder::new(isa, name + ".o", cranelift_module::default_libcall_names()).unwrap(); @@ -412,7 +414,13 @@ fn emit_module( Err(err) => return Err(format!("error writing object file: {}", err)), }; - prof.artifact_size("object_file", &*name, file.metadata().unwrap().len()); + if prof.enabled() { + prof.artifact_size( + "object_file", + tmp_file.file_name().unwrap().to_string_lossy(), + file.metadata().unwrap().len(), + ); + } Ok(CompiledModule { name, @@ -486,91 +494,101 @@ fn reuse_workproduct_for_cgu( }) } +fn codegen_cgu_content( + tcx: TyCtxt<'_>, + module: &mut dyn Module, + cgu_name: rustc_span::Symbol, +) -> (CodegenCx, Vec<CodegenedFunction>) { + let _timer = tcx.prof.generic_activity_with_arg("codegen cgu", cgu_name.as_str()); + + let cgu = tcx.codegen_unit(cgu_name); + let mono_items = cgu.items_in_deterministic_order(tcx); + + let mut cx = crate::CodegenCx::new( + tcx, + module.isa(), + tcx.sess.opts.debuginfo != DebugInfo::None, + cgu_name, + ); + let mut type_dbg = TypeDebugContext::default(); + super::predefine_mono_items(tcx, module, &mono_items); + let mut codegened_functions = vec![]; + for (mono_item, _) in mono_items { + match mono_item { + MonoItem::Fn(inst) => { + if let Some(codegened_function) = crate::base::codegen_fn( + tcx, + &mut cx, + &mut type_dbg, + Function::new(), + module, + inst, + ) { + codegened_functions.push(codegened_function); + } + } + MonoItem::Static(def_id) => { + let data_id = crate::constant::codegen_static(tcx, module, def_id); + if let Some(debug_context) = &mut cx.debug_context { + debug_context.define_static(tcx, &mut type_dbg, def_id, data_id); + } + } + MonoItem::GlobalAsm(item_id) => { + crate::global_asm::codegen_global_asm_item(tcx, &mut cx.global_asm, item_id); + } + } + } + crate::main_shim::maybe_create_entry_wrapper(tcx, module, false, cgu.is_primary()); + + (cx, codegened_functions) +} + fn module_codegen( tcx: TyCtxt<'_>, - (backend_config, global_asm_config, cgu_name, token): ( - BackendConfig, + (global_asm_config, cgu_name, token): ( Arc<GlobalAsmConfig>, rustc_span::Symbol, ConcurrencyLimiterToken, ), ) -> OngoingModuleCodegen { - let (cgu_name, mut cx, mut module, codegened_functions) = - tcx.prof.generic_activity_with_arg("codegen cgu", cgu_name.as_str()).run(|| { - let cgu = tcx.codegen_unit(cgu_name); - let mono_items = cgu.items_in_deterministic_order(tcx); - - let mut module = make_module(tcx.sess, &backend_config, cgu_name.as_str().to_string()); - - let mut cx = crate::CodegenCx::new( - tcx, - module.isa(), - tcx.sess.opts.debuginfo != DebugInfo::None, - cgu_name, - ); - let mut type_dbg = TypeDebugContext::default(); - super::predefine_mono_items(tcx, &mut module, &mono_items); - let mut codegened_functions = vec![]; - for (mono_item, _) in mono_items { - match mono_item { - MonoItem::Fn(inst) => { - if let Some(codegened_function) = crate::base::codegen_fn( - tcx, - &mut cx, - &mut type_dbg, - Function::new(), - &mut module, - inst, - ) { - codegened_functions.push(codegened_function); - } - } - MonoItem::Static(def_id) => { - let data_id = crate::constant::codegen_static(tcx, &mut module, def_id); - if let Some(debug_context) = &mut cx.debug_context { - debug_context.define_static(tcx, &mut type_dbg, def_id, data_id); - } - } - MonoItem::GlobalAsm(item_id) => { - crate::global_asm::codegen_global_asm_item( - tcx, - &mut cx.global_asm, - item_id, - ); - } - } - } - crate::main_shim::maybe_create_entry_wrapper(tcx, &mut module, false, cgu.is_primary()); + let mut module = make_module(tcx.sess, cgu_name.as_str().to_string()); - let cgu_name = cgu.name().as_str().to_owned(); + let (mut cx, codegened_functions) = codegen_cgu_content(tcx, &mut module, cgu_name); - (cgu_name, cx, module, codegened_functions) - }); + let cgu_name = cgu_name.as_str().to_owned(); let producer = crate::debuginfo::producer(tcx.sess); + let profiler = tcx.prof.clone(); + OngoingModuleCodegen::Async(std::thread::spawn(move || { - cx.profiler.clone().generic_activity_with_arg("compile functions", &*cgu_name).run(|| { + profiler.clone().generic_activity_with_arg("compile functions", &*cgu_name).run(|| { cranelift_codegen::timing::set_thread_profiler(Box::new(super::MeasuremeProfiler( - cx.profiler.clone(), + profiler.clone(), ))); let mut cached_context = Context::new(); for codegened_func in codegened_functions { - crate::base::compile_fn(&mut cx, &mut cached_context, &mut module, codegened_func); + crate::base::compile_fn( + &mut cx, + &profiler, + &mut cached_context, + &mut module, + codegened_func, + ); } }); let global_asm_object_file = - cx.profiler.generic_activity_with_arg("compile assembly", &*cgu_name).run(|| { + profiler.generic_activity_with_arg("compile assembly", &*cgu_name).run(|| { crate::global_asm::compile_global_asm(&global_asm_config, &cgu_name, &cx.global_asm) })?; let codegen_result = - cx.profiler.generic_activity_with_arg("write object file", &*cgu_name).run(|| { + profiler.generic_activity_with_arg("write object file", &*cgu_name).run(|| { emit_cgu( &global_asm_config.output_filenames, - &cx.profiler, + &profiler, cgu_name, module, cx.debug_context, @@ -583,9 +601,63 @@ fn module_codegen( })) } +fn emit_metadata_module(tcx: TyCtxt<'_>, metadata: &EncodedMetadata) -> CompiledModule { + use rustc_middle::mir::mono::CodegenUnitNameBuilder; + + let _timer = tcx.sess.timer("write compressed metadata"); + + let cgu_name_builder = &mut CodegenUnitNameBuilder::new(tcx); + let metadata_cgu_name = cgu_name_builder + .build_cgu_name(LOCAL_CRATE, ["crate"], Some("metadata")) + .as_str() + .to_string(); + + let tmp_file = + tcx.output_filenames(()).temp_path(OutputType::Metadata, Some(&metadata_cgu_name)); + + let symbol_name = rustc_middle::middle::exported_symbols::metadata_symbol_name(tcx); + let obj = create_compressed_metadata_file(tcx.sess, metadata, &symbol_name); + + if let Err(err) = std::fs::write(&tmp_file, obj) { + tcx.dcx().fatal(format!("error writing metadata object file: {}", err)); + } + + CompiledModule { + name: metadata_cgu_name, + kind: ModuleKind::Metadata, + object: Some(tmp_file), + dwarf_object: None, + bytecode: None, + assembly: None, + llvm_ir: None, + } +} + +fn emit_allocator_module(tcx: TyCtxt<'_>) -> Option<CompiledModule> { + let mut allocator_module = make_module(tcx.sess, "allocator_shim".to_string()); + let created_alloc_shim = crate::allocator::codegen(tcx, &mut allocator_module); + + if created_alloc_shim { + let product = allocator_module.finish(); + + match emit_module( + tcx.output_filenames(()), + &tcx.sess.prof, + product.object, + ModuleKind::Allocator, + "allocator_shim".to_owned(), + &crate::debuginfo::producer(tcx.sess), + ) { + Ok(allocator_module) => Some(allocator_module), + Err(err) => tcx.dcx().fatal(err), + } + } else { + None + } +} + pub(crate) fn run_aot( tcx: TyCtxt<'_>, - backend_config: BackendConfig, metadata: EncodedMetadata, need_metadata_module: bool, ) -> Box<OngoingCodegen> { @@ -631,9 +703,10 @@ pub(crate) fn run_aot( let global_asm_config = Arc::new(crate::global_asm::GlobalAsmConfig::new(tcx)); + let disable_incr_cache = disable_incr_cache(); let (todo_cgus, done_cgus) = cgus.into_iter().enumerate().partition::<Vec<_>, _>(|&(i, _)| match cgu_reuse[i] { - _ if backend_config.disable_incr_cache => true, + _ if disable_incr_cache => true, CguReuse::No => true, CguReuse::PreLto | CguReuse::PostLto => false, }); @@ -647,12 +720,7 @@ pub(crate) fn run_aot( .with_task( dep_node, tcx, - ( - backend_config.clone(), - global_asm_config.clone(), - cgu.name(), - concurrency_limiter.acquire(tcx.dcx()), - ), + (global_asm_config.clone(), cgu.name(), concurrency_limiter.acquire(tcx.dcx())), module_codegen, Some(rustc_middle::dep_graph::hash_result), ) @@ -666,62 +734,10 @@ pub(crate) fn run_aot( modules }); - let mut allocator_module = make_module(tcx.sess, &backend_config, "allocator_shim".to_string()); - let created_alloc_shim = crate::allocator::codegen(tcx, &mut allocator_module); - - let allocator_module = if created_alloc_shim { - let product = allocator_module.finish(); + let allocator_module = emit_allocator_module(tcx); - match emit_module( - tcx.output_filenames(()), - &tcx.sess.prof, - product.object, - ModuleKind::Allocator, - "allocator_shim".to_owned(), - &crate::debuginfo::producer(tcx.sess), - ) { - Ok(allocator_module) => Some(allocator_module), - Err(err) => tcx.dcx().fatal(err), - } - } else { - None - }; - - let metadata_module = if need_metadata_module { - let (metadata_cgu_name, tmp_file) = tcx.sess.time("write compressed metadata", || { - use rustc_middle::mir::mono::CodegenUnitNameBuilder; - - let cgu_name_builder = &mut CodegenUnitNameBuilder::new(tcx); - let metadata_cgu_name = cgu_name_builder - .build_cgu_name(LOCAL_CRATE, ["crate"], Some("metadata")) - .as_str() - .to_string(); - - let tmp_file = - tcx.output_filenames(()).temp_path(OutputType::Metadata, Some(&metadata_cgu_name)); - - let symbol_name = rustc_middle::middle::exported_symbols::metadata_symbol_name(tcx); - let obj = create_compressed_metadata_file(tcx.sess, &metadata, &symbol_name); - - if let Err(err) = std::fs::write(&tmp_file, obj) { - tcx.dcx().fatal(format!("error writing metadata object file: {}", err)); - } - - (metadata_cgu_name, tmp_file) - }); - - Some(CompiledModule { - name: metadata_cgu_name, - kind: ModuleKind::Metadata, - object: Some(tmp_file), - dwarf_object: None, - bytecode: None, - assembly: None, - llvm_ir: None, - }) - } else { - None - }; + let metadata_module = + if need_metadata_module { Some(emit_metadata_module(tcx, &metadata)) } else { None }; Box::new(OngoingCodegen { modules, diff --git a/compiler/rustc_codegen_cranelift/src/driver/jit.rs b/compiler/rustc_codegen_cranelift/src/driver/jit.rs index ae9578eeffb..d68948966ea 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/jit.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/jit.rs @@ -11,12 +11,12 @@ use cranelift_jit::{JITBuilder, JITModule}; use rustc_codegen_ssa::CrateInfo; use rustc_middle::mir::mono::MonoItem; use rustc_session::Session; -use rustc_span::Symbol; +use rustc_span::sym; use crate::debuginfo::TypeDebugContext; use crate::prelude::*; use crate::unwind_module::UnwindModule; -use crate::{BackendConfig, CodegenCx, CodegenMode}; +use crate::{CodegenCx, CodegenMode}; struct JitState { jit_module: UnwindModule<JITModule>, @@ -59,14 +59,10 @@ impl UnsafeMessage { } } -fn create_jit_module( - tcx: TyCtxt<'_>, - backend_config: &BackendConfig, - hotswap: bool, -) -> (UnwindModule<JITModule>, CodegenCx) { +fn create_jit_module(tcx: TyCtxt<'_>, hotswap: bool) -> (UnwindModule<JITModule>, CodegenCx) { let crate_info = CrateInfo::new(tcx, "dummy_target_cpu".to_string()); - let isa = crate::build_isa(tcx.sess, backend_config); + let isa = crate::build_isa(tcx.sess); let mut jit_builder = JITBuilder::with_isa(isa, cranelift_module::default_libcall_names()); jit_builder.hotswap(hotswap); crate::compiler_builtins::register_functions_for_jit(&mut jit_builder); @@ -81,7 +77,7 @@ fn create_jit_module( (jit_module, cx) } -pub(crate) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! { +pub(crate) fn run_jit(tcx: TyCtxt<'_>, codegen_mode: CodegenMode, jit_args: Vec<String>) -> ! { if !tcx.sess.opts.output_types.should_codegen() { tcx.dcx().fatal("JIT mode doesn't work with `cargo check`"); } @@ -90,11 +86,8 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! { tcx.dcx().fatal("can't jit non-executable crate"); } - let (mut jit_module, mut cx) = create_jit_module( - tcx, - &backend_config, - matches!(backend_config.codegen_mode, CodegenMode::JitLazy), - ); + let (mut jit_module, mut cx) = + create_jit_module(tcx, matches!(codegen_mode, CodegenMode::JitLazy)); let mut cached_context = Context::new(); let (_, cgus) = tcx.collect_and_partition_mono_items(()); @@ -110,7 +103,7 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! { super::predefine_mono_items(tcx, &mut jit_module, &mono_items); for (mono_item, _) in mono_items { match mono_item { - MonoItem::Fn(inst) => match backend_config.codegen_mode { + MonoItem::Fn(inst) => match codegen_mode { CodegenMode::Aot => unreachable!(), CodegenMode::Jit => { codegen_and_compile_fn( @@ -151,7 +144,7 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! { ); let args = std::iter::once(&*tcx.crate_name(LOCAL_CRATE).as_str().to_string()) - .chain(backend_config.jit_args.iter().map(|arg| &**arg)) + .chain(jit_args.iter().map(|arg| &**arg)) .map(|arg| CString::new(arg).unwrap()) .collect::<Vec<_>>(); @@ -211,7 +204,7 @@ pub(crate) fn codegen_and_compile_fn<'tcx>( instance: Instance<'tcx>, ) { cranelift_codegen::timing::set_thread_profiler(Box::new(super::MeasuremeProfiler( - cx.profiler.clone(), + tcx.prof.clone(), ))); tcx.prof.generic_activity("codegen and compile fn").run(|| { @@ -227,7 +220,7 @@ pub(crate) fn codegen_and_compile_fn<'tcx>( module, instance, ) { - crate::base::compile_fn(cx, cached_context, module, codegened_func); + crate::base::compile_fn(cx, &tcx.prof, cached_context, module, codegened_func); } }); } diff --git a/compiler/rustc_codegen_cranelift/src/inline_asm.rs b/compiler/rustc_codegen_cranelift/src/inline_asm.rs index d74c366a87f..33726056cc1 100644 --- a/compiler/rustc_codegen_cranelift/src/inline_asm.rs +++ b/compiler/rustc_codegen_cranelift/src/inline_asm.rs @@ -102,13 +102,12 @@ pub(crate) fn codegen_inline_asm_terminator<'tcx>( // Pass a wrapper rather than the function itself as the function itself may not // be exported from the main codegen unit and may thus be unreachable from the // object file created by an external assembler. - let inline_asm_index = fx.cx.inline_asm_index.get(); - fx.cx.inline_asm_index.set(inline_asm_index + 1); let wrapper_name = format!( "__inline_asm_{}_wrapper_n{}", fx.cx.cgu_name.as_str().replace('.', "__").replace('-', "_"), - inline_asm_index + fx.cx.inline_asm_index ); + fx.cx.inline_asm_index += 1; let sig = get_function_sig(fx.tcx, fx.target_config.default_call_conv, instance); create_wrapper_function(fx.module, sig, &wrapper_name, symbol.name); @@ -167,13 +166,12 @@ pub(crate) fn codegen_inline_asm_inner<'tcx>( asm_gen.allocate_registers(); asm_gen.allocate_stack_slots(); - let inline_asm_index = fx.cx.inline_asm_index.get(); - fx.cx.inline_asm_index.set(inline_asm_index + 1); let asm_name = format!( "__inline_asm_{}_n{}", fx.cx.cgu_name.as_str().replace('.', "__").replace('-', "_"), - inline_asm_index + fx.cx.inline_asm_index ); + fx.cx.inline_asm_index += 1; let generated_asm = asm_gen.generate_asm_wrapper(&asm_name); fx.cx.global_asm.push_str(&generated_asm); @@ -266,13 +264,12 @@ pub(crate) fn codegen_naked_asm<'tcx>( // Pass a wrapper rather than the function itself as the function itself may not // be exported from the main codegen unit and may thus be unreachable from the // object file created by an external assembler. - let inline_asm_index = cx.inline_asm_index.get(); - cx.inline_asm_index.set(inline_asm_index + 1); let wrapper_name = format!( "__inline_asm_{}_wrapper_n{}", cx.cgu_name.as_str().replace('.', "__").replace('-', "_"), - inline_asm_index + cx.inline_asm_index ); + cx.inline_asm_index += 1; let sig = get_function_sig(tcx, module.target_config().default_call_conv, instance); create_wrapper_function(module, sig, &wrapper_name, symbol.name); diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs index 3318c0797ec..5f1b71eff6b 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs @@ -1270,8 +1270,7 @@ fn codegen_regular_intrinsic_call<'tcx>( } sym::cold_path => { - // This is a no-op. The intrinsic is just a hint to the optimizer. - // We still have an impl here to avoid it being turned into a call. + fx.bcx.set_cold_block(fx.bcx.current_block().unwrap()); } // Unimplemented intrinsics must have a fallback body. The fallback body is obtained diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index cac9975f04c..c9486a730e1 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -34,7 +34,7 @@ extern crate rustc_target; extern crate rustc_driver; use std::any::Any; -use std::cell::{Cell, RefCell}; +use std::env; use std::sync::Arc; use cranelift_codegen::isa::TargetIsa; @@ -42,7 +42,6 @@ use cranelift_codegen::settings::{self, Configurable}; use rustc_codegen_ssa::CodegenResults; use rustc_codegen_ssa::back::versioned_llvm_target; use rustc_codegen_ssa::traits::CodegenBackend; -use rustc_data_structures::profiling::SelfProfilerRef; use rustc_metadata::EncodedMetadata; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; use rustc_session::Session; @@ -123,11 +122,10 @@ impl<F: Fn() -> String> Drop for PrintOnPanic<F> { /// The codegen context holds any information shared between the codegen of individual functions /// inside a single codegen unit with the exception of the Cranelift [`Module`](cranelift_module::Module). struct CodegenCx { - profiler: SelfProfilerRef, output_filenames: Arc<OutputFilenames>, should_write_ir: bool, global_asm: String, - inline_asm_index: Cell<usize>, + inline_asm_index: usize, debug_context: Option<DebugContext>, cgu_name: Symbol, } @@ -142,11 +140,10 @@ impl CodegenCx { None }; CodegenCx { - profiler: tcx.prof.clone(), output_filenames: tcx.output_filenames(()).clone(), should_write_ir: crate::pretty_clif::should_write_ir(tcx), global_asm: String::new(), - inline_asm_index: Cell::new(0), + inline_asm_index: 0, debug_context, cgu_name, } @@ -154,7 +151,7 @@ impl CodegenCx { } pub struct CraneliftCodegenBackend { - pub config: RefCell<Option<BackendConfig>>, + pub config: Option<BackendConfig>, } impl CodegenBackend for CraneliftCodegenBackend { @@ -176,13 +173,6 @@ impl CodegenBackend for CraneliftCodegenBackend { sess.dcx() .fatal("`-Cinstrument-coverage` is LLVM specific and not supported by Cranelift"); } - - let mut config = self.config.borrow_mut(); - if config.is_none() { - let new_config = BackendConfig::from_opts(&sess.opts.cg.llvm_args) - .unwrap_or_else(|err| sess.dcx().fatal(err)); - *config = Some(new_config); - } } fn target_features(&self, sess: &Session, _allow_unstable: bool) -> Vec<rustc_span::Symbol> { @@ -215,12 +205,15 @@ impl CodegenBackend for CraneliftCodegenBackend { need_metadata_module: bool, ) -> Box<dyn Any> { tcx.dcx().abort_if_errors(); - let config = self.config.borrow().clone().unwrap(); + let config = self.config.clone().unwrap_or_else(|| { + BackendConfig::from_opts(&tcx.sess.opts.cg.llvm_args) + .unwrap_or_else(|err| tcx.sess.dcx().fatal(err)) + }); match config.codegen_mode { - CodegenMode::Aot => driver::aot::run_aot(tcx, config, metadata, need_metadata_module), + CodegenMode::Aot => driver::aot::run_aot(tcx, metadata, need_metadata_module), CodegenMode::Jit | CodegenMode::JitLazy => { #[cfg(feature = "jit")] - driver::jit::run_jit(tcx, config); + driver::jit::run_jit(tcx, config.codegen_mode, config.jit_args); #[cfg(not(feature = "jit"))] tcx.dcx().fatal("jit support was disabled when compiling rustc_codegen_cranelift"); @@ -236,14 +229,20 @@ impl CodegenBackend for CraneliftCodegenBackend { ) -> (CodegenResults, FxIndexMap<WorkProductId, WorkProduct>) { let _timer = sess.timer("finish_ongoing_codegen"); - ongoing_codegen.downcast::<driver::aot::OngoingCodegen>().unwrap().join( - sess, - outputs, - self.config.borrow().as_ref().unwrap(), - ) + ongoing_codegen.downcast::<driver::aot::OngoingCodegen>().unwrap().join(sess, outputs) } } +/// Determine if the Cranelift ir verifier should run. +/// +/// Returns true when `-Zverify-llvm-ir` is passed, the `CG_CLIF_ENABLE_VERIFIER` env var is set to +/// 1 or when cg_clif is compiled with debug assertions enabled or false otherwise. +fn enable_verifier(sess: &Session) -> bool { + sess.verify_llvm_ir() + || cfg!(debug_assertions) + || env::var("CG_CLIF_ENABLE_VERIFIER").as_deref() == Ok("1") +} + fn target_triple(sess: &Session) -> target_lexicon::Triple { // FIXME(madsmtm): Use `sess.target.llvm_target` once target-lexicon supports unversioned macOS. // See <https://github.com/bytecodealliance/target-lexicon/pull/113> @@ -253,14 +252,14 @@ fn target_triple(sess: &Session) -> target_lexicon::Triple { } } -fn build_isa(sess: &Session, backend_config: &BackendConfig) -> Arc<dyn TargetIsa + 'static> { +fn build_isa(sess: &Session) -> Arc<dyn TargetIsa + 'static> { use target_lexicon::BinaryFormat; let target_triple = crate::target_triple(sess); let mut flags_builder = settings::builder(); flags_builder.enable("is_pic").unwrap(); - let enable_verifier = if backend_config.enable_verifier { "true" } else { "false" }; + let enable_verifier = if enable_verifier(sess) { "true" } else { "false" }; flags_builder.set("enable_verifier", enable_verifier).unwrap(); flags_builder.set("regalloc_checker", enable_verifier).unwrap(); @@ -295,6 +294,16 @@ fn build_isa(sess: &Session, backend_config: &BackendConfig) -> Arc<dyn TargetIs } } + if let target_lexicon::OperatingSystem::Windows = target_triple.operating_system { + // FIXME remove dependency on this from the Rust ABI. cc bytecodealliance/wasmtime#9510 + flags_builder.enable("enable_multi_ret_implicit_sret").unwrap(); + } + + if let target_lexicon::Architecture::S390x = target_triple.architecture { + // FIXME remove dependency on this from the Rust ABI. cc bytecodealliance/wasmtime#9510 + flags_builder.enable("enable_multi_ret_implicit_sret").unwrap(); + } + if let target_lexicon::Architecture::Aarch64(_) | target_lexicon::Architecture::Riscv64(_) | target_lexicon::Architecture::X86_64 = target_triple.architecture @@ -347,5 +356,5 @@ fn build_isa(sess: &Session, backend_config: &BackendConfig) -> Arc<dyn TargetIs /// This is the entrypoint for a hot plugged rustc_codegen_cranelift #[no_mangle] pub fn __rustc_codegen_backend() -> Box<dyn CodegenBackend> { - Box::new(CraneliftCodegenBackend { config: RefCell::new(None) }) + Box::new(CraneliftCodegenBackend { config: None }) } diff --git a/compiler/rustc_codegen_cranelift/src/main_shim.rs b/compiler/rustc_codegen_cranelift/src/main_shim.rs index 2ee4ff5cec7..e480f21b9df 100644 --- a/compiler/rustc_codegen_cranelift/src/main_shim.rs +++ b/compiler/rustc_codegen_cranelift/src/main_shim.rs @@ -24,7 +24,7 @@ pub(crate) fn maybe_create_entry_wrapper( }; if main_def_id.is_local() { - let instance = Instance::mono(tcx, main_def_id).polymorphize(tcx); + let instance = Instance::mono(tcx, main_def_id); if module.get_name(tcx.symbol_name(instance).name).is_none() { return; } @@ -75,7 +75,7 @@ pub(crate) fn maybe_create_entry_wrapper( } }; - let instance = Instance::mono(tcx, rust_main_def_id).polymorphize(tcx); + let instance = Instance::mono(tcx, rust_main_def_id); let main_name = tcx.symbol_name(instance).name; let main_sig = get_function_sig(tcx, m.target_config().default_call_conv, instance); @@ -117,8 +117,7 @@ pub(crate) fn maybe_create_entry_wrapper( report.def_id, tcx.mk_args(&[GenericArg::from(main_ret_ty)]), DUMMY_SP, - ) - .polymorphize(tcx); + ); let report_name = tcx.symbol_name(report).name; let report_sig = get_function_sig(tcx, m.target_config().default_call_conv, report); @@ -143,8 +142,7 @@ pub(crate) fn maybe_create_entry_wrapper( start_def_id, tcx.mk_args(&[main_ret_ty.into()]), DUMMY_SP, - ) - .polymorphize(tcx); + ); let start_func_id = import_function(tcx, m, start_instance); let main_val = bcx.ins().func_addr(m.target_config().pointer_type(), main_func_ref); diff --git a/compiler/rustc_codegen_cranelift/src/value_and_place.rs b/compiler/rustc_codegen_cranelift/src/value_and_place.rs index 6676e684ca0..c17d1f30fbe 100644 --- a/compiler/rustc_codegen_cranelift/src/value_and_place.rs +++ b/compiler/rustc_codegen_cranelift/src/value_and_place.rs @@ -1005,9 +1005,6 @@ pub(crate) fn assert_assignable<'tcx>( } } } - (ty::Param(_), _) | (_, ty::Param(_)) if fx.tcx.sess.opts.unstable_opts.polymorphize => { - // No way to check if it is correct or not with polymorphization enabled - } _ => { assert_eq!( from_ty, diff --git a/compiler/rustc_codegen_gcc/src/context.rs b/compiler/rustc_codegen_gcc/src/context.rs index 3846d025537..f67dcf0cb11 100644 --- a/compiler/rustc_codegen_gcc/src/context.rs +++ b/compiler/rustc_codegen_gcc/src/context.rs @@ -544,7 +544,10 @@ impl<'gcc, 'tcx> HasWasmCAbiOpt for CodegenCx<'gcc, 'tcx> { impl<'gcc, 'tcx> HasX86AbiOpt for CodegenCx<'gcc, 'tcx> { fn x86_abi_opt(&self) -> X86Abi { - X86Abi { regparm: self.tcx.sess.opts.unstable_opts.regparm } + X86Abi { + regparm: self.tcx.sess.opts.unstable_opts.regparm, + reg_struct_return: self.tcx.sess.opts.unstable_opts.reg_struct_return, + } } } diff --git a/compiler/rustc_codegen_gcc/tests/failing-ui-tests.txt b/compiler/rustc_codegen_gcc/tests/failing-ui-tests.txt index 56b51275a53..457072b1a5b 100644 --- a/compiler/rustc_codegen_gcc/tests/failing-ui-tests.txt +++ b/compiler/rustc_codegen_gcc/tests/failing-ui-tests.txt @@ -6,7 +6,6 @@ tests/ui/functions-closures/parallel-codegen-closures.rs tests/ui/linkage-attr/linkage1.rs tests/ui/lto/dylib-works.rs tests/ui/numbers-arithmetic/saturating-float-casts.rs -tests/ui/polymorphization/promoted-function.rs tests/ui/sepcomp/sepcomp-cci.rs tests/ui/sepcomp/sepcomp-extern.rs tests/ui/sepcomp/sepcomp-fns-backwards.rs diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs index 8852dec7d9f..adfe8aeb5c5 100644 --- a/compiler/rustc_codegen_llvm/src/common.rs +++ b/compiler/rustc_codegen_llvm/src/common.rs @@ -302,10 +302,9 @@ impl<'ll, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> { (value, AddressSpace::DATA) } } - GlobalAlloc::Function { instance, .. } => ( - self.get_fn_addr(instance.polymorphize(self.tcx)), - self.data_layout().instruction_address_space, - ), + GlobalAlloc::Function { instance, .. } => { + (self.get_fn_addr(instance), self.data_layout().instruction_address_space) + } GlobalAlloc::VTable(ty, dyn_ty) => { let alloc = self .tcx diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index dee67baaee9..59275254022 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -471,8 +471,6 @@ pub(crate) fn type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> AdtKind::Enum => enums::build_enum_type_di_node(cx, unique_type_id), }, ty::Tuple(_) => build_tuple_type_di_node(cx, unique_type_id), - // Type parameters from polymorphized functions. - ty::Param(_) => build_param_type_di_node(cx, t), _ => bug!("debuginfo: unexpected type in type_di_node(): {:?}", t), }; @@ -871,26 +869,6 @@ fn build_foreign_type_di_node<'ll, 'tcx>( ) } -fn build_param_type_di_node<'ll, 'tcx>( - cx: &CodegenCx<'ll, 'tcx>, - t: Ty<'tcx>, -) -> DINodeCreationResult<'ll> { - debug!("build_param_type_di_node: {:?}", t); - let name = format!("{t:?}"); - DINodeCreationResult { - di_node: unsafe { - llvm::LLVMRustDIBuilderCreateBasicType( - DIB(cx), - name.as_c_char_ptr(), - name.len(), - Size::ZERO.bits(), - DW_ATE_unsigned, - ) - }, - already_stored_in_typemap: false, - } -} - pub(crate) fn build_compile_unit_di_node<'ll, 'tcx>( tcx: TyCtxt<'tcx>, codegen_unit_name: &str, diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index 6c4f6d37972..cf72c2ed742 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -432,11 +432,8 @@ fn push_debuginfo_type_name<'tcx>( push_closure_or_coroutine_name(tcx, def_id, args, qualified, output, visited); } } - // Type parameters from polymorphized functions. - ty::Param(_) => { - write!(output, "{t:?}").unwrap(); - } - ty::Error(_) + ty::Param(_) + | ty::Error(_) | ty::Infer(_) | ty::Placeholder(..) | ty::Alias(..) diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index e3ed12b5ce6..b0a1dedd646 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -847,10 +847,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let (instance, mut llfn) = match *callee.layout.ty.kind() { ty::FnDef(def_id, args) => ( - Some( - ty::Instance::expect_resolve(bx.tcx(), bx.typing_env(), def_id, args, fn_span) - .polymorphize(bx.tcx()), - ), + Some(ty::Instance::expect_resolve( + bx.tcx(), + bx.typing_env(), + def_id, + args, + fn_span, + )), None, ), ty::FnPtr(..) => (None, Some(callee.immediate())), diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index f63b2d139c5..cf537392234 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -478,8 +478,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { def_id, args, ) - .unwrap() - .polymorphize(bx.cx().tcx()); + .unwrap(); OperandValue::Immediate(bx.get_fn_addr(instance)) } _ => bug!("{} cannot be reified to a fn ptr", operand.layout.ty), @@ -493,8 +492,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { def_id, args, ty::ClosureKind::FnOnce, - ) - .polymorphize(bx.cx().tcx()); + ); OperandValue::Immediate(bx.cx().get_fn_addr(instance)) } _ => bug!("{} cannot be cast to a fn ptr", operand.layout.ty), diff --git a/compiler/rustc_const_eval/src/check_consts/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs index 489bb54a6f9..23f2aa4d029 100644 --- a/compiler/rustc_const_eval/src/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/check_consts/ops.rs @@ -140,7 +140,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { err, param_ty.name.as_str(), &constraint, - None, + Some(trait_ref.def_id), None, ); } diff --git a/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs b/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs index e49d702127d..817acfcca74 100644 --- a/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs @@ -168,9 +168,9 @@ impl<'tcx> interpret::Machine<'tcx> for DummyMachine { }) } - fn expose_ptr( - _ecx: &mut InterpCx<'tcx, Self>, - _ptr: interpret::Pointer<Self::Provenance>, + fn expose_provenance( + _ecx: &InterpCx<'tcx, Self>, + _provenance: Self::Provenance, ) -> interpret::InterpResult<'tcx> { unimplemented!() } diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index b27e3606f38..11e0fac51d8 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -21,9 +21,8 @@ use crate::errors::{LongRunning, LongRunningWarn}; use crate::fluent_generated as fluent; use crate::interpret::{ self, AllocId, AllocRange, ConstAllocation, CtfeProvenance, FnArg, Frame, GlobalAlloc, ImmTy, - InterpCx, InterpResult, MPlaceTy, OpTy, Pointer, RangeSet, Scalar, compile_time_machine, - interp_ok, throw_exhaust, throw_inval, throw_ub, throw_ub_custom, throw_unsup, - throw_unsup_format, + InterpCx, InterpResult, MPlaceTy, OpTy, RangeSet, Scalar, compile_time_machine, interp_ok, + throw_exhaust, throw_inval, throw_ub, throw_ub_custom, throw_unsup, throw_unsup_format, }; /// When hitting this many interpreted terminators we emit a deny by default lint @@ -586,7 +585,10 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { } #[inline(always)] - fn expose_ptr(_ecx: &mut InterpCx<'tcx, Self>, _ptr: Pointer) -> InterpResult<'tcx> { + fn expose_provenance( + _ecx: &InterpCx<'tcx, Self>, + _provenance: Self::Provenance, + ) -> InterpResult<'tcx> { // This is only reachable with -Zunleash-the-miri-inside-of-you. throw_unsup_format!("exposing pointers is not possible at compile-time") } diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index c95e51f0a1f..ef3e96784ce 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -238,7 +238,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let scalar = src.to_scalar(); let ptr = scalar.to_pointer(self)?; match ptr.into_pointer_or_addr() { - Ok(ptr) => M::expose_ptr(self, ptr)?, + Ok(ptr) => M::expose_provenance(self, ptr.provenance)?, Err(_) => {} // Do nothing, exposing an invalid pointer (`None` provenance) is a NOP. }; interp_ok(ImmTy::from_scalar( diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index dbe09d55b2d..a180d5da941 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -327,11 +327,11 @@ pub trait Machine<'tcx>: Sized { addr: u64, ) -> InterpResult<'tcx, Pointer<Option<Self::Provenance>>>; - /// Marks a pointer as exposed, allowing it's provenance + /// Marks a pointer as exposed, allowing its provenance /// to be recovered. "Pointer-to-int cast" - fn expose_ptr( - ecx: &mut InterpCx<'tcx, Self>, - ptr: Pointer<Self::Provenance>, + fn expose_provenance( + ecx: &InterpCx<'tcx, Self>, + provenance: Self::Provenance, ) -> InterpResult<'tcx>; /// Convert a pointer with provenance into an allocation-offset pair and extra provenance info. diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 277d293597a..027ba9644cb 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -944,6 +944,52 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { interp_ok(()) } + /// Handle the effect an FFI call might have on the state of allocations. + /// This overapproximates the modifications which external code might make to memory: + /// We set all reachable allocations as initialized, mark all provenances as exposed + /// and overwrite them with `Provenance::WILDCARD`. + pub fn prepare_for_native_call( + &mut self, + id: AllocId, + initial_prov: M::Provenance, + ) -> InterpResult<'tcx> { + // Expose provenance of the root allocation. + M::expose_provenance(self, initial_prov)?; + + let mut done = FxHashSet::default(); + let mut todo = vec![id]; + while let Some(id) = todo.pop() { + if !done.insert(id) { + // We already saw this allocation before, don't process it again. + continue; + } + let info = self.get_alloc_info(id); + + // If there is no data behind this pointer, skip this. + if !matches!(info.kind, AllocKind::LiveData) { + continue; + } + + // Expose all provenances in this allocation, and add them to `todo`. + let alloc = self.get_alloc_raw(id)?; + for prov in alloc.provenance().provenances() { + M::expose_provenance(self, prov)?; + if let Some(id) = prov.get_alloc_id() { + todo.push(id); + } + } + + // Prepare for possible write from native code if mutable. + if info.mutbl.is_mut() { + self.get_alloc_raw_mut(id)? + .0 + .prepare_for_native_write() + .map_err(|e| e.to_interp_error(id))?; + } + } + interp_ok(()) + } + /// Create a lazy debug printer that prints the given allocation and all allocations it points /// to, recursively. #[must_use] diff --git a/compiler/rustc_const_eval/src/interpret/util.rs b/compiler/rustc_const_eval/src/interpret/util.rs index 8bb5f173a56..ecb7c3fc93c 100644 --- a/compiler/rustc_const_eval/src/interpret/util.rs +++ b/compiler/rustc_const_eval/src/interpret/util.rs @@ -14,10 +14,8 @@ use crate::const_eval::{CompileTimeInterpCx, CompileTimeMachine, InterpretationR /// Checks whether a type contains generic parameters which must be instantiated. /// -/// In case it does, returns a `TooGeneric` const eval error. Note that due to polymorphization -/// types may be "concrete enough" even though they still contain generic parameters in -/// case these parameters are unused. -pub(crate) fn ensure_monomorphic_enough<'tcx, T>(tcx: TyCtxt<'tcx>, ty: T) -> InterpResult<'tcx> +/// In case it does, returns a `TooGeneric` const eval error. +pub(crate) fn ensure_monomorphic_enough<'tcx, T>(_tcx: TyCtxt<'tcx>, ty: T) -> InterpResult<'tcx> where T: TypeVisitable<TyCtxt<'tcx>>, { @@ -27,11 +25,9 @@ where } struct FoundParam; - struct UsedParamsNeedInstantiationVisitor<'tcx> { - tcx: TyCtxt<'tcx>, - } + struct UsedParamsNeedInstantiationVisitor {} - impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for UsedParamsNeedInstantiationVisitor<'tcx> { + impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for UsedParamsNeedInstantiationVisitor { type Result = ControlFlow<FoundParam>; fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result { @@ -41,25 +37,7 @@ where match *ty.kind() { ty::Param(_) => ControlFlow::Break(FoundParam), - ty::Closure(def_id, args) - | ty::CoroutineClosure(def_id, args, ..) - | ty::Coroutine(def_id, args, ..) - | ty::FnDef(def_id, args) => { - let instance = ty::InstanceKind::Item(def_id); - let unused_params = self.tcx.unused_generic_params(instance); - for (index, arg) in args.into_iter().enumerate() { - let index = index - .try_into() - .expect("more generic parameters than can fit into a `u32`"); - // Only recurse when generic parameters in fns, closures and coroutines - // are used and have to be instantiated. - // - // Just in case there are closures or coroutines within this arg, - // recurse. - if unused_params.is_used(index) && arg.has_param() { - return arg.visit_with(self); - } - } + ty::Closure(..) | ty::CoroutineClosure(..) | ty::Coroutine(..) | ty::FnDef(..) => { ControlFlow::Continue(()) } _ => ty.super_visit_with(self), @@ -74,7 +52,7 @@ where } } - let mut vis = UsedParamsNeedInstantiationVisitor { tcx }; + let mut vis = UsedParamsNeedInstantiationVisitor {}; if matches!(ty.visit_with(&mut vis), ControlFlow::Break(FoundParam)) { throw_inval!(TooGeneric); } else { diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index fd08b35d242..3bf485c2eb6 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -1104,10 +1104,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ WarnFollowing, EncodeCrossCrate::No ), rustc_attr!( - TEST, rustc_polymorphize_error, Normal, template!(Word), - WarnFollowing, EncodeCrossCrate::Yes - ), - rustc_attr!( TEST, rustc_def_path, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No ), diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index ff449a858d6..2e227ead14a 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -279,7 +279,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } else { let mut err = self.dcx().create_err(err); if suggest_constraining_type_param( - tcx, generics, &mut err, &qself_str, &trait_ref, None, None, + tcx, + generics, + &mut err, + &qself_str, + &trait_ref, + Some(best_trait), + None, ) && !identically_named { // We suggested constraining a type parameter, but the associated item on it 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 cb4209116ac..3313339abb3 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -29,10 +29,9 @@ use rustc_errors::codes::*; use rustc_errors::{ Applicability, Diag, DiagCtxtHandle, ErrorGuaranteed, FatalError, struct_span_code_err, }; -use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Namespace, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::{GenericArg, GenericArgs, HirId}; +use rustc_hir::{self as hir, AnonConst, GenericArg, GenericArgs, HirId}; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::ObligationCause; use rustc_middle::middle::stability::AllowUnstable; @@ -999,6 +998,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { self.lower_const_arg(ct, FeedConstTy::No).into() } }; + if term.references_error() { + continue; + } // FIXME(#97583): This isn't syntactically well-formed! where_bounds.push(format!( " T: {trait}::{assoc_name} = {term}", @@ -2089,7 +2091,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { qpath.span(), format!("Const::lower_const_arg: invalid qpath {qpath:?}"), ), - hir::ConstArgKind::Anon(anon) => self.lower_anon_const(anon.def_id), + hir::ConstArgKind::Anon(anon) => self.lower_anon_const(anon), hir::ConstArgKind::Infer(span) => self.ct_infer(None, span), } } @@ -2180,27 +2182,22 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { /// Literals and const generic parameters are eagerly converted to a constant, everything else /// becomes `Unevaluated`. #[instrument(skip(self), level = "debug")] - fn lower_anon_const(&self, def: LocalDefId) -> Const<'tcx> { + fn lower_anon_const(&self, anon: &AnonConst) -> Const<'tcx> { let tcx = self.tcx(); - let body_id = match tcx.hir_node_by_def_id(def) { - hir::Node::AnonConst(ac) => ac.body, - node => span_bug!( - tcx.def_span(def.to_def_id()), - "from_anon_const can only process anonymous constants, not {node:?}" - ), - }; - - let expr = &tcx.hir().body(body_id).value; + let expr = &tcx.hir().body(anon.body).value; debug!(?expr); - let ty = tcx.type_of(def).no_bound_vars().expect("const parameter types cannot be generic"); + let ty = tcx + .type_of(anon.def_id) + .no_bound_vars() + .expect("const parameter types cannot be generic"); match self.try_lower_anon_const_lit(ty, expr) { Some(v) => v, None => ty::Const::new_unevaluated(tcx, ty::UnevaluatedConst { - def: def.to_def_id(), - args: ty::GenericArgs::identity_for_item(tcx, def.to_def_id()), + def: anon.def_id.to_def_id(), + args: ty::GenericArgs::identity_for_item(tcx, anon.def_id.to_def_id()), }), } } diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs index bfdf764d299..243313ee876 100644 --- a/compiler/rustc_hir_typeck/src/_match.rs +++ b/compiler/rustc_hir_typeck/src/_match.rs @@ -57,7 +57,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // type in that case) let mut all_arms_diverge = Diverges::WarnedAlways; - let expected = orig_expected.adjust_for_branches(self); + let expected = + orig_expected.try_structurally_resolve_and_adjust_for_branches(self, expr.span); debug!(?expected); let mut coercion = { diff --git a/compiler/rustc_hir_typeck/src/expectation.rs b/compiler/rustc_hir_typeck/src/expectation.rs index 4653458b5dd..6d95b6917e2 100644 --- a/compiler/rustc_hir_typeck/src/expectation.rs +++ b/compiler/rustc_hir_typeck/src/expectation.rs @@ -39,10 +39,14 @@ impl<'a, 'tcx> Expectation<'tcx> { // an expected type. Otherwise, we might write parts of the type // when checking the 'then' block which are incompatible with the // 'else' branch. - pub(super) fn adjust_for_branches(&self, fcx: &FnCtxt<'a, 'tcx>) -> Expectation<'tcx> { + pub(super) fn try_structurally_resolve_and_adjust_for_branches( + &self, + fcx: &FnCtxt<'a, 'tcx>, + span: Span, + ) -> Expectation<'tcx> { match *self { ExpectHasType(ety) => { - let ety = fcx.shallow_resolve(ety); + let ety = fcx.try_structurally_resolve_type(span, ety); if !ety.is_ty_var() { ExpectHasType(ety) } else { NoExpectation } } ExpectRvalueLikeUnsized(ety) => ExpectRvalueLikeUnsized(ety), diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 4699b342cec..04c06169d33 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -628,7 +628,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr: &'tcx hir::Expr<'tcx>, ) -> Ty<'tcx> { let hint = expected.only_has_type(self).map_or(NoExpectation, |ty| { - match ty.kind() { + match self.try_structurally_resolve_type(expr.span, ty).kind() { ty::Ref(_, ty, _) | ty::RawPtr(ty, _) => { if oprnd.is_syntactic_place_expr() { // Places may legitimately have unsized types. @@ -1293,7 +1293,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let cond_diverges = self.diverges.get(); self.diverges.set(Diverges::Maybe); - let expected = orig_expected.adjust_for_branches(self); + let expected = orig_expected.try_structurally_resolve_and_adjust_for_branches(self, sp); let then_ty = self.check_expr_with_expectation(then_expr, expected); let then_diverges = self.diverges.get(); self.diverges.set(Diverges::Maybe); @@ -1354,8 +1354,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { rhs: &'tcx hir::Expr<'tcx>, span: Span, ) -> Ty<'tcx> { - let expected_ty = expected.coercion_target_type(self, expr.span); - if expected_ty == self.tcx.types.bool { + let expected_ty = expected.only_has_type(self); + if expected_ty == Some(self.tcx.types.bool) { let guar = self.expr_assign_expected_bool_error(expr, lhs, rhs, span); return Ty::new_error(self.tcx, guar); } @@ -1639,7 +1639,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let element_ty = if !args.is_empty() { let coerce_to = expected .to_option(self) - .and_then(|uty| match *uty.kind() { + .and_then(|uty| match *self.try_structurally_resolve_type(expr.span, uty).kind() { ty::Array(ty, _) | ty::Slice(ty) => Some(ty), _ => None, }) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 30c838b74af..44582390a4b 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -936,18 +936,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // can be collated pretty easily if needed. // Next special case: if there is only one "Incompatible" error, just emit that - if let [ + if let &[ Error::Invalid(provided_idx, expected_idx, Compatibility::Incompatible(Some(err))), ] = &errors[..] { - let (formal_ty, expected_ty) = formal_and_expected_inputs[*expected_idx]; - let (provided_ty, provided_arg_span) = provided_arg_tys[*provided_idx]; + let (formal_ty, expected_ty) = formal_and_expected_inputs[expected_idx]; + let (provided_ty, provided_arg_span) = provided_arg_tys[provided_idx]; let trace = mk_trace(provided_arg_span, (formal_ty, expected_ty), provided_ty); - let mut err = - self.err_ctxt().report_and_explain_type_error(trace, self.param_env, *err); + let mut err = self.err_ctxt().report_and_explain_type_error(trace, self.param_env, err); self.emit_coerce_suggestions( &mut err, - provided_args[*provided_idx], + provided_args[provided_idx], provided_ty, Expectation::rvalue_hint(self, expected_ty) .only_has_type(self) @@ -982,7 +981,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.suggest_ptr_null_mut( expected_ty, provided_ty, - provided_args[*provided_idx], + provided_args[provided_idx], &mut err, ); @@ -992,7 +991,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { call_ident, expected_ty, provided_ty, - provided_args[*provided_idx], + provided_args[provided_idx], is_method, ); diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index d42915f4110..f53c7b5cc2d 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -876,7 +876,6 @@ fn run_required_analyses(tcx: TyCtxt<'_>) { || tcx.hir().body_const_context(def_id).is_some() { tcx.ensure().mir_drops_elaborated_and_const_checked(def_id); - tcx.ensure().unused_generic_params(ty::InstanceKind::Item(def_id.to_def_id())); } } }); @@ -895,8 +894,7 @@ fn run_required_analyses(tcx: TyCtxt<'_>) { // If `-Zvalidate-mir` is set, we also want to compute the final MIR for each item // (either its `mir_for_ctfe` or `optimized_mir`) since that helps uncover any bugs // in MIR optimizations that may only be reachable through codegen, or other codepaths - // that requires the optimized/ctfe MIR, such as polymorphization, coroutine bodies, - // or evaluating consts. + // that requires the optimized/ctfe MIR, coroutine bodies, or evaluating consts. if tcx.sess.opts.unstable_opts.validate_mir { sess.time("ensuring_final_MIR_is_computable", || { tcx.hir().par_body_owners(|def_id| { diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 3c4d9c2e928..e76e9ca9f85 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -832,6 +832,7 @@ fn test_unstable_options_tracking_hash() { tracked!(precise_enum_drop_elaboration, false); tracked!(profile_sample_use, Some(PathBuf::from("abc"))); tracked!(profiler_runtime, "abc".to_string()); + tracked!(reg_struct_return, true); tracked!(regparm, Some(3)); tracked!(relax_elf_relocations, Some(true)); tracked!(remap_cwd_prefix, Some(PathBuf::from("abc"))); diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index a89096beb8c..f01ad31d0bb 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -269,7 +269,6 @@ provide! { tcx, def_id, other, cdata, lookup_default_body_stability => { table } lookup_deprecation_entry => { table } params_in_repr => { table } - unused_generic_params => { table_direct } def_kind => { cdata.def_kind(def_id.index) } impl_parent => { table } defaultness => { table_direct } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index a34ea18f716..d4ea1276d00 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1767,10 +1767,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { { record!(self.tables.mir_coroutine_witnesses[def_id.to_def_id()] <- witnesses); } - - let instance = ty::InstanceKind::Item(def_id.to_def_id()); - let unused = tcx.unused_generic_params(instance); - self.tables.unused_generic_params.set(def_id.local_def_index, unused); } // Encode all the deduced parameter attributes for everything that has MIR, even for items diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index a486ad42482..a5e21ab51fd 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -395,7 +395,6 @@ define_tables! { inherent_impls: Table<DefIndex, LazyArray<DefIndex>>, associated_types_for_impl_traits_in_associated_fn: Table<DefIndex, LazyArray<DefId>>, opt_rpitit_info: Table<DefIndex, Option<LazyValue<ty::ImplTraitInTraitData>>>, - unused_generic_params: Table<DefIndex, UnusedGenericParams>, // Reexported names are not associated with individual `DefId`s, // e.g. a glob import can introduce a lot of names, all with the same `DefId`. // That's why the encoded list needs to contain `ModChild` structures describing all the names diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index 509f2667b35..d6f8fed755f 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -643,6 +643,28 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes> Ok(()) } + /// Initialize all previously uninitialized bytes in the entire allocation, and set + /// provenance of everything to `Wildcard`. Before calling this, make sure all + /// provenance in this allocation is exposed! + pub fn prepare_for_native_write(&mut self) -> AllocResult { + let full_range = AllocRange { start: Size::ZERO, size: Size::from_bytes(self.len()) }; + // Overwrite uninitialized bytes with 0, to ensure we don't leak whatever their value happens to be. + for chunk in self.init_mask.range_as_init_chunks(full_range) { + if !chunk.is_init() { + let uninit_bytes = &mut self.bytes + [chunk.range().start.bytes_usize()..chunk.range().end.bytes_usize()]; + uninit_bytes.fill(0); + } + } + // Mark everything as initialized now. + self.mark_init(full_range, true); + + // Set provenance of all bytes to wildcard. + self.provenance.write_wildcards(self.len()); + + Ok(()) + } + /// Remove all provenance in the given memory range. pub fn clear_provenance(&mut self, cx: &impl HasDataLayout, range: AllocRange) -> AllocResult { self.provenance.clear(range, cx)?; diff --git a/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs b/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs index 5c47fc6a399..3a83b184d83 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs @@ -195,6 +195,25 @@ impl<Prov: Provenance> ProvenanceMap<Prov> { Ok(()) } + + /// Overwrites all provenance in the allocation with wildcard provenance. + /// + /// Provided for usage in Miri and panics otherwise. + pub fn write_wildcards(&mut self, alloc_size: usize) { + assert!( + Prov::OFFSET_IS_ADDR, + "writing wildcard provenance is not supported when `OFFSET_IS_ADDR` is false" + ); + let wildcard = Prov::WILDCARD.unwrap(); + + // Remove all pointer provenances, then write wildcards into the whole byte range. + self.ptrs.clear(); + let last = Size::from_bytes(alloc_size); + let bytes = self.bytes.get_or_insert_with(Box::default); + for offset in Size::ZERO..last { + bytes.insert(offset, wildcard); + } + } } /// A partial, owned list of provenance to transfer into another allocation. diff --git a/compiler/rustc_middle/src/mir/interpret/pointer.rs b/compiler/rustc_middle/src/mir/interpret/pointer.rs index 1d5afe22573..25c7c26ddd9 100644 --- a/compiler/rustc_middle/src/mir/interpret/pointer.rs +++ b/compiler/rustc_middle/src/mir/interpret/pointer.rs @@ -66,6 +66,9 @@ pub trait Provenance: Copy + fmt::Debug + 'static { /// pointer, and implement ptr-to-int transmutation by stripping provenance. const OFFSET_IS_ADDR: bool; + /// If wildcard provenance is implemented, contains the unique, general wildcard provenance variant. + const WILDCARD: Option<Self>; + /// Determines how a pointer should be printed. fn fmt(ptr: &Pointer<Self>, f: &mut fmt::Formatter<'_>) -> fmt::Result; @@ -168,6 +171,9 @@ impl Provenance for CtfeProvenance { // so ptr-to-int casts are not possible (since we do not know the global physical offset). const OFFSET_IS_ADDR: bool = false; + // `CtfeProvenance` does not implement wildcard provenance. + const WILDCARD: Option<Self> = None; + fn fmt(ptr: &Pointer<Self>, f: &mut fmt::Formatter<'_>) -> fmt::Result { // Print AllocId. fmt::Debug::fmt(&ptr.provenance.alloc_id(), f)?; // propagates `alternate` flag @@ -197,6 +203,9 @@ impl Provenance for AllocId { // so ptr-to-int casts are not possible (since we do not know the global physical offset). const OFFSET_IS_ADDR: bool = false; + // `AllocId` does not implement wildcard provenance. + const WILDCARD: Option<Self> = None; + fn fmt(ptr: &Pointer<Self>, f: &mut fmt::Formatter<'_>) -> fmt::Result { // Forward `alternate` flag to `alloc_id` printing. if f.alternate() { diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index df110fdc20a..d04876d0bef 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -82,7 +82,7 @@ use crate::ty::print::{PrintTraitRefExt, describe_as_module}; use crate::ty::util::AlwaysRequiresDrop; use crate::ty::{ self, CrateInherentImpls, GenericArg, GenericArgsRef, PseudoCanonicalInput, Ty, TyCtxt, - TyCtxtFeed, UnusedGenericParams, + TyCtxtFeed, }; use crate::{dep_graph, mir, thir}; @@ -916,6 +916,12 @@ rustc_queries! { cache_on_disk_if { true } } + /// Checks well-formedness of tail calls (`become f()`). + query check_tail_calls(key: LocalDefId) -> Result<(), rustc_errors::ErrorGuaranteed> { + desc { |tcx| "tail-call-checking `{}`", tcx.def_path_str(key) } + cache_on_disk_if { true } + } + /// Returns the types assumed to be well formed while "inside" of the given item. /// /// Note that we've liberated the late bound regions of function signatures, so @@ -2042,15 +2048,6 @@ rustc_queries! { desc { "getting codegen unit `{sym}`" } } - query unused_generic_params(key: ty::InstanceKind<'tcx>) -> UnusedGenericParams { - cache_on_disk_if { key.def_id().is_local() } - desc { - |tcx| "determining which generic parameters are unused by `{}`", - tcx.def_path_str(key.def_id()) - } - separate_provide_extern - } - query backend_optimization_level(_: ()) -> OptLevel { desc { "optimization level used by backend" } } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 3cbb2a3acf5..d4835bb07f6 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -585,6 +585,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self.trait_def(trait_def_id).implement_via_object } + fn trait_is_unsafe(self, trait_def_id: Self::DefId) -> bool { + self.trait_def(trait_def_id).safety == hir::Safety::Unsafe + } + fn is_impl_trait_in_trait(self, def_id: DefId) -> bool { self.is_impl_trait_in_trait(def_id) } diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index fd807882e0f..604f1da26c6 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -1,11 +1,12 @@ //! Diagnostics related methods for `Ty`. -use std::borrow::Cow; use std::fmt::Write; use std::ops::ControlFlow; use rustc_data_structures::fx::FxHashMap; -use rustc_errors::{Applicability, Diag, DiagArgValue, IntoDiagArg, into_diag_arg_using_display}; +use rustc_errors::{ + Applicability, Diag, DiagArgValue, IntoDiagArg, into_diag_arg_using_display, pluralize, +}; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_hir::{self as hir, LangItem, PredicateOrigin, WherePredicateKind}; @@ -161,7 +162,7 @@ pub fn suggest_arbitrary_trait_bound<'tcx>( true } -#[derive(Debug)] +#[derive(Debug, Clone, Copy)] enum SuggestChangingConstraintsMessage<'a> { RestrictBoundFurther, RestrictType { ty: &'a str }, @@ -172,7 +173,7 @@ enum SuggestChangingConstraintsMessage<'a> { fn suggest_changing_unsized_bound( generics: &hir::Generics<'_>, - suggestions: &mut Vec<(Span, String, SuggestChangingConstraintsMessage<'_>)>, + suggestions: &mut Vec<(Span, String, String, SuggestChangingConstraintsMessage<'_>)>, param: &hir::GenericParam<'_>, def_id: Option<DefId>, ) { @@ -207,7 +208,8 @@ fn suggest_changing_unsized_bound( continue; } - let mut push_suggestion = |sp, msg| suggestions.push((sp, String::new(), msg)); + let mut push_suggestion = + |sp, msg| suggestions.push((sp, "Sized".to_string(), String::new(), msg)); if predicate.bounds.len() == unsized_bounds.len() { // All the bounds are unsized bounds, e.g. @@ -278,8 +280,25 @@ pub fn suggest_constraining_type_params<'a>( span_to_replace: Option<Span>, ) -> bool { let mut grouped = FxHashMap::default(); + let mut unstable_suggestion = false; param_names_and_constraints.for_each(|(param_name, constraint, def_id)| { - grouped.entry(param_name).or_insert(Vec::new()).push((constraint, def_id)) + let stable = match def_id { + Some(def_id) => match tcx.lookup_stability(def_id) { + Some(s) => s.level.is_stable(), + None => true, + }, + None => true, + }; + if stable || tcx.sess.is_nightly_build() { + grouped.entry(param_name).or_insert(Vec::new()).push(( + constraint, + def_id, + if stable { "" } else { "unstable " }, + )); + if !stable { + unstable_suggestion = true; + } + } }); let mut applicability = Applicability::MachineApplicable; @@ -290,16 +309,21 @@ pub fn suggest_constraining_type_params<'a>( let Some(param) = param else { return false }; { - let mut sized_constraints = constraints.extract_if(|(_, def_id)| { + let mut sized_constraints = constraints.extract_if(|(_, def_id, _)| { def_id.is_some_and(|def_id| tcx.is_lang_item(def_id, LangItem::Sized)) }); - if let Some((_, def_id)) = sized_constraints.next() { + if let Some((_, def_id, _)) = sized_constraints.next() { applicability = Applicability::MaybeIncorrect; err.span_label(param.span, "this type parameter needs to be `Sized`"); suggest_changing_unsized_bound(generics, &mut suggestions, param, def_id); } } + let bound_message = if constraints.iter().any(|(_, def_id, _)| def_id.is_none()) { + SuggestChangingConstraintsMessage::RestrictBoundFurther + } else { + SuggestChangingConstraintsMessage::RestrictTypeFurther { ty: param_name } + }; // in the scenario like impl has stricter requirements than trait, // we should not suggest restrict bound on the impl, here we double check @@ -312,15 +336,54 @@ pub fn suggest_constraining_type_params<'a>( .collect(); constraints - .retain(|(_, def_id)| def_id.map_or(true, |def| !bound_trait_defs.contains(&def))); + .retain(|(_, def_id, _)| def_id.map_or(true, |def| !bound_trait_defs.contains(&def))); if constraints.is_empty() { continue; } - let mut constraint = constraints.iter().map(|&(c, _)| c).collect::<Vec<_>>(); + let mut constraint = constraints.iter().map(|&(c, _, _)| c).collect::<Vec<_>>(); constraint.sort(); constraint.dedup(); + let all_known = constraints.iter().all(|&(_, def_id, _)| def_id.is_some()); + let all_stable = constraints.iter().all(|&(_, _, stable)| stable.is_empty()); + let all_unstable = constraints.iter().all(|&(_, _, stable)| !stable.is_empty()); + let post = if all_stable || all_unstable { + // Don't redundantly say "trait `X`, trait `Y`", instead "traits `X` and `Y`" + let mut trait_names = constraints + .iter() + .map(|&(c, def_id, _)| match def_id { + None => format!("`{c}`"), + Some(def_id) => format!("`{}`", tcx.item_name(def_id)), + }) + .collect::<Vec<_>>(); + trait_names.sort(); + trait_names.dedup(); + let n = trait_names.len(); + let stable = if all_stable { "" } else { "unstable " }; + let trait_ = if all_known { format!("trait{}", pluralize!(n)) } else { String::new() }; + format!("{stable}{trait_}{}", match &trait_names[..] { + [t] => format!(" {t}"), + [ts @ .., last] => format!(" {} and {last}", ts.join(", ")), + [] => return false, + },) + } else { + // We're more explicit when there's a mix of stable and unstable traits. + let mut trait_names = constraints + .iter() + .map(|&(c, def_id, stable)| match def_id { + None => format!("`{c}`"), + Some(def_id) => format!("{stable}trait `{}`", tcx.item_name(def_id)), + }) + .collect::<Vec<_>>(); + trait_names.sort(); + trait_names.dedup(); + match &trait_names[..] { + [t] => t.to_string(), + [ts @ .., last] => format!("{} and {last}", ts.join(", ")), + [] => return false, + } + }; let constraint = constraint.join(" + "); let mut suggest_restrict = |span, bound_list_non_empty, open_paren_sp| { let suggestion = if span_to_replace.is_some() { @@ -333,13 +396,11 @@ pub fn suggest_constraining_type_params<'a>( format!(" {constraint}") }; - use SuggestChangingConstraintsMessage::RestrictBoundFurther; - if let Some(open_paren_sp) = open_paren_sp { - suggestions.push((open_paren_sp, "(".to_string(), RestrictBoundFurther)); - suggestions.push((span, format!("){suggestion}"), RestrictBoundFurther)); + suggestions.push((open_paren_sp, post.clone(), "(".to_string(), bound_message)); + suggestions.push((span, post.clone(), format!("){suggestion}"), bound_message)); } else { - suggestions.push((span, suggestion, RestrictBoundFurther)); + suggestions.push((span, post.clone(), suggestion, bound_message)); } }; @@ -397,7 +458,8 @@ pub fn suggest_constraining_type_params<'a>( // - insert: `, X: Bar` suggestions.push(( generics.tail_span_for_predicate_suggestion(), - constraints.iter().fold(String::new(), |mut string, &(constraint, _)| { + post, + constraints.iter().fold(String::new(), |mut string, &(constraint, _, _)| { write!(string, ", {param_name}: {constraint}").unwrap(); string }), @@ -426,6 +488,7 @@ pub fn suggest_constraining_type_params<'a>( // default (`<T=Foo>`), so we suggest adding `where T: Bar`. suggestions.push(( generics.tail_span_for_predicate_suggestion(), + post, format!("{where_prefix} {param_name}: {constraint}"), SuggestChangingConstraintsMessage::RestrictTypeFurther { ty: param_name }, )); @@ -439,6 +502,7 @@ pub fn suggest_constraining_type_params<'a>( if let Some(colon_span) = param.colon_span { suggestions.push(( colon_span.shrink_to_hi(), + post, format!(" {constraint}"), SuggestChangingConstraintsMessage::RestrictType { ty: param_name }, )); @@ -451,6 +515,7 @@ pub fn suggest_constraining_type_params<'a>( // - help: consider restricting this type parameter with `T: Foo` suggestions.push(( param.span.shrink_to_hi(), + post, format!(": {constraint}"), SuggestChangingConstraintsMessage::RestrictType { ty: param_name }, )); @@ -459,39 +524,46 @@ pub fn suggest_constraining_type_params<'a>( // FIXME: remove the suggestions that are from derive, as the span is not correct suggestions = suggestions .into_iter() - .filter(|(span, _, _)| !span.in_derive_expansion()) + .filter(|(span, _, _, _)| !span.in_derive_expansion()) .collect::<Vec<_>>(); - + let suggested = !suggestions.is_empty(); if suggestions.len() == 1 { - let (span, suggestion, msg) = suggestions.pop().unwrap(); + let (span, post, suggestion, msg) = suggestions.pop().unwrap(); let msg = match msg { SuggestChangingConstraintsMessage::RestrictBoundFurther => { - Cow::from("consider further restricting this bound") + format!("consider further restricting this bound") + } + SuggestChangingConstraintsMessage::RestrictTypeFurther { ty } + | SuggestChangingConstraintsMessage::RestrictType { ty } + if ty.starts_with("impl ") => + { + format!("consider restricting opaque type `{ty}` with {post}") } SuggestChangingConstraintsMessage::RestrictType { ty } => { - Cow::from(format!("consider restricting type parameter `{ty}`")) + format!("consider restricting type parameter `{ty}` with {post}") } SuggestChangingConstraintsMessage::RestrictTypeFurther { ty } => { - Cow::from(format!("consider further restricting type parameter `{ty}`")) + format!("consider further restricting type parameter `{ty}` with {post}") } SuggestChangingConstraintsMessage::RemoveMaybeUnsized => { - Cow::from("consider removing the `?Sized` bound to make the type parameter `Sized`") + format!("consider removing the `?Sized` bound to make the type parameter `Sized`") } SuggestChangingConstraintsMessage::ReplaceMaybeUnsizedWithSized => { - Cow::from("consider replacing `?Sized` with `Sized`") + format!("consider replacing `?Sized` with `Sized`") } }; err.span_suggestion_verbose(span, msg, suggestion, applicability); } else if suggestions.len() > 1 { + let post = if unstable_suggestion { " (some of them are unstable traits)" } else { "" }; err.multipart_suggestion_verbose( - "consider restricting type parameters", - suggestions.into_iter().map(|(span, suggestion, _)| (span, suggestion)).collect(), + format!("consider restricting type parameters{post}"), + suggestions.into_iter().map(|(span, _, suggestion, _)| (span, suggestion)).collect(), applicability, ); } - true + suggested } /// Collect al types that have an implicit `'static` obligation that we could suggest `'_` for. diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 3d4ce112a64..65c909e70f6 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -19,8 +19,8 @@ use crate::error; use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; use crate::ty::print::{FmtPrinter, Printer, shrunk_instance_name}; use crate::ty::{ - self, EarlyBinder, GenericArgs, GenericArgsRef, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable, - TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, + self, EarlyBinder, GenericArgs, GenericArgsRef, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, + TypeVisitable, TypeVisitableExt, TypeVisitor, }; /// An `InstanceKind` along with the args that are needed to substitute the instance. @@ -917,116 +917,6 @@ impl<'tcx> Instance<'tcx> { tcx.try_normalize_erasing_regions(typing_env, v.instantiate_identity()) } } - - /// Returns a new `Instance` where generic parameters in `instance.args` are replaced by - /// identity parameters if they are determined to be unused in `instance.def`. - pub fn polymorphize(self, tcx: TyCtxt<'tcx>) -> Self { - debug!("polymorphize: running polymorphization analysis"); - if !tcx.sess.opts.unstable_opts.polymorphize { - return self; - } - - let polymorphized_args = polymorphize(tcx, self.def, self.args); - debug!("polymorphize: self={:?} polymorphized_args={:?}", self, polymorphized_args); - Self { def: self.def, args: polymorphized_args } - } -} - -fn polymorphize<'tcx>( - tcx: TyCtxt<'tcx>, - instance: ty::InstanceKind<'tcx>, - args: GenericArgsRef<'tcx>, -) -> GenericArgsRef<'tcx> { - debug!("polymorphize({:?}, {:?})", instance, args); - let unused = tcx.unused_generic_params(instance); - debug!("polymorphize: unused={:?}", unused); - - // If this is a closure or coroutine then we need to handle the case where another closure - // from the function is captured as an upvar and hasn't been polymorphized. In this case, - // the unpolymorphized upvar closure would result in a polymorphized closure producing - // multiple mono items (and eventually symbol clashes). - let def_id = instance.def_id(); - let upvars_ty = match tcx.type_of(def_id).skip_binder().kind() { - ty::Closure(..) => Some(args.as_closure().tupled_upvars_ty()), - ty::Coroutine(..) => { - assert_eq!( - args.as_coroutine().kind_ty(), - tcx.types.unit, - "polymorphization does not support coroutines from async closures" - ); - Some(args.as_coroutine().tupled_upvars_ty()) - } - _ => None, - }; - let has_upvars = upvars_ty.is_some_and(|ty| !ty.tuple_fields().is_empty()); - debug!("polymorphize: upvars_ty={:?} has_upvars={:?}", upvars_ty, has_upvars); - - struct PolymorphizationFolder<'tcx> { - tcx: TyCtxt<'tcx>, - } - - impl<'tcx> ty::TypeFolder<TyCtxt<'tcx>> for PolymorphizationFolder<'tcx> { - fn cx(&self) -> TyCtxt<'tcx> { - self.tcx - } - - fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - debug!("fold_ty: ty={:?}", ty); - match *ty.kind() { - ty::Closure(def_id, args) => { - let polymorphized_args = - polymorphize(self.tcx, ty::InstanceKind::Item(def_id), args); - if args == polymorphized_args { - ty - } else { - Ty::new_closure(self.tcx, def_id, polymorphized_args) - } - } - ty::Coroutine(def_id, args) => { - let polymorphized_args = - polymorphize(self.tcx, ty::InstanceKind::Item(def_id), args); - if args == polymorphized_args { - ty - } else { - Ty::new_coroutine(self.tcx, def_id, polymorphized_args) - } - } - _ => ty.super_fold_with(self), - } - } - } - - GenericArgs::for_item(tcx, def_id, |param, _| { - let is_unused = unused.is_unused(param.index); - debug!("polymorphize: param={:?} is_unused={:?}", param, is_unused); - match param.kind { - // Upvar case: If parameter is a type parameter.. - ty::GenericParamDefKind::Type { .. } if - // ..and has upvars.. - has_upvars && - // ..and this param has the same type as the tupled upvars.. - upvars_ty == Some(args[param.index as usize].expect_ty()) => { - // ..then double-check that polymorphization marked it used.. - debug_assert!(!is_unused); - // ..and polymorphize any closures/coroutines captured as upvars. - let upvars_ty = upvars_ty.unwrap(); - let polymorphized_upvars_ty = upvars_ty.fold_with( - &mut PolymorphizationFolder { tcx }); - debug!("polymorphize: polymorphized_upvars_ty={:?}", polymorphized_upvars_ty); - ty::GenericArg::from(polymorphized_upvars_ty) - }, - - // Simple case: If parameter is a const or type parameter.. - ty::GenericParamDefKind::Const { .. } | ty::GenericParamDefKind::Type { .. } if - // ..and is within range and unused.. - unused.is_unused(param.index) => - // ..then use the identity for this parameter. - tcx.mk_param_from_def(param), - - // Otherwise, use the parameter as before. - _ => args[param.index as usize], - } - }) } fn needs_fn_once_adapter_shim( diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 01ad76aedc3..07573a79260 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -552,7 +552,10 @@ impl<'tcx> HasWasmCAbiOpt for TyCtxt<'tcx> { impl<'tcx> HasX86AbiOpt for TyCtxt<'tcx> { fn x86_abi_opt(&self) -> X86Abi { - X86Abi { regparm: self.sess.opts.unstable_opts.regparm } + X86Abi { + regparm: self.sess.opts.unstable_opts.regparm, + reg_struct_return: self.sess.opts.unstable_opts.reg_struct_return, + } } } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 142db8a17f0..474062218c9 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -978,6 +978,14 @@ impl<'tcx> rustc_type_ir::inherent::Ty<TyCtxt<'tcx>> for Ty<'tcx> { fn async_destructor_ty(self, interner: TyCtxt<'tcx>) -> Ty<'tcx> { self.async_destructor_ty(interner) } + + fn has_unsafe_fields(self) -> bool { + if let ty::Adt(adt_def, ..) = self.kind() { + adt_def.all_fields().any(|x| x.safety == hir::Safety::Unsafe) + } else { + false + } + } } /// Type utilities diff --git a/compiler/rustc_middle/src/ty/vtable.rs b/compiler/rustc_middle/src/ty/vtable.rs index e5eeb23be25..09a05104e49 100644 --- a/compiler/rustc_middle/src/ty/vtable.rs +++ b/compiler/rustc_middle/src/ty/vtable.rs @@ -131,8 +131,7 @@ pub(super) fn vtable_allocation_provider<'tcx>( VtblEntry::Vacant => continue, VtblEntry::Method(instance) => { // Prepare the fn ptr we write into the vtable. - let instance = instance.polymorphize(tcx); - let fn_alloc_id = tcx.reserve_and_set_fn_alloc(instance, CTFE_ALLOC_SALT); + let fn_alloc_id = tcx.reserve_and_set_fn_alloc(*instance, CTFE_ALLOC_SALT); let fn_ptr = Pointer::from(fn_alloc_id); Scalar::from_pointer(fn_ptr, &tcx) } diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 3317f3b7f8a..f43c29d8f5d 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -50,6 +50,10 @@ pub(crate) fn mir_build<'tcx>(tcx: TyCtxtAt<'tcx>, def: LocalDefId) -> Body<'tcx return construct_error(tcx, def, e); } + if let Err(err) = tcx.check_tail_calls(def) { + return construct_error(tcx, def, err); + } + let body = match tcx.thir_body(def) { Err(error_reported) => construct_error(tcx, def, error_reported), Ok((thir, expr)) => { diff --git a/compiler/rustc_mir_build/src/check_tail_calls.rs b/compiler/rustc_mir_build/src/check_tail_calls.rs new file mode 100644 index 00000000000..b1f46d37d50 --- /dev/null +++ b/compiler/rustc_mir_build/src/check_tail_calls.rs @@ -0,0 +1,386 @@ +use rustc_abi::ExternAbi; +use rustc_errors::Applicability; +use rustc_hir::LangItem; +use rustc_hir::def::DefKind; +use rustc_middle::span_bug; +use rustc_middle::thir::visit::{self, Visitor}; +use rustc_middle::thir::{BodyTy, Expr, ExprId, ExprKind, Thir}; +use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_span::def_id::{DefId, LocalDefId}; +use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span}; + +pub(crate) fn check_tail_calls(tcx: TyCtxt<'_>, def: LocalDefId) -> Result<(), ErrorGuaranteed> { + let (thir, expr) = tcx.thir_body(def)?; + let thir = &thir.borrow(); + + // If `thir` is empty, a type error occurred, skip this body. + if thir.exprs.is_empty() { + return Ok(()); + } + + let is_closure = matches!(tcx.def_kind(def), DefKind::Closure); + let caller_ty = tcx.type_of(def).skip_binder(); + + let mut visitor = TailCallCkVisitor { + tcx, + thir, + found_errors: Ok(()), + // FIXME(#132279): we're clearly in a body here. + typing_env: ty::TypingEnv::non_body_analysis(tcx, def), + is_closure, + caller_ty, + }; + + visitor.visit_expr(&thir[expr]); + + visitor.found_errors +} + +struct TailCallCkVisitor<'a, 'tcx> { + tcx: TyCtxt<'tcx>, + thir: &'a Thir<'tcx>, + typing_env: ty::TypingEnv<'tcx>, + /// Whatever the currently checked body is one of a closure + is_closure: bool, + /// The result of the checks, `Err(_)` if there was a problem with some + /// tail call, `Ok(())` if all of them were fine. + found_errors: Result<(), ErrorGuaranteed>, + /// Type of the caller function. + caller_ty: Ty<'tcx>, +} + +impl<'tcx> TailCallCkVisitor<'_, 'tcx> { + fn check_tail_call(&mut self, call: &Expr<'_>, expr: &Expr<'_>) { + if self.is_closure { + self.report_in_closure(expr); + return; + } + + let BodyTy::Fn(caller_sig) = self.thir.body_type else { + span_bug!( + call.span, + "`become` outside of functions should have been disallowed by hit_typeck" + ) + }; + + let ExprKind::Scope { value, .. } = call.kind else { + span_bug!(call.span, "expected scope, found: {call:?}") + }; + let value = &self.thir[value]; + + if matches!( + value.kind, + ExprKind::Binary { .. } + | ExprKind::Unary { .. } + | ExprKind::AssignOp { .. } + | ExprKind::Index { .. } + ) { + self.report_builtin_op(call, expr); + return; + } + + let ExprKind::Call { ty, fun, ref args, from_hir_call, fn_span } = value.kind else { + self.report_non_call(value, expr); + return; + }; + + if !from_hir_call { + self.report_op(ty, args, fn_span, expr); + } + + // Closures in thir look something akin to + // `for<'a> extern "rust-call" fn(&'a [closure@...], ()) -> <[closure@...] as FnOnce<()>>::Output {<[closure@...] as Fn<()>>::call}` + // So we have to check for them in this weird way... + if let &ty::FnDef(did, args) = ty.kind() { + let parent = self.tcx.parent(did); + if self.tcx.fn_trait_kind_from_def_id(parent).is_some() + && args.first().and_then(|arg| arg.as_type()).is_some_and(Ty::is_closure) + { + self.report_calling_closure(&self.thir[fun], args[1].as_type().unwrap(), expr); + + // Tail calling is likely to cause unrelated errors (ABI, argument mismatches), + // skip them, producing an error about calling a closure is enough. + return; + }; + } + + // Erase regions since tail calls don't care about lifetimes + let callee_sig = + self.tcx.normalize_erasing_late_bound_regions(self.typing_env, ty.fn_sig(self.tcx)); + + if caller_sig.abi != callee_sig.abi { + self.report_abi_mismatch(expr.span, caller_sig.abi, callee_sig.abi); + } + + if caller_sig.inputs_and_output != callee_sig.inputs_and_output { + if caller_sig.inputs() != callee_sig.inputs() { + self.report_arguments_mismatch(expr.span, caller_sig, callee_sig); + } + + // FIXME(explicit_tail_calls): this currenly fails for cases where opaques are used. + // e.g. + // ``` + // fn a() -> impl Sized { become b() } // ICE + // fn b() -> u8 { 0 } + // ``` + // we should think what is the expected behavior here. + // (we should probably just accept this by revealing opaques?) + if caller_sig.output() != callee_sig.output() { + span_bug!(expr.span, "hir typeck should have checked the return type already"); + } + } + + { + let caller_needs_location = self.needs_location(self.caller_ty); + let callee_needs_location = self.needs_location(ty); + + if caller_needs_location != callee_needs_location { + self.report_track_caller_mismatch(expr.span, caller_needs_location); + } + } + + if caller_sig.c_variadic { + self.report_c_variadic_caller(expr.span); + } + + if callee_sig.c_variadic { + self.report_c_variadic_callee(expr.span); + } + } + + /// Returns true if function of type `ty` needs location argument + /// (i.e. if a function is marked as `#[track_caller]`) + fn needs_location(&self, ty: Ty<'tcx>) -> bool { + if let &ty::FnDef(did, substs) = ty.kind() { + let instance = + ty::Instance::expect_resolve(self.tcx, self.typing_env, did, substs, DUMMY_SP); + + instance.def.requires_caller_location(self.tcx) + } else { + false + } + } + + fn report_in_closure(&mut self, expr: &Expr<'_>) { + let err = self.tcx.dcx().span_err(expr.span, "`become` is not allowed in closures"); + self.found_errors = Err(err); + } + + fn report_builtin_op(&mut self, value: &Expr<'_>, expr: &Expr<'_>) { + let err = self + .tcx + .dcx() + .struct_span_err(value.span, "`become` does not support operators") + .with_note("using `become` on a builtin operator is not useful") + .with_span_suggestion( + value.span.until(expr.span), + "try using `return` instead", + "return ", + Applicability::MachineApplicable, + ) + .emit(); + self.found_errors = Err(err); + } + + fn report_op(&mut self, fun_ty: Ty<'_>, args: &[ExprId], fn_span: Span, expr: &Expr<'_>) { + let mut err = + self.tcx.dcx().struct_span_err(fn_span, "`become` does not support operators"); + + if let &ty::FnDef(did, _substs) = fun_ty.kind() + && let parent = self.tcx.parent(did) + && matches!(self.tcx.def_kind(parent), DefKind::Trait) + && let Some(method) = op_trait_as_method_name(self.tcx, parent) + { + match args { + &[arg] => { + let arg = &self.thir[arg]; + + err.multipart_suggestion( + "try using the method directly", + vec![ + (fn_span.shrink_to_lo().until(arg.span), "(".to_owned()), + (arg.span.shrink_to_hi(), format!(").{method}()")), + ], + Applicability::MaybeIncorrect, + ); + } + &[lhs, rhs] => { + let lhs = &self.thir[lhs]; + let rhs = &self.thir[rhs]; + + err.multipart_suggestion( + "try using the method directly", + vec![ + (lhs.span.shrink_to_lo(), format!("(")), + (lhs.span.between(rhs.span), format!(").{method}(")), + (rhs.span.between(expr.span.shrink_to_hi()), ")".to_owned()), + ], + Applicability::MaybeIncorrect, + ); + } + _ => span_bug!(expr.span, "operator with more than 2 args? {args:?}"), + } + } + + self.found_errors = Err(err.emit()); + } + + fn report_non_call(&mut self, value: &Expr<'_>, expr: &Expr<'_>) { + let err = self + .tcx + .dcx() + .struct_span_err(value.span, "`become` requires a function call") + .with_span_note(value.span, "not a function call") + .with_span_suggestion( + value.span.until(expr.span), + "try using `return` instead", + "return ", + Applicability::MaybeIncorrect, + ) + .emit(); + self.found_errors = Err(err); + } + + fn report_calling_closure(&mut self, fun: &Expr<'_>, tupled_args: Ty<'_>, expr: &Expr<'_>) { + let underscored_args = match tupled_args.kind() { + ty::Tuple(tys) if tys.is_empty() => "".to_owned(), + ty::Tuple(tys) => std::iter::repeat("_, ").take(tys.len() - 1).chain(["_"]).collect(), + _ => "_".to_owned(), + }; + + let err = self + .tcx + .dcx() + .struct_span_err(expr.span, "tail calling closures directly is not allowed") + .with_multipart_suggestion( + "try casting the closure to a function pointer type", + vec![ + (fun.span.shrink_to_lo(), "(".to_owned()), + (fun.span.shrink_to_hi(), format!(" as fn({underscored_args}) -> _)")), + ], + Applicability::MaybeIncorrect, + ) + .emit(); + self.found_errors = Err(err); + } + + fn report_abi_mismatch(&mut self, sp: Span, caller_abi: ExternAbi, callee_abi: ExternAbi) { + let err = self + .tcx + .dcx() + .struct_span_err(sp, "mismatched function ABIs") + .with_note("`become` requires caller and callee to have the same ABI") + .with_note(format!("caller ABI is `{caller_abi}`, while callee ABI is `{callee_abi}`")) + .emit(); + self.found_errors = Err(err); + } + + fn report_arguments_mismatch( + &mut self, + sp: Span, + caller_sig: ty::FnSig<'_>, + callee_sig: ty::FnSig<'_>, + ) { + let err = self + .tcx + .dcx() + .struct_span_err(sp, "mismatched signatures") + .with_note("`become` requires caller and callee to have matching signatures") + .with_note(format!("caller signature: `{caller_sig}`")) + .with_note(format!("callee signature: `{callee_sig}`")) + .emit(); + self.found_errors = Err(err); + } + + fn report_track_caller_mismatch(&mut self, sp: Span, caller_needs_location: bool) { + let err = match caller_needs_location { + true => self + .tcx + .dcx() + .struct_span_err( + sp, + "a function marked with `#[track_caller]` cannot tail-call one that is not", + ) + .emit(), + false => self + .tcx + .dcx() + .struct_span_err( + sp, + "a function mot marked with `#[track_caller]` cannot tail-call one that is", + ) + .emit(), + }; + + self.found_errors = Err(err); + } + + fn report_c_variadic_caller(&mut self, sp: Span) { + let err = self + .tcx + .dcx() + // FIXME(explicit_tail_calls): highlight the `...` + .struct_span_err(sp, "tail-calls are not allowed in c-variadic functions") + .emit(); + + self.found_errors = Err(err); + } + + fn report_c_variadic_callee(&mut self, sp: Span) { + let err = self + .tcx + .dcx() + // FIXME(explicit_tail_calls): highlight the function or something... + .struct_span_err(sp, "c-variadic functions can't be tail-called") + .emit(); + + self.found_errors = Err(err); + } +} + +impl<'a, 'tcx> Visitor<'a, 'tcx> for TailCallCkVisitor<'a, 'tcx> { + fn thir(&self) -> &'a Thir<'tcx> { + &self.thir + } + + fn visit_expr(&mut self, expr: &'a Expr<'tcx>) { + if let ExprKind::Become { value } = expr.kind { + let call = &self.thir[value]; + self.check_tail_call(call, expr); + } + + visit::walk_expr(self, expr); + } +} + +fn op_trait_as_method_name(tcx: TyCtxt<'_>, trait_did: DefId) -> Option<&'static str> { + let m = match tcx.as_lang_item(trait_did)? { + LangItem::Add => "add", + LangItem::Sub => "sub", + LangItem::Mul => "mul", + LangItem::Div => "div", + LangItem::Rem => "rem", + LangItem::Neg => "neg", + LangItem::Not => "not", + LangItem::BitXor => "bitxor", + LangItem::BitAnd => "bitand", + LangItem::BitOr => "bitor", + LangItem::Shl => "shl", + LangItem::Shr => "shr", + LangItem::AddAssign => "add_assign", + LangItem::SubAssign => "sub_assign", + LangItem::MulAssign => "mul_assign", + LangItem::DivAssign => "div_assign", + LangItem::RemAssign => "rem_assign", + LangItem::BitXorAssign => "bitxor_assign", + LangItem::BitAndAssign => "bitand_assign", + LangItem::BitOrAssign => "bitor_assign", + LangItem::ShlAssign => "shl_assign", + LangItem::ShrAssign => "shr_assign", + LangItem::Index => "index", + LangItem::IndexMut => "index_mut", + _ => return None, + }; + + Some(m) +} diff --git a/compiler/rustc_mir_build/src/lib.rs b/compiler/rustc_mir_build/src/lib.rs index 3dbb552cdbb..833e5019865 100644 --- a/compiler/rustc_mir_build/src/lib.rs +++ b/compiler/rustc_mir_build/src/lib.rs @@ -12,6 +12,7 @@ // tidy-alphabetical-end mod build; +mod check_tail_calls; mod check_unsafety; mod errors; pub mod lints; @@ -28,6 +29,7 @@ pub fn provide(providers: &mut Providers) { providers.closure_saved_names_of_captured_variables = build::closure_saved_names_of_captured_variables; providers.check_unsafety = check_unsafety::check_unsafety; + providers.check_tail_calls = check_tail_calls::check_tail_calls; providers.thir_body = thir::cx::thir_body; providers.hooks.thir_tree = thir::print::thir_tree; providers.hooks.thir_flat = thir::print::thir_flat; diff --git a/compiler/rustc_mir_build/src/thir/constant.rs b/compiler/rustc_mir_build/src/thir/constant.rs index 3fa0e4def82..30b6718683b 100644 --- a/compiler/rustc_mir_build/src/thir/constant.rs +++ b/compiler/rustc_mir_build/src/thir/constant.rs @@ -2,7 +2,7 @@ use rustc_ast as ast; use rustc_hir::LangItem; use rustc_middle::bug; use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput}; -use rustc_middle::ty::{self, ScalarInt, TyCtxt}; +use rustc_middle::ty::{self, ScalarInt, TyCtxt, TypeVisitableExt as _}; use tracing::trace; use crate::build::parse_float_into_scalar; @@ -13,6 +13,10 @@ pub(crate) fn lit_to_const<'tcx>( ) -> Result<ty::Const<'tcx>, LitToConstError> { let LitToConstInput { lit, ty, neg } = lit_input; + if let Err(guar) = ty.error_reported() { + return Ok(ty::Const::new_error(tcx, guar)); + } + let trunc = |n| { let width = match tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)) { Ok(layout) => layout.size, diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 3ac53fa6272..2dbc8b7b573 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -626,32 +626,8 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { ) -> PatKind<'tcx> { let tcx = self.tcx; let def_id = block.def_id; - let body_id = block.body; - let expr = &tcx.hir().body(body_id).value; let ty = tcx.typeck(def_id).node_type(block.hir_id); - // Special case inline consts that are just literals. This is solely - // a performance optimization, as we could also just go through the regular - // const eval path below. - // FIXME: investigate the performance impact of removing this. - let lit_input = match expr.kind { - hir::ExprKind::Lit(lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: false }), - hir::ExprKind::Unary(hir::UnOp::Neg, expr) => match expr.kind { - hir::ExprKind::Lit(lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: true }), - _ => None, - }, - _ => None, - }; - if let Some(lit_input) = lit_input { - match tcx.at(expr.span).lit_to_const(lit_input) { - Ok(c) => return self.const_to_pat(c, ty, id, span).kind, - // If an error occurred, ignore that it's a literal - // and leave reporting the error up to const eval of - // the unevaluated constant below. - Err(_) => {} - } - } - let typeck_root_def_id = tcx.typeck_root_def_id(def_id.to_def_id()); let parent_args = tcx.erase_regions(ty::GenericArgs::identity_for_item(tcx, typeck_root_def_id)); diff --git a/compiler/rustc_monomorphize/messages.ftl b/compiler/rustc_monomorphize/messages.ftl index 8528a2e68c0..540ce7cc4ce 100644 --- a/compiler/rustc_monomorphize/messages.ftl +++ b/compiler/rustc_monomorphize/messages.ftl @@ -41,6 +41,4 @@ monomorphize_symbol_already_defined = symbol `{$symbol}` is already defined monomorphize_unknown_cgu_collection_mode = unknown codegen-item collection mode '{$mode}', falling back to 'lazy' mode -monomorphize_unused_generic_params = item has unused generic parameters - monomorphize_written_to_path = the full type name has been written to '{$path}' diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 5efe7ffc7b9..480d82c1a38 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -965,9 +965,7 @@ fn should_codegen_locally<'tcx>(tcx: TyCtxtAt<'tcx>, instance: Instance<'tcx>) - return true; } - if tcx.is_reachable_non_generic(def_id) - || instance.polymorphize(*tcx).upstream_monomorphization(*tcx).is_some() - { + if tcx.is_reachable_non_generic(def_id) || instance.upstream_monomorphization(*tcx).is_some() { // We can link to the item in question, no instance needed in this crate. return false; } @@ -1114,7 +1112,7 @@ fn create_fn_mono_item<'tcx>( crate::util::dump_closure_profile(tcx, instance); } - respan(source, MonoItem::Fn(instance.polymorphize(tcx))) + respan(source, MonoItem::Fn(instance)) } /// Creates a `MonoItem` for each method that is referenced by the vtable for diff --git a/compiler/rustc_monomorphize/src/errors.rs b/compiler/rustc_monomorphize/src/errors.rs index 02865cad302..fc8d63b5888 100644 --- a/compiler/rustc_monomorphize/src/errors.rs +++ b/compiler/rustc_monomorphize/src/errors.rs @@ -1,11 +1,8 @@ use std::path::PathBuf; -use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level}; use rustc_macros::{Diagnostic, LintDiagnostic}; use rustc_span::{Span, Symbol}; -use crate::fluent_generated as fluent; - #[derive(Diagnostic)] #[diag(monomorphize_recursion_limit)] pub(crate) struct RecursionLimit { @@ -28,28 +25,6 @@ pub(crate) struct NoOptimizedMir { pub crate_name: Symbol, } -pub(crate) struct UnusedGenericParamsHint { - pub span: Span, - pub param_spans: Vec<Span>, - pub param_names: Vec<String>, -} - -impl<G: EmissionGuarantee> Diagnostic<'_, G> for UnusedGenericParamsHint { - #[track_caller] - fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { - let mut diag = Diag::new(dcx, level, fluent::monomorphize_unused_generic_params); - diag.span(self.span); - for (span, name) in self.param_spans.into_iter().zip(self.param_names) { - // FIXME: I can figure out how to do a label with a fluent string with a fixed message, - // or a label with a dynamic value in a hard-coded string, but I haven't figured out - // how to combine the two. 😢 - #[allow(rustc::untranslatable_diagnostic)] - diag.span_label(span, format!("generic parameter `{name}` is unused")); - } - diag - } -} - #[derive(LintDiagnostic)] #[diag(monomorphize_large_assignments)] #[note] diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs index 0f08930fb4c..caae54cd559 100644 --- a/compiler/rustc_monomorphize/src/lib.rs +++ b/compiler/rustc_monomorphize/src/lib.rs @@ -19,7 +19,6 @@ mod collector; mod errors; mod mono_checks; mod partitioning; -mod polymorphize; mod util; rustc_fluent_macro::fluent_messages! { "../messages.ftl" } @@ -50,6 +49,5 @@ fn custom_coerce_unsize_info<'tcx>( pub fn provide(providers: &mut Providers) { partitioning::provide(providers); - polymorphize::provide(providers); mono_checks::provide(providers); } diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs index 7ea4ded2b05..dabce72650a 100644 --- a/compiler/rustc_monomorphize/src/partitioning.rs +++ b/compiler/rustc_monomorphize/src/partitioning.rs @@ -113,7 +113,6 @@ use rustc_middle::mir::mono::{ Visibility, }; use rustc_middle::ty::print::{characteristic_def_id_of_type, with_no_trimmed_paths}; -use rustc_middle::ty::visit::TypeVisitableExt; use rustc_middle::ty::{self, InstanceKind, TyCtxt}; use rustc_middle::util::Providers; use rustc_session::CodegenUnits; @@ -661,18 +660,14 @@ fn characteristic_def_id_of_mono_item<'tcx>( return None; } - // When polymorphization is enabled, methods which do not depend on their generic - // parameters, but the self-type of their impl block do will fail to normalize. - if !tcx.sess.opts.unstable_opts.polymorphize || !instance.has_param() { - // This is a method within an impl, find out what the self-type is: - let impl_self_ty = tcx.instantiate_and_normalize_erasing_regions( - instance.args, - ty::TypingEnv::fully_monomorphized(), - tcx.type_of(impl_def_id), - ); - if let Some(def_id) = characteristic_def_id_of_type(impl_self_ty) { - return Some(def_id); - } + // This is a method within an impl, find out what the self-type is: + let impl_self_ty = tcx.instantiate_and_normalize_erasing_regions( + instance.args, + ty::TypingEnv::fully_monomorphized(), + tcx.type_of(impl_def_id), + ); + if let Some(def_id) = characteristic_def_id_of_type(impl_self_ty) { + return Some(def_id); } } diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs deleted file mode 100644 index e049fe99664..00000000000 --- a/compiler/rustc_monomorphize/src/polymorphize.rs +++ /dev/null @@ -1,334 +0,0 @@ -//! Polymorphization Analysis -//! ========================= -//! -//! This module implements an analysis of functions, methods and closures to determine which -//! generic parameters are unused (and eventually, in what ways generic parameters are used - only -//! for their size, offset of a field, etc.). - -use rustc_hir::ConstContext; -use rustc_hir::def::DefKind; -use rustc_hir::def_id::DefId; -use rustc_middle::mir::visit::{TyContext, Visitor}; -use rustc_middle::mir::{self, Local, LocalDecl, Location}; -use rustc_middle::query::Providers; -use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor}; -use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, UnusedGenericParams}; -use rustc_span::symbol::sym; -use tracing::{debug, instrument}; - -use crate::errors::UnusedGenericParamsHint; - -/// Provide implementations of queries relating to polymorphization analysis. -pub(crate) fn provide(providers: &mut Providers) { - providers.unused_generic_params = unused_generic_params; -} - -/// Determine which generic parameters are used by the instance. -/// -/// Returns a bitset where bits representing unused parameters are set (`is_empty` indicates all -/// parameters are used). -fn unused_generic_params<'tcx>( - tcx: TyCtxt<'tcx>, - instance: ty::InstanceKind<'tcx>, -) -> UnusedGenericParams { - assert!(instance.def_id().is_local()); - - if !tcx.sess.opts.unstable_opts.polymorphize { - // If polymorphization disabled, then all parameters are used. - return UnusedGenericParams::new_all_used(); - } - - let def_id = instance.def_id(); - // Exit early if this instance should not be polymorphized. - if !should_polymorphize(tcx, def_id, instance) { - return UnusedGenericParams::new_all_used(); - } - - let generics = tcx.generics_of(def_id); - debug!(?generics); - - // Exit early when there are no parameters to be unused. - if generics.is_empty() { - return UnusedGenericParams::new_all_used(); - } - - // Create a bitset with N rightmost ones for each parameter. - let generics_count: u32 = - generics.count().try_into().expect("more generic parameters than can fit into a `u32`"); - let mut unused_parameters = UnusedGenericParams::new_all_unused(generics_count); - debug!(?unused_parameters, "(start)"); - - mark_used_by_default_parameters(tcx, def_id, generics, &mut unused_parameters); - debug!(?unused_parameters, "(after default)"); - - // Visit MIR and accumulate used generic parameters. - let body = match tcx.hir().body_const_context(def_id.expect_local()) { - // Const functions are actually called and should thus be considered for polymorphization - // via their runtime MIR. - Some(ConstContext::ConstFn) | None => tcx.optimized_mir(def_id), - Some(_) => tcx.mir_for_ctfe(def_id), - }; - let mut vis = MarkUsedGenericParams { tcx, def_id, unused_parameters: &mut unused_parameters }; - vis.visit_body(body); - debug!(?unused_parameters, "(end)"); - - // Emit errors for debugging and testing if enabled. - if !unused_parameters.all_used() { - emit_unused_generic_params_error(tcx, def_id, generics, &unused_parameters); - } - - unused_parameters -} - -/// Returns `true` if the instance should be polymorphized. -fn should_polymorphize<'tcx>( - tcx: TyCtxt<'tcx>, - def_id: DefId, - instance: ty::InstanceKind<'tcx>, -) -> bool { - // If an instance's MIR body is not polymorphic then the modified generic parameters that are - // derived from polymorphization's result won't make any difference. - if !instance.has_polymorphic_mir_body() { - return false; - } - - // Don't polymorphize intrinsics or virtual calls - calling `instance_mir` will panic. - if matches!(instance, ty::InstanceKind::Intrinsic(..) | ty::InstanceKind::Virtual(..)) { - return false; - } - - // Foreign items have no bodies to analyze. - if tcx.is_foreign_item(def_id) { - return false; - } - - // Make sure there is MIR available. - match tcx.hir().body_const_context(def_id.expect_local()) { - Some(ConstContext::ConstFn) | None if !tcx.is_mir_available(def_id) => { - debug!("no mir available"); - return false; - } - Some(_) if !tcx.is_ctfe_mir_available(def_id) => { - debug!("no ctfe mir available"); - return false; - } - _ => true, - } -} - -/// Some parameters are considered used-by-default, such as non-generic parameters and the dummy -/// generic parameters from closures, this function marks them as used. `leaf_is_closure` should -/// be `true` if the item that `unused_generic_params` was invoked on is a closure. -#[instrument(level = "debug", skip(tcx, def_id, generics, unused_parameters))] -fn mark_used_by_default_parameters<'tcx>( - tcx: TyCtxt<'tcx>, - def_id: DefId, - generics: &'tcx ty::Generics, - unused_parameters: &mut UnusedGenericParams, -) { - match tcx.def_kind(def_id) { - DefKind::Closure | DefKind::SyntheticCoroutineBody => { - for param in &generics.own_params { - debug!(?param, "(closure/gen)"); - unused_parameters.mark_used(param.index); - } - } - DefKind::Mod - | DefKind::Struct - | DefKind::Union - | DefKind::Enum - | DefKind::Variant - | DefKind::Trait - | DefKind::TyAlias - | DefKind::ForeignTy - | DefKind::TraitAlias - | DefKind::AssocTy - | DefKind::TyParam - | DefKind::Fn - | DefKind::Const - | DefKind::ConstParam - | DefKind::Static { .. } - | DefKind::Ctor(_, _) - | DefKind::AssocFn - | DefKind::AssocConst - | DefKind::Macro(_) - | DefKind::ExternCrate - | DefKind::Use - | DefKind::ForeignMod - | DefKind::AnonConst - | DefKind::InlineConst - | DefKind::OpaqueTy - | DefKind::Field - | DefKind::LifetimeParam - | DefKind::GlobalAsm - | DefKind::Impl { .. } => { - for param in &generics.own_params { - debug!(?param, "(other)"); - if let ty::GenericParamDefKind::Lifetime = param.kind { - unused_parameters.mark_used(param.index); - } - } - } - } - - if let Some(parent) = generics.parent { - mark_used_by_default_parameters(tcx, parent, tcx.generics_of(parent), unused_parameters); - } -} - -/// Emit errors for the function annotated by `#[rustc_polymorphize_error]`, labelling each generic -/// parameter which was unused. -#[instrument(level = "debug", skip(tcx, generics))] -fn emit_unused_generic_params_error<'tcx>( - tcx: TyCtxt<'tcx>, - def_id: DefId, - generics: &'tcx ty::Generics, - unused_parameters: &UnusedGenericParams, -) { - let base_def_id = tcx.typeck_root_def_id(def_id); - if !tcx.has_attr(base_def_id, sym::rustc_polymorphize_error) { - return; - } - - let fn_span = match tcx.opt_item_ident(def_id) { - Some(ident) => ident.span, - _ => tcx.def_span(def_id), - }; - - let mut param_spans = Vec::new(); - let mut param_names = Vec::new(); - let mut next_generics = Some(generics); - while let Some(generics) = next_generics { - for param in &generics.own_params { - if unused_parameters.is_unused(param.index) { - debug!(?param); - let def_span = tcx.def_span(param.def_id); - param_spans.push(def_span); - param_names.push(param.name.to_string()); - } - } - - next_generics = generics.parent.map(|did| tcx.generics_of(did)); - } - - tcx.dcx().emit_err(UnusedGenericParamsHint { span: fn_span, param_spans, param_names }); -} - -/// Visitor used to aggregate generic parameter uses. -struct MarkUsedGenericParams<'a, 'tcx> { - tcx: TyCtxt<'tcx>, - def_id: DefId, - unused_parameters: &'a mut UnusedGenericParams, -} - -impl<'a, 'tcx> MarkUsedGenericParams<'a, 'tcx> { - /// Invoke `unused_generic_params` on a body contained within the current item (e.g. - /// a closure, coroutine or constant). - #[instrument(level = "debug", skip(self, def_id, args))] - fn visit_child_body(&mut self, def_id: DefId, args: GenericArgsRef<'tcx>) { - let instance = ty::InstanceKind::Item(def_id); - let unused = self.tcx.unused_generic_params(instance); - debug!(?self.unused_parameters, ?unused); - for (i, arg) in args.iter().enumerate() { - let i = i.try_into().unwrap(); - if unused.is_used(i) { - arg.visit_with(self); - } - } - debug!(?self.unused_parameters); - } -} - -impl<'a, 'tcx> Visitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> { - #[instrument(level = "debug", skip(self, local))] - fn visit_local_decl(&mut self, local: Local, local_decl: &LocalDecl<'tcx>) { - if local == Local::from_usize(1) { - let def_kind = self.tcx.def_kind(self.def_id); - if matches!(def_kind, DefKind::Closure) { - // Skip visiting the closure/coroutine that is currently being processed. This only - // happens because the first argument to the closure is a reference to itself and - // that will call `visit_args`, resulting in each generic parameter captured being - // considered used by default. - debug!("skipping closure args"); - return; - } - } - - self.super_local_decl(local, local_decl); - } - - fn visit_const_operand(&mut self, ct: &mir::ConstOperand<'tcx>, location: Location) { - match ct.const_ { - mir::Const::Ty(_, c) => { - c.visit_with(self); - } - mir::Const::Unevaluated(mir::UnevaluatedConst { def, args: _, promoted }, ty) => { - // Avoid considering `T` unused when constants are of the form: - // `<Self as Foo<T>>::foo::promoted[p]` - if let Some(p) = promoted { - if self.def_id == def && !self.tcx.generics_of(def).has_self { - // If there is a promoted, don't look at the args - since it will always contain - // the generic parameters, instead, traverse the promoted MIR. - let promoted = self.tcx.promoted_mir(def); - self.visit_body(&promoted[p]); - } - } - - Visitor::visit_ty(self, ty, TyContext::Location(location)); - } - mir::Const::Val(_, ty) => Visitor::visit_ty(self, ty, TyContext::Location(location)), - } - } - - fn visit_ty(&mut self, ty: Ty<'tcx>, _: TyContext) { - ty.visit_with(self); - } -} - -impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for MarkUsedGenericParams<'a, 'tcx> { - #[instrument(level = "debug", skip(self))] - fn visit_const(&mut self, c: ty::Const<'tcx>) { - if !c.has_non_region_param() { - return; - } - - match c.kind() { - ty::ConstKind::Param(param) => { - debug!(?param); - self.unused_parameters.mark_used(param.index); - } - ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, args }) - if matches!(self.tcx.def_kind(def), DefKind::AnonConst) => - { - self.visit_child_body(def, args); - } - _ => c.super_visit_with(self), - } - } - - #[instrument(level = "debug", skip(self))] - fn visit_ty(&mut self, ty: Ty<'tcx>) { - if !ty.has_non_region_param() { - return; - } - - match *ty.kind() { - ty::Closure(def_id, args) | ty::Coroutine(def_id, args, ..) => { - debug!(?def_id); - // Avoid cycle errors with coroutines. - if def_id == self.def_id { - return; - } - - // Consider any generic parameters used by any closures/coroutines as used in the - // parent. - self.visit_child_body(def_id, args); - } - ty::Param(param) => { - debug!(?param); - self.unused_parameters.mark_used(param.index); - } - _ => ty.super_visit_with(self), - } - } -} diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 6641d2bf924..12df35d30b8 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -169,6 +169,14 @@ where return result; } + // Only consider auto impls of unsafe traits when there are no unsafe + // fields. + if ecx.cx().trait_is_unsafe(goal.predicate.def_id()) + && goal.predicate.self_ty().has_unsafe_fields() + { + return Err(NoSolution); + } + // We only look into opaque types during analysis for opaque types // outside of their defining scope. Doing so for opaques in the // defining scope may require calling `typeck` on the same item we're diff --git a/compiler/rustc_session/messages.ftl b/compiler/rustc_session/messages.ftl index 8fd87893a98..eb14b78a003 100644 --- a/compiler/rustc_session/messages.ftl +++ b/compiler/rustc_session/messages.ftl @@ -135,5 +135,6 @@ session_unsupported_crate_type_for_target = session_unsupported_dwarf_version = requested DWARF version {$dwarf_version} is greater than 5 +session_unsupported_reg_struct_return_arch = `-Zreg-struct-return` is only supported on x86 session_unsupported_regparm = `-Zregparm={$regparm}` is unsupported (valid values 0-3) session_unsupported_regparm_arch = `-Zregparm=N` is only supported on x86 diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index 736a5ce0704..6c26a781487 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -490,6 +490,10 @@ pub(crate) struct UnsupportedRegparm { pub(crate) struct UnsupportedRegparmArch; #[derive(Diagnostic)] +#[diag(session_unsupported_reg_struct_return_arch)] +pub(crate) struct UnsupportedRegStructReturnArch; + +#[derive(Diagnostic)] #[diag(session_failed_to_create_profiler)] pub(crate) struct FailedToCreateProfiler { pub(crate) err: String, diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 2c0302bbb2b..b01d9e5e8e3 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1950,8 +1950,6 @@ options! { (default: PLT is disabled if full relro is enabled on x86_64)"), polonius: Polonius = (Polonius::default(), parse_polonius, [TRACKED], "enable polonius-based borrow-checker (default: no)"), - polymorphize: bool = (false, parse_bool, [TRACKED], - "perform polymorphization analysis"), pre_link_arg: (/* redirected to pre_link_args */) = ((), parse_string_push, [UNTRACKED], "a single extra argument to prepend the linker invocation (can be used several times)"), pre_link_args: Vec<String> = (Vec::new(), parse_list, [UNTRACKED], @@ -1988,6 +1986,9 @@ options! { "enable queries of the dependency graph for regression testing (default: no)"), randomize_layout: bool = (false, parse_bool, [TRACKED], "randomize the layout of types (default: no)"), + reg_struct_return: bool = (false, parse_bool, [TRACKED], + "On x86-32 targets, it overrides the default ABI to return small structs in registers. + It is UNSOUND to link together crates that use different values for this flag!"), regparm: Option<u32> = (None, parse_opt_number, [TRACKED], "On x86-32 targets, setting this to N causes the compiler to pass N arguments \ in registers EAX, EDX, and ECX instead of on the stack for\ diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 120ae9946ea..7db3b7b7d9d 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -1305,6 +1305,11 @@ fn validate_commandline_args_with_session_available(sess: &Session) { sess.dcx().emit_err(errors::UnsupportedRegparmArch); } } + if sess.opts.unstable_opts.reg_struct_return { + if sess.target.arch != "x86" { + sess.dcx().emit_err(errors::UnsupportedRegStructReturnArch); + } + } // The code model check applies to `thunk` and `thunk-extern`, but not `thunk-inline`, so it is // kept as a `match` to force a change if new ones are added, even if we currently only support diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 47ceab750cf..a7dc20a874b 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1746,7 +1746,6 @@ symbols! { rustc_peek_liveness, rustc_peek_maybe_init, rustc_peek_maybe_uninit, - rustc_polymorphize_error, rustc_preserve_ub_checks, rustc_private, rustc_proc_macro_decls, diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index dcbc5f0f76d..1a10ab8829c 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -256,7 +256,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { }); // Encode impl generic params if the generic parameters contain non-region parameters - // (implying polymorphization is enabled) and this isn't an inherent impl. + // and this isn't an inherent impl. if impl_trait_ref.is_some() && args.iter().any(|a| a.has_non_region_param()) { self.path_generic_args( |this| { @@ -330,9 +330,8 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { ty::Float(FloatTy::F128) => "C4f128", ty::Never => "z", - // Should only be encountered with polymorphization, - // or within the identity-substituted impl header of an - // item nested within an impl item. + // Should only be encountered within the identity-substituted + // impl header of an item nested within an impl item. ty::Param(_) => "p", ty::Bound(..) | ty::Placeholder(_) | ty::Infer(_) | ty::Error(_) => bug!(), @@ -558,9 +557,8 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { let (ct_ty, valtree) = match ct.kind() { ty::ConstKind::Value(ty, val) => (ty, val), - // Should only be encountered with polymorphization, - // or within the identity-substituted impl header of an - // item nested within an impl item. + // Should only be encountered within the identity-substituted + // impl header of an item nested within an impl item. ty::ConstKind::Param(_) => { // Never cached (single-character). self.push("p"); diff --git a/compiler/rustc_target/src/callconv/mod.rs b/compiler/rustc_target/src/callconv/mod.rs index fb0fe402934..746e8173807 100644 --- a/compiler/rustc_target/src/callconv/mod.rs +++ b/compiler/rustc_target/src/callconv/mod.rs @@ -661,7 +661,9 @@ impl<'a, Ty> FnAbi<'a, Ty> { } _ => (x86::Flavor::General, None), }; - x86::compute_abi_info(cx, self, x86::X86Options { flavor, regparm }); + let reg_struct_return = cx.x86_abi_opt().reg_struct_return; + let opts = x86::X86Options { flavor, regparm, reg_struct_return }; + x86::compute_abi_info(cx, self, opts); } "x86_64" => match abi { spec::abi::Abi::SysV64 { .. } => x86_64::compute_abi_info(cx, self), diff --git a/compiler/rustc_target/src/callconv/x86.rs b/compiler/rustc_target/src/callconv/x86.rs index a5af975d4d2..cd8465c09ca 100644 --- a/compiler/rustc_target/src/callconv/x86.rs +++ b/compiler/rustc_target/src/callconv/x86.rs @@ -14,6 +14,7 @@ pub(crate) enum Flavor { pub(crate) struct X86Options { pub flavor: Flavor, pub regparm: Option<u32>, + pub reg_struct_return: bool, } pub(crate) fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>, opts: X86Options) @@ -31,7 +32,7 @@ where // https://www.angelcode.com/dev/callconv/callconv.html // Clang's ABI handling is in lib/CodeGen/TargetInfo.cpp let t = cx.target_spec(); - if t.abi_return_struct_as_int { + if t.abi_return_struct_as_int || opts.reg_struct_return { // According to Clang, everyone but MSVC returns single-element // float aggregates directly in a floating-point register. if !t.is_like_msvc && fn_abi.ret.layout.is_single_fp_element(cx) { diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index a2e9430830a..210d67fa1aa 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -2117,6 +2117,8 @@ pub struct X86Abi { /// On x86-32 targets, the regparm N causes the compiler to pass arguments /// in registers EAX, EDX, and ECX instead of on the stack. pub regparm: Option<u32>, + /// Override the default ABI to return small structs in registers + pub reg_struct_return: bool, } pub trait HasX86AbiOpt { diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 32b4567aba4..3e2c8467d32 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -18,6 +18,7 @@ use rustc_infer::traits::{ use rustc_middle::ty::fast_reject::DeepRejectCtxt; use rustc_middle::ty::{self, ToPolyTraitRef, Ty, TypeVisitableExt, TypingMode}; use rustc_middle::{bug, span_bug}; +use rustc_type_ir::Interner; use tracing::{debug, instrument, trace}; use super::SelectionCandidate::*; @@ -794,6 +795,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::Never | ty::Tuple(_) | ty::CoroutineWitness(..) => { + use rustc_type_ir::inherent::*; + + // Only consider auto impls of unsafe traits when there are + // no unsafe fields. + if self.tcx().trait_is_unsafe(def_id) && self_ty.has_unsafe_fields() { + return; + } + // Only consider auto impls if there are no manual impls for the root of `self_ty`. // // For example, we only consider auto candidates for `&i32: Auto` if no explicit impl diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index b746d6299ef..ae6d697794f 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -45,23 +45,8 @@ fn fn_sig_for_fn_abi<'tcx>( let ty = instance.ty(tcx, typing_env); match *ty.kind() { ty::FnDef(def_id, args) => { - // HACK(davidtwco,eddyb): This is a workaround for polymorphization considering - // parameters unused if they show up in the signature, but not in the `mir::Body` - // (i.e. due to being inside a projection that got normalized, see - // `tests/ui/polymorphization/normalized_sig_types.rs`), and codegen not keeping - // track of a polymorphization `ParamEnv` to allow normalizing later. - // - // We normalize the `fn_sig` again after instantiating at a later point. - let mut sig = tcx.instantiate_bound_regions_with_erased( - tcx.fn_sig(def_id) - .map_bound(|fn_sig| { - tcx.normalize_erasing_regions( - ty::TypingEnv::non_body_analysis(tcx, def_id), - fn_sig, - ) - }) - .instantiate(tcx, args), - ); + let mut sig = tcx + .instantiate_bound_regions_with_erased(tcx.fn_sig(def_id).instantiate(tcx, args)); if let ty::InstanceKind::VTableShim(..) = instance.def { let mut inputs_and_output = sig.inputs_and_output.to_vec(); @@ -473,20 +458,30 @@ fn fn_abi_sanity_check<'tcx>( // This really shouldn't happen even for sized aggregates, since // `immediate_llvm_type` will use `layout.fields` to turn this Rust type into an // LLVM type. This means all sorts of Rust type details leak into the ABI. - // However wasm sadly *does* currently use this mode so we have to allow it -- - // but we absolutely shouldn't let any more targets do that. - // (Also see <https://github.com/rust-lang/rust/issues/115666>.) + // However wasm sadly *does* currently use this mode for it's "C" ABI so we + // have to allow it -- but we absolutely shouldn't let any more targets do + // that. (Also see <https://github.com/rust-lang/rust/issues/115666>.) // // The unstable abi `PtxKernel` also uses Direct for now. // It needs to switch to something else before stabilization can happen. // (See issue: https://github.com/rust-lang/rust/issues/117271) - assert!( - matches!(&*tcx.sess.target.arch, "wasm32" | "wasm64") - || matches!(spec_abi, ExternAbi::PtxKernel | ExternAbi::Unadjusted), - "`PassMode::Direct` for aggregates only allowed for \"unadjusted\" and \"ptx-kernel\" functions and on wasm\n\ - Problematic type: {:#?}", - arg.layout, - ); + // + // And finally the unadjusted ABI is ill specified and uses Direct for all + // args, but unfortunately we need it for calling certain LLVM intrinsics. + + match spec_abi { + ExternAbi::Unadjusted => {} + ExternAbi::PtxKernel => {} + ExternAbi::C { unwind: _ } + if matches!(&*tcx.sess.target.arch, "wasm32" | "wasm64") => {} + _ => { + panic!( + "`PassMode::Direct` for aggregates only allowed for \"unadjusted\" and \"ptx-kernel\" functions and on wasm\n\ + Problematic type: {:#?}", + arg.layout, + ); + } + } } } } diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index a201f2b1c11..f45c94127bd 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -136,6 +136,9 @@ pub trait Ty<I: Interner<Ty = Self>>: matches!(self.kind(), ty::FnPtr(..)) } + /// Checks whether this type is an ADT that has unsafe fields. + fn has_unsafe_fields(self) -> bool; + fn fn_sig(self, interner: I) -> ty::Binder<I, ty::FnSig<I>> { match self.kind() { ty::FnPtr(sig_tys, hdr) => sig_tys.with(hdr), diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 0ae688848eb..025ec7ae896 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -270,6 +270,9 @@ pub trait Interner: fn trait_may_be_implemented_via_object(self, trait_def_id: Self::DefId) -> bool; + /// Returns `true` if this is an `unsafe trait`. + fn trait_is_unsafe(self, trait_def_id: Self::DefId) -> bool; + fn is_impl_trait_in_trait(self, def_id: Self::DefId) -> bool; fn delay_bug(self, msg: impl ToString) -> Self::ErrorGuaranteed; diff --git a/library/alloc/src/fmt.rs b/library/alloc/src/fmt.rs index 695dddb25ee..e40de13f3d4 100644 --- a/library/alloc/src/fmt.rs +++ b/library/alloc/src/fmt.rs @@ -596,6 +596,8 @@ pub use core::fmt::{Arguments, write}; pub use core::fmt::{Binary, Octal}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::fmt::{Debug, Display}; +#[unstable(feature = "formatting_options", issue = "118117")] +pub use core::fmt::{DebugAsHex, FormattingOptions, Sign}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::fmt::{DebugList, DebugMap, DebugSet, DebugStruct, DebugTuple}; #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 84f4202c02a..927c3aa23b9 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -117,6 +117,7 @@ #![feature(extend_one_unchecked)] #![feature(fmt_internals)] #![feature(fn_traits)] +#![feature(formatting_options)] #![feature(hasher_prefixfree_extras)] #![feature(inplace_iteration)] #![feature(iter_advance_by)] diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index e0576c25515..c5378d78d59 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -2682,7 +2682,8 @@ impl<T: fmt::Display + ?Sized> ToString for T { #[inline] default fn to_string(&self) -> String { let mut buf = String::new(); - let mut formatter = core::fmt::Formatter::new(&mut buf); + let mut formatter = + core::fmt::Formatter::new(&mut buf, core::fmt::FormattingOptions::new()); // Bypass format_args!() to avoid write_str with zero-length strs fmt::Display::fmt(self, &mut formatter) .expect("a Display implementation returned an error unexpectedly"); diff --git a/library/alloc/src/task.rs b/library/alloc/src/task.rs index 0f8e74300a4..b4116f4988b 100644 --- a/library/alloc/src/task.rs +++ b/library/alloc/src/task.rs @@ -199,7 +199,6 @@ fn raw_waker<W: Wake + Send + Sync + 'static>(waker: Arc<W>) -> RawWaker { /// /// ```rust /// #![feature(local_waker)] -/// #![feature(noop_waker)] /// use std::task::{LocalWake, ContextBuilder, LocalWaker, Waker}; /// use std::future::Future; /// use std::pin::Pin; diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 4b706086e07..457be3ae77f 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -3025,26 +3025,29 @@ impl<T: Clone, A: Allocator> Vec<T, A> { self.spec_extend(other.iter()) } - /// Copies elements from `src` range to the end of the vector. + /// Given a range `src`, clones a slice of elements in that range and appends it to the end. + /// + /// `src` must be a range that can form a valid subslice of the `Vec`. /// /// # Panics /// - /// Panics if the starting point is greater than the end point or if - /// the end point is greater than the length of the vector. + /// Panics if starting index is greater than the end index + /// or if the index is greater than the length of the vector. /// /// # Examples /// /// ``` - /// let mut vec = vec![0, 1, 2, 3, 4]; - /// - /// vec.extend_from_within(2..); - /// assert_eq!(vec, [0, 1, 2, 3, 4, 2, 3, 4]); + /// let mut characters = vec!['a', 'b', 'c', 'd', 'e']; + /// characters.extend_from_within(2..); + /// assert_eq!(characters, ['a', 'b', 'c', 'd', 'e', 'c', 'd', 'e']); /// - /// vec.extend_from_within(..2); - /// assert_eq!(vec, [0, 1, 2, 3, 4, 2, 3, 4, 0, 1]); + /// let mut numbers = vec![0, 1, 2, 3, 4]; + /// numbers.extend_from_within(..2); + /// assert_eq!(numbers, [0, 1, 2, 3, 4, 0, 1]); /// - /// vec.extend_from_within(4..8); - /// assert_eq!(vec, [0, 1, 2, 3, 4, 2, 3, 4, 0, 1, 4, 2, 3, 4]); + /// let mut strings = vec![String::from("hello"), String::from("world"), String::from("!")]; + /// strings.extend_from_within(1..=2); + /// assert_eq!(strings, ["hello", "world", "!", "world", "!"]); /// ``` #[cfg(not(no_global_oom_handling))] #[stable(feature = "vec_extend_from_within", since = "1.53.0")] diff --git a/library/core/src/fmt/float.rs b/library/core/src/fmt/float.rs index 04230b1610a..3f10158193d 100644 --- a/library/core/src/fmt/float.rs +++ b/library/core/src/fmt/float.rs @@ -86,7 +86,7 @@ where true => flt2dec::Sign::MinusPlus, }; - if let Some(precision) = fmt.precision { + if let Some(precision) = fmt.options.precision { float_to_decimal_common_exact(fmt, num, sign, precision) } else { let min_precision = 0; @@ -162,7 +162,7 @@ where true => flt2dec::Sign::MinusPlus, }; - if let Some(precision) = fmt.precision { + if let Some(precision) = fmt.options.precision { // 1 integral digit + `precision` fractional digits = `precision + 1` total digits float_to_exponential_common_exact(fmt, num, sign, precision + 1, upper) } else { @@ -180,7 +180,7 @@ where true => flt2dec::Sign::MinusPlus, }; - if let Some(precision) = fmt.precision { + if let Some(precision) = fmt.options.precision { // this behavior of {:.PREC?} predates exponential formatting for {:?} float_to_decimal_common_exact(fmt, num, sign, precision) } else { diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 7fc9dd21fdd..14c70065101 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -33,6 +33,19 @@ pub enum Alignment { Center, } +#[doc(hidden)] +#[unstable(feature = "fmt_internals", reason = "internal to standard library", issue = "none")] +impl From<rt::Alignment> for Option<Alignment> { + fn from(value: rt::Alignment) -> Self { + match value { + rt::Alignment::Left => Some(Alignment::Left), + rt::Alignment::Right => Some(Alignment::Right), + rt::Alignment::Center => Some(Alignment::Center), + rt::Alignment::Unknown => None, + } + } +} + #[stable(feature = "debug_builders", since = "1.2.0")] pub use self::builders::{DebugList, DebugMap, DebugSet, DebugStruct, DebugTuple}; #[unstable(feature = "debug_closure_helpers", issue = "117729")] @@ -247,6 +260,251 @@ impl<W: Write + ?Sized> Write for &mut W { } } +/// The signedness of a [`Formatter`] (or of a [`FormattingOptions`]). +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +#[unstable(feature = "formatting_options", issue = "118117")] +pub enum Sign { + /// Represents the `+` flag. + Plus, + /// Represents the `-` flag. + Minus, +} + +/// Specifies whether the [`Debug`] trait should use lower-/upper-case +/// hexadecimal or normal integers. +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +#[unstable(feature = "formatting_options", issue = "118117")] +pub enum DebugAsHex { + /// Use lower-case hexadecimal integers for the `Debug` trait (like [the `x?` type](../../std/fmt/index.html#formatting-traits)). + Lower, + /// Use upper-case hexadecimal integers for the `Debug` trait (like [the `X?` type](../../std/fmt/index.html#formatting-traits)). + Upper, +} + +/// Options for formatting. +/// +/// `FormattingOptions` is a [`Formatter`] without an attached [`Write`] trait. +/// It is mainly used to construct `Formatter` instances. +#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)] +#[unstable(feature = "formatting_options", issue = "118117")] +pub struct FormattingOptions { + flags: u32, + fill: char, + align: Option<Alignment>, + width: Option<usize>, + precision: Option<usize>, +} + +impl FormattingOptions { + /// Construct a new `FormatterBuilder` with the supplied `Write` trait + /// object for output that is equivalent to the `{}` formatting + /// specifier: + /// + /// - no flags, + /// - filled with spaces, + /// - no alignment, + /// - no width, + /// - no precision, and + /// - no [`DebugAsHex`] output mode. + #[unstable(feature = "formatting_options", issue = "118117")] + pub const fn new() -> Self { + Self { flags: 0, fill: ' ', align: None, width: None, precision: None } + } + + /// Sets or removes the sign (the `+` or the `-` flag). + /// + /// - `+`: This is intended for numeric types and indicates that the sign + /// should always be printed. By default only the negative sign of signed + /// values is printed, and the sign of positive or unsigned values is + /// omitted. This flag indicates that the correct sign (+ or -) should + /// always be printed. + /// - `-`: Currently not used + #[unstable(feature = "formatting_options", issue = "118117")] + pub fn sign(&mut self, sign: Option<Sign>) -> &mut Self { + self.flags = + self.flags & !(1 << rt::Flag::SignMinus as u32 | 1 << rt::Flag::SignPlus as u32); + match sign { + None => {} + Some(Sign::Plus) => self.flags |= 1 << rt::Flag::SignPlus as u32, + Some(Sign::Minus) => self.flags |= 1 << rt::Flag::SignMinus as u32, + } + self + } + /// Sets or unsets the `0` flag. + /// + /// This is used to indicate for integer formats that the padding to width should both be done with a 0 character as well as be sign-aware + #[unstable(feature = "formatting_options", issue = "118117")] + pub fn sign_aware_zero_pad(&mut self, sign_aware_zero_pad: bool) -> &mut Self { + if sign_aware_zero_pad { + self.flags |= 1 << rt::Flag::SignAwareZeroPad as u32 + } else { + self.flags &= !(1 << rt::Flag::SignAwareZeroPad as u32) + } + self + } + /// Sets or unsets the `#` flag. + /// + /// This flag indicates that the "alternate" form of printing should be + /// used. The alternate forms are: + /// - [`Debug`] : pretty-print the [`Debug`] formatting (adds linebreaks and indentation) + /// - [`LowerHex`] as well as [`UpperHex`] - precedes the argument with a `0x` + /// - [`Octal`] - precedes the argument with a `0b` + /// - [`Binary`] - precedes the argument with a `0o` + #[unstable(feature = "formatting_options", issue = "118117")] + pub fn alternate(&mut self, alternate: bool) -> &mut Self { + if alternate { + self.flags |= 1 << rt::Flag::Alternate as u32 + } else { + self.flags &= !(1 << rt::Flag::Alternate as u32) + } + self + } + /// Sets the fill character. + /// + /// The optional fill character and alignment is provided normally in + /// conjunction with the width parameter. This indicates that if the value + /// being formatted is smaller than width some extra characters will be + /// printed around it. + #[unstable(feature = "formatting_options", issue = "118117")] + pub fn fill(&mut self, fill: char) -> &mut Self { + self.fill = fill; + self + } + /// Sets or removes the alignment. + /// + /// The alignment specifies how the value being formatted should be + /// positioned if it is smaller than the width of the formatter. + #[unstable(feature = "formatting_options", issue = "118117")] + pub fn align(&mut self, align: Option<Alignment>) -> &mut Self { + self.align = align; + self + } + /// Sets or removes the width. + /// + /// This is a parameter for the “minimum width” that the format should take + /// up. If the value’s string does not fill up this many characters, then + /// the padding specified by [`FormattingOptions::fill`]/[`FormattingOptions::align`] + /// will be used to take up the required space. + #[unstable(feature = "formatting_options", issue = "118117")] + pub fn width(&mut self, width: Option<usize>) -> &mut Self { + self.width = width; + self + } + /// Sets or removes the precision. + /// + /// - For non-numeric types, this can be considered a “maximum width”. If + /// the resulting string is longer than this width, then it is truncated + /// down to this many characters and that truncated value is emitted with + /// proper fill, alignment and width if those parameters are set. + /// - For integral types, this is ignored. + /// - For floating-point types, this indicates how many digits after the + /// decimal point should be printed. + #[unstable(feature = "formatting_options", issue = "118117")] + pub fn precision(&mut self, precision: Option<usize>) -> &mut Self { + self.precision = precision; + self + } + /// Specifies whether the [`Debug`] trait should use lower-/upper-case + /// hexadecimal or normal integers + #[unstable(feature = "formatting_options", issue = "118117")] + pub fn debug_as_hex(&mut self, debug_as_hex: Option<DebugAsHex>) -> &mut Self { + self.flags = self.flags + & !(1 << rt::Flag::DebugUpperHex as u32 | 1 << rt::Flag::DebugLowerHex as u32); + match debug_as_hex { + None => {} + Some(DebugAsHex::Upper) => self.flags |= 1 << rt::Flag::DebugUpperHex as u32, + Some(DebugAsHex::Lower) => self.flags |= 1 << rt::Flag::DebugLowerHex as u32, + } + self + } + + /// Returns the current sign (the `+` or the `-` flag). + #[unstable(feature = "formatting_options", issue = "118117")] + pub const fn get_sign(&self) -> Option<Sign> { + const SIGN_PLUS_BITFIELD: u32 = 1 << rt::Flag::SignPlus as u32; + const SIGN_MINUS_BITFIELD: u32 = 1 << rt::Flag::SignMinus as u32; + match self.flags & ((1 << rt::Flag::SignPlus as u32) | (1 << rt::Flag::SignMinus as u32)) { + SIGN_PLUS_BITFIELD => Some(Sign::Plus), + SIGN_MINUS_BITFIELD => Some(Sign::Minus), + 0 => None, + _ => panic!("Invalid sign bits set in flags"), + } + } + /// Returns the current `0` flag. + #[unstable(feature = "formatting_options", issue = "118117")] + pub const fn get_sign_aware_zero_pad(&self) -> bool { + self.flags & (1 << rt::Flag::SignAwareZeroPad as u32) != 0 + } + /// Returns the current `#` flag. + #[unstable(feature = "formatting_options", issue = "118117")] + pub const fn get_alternate(&self) -> bool { + self.flags & (1 << rt::Flag::Alternate as u32) != 0 + } + /// Returns the current fill character. + #[unstable(feature = "formatting_options", issue = "118117")] + pub const fn get_fill(&self) -> char { + self.fill + } + /// Returns the current alignment. + #[unstable(feature = "formatting_options", issue = "118117")] + pub const fn get_align(&self) -> Option<Alignment> { + self.align + } + /// Returns the current width. + #[unstable(feature = "formatting_options", issue = "118117")] + pub const fn get_width(&self) -> Option<usize> { + self.width + } + /// Returns the current precision. + #[unstable(feature = "formatting_options", issue = "118117")] + pub const fn get_precision(&self) -> Option<usize> { + self.precision + } + /// Returns the current precision. + #[unstable(feature = "formatting_options", issue = "118117")] + pub const fn get_debug_as_hex(&self) -> Option<DebugAsHex> { + const DEBUG_UPPER_BITFIELD: u32 = 1 << rt::Flag::DebugUpperHex as u32; + const DEBUG_LOWER_BITFIELD: u32 = 1 << rt::Flag::DebugLowerHex as u32; + match self.flags + & ((1 << rt::Flag::DebugUpperHex as u32) | (1 << rt::Flag::DebugLowerHex as u32)) + { + DEBUG_UPPER_BITFIELD => Some(DebugAsHex::Upper), + DEBUG_LOWER_BITFIELD => Some(DebugAsHex::Lower), + 0 => None, + _ => panic!("Invalid hex debug bits set in flags"), + } + } + + /// Creates a [`Formatter`] that writes its output to the given [`Write`] trait. + /// + /// You may alternatively use [`Formatter::new()`]. + #[unstable(feature = "formatting_options", issue = "118117")] + pub fn create_formatter<'a>(self, write: &'a mut (dyn Write + 'a)) -> Formatter<'a> { + Formatter { options: self, buf: write } + } + + #[doc(hidden)] + #[unstable( + feature = "fmt_internals", + reason = "internal routines only exposed for testing", + issue = "none" + )] + /// Flags for formatting + pub fn flags(&mut self, flags: u32) { + self.flags = flags + } + #[doc(hidden)] + #[unstable( + feature = "fmt_internals", + reason = "internal routines only exposed for testing", + issue = "none" + )] + /// Flags for formatting + pub fn get_flags(&self) -> u32 { + self.flags + } +} + /// Configuration for formatting. /// /// A `Formatter` represents various options related to formatting. Users do not @@ -260,34 +518,28 @@ impl<W: Write + ?Sized> Write for &mut W { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "Formatter"] pub struct Formatter<'a> { - flags: u32, - fill: char, - align: rt::Alignment, - width: Option<usize>, - precision: Option<usize>, + options: FormattingOptions, buf: &'a mut (dyn Write + 'a), } impl<'a> Formatter<'a> { - /// Creates a new formatter with default settings. + /// Creates a new formatter with given [`FormattingOptions`]. /// - /// This can be used as a micro-optimization in cases where a full `Arguments` - /// structure (as created by `format_args!`) is not necessary; `Arguments` - /// is a little more expensive to use in simple formatting scenarios. + /// If `write` is a reference to a formatter, it is recommended to use + /// [`Formatter::with_options`] instead as this can borrow the underlying + /// `write`, thereby bypassing one layer of indirection. /// - /// Currently not intended for use outside of the standard library. - #[unstable(feature = "fmt_internals", reason = "internal to standard library", issue = "none")] - #[doc(hidden)] - pub fn new(buf: &'a mut (dyn Write + 'a)) -> Formatter<'a> { - Formatter { - flags: 0, - fill: ' ', - align: rt::Alignment::Unknown, - width: None, - precision: None, - buf, - } + /// You may alternatively use [`FormattingOptions::create_formatter()`]. + #[unstable(feature = "formatting_options", issue = "118117")] + pub fn new(write: &'a mut (dyn Write + 'a), options: FormattingOptions) -> Self { + Formatter { options, buf: write } + } + + /// Creates a new formatter based on this one with given [`FormattingOptions`]. + #[unstable(feature = "formatting_options", issue = "118117")] + pub fn with_options<'b>(&'b mut self, options: FormattingOptions) -> Formatter<'b> { + Formatter { options, buf: self.buf } } } @@ -1165,7 +1417,7 @@ pub trait UpperExp { /// [`write!`]: crate::write! #[stable(feature = "rust1", since = "1.0.0")] pub fn write(output: &mut dyn Write, args: Arguments<'_>) -> Result { - let mut formatter = Formatter::new(output); + let mut formatter = Formatter::new(output, FormattingOptions::new()); let mut idx = 0; match args.fmt { @@ -1214,14 +1466,14 @@ pub fn write(output: &mut dyn Write, args: Arguments<'_>) -> Result { } unsafe fn run(fmt: &mut Formatter<'_>, arg: &rt::Placeholder, args: &[rt::Argument<'_>]) -> Result { - fmt.fill = arg.fill; - fmt.align = arg.align; - fmt.flags = arg.flags; + fmt.options.fill = arg.fill; + fmt.options.align = arg.align.into(); + fmt.options.flags = arg.flags; // SAFETY: arg and args come from the same Arguments, // which guarantees the indexes are always within bounds. unsafe { - fmt.width = getcount(args, &arg.width); - fmt.precision = getcount(args, &arg.precision); + fmt.options.width = getcount(args, &arg.width); + fmt.options.precision = getcount(args, &arg.precision); } // Extract the correct argument @@ -1280,11 +1532,7 @@ impl<'a> Formatter<'a> { buf: wrap(self.buf), // And preserve these - flags: self.flags, - fill: self.fill, - align: self.align, - width: self.width, - precision: self.precision, + options: self.options, } } @@ -1365,7 +1613,7 @@ impl<'a> Formatter<'a> { } // The `width` field is more of a `min-width` parameter at this point. - match self.width { + match self.options.width { // If there's no minimum length requirements then we can just // write the bytes. None => { @@ -1381,14 +1629,15 @@ impl<'a> Formatter<'a> { // The sign and prefix goes before the padding if the fill character // is zero Some(min) if self.sign_aware_zero_pad() => { - let old_fill = crate::mem::replace(&mut self.fill, '0'); - let old_align = crate::mem::replace(&mut self.align, rt::Alignment::Right); + let old_fill = crate::mem::replace(&mut self.options.fill, '0'); + let old_align = + crate::mem::replace(&mut self.options.align, Some(Alignment::Right)); write_prefix(self, sign, prefix)?; let post_padding = self.padding(min - width, Alignment::Right)?; self.buf.write_str(buf)?; post_padding.write(self)?; - self.fill = old_fill; - self.align = old_align; + self.options.fill = old_fill; + self.options.align = old_align; Ok(()) } // Otherwise, the sign and prefix goes after the padding @@ -1433,12 +1682,12 @@ impl<'a> Formatter<'a> { #[stable(feature = "rust1", since = "1.0.0")] pub fn pad(&mut self, s: &str) -> Result { // Make sure there's a fast path up front - if self.width.is_none() && self.precision.is_none() { + if self.options.width.is_none() && self.options.precision.is_none() { return self.buf.write_str(s); } // The `precision` field can be interpreted as a `max-width` for the // string being formatted. - let s = if let Some(max) = self.precision { + let s = if let Some(max) = self.options.precision { // If our string is longer that the precision, then we must have // truncation. However other flags like `fill`, `width` and `align` // must act as always. @@ -1455,7 +1704,7 @@ impl<'a> Formatter<'a> { &s }; // The `width` field is more of a `min-width` parameter at this point. - match self.width { + match self.options.width { // If we're under the maximum length, and there's no minimum length // requirements, then we can just emit the string None => self.buf.write_str(s), @@ -1487,12 +1736,7 @@ impl<'a> Formatter<'a> { padding: usize, default: Alignment, ) -> result::Result<PostPadding, Error> { - let align = match self.align { - rt::Alignment::Unknown => default, - rt::Alignment::Left => Alignment::Left, - rt::Alignment::Right => Alignment::Right, - rt::Alignment::Center => Alignment::Center, - }; + let align = self.align().unwrap_or(default); let (pre_pad, post_pad) = match align { Alignment::Left => (0, padding), @@ -1501,10 +1745,10 @@ impl<'a> Formatter<'a> { }; for _ in 0..pre_pad { - self.buf.write_char(self.fill)?; + self.buf.write_char(self.options.fill)?; } - Ok(PostPadding::new(self.fill, post_pad)) + Ok(PostPadding::new(self.options.fill, post_pad)) } /// Takes the formatted parts and applies the padding. @@ -1516,12 +1760,12 @@ impl<'a> Formatter<'a> { /// /// Any `numfmt::Part::Copy` parts in `formatted` must contain valid UTF-8. unsafe fn pad_formatted_parts(&mut self, formatted: &numfmt::Formatted<'_>) -> Result { - if let Some(mut width) = self.width { + if let Some(mut width) = self.options.width { // for the sign-aware zero padding, we render the sign first and // behave as if we had no sign from the beginning. let mut formatted = formatted.clone(); - let old_fill = self.fill; - let old_align = self.align; + let old_fill = self.options.fill; + let old_align = self.options.align; if self.sign_aware_zero_pad() { // a sign always goes first let sign = formatted.sign; @@ -1530,8 +1774,8 @@ impl<'a> Formatter<'a> { // remove the sign from the formatted parts formatted.sign = ""; width = width.saturating_sub(sign.len()); - self.fill = '0'; - self.align = rt::Alignment::Right; + self.options.fill = '0'; + self.options.align = Some(Alignment::Right); } // remaining parts go through the ordinary padding process. @@ -1548,8 +1792,8 @@ impl<'a> Formatter<'a> { } post_padding.write(self) }; - self.fill = old_fill; - self.align = old_align; + self.options.fill = old_fill; + self.options.align = old_align; ret } else { // this is the common case and we take a shortcut @@ -1675,7 +1919,7 @@ impl<'a> Formatter<'a> { or `sign_aware_zero_pad` methods instead" )] pub fn flags(&self) -> u32 { - self.flags + self.options.flags } /// Returns the character used as 'fill' whenever there is alignment. @@ -1708,7 +1952,7 @@ impl<'a> Formatter<'a> { #[must_use] #[stable(feature = "fmt_flags", since = "1.5.0")] pub fn fill(&self) -> char { - self.fill + self.options.fill } /// Returns a flag indicating what form of alignment was requested. @@ -1743,12 +1987,7 @@ impl<'a> Formatter<'a> { #[must_use] #[stable(feature = "fmt_flags_align", since = "1.28.0")] pub fn align(&self) -> Option<Alignment> { - match self.align { - rt::Alignment::Left => Some(Alignment::Left), - rt::Alignment::Right => Some(Alignment::Right), - rt::Alignment::Center => Some(Alignment::Center), - rt::Alignment::Unknown => None, - } + self.options.align } /// Returns the optionally specified integer width that the output should be. @@ -1778,7 +2017,7 @@ impl<'a> Formatter<'a> { #[must_use] #[stable(feature = "fmt_flags", since = "1.5.0")] pub fn width(&self) -> Option<usize> { - self.width + self.options.width } /// Returns the optionally specified precision for numeric types. @@ -1809,7 +2048,7 @@ impl<'a> Formatter<'a> { #[must_use] #[stable(feature = "fmt_flags", since = "1.5.0")] pub fn precision(&self) -> Option<usize> { - self.precision + self.options.precision } /// Determines if the `+` flag was specified. @@ -1841,7 +2080,7 @@ impl<'a> Formatter<'a> { #[must_use] #[stable(feature = "fmt_flags", since = "1.5.0")] pub fn sign_plus(&self) -> bool { - self.flags & (1 << rt::Flag::SignPlus as u32) != 0 + self.options.flags & (1 << rt::Flag::SignPlus as u32) != 0 } /// Determines if the `-` flag was specified. @@ -1870,7 +2109,7 @@ impl<'a> Formatter<'a> { #[must_use] #[stable(feature = "fmt_flags", since = "1.5.0")] pub fn sign_minus(&self) -> bool { - self.flags & (1 << rt::Flag::SignMinus as u32) != 0 + self.options.flags & (1 << rt::Flag::SignMinus as u32) != 0 } /// Determines if the `#` flag was specified. @@ -1898,7 +2137,7 @@ impl<'a> Formatter<'a> { #[must_use] #[stable(feature = "fmt_flags", since = "1.5.0")] pub fn alternate(&self) -> bool { - self.flags & (1 << rt::Flag::Alternate as u32) != 0 + self.options.flags & (1 << rt::Flag::Alternate as u32) != 0 } /// Determines if the `0` flag was specified. @@ -1924,17 +2163,17 @@ impl<'a> Formatter<'a> { #[must_use] #[stable(feature = "fmt_flags", since = "1.5.0")] pub fn sign_aware_zero_pad(&self) -> bool { - self.flags & (1 << rt::Flag::SignAwareZeroPad as u32) != 0 + self.options.flags & (1 << rt::Flag::SignAwareZeroPad as u32) != 0 } // FIXME: Decide what public API we want for these two flags. // https://github.com/rust-lang/rust/issues/48584 fn debug_lower_hex(&self) -> bool { - self.flags & (1 << rt::Flag::DebugLowerHex as u32) != 0 + self.options.flags & (1 << rt::Flag::DebugLowerHex as u32) != 0 } fn debug_upper_hex(&self) -> bool { - self.flags & (1 << rt::Flag::DebugUpperHex as u32) != 0 + self.options.flags & (1 << rt::Flag::DebugUpperHex as u32) != 0 } /// Creates a [`DebugStruct`] builder designed to assist with creation of @@ -2350,6 +2589,18 @@ impl<'a> Formatter<'a> { pub fn debug_map<'b>(&'b mut self) -> DebugMap<'b, 'a> { builders::debug_map_new(self) } + + /// Returns the sign of this formatter (`+` or `-`). + #[unstable(feature = "formatting_options", issue = "118117")] + pub const fn sign(&self) -> Option<Sign> { + self.options.get_sign() + } + + /// Returns the formatting options this formatter corresponds to. + #[unstable(feature = "formatting_options", issue = "118117")] + pub const fn options(&self) -> FormattingOptions { + self.options + } } #[stable(since = "1.2.0", feature = "formatter_write")] @@ -2502,7 +2753,7 @@ impl Debug for char { #[stable(feature = "rust1", since = "1.0.0")] impl Display for char { fn fmt(&self, f: &mut Formatter<'_>) -> Result { - if f.width.is_none() && f.precision.is_none() { + if f.options.width.is_none() && f.options.precision.is_none() { f.write_char(*self) } else { f.pad(self.encode_utf8(&mut [0; 4])) @@ -2526,26 +2777,26 @@ impl<T: ?Sized> Pointer for *const T { /// /// [problematic]: https://github.com/rust-lang/rust/issues/95489 pub(crate) fn pointer_fmt_inner(ptr_addr: usize, f: &mut Formatter<'_>) -> Result { - let old_width = f.width; - let old_flags = f.flags; + let old_width = f.options.width; + let old_flags = f.options.flags; // The alternate flag is already treated by LowerHex as being special- // it denotes whether to prefix with 0x. We use it to work out whether // or not to zero extend, and then unconditionally set it to get the // prefix. if f.alternate() { - f.flags |= 1 << (rt::Flag::SignAwareZeroPad as u32); + f.options.flags |= 1 << (rt::Flag::SignAwareZeroPad as u32); - if f.width.is_none() { - f.width = Some((usize::BITS / 4) as usize + 2); + if f.options.width.is_none() { + f.options.width = Some((usize::BITS / 4) as usize + 2); } } - f.flags |= 1 << (rt::Flag::Alternate as u32); + f.options.flags |= 1 << (rt::Flag::Alternate as u32); let ret = LowerHex::fmt(&ptr_addr, f); - f.width = old_width; - f.flags = old_flags; + f.options.width = old_width; + f.options.flags = old_flags; ret } diff --git a/library/core/src/iter/traits/collect.rs b/library/core/src/iter/traits/collect.rs index 2cf2ea58fd4..c3c7288e389 100644 --- a/library/core/src/iter/traits/collect.rs +++ b/library/core/src/iter/traits/collect.rs @@ -492,131 +492,150 @@ impl Extend<()> for () { fn extend_one(&mut self, _item: ()) {} } -#[stable(feature = "extend_for_tuple", since = "1.56.0")] -impl<A, B, ExtendA, ExtendB> Extend<(A, B)> for (ExtendA, ExtendB) -where - ExtendA: Extend<A>, - ExtendB: Extend<B>, -{ - /// Allows to `extend` a tuple of collections that also implement `Extend`. - /// - /// See also: [`Iterator::unzip`] - /// - /// # Examples - /// ``` - /// let mut tuple = (vec![0], vec![1]); - /// tuple.extend([(2, 3), (4, 5), (6, 7)]); - /// assert_eq!(tuple.0, [0, 2, 4, 6]); - /// assert_eq!(tuple.1, [1, 3, 5, 7]); - /// - /// // also allows for arbitrarily nested tuples as elements - /// let mut nested_tuple = (vec![1], (vec![2], vec![3])); - /// nested_tuple.extend([(4, (5, 6)), (7, (8, 9))]); - /// - /// let (a, (b, c)) = nested_tuple; - /// assert_eq!(a, [1, 4, 7]); - /// assert_eq!(b, [2, 5, 8]); - /// assert_eq!(c, [3, 6, 9]); - /// ``` - fn extend<T: IntoIterator<Item = (A, B)>>(&mut self, into_iter: T) { - let (a, b) = self; - let iter = into_iter.into_iter(); - SpecTupleExtend::extend(iter, a, b); - } +macro_rules! spec_tuple_impl { + ( ($ty_name:ident, $var_name:ident, $extend_ty_name: ident, $trait_name:ident, $default_fn_name:ident, $cnt:tt), ) => { + spec_tuple_impl!($trait_name, $default_fn_name, #[doc(fake_variadic)] #[doc = "This trait is implemented for tuples up to twelve items long. The `impl`s for 1- and 3- through 12-ary tuples were stabilized after 2-tuples, in RUSTC_CURRENT_VERSION."] => ($ty_name, $var_name, $extend_ty_name, $cnt),); + }; + ( ($ty_name:ident, $var_name:ident, $extend_ty_name: ident, $trait_name:ident, $default_fn_name:ident, $cnt:tt), $(($ty_names:ident, $var_names:ident, $extend_ty_names:ident, $trait_names:ident, $default_fn_names:ident, $cnts:tt),)*) => { - fn extend_one(&mut self, item: (A, B)) { - self.0.extend_one(item.0); - self.1.extend_one(item.1); - } + spec_tuple_impl!($(($ty_names, $var_names, $extend_ty_names, $trait_names, $default_fn_names, $cnts),)*); + spec_tuple_impl!($trait_name, $default_fn_name, #[doc(hidden)] => ($ty_name, $var_name, $extend_ty_name, $cnt), $(($ty_names, $var_names, $extend_ty_names, $cnts),)*); + }; + ($trait_name:ident, $default_fn_name:ident, #[$meta:meta] $(#[$doctext:meta])? => $(($ty_names:ident, $var_names:ident, $extend_ty_names:ident, $cnts:tt),)*) => { + #[$meta] + $(#[$doctext])? + #[stable(feature = "extend_for_tuple", since = "1.56.0")] + impl<$($ty_names,)* $($extend_ty_names,)*> Extend<($($ty_names,)*)> for ($($extend_ty_names,)*) + where + $($extend_ty_names: Extend<$ty_names>,)* + { + /// Allows to `extend` a tuple of collections that also implement `Extend`. + /// + /// See also: [`Iterator::unzip`] + /// + /// # Examples + /// ``` + /// // Example given for a 2-tuple, but 1- through 12-tuples are supported + /// let mut tuple = (vec![0], vec![1]); + /// tuple.extend([(2, 3), (4, 5), (6, 7)]); + /// assert_eq!(tuple.0, [0, 2, 4, 6]); + /// assert_eq!(tuple.1, [1, 3, 5, 7]); + /// + /// // also allows for arbitrarily nested tuples as elements + /// let mut nested_tuple = (vec![1], (vec![2], vec![3])); + /// nested_tuple.extend([(4, (5, 6)), (7, (8, 9))]); + /// + /// let (a, (b, c)) = nested_tuple; + /// assert_eq!(a, [1, 4, 7]); + /// assert_eq!(b, [2, 5, 8]); + /// assert_eq!(c, [3, 6, 9]); + /// ``` + fn extend<T: IntoIterator<Item = ($($ty_names,)*)>>(&mut self, into_iter: T) { + let ($($var_names,)*) = self; + let iter = into_iter.into_iter(); + $trait_name::extend(iter, $($var_names,)*); + } - fn extend_reserve(&mut self, additional: usize) { - self.0.extend_reserve(additional); - self.1.extend_reserve(additional); - } + fn extend_one(&mut self, item: ($($ty_names,)*)) { + $(self.$cnts.extend_one(item.$cnts);)* + } - unsafe fn extend_one_unchecked(&mut self, item: (A, B)) { - // SAFETY: Those are our safety preconditions, and we correctly forward `extend_reserve`. - unsafe { - self.0.extend_one_unchecked(item.0); - self.1.extend_one_unchecked(item.1); - } - } -} + fn extend_reserve(&mut self, additional: usize) { + $(self.$cnts.extend_reserve(additional);)* + } -fn default_extend_tuple<A, B, ExtendA, ExtendB>( - iter: impl Iterator<Item = (A, B)>, - a: &mut ExtendA, - b: &mut ExtendB, -) where - ExtendA: Extend<A>, - ExtendB: Extend<B>, -{ - fn extend<'a, A, B>( - a: &'a mut impl Extend<A>, - b: &'a mut impl Extend<B>, - ) -> impl FnMut((), (A, B)) + 'a { - move |(), (t, u)| { - a.extend_one(t); - b.extend_one(u); + unsafe fn extend_one_unchecked(&mut self, item: ($($ty_names,)*)) { + // SAFETY: Those are our safety preconditions, and we correctly forward `extend_reserve`. + unsafe { + $(self.$cnts.extend_one_unchecked(item.$cnts);)* + } + } } - } - let (lower_bound, _) = iter.size_hint(); - if lower_bound > 0 { - a.extend_reserve(lower_bound); - b.extend_reserve(lower_bound); - } + trait $trait_name<$($ty_names),*> { + fn extend(self, $($var_names: &mut $ty_names,)*); + } - iter.fold((), extend(a, b)); -} + fn $default_fn_name<$($ty_names,)* $($extend_ty_names,)*>( + iter: impl Iterator<Item = ($($ty_names,)*)>, + $($var_names: &mut $extend_ty_names,)* + ) where + $($extend_ty_names: Extend<$ty_names>,)* + { + fn extend<'a, $($ty_names,)*>( + $($var_names: &'a mut impl Extend<$ty_names>,)* + ) -> impl FnMut((), ($($ty_names,)*)) + 'a { + #[allow(non_snake_case)] + move |(), ($($extend_ty_names,)*)| { + $($var_names.extend_one($extend_ty_names);)* + } + } -trait SpecTupleExtend<A, B> { - fn extend(self, a: &mut A, b: &mut B); -} + let (lower_bound, _) = iter.size_hint(); + if lower_bound > 0 { + $($var_names.extend_reserve(lower_bound);)* + } -impl<A, B, ExtendA, ExtendB, Iter> SpecTupleExtend<ExtendA, ExtendB> for Iter -where - ExtendA: Extend<A>, - ExtendB: Extend<B>, - Iter: Iterator<Item = (A, B)>, -{ - default fn extend(self, a: &mut ExtendA, b: &mut ExtendB) { - default_extend_tuple(self, a, b); - } -} + iter.fold((), extend($($var_names,)*)); + } -impl<A, B, ExtendA, ExtendB, Iter> SpecTupleExtend<ExtendA, ExtendB> for Iter -where - ExtendA: Extend<A>, - ExtendB: Extend<B>, - Iter: TrustedLen<Item = (A, B)>, -{ - fn extend(self, a: &mut ExtendA, b: &mut ExtendB) { - fn extend<'a, A, B>( - a: &'a mut impl Extend<A>, - b: &'a mut impl Extend<B>, - ) -> impl FnMut((), (A, B)) + 'a { - // SAFETY: We reserve enough space for the `size_hint`, and the iterator is `TrustedLen` - // so its `size_hint` is exact. - move |(), (t, u)| unsafe { - a.extend_one_unchecked(t); - b.extend_one_unchecked(u); + impl<$($ty_names,)* $($extend_ty_names,)* Iter> $trait_name<$($extend_ty_names),*> for Iter + where + $($extend_ty_names: Extend<$ty_names>,)* + Iter: Iterator<Item = ($($ty_names,)*)>, + { + default fn extend(self, $($var_names: &mut $extend_ty_names),*) { + $default_fn_name(self, $($var_names),*); } } - let (lower_bound, upper_bound) = self.size_hint(); + impl<$($ty_names,)* $($extend_ty_names,)* Iter> $trait_name<$($extend_ty_names),*> for Iter + where + $($extend_ty_names: Extend<$ty_names>,)* + Iter: TrustedLen<Item = ($($ty_names,)*)>, + { + fn extend(self, $($var_names: &mut $extend_ty_names,)*) { + fn extend<'a, $($ty_names,)*>( + $($var_names: &'a mut impl Extend<$ty_names>,)* + ) -> impl FnMut((), ($($ty_names,)*)) + 'a { + #[allow(non_snake_case)] + // SAFETY: We reserve enough space for the `size_hint`, and the iterator is `TrustedLen` + // so its `size_hint` is exact. + move |(), ($($extend_ty_names,)*)| unsafe { + $($var_names.extend_one_unchecked($extend_ty_names);)* + } + } - if upper_bound.is_none() { - // We cannot reserve more than `usize::MAX` items, and this is likely to go out of memory anyway. - default_extend_tuple(self, a, b); - return; - } + let (lower_bound, upper_bound) = self.size_hint(); - if lower_bound > 0 { - a.extend_reserve(lower_bound); - b.extend_reserve(lower_bound); - } + if upper_bound.is_none() { + // We cannot reserve more than `usize::MAX` items, and this is likely to go out of memory anyway. + $default_fn_name(self, $($var_names,)*); + return; + } - self.fold((), extend(a, b)); + if lower_bound > 0 { + $($var_names.extend_reserve(lower_bound);)* + } + + self.fold((), extend($($var_names,)*)); + } } + + }; } + +spec_tuple_impl!( + (L, l, EL, TraitL, default_extend_tuple_l, 11), + (K, k, EK, TraitK, default_extend_tuple_k, 10), + (J, j, EJ, TraitJ, default_extend_tuple_j, 9), + (I, i, EI, TraitI, default_extend_tuple_i, 8), + (H, h, EH, TraitH, default_extend_tuple_h, 7), + (G, g, EG, TraitG, default_extend_tuple_g, 6), + (F, f, EF, TraitF, default_extend_tuple_f, 5), + (E, e, EE, TraitE, default_extend_tuple_e, 4), + (D, d, ED, TraitD, default_extend_tuple_d, 3), + (C, c, EC, TraitC, default_extend_tuple_c, 2), + (B, b, EB, TraitB, default_extend_tuple_b, 1), + (A, a, EA, TraitA, default_extend_tuple_a, 0), +); diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index 41e9c593ebd..6762ed54e5c 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -60,7 +60,8 @@ impl RawWaker { RawWaker { data, vtable } } - #[unstable(feature = "noop_waker", issue = "98286")] + #[stable(feature = "noop_waker", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "noop_waker", since = "CURRENT_RUSTC_VERSION")] const NOOP: RawWaker = { const VTABLE: RawWakerVTable = RawWakerVTable::new( // Cloning just returns a new no-op raw waker @@ -283,7 +284,6 @@ impl fmt::Debug for Context<'_> { /// # Examples /// ``` /// #![feature(local_waker)] -/// #![feature(noop_waker)] /// use std::task::{ContextBuilder, LocalWaker, Waker, Poll}; /// use std::future::Future; /// @@ -555,8 +555,6 @@ impl Waker { /// # Examples /// /// ``` - /// #![feature(noop_waker)] - /// /// use std::future::Future; /// use std::task; /// @@ -567,7 +565,8 @@ impl Waker { /// ``` #[inline] #[must_use] - #[unstable(feature = "noop_waker", issue = "98286")] + #[stable(feature = "noop_waker", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "noop_waker", since = "CURRENT_RUSTC_VERSION")] pub const fn noop() -> &'static Waker { const WAKER: &Waker = &Waker { waker: RawWaker::NOOP }; WAKER @@ -850,8 +849,6 @@ impl LocalWaker { /// /// ``` /// #![feature(local_waker)] - /// #![feature(noop_waker)] - /// /// use std::future::Future; /// use std::task::{ContextBuilder, LocalWaker, Waker, Poll}; /// @@ -864,7 +861,7 @@ impl LocalWaker { /// ``` #[inline] #[must_use] - #[unstable(feature = "noop_waker", issue = "98286")] + #[unstable(feature = "local_waker", issue = "118959")] pub const fn noop() -> &'static LocalWaker { const WAKER: &LocalWaker = &LocalWaker { waker: RawWaker::NOOP }; WAKER diff --git a/library/core/src/unicode/printable.py b/library/core/src/unicode/printable.py index 4d39ace066c..260fa9f9e6a 100755 --- a/library/core/src/unicode/printable.py +++ b/library/core/src/unicode/printable.py @@ -9,7 +9,8 @@ import csv import os import subprocess -NUM_CODEPOINTS=0x110000 +NUM_CODEPOINTS = 0x110000 + def to_ranges(iter): current = None @@ -23,11 +24,15 @@ def to_ranges(iter): if current is not None: yield tuple(current) + def get_escaped(codepoints): for c in codepoints: - if (c.class_ or "Cn") in "Cc Cf Cs Co Cn Zl Zp Zs".split() and c.value != ord(' '): + if (c.class_ or "Cn") in "Cc Cf Cs Co Cn Zl Zp Zs".split() and c.value != ord( + " " + ): yield c.value + def get_file(f): try: return open(os.path.basename(f)) @@ -35,7 +40,9 @@ def get_file(f): subprocess.run(["curl", "-O", f], check=True) return open(os.path.basename(f)) -Codepoint = namedtuple('Codepoint', 'value class_') + +Codepoint = namedtuple("Codepoint", "value class_") + def get_codepoints(f): r = csv.reader(f, delimiter=";") @@ -66,13 +73,14 @@ def get_codepoints(f): for c in range(prev_codepoint + 1, NUM_CODEPOINTS): yield Codepoint(c, None) + def compress_singletons(singletons): - uppers = [] # (upper, # items in lowers) + uppers = [] # (upper, # items in lowers) lowers = [] for i in singletons: upper = i >> 8 - lower = i & 0xff + lower = i & 0xFF if len(uppers) == 0 or uppers[-1][0] != upper: uppers.append((upper, 1)) else: @@ -82,10 +90,11 @@ def compress_singletons(singletons): return uppers, lowers + def compress_normal(normal): # lengths 0x00..0x7f are encoded as 00, 01, ..., 7e, 7f # lengths 0x80..0x7fff are encoded as 80 80, 80 81, ..., ff fe, ff ff - compressed = [] # [truelen, (truelenaux), falselen, (falselenaux)] + compressed = [] # [truelen, (truelenaux), falselen, (falselenaux)] prev_start = 0 for start, count in normal: @@ -95,21 +104,22 @@ def compress_normal(normal): assert truelen < 0x8000 and falselen < 0x8000 entry = [] - if truelen > 0x7f: + if truelen > 0x7F: entry.append(0x80 | (truelen >> 8)) - entry.append(truelen & 0xff) + entry.append(truelen & 0xFF) else: - entry.append(truelen & 0x7f) - if falselen > 0x7f: + entry.append(truelen & 0x7F) + if falselen > 0x7F: entry.append(0x80 | (falselen >> 8)) - entry.append(falselen & 0xff) + entry.append(falselen & 0xFF) else: - entry.append(falselen & 0x7f) + entry.append(falselen & 0x7F) compressed.append(entry) return compressed + def print_singletons(uppers, lowers, uppersname, lowersname): print("#[rustfmt::skip]") print("const {}: &[(u8, u8)] = &[".format(uppersname)) @@ -119,9 +129,12 @@ def print_singletons(uppers, lowers, uppersname, lowersname): print("#[rustfmt::skip]") print("const {}: &[u8] = &[".format(lowersname)) for i in range(0, len(lowers), 8): - print(" {}".format(" ".join("{:#04x},".format(x) for x in lowers[i:i+8]))) + print( + " {}".format(" ".join("{:#04x},".format(x) for x in lowers[i : i + 8])) + ) print("];") + def print_normal(normal, normalname): print("#[rustfmt::skip]") print("const {}: &[u8] = &[".format(normalname)) @@ -129,12 +142,13 @@ def print_normal(normal, normalname): print(" {}".format(" ".join("{:#04x},".format(i) for i in v))) print("];") + def main(): file = get_file("https://www.unicode.org/Public/UNIDATA/UnicodeData.txt") codepoints = get_codepoints(file) - CUTOFF=0x10000 + CUTOFF = 0x10000 singletons0 = [] singletons1 = [] normal0 = [] @@ -234,10 +248,11 @@ pub(crate) fn is_printable(x: char) -> bool { }\ """) print() - print_singletons(singletons0u, singletons0l, 'SINGLETONS0U', 'SINGLETONS0L') - print_singletons(singletons1u, singletons1l, 'SINGLETONS1U', 'SINGLETONS1L') - print_normal(normal0, 'NORMAL0') - print_normal(normal1, 'NORMAL1') + print_singletons(singletons0u, singletons0l, "SINGLETONS0U", "SINGLETONS0L") + print_singletons(singletons1u, singletons1l, "SINGLETONS1U", "SINGLETONS1L") + print_normal(normal0, "NORMAL0") + print_normal(normal1, "NORMAL1") + -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/library/core/tests/fmt/mod.rs b/library/core/tests/fmt/mod.rs index f7512abae38..2c93a9bc80d 100644 --- a/library/core/tests/fmt/mod.rs +++ b/library/core/tests/fmt/mod.rs @@ -50,3 +50,27 @@ fn test_maybe_uninit_short() { let x = core::mem::MaybeUninit::new(0u32); assert_eq!(format!("{x:?}"), "MaybeUninit<u32>"); } + +#[test] +fn formatting_options_flags() { + use core::fmt::*; + for sign in [None, Some(Sign::Plus), Some(Sign::Minus)] { + for alternate in [true, false] { + for sign_aware_zero_pad in [true, false] { + for debug_as_hex in [None, Some(DebugAsHex::Lower), Some(DebugAsHex::Upper)] { + let mut formatting_options = FormattingOptions::new(); + formatting_options + .sign(sign) + .sign_aware_zero_pad(sign_aware_zero_pad) + .alternate(alternate) + .debug_as_hex(debug_as_hex); + + assert_eq!(formatting_options.get_sign(), sign); + assert_eq!(formatting_options.get_alternate(), alternate); + assert_eq!(formatting_options.get_sign_aware_zero_pad(), sign_aware_zero_pad); + assert_eq!(formatting_options.get_debug_as_hex(), debug_as_hex); + } + } + } + } +} diff --git a/library/core/tests/iter/traits/iterator.rs b/library/core/tests/iter/traits/iterator.rs index 93ef9c0812b..76f1e3319d4 100644 --- a/library/core/tests/iter/traits/iterator.rs +++ b/library/core/tests/iter/traits/iterator.rs @@ -617,6 +617,19 @@ fn test_next_chunk() { assert_eq!(it.next_chunk::<0>().unwrap(), []); } +#[test] +fn test_collect_into_tuples() { + let a = vec![(1, 2, 3), (4, 5, 6), (7, 8, 9)]; + let b = vec![1, 4, 7]; + let c = vec![2, 5, 8]; + let d = vec![3, 6, 9]; + let mut e = (Vec::new(), Vec::new(), Vec::new()); + a.iter().cloned().collect_into(&mut e); + assert!(e.0 == b); + assert!(e.1 == c); + assert!(e.2 == d); +} + // just tests by whether or not this compiles fn _empty_impl_all_auto_traits<T>() { use std::panic::{RefUnwindSafe, UnwindSafe}; diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index e0b1c21e1ec..a4a794691fe 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -31,6 +31,7 @@ #![feature(float_minimum_maximum)] #![feature(flt2dec)] #![feature(fmt_internals)] +#![feature(formatting_options)] #![feature(freeze)] #![feature(future_join)] #![feature(generic_assert_internals)] @@ -61,7 +62,6 @@ #![feature(maybe_uninit_write_slice)] #![feature(min_specialization)] #![feature(never_type)] -#![feature(noop_waker)] #![feature(num_midpoint_signed)] #![feature(numfmt)] #![feature(pattern)] diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs index 03f38e220a5..476c403c21f 100644 --- a/library/std/src/io/error.rs +++ b/library/std/src/io/error.rs @@ -338,9 +338,9 @@ pub enum ErrorKind { /// example, on Unix, a named pipe opened with `File::open`. #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] NotSeekable, - /// Filesystem quota was exceeded. - #[unstable(feature = "io_error_more", issue = "86442")] - FilesystemQuotaExceeded, + /// Filesystem quota or some other kind of quota was exceeded. + #[stable(feature = "io_error_quota_exceeded", since = "CURRENT_RUSTC_VERSION")] + QuotaExceeded, /// File larger than allowed or supported. /// /// This might arise from a hard limit of the underlying filesystem or file access API, or from @@ -364,7 +364,7 @@ pub enum ErrorKind { #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] Deadlock, /// Cross-device or cross-filesystem (hard) link or rename. - #[unstable(feature = "io_error_more", issue = "86442")] + #[stable(feature = "io_error_crosses_devices", since = "CURRENT_RUSTC_VERSION")] CrossesDevices, /// Too many (hard) links to the same filesystem object. /// @@ -446,8 +446,8 @@ pub enum ErrorKind { impl ErrorKind { pub(crate) fn as_str(&self) -> &'static str { use ErrorKind::*; - // tidy-alphabetical-start match *self { + // tidy-alphabetical-start AddrInUse => "address in use", AddrNotAvailable => "address not available", AlreadyExists => "entity already exists", @@ -460,12 +460,11 @@ impl ErrorKind { Deadlock => "deadlock", DirectoryNotEmpty => "directory not empty", ExecutableFileBusy => "executable file busy", - FileTooLarge => "file too large", FilesystemLoop => "filesystem loop or indirection limit (e.g. symlink loop)", - FilesystemQuotaExceeded => "filesystem quota exceeded", + FileTooLarge => "file too large", HostUnreachable => "host unreachable", - Interrupted => "operation interrupted", InProgress => "in progress", + Interrupted => "operation interrupted", InvalidData => "invalid data", InvalidFilename => "invalid filename", InvalidInput => "invalid input parameter", @@ -479,6 +478,7 @@ impl ErrorKind { Other => "other error", OutOfMemory => "out of memory", PermissionDenied => "permission denied", + QuotaExceeded => "quota exceeded", ReadOnlyFilesystem => "read-only filesystem or storage medium", ResourceBusy => "resource busy", StaleNetworkFileHandle => "stale network file handle", @@ -490,8 +490,8 @@ impl ErrorKind { Unsupported => "unsupported", WouldBlock => "operation would block", WriteZero => "write zero", + // tidy-alphabetical-end } - // tidy-alphabetical-end } } diff --git a/library/std/src/io/error/repr_bitpacked.rs b/library/std/src/io/error/repr_bitpacked.rs index a839a2fbac1..f958a938646 100644 --- a/library/std/src/io/error/repr_bitpacked.rs +++ b/library/std/src/io/error/repr_bitpacked.rs @@ -335,7 +335,7 @@ fn kind_from_prim(ek: u32) -> Option<ErrorKind> { WriteZero, StorageFull, NotSeekable, - FilesystemQuotaExceeded, + QuotaExceeded, FileTooLarge, ResourceBusy, ExecutableFileBusy, diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 6be27b283b2..49a03220039 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -292,6 +292,7 @@ #![feature(dropck_eyepatch)] #![feature(f128)] #![feature(f16)] +#![feature(formatting_options)] #![feature(if_let_guard)] #![feature(intra_doc_pointers)] #![feature(lang_items)] diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index 97f800dddaa..dca5ccca0c4 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -623,7 +623,7 @@ pub fn begin_panic_handler(info: &core::panic::PanicInfo<'_>) -> ! { // Lazily, the first time this gets called, run the actual string formatting. self.string.get_or_insert_with(|| { let mut s = String::new(); - let mut fmt = fmt::Formatter::new(&mut s); + let mut fmt = fmt::Formatter::new(&mut s, fmt::FormattingOptions::new()); let _err = fmt::Display::fmt(&inner, &mut fmt); s }) diff --git a/library/std/src/sys/pal/teeos/mod.rs b/library/std/src/sys/pal/teeos/mod.rs index 2bf2e2ceb31..a9900f55b19 100644 --- a/library/std/src/sys/pal/teeos/mod.rs +++ b/library/std/src/sys/pal/teeos/mod.rs @@ -71,7 +71,7 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind { libc::ECONNREFUSED => ConnectionRefused, libc::ECONNRESET => ConnectionReset, libc::EDEADLK => Deadlock, - libc::EDQUOT => FilesystemQuotaExceeded, + libc::EDQUOT => QuotaExceeded, libc::EEXIST => AlreadyExists, libc::EFBIG => FileTooLarge, libc::EHOSTUNREACH => HostUnreachable, diff --git a/library/std/src/sys/pal/unix/mod.rs b/library/std/src/sys/pal/unix/mod.rs index 8eaa50d7f81..3cc1cae8d00 100644 --- a/library/std/src/sys/pal/unix/mod.rs +++ b/library/std/src/sys/pal/unix/mod.rs @@ -254,7 +254,7 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind { libc::ECONNREFUSED => ConnectionRefused, libc::ECONNRESET => ConnectionReset, libc::EDEADLK => Deadlock, - libc::EDQUOT => FilesystemQuotaExceeded, + libc::EDQUOT => QuotaExceeded, libc::EEXIST => AlreadyExists, libc::EFBIG => FileTooLarge, libc::EHOSTUNREACH => HostUnreachable, diff --git a/library/std/src/sys/pal/windows/mod.rs b/library/std/src/sys/pal/windows/mod.rs index d66ff15e10b..88e6def7a75 100644 --- a/library/std/src/sys/pal/windows/mod.rs +++ b/library/std/src/sys/pal/windows/mod.rs @@ -113,7 +113,7 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind { c::ERROR_WRITE_PROTECT => return ReadOnlyFilesystem, c::ERROR_DISK_FULL | c::ERROR_HANDLE_DISK_FULL => return StorageFull, c::ERROR_SEEK_ON_DEVICE => return NotSeekable, - c::ERROR_DISK_QUOTA_EXCEEDED => return FilesystemQuotaExceeded, + c::ERROR_DISK_QUOTA_EXCEEDED => return QuotaExceeded, c::ERROR_FILE_TOO_LARGE => return FileTooLarge, c::ERROR_BUSY => return ResourceBusy, c::ERROR_POSSIBLE_DEADLOCK => return Deadlock, @@ -138,7 +138,7 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind { c::WSAEHOSTUNREACH => HostUnreachable, c::WSAENETDOWN => NetworkDown, c::WSAENETUNREACH => NetworkUnreachable, - c::WSAEDQUOT => FilesystemQuotaExceeded, + c::WSAEDQUOT => QuotaExceeded, _ => Uncategorized, } diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 9ef9ccec193..89415afbe3b 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -19,14 +19,17 @@ try: except ImportError: lzma = None + def platform_is_win32(): - return sys.platform == 'win32' + return sys.platform == "win32" + if platform_is_win32(): EXE_SUFFIX = ".exe" else: EXE_SUFFIX = "" + def get_cpus(): if hasattr(os, "sched_getaffinity"): return len(os.sched_getaffinity(0)) @@ -51,11 +54,14 @@ def get(base, url, path, checksums, verbose=False): try: if url not in checksums: - raise RuntimeError(("src/stage0 doesn't contain a checksum for {}. " - "Pre-built artifacts might not be available for this " - "target at this time, see https://doc.rust-lang.org/nightly" - "/rustc/platform-support.html for more information.") - .format(url)) + raise RuntimeError( + ( + "src/stage0 doesn't contain a checksum for {}. " + "Pre-built artifacts might not be available for this " + "target at this time, see https://doc.rust-lang.org/nightly" + "/rustc/platform-support.html for more information." + ).format(url) + ) sha256 = checksums[url] if os.path.exists(path): if verify(path, sha256, False): @@ -64,8 +70,11 @@ def get(base, url, path, checksums, verbose=False): return else: if verbose: - eprint("ignoring already-download file", - path, "due to failed verification") + eprint( + "ignoring already-download file", + path, + "due to failed verification", + ) os.unlink(path) download(temp_path, "{}/{}".format(base, url), True, verbose) if not verify(temp_path, sha256, verbose): @@ -79,12 +88,14 @@ def get(base, url, path, checksums, verbose=False): eprint("removing", temp_path) os.unlink(temp_path) + def curl_version(): m = re.match(bytes("^curl ([0-9]+)\\.([0-9]+)", "utf8"), require(["curl", "-V"])) if m is None: return (0, 0) return (int(m[1]), int(m[2])) + def download(path, url, probably_big, verbose): for _ in range(4): try: @@ -114,32 +125,53 @@ def _download(path, url, probably_big, verbose, exception): require(["curl", "--version"], exception=platform_is_win32()) extra_flags = [] if curl_version() > (7, 70): - extra_flags = [ "--retry-all-errors" ] + extra_flags = ["--retry-all-errors"] # options should be kept in sync with # src/bootstrap/src/core/download.rs # for consistency. # they are also more compreprensivly explained in that file. - run(["curl", option] + extra_flags + [ - # Follow redirect. - "--location", - # timeout if speed is < 10 bytes/sec for > 30 seconds - "--speed-time", "30", "--speed-limit", "10", - # timeout if cannot connect within 30 seconds - "--connect-timeout", "30", - "--output", path, - "--continue-at", "-", - "--retry", "3", "--show-error", "--remote-time", "--fail", url], + run( + ["curl", option] + + extra_flags + + [ + # Follow redirect. + "--location", + # timeout if speed is < 10 bytes/sec for > 30 seconds + "--speed-time", + "30", + "--speed-limit", + "10", + # timeout if cannot connect within 30 seconds + "--connect-timeout", + "30", + "--output", + path, + "--continue-at", + "-", + "--retry", + "3", + "--show-error", + "--remote-time", + "--fail", + url, + ], verbose=verbose, - exception=True, # Will raise RuntimeError on failure + exception=True, # Will raise RuntimeError on failure ) except (subprocess.CalledProcessError, OSError, RuntimeError): # see http://serverfault.com/questions/301128/how-to-download + script = "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12;" if platform_is_win32(): - run_powershell([ - "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12;", - "(New-Object System.Net.WebClient).DownloadFile('{}', '{}')".format(url, path)], + run_powershell( + [ + script, + "(New-Object System.Net.WebClient).DownloadFile('{}', '{}')".format( + url, path + ), + ], verbose=verbose, - exception=exception) + exception=exception, + ) # Check if the RuntimeError raised by run(curl) should be silenced elif verbose or exception: raise @@ -153,9 +185,11 @@ def verify(path, expected, verbose): found = hashlib.sha256(source.read()).hexdigest() verified = found == expected if not verified: - eprint("invalid checksum:\n" - " found: {}\n" - " expected: {}".format(found, expected)) + eprint( + "invalid checksum:\n" " found: {}\n" " expected: {}".format( + found, expected + ) + ) return verified @@ -170,7 +204,7 @@ def unpack(tarball, tarball_suffix, dst, verbose=False, match=None): name = member.replace(fname + "/", "", 1) if match is not None and not name.startswith(match): continue - name = name[len(match) + 1:] + name = name[len(match) + 1 :] dst_path = os.path.join(dst, name) if verbose: @@ -186,18 +220,18 @@ def unpack(tarball, tarball_suffix, dst, verbose=False, match=None): def run(args, verbose=False, exception=False, is_bootstrap=False, **kwargs): """Run a child program in a new process""" if verbose: - eprint("running: " + ' '.join(args)) + eprint("running: " + " ".join(args)) sys.stdout.flush() # Ensure that the .exe is used on Windows just in case a Linux ELF has been # compiled in the same directory. - if os.name == 'nt' and not args[0].endswith('.exe'): - args[0] += '.exe' + if os.name == "nt" and not args[0].endswith(".exe"): + args[0] += ".exe" # Use Popen here instead of call() as it apparently allows powershell on # Windows to not lock up waiting for input presumably. ret = subprocess.Popen(args, **kwargs) code = ret.wait() if code != 0: - err = "failed to run: " + ' '.join(args) + err = "failed to run: " + " ".join(args) if verbose or exception: raise RuntimeError(err) # For most failures, we definitely do want to print this error, or the user will have no @@ -209,30 +243,30 @@ def run(args, verbose=False, exception=False, is_bootstrap=False, **kwargs): else: sys.exit(err) + def run_powershell(script, *args, **kwargs): """Run a powershell script""" run(["PowerShell.exe", "/nologo", "-Command"] + script, *args, **kwargs) def require(cmd, exit=True, exception=False): - '''Run a command, returning its output. + """Run a command, returning its output. On error, If `exception` is `True`, raise the error Otherwise If `exit` is `True`, exit the process - Else return None.''' + Else return None.""" try: return subprocess.check_output(cmd).strip() except (subprocess.CalledProcessError, OSError) as exc: if exception: raise elif exit: - eprint("ERROR: unable to run `{}`: {}".format(' '.join(cmd), exc)) + eprint("ERROR: unable to run `{}`: {}".format(" ".join(cmd), exc)) eprint("Please make sure it's installed and in the path.") sys.exit(1) return None - def format_build_time(duration): """Return a nicer format for build time @@ -252,13 +286,16 @@ def default_build_triple(verbose): if platform_is_win32(): try: - version = subprocess.check_output(["rustc", "--version", "--verbose"], - stderr=subprocess.DEVNULL) + version = subprocess.check_output( + ["rustc", "--version", "--verbose"], stderr=subprocess.DEVNULL + ) version = version.decode(default_encoding) - host = next(x for x in version.split('\n') if x.startswith("host: ")) + host = next(x for x in version.split("\n") if x.startswith("host: ")) triple = host.split("host: ")[1] if verbose: - eprint("detected default triple {} from pre-installed rustc".format(triple)) + eprint( + "detected default triple {} from pre-installed rustc".format(triple) + ) return triple except Exception as e: if verbose: @@ -270,148 +307,149 @@ def default_build_triple(verbose): # If we do not have `uname`, assume Windows. if uname is None: - return 'x86_64-pc-windows-msvc' + return "x86_64-pc-windows-msvc" kernel, cputype, processor = uname.decode(default_encoding).split(maxsplit=2) # The goal here is to come up with the same triple as LLVM would, # at least for the subset of platforms we're willing to target. kerneltype_mapper = { - 'Darwin': 'apple-darwin', - 'DragonFly': 'unknown-dragonfly', - 'FreeBSD': 'unknown-freebsd', - 'Haiku': 'unknown-haiku', - 'NetBSD': 'unknown-netbsd', - 'OpenBSD': 'unknown-openbsd', - 'GNU': 'unknown-hurd', + "Darwin": "apple-darwin", + "DragonFly": "unknown-dragonfly", + "FreeBSD": "unknown-freebsd", + "Haiku": "unknown-haiku", + "NetBSD": "unknown-netbsd", + "OpenBSD": "unknown-openbsd", + "GNU": "unknown-hurd", } # Consider the direct transformation first and then the special cases if kernel in kerneltype_mapper: kernel = kerneltype_mapper[kernel] - elif kernel == 'Linux': + elif kernel == "Linux": # Apple doesn't support `-o` so this can't be used in the combined # uname invocation above ostype = require(["uname", "-o"], exit=required).decode(default_encoding) - if ostype == 'Android': - kernel = 'linux-android' + if ostype == "Android": + kernel = "linux-android" else: - kernel = 'unknown-linux-gnu' - elif kernel == 'SunOS': - kernel = 'pc-solaris' + kernel = "unknown-linux-gnu" + elif kernel == "SunOS": + kernel = "pc-solaris" # On Solaris, uname -m will return a machine classification instead # of a cpu type, so uname -p is recommended instead. However, the # output from that option is too generic for our purposes (it will # always emit 'i386' on x86/amd64 systems). As such, isainfo -k # must be used instead. - cputype = require(['isainfo', '-k']).decode(default_encoding) + cputype = require(["isainfo", "-k"]).decode(default_encoding) # sparc cpus have sun as a target vendor - if 'sparc' in cputype: - kernel = 'sun-solaris' - elif kernel.startswith('MINGW'): + if "sparc" in cputype: + kernel = "sun-solaris" + elif kernel.startswith("MINGW"): # msys' `uname` does not print gcc configuration, but prints msys # configuration. so we cannot believe `uname -m`: # msys1 is always i686 and msys2 is always x86_64. # instead, msys defines $MSYSTEM which is MINGW32 on i686 and # MINGW64 on x86_64. - kernel = 'pc-windows-gnu' - cputype = 'i686' - if os.environ.get('MSYSTEM') == 'MINGW64': - cputype = 'x86_64' - elif kernel.startswith('MSYS'): - kernel = 'pc-windows-gnu' - elif kernel.startswith('CYGWIN_NT'): - cputype = 'i686' - if kernel.endswith('WOW64'): - cputype = 'x86_64' - kernel = 'pc-windows-gnu' + kernel = "pc-windows-gnu" + cputype = "i686" + if os.environ.get("MSYSTEM") == "MINGW64": + cputype = "x86_64" + elif kernel.startswith("MSYS"): + kernel = "pc-windows-gnu" + elif kernel.startswith("CYGWIN_NT"): + cputype = "i686" + if kernel.endswith("WOW64"): + cputype = "x86_64" + kernel = "pc-windows-gnu" elif platform_is_win32(): # Some Windows platforms might have a `uname` command that returns a # non-standard string (e.g. gnuwin32 tools returns `windows32`). In # these cases, fall back to using sys.platform. - return 'x86_64-pc-windows-msvc' - elif kernel == 'AIX': + return "x86_64-pc-windows-msvc" + elif kernel == "AIX": # `uname -m` returns the machine ID rather than machine hardware on AIX, # so we are unable to use cputype to form triple. AIX 7.2 and # above supports 32-bit and 64-bit mode simultaneously and `uname -p` # returns `powerpc`, however we only supports `powerpc64-ibm-aix` in # rust on AIX. For above reasons, kerneltype_mapper and cputype_mapper # are not used to infer AIX's triple. - return 'powerpc64-ibm-aix' + return "powerpc64-ibm-aix" else: err = "unknown OS type: {}".format(kernel) sys.exit(err) - if cputype in ['powerpc', 'riscv'] and kernel == 'unknown-freebsd': - cputype = subprocess.check_output( - ['uname', '-p']).strip().decode(default_encoding) + if cputype in ["powerpc", "riscv"] and kernel == "unknown-freebsd": + cputype = ( + subprocess.check_output(["uname", "-p"]).strip().decode(default_encoding) + ) cputype_mapper = { - 'BePC': 'i686', - 'aarch64': 'aarch64', - 'aarch64eb': 'aarch64', - 'amd64': 'x86_64', - 'arm64': 'aarch64', - 'i386': 'i686', - 'i486': 'i686', - 'i686': 'i686', - 'i686-AT386': 'i686', - 'i786': 'i686', - 'loongarch64': 'loongarch64', - 'm68k': 'm68k', - 'csky': 'csky', - 'powerpc': 'powerpc', - 'powerpc64': 'powerpc64', - 'powerpc64le': 'powerpc64le', - 'ppc': 'powerpc', - 'ppc64': 'powerpc64', - 'ppc64le': 'powerpc64le', - 'riscv64': 'riscv64gc', - 's390x': 's390x', - 'x64': 'x86_64', - 'x86': 'i686', - 'x86-64': 'x86_64', - 'x86_64': 'x86_64' + "BePC": "i686", + "aarch64": "aarch64", + "aarch64eb": "aarch64", + "amd64": "x86_64", + "arm64": "aarch64", + "i386": "i686", + "i486": "i686", + "i686": "i686", + "i686-AT386": "i686", + "i786": "i686", + "loongarch64": "loongarch64", + "m68k": "m68k", + "csky": "csky", + "powerpc": "powerpc", + "powerpc64": "powerpc64", + "powerpc64le": "powerpc64le", + "ppc": "powerpc", + "ppc64": "powerpc64", + "ppc64le": "powerpc64le", + "riscv64": "riscv64gc", + "s390x": "s390x", + "x64": "x86_64", + "x86": "i686", + "x86-64": "x86_64", + "x86_64": "x86_64", } # Consider the direct transformation first and then the special cases if cputype in cputype_mapper: cputype = cputype_mapper[cputype] - elif cputype in {'xscale', 'arm'}: - cputype = 'arm' - if kernel == 'linux-android': - kernel = 'linux-androideabi' - elif kernel == 'unknown-freebsd': + elif cputype in {"xscale", "arm"}: + cputype = "arm" + if kernel == "linux-android": + kernel = "linux-androideabi" + elif kernel == "unknown-freebsd": cputype = processor - kernel = 'unknown-freebsd' - elif cputype == 'armv6l': - cputype = 'arm' - if kernel == 'linux-android': - kernel = 'linux-androideabi' + kernel = "unknown-freebsd" + elif cputype == "armv6l": + cputype = "arm" + if kernel == "linux-android": + kernel = "linux-androideabi" else: - kernel += 'eabihf' - elif cputype in {'armv7l', 'armv8l'}: - cputype = 'armv7' - if kernel == 'linux-android': - kernel = 'linux-androideabi' + kernel += "eabihf" + elif cputype in {"armv7l", "armv8l"}: + cputype = "armv7" + if kernel == "linux-android": + kernel = "linux-androideabi" else: - kernel += 'eabihf' - elif cputype == 'mips': - if sys.byteorder == 'big': - cputype = 'mips' - elif sys.byteorder == 'little': - cputype = 'mipsel' + kernel += "eabihf" + elif cputype == "mips": + if sys.byteorder == "big": + cputype = "mips" + elif sys.byteorder == "little": + cputype = "mipsel" else: raise ValueError("unknown byteorder: {}".format(sys.byteorder)) - elif cputype == 'mips64': - if sys.byteorder == 'big': - cputype = 'mips64' - elif sys.byteorder == 'little': - cputype = 'mips64el' + elif cputype == "mips64": + if sys.byteorder == "big": + cputype = "mips64" + elif sys.byteorder == "little": + cputype = "mips64el" else: - raise ValueError('unknown byteorder: {}'.format(sys.byteorder)) + raise ValueError("unknown byteorder: {}".format(sys.byteorder)) # only the n64 ABI is supported, indicate it - kernel += 'abi64' - elif cputype == 'sparc' or cputype == 'sparcv9' or cputype == 'sparc64': + kernel += "abi64" + elif cputype == "sparc" or cputype == "sparcv9" or cputype == "sparc64": pass else: err = "unknown cpu type: {}".format(cputype) @@ -422,8 +460,8 @@ def default_build_triple(verbose): @contextlib.contextmanager def output(filepath): - tmp = filepath + '.tmp' - with open(tmp, 'w') as f: + tmp = filepath + ".tmp" + with open(tmp, "w") as f: yield f try: if os.path.exists(filepath): @@ -467,6 +505,7 @@ class DownloadInfo: self.pattern = pattern self.verbose = verbose + def download_component(download_info): if not os.path.exists(download_info.tarball_path): get( @@ -477,6 +516,7 @@ def download_component(download_info): verbose=download_info.verbose, ) + def unpack_component(download_info): unpack( download_info.tarball_path, @@ -486,26 +526,30 @@ def unpack_component(download_info): verbose=download_info.verbose, ) + class FakeArgs: """Used for unit tests to avoid updating all call sites""" + def __init__(self): - self.build = '' - self.build_dir = '' + self.build = "" + self.build_dir = "" self.clean = False self.verbose = False self.json_output = False - self.color = 'auto' - self.warnings = 'default' + self.color = "auto" + self.warnings = "default" + class RustBuild(object): """Provide all the methods required to build Rust""" + def __init__(self, config_toml="", args=None): if args is None: args = FakeArgs() self.git_version = None self.nix_deps_dir = None self._should_fix_bins_and_dylibs = None - self.rust_root = os.path.abspath(os.path.join(__file__, '../../..')) + self.rust_root = os.path.abspath(os.path.join(__file__, "../../..")) self.config_toml = config_toml @@ -515,26 +559,28 @@ class RustBuild(object): self.color = args.color self.warnings = args.warnings - config_verbose_count = self.get_toml('verbose', 'build') + config_verbose_count = self.get_toml("verbose", "build") if config_verbose_count is not None: self.verbose = max(self.verbose, int(config_verbose_count)) - self.use_vendored_sources = self.get_toml('vendor', 'build') == 'true' - self.use_locked_deps = self.get_toml('locked-deps', 'build') == 'true' + self.use_vendored_sources = self.get_toml("vendor", "build") == "true" + self.use_locked_deps = self.get_toml("locked-deps", "build") == "true" - build_dir = args.build_dir or self.get_toml('build-dir', 'build') or 'build' + build_dir = args.build_dir or self.get_toml("build-dir", "build") or "build" self.build_dir = os.path.abspath(build_dir) - self.stage0_data = parse_stage0_file(os.path.join(self.rust_root, "src", "stage0")) + self.stage0_data = parse_stage0_file( + os.path.join(self.rust_root, "src", "stage0") + ) self.stage0_compiler = Stage0Toolchain( - self.stage0_data["compiler_date"], - self.stage0_data["compiler_version"] + self.stage0_data["compiler_date"], self.stage0_data["compiler_version"] + ) + self.download_url = ( + os.getenv("RUSTUP_DIST_SERVER") or self.stage0_data["dist_server"] ) - self.download_url = os.getenv("RUSTUP_DIST_SERVER") or self.stage0_data["dist_server"] self.build = args.build or self.build_triple() - def download_toolchain(self): """Fetch the build system for Rust, written in Rust @@ -550,58 +596,73 @@ class RustBuild(object): key = self.stage0_compiler.date is_outdated = self.program_out_of_date(self.rustc_stamp(), key) - need_rustc = self.rustc().startswith(bin_root) and (not os.path.exists(self.rustc()) \ - or is_outdated) - need_cargo = self.cargo().startswith(bin_root) and (not os.path.exists(self.cargo()) \ - or is_outdated) + need_rustc = self.rustc().startswith(bin_root) and ( + not os.path.exists(self.rustc()) or is_outdated + ) + need_cargo = self.cargo().startswith(bin_root) and ( + not os.path.exists(self.cargo()) or is_outdated + ) if need_rustc or need_cargo: if os.path.exists(bin_root): # HACK: On Windows, we can't delete rust-analyzer-proc-macro-server while it's # running. Kill it. if platform_is_win32(): - print("Killing rust-analyzer-proc-macro-srv before deleting stage0 toolchain") - regex = '{}\\\\(host|{})\\\\stage0\\\\libexec'.format( - os.path.basename(self.build_dir), - self.build + print( + "Killing rust-analyzer-proc-macro-srv before deleting stage0 toolchain" + ) + regex = "{}\\\\(host|{})\\\\stage0\\\\libexec".format( + os.path.basename(self.build_dir), self.build ) script = ( # NOTE: can't use `taskkill` or `Get-Process -Name` because they error if # the server isn't running. - 'Get-Process | ' + - 'Where-Object {$_.Name -eq "rust-analyzer-proc-macro-srv"} |' + - 'Where-Object {{$_.Path -match "{}"}} |'.format(regex) + - 'Stop-Process' + "Get-Process | " + + 'Where-Object {$_.Name -eq "rust-analyzer-proc-macro-srv"} |' + + 'Where-Object {{$_.Path -match "{}"}} |'.format(regex) + + "Stop-Process" ) run_powershell([script]) shutil.rmtree(bin_root) - cache_dst = (self.get_toml('bootstrap-cache-path', 'build') or - os.path.join(self.build_dir, "cache")) + cache_dst = self.get_toml("bootstrap-cache-path", "build") or os.path.join( + self.build_dir, "cache" + ) rustc_cache = os.path.join(cache_dst, key) if not os.path.exists(rustc_cache): os.makedirs(rustc_cache) - tarball_suffix = '.tar.gz' if lzma is None else '.tar.xz' + tarball_suffix = ".tar.gz" if lzma is None else ".tar.xz" - toolchain_suffix = "{}-{}{}".format(rustc_channel, self.build, tarball_suffix) + toolchain_suffix = "{}-{}{}".format( + rustc_channel, self.build, tarball_suffix + ) tarballs_to_download = [] if need_rustc: tarballs_to_download.append( - ("rust-std-{}".format(toolchain_suffix), "rust-std-{}".format(self.build)) + ( + "rust-std-{}".format(toolchain_suffix), + "rust-std-{}".format(self.build), + ) + ) + tarballs_to_download.append( + ("rustc-{}".format(toolchain_suffix), "rustc") ) - tarballs_to_download.append(("rustc-{}".format(toolchain_suffix), "rustc")) if need_cargo: - tarballs_to_download.append(("cargo-{}".format(toolchain_suffix), "cargo")) + tarballs_to_download.append( + ("cargo-{}".format(toolchain_suffix), "cargo") + ) tarballs_download_info = [ DownloadInfo( base_download_url=self.download_url, - download_path="dist/{}/{}".format(self.stage0_compiler.date, filename), + download_path="dist/{}/{}".format( + self.stage0_compiler.date, filename + ), bin_root=self.bin_root(), tarball_path=os.path.join(rustc_cache, filename), tarball_suffix=tarball_suffix, @@ -620,7 +681,11 @@ class RustBuild(object): # In Python 2.7, Pool cannot be used as a context manager. pool_size = min(len(tarballs_download_info), get_cpus()) if self.verbose: - print('Choosing a pool size of', pool_size, 'for the unpacking of the tarballs') + print( + "Choosing a pool size of", + pool_size, + "for the unpacking of the tarballs", + ) p = Pool(pool_size) try: # FIXME: A cheap workaround for https://github.com/rust-lang/rust/issues/125578, @@ -639,7 +704,9 @@ class RustBuild(object): self.fix_bin_or_dylib("{}/bin/rustc".format(bin_root)) self.fix_bin_or_dylib("{}/bin/rustdoc".format(bin_root)) - self.fix_bin_or_dylib("{}/libexec/rust-analyzer-proc-macro-srv".format(bin_root)) + self.fix_bin_or_dylib( + "{}/libexec/rust-analyzer-proc-macro-srv".format(bin_root) + ) lib_dir = "{}/lib".format(bin_root) rustlib_bin_dir = "{}/rustlib/{}/bin".format(lib_dir, self.build) self.fix_bin_or_dylib("{}/rust-lld".format(rustlib_bin_dir)) @@ -667,12 +734,15 @@ class RustBuild(object): def get_answer(): default_encoding = sys.getdefaultencoding() try: - ostype = subprocess.check_output( - ['uname', '-s']).strip().decode(default_encoding) + ostype = ( + subprocess.check_output(["uname", "-s"]) + .strip() + .decode(default_encoding) + ) except subprocess.CalledProcessError: return False except OSError as reason: - if getattr(reason, 'winerror', None) is not None: + if getattr(reason, "winerror", None) is not None: return False raise reason @@ -690,17 +760,23 @@ class RustBuild(object): # The latter one does not exist on NixOS when using tmpfs as root. try: with open("/etc/os-release", "r") as f: - is_nixos = any(ln.strip() in ("ID=nixos", "ID='nixos'", 'ID="nixos"') - for ln in f) + is_nixos = any( + ln.strip() in ("ID=nixos", "ID='nixos'", 'ID="nixos"') + for ln in f + ) except FileNotFoundError: is_nixos = False # If not on NixOS, then warn if user seems to be atop Nix shell if not is_nixos: - in_nix_shell = os.getenv('IN_NIX_SHELL') + in_nix_shell = os.getenv("IN_NIX_SHELL") if in_nix_shell: - eprint("The IN_NIX_SHELL environment variable is `{}`;".format(in_nix_shell), - "you may need to set `patch-binaries-for-nix=true` in config.toml") + eprint( + "The IN_NIX_SHELL environment variable is `{}`;".format( + in_nix_shell + ), + "you may need to set `patch-binaries-for-nix=true` in config.toml", + ) return is_nixos @@ -736,7 +812,7 @@ class RustBuild(object): # zlib: Needed as a system dependency of `libLLVM-*.so`. # patchelf: Needed for patching ELF binaries (see doc comment above). nix_deps_dir = "{}/{}".format(self.build_dir, ".nix-deps") - nix_expr = ''' + nix_expr = """ with (import <nixpkgs> {}); symlinkJoin { name = "rust-stage0-dependencies"; @@ -746,24 +822,30 @@ class RustBuild(object): stdenv.cc.bintools ]; } - ''' + """ try: - subprocess.check_output([ - "nix-build", "-E", nix_expr, "-o", nix_deps_dir, - ]) + subprocess.check_output( + [ + "nix-build", + "-E", + nix_expr, + "-o", + nix_deps_dir, + ] + ) except subprocess.CalledProcessError as reason: eprint("WARNING: failed to call nix-build:", reason) return self.nix_deps_dir = nix_deps_dir patchelf = "{}/bin/patchelf".format(nix_deps_dir) - rpath_entries = [ - os.path.join(os.path.realpath(nix_deps_dir), "lib") - ] + rpath_entries = [os.path.join(os.path.realpath(nix_deps_dir), "lib")] patchelf_args = ["--add-rpath", ":".join(rpath_entries)] if ".so" not in fname: # Finally, set the correct .interp for binaries - with open("{}/nix-support/dynamic-linker".format(nix_deps_dir)) as dynamic_linker: + with open( + "{}/nix-support/dynamic-linker".format(nix_deps_dir) + ) as dynamic_linker: patchelf_args += ["--set-interpreter", dynamic_linker.read().rstrip()] try: @@ -781,13 +863,13 @@ class RustBuild(object): >>> expected = os.path.join("build", "host", "stage0", ".rustc-stamp") >>> assert rb.rustc_stamp() == expected, rb.rustc_stamp() """ - return os.path.join(self.bin_root(), '.rustc-stamp') + return os.path.join(self.bin_root(), ".rustc-stamp") def program_out_of_date(self, stamp_path, key): """Check if the given program stamp is out of date""" if not os.path.exists(stamp_path) or self.clean: return True - with open(stamp_path, 'r') as stamp: + with open(stamp_path, "r") as stamp: return key != stamp.read() def bin_root(self): @@ -834,11 +916,11 @@ class RustBuild(object): def get_toml_static(config_toml, key, section=None): cur_section = None for line in config_toml.splitlines(): - section_match = re.match(r'^\s*\[(.*)\]\s*$', line) + section_match = re.match(r"^\s*\[(.*)\]\s*$", line) if section_match is not None: cur_section = section_match.group(1) - match = re.match(r'^{}\s*=(.*)$'.format(key), line) + match = re.match(r"^{}\s*=(.*)$".format(key), line) if match is not None: value = match.group(1) if section is None or section == cur_section: @@ -847,11 +929,11 @@ class RustBuild(object): def cargo(self): """Return config path for cargo""" - return self.program_config('cargo') + return self.program_config("cargo") def rustc(self): """Return config path for rustc""" - return self.program_config('rustc') + return self.program_config("rustc") def program_config(self, program): """Return config path for the given program at the given stage @@ -886,12 +968,12 @@ class RustBuild(object): """ start = line.find('"') if start != -1: - end = start + 1 + line[start + 1:].find('"') - return line[start + 1:end] - start = line.find('\'') + end = start + 1 + line[start + 1 :].find('"') + return line[start + 1 : end] + start = line.find("'") if start != -1: - end = start + 1 + line[start + 1:].find('\'') - return line[start + 1:end] + end = start + 1 + line[start + 1 :].find("'") + return line[start + 1 : end] return None def bootstrap_out(self): @@ -941,24 +1023,37 @@ class RustBuild(object): del env["CARGO_BUILD_TARGET"] env["CARGO_TARGET_DIR"] = build_dir env["RUSTC"] = self.rustc() - env["LD_LIBRARY_PATH"] = os.path.join(self.bin_root(), "lib") + \ - (os.pathsep + env["LD_LIBRARY_PATH"]) \ - if "LD_LIBRARY_PATH" in env else "" - env["DYLD_LIBRARY_PATH"] = os.path.join(self.bin_root(), "lib") + \ - (os.pathsep + env["DYLD_LIBRARY_PATH"]) \ - if "DYLD_LIBRARY_PATH" in env else "" - env["LIBRARY_PATH"] = os.path.join(self.bin_root(), "lib") + \ - (os.pathsep + env["LIBRARY_PATH"]) \ - if "LIBRARY_PATH" in env else "" - env["LIBPATH"] = os.path.join(self.bin_root(), "lib") + \ - (os.pathsep + env["LIBPATH"]) \ - if "LIBPATH" in env else "" + env["LD_LIBRARY_PATH"] = ( + os.path.join(self.bin_root(), "lib") + (os.pathsep + env["LD_LIBRARY_PATH"]) + if "LD_LIBRARY_PATH" in env + else "" + ) + env["DYLD_LIBRARY_PATH"] = ( + os.path.join(self.bin_root(), "lib") + + (os.pathsep + env["DYLD_LIBRARY_PATH"]) + if "DYLD_LIBRARY_PATH" in env + else "" + ) + env["LIBRARY_PATH"] = ( + os.path.join(self.bin_root(), "lib") + (os.pathsep + env["LIBRARY_PATH"]) + if "LIBRARY_PATH" in env + else "" + ) + env["LIBPATH"] = ( + os.path.join(self.bin_root(), "lib") + (os.pathsep + env["LIBPATH"]) + if "LIBPATH" in env + else "" + ) # Export Stage0 snapshot compiler related env variables build_section = "target.{}".format(self.build) host_triple_sanitized = self.build.replace("-", "_") var_data = { - "CC": "cc", "CXX": "cxx", "LD": "linker", "AR": "ar", "RANLIB": "ranlib" + "CC": "cc", + "CXX": "cxx", + "LD": "linker", + "AR": "ar", + "RANLIB": "ranlib", } for var_name, toml_key in var_data.items(): toml_val = self.get_toml(toml_key, build_section) @@ -1023,14 +1118,16 @@ class RustBuild(object): if "RUSTFLAGS_BOOTSTRAP" in env: env["RUSTFLAGS"] += " " + env["RUSTFLAGS_BOOTSTRAP"] - env["PATH"] = os.path.join(self.bin_root(), "bin") + \ - os.pathsep + env["PATH"] + env["PATH"] = os.path.join(self.bin_root(), "bin") + os.pathsep + env["PATH"] if not os.path.isfile(self.cargo()): - raise Exception("no cargo executable found at `{}`".format( - self.cargo())) - args = [self.cargo(), "build", "--manifest-path", - os.path.join(self.rust_root, "src/bootstrap/Cargo.toml"), - "-Zroot-dir="+self.rust_root] + raise Exception("no cargo executable found at `{}`".format(self.cargo())) + args = [ + self.cargo(), + "build", + "--manifest-path", + os.path.join(self.rust_root, "src/bootstrap/Cargo.toml"), + "-Zroot-dir=" + self.rust_root, + ] args.extend("--verbose" for _ in range(self.verbose)) if self.use_locked_deps: args.append("--locked") @@ -1058,83 +1155,103 @@ class RustBuild(object): Note that `default_build_triple` is moderately expensive, so use `self.build` where possible. """ - config = self.get_toml('build') + config = self.get_toml("build") return config or default_build_triple(self.verbose) def check_vendored_status(self): """Check that vendoring is configured properly""" # keep this consistent with the equivalent check in bootstrap: # https://github.com/rust-lang/rust/blob/a8a33cf27166d3eabaffc58ed3799e054af3b0c6/src/bootstrap/lib.rs#L399-L405 - if 'SUDO_USER' in os.environ and not self.use_vendored_sources: + if "SUDO_USER" in os.environ and not self.use_vendored_sources: if os.getuid() == 0: self.use_vendored_sources = True - eprint('INFO: looks like you\'re trying to run this command as root') - eprint(' and so in order to preserve your $HOME this will now') - eprint(' use vendored sources by default.') + eprint("INFO: looks like you're trying to run this command as root") + eprint(" and so in order to preserve your $HOME this will now") + eprint(" use vendored sources by default.") - cargo_dir = os.path.join(self.rust_root, '.cargo') + cargo_dir = os.path.join(self.rust_root, ".cargo") + url = "https://ci-artifacts.rust-lang.org/rustc-builds/<commit>/rustc-nightly-src.tar.xz" if self.use_vendored_sources: - vendor_dir = os.path.join(self.rust_root, 'vendor') + vendor_dir = os.path.join(self.rust_root, "vendor") if not os.path.exists(vendor_dir): - eprint('ERROR: vendoring required, but vendor directory does not exist.') - eprint(' Run `x.py vendor` to initialize the vendor directory.') - eprint(' Alternatively, use the pre-vendored `rustc-src` dist component.') - eprint(' To get a stable/beta/nightly version, download it from: ') - eprint(' ' - 'https://forge.rust-lang.org/infra/other-installation-methods.html#source-code') - eprint(' To get a specific commit version, download it using the below URL,') - eprint(' replacing <commit> with a specific commit checksum: ') - eprint(' ' - 'https://ci-artifacts.rust-lang.org/rustc-builds/<commit>/rustc-nightly-src.tar.xz') - eprint(' Once you have the source downloaded, place the vendor directory') - eprint(' from the archive in the root of the rust project.') + eprint( + "ERROR: vendoring required, but vendor directory does not exist." + ) + eprint(" Run `x.py vendor` to initialize the vendor directory.") + eprint( + " Alternatively, use the pre-vendored `rustc-src` dist component." + ) + eprint( + " To get a stable/beta/nightly version, download it from: " + ) + eprint( + " " + "https://forge.rust-lang.org/infra/other-installation-methods.html#source-code" + ) + eprint( + " To get a specific commit version, download it using the below URL," + ) + eprint(" replacing <commit> with a specific commit checksum: ") + eprint(" ", url) + eprint( + " Once you have the source downloaded, place the vendor directory" + ) + eprint(" from the archive in the root of the rust project.") raise Exception("{} not found".format(vendor_dir)) if not os.path.exists(cargo_dir): - eprint('ERROR: vendoring required, but .cargo/config does not exist.') + eprint("ERROR: vendoring required, but .cargo/config does not exist.") raise Exception("{} not found".format(cargo_dir)) + def parse_args(args): """Parse the command line arguments that the python script needs.""" parser = argparse.ArgumentParser(add_help=False) - parser.add_argument('-h', '--help', action='store_true') - parser.add_argument('--config') - parser.add_argument('--build-dir') - parser.add_argument('--build') - parser.add_argument('--color', choices=['always', 'never', 'auto']) - parser.add_argument('--clean', action='store_true') - parser.add_argument('--json-output', action='store_true') - parser.add_argument('--warnings', choices=['deny', 'warn', 'default'], default='default') - parser.add_argument('-v', '--verbose', action='count', default=0) + parser.add_argument("-h", "--help", action="store_true") + parser.add_argument("--config") + parser.add_argument("--build-dir") + parser.add_argument("--build") + parser.add_argument("--color", choices=["always", "never", "auto"]) + parser.add_argument("--clean", action="store_true") + parser.add_argument("--json-output", action="store_true") + parser.add_argument( + "--warnings", choices=["deny", "warn", "default"], default="default" + ) + parser.add_argument("-v", "--verbose", action="count", default=0) return parser.parse_known_args(args)[0] + def parse_stage0_file(path): result = {} - with open(path, 'r') as file: + with open(path, "r") as file: for line in file: line = line.strip() - if line and not line.startswith('#'): - key, value = line.split('=', 1) + if line and not line.startswith("#"): + key, value = line.split("=", 1) result[key.strip()] = value.strip() return result + def bootstrap(args): """Configure, fetch, build and run the initial bootstrap""" - rust_root = os.path.abspath(os.path.join(__file__, '../../..')) + rust_root = os.path.abspath(os.path.join(__file__, "../../..")) - if not os.path.exists(os.path.join(rust_root, '.git')) and \ - os.path.exists(os.path.join(rust_root, '.github')): - eprint("warn: Looks like you are trying to bootstrap Rust from a source that is neither a " - "git clone nor distributed tarball.\nThis build may fail due to missing submodules " - "unless you put them in place manually.") + if not os.path.exists(os.path.join(rust_root, ".git")) and os.path.exists( + os.path.join(rust_root, ".github") + ): + eprint( + "warn: Looks like you are trying to bootstrap Rust from a source that is neither a " + "git clone nor distributed tarball.\nThis build may fail due to missing submodules " + "unless you put them in place manually." + ) # Read from `--config`, then `RUST_BOOTSTRAP_CONFIG`, then `./config.toml`, # then `config.toml` in the root directory. - toml_path = args.config or os.getenv('RUST_BOOTSTRAP_CONFIG') + toml_path = args.config or os.getenv("RUST_BOOTSTRAP_CONFIG") using_default_path = toml_path is None if using_default_path: - toml_path = 'config.toml' + toml_path = "config.toml" if not os.path.exists(toml_path): toml_path = os.path.join(rust_root, toml_path) @@ -1144,23 +1261,23 @@ def bootstrap(args): with open(toml_path) as config: config_toml = config.read() else: - config_toml = '' + config_toml = "" - profile = RustBuild.get_toml_static(config_toml, 'profile') + profile = RustBuild.get_toml_static(config_toml, "profile") if profile is not None: # Allows creating alias for profile names, allowing # profiles to be renamed while maintaining back compatibility # Keep in sync with `profile_aliases` in config.rs - profile_aliases = { - "user": "dist" - } - include_file = 'config.{}.toml'.format(profile_aliases.get(profile) or profile) - include_dir = os.path.join(rust_root, 'src', 'bootstrap', 'defaults') + profile_aliases = {"user": "dist"} + include_file = "config.{}.toml".format(profile_aliases.get(profile) or profile) + include_dir = os.path.join(rust_root, "src", "bootstrap", "defaults") include_path = os.path.join(include_dir, include_file) if not os.path.exists(include_path): - raise Exception("Unrecognized config profile '{}'. Check src/bootstrap/defaults" - " for available options.".format(profile)) + raise Exception( + "Unrecognized config profile '{}'. Check src/bootstrap/defaults" + " for available options.".format(profile) + ) # HACK: This works because `self.get_toml()` returns the first match it finds for a # specific key, so appending our defaults at the end allows the user to override them @@ -1196,8 +1313,8 @@ def main(): start_time = time() # x.py help <cmd> ... - if len(sys.argv) > 1 and sys.argv[1] == 'help': - sys.argv[1] = '-h' + if len(sys.argv) > 1 and sys.argv[1] == "help": + sys.argv[1] = "-h" args = parse_args(sys.argv) help_triggered = args.help or len(sys.argv) == 1 @@ -1207,14 +1324,15 @@ def main(): if help_triggered: eprint( "INFO: Downloading and building bootstrap before processing --help command.\n" - " See src/bootstrap/README.md for help with common commands.") + " See src/bootstrap/README.md for help with common commands." + ) exit_code = 0 success_word = "successfully" try: bootstrap(args) except (SystemExit, KeyboardInterrupt) as error: - if hasattr(error, 'code') and isinstance(error.code, int): + if hasattr(error, "code") and isinstance(error.code, int): exit_code = error.code else: exit_code = 1 @@ -1222,9 +1340,14 @@ def main(): success_word = "unsuccessfully" if not help_triggered: - eprint("Build completed", success_word, "in", format_build_time(time() - start_time)) + eprint( + "Build completed", + success_word, + "in", + format_build_time(time() - start_time), + ) sys.exit(exit_code) -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/src/bootstrap/bootstrap_test.py b/src/bootstrap/bootstrap_test.py index 70ed12b96e8..7494536539d 100644 --- a/src/bootstrap/bootstrap_test.py +++ b/src/bootstrap/bootstrap_test.py @@ -16,8 +16,9 @@ from shutil import rmtree bootstrap_dir = os.path.dirname(os.path.abspath(__file__)) # For the import below, have Python search in src/bootstrap first. sys.path.insert(0, bootstrap_dir) -import bootstrap # noqa: E402 -import configure # noqa: E402 +import bootstrap # noqa: E402 +import configure # noqa: E402 + def serialize_and_parse(configure_args, bootstrap_args=None): from io import StringIO @@ -32,15 +33,20 @@ def serialize_and_parse(configure_args, bootstrap_args=None): try: import tomllib + # Verify this is actually valid TOML. tomllib.loads(build.config_toml) except ImportError: - print("WARNING: skipping TOML validation, need at least python 3.11", file=sys.stderr) + print( + "WARNING: skipping TOML validation, need at least python 3.11", + file=sys.stderr, + ) return build class VerifyTestCase(unittest.TestCase): """Test Case for verify""" + def setUp(self): self.container = tempfile.mkdtemp() self.src = os.path.join(self.container, "src.txt") @@ -68,14 +74,14 @@ class VerifyTestCase(unittest.TestCase): class ProgramOutOfDate(unittest.TestCase): """Test if a program is out of date""" + def setUp(self): self.container = tempfile.mkdtemp() os.mkdir(os.path.join(self.container, "stage0")) self.build = bootstrap.RustBuild() self.build.date = "2017-06-15" self.build.build_dir = self.container - self.rustc_stamp_path = os.path.join(self.container, "stage0", - ".rustc-stamp") + self.rustc_stamp_path = os.path.join(self.container, "stage0", ".rustc-stamp") self.key = self.build.date + str(None) def tearDown(self): @@ -97,11 +103,14 @@ class ProgramOutOfDate(unittest.TestCase): """Return False both dates match""" with open(self.rustc_stamp_path, "w") as rustc_stamp: rustc_stamp.write("2017-06-15None") - self.assertFalse(self.build.program_out_of_date(self.rustc_stamp_path, self.key)) + self.assertFalse( + self.build.program_out_of_date(self.rustc_stamp_path, self.key) + ) class ParseArgsInConfigure(unittest.TestCase): """Test if `parse_args` function in `configure.py` works properly""" + @patch("configure.err") def test_unknown_args(self, err): # It should be print an error message if the argument doesn't start with '--' @@ -148,28 +157,35 @@ class ParseArgsInConfigure(unittest.TestCase): class GenerateAndParseConfig(unittest.TestCase): """Test that we can serialize and deserialize a config.toml file""" + def test_no_args(self): build = serialize_and_parse([]) - self.assertEqual(build.get_toml("profile"), 'dist') + self.assertEqual(build.get_toml("profile"), "dist") self.assertIsNone(build.get_toml("llvm.download-ci-llvm")) def test_set_section(self): build = serialize_and_parse(["--set", "llvm.download-ci-llvm"]) - self.assertEqual(build.get_toml("download-ci-llvm", section="llvm"), 'true') + self.assertEqual(build.get_toml("download-ci-llvm", section="llvm"), "true") def test_set_target(self): build = serialize_and_parse(["--set", "target.x86_64-unknown-linux-gnu.cc=gcc"]) - self.assertEqual(build.get_toml("cc", section="target.x86_64-unknown-linux-gnu"), 'gcc') + self.assertEqual( + build.get_toml("cc", section="target.x86_64-unknown-linux-gnu"), "gcc" + ) def test_set_top_level(self): build = serialize_and_parse(["--set", "profile=compiler"]) - self.assertEqual(build.get_toml("profile"), 'compiler') + self.assertEqual(build.get_toml("profile"), "compiler") def test_set_codegen_backends(self): build = serialize_and_parse(["--set", "rust.codegen-backends=cranelift"]) - self.assertNotEqual(build.config_toml.find("codegen-backends = ['cranelift']"), -1) + self.assertNotEqual( + build.config_toml.find("codegen-backends = ['cranelift']"), -1 + ) build = serialize_and_parse(["--set", "rust.codegen-backends=cranelift,llvm"]) - self.assertNotEqual(build.config_toml.find("codegen-backends = ['cranelift', 'llvm']"), -1) + self.assertNotEqual( + build.config_toml.find("codegen-backends = ['cranelift', 'llvm']"), -1 + ) build = serialize_and_parse(["--enable-full-tools"]) self.assertNotEqual(build.config_toml.find("codegen-backends = ['llvm']"), -1) @@ -223,7 +239,7 @@ class BuildBootstrap(unittest.TestCase): self.assertTrue("--timings" in args) def test_warnings(self): - for toml_warnings in ['false', 'true', None]: + for toml_warnings in ["false", "true", None]: configure_args = [] if toml_warnings is not None: configure_args = ["--set", "rust.deny-warnings=" + toml_warnings] diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index 70f4e70962a..71750022145 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -6,11 +6,12 @@ from __future__ import absolute_import, division, print_function import shlex import sys import os + rust_dir = os.path.dirname(os.path.abspath(__file__)) rust_dir = os.path.dirname(rust_dir) rust_dir = os.path.dirname(rust_dir) sys.path.append(os.path.join(rust_dir, "src", "bootstrap")) -import bootstrap # noqa: E402 +import bootstrap # noqa: E402 class Option(object): @@ -32,26 +33,62 @@ def v(*args): options.append(Option(*args, value=True)) -o("debug", "rust.debug", "enables debugging environment; does not affect optimization of bootstrapped code") +o( + "debug", + "rust.debug", + "enables debugging environment; does not affect optimization of bootstrapped code", +) o("docs", "build.docs", "build standard library documentation") o("compiler-docs", "build.compiler-docs", "build compiler documentation") o("optimize-tests", "rust.optimize-tests", "build tests with optimizations") o("verbose-tests", "rust.verbose-tests", "enable verbose output when running tests") -o("ccache", "llvm.ccache", "invoke gcc/clang via ccache to reuse object files between builds") +o( + "ccache", + "llvm.ccache", + "invoke gcc/clang via ccache to reuse object files between builds", +) o("sccache", None, "invoke gcc/clang via sccache to reuse object files between builds") o("local-rust", None, "use an installed rustc rather than downloading a snapshot") v("local-rust-root", None, "set prefix for local rust binary") -o("local-rebuild", "build.local-rebuild", "assume local-rust matches the current version, for rebuilds; implies local-rust, and is implied if local-rust already matches the current version") -o("llvm-static-stdcpp", "llvm.static-libstdcpp", "statically link to libstdc++ for LLVM") -o("llvm-link-shared", "llvm.link-shared", "prefer shared linking to LLVM (llvm-config --link-shared)") +o( + "local-rebuild", + "build.local-rebuild", + "assume local-rust matches the current version, for rebuilds; implies local-rust, and is implied if local-rust already matches the current version", +) +o( + "llvm-static-stdcpp", + "llvm.static-libstdcpp", + "statically link to libstdc++ for LLVM", +) +o( + "llvm-link-shared", + "llvm.link-shared", + "prefer shared linking to LLVM (llvm-config --link-shared)", +) o("rpath", "rust.rpath", "build rpaths into rustc itself") o("codegen-tests", "rust.codegen-tests", "run the tests/codegen tests") -o("ninja", "llvm.ninja", "build LLVM using the Ninja generator (for MSVC, requires building in the correct environment)") +o( + "ninja", + "llvm.ninja", + "build LLVM using the Ninja generator (for MSVC, requires building in the correct environment)", +) o("locked-deps", "build.locked-deps", "force Cargo.lock to be up to date") o("vendor", "build.vendor", "enable usage of vendored Rust crates") -o("sanitizers", "build.sanitizers", "build the sanitizer runtimes (asan, dfsan, lsan, msan, tsan, hwasan)") -o("dist-src", "rust.dist-src", "when building tarballs enables building a source tarball") -o("cargo-native-static", "build.cargo-native-static", "static native libraries in cargo") +o( + "sanitizers", + "build.sanitizers", + "build the sanitizer runtimes (asan, dfsan, lsan, msan, tsan, hwasan)", +) +o( + "dist-src", + "rust.dist-src", + "when building tarballs enables building a source tarball", +) +o( + "cargo-native-static", + "build.cargo-native-static", + "static native libraries in cargo", +) o("profiler", "build.profiler", "build the profiler runtime") o("full-tools", None, "enable all tools") o("lld", "rust.lld", "build lld") @@ -59,7 +96,11 @@ o("llvm-bitcode-linker", "rust.llvm-bitcode-linker", "build llvm bitcode linker" o("clang", "llvm.clang", "build clang") o("use-libcxx", "llvm.use-libcxx", "build LLVM with libc++") o("control-flow-guard", "rust.control-flow-guard", "Enable Control Flow Guard") -o("patch-binaries-for-nix", "build.patch-binaries-for-nix", "whether patch binaries for usage with Nix toolchains") +o( + "patch-binaries-for-nix", + "build.patch-binaries-for-nix", + "whether patch binaries for usage with Nix toolchains", +) o("new-symbol-mangling", "rust.new-symbol-mangling", "use symbol-mangling-version v0") v("llvm-cflags", "llvm.cflags", "build LLVM with these extra compiler flags") @@ -76,16 +117,48 @@ o("llvm-enzyme", "llvm.enzyme", "build LLVM with enzyme") o("llvm-offload", "llvm.offload", "build LLVM with gpu offload support") o("llvm-plugins", "llvm.plugins", "build LLVM with plugin interface") o("debug-assertions", "rust.debug-assertions", "build with debugging assertions") -o("debug-assertions-std", "rust.debug-assertions-std", "build the standard library with debugging assertions") +o( + "debug-assertions-std", + "rust.debug-assertions-std", + "build the standard library with debugging assertions", +) o("overflow-checks", "rust.overflow-checks", "build with overflow checks") -o("overflow-checks-std", "rust.overflow-checks-std", "build the standard library with overflow checks") -o("llvm-release-debuginfo", "llvm.release-debuginfo", "build LLVM with debugger metadata") +o( + "overflow-checks-std", + "rust.overflow-checks-std", + "build the standard library with overflow checks", +) +o( + "llvm-release-debuginfo", + "llvm.release-debuginfo", + "build LLVM with debugger metadata", +) v("debuginfo-level", "rust.debuginfo-level", "debuginfo level for Rust code") -v("debuginfo-level-rustc", "rust.debuginfo-level-rustc", "debuginfo level for the compiler") -v("debuginfo-level-std", "rust.debuginfo-level-std", "debuginfo level for the standard library") -v("debuginfo-level-tools", "rust.debuginfo-level-tools", "debuginfo level for the tools") -v("debuginfo-level-tests", "rust.debuginfo-level-tests", "debuginfo level for the test suites run with compiletest") -v("save-toolstates", "rust.save-toolstates", "save build and test status of external tools into this file") +v( + "debuginfo-level-rustc", + "rust.debuginfo-level-rustc", + "debuginfo level for the compiler", +) +v( + "debuginfo-level-std", + "rust.debuginfo-level-std", + "debuginfo level for the standard library", +) +v( + "debuginfo-level-tools", + "rust.debuginfo-level-tools", + "debuginfo level for the tools", +) +v( + "debuginfo-level-tests", + "rust.debuginfo-level-tests", + "debuginfo level for the test suites run with compiletest", +) +v( + "save-toolstates", + "rust.save-toolstates", + "save build and test status of external tools into this file", +) v("prefix", "install.prefix", "set installation prefix") v("localstatedir", "install.localstatedir", "local state directory") @@ -102,50 +175,117 @@ v("llvm-config", None, "set path to llvm-config") v("llvm-filecheck", None, "set path to LLVM's FileCheck utility") v("python", "build.python", "set path to python") v("android-ndk", "build.android-ndk", "set path to Android NDK") -v("musl-root", "target.x86_64-unknown-linux-musl.musl-root", - "MUSL root installation directory (deprecated)") -v("musl-root-x86_64", "target.x86_64-unknown-linux-musl.musl-root", - "x86_64-unknown-linux-musl install directory") -v("musl-root-i586", "target.i586-unknown-linux-musl.musl-root", - "i586-unknown-linux-musl install directory") -v("musl-root-i686", "target.i686-unknown-linux-musl.musl-root", - "i686-unknown-linux-musl install directory") -v("musl-root-arm", "target.arm-unknown-linux-musleabi.musl-root", - "arm-unknown-linux-musleabi install directory") -v("musl-root-armhf", "target.arm-unknown-linux-musleabihf.musl-root", - "arm-unknown-linux-musleabihf install directory") -v("musl-root-armv5te", "target.armv5te-unknown-linux-musleabi.musl-root", - "armv5te-unknown-linux-musleabi install directory") -v("musl-root-armv7", "target.armv7-unknown-linux-musleabi.musl-root", - "armv7-unknown-linux-musleabi install directory") -v("musl-root-armv7hf", "target.armv7-unknown-linux-musleabihf.musl-root", - "armv7-unknown-linux-musleabihf install directory") -v("musl-root-aarch64", "target.aarch64-unknown-linux-musl.musl-root", - "aarch64-unknown-linux-musl install directory") -v("musl-root-mips", "target.mips-unknown-linux-musl.musl-root", - "mips-unknown-linux-musl install directory") -v("musl-root-mipsel", "target.mipsel-unknown-linux-musl.musl-root", - "mipsel-unknown-linux-musl install directory") -v("musl-root-mips64", "target.mips64-unknown-linux-muslabi64.musl-root", - "mips64-unknown-linux-muslabi64 install directory") -v("musl-root-mips64el", "target.mips64el-unknown-linux-muslabi64.musl-root", - "mips64el-unknown-linux-muslabi64 install directory") -v("musl-root-riscv32gc", "target.riscv32gc-unknown-linux-musl.musl-root", - "riscv32gc-unknown-linux-musl install directory") -v("musl-root-riscv64gc", "target.riscv64gc-unknown-linux-musl.musl-root", - "riscv64gc-unknown-linux-musl install directory") -v("musl-root-loongarch64", "target.loongarch64-unknown-linux-musl.musl-root", - "loongarch64-unknown-linux-musl install directory") -v("qemu-armhf-rootfs", "target.arm-unknown-linux-gnueabihf.qemu-rootfs", - "rootfs in qemu testing, you probably don't want to use this") -v("qemu-aarch64-rootfs", "target.aarch64-unknown-linux-gnu.qemu-rootfs", - "rootfs in qemu testing, you probably don't want to use this") -v("qemu-riscv64-rootfs", "target.riscv64gc-unknown-linux-gnu.qemu-rootfs", - "rootfs in qemu testing, you probably don't want to use this") -v("experimental-targets", "llvm.experimental-targets", - "experimental LLVM targets to build") +v( + "musl-root", + "target.x86_64-unknown-linux-musl.musl-root", + "MUSL root installation directory (deprecated)", +) +v( + "musl-root-x86_64", + "target.x86_64-unknown-linux-musl.musl-root", + "x86_64-unknown-linux-musl install directory", +) +v( + "musl-root-i586", + "target.i586-unknown-linux-musl.musl-root", + "i586-unknown-linux-musl install directory", +) +v( + "musl-root-i686", + "target.i686-unknown-linux-musl.musl-root", + "i686-unknown-linux-musl install directory", +) +v( + "musl-root-arm", + "target.arm-unknown-linux-musleabi.musl-root", + "arm-unknown-linux-musleabi install directory", +) +v( + "musl-root-armhf", + "target.arm-unknown-linux-musleabihf.musl-root", + "arm-unknown-linux-musleabihf install directory", +) +v( + "musl-root-armv5te", + "target.armv5te-unknown-linux-musleabi.musl-root", + "armv5te-unknown-linux-musleabi install directory", +) +v( + "musl-root-armv7", + "target.armv7-unknown-linux-musleabi.musl-root", + "armv7-unknown-linux-musleabi install directory", +) +v( + "musl-root-armv7hf", + "target.armv7-unknown-linux-musleabihf.musl-root", + "armv7-unknown-linux-musleabihf install directory", +) +v( + "musl-root-aarch64", + "target.aarch64-unknown-linux-musl.musl-root", + "aarch64-unknown-linux-musl install directory", +) +v( + "musl-root-mips", + "target.mips-unknown-linux-musl.musl-root", + "mips-unknown-linux-musl install directory", +) +v( + "musl-root-mipsel", + "target.mipsel-unknown-linux-musl.musl-root", + "mipsel-unknown-linux-musl install directory", +) +v( + "musl-root-mips64", + "target.mips64-unknown-linux-muslabi64.musl-root", + "mips64-unknown-linux-muslabi64 install directory", +) +v( + "musl-root-mips64el", + "target.mips64el-unknown-linux-muslabi64.musl-root", + "mips64el-unknown-linux-muslabi64 install directory", +) +v( + "musl-root-riscv32gc", + "target.riscv32gc-unknown-linux-musl.musl-root", + "riscv32gc-unknown-linux-musl install directory", +) +v( + "musl-root-riscv64gc", + "target.riscv64gc-unknown-linux-musl.musl-root", + "riscv64gc-unknown-linux-musl install directory", +) +v( + "musl-root-loongarch64", + "target.loongarch64-unknown-linux-musl.musl-root", + "loongarch64-unknown-linux-musl install directory", +) +v( + "qemu-armhf-rootfs", + "target.arm-unknown-linux-gnueabihf.qemu-rootfs", + "rootfs in qemu testing, you probably don't want to use this", +) +v( + "qemu-aarch64-rootfs", + "target.aarch64-unknown-linux-gnu.qemu-rootfs", + "rootfs in qemu testing, you probably don't want to use this", +) +v( + "qemu-riscv64-rootfs", + "target.riscv64gc-unknown-linux-gnu.qemu-rootfs", + "rootfs in qemu testing, you probably don't want to use this", +) +v( + "experimental-targets", + "llvm.experimental-targets", + "experimental LLVM targets to build", +) v("release-channel", "rust.channel", "the name of the release channel to build") -v("release-description", "rust.description", "optional descriptive string for version output") +v( + "release-description", + "rust.description", + "optional descriptive string for version output", +) v("dist-compression-formats", None, "List of compression formats to use") # Used on systems where "cc" is unavailable @@ -154,7 +294,11 @@ v("default-linker", "rust.default-linker", "the default linker") # Many of these are saved below during the "writing configuration" step # (others are conditionally saved). o("manage-submodules", "build.submodules", "let the build manage the git submodules") -o("full-bootstrap", "build.full-bootstrap", "build three compilers instead of two (not recommended except for testing reproducible builds)") +o( + "full-bootstrap", + "build.full-bootstrap", + "build three compilers instead of two (not recommended except for testing reproducible builds)", +) o("extended", "build.extended", "build an extended rust tool set") v("bootstrap-cache-path", None, "use provided path for the bootstrap cache") @@ -165,8 +309,16 @@ v("host", None, "List of GNUs ./configure syntax LLVM host triples") v("target", None, "List of GNUs ./configure syntax LLVM target triples") # Options specific to this configure script -o("option-checking", None, "complain about unrecognized options in this configure script") -o("verbose-configure", None, "don't truncate options when printing them in this configure script") +o( + "option-checking", + None, + "complain about unrecognized options in this configure script", +) +o( + "verbose-configure", + None, + "don't truncate options when printing them in this configure script", +) v("set", None, "set arbitrary key/value pairs in TOML configuration") @@ -178,39 +330,42 @@ def err(msg): print("\nconfigure: ERROR: " + msg + "\n") sys.exit(1) + def is_value_list(key): for option in options: - if option.name == key and option.desc.startswith('List of'): + if option.name == key and option.desc.startswith("List of"): return True return False -if '--help' in sys.argv or '-h' in sys.argv: - print('Usage: ./configure [options]') - print('') - print('Options') + +if "--help" in sys.argv or "-h" in sys.argv: + print("Usage: ./configure [options]") + print("") + print("Options") for option in options: - if 'android' in option.name: + if "android" in option.name: # no one needs to know about these obscure options continue if option.value: - print('\t{:30} {}'.format('--{}=VAL'.format(option.name), option.desc)) + print("\t{:30} {}".format("--{}=VAL".format(option.name), option.desc)) else: - print('\t--enable-{:25} OR --disable-{}'.format(option.name, option.name)) - print('\t\t' + option.desc) - print('') - print('This configure script is a thin configuration shim over the true') - print('configuration system, `config.toml`. You can explore the comments') - print('in `config.example.toml` next to this configure script to see') - print('more information about what each option is. Additionally you can') - print('pass `--set` as an argument to set arbitrary key/value pairs') - print('in the TOML configuration if desired') - print('') - print('Also note that all options which take `--enable` can similarly') - print('be passed with `--disable-foo` to forcibly disable the option') + print("\t--enable-{:25} OR --disable-{}".format(option.name, option.name)) + print("\t\t" + option.desc) + print("") + print("This configure script is a thin configuration shim over the true") + print("configuration system, `config.toml`. You can explore the comments") + print("in `config.example.toml` next to this configure script to see") + print("more information about what each option is. Additionally you can") + print("pass `--set` as an argument to set arbitrary key/value pairs") + print("in the TOML configuration if desired") + print("") + print("Also note that all options which take `--enable` can similarly") + print("be passed with `--disable-foo` to forcibly disable the option") sys.exit(0) VERBOSE = False + # Parse all command line arguments into one of these three lists, handling # boolean and value-based options separately def parse_args(args): @@ -222,7 +377,7 @@ def parse_args(args): while i < len(args): arg = args[i] i += 1 - if not arg.startswith('--'): + if not arg.startswith("--"): unknown_args.append(arg) continue @@ -230,7 +385,7 @@ def parse_args(args): for option in options: value = None if option.value: - keyval = arg[2:].split('=', 1) + keyval = arg[2:].split("=", 1) key = keyval[0] if option.name != key: continue @@ -244,9 +399,9 @@ def parse_args(args): need_value_args.append(arg) continue else: - if arg[2:] == 'enable-' + option.name: + if arg[2:] == "enable-" + option.name: value = True - elif arg[2:] == 'disable-' + option.name: + elif arg[2:] == "disable-" + option.name: value = False else: continue @@ -263,8 +418,9 @@ def parse_args(args): # NOTE: here and a few other places, we use [-1] to apply the *last* value # passed. But if option-checking is enabled, then the known_args loop will # also assert that options are only passed once. - option_checking = ('option-checking' not in known_args - or known_args['option-checking'][-1][1]) + option_checking = ( + "option-checking" not in known_args or known_args["option-checking"][-1][1] + ) if option_checking: if len(unknown_args) > 0: err("Option '" + unknown_args[0] + "' is not recognized") @@ -272,18 +428,18 @@ def parse_args(args): err("Option '{0}' needs a value ({0}=val)".format(need_value_args[0])) global VERBOSE - VERBOSE = 'verbose-configure' in known_args + VERBOSE = "verbose-configure" in known_args config = {} - set('build.configure-args', args, config) + set("build.configure-args", args, config) apply_args(known_args, option_checking, config) return parse_example_config(known_args, config) def build(known_args): - if 'build' in known_args: - return known_args['build'][-1][1] + if "build" in known_args: + return known_args["build"][-1][1] return bootstrap.default_build_triple(verbose=False) @@ -291,7 +447,7 @@ def set(key, value, config): if isinstance(value, list): # Remove empty values, which value.split(',') tends to generate and # replace single quotes for double quotes to ensure correct parsing. - value = [v.replace('\'', '"') for v in value if v] + value = [v.replace("'", '"') for v in value if v] s = "{:20} := {}".format(key, value) if len(s) < 70 or VERBOSE: @@ -310,7 +466,7 @@ def set(key, value, config): for i, part in enumerate(parts): if i == len(parts) - 1: if is_value_list(part) and isinstance(value, str): - value = value.split(',') + value = value.split(",") arr[part] = value else: if part not in arr: @@ -321,9 +477,9 @@ def set(key, value, config): def apply_args(known_args, option_checking, config): for key in known_args: # The `set` option is special and can be passed a bunch of times - if key == 'set': + if key == "set": for _option, value in known_args[key]: - keyval = value.split('=', 1) + keyval = value.split("=", 1) if len(keyval) == 1 or keyval[1] == "true": value = True elif keyval[1] == "false": @@ -348,50 +504,55 @@ def apply_args(known_args, option_checking, config): # that here. build_triple = build(known_args) - if option.name == 'sccache': - set('llvm.ccache', 'sccache', config) - elif option.name == 'local-rust': - for path in os.environ['PATH'].split(os.pathsep): - if os.path.exists(path + '/rustc'): - set('build.rustc', path + '/rustc', config) + if option.name == "sccache": + set("llvm.ccache", "sccache", config) + elif option.name == "local-rust": + for path in os.environ["PATH"].split(os.pathsep): + if os.path.exists(path + "/rustc"): + set("build.rustc", path + "/rustc", config) break - for path in os.environ['PATH'].split(os.pathsep): - if os.path.exists(path + '/cargo'): - set('build.cargo', path + '/cargo', config) + for path in os.environ["PATH"].split(os.pathsep): + if os.path.exists(path + "/cargo"): + set("build.cargo", path + "/cargo", config) break - elif option.name == 'local-rust-root': - set('build.rustc', value + '/bin/rustc', config) - set('build.cargo', value + '/bin/cargo', config) - elif option.name == 'llvm-root': - set('target.{}.llvm-config'.format(build_triple), value + '/bin/llvm-config', config) - elif option.name == 'llvm-config': - set('target.{}.llvm-config'.format(build_triple), value, config) - elif option.name == 'llvm-filecheck': - set('target.{}.llvm-filecheck'.format(build_triple), value, config) - elif option.name == 'tools': - set('build.tools', value.split(','), config) - elif option.name == 'bootstrap-cache-path': - set('build.bootstrap-cache-path', value, config) - elif option.name == 'codegen-backends': - set('rust.codegen-backends', value.split(','), config) - elif option.name == 'host': - set('build.host', value.split(','), config) - elif option.name == 'target': - set('build.target', value.split(','), config) - elif option.name == 'full-tools': - set('rust.codegen-backends', ['llvm'], config) - set('rust.lld', True, config) - set('rust.llvm-tools', True, config) - set('rust.llvm-bitcode-linker', True, config) - set('build.extended', True, config) - elif option.name in ['option-checking', 'verbose-configure']: + elif option.name == "local-rust-root": + set("build.rustc", value + "/bin/rustc", config) + set("build.cargo", value + "/bin/cargo", config) + elif option.name == "llvm-root": + set( + "target.{}.llvm-config".format(build_triple), + value + "/bin/llvm-config", + config, + ) + elif option.name == "llvm-config": + set("target.{}.llvm-config".format(build_triple), value, config) + elif option.name == "llvm-filecheck": + set("target.{}.llvm-filecheck".format(build_triple), value, config) + elif option.name == "tools": + set("build.tools", value.split(","), config) + elif option.name == "bootstrap-cache-path": + set("build.bootstrap-cache-path", value, config) + elif option.name == "codegen-backends": + set("rust.codegen-backends", value.split(","), config) + elif option.name == "host": + set("build.host", value.split(","), config) + elif option.name == "target": + set("build.target", value.split(","), config) + elif option.name == "full-tools": + set("rust.codegen-backends", ["llvm"], config) + set("rust.lld", True, config) + set("rust.llvm-tools", True, config) + set("rust.llvm-bitcode-linker", True, config) + set("build.extended", True, config) + elif option.name in ["option-checking", "verbose-configure"]: # this was handled above pass - elif option.name == 'dist-compression-formats': - set('dist.compression-formats', value.split(','), config) + elif option.name == "dist-compression-formats": + set("dist.compression-formats", value.split(","), config) else: raise RuntimeError("unhandled option {}".format(option.name)) + # "Parse" the `config.example.toml` file into the various sections, and we'll # use this as a template of a `config.toml` to write out which preserves # all the various comments and whatnot. @@ -406,20 +567,22 @@ def parse_example_config(known_args, config): targets = {} top_level_keys = [] - with open(rust_dir + '/config.example.toml') as example_config: + with open(rust_dir + "/config.example.toml") as example_config: example_lines = example_config.read().split("\n") for line in example_lines: if cur_section is None: - if line.count('=') == 1: - top_level_key = line.split('=')[0] - top_level_key = top_level_key.strip(' #') + if line.count("=") == 1: + top_level_key = line.split("=")[0] + top_level_key = top_level_key.strip(" #") top_level_keys.append(top_level_key) - if line.startswith('['): + if line.startswith("["): cur_section = line[1:-1] - if cur_section.startswith('target'): - cur_section = 'target' - elif '.' in cur_section: - raise RuntimeError("don't know how to deal with section: {}".format(cur_section)) + if cur_section.startswith("target"): + cur_section = "target" + elif "." in cur_section: + raise RuntimeError( + "don't know how to deal with section: {}".format(cur_section) + ) sections[cur_section] = [line] section_order.append(cur_section) else: @@ -428,22 +591,25 @@ def parse_example_config(known_args, config): # Fill out the `targets` array by giving all configured targets a copy of the # `target` section we just loaded from the example config configured_targets = [build(known_args)] - if 'build' in config: - if 'host' in config['build']: - configured_targets += config['build']['host'] - if 'target' in config['build']: - configured_targets += config['build']['target'] - if 'target' in config: - for target in config['target']: + if "build" in config: + if "host" in config["build"]: + configured_targets += config["build"]["host"] + if "target" in config["build"]: + configured_targets += config["build"]["target"] + if "target" in config: + for target in config["target"]: configured_targets.append(target) for target in configured_targets: - targets[target] = sections['target'][:] + targets[target] = sections["target"][:] # For `.` to be valid TOML, it needs to be quoted. But `bootstrap.py` doesn't use a proper TOML parser and fails to parse the target. # Avoid using quotes unless it's necessary. - targets[target][0] = targets[target][0].replace("x86_64-unknown-linux-gnu", "'{}'".format(target) if "." in target else target) + targets[target][0] = targets[target][0].replace( + "x86_64-unknown-linux-gnu", + "'{}'".format(target) if "." in target else target, + ) - if 'profile' not in config: - set('profile', 'dist', config) + if "profile" not in config: + set("profile", "dist", config) configure_file(sections, top_level_keys, targets, config) return section_order, sections, targets @@ -467,7 +633,7 @@ def to_toml(value): else: return "false" elif isinstance(value, list): - return '[' + ', '.join(map(to_toml, value)) + ']' + return "[" + ", ".join(map(to_toml, value)) + "]" elif isinstance(value, str): # Don't put quotes around numeric values if is_number(value): @@ -475,9 +641,18 @@ def to_toml(value): else: return "'" + value + "'" elif isinstance(value, dict): - return "{" + ", ".join(map(lambda a: "{} = {}".format(to_toml(a[0]), to_toml(a[1])), value.items())) + "}" + return ( + "{" + + ", ".join( + map( + lambda a: "{} = {}".format(to_toml(a[0]), to_toml(a[1])), + value.items(), + ) + ) + + "}" + ) else: - raise RuntimeError('no toml') + raise RuntimeError("no toml") def configure_section(lines, config): @@ -485,7 +660,7 @@ def configure_section(lines, config): value = config[key] found = False for i, line in enumerate(lines): - if not line.startswith('#' + key + ' = '): + if not line.startswith("#" + key + " = "): continue found = True lines[i] = "{} = {}".format(key, to_toml(value)) @@ -501,7 +676,9 @@ def configure_section(lines, config): def configure_top_level_key(lines, top_level_key, value): for i, line in enumerate(lines): - if line.startswith('#' + top_level_key + ' = ') or line.startswith(top_level_key + ' = '): + if line.startswith("#" + top_level_key + " = ") or line.startswith( + top_level_key + " = " + ): lines[i] = "{} = {}".format(top_level_key, to_toml(value)) return @@ -512,11 +689,13 @@ def configure_top_level_key(lines, top_level_key, value): def configure_file(sections, top_level_keys, targets, config): for section_key, section_config in config.items(): if section_key not in sections and section_key not in top_level_keys: - raise RuntimeError("config key {} not in sections or top_level_keys".format(section_key)) + raise RuntimeError( + "config key {} not in sections or top_level_keys".format(section_key) + ) if section_key in top_level_keys: configure_top_level_key(sections[None], section_key, section_config) - elif section_key == 'target': + elif section_key == "target": for target in section_config: configure_section(targets[target], section_config[target]) else: @@ -536,18 +715,19 @@ def write_uncommented(target, f): block = [] is_comment = True continue - is_comment = is_comment and line.startswith('#') + is_comment = is_comment and line.startswith("#") return f def write_config_toml(writer, section_order, targets, sections): for section in section_order: - if section == 'target': + if section == "target": for target in targets: writer = write_uncommented(targets[target], writer) else: writer = write_uncommented(sections[section], writer) + def quit_if_file_exists(file): if os.path.isfile(file): msg = "Existing '{}' detected. Exiting".format(file) @@ -559,9 +739,10 @@ def quit_if_file_exists(file): err(msg) + if __name__ == "__main__": # If 'config.toml' already exists, exit the script at this point - quit_if_file_exists('config.toml') + quit_if_file_exists("config.toml") if "GITHUB_ACTIONS" in os.environ: print("::group::Configure the build") @@ -575,13 +756,13 @@ if __name__ == "__main__": # order that we read it in. p("") p("writing `config.toml` in current directory") - with bootstrap.output('config.toml') as f: + with bootstrap.output("config.toml") as f: write_config_toml(f, section_order, targets, sections) - with bootstrap.output('Makefile') as f: - contents = os.path.join(rust_dir, 'src', 'bootstrap', 'mk', 'Makefile.in') + with bootstrap.output("Makefile") as f: + contents = os.path.join(rust_dir, "src", "bootstrap", "mk", "Makefile.in") contents = open(contents).read() - contents = contents.replace("$(CFG_SRC_DIR)", rust_dir + '/') + contents = contents.replace("$(CFG_SRC_DIR)", rust_dir + "/") contents = contents.replace("$(CFG_PYTHON)", sys.executable) f.write(contents) diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 161157acffe..30fdea7e19e 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -1070,23 +1070,33 @@ impl Step for Tidy { } if builder.config.channel == "dev" || builder.config.channel == "nightly" { - builder.info("fmt check"); - if builder.initial_rustfmt().is_none() { - let inferred_rustfmt_dir = builder.initial_sysroot.join("bin"); - eprintln!( - "\ + if !builder.config.json_output { + builder.info("fmt check"); + if builder.initial_rustfmt().is_none() { + let inferred_rustfmt_dir = builder.initial_sysroot.join("bin"); + eprintln!( + "\ ERROR: no `rustfmt` binary found in {PATH} INFO: `rust.channel` is currently set to \"{CHAN}\" HELP: if you are testing a beta branch, set `rust.channel` to \"beta\" in the `config.toml` file HELP: to skip test's attempt to check tidiness, pass `--skip src/tools/tidy` to `x.py test`", - PATH = inferred_rustfmt_dir.display(), - CHAN = builder.config.channel, + PATH = inferred_rustfmt_dir.display(), + CHAN = builder.config.channel, + ); + crate::exit!(1); + } + let all = false; + crate::core::build_steps::format::format( + builder, + !builder.config.cmd.bless(), + all, + &[], + ); + } else { + eprintln!( + "WARNING: `--json-output` is not supported on rustfmt, formatting will be skipped" ); - crate::exit!(1); } - let all = false; - crate::core::build_steps::format::format(builder, !builder.config.cmd.bless(), all, &[ - ]); } builder.info("tidy check"); @@ -2624,6 +2634,11 @@ fn prepare_cargo_test( if builder.kind == Kind::Test && !builder.fail_fast { cargo.arg("--no-fail-fast"); } + + if builder.config.json_output { + cargo.arg("--message-format=json"); + } + match builder.doc_tests { DocTests::Only => { cargo.arg("--doc"); diff --git a/src/ci/cpu-usage-over-time.py b/src/ci/cpu-usage-over-time.py index adfd895ead0..3d9dc86734f 100755 --- a/src/ci/cpu-usage-over-time.py +++ b/src/ci/cpu-usage-over-time.py @@ -40,12 +40,13 @@ import time # Python 3.3 changed the value of `sys.platform` on Linux from "linux2" to just # "linux". We check here with `.startswith` to keep compatibility with older # Python versions (especially Python 2.7). -if sys.platform.startswith('linux'): +if sys.platform.startswith("linux"): + class State: def __init__(self): - with open('/proc/stat', 'r') as file: + with open("/proc/stat", "r") as file: data = file.readline().split() - if data[0] != 'cpu': + if data[0] != "cpu": raise Exception('did not start with "cpu"') self.user = int(data[1]) self.nice = int(data[2]) @@ -69,10 +70,21 @@ if sys.platform.startswith('linux'): steal = self.steal - prev.steal guest = self.guest - prev.guest guest_nice = self.guest_nice - prev.guest_nice - total = user + nice + system + idle + iowait + irq + softirq + steal + guest + guest_nice + total = ( + user + + nice + + system + + idle + + iowait + + irq + + softirq + + steal + + guest + + guest_nice + ) return float(idle) / float(total) * 100 -elif sys.platform == 'win32': +elif sys.platform == "win32": from ctypes.wintypes import DWORD from ctypes import Structure, windll, WinError, GetLastError, byref @@ -104,9 +116,10 @@ elif sys.platform == 'win32': kernel = self.kernel - prev.kernel return float(idle) / float(user + kernel) * 100 -elif sys.platform == 'darwin': +elif sys.platform == "darwin": from ctypes import * - libc = cdll.LoadLibrary('/usr/lib/libc.dylib') + + libc = cdll.LoadLibrary("/usr/lib/libc.dylib") class host_cpu_load_info_data_t(Structure): _fields_ = [("cpu_ticks", c_uint * 4)] @@ -116,7 +129,7 @@ elif sys.platform == 'darwin': c_uint, c_int, POINTER(host_cpu_load_info_data_t), - POINTER(c_int) + POINTER(c_int), ] host_statistics.restype = c_int @@ -124,13 +137,14 @@ elif sys.platform == 'darwin': CPU_STATE_SYSTEM = 1 CPU_STATE_IDLE = 2 CPU_STATE_NICE = 3 + class State: def __init__(self): stats = host_cpu_load_info_data_t() - count = c_int(4) # HOST_CPU_LOAD_INFO_COUNT + count = c_int(4) # HOST_CPU_LOAD_INFO_COUNT err = libc.host_statistics( libc.mach_host_self(), - c_int(3), # HOST_CPU_LOAD_INFO + c_int(3), # HOST_CPU_LOAD_INFO byref(stats), byref(count), ) @@ -148,7 +162,7 @@ elif sys.platform == 'darwin': return float(idle) / float(user + system + idle + nice) * 100.0 else: - print('unknown platform', sys.platform) + print("unknown platform", sys.platform) sys.exit(1) cur_state = State() diff --git a/src/ci/docker/host-x86_64/i686-gnu-nopt/Dockerfile b/src/ci/docker/host-x86_64/i686-gnu-nopt/Dockerfile index e2b66c2cff1..e2736720607 100644 --- a/src/ci/docker/host-x86_64/i686-gnu-nopt/Dockerfile +++ b/src/ci/docker/host-x86_64/i686-gnu-nopt/Dockerfile @@ -27,5 +27,5 @@ RUN echo "[rust]" > /config/nopt-std-config.toml RUN echo "optimize = false" >> /config/nopt-std-config.toml ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu --disable-optimize-tests -ENV SCRIPT python3 ../x.py test --stage 0 --config /config/nopt-std-config.toml library/std \ - && python3 ../x.py --stage 2 test +ARG SCRIPT_ARG +ENV SCRIPT=${SCRIPT_ARG} diff --git a/src/ci/docker/host-x86_64/i686-gnu/Dockerfile b/src/ci/docker/host-x86_64/i686-gnu/Dockerfile index 61811c41904..dec25461bb4 100644 --- a/src/ci/docker/host-x86_64/i686-gnu/Dockerfile +++ b/src/ci/docker/host-x86_64/i686-gnu/Dockerfile @@ -24,10 +24,5 @@ COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu -# Skip some tests that are unlikely to be platform specific, to speed up -# this slow job. -ENV SCRIPT python3 ../x.py --stage 2 test \ - --skip src/bootstrap \ - --skip tests/rustdoc-js \ - --skip src/tools/error_index_generator \ - --skip src/tools/linkchecker +ARG SCRIPT_ARG +ENV SCRIPT=${SCRIPT_ARG} diff --git a/src/ci/docker/host-x86_64/test-various/uefi_qemu_test/run.py b/src/ci/docker/host-x86_64/test-various/uefi_qemu_test/run.py index 3577643ca55..4f877389fbc 100755 --- a/src/ci/docker/host-x86_64/test-various/uefi_qemu_test/run.py +++ b/src/ci/docker/host-x86_64/test-various/uefi_qemu_test/run.py @@ -8,78 +8,79 @@ import tempfile from pathlib import Path -TARGET_AARCH64 = 'aarch64-unknown-uefi' -TARGET_I686 = 'i686-unknown-uefi' -TARGET_X86_64 = 'x86_64-unknown-uefi' +TARGET_AARCH64 = "aarch64-unknown-uefi" +TARGET_I686 = "i686-unknown-uefi" +TARGET_X86_64 = "x86_64-unknown-uefi" + def run(*cmd, capture=False, check=True, env=None, timeout=None): """Print and run a command, optionally capturing the output.""" cmd = [str(p) for p in cmd] - print(' '.join(cmd)) - return subprocess.run(cmd, - capture_output=capture, - check=check, - env=env, - text=True, - timeout=timeout) + print(" ".join(cmd)) + return subprocess.run( + cmd, capture_output=capture, check=check, env=env, text=True, timeout=timeout + ) + def build_and_run(tmp_dir, target): if target == TARGET_AARCH64: - boot_file_name = 'bootaa64.efi' - ovmf_dir = Path('/usr/share/AAVMF') - ovmf_code = 'AAVMF_CODE.fd' - ovmf_vars = 'AAVMF_VARS.fd' - qemu = 'qemu-system-aarch64' - machine = 'virt' - cpu = 'cortex-a72' + boot_file_name = "bootaa64.efi" + ovmf_dir = Path("/usr/share/AAVMF") + ovmf_code = "AAVMF_CODE.fd" + ovmf_vars = "AAVMF_VARS.fd" + qemu = "qemu-system-aarch64" + machine = "virt" + cpu = "cortex-a72" elif target == TARGET_I686: - boot_file_name = 'bootia32.efi' - ovmf_dir = Path('/usr/share/OVMF') - ovmf_code = 'OVMF32_CODE_4M.secboot.fd' - ovmf_vars = 'OVMF32_VARS_4M.fd' + boot_file_name = "bootia32.efi" + ovmf_dir = Path("/usr/share/OVMF") + ovmf_code = "OVMF32_CODE_4M.secboot.fd" + ovmf_vars = "OVMF32_VARS_4M.fd" # The i686 target intentionally uses 64-bit qemu; the important # difference is that the OVMF code provides a 32-bit environment. - qemu = 'qemu-system-x86_64' - machine = 'q35' - cpu = 'qemu64' + qemu = "qemu-system-x86_64" + machine = "q35" + cpu = "qemu64" elif target == TARGET_X86_64: - boot_file_name = 'bootx64.efi' - ovmf_dir = Path('/usr/share/OVMF') - ovmf_code = 'OVMF_CODE.fd' - ovmf_vars = 'OVMF_VARS.fd' - qemu = 'qemu-system-x86_64' - machine = 'q35' - cpu = 'qemu64' + boot_file_name = "bootx64.efi" + ovmf_dir = Path("/usr/share/OVMF") + ovmf_code = "OVMF_CODE.fd" + ovmf_vars = "OVMF_VARS.fd" + qemu = "qemu-system-x86_64" + machine = "q35" + cpu = "qemu64" else: - raise KeyError('invalid target') + raise KeyError("invalid target") - host_artifacts = Path('/checkout/obj/build/x86_64-unknown-linux-gnu') - stage0 = host_artifacts / 'stage0/bin' - stage2 = host_artifacts / 'stage2/bin' + host_artifacts = Path("/checkout/obj/build/x86_64-unknown-linux-gnu") + stage0 = host_artifacts / "stage0/bin" + stage2 = host_artifacts / "stage2/bin" env = dict(os.environ) - env['PATH'] = '{}:{}:{}'.format(stage2, stage0, env['PATH']) + env["PATH"] = "{}:{}:{}".format(stage2, stage0, env["PATH"]) # Copy the test create into `tmp_dir`. - test_crate = Path(tmp_dir) / 'uefi_qemu_test' - shutil.copytree('/uefi_qemu_test', test_crate) + test_crate = Path(tmp_dir) / "uefi_qemu_test" + shutil.copytree("/uefi_qemu_test", test_crate) # Build the UEFI executable. - run('cargo', - 'build', - '--manifest-path', - test_crate / 'Cargo.toml', - '--target', + run( + "cargo", + "build", + "--manifest-path", + test_crate / "Cargo.toml", + "--target", target, - env=env) + env=env, + ) # Create a mock EFI System Partition in a subdirectory. - esp = test_crate / 'esp' - boot = esp / 'efi/boot' + esp = test_crate / "esp" + boot = esp / "efi/boot" os.makedirs(boot, exist_ok=True) # Copy the executable into the ESP. - src_exe_path = test_crate / 'target' / target / 'debug/uefi_qemu_test.efi' + src_exe_path = test_crate / "target" / target / "debug/uefi_qemu_test.efi" shutil.copy(src_exe_path, boot / boot_file_name) print(src_exe_path, boot / boot_file_name) @@ -89,37 +90,39 @@ def build_and_run(tmp_dir, target): # Make a writable copy of the vars file. aarch64 doesn't boot # correctly with read-only vars. - ovmf_rw_vars = Path(tmp_dir) / 'vars.fd' + ovmf_rw_vars = Path(tmp_dir) / "vars.fd" shutil.copy(ovmf_vars, ovmf_rw_vars) # Run the executable in QEMU and capture the output. - output = run(qemu, - '-machine', - machine, - '-cpu', - cpu, - '-display', - 'none', - '-serial', - 'stdio', - '-drive', - f'if=pflash,format=raw,readonly=on,file={ovmf_code}', - '-drive', - f'if=pflash,format=raw,readonly=off,file={ovmf_rw_vars}', - '-drive', - f'format=raw,file=fat:rw:{esp}', - capture=True, - check=True, - # Set a timeout to kill the VM in case something goes wrong. - timeout=60).stdout - - if 'Hello World!' in output: - print('VM produced expected output') + output = run( + qemu, + "-machine", + machine, + "-cpu", + cpu, + "-display", + "none", + "-serial", + "stdio", + "-drive", + f"if=pflash,format=raw,readonly=on,file={ovmf_code}", + "-drive", + f"if=pflash,format=raw,readonly=off,file={ovmf_rw_vars}", + "-drive", + f"format=raw,file=fat:rw:{esp}", + capture=True, + check=True, + # Set a timeout to kill the VM in case something goes wrong. + timeout=60, + ).stdout + + if "Hello World!" in output: + print("VM produced expected output") else: - print('unexpected VM output:') - print('---start---') + print("unexpected VM output:") + print("---start---") print(output) - print('---end---') + print("---end---") sys.exit(1) diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version index 6b2d58c8ef3..7211b157c69 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version +++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version @@ -1 +1 @@ -0.18.1 \ No newline at end of file +0.18.2 \ No newline at end of file diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh index d554186df4c..a0adf60b6b2 100755 --- a/src/ci/docker/run.sh +++ b/src/ci/docker/run.sh @@ -105,6 +105,23 @@ if [ -f "$docker_dir/$image/Dockerfile" ]; then # It seems that it cannot be the same as $IMAGE_TAG, otherwise it overwrites the cache CACHE_IMAGE_TAG=${REGISTRY}/${REGISTRY_USERNAME}/rust-ci-cache:${cksum} + # Docker build arguments. + build_args=( + "build" + "--rm" + "-t" "rust-ci" + "-f" "$dockerfile" + "$context" + ) + + # If the environment variable DOCKER_SCRIPT is defined, + # set the build argument SCRIPT_ARG to DOCKER_SCRIPT. + # In this way, we run the script defined in CI, + # instead of the one defined in the Dockerfile. + if [ -n "${DOCKER_SCRIPT+x}" ]; then + build_args+=("--build-arg" "SCRIPT_ARG=${DOCKER_SCRIPT}") + fi + # On non-CI jobs, we try to download a pre-built image from the rust-lang-ci # ghcr.io registry. If it is not possible, we fall back to building the image # locally. @@ -115,7 +132,7 @@ if [ -f "$docker_dir/$image/Dockerfile" ]; then docker tag "${IMAGE_TAG}" rust-ci else echo "Building local Docker image" - retry docker build --rm -t rust-ci -f "$dockerfile" "$context" + retry docker "${build_args[@]}" fi # On PR CI jobs, we don't have permissions to write to the registry cache, # but we can still read from it. @@ -127,13 +144,9 @@ if [ -f "$docker_dir/$image/Dockerfile" ]; then # Build the image using registry caching backend retry docker \ buildx \ - build \ - --rm \ - -t rust-ci \ - -f "$dockerfile" \ + "${build_args[@]}" \ --cache-from type=registry,ref=${CACHE_IMAGE_TAG} \ - --output=type=docker \ - "$context" + --output=type=docker # On auto/try builds, we can also write to the cache. else # Log into the Docker registry, so that we can read/write cache and the final image @@ -147,14 +160,10 @@ if [ -f "$docker_dir/$image/Dockerfile" ]; then # Build the image using registry caching backend retry docker \ buildx \ - build \ - --rm \ - -t rust-ci \ - -f "$dockerfile" \ + "${build_args[@]}" \ --cache-from type=registry,ref=${CACHE_IMAGE_TAG} \ --cache-to type=registry,ref=${CACHE_IMAGE_TAG},compression=zstd \ - --output=type=docker \ - "$context" + --output=type=docker # Print images for debugging purposes docker images diff --git a/src/ci/docker/scripts/android-sdk-manager.py b/src/ci/docker/scripts/android-sdk-manager.py index 66cba58427b..6356f15a886 100755 --- a/src/ci/docker/scripts/android-sdk-manager.py +++ b/src/ci/docker/scripts/android-sdk-manager.py @@ -35,6 +35,7 @@ MIRROR_BUCKET = "rust-lang-ci-mirrors" MIRROR_BUCKET_REGION = "us-west-1" MIRROR_BASE_DIR = "rustc/android/" + class Package: def __init__(self, path, url, sha1, deps=None): if deps is None: @@ -53,18 +54,25 @@ class Package: sha1 = hashlib.sha1(f.read()).hexdigest() if sha1 != self.sha1: raise RuntimeError( - "hash mismatch for package " + self.path + ": " + - sha1 + " vs " + self.sha1 + " (known good)" + "hash mismatch for package " + + self.path + + ": " + + sha1 + + " vs " + + self.sha1 + + " (known good)" ) return file def __repr__(self): - return "<Package "+self.path+" at "+self.url+" (sha1="+self.sha1+")" + return "<Package " + self.path + " at " + self.url + " (sha1=" + self.sha1 + ")" + def fetch_url(url): page = urllib.request.urlopen(url) return page.read() + def fetch_repository(base, repo_url): packages = {} root = ET.fromstring(fetch_url(base + repo_url)) @@ -92,12 +100,14 @@ def fetch_repository(base, repo_url): return packages + def fetch_repositories(): packages = {} for repo in REPOSITORIES: packages.update(fetch_repository(BASE_REPOSITORY, repo)) return packages + class Lockfile: def __init__(self, path): self.path = path @@ -123,6 +133,7 @@ class Lockfile: for package in packages: f.write(package.path + " " + package.url + " " + package.sha1 + "\n") + def cli_add_to_lockfile(args): lockfile = Lockfile(args.lockfile) packages = fetch_repositories() @@ -130,28 +141,49 @@ def cli_add_to_lockfile(args): lockfile.add(packages, package) lockfile.save() + def cli_update_mirror(args): lockfile = Lockfile(args.lockfile) for package in lockfile.packages.values(): path = package.download(BASE_REPOSITORY) - subprocess.run([ - "aws", "s3", "mv", path, - "s3://" + MIRROR_BUCKET + "/" + MIRROR_BASE_DIR + package.url, - "--profile=" + args.awscli_profile, - ], check=True) + subprocess.run( + [ + "aws", + "s3", + "mv", + path, + "s3://" + MIRROR_BUCKET + "/" + MIRROR_BASE_DIR + package.url, + "--profile=" + args.awscli_profile, + ], + check=True, + ) + def cli_install(args): lockfile = Lockfile(args.lockfile) for package in lockfile.packages.values(): # Download the file from the mirror into a temp file - url = "https://" + MIRROR_BUCKET + ".s3-" + MIRROR_BUCKET_REGION + \ - ".amazonaws.com/" + MIRROR_BASE_DIR + url = ( + "https://" + + MIRROR_BUCKET + + ".s3-" + + MIRROR_BUCKET_REGION + + ".amazonaws.com/" + + MIRROR_BASE_DIR + ) downloaded = package.download(url) # Extract the file in a temporary directory extract_dir = tempfile.mkdtemp() - subprocess.run([ - "unzip", "-q", downloaded, "-d", extract_dir, - ], check=True) + subprocess.run( + [ + "unzip", + "-q", + downloaded, + "-d", + extract_dir, + ], + check=True, + ) # Figure out the prefix used in the zip subdirs = [d for d in os.listdir(extract_dir) if not d.startswith(".")] if len(subdirs) != 1: @@ -162,6 +194,7 @@ def cli_install(args): os.rename(os.path.join(extract_dir, subdirs[0]), dest) os.unlink(downloaded) + def cli(): parser = argparse.ArgumentParser() subparsers = parser.add_subparsers() @@ -187,5 +220,6 @@ def cli(): exit(1) args.func(args) + if __name__ == "__main__": cli() diff --git a/src/ci/docker/scripts/fuchsia-test-runner.py b/src/ci/docker/scripts/fuchsia-test-runner.py index 77e2741f9ea..4a30de5a263 100755 --- a/src/ci/docker/scripts/fuchsia-test-runner.py +++ b/src/ci/docker/scripts/fuchsia-test-runner.py @@ -588,7 +588,7 @@ class TestEnvironment: "--repo-path", self.repo_dir(), "--repository", - self.TEST_REPO_NAME + self.TEST_REPO_NAME, ], env=ffx_env, stdout_handler=self.subprocess_logger.debug, @@ -619,9 +619,7 @@ class TestEnvironment: # `facet` statement required for TCP testing via # protocol `fuchsia.posix.socket.Provider`. See # https://fuchsia.dev/fuchsia-src/development/testing/components/test_runner_framework?hl=en#legacy_non-hermetic_tests - CML_TEMPLATE: ClassVar[ - str - ] = """ + CML_TEMPLATE: ClassVar[str] = """ {{ program: {{ runner: "elf_test_runner", @@ -994,7 +992,7 @@ class TestEnvironment: "repository", "server", "stop", - self.TEST_REPO_NAME + self.TEST_REPO_NAME, ], env=self.ffx_cmd_env(), stdout_handler=self.subprocess_logger.debug, diff --git a/src/ci/docker/scripts/rfl-build.sh b/src/ci/docker/scripts/rfl-build.sh index f07515f7784..8776e0f0be9 100755 --- a/src/ci/docker/scripts/rfl-build.sh +++ b/src/ci/docker/scripts/rfl-build.sh @@ -2,7 +2,7 @@ set -euo pipefail -LINUX_VERSION=28e848386b92645f93b9f2fdba5882c3ca7fb3e2 +LINUX_VERSION=v6.13-rc1 # Build rustc, rustdoc, cargo, clippy-driver and rustfmt ../x.py build --stage 2 library rustdoc clippy rustfmt @@ -64,7 +64,7 @@ make -C linux LLVM=1 -j$(($(nproc) + 1)) \ BUILD_TARGETS=" samples/rust/rust_minimal.o - samples/rust/rust_print.o + samples/rust/rust_print_main.o drivers/net/phy/ax88796b_rust.o rust/doctests_kernel_generated.o " diff --git a/src/ci/github-actions/calculate-job-matrix.py b/src/ci/github-actions/calculate-job-matrix.py index 7de6d5fcd5f..1f994f0ffd2 100755 --- a/src/ci/github-actions/calculate-job-matrix.py +++ b/src/ci/github-actions/calculate-job-matrix.py @@ -7,6 +7,7 @@ be executed on CI. It reads job definitions from `src/ci/github-actions/jobs.yml` and filters them based on the event that happened on CI. """ + import dataclasses import json import logging @@ -94,7 +95,7 @@ def find_run_type(ctx: GitHubCtx) -> Optional[WorkflowRunType]: try_build = ctx.ref in ( "refs/heads/try", "refs/heads/try-perf", - "refs/heads/automation/bors/try" + "refs/heads/automation/bors/try", ) # Unrolled branch from a rollup for testing perf @@ -135,11 +136,15 @@ def calculate_jobs(run_type: WorkflowRunType, job_data: Dict[str, Any]) -> List[ continue jobs.append(job[0]) if unknown_jobs: - raise Exception(f"Custom job(s) `{unknown_jobs}` not found in auto jobs") + raise Exception( + f"Custom job(s) `{unknown_jobs}` not found in auto jobs" + ) return add_base_env(name_jobs(jobs, "try"), job_data["envs"]["try"]) elif isinstance(run_type, AutoRunType): - return add_base_env(name_jobs(job_data["auto"], "auto"), job_data["envs"]["auto"]) + return add_base_env( + name_jobs(job_data["auto"], "auto"), job_data["envs"]["auto"] + ) return [] @@ -161,7 +166,7 @@ def get_github_ctx() -> GitHubCtx: event_name=event_name, ref=os.environ["GITHUB_REF"], repository=os.environ["GITHUB_REPOSITORY"], - commit_message=commit_message + commit_message=commit_message, ) diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index 2ea37c168dd..288b133f0da 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -58,6 +58,22 @@ envs: NO_DEBUG_ASSERTIONS: 1 NO_OVERFLOW_CHECKS: 1 + # Different set of tests to run tests in parallel in multiple jobs. + stage_2_test_set1: &stage_2_test_set1 + DOCKER_SCRIPT: >- + python3 ../x.py --stage 2 test + --skip compiler + --skip src + + stage_2_test_set2: &stage_2_test_set2 + DOCKER_SCRIPT: >- + python3 ../x.py --stage 2 test + --skip tests + --skip coverage-map + --skip coverage-run + --skip library + --skip tidyselftest + production: &production DEPLOY_BUCKET: rust-lang-ci2 @@ -212,11 +228,42 @@ auto: - image: dist-x86_64-netbsd <<: *job-linux-4c - - image: i686-gnu - <<: *job-linux-8c + # The i686-gnu job is split into multiple jobs to run tests in parallel. + # i686-gnu-1 skips tests that run in i686-gnu-2. + - image: i686-gnu-1 + env: + IMAGE: i686-gnu + <<: *stage_2_test_set1 + <<: *job-linux-4c - - image: i686-gnu-nopt - <<: *job-linux-8c + # Skip tests that run in i686-gnu-1 + - image: i686-gnu-2 + env: + IMAGE: i686-gnu + <<: *stage_2_test_set2 + <<: *job-linux-4c + + # The i686-gnu-nopt job is split into multiple jobs to run tests in parallel. + # i686-gnu-nopt-1 skips tests that run in i686-gnu-nopt-2 + - image: i686-gnu-nopt-1 + env: + IMAGE: i686-gnu-nopt + <<: *stage_2_test_set1 + <<: *job-linux-4c + + # Skip tests that run in i686-gnu-nopt-1 + - image: i686-gnu-nopt-2 + env: + IMAGE: i686-gnu-nopt + DOCKER_SCRIPT: >- + python3 ../x.py test --stage 0 --config /config/nopt-std-config.toml library/std && + python3 ../x.py --stage 2 test + --skip tests + --skip coverage-map + --skip coverage-run + --skip library + --skip tidyselftest + <<: *job-linux-4c - image: mingw-check <<: *job-linux-4c diff --git a/src/ci/scripts/upload-build-metrics.py b/src/ci/scripts/upload-build-metrics.py index a95e0949d70..23061884a39 100644 --- a/src/ci/scripts/upload-build-metrics.py +++ b/src/ci/scripts/upload-build-metrics.py @@ -19,6 +19,7 @@ $ python3 upload-build-metrics.py <path-to-CPU-usage-CSV> `path-to-CPU-usage-CSV` is a path to a CSV generated by the `src/ci/cpu-usage-over-time.py` script. """ + import argparse import csv import os @@ -31,7 +32,7 @@ from typing import List def load_cpu_usage(path: Path) -> List[float]: usage = [] with open(path) as f: - reader = csv.reader(f, delimiter=',') + reader = csv.reader(f, delimiter=",") for row in reader: # The log might contain incomplete rows or some Python exception if len(row) == 2: @@ -50,25 +51,21 @@ def upload_datadog_measure(name: str, value: float): print(f"Metric {name}: {value:.4f}") datadog_cmd = "datadog-ci" - if os.getenv("GITHUB_ACTIONS") is not None and sys.platform.lower().startswith("win"): + if os.getenv("GITHUB_ACTIONS") is not None and sys.platform.lower().startswith( + "win" + ): # Due to weird interaction of MSYS2 and Python, we need to use an absolute path, # and also specify the ".cmd" at the end. See https://github.com/rust-lang/rust/pull/125771. datadog_cmd = "C:\\npm\\prefix\\datadog-ci.cmd" - subprocess.run([ - datadog_cmd, - "measure", - "--level", "job", - "--measures", f"{name}:{value}" - ], - check=False + subprocess.run( + [datadog_cmd, "measure", "--level", "job", "--measures", f"{name}:{value}"], + check=False, ) if __name__ == "__main__": - parser = argparse.ArgumentParser( - prog="DataDog metric uploader" - ) + parser = argparse.ArgumentParser(prog="DataDog metric uploader") parser.add_argument("cpu-usage-history-csv") args = parser.parse_args() diff --git a/src/doc/book b/src/doc/book -Subproject 614c19cb4025636eb2ba68ebb3d44e3bd3a5e6e +Subproject 9900d976bbfecf4e8124da54351a9ad85ee3c7f diff --git a/src/doc/unstable-book/src/compiler-flags/reg-struct-return.md b/src/doc/unstable-book/src/compiler-flags/reg-struct-return.md new file mode 100644 index 00000000000..35b782f38dc --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/reg-struct-return.md @@ -0,0 +1,15 @@ +# `reg-struct-return` + +The tracking issue for this feature is: https://github.com/rust-lang/rust/issues/116973. + +------------------------ + +Option -Zreg-struct-return causes the compiler to return small structs in registers +instead of on the stack for extern "C"-like functions. +It is UNSOUND to link together crates that use different values for this flag. +It is only supported on `x86`. + +It is equivalent to [Clang]'s and [GCC]'s `-freg-struct-return`. + +[Clang]: https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-freg-struct-return +[GCC]: https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html#index-freg-struct-return diff --git a/src/etc/dec2flt_table.py b/src/etc/dec2flt_table.py index 9264a8439bb..791186de9c1 100755 --- a/src/etc/dec2flt_table.py +++ b/src/etc/dec2flt_table.py @@ -13,6 +13,7 @@ i.e., within 0.5 ULP of the true value. Adapted from Daniel Lemire's fast_float ``table_generation.py``, available here: <https://github.com/fastfloat/fast_float/blob/main/script/table_generation.py>. """ + from __future__ import print_function from math import ceil, floor, log from collections import deque @@ -34,6 +35,7 @@ STATIC_WARNING = """ // the final binary. """ + def main(): min_exp = minimum_exponent(10) max_exp = maximum_exponent(10) @@ -41,10 +43,10 @@ def main(): print(HEADER.strip()) print() - print('pub const SMALLEST_POWER_OF_FIVE: i32 = {};'.format(min_exp)) - print('pub const LARGEST_POWER_OF_FIVE: i32 = {};'.format(max_exp)) - print('pub const N_POWERS_OF_FIVE: usize = ', end='') - print('(LARGEST_POWER_OF_FIVE - SMALLEST_POWER_OF_FIVE + 1) as usize;') + print("pub const SMALLEST_POWER_OF_FIVE: i32 = {};".format(min_exp)) + print("pub const LARGEST_POWER_OF_FIVE: i32 = {};".format(max_exp)) + print("pub const N_POWERS_OF_FIVE: usize = ", end="") + print("(LARGEST_POWER_OF_FIVE - SMALLEST_POWER_OF_FIVE + 1) as usize;") print() print_proper_powers(min_exp, max_exp, bias) @@ -54,7 +56,7 @@ def minimum_exponent(base): def maximum_exponent(base): - return floor(log(1.7976931348623157e+308, base)) + return floor(log(1.7976931348623157e308, base)) def print_proper_powers(min_exp, max_exp, bias): @@ -64,46 +66,46 @@ def print_proper_powers(min_exp, max_exp, bias): # 2^(2b)/(5^−q) with b=64 + int(math.ceil(log2(5^−q))) powers = [] for q in range(min_exp, 0): - power5 = 5 ** -q + power5 = 5**-q z = 0 while (1 << z) < power5: z += 1 if q >= -27: b = z + 127 - c = 2 ** b // power5 + 1 + c = 2**b // power5 + 1 powers.append((c, q)) else: b = 2 * z + 2 * 64 - c = 2 ** b // power5 + 1 + c = 2**b // power5 + 1 # truncate - while c >= (1<<128): + while c >= (1 << 128): c //= 2 powers.append((c, q)) # Add positive exponents for q in range(0, max_exp + 1): - power5 = 5 ** q + power5 = 5**q # move the most significant bit in position - while power5 < (1<<127): + while power5 < (1 << 127): power5 *= 2 # *truncate* - while power5 >= (1<<128): + while power5 >= (1 << 128): power5 //= 2 powers.append((power5, q)) # Print the powers. print(STATIC_WARNING.strip()) - print('#[rustfmt::skip]') - typ = '[(u64, u64); N_POWERS_OF_FIVE]' - print('pub static POWER_OF_FIVE_128: {} = ['.format(typ)) + print("#[rustfmt::skip]") + typ = "[(u64, u64); N_POWERS_OF_FIVE]" + print("pub static POWER_OF_FIVE_128: {} = [".format(typ)) for c, exp in powers: - hi = '0x{:x}'.format(c // (1 << 64)) - lo = '0x{:x}'.format(c % (1 << 64)) - value = ' ({}, {}), '.format(hi, lo) - comment = '// {}^{}'.format(5, exp) - print(value.ljust(46, ' ') + comment) - print('];') + hi = "0x{:x}".format(c // (1 << 64)) + lo = "0x{:x}".format(c % (1 << 64)) + value = " ({}, {}), ".format(hi, lo) + comment = "// {}^{}".format(5, exp) + print(value.ljust(46, " ") + comment) + print("];") -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/src/etc/gdb_load_rust_pretty_printers.py b/src/etc/gdb_load_rust_pretty_printers.py index e05039ce474..73d1e79f961 100644 --- a/src/etc/gdb_load_rust_pretty_printers.py +++ b/src/etc/gdb_load_rust_pretty_printers.py @@ -1,6 +1,7 @@ # Add this folder to the python sys path; GDB Python-interpreter will now find modules in this path import sys from os import path + self_dir = path.dirname(path.realpath(__file__)) sys.path.append(self_dir) diff --git a/src/etc/gdb_lookup.py b/src/etc/gdb_lookup.py index f3ac9c10978..d368f7ed1ec 100644 --- a/src/etc/gdb_lookup.py +++ b/src/etc/gdb_lookup.py @@ -6,8 +6,11 @@ from gdb_providers import * from rust_types import * -_gdb_version_matched = re.search('([0-9]+)\\.([0-9]+)', gdb.VERSION) -gdb_version = [int(num) for num in _gdb_version_matched.groups()] if _gdb_version_matched else [] +_gdb_version_matched = re.search("([0-9]+)\\.([0-9]+)", gdb.VERSION) +gdb_version = ( + [int(num) for num in _gdb_version_matched.groups()] if _gdb_version_matched else [] +) + def register_printers(objfile): objfile.pretty_printers.append(printer) diff --git a/src/etc/gdb_providers.py b/src/etc/gdb_providers.py index e8f9dee07d3..34bb5c39909 100644 --- a/src/etc/gdb_providers.py +++ b/src/etc/gdb_providers.py @@ -21,7 +21,7 @@ def unwrap_unique_or_non_null(unique_or_nonnull): # GDB 14 has a tag class that indicates that extension methods are ok # to call. Use of this tag only requires that printers hide local # attributes and methods by prefixing them with "_". -if hasattr(gdb, 'ValuePrinter'): +if hasattr(gdb, "ValuePrinter"): printer_base = gdb.ValuePrinter else: printer_base = object @@ -98,7 +98,7 @@ class StdStrProvider(printer_base): def _enumerate_array_elements(element_ptrs): - for (i, element_ptr) in enumerate(element_ptrs): + for i, element_ptr in enumerate(element_ptrs): key = "[{}]".format(i) element = element_ptr.dereference() @@ -173,7 +173,8 @@ class StdVecDequeProvider(printer_base): def children(self): return _enumerate_array_elements( - (self._data_ptr + ((self._head + index) % self._cap)) for index in xrange(self._size) + (self._data_ptr + ((self._head + index) % self._cap)) + for index in xrange(self._size) ) @staticmethod @@ -270,7 +271,9 @@ def children_of_btree_map(map): # Yields each key/value pair in the node and in any child nodes. def children_of_node(node_ptr, height): def cast_to_internal(node): - internal_type_name = node.type.target().name.replace("LeafNode", "InternalNode", 1) + internal_type_name = node.type.target().name.replace( + "LeafNode", "InternalNode", 1 + ) internal_type = gdb.lookup_type(internal_type_name) return node.cast(internal_type.pointer()) @@ -293,8 +296,16 @@ def children_of_btree_map(map): # Avoid "Cannot perform pointer math on incomplete type" on zero-sized arrays. key_type_size = keys.type.sizeof val_type_size = vals.type.sizeof - key = keys[i]["value"]["value"] if key_type_size > 0 else gdb.parse_and_eval("()") - val = vals[i]["value"]["value"] if val_type_size > 0 else gdb.parse_and_eval("()") + key = ( + keys[i]["value"]["value"] + if key_type_size > 0 + else gdb.parse_and_eval("()") + ) + val = ( + vals[i]["value"]["value"] + if val_type_size > 0 + else gdb.parse_and_eval("()") + ) yield key, val if map["length"] > 0: @@ -352,7 +363,7 @@ class StdOldHashMapProvider(printer_base): self._hashes = self._table["hashes"] self._hash_uint_type = self._hashes.type self._hash_uint_size = self._hashes.type.sizeof - self._modulo = 2 ** self._hash_uint_size + self._modulo = 2**self._hash_uint_size self._data_ptr = self._hashes[ZERO_FIELD]["pointer"] self._capacity_mask = int(self._table["capacity_mask"]) @@ -382,8 +393,14 @@ class StdOldHashMapProvider(printer_base): hashes = self._hash_uint_size * self._capacity align = self._pair_type_size - len_rounded_up = (((((hashes + align) % self._modulo - 1) % self._modulo) & ~( - (align - 1) % self._modulo)) % self._modulo - hashes) % self._modulo + len_rounded_up = ( + ( + (((hashes + align) % self._modulo - 1) % self._modulo) + & ~((align - 1) % self._modulo) + ) + % self._modulo + - hashes + ) % self._modulo pairs_offset = hashes + len_rounded_up pairs_start = gdb.Value(start + pairs_offset).cast(self._pair_type.pointer()) diff --git a/src/etc/generate-deriving-span-tests.py b/src/etc/generate-deriving-span-tests.py index d61693460bc..2e810d7df97 100755 --- a/src/etc/generate-deriving-span-tests.py +++ b/src/etc/generate-deriving-span-tests.py @@ -12,7 +12,8 @@ import os import stat TEST_DIR = os.path.abspath( - os.path.join(os.path.dirname(__file__), '../test/ui/derives/')) + os.path.join(os.path.dirname(__file__), "../test/ui/derives/") +) TEMPLATE = """\ // This file was auto-generated using 'src/etc/generate-deriving-span-tests.py' @@ -56,28 +57,33 @@ ENUM_TUPLE, ENUM_STRUCT, STRUCT_FIELDS, STRUCT_TUPLE = range(4) def create_test_case(type, trait, super_traits, error_count): - string = [ENUM_STRING, ENUM_STRUCT_VARIANT_STRING, STRUCT_STRING, STRUCT_TUPLE_STRING][type] - all_traits = ','.join([trait] + super_traits) - super_traits = ','.join(super_traits) - error_deriving = '#[derive(%s)]' % super_traits if super_traits else '' - - errors = '\n'.join('//~%s ERROR' % ('^' * n) for n in range(error_count)) + string = [ + ENUM_STRING, + ENUM_STRUCT_VARIANT_STRING, + STRUCT_STRING, + STRUCT_TUPLE_STRING, + ][type] + all_traits = ",".join([trait] + super_traits) + super_traits = ",".join(super_traits) + error_deriving = "#[derive(%s)]" % super_traits if super_traits else "" + + errors = "\n".join("//~%s ERROR" % ("^" * n) for n in range(error_count)) code = string.format(traits=all_traits, errors=errors) return TEMPLATE.format(error_deriving=error_deriving, code=code) def write_file(name, string): - test_file = os.path.join(TEST_DIR, 'derives-span-%s.rs' % name) + test_file = os.path.join(TEST_DIR, "derives-span-%s.rs" % name) # set write permission if file exists, so it can be changed if os.path.exists(test_file): os.chmod(test_file, stat.S_IWUSR) - with open(test_file, 'w') as f: + with open(test_file, "w") as f: f.write(string) # mark file read-only - os.chmod(test_file, stat.S_IRUSR|stat.S_IRGRP|stat.S_IROTH) + os.chmod(test_file, stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH) ENUM = 1 @@ -85,29 +91,31 @@ STRUCT = 2 ALL = STRUCT | ENUM traits = { - 'Default': (STRUCT, [], 1), - 'FromPrimitive': (0, [], 0), # only works for C-like enums - - 'Decodable': (0, [], 0), # FIXME: quoting gives horrible spans - 'Encodable': (0, [], 0), # FIXME: quoting gives horrible spans + "Default": (STRUCT, [], 1), + "FromPrimitive": (0, [], 0), # only works for C-like enums + "Decodable": (0, [], 0), # FIXME: quoting gives horrible spans + "Encodable": (0, [], 0), # FIXME: quoting gives horrible spans } -for (trait, supers, errs) in [('Clone', [], 1), - ('PartialEq', [], 2), - ('PartialOrd', ['PartialEq'], 1), - ('Eq', ['PartialEq'], 1), - ('Ord', ['Eq', 'PartialOrd', 'PartialEq'], 1), - ('Debug', [], 1), - ('Hash', [], 1)]: +for trait, supers, errs in [ + ("Clone", [], 1), + ("PartialEq", [], 2), + ("PartialOrd", ["PartialEq"], 1), + ("Eq", ["PartialEq"], 1), + ("Ord", ["Eq", "PartialOrd", "PartialEq"], 1), + ("Debug", [], 1), + ("Hash", [], 1), +]: traits[trait] = (ALL, supers, errs) -for (trait, (types, super_traits, error_count)) in traits.items(): +for trait, (types, super_traits, error_count) in traits.items(): + def mk(ty, t=trait, st=super_traits, ec=error_count): return create_test_case(ty, t, st, ec) if types & ENUM: - write_file(trait + '-enum', mk(ENUM_TUPLE)) - write_file(trait + '-enum-struct-variant', mk(ENUM_STRUCT)) + write_file(trait + "-enum", mk(ENUM_TUPLE)) + write_file(trait + "-enum-struct-variant", mk(ENUM_STRUCT)) if types & STRUCT: - write_file(trait + '-struct', mk(STRUCT_FIELDS)) - write_file(trait + '-tuple-struct', mk(STRUCT_TUPLE)) + write_file(trait + "-struct", mk(STRUCT_FIELDS)) + write_file(trait + "-tuple-struct", mk(STRUCT_TUPLE)) diff --git a/src/etc/generate-keyword-tests.py b/src/etc/generate-keyword-tests.py index 77c3d2758c6..28f932acd9d 100755 --- a/src/etc/generate-keyword-tests.py +++ b/src/etc/generate-keyword-tests.py @@ -22,18 +22,16 @@ fn main() { } """ -test_dir = os.path.abspath( - os.path.join(os.path.dirname(__file__), '../test/ui/parser') -) +test_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), "../test/ui/parser")) for kw in sys.argv[1:]: - test_file = os.path.join(test_dir, 'keyword-%s-as-identifier.rs' % kw) + test_file = os.path.join(test_dir, "keyword-%s-as-identifier.rs" % kw) # set write permission if file exists, so it can be changed if os.path.exists(test_file): os.chmod(test_file, stat.S_IWUSR) - with open(test_file, 'wt') as f: + with open(test_file, "wt") as f: f.write(template % (kw, kw, kw)) # mark file read-only diff --git a/src/etc/htmldocck.py b/src/etc/htmldocck.py index 851b01a7458..d6b594aca71 100755 --- a/src/etc/htmldocck.py +++ b/src/etc/htmldocck.py @@ -127,6 +127,7 @@ import os.path import re import shlex from collections import namedtuple + try: from html.parser import HTMLParser except ImportError: @@ -142,12 +143,28 @@ except ImportError: from htmlentitydefs import name2codepoint # "void elements" (no closing tag) from the HTML Standard section 12.1.2 -VOID_ELEMENTS = {'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'keygen', - 'link', 'menuitem', 'meta', 'param', 'source', 'track', 'wbr'} +VOID_ELEMENTS = { + "area", + "base", + "br", + "col", + "embed", + "hr", + "img", + "input", + "keygen", + "link", + "menuitem", + "meta", + "param", + "source", + "track", + "wbr", +} # Python 2 -> 3 compatibility try: - unichr # noqa: B018 FIXME: py2 + unichr # noqa: B018 FIXME: py2 except NameError: unichr = chr @@ -158,18 +175,20 @@ channel = os.environ["DOC_RUST_LANG_ORG_CHANNEL"] rust_test_path = None bless = None + class CustomHTMLParser(HTMLParser): """simplified HTML parser. this is possible because we are dealing with very regular HTML from rustdoc; we only have to deal with i) void elements and ii) empty attributes.""" + def __init__(self, target=None): HTMLParser.__init__(self) self.__builder = target or ET.TreeBuilder() def handle_starttag(self, tag, attrs): - attrs = {k: v or '' for k, v in attrs} + attrs = {k: v or "" for k, v in attrs} self.__builder.start(tag, attrs) if tag in VOID_ELEMENTS: self.__builder.end(tag) @@ -178,7 +197,7 @@ class CustomHTMLParser(HTMLParser): self.__builder.end(tag) def handle_startendtag(self, tag, attrs): - attrs = {k: v or '' for k, v in attrs} + attrs = {k: v or "" for k, v in attrs} self.__builder.start(tag, attrs) self.__builder.end(tag) @@ -189,7 +208,7 @@ class CustomHTMLParser(HTMLParser): self.__builder.data(unichr(name2codepoint[name])) def handle_charref(self, name): - code = int(name[1:], 16) if name.startswith(('x', 'X')) else int(name, 10) + code = int(name[1:], 16) if name.startswith(("x", "X")) else int(name, 10) self.__builder.data(unichr(code)) def close(self): @@ -197,7 +216,7 @@ class CustomHTMLParser(HTMLParser): return self.__builder.close() -Command = namedtuple('Command', 'negated cmd args lineno context') +Command = namedtuple("Command", "negated cmd args lineno context") class FailedCheck(Exception): @@ -216,17 +235,17 @@ def concat_multi_lines(f): concatenated.""" lastline = None # set to the last line when the last line has a backslash firstlineno = None - catenated = '' + catenated = "" for lineno, line in enumerate(f): - line = line.rstrip('\r\n') + line = line.rstrip("\r\n") # strip the common prefix from the current line if needed if lastline is not None: common_prefix = os.path.commonprefix([line, lastline]) - line = line[len(common_prefix):].lstrip() + line = line[len(common_prefix) :].lstrip() firstlineno = firstlineno or lineno - if line.endswith('\\'): + if line.endswith("\\"): if lastline is None: lastline = line[:-1] catenated += line[:-1] @@ -234,10 +253,10 @@ def concat_multi_lines(f): yield firstlineno, catenated + line lastline = None firstlineno = None - catenated = '' + catenated = "" if lastline is not None: - print_err(lineno, line, 'Trailing backslash at the end of the file') + print_err(lineno, line, "Trailing backslash at the end of the file") def get_known_directive_names(): @@ -253,12 +272,12 @@ def get_known_directive_names(): "tools/compiletest/src/directive-list.rs", ), "r", - encoding="utf8" + encoding="utf8", ) as fd: content = fd.read() return [ - line.strip().replace('",', '').replace('"', '') - for line in content.split('\n') + line.strip().replace('",', "").replace('"', "") + for line in content.split("\n") if filter_line(line) ] @@ -269,35 +288,42 @@ def get_known_directive_names(): # See <https://github.com/rust-lang/rust/issues/125813#issuecomment-2141953780>. KNOWN_DIRECTIVE_NAMES = get_known_directive_names() -LINE_PATTERN = re.compile(r''' +LINE_PATTERN = re.compile( + r""" //@\s+ (?P<negated>!?)(?P<cmd>[A-Za-z0-9]+(?:-[A-Za-z0-9]+)*) (?P<args>.*)$ -''', re.X | re.UNICODE) +""", + re.X | re.UNICODE, +) def get_commands(template): - with io.open(template, encoding='utf-8') as f: + with io.open(template, encoding="utf-8") as f: for lineno, line in concat_multi_lines(f): m = LINE_PATTERN.search(line) if not m: continue - cmd = m.group('cmd') - negated = (m.group('negated') == '!') + cmd = m.group("cmd") + negated = m.group("negated") == "!" if not negated and cmd in KNOWN_DIRECTIVE_NAMES: continue - args = m.group('args') + args = m.group("args") if args and not args[:1].isspace(): - print_err(lineno, line, 'Invalid template syntax') + print_err(lineno, line, "Invalid template syntax") continue try: args = shlex.split(args) except UnicodeEncodeError: - args = [arg.decode('utf-8') for arg in shlex.split(args.encode('utf-8'))] + args = [ + arg.decode("utf-8") for arg in shlex.split(args.encode("utf-8")) + ] except Exception as exc: raise Exception("line {}: {}".format(lineno + 1, exc)) from None - yield Command(negated=negated, cmd=cmd, args=args, lineno=lineno+1, context=line) + yield Command( + negated=negated, cmd=cmd, args=args, lineno=lineno + 1, context=line + ) def _flatten(node, acc): @@ -312,22 +338,24 @@ def _flatten(node, acc): def flatten(node): acc = [] _flatten(node, acc) - return ''.join(acc) + return "".join(acc) def make_xml(text): - xml = ET.XML('<xml>%s</xml>' % text) + xml = ET.XML("<xml>%s</xml>" % text) return xml def normalize_xpath(path): path = path.replace("{{channel}}", channel) - if path.startswith('//'): - return '.' + path # avoid warnings - elif path.startswith('.//'): + if path.startswith("//"): + return "." + path # avoid warnings + elif path.startswith(".//"): return path else: - raise InvalidCheck('Non-absolute XPath is not supported due to implementation issues') + raise InvalidCheck( + "Non-absolute XPath is not supported due to implementation issues" + ) class CachedFiles(object): @@ -338,12 +366,12 @@ class CachedFiles(object): self.last_path = None def resolve_path(self, path): - if path != '-': + if path != "-": path = os.path.normpath(path) self.last_path = path return path elif self.last_path is None: - raise InvalidCheck('Tried to use the previous path in the first command') + raise InvalidCheck("Tried to use the previous path in the first command") else: return self.last_path @@ -356,10 +384,10 @@ class CachedFiles(object): return self.files[path] abspath = self.get_absolute_path(path) - if not(os.path.exists(abspath) and os.path.isfile(abspath)): - raise FailedCheck('File does not exist {!r}'.format(path)) + if not (os.path.exists(abspath) and os.path.isfile(abspath)): + raise FailedCheck("File does not exist {!r}".format(path)) - with io.open(abspath, encoding='utf-8') as f: + with io.open(abspath, encoding="utf-8") as f: data = f.read() self.files[path] = data return data @@ -370,15 +398,15 @@ class CachedFiles(object): return self.trees[path] abspath = self.get_absolute_path(path) - if not(os.path.exists(abspath) and os.path.isfile(abspath)): - raise FailedCheck('File does not exist {!r}'.format(path)) + if not (os.path.exists(abspath) and os.path.isfile(abspath)): + raise FailedCheck("File does not exist {!r}".format(path)) - with io.open(abspath, encoding='utf-8') as f: + with io.open(abspath, encoding="utf-8") as f: try: tree = ET.fromstringlist(f.readlines(), CustomHTMLParser()) except Exception as e: - raise RuntimeError( # noqa: B904 FIXME: py2 - 'Cannot parse an HTML file {!r}: {}'.format(path, e) + raise RuntimeError( # noqa: B904 FIXME: py2 + "Cannot parse an HTML file {!r}: {}".format(path, e) ) self.trees[path] = tree return self.trees[path] @@ -386,8 +414,8 @@ class CachedFiles(object): def get_dir(self, path): path = self.resolve_path(path) abspath = self.get_absolute_path(path) - if not(os.path.exists(abspath) and os.path.isdir(abspath)): - raise FailedCheck('Directory does not exist {!r}'.format(path)) + if not (os.path.exists(abspath) and os.path.isdir(abspath)): + raise FailedCheck("Directory does not exist {!r}".format(path)) def check_string(data, pat, regexp): @@ -397,8 +425,8 @@ def check_string(data, pat, regexp): elif regexp: return re.search(pat, data, flags=re.UNICODE) is not None else: - data = ' '.join(data.split()) - pat = ' '.join(pat.split()) + data = " ".join(data.split()) + pat = " ".join(pat.split()) return pat in data @@ -444,19 +472,19 @@ def get_tree_count(tree, path): def check_snapshot(snapshot_name, actual_tree, normalize_to_text): - assert rust_test_path.endswith('.rs') - snapshot_path = '{}.{}.{}'.format(rust_test_path[:-3], snapshot_name, 'html') + assert rust_test_path.endswith(".rs") + snapshot_path = "{}.{}.{}".format(rust_test_path[:-3], snapshot_name, "html") try: - with open(snapshot_path, 'r') as snapshot_file: + with open(snapshot_path, "r") as snapshot_file: expected_str = snapshot_file.read().replace("{{channel}}", channel) except FileNotFoundError: if bless: expected_str = None else: - raise FailedCheck('No saved snapshot value') # noqa: B904 FIXME: py2 + raise FailedCheck("No saved snapshot value") # noqa: B904 FIXME: py2 if not normalize_to_text: - actual_str = ET.tostring(actual_tree).decode('utf-8') + actual_str = ET.tostring(actual_tree).decode("utf-8") else: actual_str = flatten(actual_tree) @@ -464,64 +492,66 @@ def check_snapshot(snapshot_name, actual_tree, normalize_to_text): # 1. Is --bless # 2. Are actual and expected tree different # 3. Are actual and expected text different - if not expected_str \ - or (not normalize_to_text and \ - not compare_tree(make_xml(actual_str), make_xml(expected_str), stderr)) \ - or (normalize_to_text and actual_str != expected_str): - + if ( + not expected_str + or ( + not normalize_to_text + and not compare_tree(make_xml(actual_str), make_xml(expected_str), stderr) + ) + or (normalize_to_text and actual_str != expected_str) + ): if bless: - with open(snapshot_path, 'w') as snapshot_file: + with open(snapshot_path, "w") as snapshot_file: actual_str = actual_str.replace(channel, "{{channel}}") snapshot_file.write(actual_str) else: - print('--- expected ---\n') + print("--- expected ---\n") print(expected_str) - print('\n\n--- actual ---\n') + print("\n\n--- actual ---\n") print(actual_str) print() - raise FailedCheck('Actual snapshot value is different than expected') + raise FailedCheck("Actual snapshot value is different than expected") # Adapted from https://github.com/formencode/formencode/blob/3a1ba9de2fdd494dd945510a4568a3afeddb0b2e/formencode/doctest_xml_compare.py#L72-L120 def compare_tree(x1, x2, reporter=None): if x1.tag != x2.tag: if reporter: - reporter('Tags do not match: %s and %s' % (x1.tag, x2.tag)) + reporter("Tags do not match: %s and %s" % (x1.tag, x2.tag)) return False for name, value in x1.attrib.items(): if x2.attrib.get(name) != value: if reporter: - reporter('Attributes do not match: %s=%r, %s=%r' - % (name, value, name, x2.attrib.get(name))) + reporter( + "Attributes do not match: %s=%r, %s=%r" + % (name, value, name, x2.attrib.get(name)) + ) return False for name in x2.attrib: if name not in x1.attrib: if reporter: - reporter('x2 has an attribute x1 is missing: %s' - % name) + reporter("x2 has an attribute x1 is missing: %s" % name) return False if not text_compare(x1.text, x2.text): if reporter: - reporter('text: %r != %r' % (x1.text, x2.text)) + reporter("text: %r != %r" % (x1.text, x2.text)) return False if not text_compare(x1.tail, x2.tail): if reporter: - reporter('tail: %r != %r' % (x1.tail, x2.tail)) + reporter("tail: %r != %r" % (x1.tail, x2.tail)) return False cl1 = list(x1) cl2 = list(x2) if len(cl1) != len(cl2): if reporter: - reporter('children length differs, %i != %i' - % (len(cl1), len(cl2))) + reporter("children length differs, %i != %i" % (len(cl1), len(cl2))) return False i = 0 for c1, c2 in zip(cl1, cl2): i += 1 if not compare_tree(c1, c2, reporter=reporter): if reporter: - reporter('children %i do not match: %s' - % (i, c1.tag)) + reporter("children %i do not match: %s" % (i, c1.tag)) return False return True @@ -529,14 +559,14 @@ def compare_tree(x1, x2, reporter=None): def text_compare(t1, t2): if not t1 and not t2: return True - if t1 == '*' or t2 == '*': + if t1 == "*" or t2 == "*": return True - return (t1 or '').strip() == (t2 or '').strip() + return (t1 or "").strip() == (t2 or "").strip() def stderr(*args): if sys.version_info.major < 3: - file = codecs.getwriter('utf-8')(sys.stderr) + file = codecs.getwriter("utf-8")(sys.stderr) else: file = sys.stderr @@ -556,21 +586,25 @@ def print_err(lineno, context, err, message=None): def get_nb_matching_elements(cache, c, regexp, stop_at_first): tree = cache.get_tree(c.args[0]) - pat, sep, attr = c.args[1].partition('/@') + pat, sep, attr = c.args[1].partition("/@") if sep: # attribute tree = cache.get_tree(c.args[0]) return check_tree_attr(tree, pat, attr, c.args[2], False) else: # normalized text pat = c.args[1] - if pat.endswith('/text()'): + if pat.endswith("/text()"): pat = pat[:-7] - return check_tree_text(cache.get_tree(c.args[0]), pat, c.args[2], regexp, stop_at_first) + return check_tree_text( + cache.get_tree(c.args[0]), pat, c.args[2], regexp, stop_at_first + ) def check_files_in_folder(c, cache, folder, files): files = files.strip() - if not files.startswith('[') or not files.endswith(']'): - raise InvalidCheck("Expected list as second argument of {} (ie '[]')".format(c.cmd)) + if not files.startswith("[") or not files.endswith("]"): + raise InvalidCheck( + "Expected list as second argument of {} (ie '[]')".format(c.cmd) + ) folder = cache.get_absolute_path(folder) @@ -592,12 +626,18 @@ def check_files_in_folder(c, cache, folder, files): error = 0 if len(files_set) != 0: - print_err(c.lineno, c.context, "Entries not found in folder `{}`: `{}`".format( - folder, files_set)) + print_err( + c.lineno, + c.context, + "Entries not found in folder `{}`: `{}`".format(folder, files_set), + ) error += 1 if len(folder_set) != 0: - print_err(c.lineno, c.context, "Extra entries in folder `{}`: `{}`".format( - folder, folder_set)) + print_err( + c.lineno, + c.context, + "Extra entries in folder `{}`: `{}`".format(folder, folder_set), + ) error += 1 return error == 0 @@ -608,11 +648,11 @@ ERR_COUNT = 0 def check_command(c, cache): try: cerr = "" - if c.cmd in ['has', 'hasraw', 'matches', 'matchesraw']: # string test - regexp = c.cmd.startswith('matches') + if c.cmd in ["has", "hasraw", "matches", "matchesraw"]: # string test + regexp = c.cmd.startswith("matches") # has <path> = file existence - if len(c.args) == 1 and not regexp and 'raw' not in c.cmd: + if len(c.args) == 1 and not regexp and "raw" not in c.cmd: try: cache.get_file(c.args[0]) ret = True @@ -620,24 +660,24 @@ def check_command(c, cache): cerr = str(err) ret = False # hasraw/matchesraw <path> <pat> = string test - elif len(c.args) == 2 and 'raw' in c.cmd: + elif len(c.args) == 2 and "raw" in c.cmd: cerr = "`PATTERN` did not match" ret = check_string(cache.get_file(c.args[0]), c.args[1], regexp) # has/matches <path> <pat> <match> = XML tree test - elif len(c.args) == 3 and 'raw' not in c.cmd: + elif len(c.args) == 3 and "raw" not in c.cmd: cerr = "`XPATH PATTERN` did not match" ret = get_nb_matching_elements(cache, c, regexp, True) != 0 else: - raise InvalidCheck('Invalid number of {} arguments'.format(c.cmd)) + raise InvalidCheck("Invalid number of {} arguments".format(c.cmd)) - elif c.cmd == 'files': # check files in given folder - if len(c.args) != 2: # files <folder path> <file list> + elif c.cmd == "files": # check files in given folder + if len(c.args) != 2: # files <folder path> <file list> raise InvalidCheck("Invalid number of {} arguments".format(c.cmd)) elif c.negated: raise InvalidCheck("{} doesn't support negative check".format(c.cmd)) ret = check_files_in_folder(c, cache, c.args[0], c.args[1]) - elif c.cmd == 'count': # count test + elif c.cmd == "count": # count test if len(c.args) == 3: # count <path> <pat> <count> = count test expected = int(c.args[2]) found = get_tree_count(cache.get_tree(c.args[0]), c.args[1]) @@ -649,15 +689,15 @@ def check_command(c, cache): cerr = "Expected {} occurrences but found {}".format(expected, found) ret = found == expected else: - raise InvalidCheck('Invalid number of {} arguments'.format(c.cmd)) + raise InvalidCheck("Invalid number of {} arguments".format(c.cmd)) - elif c.cmd == 'snapshot': # snapshot test + elif c.cmd == "snapshot": # snapshot test if len(c.args) == 3: # snapshot <snapshot-name> <html-path> <xpath> [snapshot_name, html_path, pattern] = c.args tree = cache.get_tree(html_path) xpath = normalize_xpath(pattern) normalize_to_text = False - if xpath.endswith('/text()'): + if xpath.endswith("/text()"): xpath = xpath[:-7] normalize_to_text = True @@ -671,13 +711,15 @@ def check_command(c, cache): cerr = str(err) ret = False elif len(subtrees) == 0: - raise FailedCheck('XPATH did not match') + raise FailedCheck("XPATH did not match") else: - raise FailedCheck('Expected 1 match, but found {}'.format(len(subtrees))) + raise FailedCheck( + "Expected 1 match, but found {}".format(len(subtrees)) + ) else: - raise InvalidCheck('Invalid number of {} arguments'.format(c.cmd)) + raise InvalidCheck("Invalid number of {} arguments".format(c.cmd)) - elif c.cmd == 'has-dir': # has-dir test + elif c.cmd == "has-dir": # has-dir test if len(c.args) == 1: # has-dir <path> = has-dir test try: cache.get_dir(c.args[0]) @@ -686,22 +728,22 @@ def check_command(c, cache): cerr = str(err) ret = False else: - raise InvalidCheck('Invalid number of {} arguments'.format(c.cmd)) + raise InvalidCheck("Invalid number of {} arguments".format(c.cmd)) - elif c.cmd == 'valid-html': - raise InvalidCheck('Unimplemented valid-html') + elif c.cmd == "valid-html": + raise InvalidCheck("Unimplemented valid-html") - elif c.cmd == 'valid-links': - raise InvalidCheck('Unimplemented valid-links') + elif c.cmd == "valid-links": + raise InvalidCheck("Unimplemented valid-links") else: - raise InvalidCheck('Unrecognized {}'.format(c.cmd)) + raise InvalidCheck("Unrecognized {}".format(c.cmd)) if ret == c.negated: raise FailedCheck(cerr) except FailedCheck as err: - message = '{}{} check failed'.format('!' if c.negated else '', c.cmd) + message = "{}{} check failed".format("!" if c.negated else "", c.cmd) print_err(c.lineno, c.context, str(err), message) except InvalidCheck as err: print_err(c.lineno, c.context, str(err)) @@ -713,18 +755,18 @@ def check(target, commands): check_command(c, cache) -if __name__ == '__main__': +if __name__ == "__main__": if len(sys.argv) not in [3, 4]: - stderr('Usage: {} <doc dir> <template> [--bless]'.format(sys.argv[0])) + stderr("Usage: {} <doc dir> <template> [--bless]".format(sys.argv[0])) raise SystemExit(1) rust_test_path = sys.argv[2] - if len(sys.argv) > 3 and sys.argv[3] == '--bless': + if len(sys.argv) > 3 and sys.argv[3] == "--bless": bless = True else: # We only support `--bless` at the end of the arguments. # This assert is to prevent silent failures. - assert '--bless' not in sys.argv + assert "--bless" not in sys.argv bless = False check(sys.argv[1], get_commands(rust_test_path)) if ERR_COUNT: diff --git a/src/etc/lldb_batchmode.py b/src/etc/lldb_batchmode.py index db1e0035ea0..cf88c53e085 100644 --- a/src/etc/lldb_batchmode.py +++ b/src/etc/lldb_batchmode.py @@ -45,7 +45,7 @@ def normalize_whitespace(s): def breakpoint_callback(frame, bp_loc, dict): """This callback is registered with every breakpoint and makes sure that the - frame containing the breakpoint location is selected """ + frame containing the breakpoint location is selected""" # HACK(eddyb) print a newline to avoid continuing an unfinished line. print("") @@ -79,7 +79,7 @@ def execute_command(command_interpreter, command): if res.Succeeded(): if res.HasResult(): - print(normalize_whitespace(res.GetOutput() or ''), end='\n') + print(normalize_whitespace(res.GetOutput() or ""), end="\n") # If the command introduced any breakpoints, make sure to register # them with the breakpoint @@ -89,20 +89,32 @@ def execute_command(command_interpreter, command): breakpoint_id = new_breakpoints.pop() if breakpoint_id in registered_breakpoints: - print_debug("breakpoint with id %s is already registered. Ignoring." % - str(breakpoint_id)) + print_debug( + "breakpoint with id %s is already registered. Ignoring." + % str(breakpoint_id) + ) else: - print_debug("registering breakpoint callback, id = " + str(breakpoint_id)) - callback_command = ("breakpoint command add -F breakpoint_callback " + - str(breakpoint_id)) + print_debug( + "registering breakpoint callback, id = " + str(breakpoint_id) + ) + callback_command = ( + "breakpoint command add -F breakpoint_callback " + + str(breakpoint_id) + ) command_interpreter.HandleCommand(callback_command, res) if res.Succeeded(): - print_debug("successfully registered breakpoint callback, id = " + - str(breakpoint_id)) + print_debug( + "successfully registered breakpoint callback, id = " + + str(breakpoint_id) + ) registered_breakpoints.add(breakpoint_id) else: - print("Error while trying to register breakpoint callback, id = " + - str(breakpoint_id) + ", message = " + str(res.GetError())) + print( + "Error while trying to register breakpoint callback, id = " + + str(breakpoint_id) + + ", message = " + + str(res.GetError()) + ) else: print(res.GetError()) @@ -117,14 +129,16 @@ def start_breakpoint_listener(target): try: while True: if listener.WaitForEvent(120, event): - if lldb.SBBreakpoint.EventIsBreakpointEvent(event) and \ - lldb.SBBreakpoint.GetBreakpointEventTypeFromEvent(event) == \ - lldb.eBreakpointEventTypeAdded: + if ( + lldb.SBBreakpoint.EventIsBreakpointEvent(event) + and lldb.SBBreakpoint.GetBreakpointEventTypeFromEvent(event) + == lldb.eBreakpointEventTypeAdded + ): global new_breakpoints breakpoint = lldb.SBBreakpoint.GetBreakpointFromEvent(event) print_debug("breakpoint added, id = " + str(breakpoint.id)) new_breakpoints.append(breakpoint.id) - except BaseException: # explicitly catch ctrl+c/sysexit + except BaseException: # explicitly catch ctrl+c/sysexit print_debug("breakpoint listener shutting down") # Start the listener and let it run as a daemon @@ -133,7 +147,9 @@ def start_breakpoint_listener(target): listener_thread.start() # Register the listener with the target - target.GetBroadcaster().AddListener(listener, lldb.SBTarget.eBroadcastBitBreakpointChanged) + target.GetBroadcaster().AddListener( + listener, lldb.SBTarget.eBroadcastBitBreakpointChanged + ) def start_watchdog(): @@ -159,6 +175,7 @@ def start_watchdog(): watchdog_thread.daemon = True watchdog_thread.start() + #################################################################################################### # ~main #################################################################################################### @@ -193,8 +210,14 @@ target_error = lldb.SBError() target = debugger.CreateTarget(target_path, None, None, True, target_error) if not target: - print("Could not create debugging target '" + target_path + "': " + - str(target_error) + ". Aborting.", file=sys.stderr) + print( + "Could not create debugging target '" + + target_path + + "': " + + str(target_error) + + ". Aborting.", + file=sys.stderr, + ) sys.exit(1) @@ -204,15 +227,19 @@ start_breakpoint_listener(target) command_interpreter = debugger.GetCommandInterpreter() try: - script_file = open(script_path, 'r') + script_file = open(script_path, "r") for line in script_file: command = line.strip() - if command == "run" or command == "r" or re.match("^process\s+launch.*", command): + if ( + command == "run" + or command == "r" + or re.match("^process\s+launch.*", command) + ): # Before starting to run the program, let the thread sleep a bit, so all # breakpoint added events can be processed time.sleep(0.5) - if command != '': + if command != "": execute_command(command_interpreter, command) except IOError as e: diff --git a/src/etc/lldb_providers.py b/src/etc/lldb_providers.py index a42ce111ebc..c24ec8ab310 100644 --- a/src/etc/lldb_providers.py +++ b/src/etc/lldb_providers.py @@ -1,7 +1,12 @@ import sys -from lldb import SBData, SBError, eBasicTypeLong, eBasicTypeUnsignedLong, \ - eBasicTypeUnsignedChar +from lldb import ( + SBData, + SBError, + eBasicTypeLong, + eBasicTypeUnsignedLong, + eBasicTypeUnsignedChar, +) # from lldb.formatters import Logger @@ -50,13 +55,17 @@ class ValueBuilder: def from_int(self, name, value): # type: (str, int) -> SBValue type = self.valobj.GetType().GetBasicType(eBasicTypeLong) - data = SBData.CreateDataFromSInt64Array(self.endianness, self.pointer_size, [value]) + data = SBData.CreateDataFromSInt64Array( + self.endianness, self.pointer_size, [value] + ) return self.valobj.CreateValueFromData(name, data, type) def from_uint(self, name, value): # type: (str, int) -> SBValue type = self.valobj.GetType().GetBasicType(eBasicTypeUnsignedLong) - data = SBData.CreateDataFromUInt64Array(self.endianness, self.pointer_size, [value]) + data = SBData.CreateDataFromUInt64Array( + self.endianness, self.pointer_size, [value] + ) return self.valobj.CreateValueFromData(name, data, type) @@ -127,13 +136,17 @@ class EmptySyntheticProvider: def SizeSummaryProvider(valobj, dict): # type: (SBValue, dict) -> str - return 'size=' + str(valobj.GetNumChildren()) + return "size=" + str(valobj.GetNumChildren()) def vec_to_string(vec): length = vec.GetNumChildren() chars = [vec.GetChildAtIndex(i).GetValueAsUnsigned() for i in range(length)] - return bytes(chars).decode(errors='replace') if PY3 else "".join(chr(char) for char in chars) + return ( + bytes(chars).decode(errors="replace") + if PY3 + else "".join(chr(char) for char in chars) + ) def StdStringSummaryProvider(valobj, dict): @@ -172,7 +185,7 @@ def StdStrSummaryProvider(valobj, dict): error = SBError() process = data_ptr.GetProcess() data = process.ReadMemory(start, length, error) - data = data.decode(encoding='UTF-8') if PY3 else data + data = data.decode(encoding="UTF-8") if PY3 else data return '"%s"' % data @@ -199,9 +212,9 @@ def StdPathSummaryProvider(valobj, dict): data = process.ReadMemory(start, length, error) if PY3: try: - data = data.decode(encoding='UTF-8') + data = data.decode(encoding="UTF-8") except UnicodeDecodeError: - return '%r' % data + return "%r" % data return '"%s"' % data @@ -250,8 +263,10 @@ class StructSyntheticProvider: # type: () -> bool return True + class ClangEncodedEnumProvider: """Pretty-printer for 'clang-encoded' enums support implemented in LLDB""" + DISCRIMINANT_MEMBER_NAME = "$discr$" VALUE_MEMBER_NAME = "value" @@ -260,7 +275,7 @@ class ClangEncodedEnumProvider: self.update() def has_children(self): - return True + return True def num_children(self): if self.is_default: @@ -276,25 +291,32 @@ class ClangEncodedEnumProvider: def get_child_at_index(self, index): if index == 0: - return self.variant.GetChildMemberWithName(ClangEncodedEnumProvider.VALUE_MEMBER_NAME) + return self.variant.GetChildMemberWithName( + ClangEncodedEnumProvider.VALUE_MEMBER_NAME + ) if index == 1: return self.variant.GetChildMemberWithName( - ClangEncodedEnumProvider.DISCRIMINANT_MEMBER_NAME) - + ClangEncodedEnumProvider.DISCRIMINANT_MEMBER_NAME + ) def update(self): all_variants = self.valobj.GetChildAtIndex(0) index = self._getCurrentVariantIndex(all_variants) self.variant = all_variants.GetChildAtIndex(index) - self.is_default = self.variant.GetIndexOfChildWithName( - ClangEncodedEnumProvider.DISCRIMINANT_MEMBER_NAME) == -1 + self.is_default = ( + self.variant.GetIndexOfChildWithName( + ClangEncodedEnumProvider.DISCRIMINANT_MEMBER_NAME + ) + == -1 + ) def _getCurrentVariantIndex(self, all_variants): default_index = 0 for i in range(all_variants.GetNumChildren()): variant = all_variants.GetChildAtIndex(i) discr = variant.GetChildMemberWithName( - ClangEncodedEnumProvider.DISCRIMINANT_MEMBER_NAME) + ClangEncodedEnumProvider.DISCRIMINANT_MEMBER_NAME + ) if discr.IsValid(): discr_unsigned_value = discr.GetValueAsUnsigned() if variant.GetName() == f"$variant${discr_unsigned_value}": @@ -303,6 +325,7 @@ class ClangEncodedEnumProvider: default_index = i return default_index + class TupleSyntheticProvider: """Pretty-printer for tuples and tuple enum variants""" @@ -336,7 +359,9 @@ class TupleSyntheticProvider: else: field = self.type.GetFieldAtIndex(index) element = self.valobj.GetChildMemberWithName(field.name) - return self.valobj.CreateValueFromData(str(index), element.GetData(), element.GetType()) + return self.valobj.CreateValueFromData( + str(index), element.GetData(), element.GetType() + ) def update(self): # type: () -> None @@ -373,7 +398,7 @@ class StdVecSyntheticProvider: def get_child_index(self, name): # type: (str) -> int - index = name.lstrip('[').rstrip(']') + index = name.lstrip("[").rstrip("]") if index.isdigit(): return int(index) else: @@ -383,15 +408,21 @@ class StdVecSyntheticProvider: # type: (int) -> SBValue start = self.data_ptr.GetValueAsUnsigned() address = start + index * self.element_type_size - element = self.data_ptr.CreateValueFromAddress("[%s]" % index, address, self.element_type) + element = self.data_ptr.CreateValueFromAddress( + "[%s]" % index, address, self.element_type + ) return element def update(self): # type: () -> None self.length = self.valobj.GetChildMemberWithName("len").GetValueAsUnsigned() - self.buf = self.valobj.GetChildMemberWithName("buf").GetChildMemberWithName("inner") + self.buf = self.valobj.GetChildMemberWithName("buf").GetChildMemberWithName( + "inner" + ) - self.data_ptr = unwrap_unique_or_non_null(self.buf.GetChildMemberWithName("ptr")) + self.data_ptr = unwrap_unique_or_non_null( + self.buf.GetChildMemberWithName("ptr") + ) self.element_type = self.valobj.GetType().GetTemplateArgumentType(0) self.element_type_size = self.element_type.GetByteSize() @@ -412,7 +443,7 @@ class StdSliceSyntheticProvider: def get_child_index(self, name): # type: (str) -> int - index = name.lstrip('[').rstrip(']') + index = name.lstrip("[").rstrip("]") if index.isdigit(): return int(index) else: @@ -422,7 +453,9 @@ class StdSliceSyntheticProvider: # type: (int) -> SBValue start = self.data_ptr.GetValueAsUnsigned() address = start + index * self.element_type_size - element = self.data_ptr.CreateValueFromAddress("[%s]" % index, address, self.element_type) + element = self.data_ptr.CreateValueFromAddress( + "[%s]" % index, address, self.element_type + ) return element def update(self): @@ -457,7 +490,7 @@ class StdVecDequeSyntheticProvider: def get_child_index(self, name): # type: (str) -> int - index = name.lstrip('[').rstrip(']') + index = name.lstrip("[").rstrip("]") if index.isdigit() and int(index) < self.size: return int(index) else: @@ -467,20 +500,26 @@ class StdVecDequeSyntheticProvider: # type: (int) -> SBValue start = self.data_ptr.GetValueAsUnsigned() address = start + ((index + self.head) % self.cap) * self.element_type_size - element = self.data_ptr.CreateValueFromAddress("[%s]" % index, address, self.element_type) + element = self.data_ptr.CreateValueFromAddress( + "[%s]" % index, address, self.element_type + ) return element def update(self): # type: () -> None self.head = self.valobj.GetChildMemberWithName("head").GetValueAsUnsigned() self.size = self.valobj.GetChildMemberWithName("len").GetValueAsUnsigned() - self.buf = self.valobj.GetChildMemberWithName("buf").GetChildMemberWithName("inner") + self.buf = self.valobj.GetChildMemberWithName("buf").GetChildMemberWithName( + "inner" + ) cap = self.buf.GetChildMemberWithName("cap") if cap.GetType().num_fields == 1: cap = cap.GetChildAtIndex(0) self.cap = cap.GetValueAsUnsigned() - self.data_ptr = unwrap_unique_or_non_null(self.buf.GetChildMemberWithName("ptr")) + self.data_ptr = unwrap_unique_or_non_null( + self.buf.GetChildMemberWithName("ptr") + ) self.element_type = self.valobj.GetType().GetTemplateArgumentType(0) self.element_type_size = self.element_type.GetByteSize() @@ -510,7 +549,7 @@ class StdOldHashMapSyntheticProvider: def get_child_index(self, name): # type: (str) -> int - index = name.lstrip('[').rstrip(']') + index = name.lstrip("[").rstrip("]") if index.isdigit(): return int(index) else: @@ -525,8 +564,14 @@ class StdOldHashMapSyntheticProvider: hashes = self.hash_uint_size * self.capacity align = self.pair_type_size # See `libcore/alloc.rs:padding_needed_for` - len_rounded_up = (((((hashes + align) % self.modulo - 1) % self.modulo) & ~( - (align - 1) % self.modulo)) % self.modulo - hashes) % self.modulo + len_rounded_up = ( + ( + (((hashes + align) % self.modulo - 1) % self.modulo) + & ~((align - 1) % self.modulo) + ) + % self.modulo + - hashes + ) % self.modulo # len_rounded_up = ((hashes + align - 1) & ~(align - 1)) - hashes pairs_offset = hashes + len_rounded_up @@ -535,12 +580,16 @@ class StdOldHashMapSyntheticProvider: table_index = self.valid_indices[index] idx = table_index & self.capacity_mask address = pairs_start + idx * self.pair_type_size - element = self.data_ptr.CreateValueFromAddress("[%s]" % index, address, self.pair_type) + element = self.data_ptr.CreateValueFromAddress( + "[%s]" % index, address, self.pair_type + ) if self.show_values: return element else: key = element.GetChildAtIndex(0) - return self.valobj.CreateValueFromData("[%s]" % index, key.GetData(), key.GetType()) + return self.valobj.CreateValueFromData( + "[%s]" % index, key.GetData(), key.GetType() + ) def update(self): # type: () -> None @@ -551,10 +600,12 @@ class StdOldHashMapSyntheticProvider: self.hashes = self.table.GetChildMemberWithName("hashes") self.hash_uint_type = self.hashes.GetType() self.hash_uint_size = self.hashes.GetType().GetByteSize() - self.modulo = 2 ** self.hash_uint_size + self.modulo = 2**self.hash_uint_size self.data_ptr = self.hashes.GetChildAtIndex(0).GetChildAtIndex(0) - self.capacity_mask = self.table.GetChildMemberWithName("capacity_mask").GetValueAsUnsigned() + self.capacity_mask = self.table.GetChildMemberWithName( + "capacity_mask" + ).GetValueAsUnsigned() self.capacity = (self.capacity_mask + 1) % self.modulo marker = self.table.GetChildMemberWithName("marker").GetType() # type: SBType @@ -564,8 +615,9 @@ class StdOldHashMapSyntheticProvider: self.valid_indices = [] for idx in range(self.capacity): address = self.data_ptr.GetValueAsUnsigned() + idx * self.hash_uint_size - hash_uint = self.data_ptr.CreateValueFromAddress("[%s]" % idx, address, - self.hash_uint_type) + hash_uint = self.data_ptr.CreateValueFromAddress( + "[%s]" % idx, address, self.hash_uint_type + ) hash_ptr = hash_uint.GetChildAtIndex(0).GetChildAtIndex(0) if hash_ptr.GetValueAsUnsigned() != 0: self.valid_indices.append(idx) @@ -592,7 +644,7 @@ class StdHashMapSyntheticProvider: def get_child_index(self, name): # type: (str) -> int - index = name.lstrip('[').rstrip(']') + index = name.lstrip("[").rstrip("]") if index.isdigit(): return int(index) else: @@ -605,19 +657,25 @@ class StdHashMapSyntheticProvider: if self.new_layout: idx = -(idx + 1) address = pairs_start + idx * self.pair_type_size - element = self.data_ptr.CreateValueFromAddress("[%s]" % index, address, self.pair_type) + element = self.data_ptr.CreateValueFromAddress( + "[%s]" % index, address, self.pair_type + ) if self.show_values: return element else: key = element.GetChildAtIndex(0) - return self.valobj.CreateValueFromData("[%s]" % index, key.GetData(), key.GetType()) + return self.valobj.CreateValueFromData( + "[%s]" % index, key.GetData(), key.GetType() + ) def update(self): # type: () -> None table = self.table() inner_table = table.GetChildMemberWithName("table") - capacity = inner_table.GetChildMemberWithName("bucket_mask").GetValueAsUnsigned() + 1 + capacity = ( + inner_table.GetChildMemberWithName("bucket_mask").GetValueAsUnsigned() + 1 + ) ctrl = inner_table.GetChildMemberWithName("ctrl").GetChildAtIndex(0) self.size = inner_table.GetChildMemberWithName("items").GetValueAsUnsigned() @@ -630,16 +688,21 @@ class StdHashMapSyntheticProvider: if self.new_layout: self.data_ptr = ctrl.Cast(self.pair_type.GetPointerType()) else: - self.data_ptr = inner_table.GetChildMemberWithName("data").GetChildAtIndex(0) + self.data_ptr = inner_table.GetChildMemberWithName("data").GetChildAtIndex( + 0 + ) u8_type = self.valobj.GetTarget().GetBasicType(eBasicTypeUnsignedChar) - u8_type_size = self.valobj.GetTarget().GetBasicType(eBasicTypeUnsignedChar).GetByteSize() + u8_type_size = ( + self.valobj.GetTarget().GetBasicType(eBasicTypeUnsignedChar).GetByteSize() + ) self.valid_indices = [] for idx in range(capacity): address = ctrl.GetValueAsUnsigned() + idx * u8_type_size - value = ctrl.CreateValueFromAddress("ctrl[%s]" % idx, address, - u8_type).GetValueAsUnsigned() + value = ctrl.CreateValueFromAddress( + "ctrl[%s]" % idx, address, u8_type + ).GetValueAsUnsigned() is_present = value & 128 == 0 if is_present: self.valid_indices.append(idx) @@ -691,10 +754,16 @@ class StdRcSyntheticProvider: self.value = self.ptr.GetChildMemberWithName("data" if is_atomic else "value") - self.strong = self.ptr.GetChildMemberWithName("strong").GetChildAtIndex( - 0).GetChildMemberWithName("value") - self.weak = self.ptr.GetChildMemberWithName("weak").GetChildAtIndex( - 0).GetChildMemberWithName("value") + self.strong = ( + self.ptr.GetChildMemberWithName("strong") + .GetChildAtIndex(0) + .GetChildMemberWithName("value") + ) + self.weak = ( + self.ptr.GetChildMemberWithName("weak") + .GetChildAtIndex(0) + .GetChildMemberWithName("value") + ) self.value_builder = ValueBuilder(valobj) @@ -772,7 +841,9 @@ class StdCellSyntheticProvider: def StdRefSummaryProvider(valobj, dict): # type: (SBValue, dict) -> str borrow = valobj.GetChildMemberWithName("borrow").GetValueAsSigned() - return "borrow={}".format(borrow) if borrow >= 0 else "borrow_mut={}".format(-borrow) + return ( + "borrow={}".format(borrow) if borrow >= 0 else "borrow_mut={}".format(-borrow) + ) class StdRefSyntheticProvider: @@ -785,11 +856,16 @@ class StdRefSyntheticProvider: borrow = valobj.GetChildMemberWithName("borrow") value = valobj.GetChildMemberWithName("value") if is_cell: - self.borrow = borrow.GetChildMemberWithName("value").GetChildMemberWithName("value") + self.borrow = borrow.GetChildMemberWithName("value").GetChildMemberWithName( + "value" + ) self.value = value.GetChildMemberWithName("value") else: - self.borrow = borrow.GetChildMemberWithName("borrow").GetChildMemberWithName( - "value").GetChildMemberWithName("value") + self.borrow = ( + borrow.GetChildMemberWithName("borrow") + .GetChildMemberWithName("value") + .GetChildMemberWithName("value") + ) self.value = value.Dereference() self.value_builder = ValueBuilder(valobj) @@ -832,7 +908,7 @@ def StdNonZeroNumberSummaryProvider(valobj, _dict): # FIXME: Avoid printing as character literal, # see https://github.com/llvm/llvm-project/issues/65076. - if inner_inner.GetTypeName() in ['char', 'unsigned char']: - return str(inner_inner.GetValueAsSigned()) + if inner_inner.GetTypeName() in ["char", "unsigned char"]: + return str(inner_inner.GetValueAsSigned()) else: - return inner_inner.GetValue() + return inner_inner.GetValue() diff --git a/src/etc/rust_types.py b/src/etc/rust_types.py index 190fbc13a17..42ec9bed9bd 100644 --- a/src/etc/rust_types.py +++ b/src/etc/rust_types.py @@ -54,7 +54,7 @@ STD_REF_MUT_REGEX = re.compile(r"^(core::([a-z_]+::)+)RefMut<.+>$") STD_REF_CELL_REGEX = re.compile(r"^(core::([a-z_]+::)+)RefCell<.+>$") STD_NONZERO_NUMBER_REGEX = re.compile(r"^(core::([a-z_]+::)+)NonZero<.+>$") STD_PATHBUF_REGEX = re.compile(r"^(std::([a-z_]+::)+)PathBuf$") -STD_PATH_REGEX = re.compile(r"^&(mut )?(std::([a-z_]+::)+)Path$") +STD_PATH_REGEX = re.compile(r"^&(mut )?(std::([a-z_]+::)+)Path$") TUPLE_ITEM_REGEX = re.compile(r"__\d+$") @@ -84,6 +84,7 @@ STD_TYPE_TO_REGEX = { RustType.STD_PATH: STD_PATH_REGEX, } + def is_tuple_fields(fields): # type: (list) -> bool return all(TUPLE_ITEM_REGEX.match(str(field.name)) for field in fields) diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 715bf68374a..cba947eb833 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1241,19 +1241,6 @@ impl Attributes { } } -impl PartialEq for Attributes { - fn eq(&self, rhs: &Self) -> bool { - self.doc_strings == rhs.doc_strings - && self - .other_attrs - .iter() - .map(|attr| attr.id) - .eq(rhs.other_attrs.iter().map(|attr| attr.id)) - } -} - -impl Eq for Attributes {} - #[derive(Clone, PartialEq, Eq, Debug, Hash)] pub(crate) enum GenericBound { TraitBound(PolyTrait, hir::TraitBoundModifiers), diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 5e3d06a4ae7..90c49270566 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -32,6 +32,8 @@ use std::iter::Peekable; use std::ops::{ControlFlow, Range}; use std::path::PathBuf; use std::str::{self, CharIndices}; +use std::sync::atomic::AtomicUsize; +use std::sync::{Arc, Weak}; use pulldown_cmark::{ BrokenLink, CodeBlockKind, CowStr, Event, LinkType, Options, Parser, Tag, TagEnd, html, @@ -1301,8 +1303,20 @@ impl LangString { } } -impl Markdown<'_> { +impl<'a> Markdown<'a> { pub fn into_string(self) -> String { + // This is actually common enough to special-case + if self.content.is_empty() { + return String::new(); + } + + let mut s = String::with_capacity(self.content.len() * 3 / 2); + html::push_html(&mut s, self.into_iter()); + + s + } + + fn into_iter(self) -> CodeBlocks<'a, 'a, impl Iterator<Item = Event<'a>>> { let Markdown { content: md, links, @@ -1313,32 +1327,72 @@ impl Markdown<'_> { heading_offset, } = self; - // This is actually common enough to special-case - if md.is_empty() { - return String::new(); - } - let mut replacer = |broken_link: BrokenLink<'_>| { + let replacer = move |broken_link: BrokenLink<'_>| { links .iter() .find(|link| *link.original_text == *broken_link.reference) .map(|link| (link.href.as_str().into(), link.tooltip.as_str().into())) }; - let p = Parser::new_with_broken_link_callback(md, main_body_opts(), Some(&mut replacer)); + let p = Parser::new_with_broken_link_callback(md, main_body_opts(), Some(replacer)); let p = p.into_offset_iter(); - let mut s = String::with_capacity(md.len() * 3 / 2); - ids.handle_footnotes(|ids, existing_footnotes| { let p = HeadingLinks::new(p, None, ids, heading_offset); let p = footnotes::Footnotes::new(p, existing_footnotes); let p = LinkReplacer::new(p.map(|(ev, _)| ev), links); let p = TableWrapper::new(p); - let p = CodeBlocks::new(p, codes, edition, playground); - html::push_html(&mut s, p); - }); + CodeBlocks::new(p, codes, edition, playground) + }) + } - s + /// Convert markdown to (summary, remaining) HTML. + /// + /// - The summary is the first top-level Markdown element (usually a paragraph, but potentially + /// any block). + /// - The remaining docs contain everything after the summary. + pub(crate) fn split_summary_and_content(self) -> (Option<String>, Option<String>) { + if self.content.is_empty() { + return (None, None); + } + let mut p = self.into_iter(); + + let mut event_level = 0; + let mut summary_events = Vec::new(); + let mut get_next_tag = false; + + let mut end_of_summary = false; + while let Some(event) = p.next() { + match event { + Event::Start(_) => event_level += 1, + Event::End(kind) => { + event_level -= 1; + if event_level == 0 { + // We're back at the "top" so it means we're done with the summary. + end_of_summary = true; + // We surround tables with `<div>` HTML tags so this is a special case. + get_next_tag = kind == TagEnd::Table; + } + } + _ => {} + } + summary_events.push(event); + if end_of_summary { + if get_next_tag && let Some(event) = p.next() { + summary_events.push(event); + } + break; + } + } + let mut summary = String::new(); + html::push_html(&mut summary, summary_events.into_iter()); + if summary.is_empty() { + return (None, None); + } + let mut content = String::new(); + html::push_html(&mut content, p); + + if content.is_empty() { (Some(summary), None) } else { (Some(summary), Some(content)) } } } @@ -1882,7 +1936,7 @@ pub(crate) fn rust_code_blocks(md: &str, extra_info: &ExtraInfo<'_>) -> Vec<Rust #[derive(Clone, Default, Debug)] pub struct IdMap { map: FxHashMap<String, usize>, - existing_footnotes: usize, + existing_footnotes: Arc<AtomicUsize>, } fn is_default_id(id: &str) -> bool { @@ -1942,7 +1996,7 @@ fn is_default_id(id: &str) -> bool { impl IdMap { pub fn new() -> Self { - IdMap { map: FxHashMap::default(), existing_footnotes: 0 } + IdMap { map: FxHashMap::default(), existing_footnotes: Arc::new(AtomicUsize::new(0)) } } pub(crate) fn derive<S: AsRef<str> + ToString>(&mut self, candidate: S) -> String { @@ -1970,15 +2024,17 @@ impl IdMap { /// Method to handle `existing_footnotes` increment automatically (to prevent forgetting /// about it). - pub(crate) fn handle_footnotes<F: FnOnce(&mut Self, &mut usize)>(&mut self, closure: F) { - let mut existing_footnotes = self.existing_footnotes; + pub(crate) fn handle_footnotes<'a, T, F: FnOnce(&'a mut Self, Weak<AtomicUsize>) -> T>( + &'a mut self, + closure: F, + ) -> T { + let existing_footnotes = Arc::downgrade(&self.existing_footnotes); - closure(self, &mut existing_footnotes); - self.existing_footnotes = existing_footnotes; + closure(self, existing_footnotes) } pub(crate) fn clear(&mut self) { self.map.clear(); - self.existing_footnotes = 0; + self.existing_footnotes = Arc::new(AtomicUsize::new(0)); } } diff --git a/src/librustdoc/html/markdown/footnotes.rs b/src/librustdoc/html/markdown/footnotes.rs index ebf55b38373..519778e4d3b 100644 --- a/src/librustdoc/html/markdown/footnotes.rs +++ b/src/librustdoc/html/markdown/footnotes.rs @@ -1,5 +1,8 @@ //! Markdown footnote handling. + use std::fmt::Write as _; +use std::sync::atomic::{AtomicUsize, Ordering}; +use std::sync::{Arc, Weak}; use pulldown_cmark::{CowStr, Event, Tag, TagEnd, html}; use rustc_data_structures::fx::FxIndexMap; @@ -8,10 +11,11 @@ use super::SpannedEvent; /// Moves all footnote definitions to the end and add back links to the /// references. -pub(super) struct Footnotes<'a, 'b, I> { +pub(super) struct Footnotes<'a, I> { inner: I, footnotes: FxIndexMap<String, FootnoteDef<'a>>, - existing_footnotes: &'b mut usize, + existing_footnotes: Arc<AtomicUsize>, + start_id: usize, } /// The definition of a single footnote. @@ -21,13 +25,16 @@ struct FootnoteDef<'a> { id: usize, } -impl<'a, 'b, I: Iterator<Item = SpannedEvent<'a>>> Footnotes<'a, 'b, I> { - pub(super) fn new(iter: I, existing_footnotes: &'b mut usize) -> Self { - Footnotes { inner: iter, footnotes: FxIndexMap::default(), existing_footnotes } +impl<'a, I: Iterator<Item = SpannedEvent<'a>>> Footnotes<'a, I> { + pub(super) fn new(iter: I, existing_footnotes: Weak<AtomicUsize>) -> Self { + let existing_footnotes = + existing_footnotes.upgrade().expect("`existing_footnotes` was dropped"); + let start_id = existing_footnotes.load(Ordering::Relaxed); + Footnotes { inner: iter, footnotes: FxIndexMap::default(), existing_footnotes, start_id } } fn get_entry(&mut self, key: &str) -> (&mut Vec<Event<'a>>, usize) { - let new_id = self.footnotes.len() + 1 + *self.existing_footnotes; + let new_id = self.footnotes.len() + 1 + self.start_id; let key = key.to_owned(); let FootnoteDef { content, id } = self.footnotes.entry(key).or_insert(FootnoteDef { content: Vec::new(), id: new_id }); @@ -44,7 +51,7 @@ impl<'a, 'b, I: Iterator<Item = SpannedEvent<'a>>> Footnotes<'a, 'b, I> { id, // Although the ID count is for the whole page, the footnote reference // are local to the item so we make this ID "local" when displayed. - id - *self.existing_footnotes + id - self.start_id ); Event::Html(reference.into()) } @@ -64,7 +71,7 @@ impl<'a, 'b, I: Iterator<Item = SpannedEvent<'a>>> Footnotes<'a, 'b, I> { } } -impl<'a, I: Iterator<Item = SpannedEvent<'a>>> Iterator for Footnotes<'a, '_, I> { +impl<'a, I: Iterator<Item = SpannedEvent<'a>>> Iterator for Footnotes<'a, I> { type Item = SpannedEvent<'a>; fn next(&mut self) -> Option<Self::Item> { @@ -87,7 +94,7 @@ impl<'a, I: Iterator<Item = SpannedEvent<'a>>> Iterator for Footnotes<'a, '_, I> // After all the markdown is emmited, emit an <hr> then all the footnotes // in a list. let defs: Vec<_> = self.footnotes.drain(..).map(|(_, x)| x).collect(); - *self.existing_footnotes += defs.len(); + self.existing_footnotes.fetch_add(defs.len(), Ordering::Relaxed); let defs_html = render_footnotes_defs(defs); return Some((Event::Html(defs_html.into()), 0..0)); } else { diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index f4367257572..e013829e5e0 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -1904,7 +1904,6 @@ fn render_impl( } } - let trait_is_none = trait_.is_none(); // If we've implemented a trait, then also emit documentation for all // default items which weren't overridden in the implementation block. // We don't emit documentation for default items if they appear in the @@ -1936,6 +1935,23 @@ fn render_impl( if rendering_params.toggle_open_by_default { " open" } else { "" } ); } + + let (before_dox, after_dox) = i + .impl_item + .opt_doc_value() + .map(|dox| { + Markdown { + content: &*dox, + links: &i.impl_item.links(cx), + ids: &mut cx.id_map.borrow_mut(), + error_codes: cx.shared.codes, + edition: cx.shared.edition(), + playground: &cx.shared.playground, + heading_offset: HeadingOffset::H4, + } + .split_summary_and_content() + }) + .unwrap_or((None, None)); render_impl_summary( w, cx, @@ -1944,33 +1960,23 @@ fn render_impl( rendering_params.show_def_docs, use_absolute, aliases, + &before_dox, ); if toggled { w.write_str("</summary>"); } - if let Some(ref dox) = i.impl_item.opt_doc_value() { - if trait_is_none && impl_.items.is_empty() { + if before_dox.is_some() { + if trait_.is_none() && impl_.items.is_empty() { w.write_str( "<div class=\"item-info\">\ <div class=\"stab empty-impl\">This impl block contains no items.</div>\ </div>", ); } - write!( - w, - "<div class=\"docblock\">{}</div>", - Markdown { - content: dox, - links: &i.impl_item.links(cx), - ids: &mut cx.id_map.borrow_mut(), - error_codes: cx.shared.codes, - edition: cx.shared.edition(), - playground: &cx.shared.playground, - heading_offset: HeadingOffset::H4, - } - .into_string() - ); + if let Some(after_dox) = after_dox { + write!(w, "<div class=\"docblock\">{after_dox}</div>"); + } } if !default_impl_items.is_empty() || !impl_items.is_empty() { w.write_str("<div class=\"impl-items\">"); @@ -2031,6 +2037,7 @@ pub(crate) fn render_impl_summary( // This argument is used to reference same type with different paths to avoid duplication // in documentation pages for trait with automatic implementations like "Send" and "Sync". aliases: &[String], + doc: &Option<String>, ) { let inner_impl = i.inner_impl(); let id = cx.derive_id(get_id_for_impl(cx.tcx(), i.impl_item.item_id)); @@ -2082,6 +2089,10 @@ pub(crate) fn render_impl_summary( ); } + if let Some(doc) = doc { + write!(w, "<div class=\"docblock\">{doc}</div>"); + } + w.write_str("</section>"); } diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 90aa5904daf..27496381b2c 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -2210,6 +2210,39 @@ details.toggle[open] > summary::after { content: "Collapse"; } +details.toggle:not([open]) > summary .docblock { + max-height: calc(1.5em + 0.75em); + overflow-y: hidden; +} +details.toggle:not([open]) > summary .docblock > :first-child { + max-width: 100%; + overflow: hidden; + width: fit-content; + white-space: nowrap; + position: relative; + padding-right: 1em; +} +details.toggle:not([open]) > summary .docblock > :first-child::after { + content: "…"; + position: absolute; + right: 0; + top: 0; + bottom: 0; + z-index: 1; + background-color: var(--main-background-color); + font: 1rem/1.5 "Source Serif 4", NanumBarunGothic, serif; + /* To make it look a bit better and not have it stuck to the preceding element. */ + padding-left: 0.2em; +} +details.toggle:not([open]) > summary .docblock > div:first-child::after { + /* This is to make the "..." always appear at the bottom. */ + padding-top: calc(1.5em + 0.75em - 1.2rem); +} + +details.toggle > summary .docblock { + margin-top: 0.75em; +} + /* This is needed in docblocks to have the "▶" element to be on the same line. */ .docblock summary > * { display: inline-block; diff --git a/src/tools/cargo b/src/tools/cargo -Subproject 05f54fdc34310f458033af8a63ce1d699fae8bf +Subproject 20a443231846b81c7b909691ec3f15eb173f2b1 diff --git a/src/tools/miri/src/alloc_addresses/mod.rs b/src/tools/miri/src/alloc_addresses/mod.rs index fe7d8db245b..f7295fd7d8a 100644 --- a/src/tools/miri/src/alloc_addresses/mod.rs +++ b/src/tools/miri/src/alloc_addresses/mod.rs @@ -286,9 +286,9 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { - fn expose_ptr(&mut self, alloc_id: AllocId, tag: BorTag) -> InterpResult<'tcx> { - let this = self.eval_context_mut(); - let global_state = this.machine.alloc_addresses.get_mut(); + fn expose_ptr(&self, alloc_id: AllocId, tag: BorTag) -> InterpResult<'tcx> { + let this = self.eval_context_ref(); + let mut global_state = this.machine.alloc_addresses.borrow_mut(); // In strict mode, we don't need this, so we can save some cycles by not tracking it. if global_state.provenance_mode == ProvenanceMode::Strict { return interp_ok(()); @@ -299,8 +299,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { return interp_ok(()); } trace!("Exposing allocation id {alloc_id:?}"); - let global_state = this.machine.alloc_addresses.get_mut(); global_state.exposed.insert(alloc_id); + // Release the global state before we call `expose_tag`, which may call `get_alloc_info_extra`, + // which may need access to the global state. + drop(global_state); if this.machine.borrow_tracker.is_some() { this.expose_tag(alloc_id, tag)?; } diff --git a/src/tools/miri/src/borrow_tracker/mod.rs b/src/tools/miri/src/borrow_tracker/mod.rs index 4883613dea5..9808102f4ba 100644 --- a/src/tools/miri/src/borrow_tracker/mod.rs +++ b/src/tools/miri/src/borrow_tracker/mod.rs @@ -302,8 +302,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } } - fn expose_tag(&mut self, alloc_id: AllocId, tag: BorTag) -> InterpResult<'tcx> { - let this = self.eval_context_mut(); + fn expose_tag(&self, alloc_id: AllocId, tag: BorTag) -> InterpResult<'tcx> { + let this = self.eval_context_ref(); let method = this.machine.borrow_tracker.as_ref().unwrap().borrow().borrow_tracker_method; match method { BorrowTrackerMethod::StackedBorrows => this.sb_expose_tag(alloc_id, tag), diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs index a855603eeb3..ea75131078e 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs @@ -1011,8 +1011,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } /// Mark the given tag as exposed. It was found on a pointer with the given AllocId. - fn sb_expose_tag(&mut self, alloc_id: AllocId, tag: BorTag) -> InterpResult<'tcx> { - let this = self.eval_context_mut(); + fn sb_expose_tag(&self, alloc_id: AllocId, tag: BorTag) -> InterpResult<'tcx> { + let this = self.eval_context_ref(); // Function pointers and dead objects don't have an alloc_extra so we ignore them. // This is okay because accessing them is UB anyway, no need for any Stacked Borrows checks. diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs index 8469744bbc4..9fb81453ec6 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs @@ -532,8 +532,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } /// Mark the given tag as exposed. It was found on a pointer with the given AllocId. - fn tb_expose_tag(&mut self, alloc_id: AllocId, tag: BorTag) -> InterpResult<'tcx> { - let this = self.eval_context_mut(); + fn tb_expose_tag(&self, alloc_id: AllocId, tag: BorTag) -> InterpResult<'tcx> { + let this = self.eval_context_ref(); // Function pointers and dead objects don't have an alloc_extra so we ignore them. // This is okay because accessing them is UB anyway, no need for any Tree Borrows checks. diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 814dc6d2b01..888465c5262 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -270,6 +270,9 @@ impl interpret::Provenance for Provenance { /// We use absolute addresses in the `offset` of a `StrictPointer`. const OFFSET_IS_ADDR: bool = true; + /// Miri implements wildcard provenance. + const WILDCARD: Option<Self> = Some(Provenance::Wildcard); + fn get_alloc_id(self) -> Option<AllocId> { match self { Provenance::Concrete { alloc_id, .. } => Some(alloc_id), @@ -1242,8 +1245,8 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { /// Called on `ptr as usize` casts. /// (Actually computing the resulting `usize` doesn't need machine help, /// that's just `Scalar::try_to_int`.) - fn expose_ptr(ecx: &mut InterpCx<'tcx, Self>, ptr: StrictPointer) -> InterpResult<'tcx> { - match ptr.provenance { + fn expose_provenance(ecx: &InterpCx<'tcx, Self>, provenance: Self::Provenance) -> InterpResult<'tcx> { + match provenance { Provenance::Concrete { alloc_id, tag } => ecx.expose_ptr(alloc_id, tag), Provenance::Wildcard => { // No need to do anything for wildcard pointers as diff --git a/src/tools/miri/src/shims/io_error.rs b/src/tools/miri/src/shims/io_error.rs index 0cbb4850b7f..634dbd9f953 100644 --- a/src/tools/miri/src/shims/io_error.rs +++ b/src/tools/miri/src/shims/io_error.rs @@ -44,7 +44,7 @@ const UNIX_IO_ERROR_TABLE: &[(&str, std::io::ErrorKind)] = { ("ECONNREFUSED", ConnectionRefused), ("ECONNRESET", ConnectionReset), ("EDEADLK", Deadlock), - ("EDQUOT", FilesystemQuotaExceeded), + ("EDQUOT", QuotaExceeded), ("EEXIST", AlreadyExists), ("EFBIG", FileTooLarge), ("EHOSTUNREACH", HostUnreachable), diff --git a/src/tools/miri/src/shims/native_lib.rs b/src/tools/miri/src/shims/native_lib.rs index e7a4251242e..4082b8eed45 100644 --- a/src/tools/miri/src/shims/native_lib.rs +++ b/src/tools/miri/src/shims/native_lib.rs @@ -3,8 +3,11 @@ use std::ops::Deref; use libffi::high::call as ffi; use libffi::low::CodePtr; -use rustc_abi::{BackendRepr, HasDataLayout}; -use rustc_middle::ty::{self as ty, IntTy, UintTy}; +use rustc_abi::{BackendRepr, HasDataLayout, Size}; +use rustc_middle::{ + mir::interpret::Pointer, + ty::{self as ty, IntTy, UintTy}, +}; use rustc_span::Symbol; use crate::*; @@ -75,6 +78,11 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { unsafe { ffi::call::<()>(ptr, libffi_args.as_slice()) }; return interp_ok(ImmTy::uninit(dest.layout)); } + ty::RawPtr(..) => { + let x = unsafe { ffi::call::<*const ()>(ptr, libffi_args.as_slice()) }; + let ptr = Pointer::new(Provenance::Wildcard, Size::from_bytes(x.addr())); + Scalar::from_pointer(ptr, this) + } _ => throw_unsup_format!("unsupported return type for native call: {:?}", link_name), }; interp_ok(ImmTy::from_scalar(scalar, dest.layout)) @@ -152,8 +160,26 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { if !matches!(arg.layout.backend_repr, BackendRepr::Scalar(_)) { throw_unsup_format!("only scalar argument types are support for native calls") } - libffi_args.push(imm_to_carg(this.read_immediate(arg)?, this)?); + let imm = this.read_immediate(arg)?; + libffi_args.push(imm_to_carg(&imm, this)?); + // If we are passing a pointer, prepare the memory it points to. + if matches!(arg.layout.ty.kind(), ty::RawPtr(..)) { + let ptr = imm.to_scalar().to_pointer(this)?; + let Some(prov) = ptr.provenance else { + // Pointer without provenance may not access any memory. + continue; + }; + // We use `get_alloc_id` for its best-effort behaviour with Wildcard provenance. + let Some(alloc_id) = prov.get_alloc_id() else { + // Wildcard pointer, whatever it points to must be already exposed. + continue; + }; + this.prepare_for_native_call(alloc_id, prov)?; + } } + + // FIXME: In the future, we should also call `prepare_for_native_call` on all previously + // exposed allocations, since C may access any of them. // Convert them to `libffi::high::Arg` type. let libffi_args = libffi_args @@ -220,7 +246,7 @@ impl<'a> CArg { /// Extract the scalar value from the result of reading a scalar from the machine, /// and convert it to a `CArg`. -fn imm_to_carg<'tcx>(v: ImmTy<'tcx>, cx: &impl HasDataLayout) -> InterpResult<'tcx, CArg> { +fn imm_to_carg<'tcx>(v: &ImmTy<'tcx>, cx: &impl HasDataLayout) -> InterpResult<'tcx, CArg> { interp_ok(match v.layout.ty.kind() { // If the primitive provided can be converted to a type matching the type pattern // then create a `CArg` of this primitive value with the corresponding `CArg` constructor. @@ -238,18 +264,10 @@ fn imm_to_carg<'tcx>(v: ImmTy<'tcx>, cx: &impl HasDataLayout) -> InterpResult<'t ty::Uint(UintTy::U64) => CArg::UInt64(v.to_scalar().to_u64()?), ty::Uint(UintTy::Usize) => CArg::USize(v.to_scalar().to_target_usize(cx)?.try_into().unwrap()), - ty::RawPtr(_, mutability) => { - // Arbitrary mutable pointer accesses are not currently supported in Miri. - if mutability.is_mut() { - throw_unsup_format!( - "unsupported mutable pointer type for native call: {}", - v.layout.ty - ); - } else { - let s = v.to_scalar().to_pointer(cx)?.addr(); - // This relies on the `expose_provenance` in `addr_from_alloc_id`. - CArg::RawPtr(std::ptr::with_exposed_provenance_mut(s.bytes_usize())) - } + ty::RawPtr(..) => { + let s = v.to_scalar().to_pointer(cx)?.addr(); + // This relies on the `expose_provenance` in `addr_from_alloc_id`. + CArg::RawPtr(std::ptr::with_exposed_provenance_mut(s.bytes_usize())) } _ => throw_unsup_format!("unsupported argument type for native call: {}", v.layout.ty), }) diff --git a/src/tools/miri/tests/native-lib/pass/ptr_read_access.rs b/src/tools/miri/tests/native-lib/pass/ptr_read_access.rs index 46eb5778b32..3ccfecc6fb3 100644 --- a/src/tools/miri/tests/native-lib/pass/ptr_read_access.rs +++ b/src/tools/miri/tests/native-lib/pass/ptr_read_access.rs @@ -3,17 +3,14 @@ //@only-on-host fn main() { - test_pointer(); - - test_simple(); - - test_nested(); - - test_static(); + test_access_pointer(); + test_access_simple(); + test_access_nested(); + test_access_static(); } -// Test void function that dereferences a pointer and prints its contents from C. -fn test_pointer() { +/// Test function that dereferences an int pointer and prints its contents from C. +fn test_access_pointer() { extern "C" { fn print_pointer(ptr: *const i32); } @@ -23,8 +20,8 @@ fn test_pointer() { unsafe { print_pointer(&x) }; } -// Test function that dereferences a simple struct pointer and accesses a field. -fn test_simple() { +/// Test function that dereferences a simple struct pointer and accesses a field. +fn test_access_simple() { #[repr(C)] struct Simple { field: i32, @@ -39,8 +36,8 @@ fn test_simple() { assert_eq!(unsafe { access_simple(&simple) }, -42); } -// Test function that dereferences nested struct pointers and accesses fields. -fn test_nested() { +/// Test function that dereferences nested struct pointers and accesses fields. +fn test_access_nested() { use std::ptr::NonNull; #[derive(Debug, PartialEq, Eq)] @@ -61,8 +58,8 @@ fn test_nested() { assert_eq!(unsafe { access_nested(&nested_2) }, 97); } -// Test function that dereferences static struct pointers and accesses fields. -fn test_static() { +/// Test function that dereferences a static struct pointer and accesses fields. +fn test_access_static() { #[repr(C)] struct Static { value: i32, diff --git a/src/tools/miri/tests/native-lib/pass/ptr_write_access.rs b/src/tools/miri/tests/native-lib/pass/ptr_write_access.rs new file mode 100644 index 00000000000..4045ef3cee5 --- /dev/null +++ b/src/tools/miri/tests/native-lib/pass/ptr_write_access.rs @@ -0,0 +1,208 @@ +// Only works on Unix targets +//@ignore-target: windows wasm +//@only-on-host +//@compile-flags: -Zmiri-permissive-provenance + + +#![feature(box_as_ptr)] + +use std::mem::MaybeUninit; +use std::ptr::null; + +fn main() { + test_increment_int(); + test_init_int(); + test_init_array(); + test_init_static_inner(); + test_exposed(); + test_swap_ptr(); + test_swap_ptr_tuple(); + test_overwrite_dangling(); + test_pass_dangling(); + test_swap_ptr_triple_dangling(); + test_return_ptr(); +} + +/// Test function that modifies an int. +fn test_increment_int() { + extern "C" { + fn increment_int(ptr: *mut i32); + } + + let mut x = 11; + + unsafe { increment_int(&mut x) }; + assert_eq!(x, 12); +} + +/// Test function that initializes an int. +fn test_init_int() { + extern "C" { + fn init_int(ptr: *mut i32, val: i32); + } + + let mut x = MaybeUninit::<i32>::uninit(); + let val = 21; + + let x = unsafe { + init_int(x.as_mut_ptr(), val); + x.assume_init() + }; + assert_eq!(x, val); +} + +/// Test function that initializes an array. +fn test_init_array() { + extern "C" { + fn init_array(ptr: *mut i32, len: usize, val: i32); + } + + const LEN: usize = 3; + let mut array = MaybeUninit::<[i32; LEN]>::uninit(); + let val = 31; + + let array = unsafe { + init_array(array.as_mut_ptr().cast::<i32>(), LEN, val); + array.assume_init() + }; + assert_eq!(array, [val; LEN]); +} + +/// Test function that initializes an int pointed to by an immutable static. +fn test_init_static_inner() { + #[repr(C)] + struct SyncPtr { + ptr: *mut i32 + } + unsafe impl Sync for SyncPtr {} + + extern "C" { + fn init_static_inner(s_ptr: *const SyncPtr, val: i32); + } + + static mut INNER: MaybeUninit<i32> = MaybeUninit::uninit(); + #[allow(static_mut_refs)] + static STATIC: SyncPtr = SyncPtr { ptr: unsafe { INNER.as_mut_ptr() } }; + let val = 41; + + let inner = unsafe { + init_static_inner(&STATIC, val); + INNER.assume_init() + }; + assert_eq!(inner, val); +} + +// Test function that marks an allocation as exposed. +fn test_exposed() { + extern "C" { + fn ignore_ptr(ptr: *const i32); + } + + let x = 51; + let ptr = &raw const x; + let p = ptr.addr(); + + unsafe { ignore_ptr(ptr) }; + assert_eq!(unsafe { *(p as *const i32) }, x); +} + +/// Test function that swaps two pointers and exposes the alloc of an int. +fn test_swap_ptr() { + extern "C" { + fn swap_ptr(pptr0: *mut *const i32, pptr1: *mut *const i32); + } + + let x = 61; + let (mut ptr0, mut ptr1) = (&raw const x, null()); + + unsafe { swap_ptr(&mut ptr0, &mut ptr1) }; + assert_eq!(unsafe { *ptr1 }, x); +} + +/// Test function that swaps two pointers in a struct and exposes the alloc of an int. +fn test_swap_ptr_tuple() { + #[repr(C)] + struct Tuple { + ptr0: *const i32, + ptr1: *const i32, + } + + extern "C" { + fn swap_ptr_tuple(t_ptr: *mut Tuple); + } + + let x = 71; + let mut tuple = Tuple { ptr0: &raw const x, ptr1: null() }; + + unsafe { swap_ptr_tuple(&mut tuple) } + assert_eq!(unsafe { *tuple.ptr1 }, x); +} + +/// Test function that interacts with a dangling pointer. +fn test_overwrite_dangling() { + extern "C" { + fn overwrite_ptr(pptr: *mut *const i32); + } + + let b = Box::new(81); + let mut ptr = Box::as_ptr(&b); + drop(b); + + unsafe { overwrite_ptr(&mut ptr) }; + assert_eq!(ptr, null()); +} + +/// Test function that passes a dangling pointer. +fn test_pass_dangling() { + extern "C" { + fn ignore_ptr(ptr: *const i32); + } + + let b = Box::new(91); + let ptr = Box::as_ptr(&b); + drop(b); + + unsafe { ignore_ptr(ptr) }; +} + +/// Test function that interacts with a struct storing a dangling pointer. +fn test_swap_ptr_triple_dangling() { + #[repr(C)] + struct Triple { + ptr0: *const i32, + ptr1: *const i32, + ptr2: *const i32, + } + + extern "C" { + fn swap_ptr_triple_dangling(t_ptr: *const Triple); + } + + let x = 101; + let b = Box::new(111); + let ptr = Box::as_ptr(&b); + drop(b); + let z = 121; + let triple = Triple { + ptr0: &raw const x, + ptr1: ptr, + ptr2: &raw const z + }; + + unsafe { swap_ptr_triple_dangling(&triple) } + assert_eq!(unsafe { *triple.ptr2 }, x); +} + + +/// Test function that directly returns its pointer argument. +fn test_return_ptr() { + extern "C" { + fn return_ptr(ptr: *const i32) -> *const i32; + } + + let x = 131; + let ptr = &raw const x; + + let ptr = unsafe { return_ptr(ptr) }; + assert_eq!(unsafe { *ptr }, x); +} diff --git a/src/tools/miri/tests/native-lib/ptr_read_access.c b/src/tools/miri/tests/native-lib/ptr_read_access.c index 540845d53a7..3b427d6033e 100644 --- a/src/tools/miri/tests/native-lib/ptr_read_access.c +++ b/src/tools/miri/tests/native-lib/ptr_read_access.c @@ -3,13 +3,13 @@ // See comments in build_native_lib() #define EXPORT __attribute__((visibility("default"))) -/* Test: test_pointer */ +/* Test: test_access_pointer */ EXPORT void print_pointer(const int *ptr) { printf("printing pointer dereference from C: %d\n", *ptr); } -/* Test: test_simple */ +/* Test: test_access_simple */ typedef struct Simple { int field; @@ -19,7 +19,7 @@ EXPORT int access_simple(const Simple *s_ptr) { return s_ptr->field; } -/* Test: test_nested */ +/* Test: test_access_nested */ typedef struct Nested { int value; @@ -38,7 +38,7 @@ EXPORT int access_nested(const Nested *n_ptr) { return n_ptr->value; } -/* Test: test_static */ +/* Test: test_access_static */ typedef struct Static { int value; diff --git a/src/tools/miri/tests/native-lib/ptr_write_access.c b/src/tools/miri/tests/native-lib/ptr_write_access.c new file mode 100644 index 00000000000..b54c5d86b21 --- /dev/null +++ b/src/tools/miri/tests/native-lib/ptr_write_access.c @@ -0,0 +1,90 @@ +#include <stddef.h> + +// See comments in build_native_lib() +#define EXPORT __attribute__((visibility("default"))) + +/* Test: test_increment_int */ + +EXPORT void increment_int(int *ptr) { + *ptr += 1; +} + +/* Test: test_init_int */ + +EXPORT void init_int(int *ptr, int val) { + *ptr = val; +} + +/* Test: test_init_array */ + +EXPORT void init_array(int *array, size_t len, int val) { + for (size_t i = 0; i < len; i++) { + array[i] = val; + } +} + +/* Test: test_init_static_inner */ + +typedef struct SyncPtr { + int *ptr; +} SyncPtr; + +EXPORT void init_static_inner(const SyncPtr *s_ptr, int val) { + *(s_ptr->ptr) = val; +} + +/* Tests: test_exposed, test_pass_dangling */ + +EXPORT void ignore_ptr(__attribute__((unused)) const int *ptr) { + return; +} + +/* Test: test_expose_int */ +EXPORT void expose_int(const int *int_ptr, const int **pptr) { + *pptr = int_ptr; +} + +/* Test: test_swap_ptr */ + +EXPORT void swap_ptr(const int **pptr0, const int **pptr1) { + const int *tmp = *pptr0; + *pptr0 = *pptr1; + *pptr1 = tmp; +} + +/* Test: test_swap_ptr_tuple */ + +typedef struct Tuple { + int *ptr0; + int *ptr1; +} Tuple; + +EXPORT void swap_ptr_tuple(Tuple *t_ptr) { + int *tmp = t_ptr->ptr0; + t_ptr->ptr0 = t_ptr->ptr1; + t_ptr->ptr1 = tmp; +} + +/* Test: test_overwrite_dangling */ + +EXPORT void overwrite_ptr(const int **pptr) { + *pptr = NULL; +} + +/* Test: test_swap_ptr_triple_dangling */ + +typedef struct Triple { + int *ptr0; + int *ptr1; + int *ptr2; +} Triple; + +EXPORT void swap_ptr_triple_dangling(Triple *t_ptr) { + int *tmp = t_ptr->ptr0; + t_ptr->ptr0 = t_ptr->ptr2; + t_ptr->ptr2 = tmp; +} + +EXPORT const int *return_ptr(const int *ptr) { + return ptr; +} diff --git a/src/tools/miri/tests/pass/async-closure-captures.rs b/src/tools/miri/tests/pass/async-closure-captures.rs index 423ef7a5cf7..979a6d1cbe0 100644 --- a/src/tools/miri/tests/pass/async-closure-captures.rs +++ b/src/tools/miri/tests/pass/async-closure-captures.rs @@ -1,6 +1,6 @@ // Same as rustc's `tests/ui/async-await/async-closures/captures.rs`, keep in sync -#![feature(async_closure, noop_waker, async_trait_bounds)] +#![feature(async_closure, async_trait_bounds)] use std::future::Future; use std::pin::pin; diff --git a/src/tools/miri/tests/pass/async-closure-drop.rs b/src/tools/miri/tests/pass/async-closure-drop.rs index 264da5a9518..ad9822fa46d 100644 --- a/src/tools/miri/tests/pass/async-closure-drop.rs +++ b/src/tools/miri/tests/pass/async-closure-drop.rs @@ -1,4 +1,4 @@ -#![feature(async_closure, noop_waker, async_trait_bounds)] +#![feature(async_closure, async_trait_bounds)] use std::future::Future; use std::pin::pin; diff --git a/src/tools/miri/tests/pass/async-closure.rs b/src/tools/miri/tests/pass/async-closure.rs index 721af578883..979b83687e4 100644 --- a/src/tools/miri/tests/pass/async-closure.rs +++ b/src/tools/miri/tests/pass/async-closure.rs @@ -1,4 +1,4 @@ -#![feature(async_closure, noop_waker, async_fn_traits)] +#![feature(async_closure, async_fn_traits)] #![allow(unused)] use std::future::Future; diff --git a/src/tools/miri/tests/pass/async-drop.rs b/src/tools/miri/tests/pass/async-drop.rs index 53e3476f620..a455f377e85 100644 --- a/src/tools/miri/tests/pass/async-drop.rs +++ b/src/tools/miri/tests/pass/async-drop.rs @@ -6,7 +6,7 @@ // please consider modifying rustc's async drop test at // `tests/ui/async-await/async-drop.rs`. -#![feature(async_drop, impl_trait_in_assoc_type, noop_waker, async_closure)] +#![feature(async_drop, impl_trait_in_assoc_type, async_closure)] #![allow(incomplete_features, dead_code)] // FIXME(zetanumbers): consider AsyncDestruct::async_drop cleanup tests diff --git a/src/tools/miri/tests/pass/async-fn.rs b/src/tools/miri/tests/pass/async-fn.rs index 67ec2e26b30..42c60bb4fab 100644 --- a/src/tools/miri/tests/pass/async-fn.rs +++ b/src/tools/miri/tests/pass/async-fn.rs @@ -1,5 +1,4 @@ #![feature(never_type)] -#![feature(noop_waker)] use std::future::Future; diff --git a/src/tools/miri/tests/pass/dyn-star.rs b/src/tools/miri/tests/pass/dyn-star.rs index dab589b4651..1ce0dd3c9d5 100644 --- a/src/tools/miri/tests/pass/dyn-star.rs +++ b/src/tools/miri/tests/pass/dyn-star.rs @@ -1,7 +1,6 @@ #![feature(dyn_star)] #![allow(incomplete_features)] #![feature(custom_inner_attributes)] -#![feature(noop_waker)] // rustfmt destroys `dyn* Trait` syntax #![rustfmt::skip] diff --git a/src/tools/miri/tests/pass/future-self-referential.rs b/src/tools/miri/tests/pass/future-self-referential.rs index 8aeb26a7a95..88d52d8f1c1 100644 --- a/src/tools/miri/tests/pass/future-self-referential.rs +++ b/src/tools/miri/tests/pass/future-self-referential.rs @@ -1,6 +1,5 @@ //@revisions: stack tree //@[tree]compile-flags: -Zmiri-tree-borrows -#![feature(noop_waker)] use std::future::*; use std::marker::PhantomPinned; diff --git a/src/tools/miri/tests/pass/issues/issue-miri-2068.rs b/src/tools/miri/tests/pass/issues/issue-miri-2068.rs index ccee2221e29..1931b6c9d79 100644 --- a/src/tools/miri/tests/pass/issues/issue-miri-2068.rs +++ b/src/tools/miri/tests/pass/issues/issue-miri-2068.rs @@ -1,5 +1,3 @@ -#![feature(noop_waker)] - use std::future::Future; use std::pin::Pin; use std::task::{Context, Poll, Waker}; diff --git a/src/tools/miri/tests/pass/move-data-across-await-point.rs b/src/tools/miri/tests/pass/move-data-across-await-point.rs index 1a93a6bf664..5aafddd99b9 100644 --- a/src/tools/miri/tests/pass/move-data-across-await-point.rs +++ b/src/tools/miri/tests/pass/move-data-across-await-point.rs @@ -1,4 +1,3 @@ -#![feature(noop_waker)] use std::future::Future; use std::ptr; diff --git a/src/tools/miri/tests/ui.rs b/src/tools/miri/tests/ui.rs index 9553a37c9a8..9b9542b88a9 100644 --- a/src/tools/miri/tests/ui.rs +++ b/src/tools/miri/tests/ui.rs @@ -64,6 +64,7 @@ fn build_native_lib() -> PathBuf { // FIXME: Automate gathering of all relevant C source files in the directory. "tests/native-lib/scalar_arguments.c", "tests/native-lib/ptr_read_access.c", + "tests/native-lib/ptr_write_access.c", // Ensure we notice serious problems in the C code. "-Wall", "-Wextra", diff --git a/src/tools/publish_toolstate.py b/src/tools/publish_toolstate.py index 328b48e04d2..a639dc20a60 100755 --- a/src/tools/publish_toolstate.py +++ b/src/tools/publish_toolstate.py @@ -14,6 +14,7 @@ import json import datetime import collections import textwrap + try: import urllib2 from urllib2 import HTTPError @@ -21,7 +22,7 @@ except ImportError: import urllib.request as urllib2 from urllib.error import HTTPError try: - import typing # noqa: F401 FIXME: py2 + import typing # noqa: F401 FIXME: py2 except ImportError: pass @@ -29,40 +30,41 @@ except ImportError: # These should be collaborators of the rust-lang/rust repository (with at least # read privileges on it). CI will fail otherwise. MAINTAINERS = { - 'book': {'carols10cents'}, - 'nomicon': {'frewsxcv', 'Gankra', 'JohnTitor'}, - 'reference': {'Havvy', 'matthewjasper', 'ehuss'}, - 'rust-by-example': {'marioidival'}, - 'embedded-book': {'adamgreig', 'andre-richter', 'jamesmunns', 'therealprof'}, - 'edition-guide': {'ehuss'}, - 'rustc-dev-guide': {'spastorino', 'amanjeev', 'JohnTitor'}, + "book": {"carols10cents"}, + "nomicon": {"frewsxcv", "Gankra", "JohnTitor"}, + "reference": {"Havvy", "matthewjasper", "ehuss"}, + "rust-by-example": {"marioidival"}, + "embedded-book": {"adamgreig", "andre-richter", "jamesmunns", "therealprof"}, + "edition-guide": {"ehuss"}, + "rustc-dev-guide": {"spastorino", "amanjeev", "JohnTitor"}, } LABELS = { - 'book': ['C-bug'], - 'nomicon': ['C-bug'], - 'reference': ['C-bug'], - 'rust-by-example': ['C-bug'], - 'embedded-book': ['C-bug'], - 'edition-guide': ['C-bug'], - 'rustc-dev-guide': ['C-bug'], + "book": ["C-bug"], + "nomicon": ["C-bug"], + "reference": ["C-bug"], + "rust-by-example": ["C-bug"], + "embedded-book": ["C-bug"], + "edition-guide": ["C-bug"], + "rustc-dev-guide": ["C-bug"], } REPOS = { - 'book': 'https://github.com/rust-lang/book', - 'nomicon': 'https://github.com/rust-lang/nomicon', - 'reference': 'https://github.com/rust-lang/reference', - 'rust-by-example': 'https://github.com/rust-lang/rust-by-example', - 'embedded-book': 'https://github.com/rust-embedded/book', - 'edition-guide': 'https://github.com/rust-lang/edition-guide', - 'rustc-dev-guide': 'https://github.com/rust-lang/rustc-dev-guide', + "book": "https://github.com/rust-lang/book", + "nomicon": "https://github.com/rust-lang/nomicon", + "reference": "https://github.com/rust-lang/reference", + "rust-by-example": "https://github.com/rust-lang/rust-by-example", + "embedded-book": "https://github.com/rust-embedded/book", + "edition-guide": "https://github.com/rust-lang/edition-guide", + "rustc-dev-guide": "https://github.com/rust-lang/rustc-dev-guide", } + def load_json_from_response(resp): # type: (typing.Any) -> typing.Any content = resp.read() if isinstance(content, bytes): - content_str = content.decode('utf-8') + content_str = content.decode("utf-8") else: print("Refusing to decode " + str(type(content)) + " to str") return json.loads(content_str) @@ -70,11 +72,10 @@ def load_json_from_response(resp): def read_current_status(current_commit, path): # type: (str, str) -> typing.Mapping[str, typing.Any] - '''Reads build status of `current_commit` from content of `history/*.tsv` - ''' - with open(path, 'r') as f: + """Reads build status of `current_commit` from content of `history/*.tsv`""" + with open(path, "r") as f: for line in f: - (commit, status) = line.split('\t', 1) + (commit, status) = line.split("\t", 1) if commit == current_commit: return json.loads(status) return {} @@ -82,12 +83,12 @@ def read_current_status(current_commit, path): def gh_url(): # type: () -> str - return os.environ['TOOLSTATE_ISSUES_API_URL'] + return os.environ["TOOLSTATE_ISSUES_API_URL"] def maybe_remove_mention(message): # type: (str) -> str - if os.environ.get('TOOLSTATE_SKIP_MENTIONS') is not None: + if os.environ.get("TOOLSTATE_SKIP_MENTIONS") is not None: return message.replace("@", "") return message @@ -102,36 +103,45 @@ def issue( github_token, ): # type: (str, str, typing.Iterable[str], str, str, typing.List[str], str) -> None - '''Open an issue about the toolstate failure.''' - if status == 'test-fail': - status_description = 'has failing tests' + """Open an issue about the toolstate failure.""" + if status == "test-fail": + status_description = "has failing tests" else: - status_description = 'no longer builds' - request = json.dumps({ - 'body': maybe_remove_mention(textwrap.dedent('''\ + status_description = "no longer builds" + request = json.dumps( + { + "body": maybe_remove_mention( + textwrap.dedent("""\ Hello, this is your friendly neighborhood mergebot. After merging PR {}, I observed that the tool {} {}. A follow-up PR to the repository {} is needed to fix the fallout. cc @{}, do you think you would have time to do the follow-up work? If so, that would be great! - ''').format( - relevant_pr_number, tool, status_description, - REPOS.get(tool), relevant_pr_user - )), - 'title': '`{}` no longer builds after {}'.format(tool, relevant_pr_number), - 'assignees': list(assignees), - 'labels': labels, - }) - print("Creating issue:\n{}".format(request)) - response = urllib2.urlopen(urllib2.Request( - gh_url(), - request.encode(), - { - 'Authorization': 'token ' + github_token, - 'Content-Type': 'application/json', + """).format( + relevant_pr_number, + tool, + status_description, + REPOS.get(tool), + relevant_pr_user, + ) + ), + "title": "`{}` no longer builds after {}".format(tool, relevant_pr_number), + "assignees": list(assignees), + "labels": labels, } - )) + ) + print("Creating issue:\n{}".format(request)) + response = urllib2.urlopen( + urllib2.Request( + gh_url(), + request.encode(), + { + "Authorization": "token " + github_token, + "Content-Type": "application/json", + }, + ) + ) response.read() @@ -145,27 +155,26 @@ def update_latest( github_token, ): # type: (str, str, str, str, str, str, str) -> str - '''Updates `_data/latest.json` to match build result of the given commit. - ''' - with open('_data/latest.json', 'r+') as f: + """Updates `_data/latest.json` to match build result of the given commit.""" + with open("_data/latest.json", "r+") as f: latest = json.load(f, object_pairs_hook=collections.OrderedDict) current_status = { - os_: read_current_status(current_commit, 'history/' + os_ + '.tsv') - for os_ in ['windows', 'linux'] + os_: read_current_status(current_commit, "history/" + os_ + ".tsv") + for os_ in ["windows", "linux"] } - slug = 'rust-lang/rust' - message = textwrap.dedent('''\ + slug = "rust-lang/rust" + message = textwrap.dedent("""\ 📣 Toolstate changed by {}! Tested on commit {}@{}. Direct link to PR: <{}> - ''').format(relevant_pr_number, slug, current_commit, relevant_pr_url) + """).format(relevant_pr_number, slug, current_commit, relevant_pr_url) anything_changed = False for status in latest: - tool = status['tool'] + tool = status["tool"] changed = False create_issue_for_status = None # set to the status that caused the issue @@ -173,57 +182,70 @@ def update_latest( old = status[os_] new = s.get(tool, old) status[os_] = new - maintainers = ' '.join('@'+name for name in MAINTAINERS.get(tool, ())) + maintainers = " ".join("@" + name for name in MAINTAINERS.get(tool, ())) # comparing the strings, but they are ordered appropriately: # "test-pass" > "test-fail" > "build-fail" if new > old: # things got fixed or at least the status quo improved changed = True - message += '🎉 {} on {}: {} → {} (cc {}).\n' \ - .format(tool, os_, old, new, maintainers) + message += "🎉 {} on {}: {} → {} (cc {}).\n".format( + tool, os_, old, new, maintainers + ) elif new < old: # tests or builds are failing and were not failing before changed = True - title = '💔 {} on {}: {} → {}' \ - .format(tool, os_, old, new) - message += '{} (cc {}).\n' \ - .format(title, maintainers) + title = "💔 {} on {}: {} → {}".format(tool, os_, old, new) + message += "{} (cc {}).\n".format(title, maintainers) # See if we need to create an issue. # Create issue if things no longer build. # (No issue for mere test failures to avoid spurious issues.) - if new == 'build-fail': + if new == "build-fail": create_issue_for_status = new if create_issue_for_status is not None: try: issue( - tool, create_issue_for_status, MAINTAINERS.get(tool, ()), - relevant_pr_number, relevant_pr_user, LABELS.get(tool, []), + tool, + create_issue_for_status, + MAINTAINERS.get(tool, ()), + relevant_pr_number, + relevant_pr_user, + LABELS.get(tool, []), github_token, ) except HTTPError as e: # network errors will simply end up not creating an issue, but that's better # than failing the entire build job - print("HTTPError when creating issue for status regression: {0}\n{1!r}" - .format(e, e.read())) + print( + "HTTPError when creating issue for status regression: {0}\n{1!r}".format( + e, e.read() + ) + ) except IOError as e: - print("I/O error when creating issue for status regression: {0}".format(e)) + print( + "I/O error when creating issue for status regression: {0}".format( + e + ) + ) except: - print("Unexpected error when creating issue for status regression: {0}" - .format(sys.exc_info()[0])) + print( + "Unexpected error when creating issue for status regression: {0}".format( + sys.exc_info()[0] + ) + ) raise if changed: - status['commit'] = current_commit - status['datetime'] = current_datetime + status["commit"] = current_commit + status["datetime"] = current_datetime anything_changed = True if not anything_changed: - return '' + return "" f.seek(0) f.truncate(0) - json.dump(latest, f, indent=4, separators=(',', ': ')) + json.dump(latest, f, indent=4, separators=(",", ": ")) return message @@ -231,12 +253,12 @@ def update_latest( # There are variables declared within that are implicitly global; it is unknown # which ones precisely but at least this is true for `github_token`. try: - if __name__ != '__main__': + if __name__ != "__main__": exit(0) cur_commit = sys.argv[1] cur_datetime = datetime.datetime.now(datetime.timezone.utc).strftime( - '%Y-%m-%dT%H:%M:%SZ' + "%Y-%m-%dT%H:%M:%SZ" ) cur_commit_msg = sys.argv[2] save_message_to_path = sys.argv[3] @@ -244,21 +266,21 @@ try: # assume that PR authors are also owners of the repo where the branch lives relevant_pr_match = re.search( - r'Auto merge of #([0-9]+) - ([^:]+):[^,]+, r=(\S+)', + r"Auto merge of #([0-9]+) - ([^:]+):[^,]+, r=(\S+)", cur_commit_msg, ) if relevant_pr_match: number = relevant_pr_match.group(1) relevant_pr_user = relevant_pr_match.group(2) - relevant_pr_number = 'rust-lang/rust#' + number - relevant_pr_url = 'https://github.com/rust-lang/rust/pull/' + number + relevant_pr_number = "rust-lang/rust#" + number + relevant_pr_url = "https://github.com/rust-lang/rust/pull/" + number pr_reviewer = relevant_pr_match.group(3) else: - number = '-1' - relevant_pr_user = 'ghost' - relevant_pr_number = '<unknown PR>' - relevant_pr_url = '<unknown>' - pr_reviewer = 'ghost' + number = "-1" + relevant_pr_user = "ghost" + relevant_pr_number = "<unknown PR>" + relevant_pr_url = "<unknown>" + pr_reviewer = "ghost" message = update_latest( cur_commit, @@ -270,28 +292,30 @@ try: github_token, ) if not message: - print('<Nothing changed>') + print("<Nothing changed>") sys.exit(0) print(message) if not github_token: - print('Dry run only, not committing anything') + print("Dry run only, not committing anything") sys.exit(0) - with open(save_message_to_path, 'w') as f: + with open(save_message_to_path, "w") as f: f.write(message) # Write the toolstate comment on the PR as well. - issue_url = gh_url() + '/{}/comments'.format(number) - response = urllib2.urlopen(urllib2.Request( - issue_url, - json.dumps({'body': maybe_remove_mention(message)}).encode(), - { - 'Authorization': 'token ' + github_token, - 'Content-Type': 'application/json', - } - )) + issue_url = gh_url() + "/{}/comments".format(number) + response = urllib2.urlopen( + urllib2.Request( + issue_url, + json.dumps({"body": maybe_remove_mention(message)}).encode(), + { + "Authorization": "token " + github_token, + "Content-Type": "application/json", + }, + ) + ) response.read() except HTTPError as e: print("HTTPError: %s\n%r" % (e, e.read())) diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs index 95dfe56ff54..9a7a1a01a09 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs @@ -695,7 +695,6 @@ pub const INERT_ATTRIBUTES: &[BuiltinAttribute] = &[ template!(List: r#"cfg = "...", module = "...", kind = "...""#), DuplicatesOk, ), rustc_attr!(TEST, rustc_symbol_name, Normal, template!(Word), WarnFollowing), - rustc_attr!(TEST, rustc_polymorphize_error, Normal, template!(Word), WarnFollowing), rustc_attr!(TEST, rustc_def_path, Normal, template!(Word), WarnFollowing), rustc_attr!(TEST, rustc_mir, Normal, template!(List: "arg1, arg2, ..."), DuplicatesOk), gated!( diff --git a/src/tools/rustbook/Cargo.lock b/src/tools/rustbook/Cargo.lock index 400eb7c5e0d..024b8f9becb 100644 --- a/src/tools/rustbook/Cargo.lock +++ b/src/tools/rustbook/Cargo.lock @@ -709,31 +709,21 @@ dependencies = [ ] [[package]] -name = "mdbook-trpl-listing" +name = "mdbook-trpl" version = "0.1.0" dependencies = [ + "anyhow", "clap", "html_parser", "mdbook", - "pulldown-cmark 0.10.3", - "pulldown-cmark-to-cmark 13.0.0", + "pulldown-cmark 0.12.2", + "pulldown-cmark-to-cmark 19.0.0", "serde_json", "thiserror", "toml 0.8.19", ] [[package]] -name = "mdbook-trpl-note" -version = "1.0.0" -dependencies = [ - "clap", - "mdbook", - "pulldown-cmark 0.10.3", - "pulldown-cmark-to-cmark 13.0.0", - "serde_json", -] - -[[package]] name = "memchr" version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1010,7 +1000,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76979bea66e7875e7509c4ec5300112b316af87fa7a252ca91c448b32dfe3993" dependencies = [ "bitflags 2.6.0", - "getopts", "memchr", "pulldown-cmark-escape 0.10.1", "unicase", @@ -1029,6 +1018,19 @@ dependencies = [ ] [[package]] +name = "pulldown-cmark" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f86ba2052aebccc42cbbb3ed234b8b13ce76f75c3551a303cb2bcffcff12bb14" +dependencies = [ + "bitflags 2.6.0", + "getopts", + "memchr", + "pulldown-cmark-escape 0.11.0", + "unicase", +] + +[[package]] name = "pulldown-cmark-escape" version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1042,20 +1044,20 @@ checksum = "007d8adb5ddab6f8e3f491ac63566a7d5002cc7ed73901f72057943fa71ae1ae" [[package]] name = "pulldown-cmark-to-cmark" -version = "13.0.0" +version = "15.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f609795c8d835f79dcfcf768415b9fb57ef1b74891e99f86e73f43a7a257163b" +checksum = "b9c77db841443d89a57ae94f22d29c022f6d9f41b00bddbf1f4024dbaf4bdce1" dependencies = [ - "pulldown-cmark 0.10.3", + "pulldown-cmark 0.11.3", ] [[package]] name = "pulldown-cmark-to-cmark" -version = "15.0.1" +version = "19.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9c77db841443d89a57ae94f22d29c022f6d9f41b00bddbf1f4024dbaf4bdce1" +checksum = "7d742adcc7b655dba3e9ebab47954ca229fc0fa1df01fdc94349b6f3a2e6d257" dependencies = [ - "pulldown-cmark 0.11.3", + "pulldown-cmark 0.12.2", ] [[package]] @@ -1144,8 +1146,7 @@ dependencies = [ "mdbook", "mdbook-i18n-helpers", "mdbook-spec", - "mdbook-trpl-listing", - "mdbook-trpl-note", + "mdbook-trpl", ] [[package]] diff --git a/src/tools/rustbook/Cargo.toml b/src/tools/rustbook/Cargo.toml index 854c4547337..c2ce8fef4d0 100644 --- a/src/tools/rustbook/Cargo.toml +++ b/src/tools/rustbook/Cargo.toml @@ -9,8 +9,7 @@ edition = "2021" [dependencies] clap = "4.0.32" env_logger = "0.11" -mdbook-trpl-listing = { path = "../../doc/book/packages/mdbook-trpl-listing" } -mdbook-trpl-note = { path = "../../doc/book/packages/mdbook-trpl-note" } +mdbook-trpl = { path = "../../doc/book/packages/mdbook-trpl" } mdbook-i18n-helpers = "0.3.3" mdbook-spec = { path = "../../doc/reference/mdbook-spec" } diff --git a/src/tools/rustbook/src/main.rs b/src/tools/rustbook/src/main.rs index a1ef18610b0..33f2a51215d 100644 --- a/src/tools/rustbook/src/main.rs +++ b/src/tools/rustbook/src/main.rs @@ -6,8 +6,7 @@ use mdbook::MDBook; use mdbook::errors::Result as Result3; use mdbook_i18n_helpers::preprocessors::Gettext; use mdbook_spec::Spec; -use mdbook_trpl_listing::TrplListing; -use mdbook_trpl_note::TrplNote; +use mdbook_trpl::{Figure, Listing, Note}; fn main() { let crate_version = concat!("v", crate_version!()); @@ -109,11 +108,15 @@ pub fn build(args: &ArgMatches) -> Result3<()> { // preprocessor, or this should modify the config and use // MDBook::load_with_config. if book.config.get_preprocessor("trpl-note").is_some() { - book.with_preprocessor(TrplNote); + book.with_preprocessor(Note); } if book.config.get_preprocessor("trpl-listing").is_some() { - book.with_preprocessor(TrplListing); + book.with_preprocessor(Listing); + } + + if book.config.get_preprocessor("trpl-figure").is_some() { + book.with_preprocessor(Figure); } if book.config.get_preprocessor("spec").is_some() { diff --git a/src/tools/tidy/config/black.toml b/src/tools/tidy/config/black.toml deleted file mode 100644 index d5b8b198afb..00000000000 --- a/src/tools/tidy/config/black.toml +++ /dev/null @@ -1,18 +0,0 @@ -[tool.black] -# Ignore all submodules -extend-exclude = """(\ - src/doc/nomicon|\ - src/tools/cargo/|\ - src/doc/reference/|\ - src/doc/book/|\ - src/doc/rust-by-example/|\ - library/stdarch/|\ - src/doc/rustc-dev-guide/|\ - src/doc/edition-guide/|\ - src/llvm-project/|\ - src/doc/embedded-book/|\ - src/tools/rustc-perf/|\ - src/tools/enzyme/|\ - library/backtrace/|\ - src/gcc/ - )""" diff --git a/src/tools/tidy/config/requirements.in b/src/tools/tidy/config/requirements.in index 8938dc03243..1b2c38f2b5d 100644 --- a/src/tools/tidy/config/requirements.in +++ b/src/tools/tidy/config/requirements.in @@ -6,6 +6,5 @@ # Note: this generation step should be run with the oldest supported python # version (currently 3.9) to ensure backward compatibility -black==24.4.2 ruff==0.4.9 clang-format==18.1.7 diff --git a/src/tools/tidy/config/requirements.txt b/src/tools/tidy/config/requirements.txt index 790eabf5cf8..938179d5b3e 100644 --- a/src/tools/tidy/config/requirements.txt +++ b/src/tools/tidy/config/requirements.txt @@ -4,30 +4,6 @@ # # pip-compile --generate-hashes --strip-extras src/tools/tidy/config/requirements.in # -black==24.4.2 \ - --hash=sha256:257d724c2c9b1660f353b36c802ccece186a30accc7742c176d29c146df6e474 \ - --hash=sha256:37aae07b029fa0174d39daf02748b379399b909652a806e5708199bd93899da1 \ - --hash=sha256:415e686e87dbbe6f4cd5ef0fbf764af7b89f9057b97c908742b6008cc554b9c0 \ - --hash=sha256:48a85f2cb5e6799a9ef05347b476cce6c182d6c71ee36925a6c194d074336ef8 \ - --hash=sha256:7768a0dbf16a39aa5e9a3ded568bb545c8c2727396d063bbaf847df05b08cd96 \ - --hash=sha256:7e122b1c4fb252fd85df3ca93578732b4749d9be076593076ef4d07a0233c3e1 \ - --hash=sha256:88c57dc656038f1ab9f92b3eb5335ee9b021412feaa46330d5eba4e51fe49b04 \ - --hash=sha256:8e537d281831ad0e71007dcdcbe50a71470b978c453fa41ce77186bbe0ed6021 \ - --hash=sha256:98e123f1d5cfd42f886624d84464f7756f60ff6eab89ae845210631714f6db94 \ - --hash=sha256:accf49e151c8ed2c0cdc528691838afd217c50412534e876a19270fea1e28e2d \ - --hash=sha256:b1530ae42e9d6d5b670a34db49a94115a64596bc77710b1d05e9801e62ca0a7c \ - --hash=sha256:b9176b9832e84308818a99a561e90aa479e73c523b3f77afd07913380ae2eab7 \ - --hash=sha256:bdde6f877a18f24844e381d45e9947a49e97933573ac9d4345399be37621e26c \ - --hash=sha256:be8bef99eb46d5021bf053114442914baeb3649a89dc5f3a555c88737e5e98fc \ - --hash=sha256:bf10f7310db693bb62692609b397e8d67257c55f949abde4c67f9cc574492cc7 \ - --hash=sha256:c872b53057f000085da66a19c55d68f6f8ddcac2642392ad3a355878406fbd4d \ - --hash=sha256:d36ed1124bb81b32f8614555b34cc4259c3fbc7eec17870e8ff8ded335b58d8c \ - --hash=sha256:da33a1a5e49c4122ccdfd56cd021ff1ebc4a1ec4e2d01594fef9b6f267a9e741 \ - --hash=sha256:dd1b5a14e417189db4c7b64a6540f31730713d173f0b63e55fabd52d61d8fdce \ - --hash=sha256:e151054aa00bad1f4e1f04919542885f89f5f7d086b8a59e5000e6c616896ffb \ - --hash=sha256:eaea3008c281f1038edb473c1aa8ed8143a5535ff18f978a318f10302b254063 \ - --hash=sha256:ef703f83fc32e131e9bcc0a5094cfe85599e7109f896fe8bc96cc402f3eb4b6e - # via -r src/tools/tidy/config/requirements.in clang-format==18.1.7 \ --hash=sha256:035204410f65d03f98cb81c9c39d6d193f9987917cc88de9d0dbd01f2aa9c302 \ --hash=sha256:05c482a854287a5d21f7567186c0bd4b8dbd4a871751e655a45849185f30b931 \ @@ -45,26 +21,6 @@ clang-format==18.1.7 \ --hash=sha256:f4f77ac0f4f9a659213fedda0f2d216886c410132e6e7dd4b13f92b34e925554 \ --hash=sha256:f935d34152a2e11e55120eb9182862f432bc9789ab819f680c9f6db4edebf9e3 # via -r src/tools/tidy/config/requirements.in -click==8.1.3 \ - --hash=sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e \ - --hash=sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48 - # via black -mypy-extensions==1.0.0 \ - --hash=sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d \ - --hash=sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782 - # via black -packaging==23.1 \ - --hash=sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61 \ - --hash=sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f - # via black -pathspec==0.11.1 \ - --hash=sha256:2798de800fa92780e33acca925945e9a19a133b715067cf165b8866c15a31687 \ - --hash=sha256:d8af70af76652554bd134c22b3e8a1cc46ed7d91edcdd721ef1a0c51a84a5293 - # via black -platformdirs==4.2.2 \ - --hash=sha256:2d7a1657e36a80ea911db832a8a6ece5ee53d8de21edd5cc5879af6530b1bfee \ - --hash=sha256:38b7b51f512eed9e84a22788b4bce1de17c0adb134d6becb09836e37d8654cd3 - # via black ruff==0.4.9 \ --hash=sha256:06b60f91bfa5514bb689b500a25ba48e897d18fea14dce14b48a0c40d1635893 \ --hash=sha256:0e8e7b95673f22e0efd3571fb5b0cf71a5eaaa3cc8a776584f3b2cc878e46bff \ @@ -84,11 +40,3 @@ ruff==0.4.9 \ --hash=sha256:e91175fbe48f8a2174c9aad70438fe9cb0a5732c4159b2a10a3565fea2d94cde \ --hash=sha256:f1cb0828ac9533ba0135d148d214e284711ede33640465e706772645483427e3 # via -r src/tools/tidy/config/requirements.in -tomli==2.0.1 \ - --hash=sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc \ - --hash=sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f - # via black -typing-extensions==4.12.2 \ - --hash=sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d \ - --hash=sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8 - # via black diff --git a/src/tools/tidy/config/ruff.toml b/src/tools/tidy/config/ruff.toml index de23d93593c..4a5aa618be1 100644 --- a/src/tools/tidy/config/ruff.toml +++ b/src/tools/tidy/config/ruff.toml @@ -19,6 +19,9 @@ extend-exclude = [ "src/tools/enzyme/", "src/tools/rustc-perf/", "src/gcc/", + "compiler/rustc_codegen_gcc", + "src/tools/clippy", + "src/tools/miri", # Hack: CI runs from a subdirectory under the main checkout "../src/doc/nomicon/", "../src/tools/cargo/", @@ -34,6 +37,9 @@ extend-exclude = [ "../src/tools/enzyme/", "../src/tools/rustc-perf/", "../src/gcc/", + "../compiler/rustc_codegen_gcc", + "../src/tools/clippy", + "../src/tools/miri", ] [lint] diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index afa0b9a6760..7d3287aaeb9 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -535,6 +535,8 @@ const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[ "regalloc2", "region", "rustc-hash", + "serde", + "serde_derive", "slice-group-by", "smallvec", "stable_deref_trait", diff --git a/src/tools/tidy/src/ext_tool_checks.rs b/src/tools/tidy/src/ext_tool_checks.rs index 8f21338c7db..9792650d37d 100644 --- a/src/tools/tidy/src/ext_tool_checks.rs +++ b/src/tools/tidy/src/ext_tool_checks.rs @@ -32,9 +32,8 @@ const REL_PY_PATH: &[&str] = &["Scripts", "python3.exe"]; const REL_PY_PATH: &[&str] = &["bin", "python3"]; const RUFF_CONFIG_PATH: &[&str] = &["src", "tools", "tidy", "config", "ruff.toml"]; -const BLACK_CONFIG_PATH: &[&str] = &["src", "tools", "tidy", "config", "black.toml"]; /// Location within build directory -const RUFF_CACH_PATH: &[&str] = &["cache", "ruff_cache"]; +const RUFF_CACHE_PATH: &[&str] = &["cache", "ruff_cache"]; const PIP_REQ_PATH: &[&str] = &["src", "tools", "tidy", "config", "requirements.txt"]; pub fn check( @@ -96,7 +95,7 @@ fn check_impl( let mut cfg_path = root_path.to_owned(); cfg_path.extend(RUFF_CONFIG_PATH); let mut cache_dir = outdir.to_owned(); - cache_dir.extend(RUFF_CACH_PATH); + cache_dir.extend(RUFF_CACHE_PATH); cfg_args_ruff.extend([ "--config".as_ref(), @@ -124,33 +123,36 @@ fn check_impl( } if python_fmt { - let mut cfg_args_black = cfg_args.clone(); - let mut file_args_black = file_args.clone(); + let mut cfg_args_ruff = cfg_args.clone(); + let mut file_args_ruff = file_args.clone(); if bless { eprintln!("formatting python files"); } else { eprintln!("checking python file formatting"); - cfg_args_black.push("--check".as_ref()); + cfg_args_ruff.push("--check".as_ref()); } let mut cfg_path = root_path.to_owned(); - cfg_path.extend(BLACK_CONFIG_PATH); + cfg_path.extend(RUFF_CONFIG_PATH); + let mut cache_dir = outdir.to_owned(); + cache_dir.extend(RUFF_CACHE_PATH); - cfg_args_black.extend(["--config".as_ref(), cfg_path.as_os_str()]); + cfg_args_ruff.extend(["--config".as_ref(), cfg_path.as_os_str()]); - if file_args_black.is_empty() { - file_args_black.push(root_path.as_os_str()); + if file_args_ruff.is_empty() { + file_args_ruff.push(root_path.as_os_str()); } - let mut args = merge_args(&cfg_args_black, &file_args_black); - let res = py_runner(py_path.as_ref().unwrap(), true, None, "black", &args); + let mut args = merge_args(&cfg_args_ruff, &file_args_ruff); + args.insert(0, "format".as_ref()); + let res = py_runner(py_path.as_ref().unwrap(), true, None, "ruff", &args); if res.is_err() && show_diff { eprintln!("\npython formatting does not match! Printing diff:"); args.insert(0, "--diff".as_ref()); - let _ = py_runner(py_path.as_ref().unwrap(), true, None, "black", &args); + let _ = py_runner(py_path.as_ref().unwrap(), true, None, "ruff", &args); } // Rethrow error let _ = res?; @@ -445,7 +447,7 @@ fn shellcheck_runner(args: &[&OsStr]) -> Result<(), Error> { } let status = Command::new("shellcheck").args(args).status()?; - if status.success() { Ok(()) } else { Err(Error::FailedCheck("black")) } + if status.success() { Ok(()) } else { Err(Error::FailedCheck("shellcheck")) } } /// Check git for tracked files matching an extension diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt index ac82a17e145..3a021e189f3 100644 --- a/src/tools/tidy/src/issues.txt +++ b/src/tools/tidy/src/issues.txt @@ -510,7 +510,6 @@ ui/confuse-field-and-method/issue-2392.rs ui/confuse-field-and-method/issue-32128.rs ui/confuse-field-and-method/issue-33784.rs ui/const-generics/generic_arg_infer/issue-91614.rs -ui/const-generics/generic_const_exprs/auxiliary/issue-94287-aux.rs ui/const-generics/generic_const_exprs/const_kind_expr/issue_114151.rs ui/const-generics/generic_const_exprs/issue-100217.rs ui/const-generics/generic_const_exprs/issue-100360.rs @@ -540,7 +539,6 @@ ui/const-generics/generic_const_exprs/issue-85848.rs ui/const-generics/generic_const_exprs/issue-86710.rs ui/const-generics/generic_const_exprs/issue-89851.rs ui/const-generics/generic_const_exprs/issue-90847.rs -ui/const-generics/generic_const_exprs/issue-94287.rs ui/const-generics/generic_const_exprs/issue-94293.rs ui/const-generics/generic_const_exprs/issue-96699.rs ui/const-generics/generic_const_exprs/issue-97047-ice-1.rs @@ -3481,8 +3479,6 @@ ui/pattern/usefulness/issue-80501-or-pat-and-macro.rs ui/pattern/usefulness/issue-82772-match-box-as-struct.rs ui/pattern/usefulness/issue-85222-types-containing-non-exhaustive-types.rs ui/pattern/usefulness/issue-88747.rs -ui/polymorphization/issue-74614.rs -ui/polymorphization/issue-74636.rs ui/privacy/auxiliary/issue-117997.rs ui/privacy/auxiliary/issue-119463-extern.rs ui/privacy/auxiliary/issue-17718-const-privacy.rs diff --git a/tests/codegen-units/item-collection/static-init.rs b/tests/codegen-units/item-collection/static-init.rs index 1406fba2b98..44b80ef73a4 100644 --- a/tests/codegen-units/item-collection/static-init.rs +++ b/tests/codegen-units/item-collection/static-init.rs @@ -1,4 +1,4 @@ -//@ compile-flags:-Zprint-mono-items=eager -Zpolymorphize=on +//@ compile-flags:-Zprint-mono-items=eager #![feature(start)] @@ -6,7 +6,7 @@ pub static FN: fn() = foo::<i32>; pub fn foo<T>() {} -//~ MONO_ITEM fn foo::<T> +//~ MONO_ITEM fn foo::<i32> //~ MONO_ITEM static FN //~ MONO_ITEM fn start diff --git a/tests/codegen-units/item-collection/trait-method-default-impl.rs b/tests/codegen-units/item-collection/trait-method-default-impl.rs index b0a43d28e40..fd73786a402 100644 --- a/tests/codegen-units/item-collection/trait-method-default-impl.rs +++ b/tests/codegen-units/item-collection/trait-method-default-impl.rs @@ -1,4 +1,4 @@ -//@ compile-flags:-Zprint-mono-items=eager -Zpolymorphize=on -Zinline-mir=no +//@ compile-flags:-Zprint-mono-items=eager -Zinline-mir=no #![deny(dead_code)] #![feature(start)] @@ -29,7 +29,7 @@ impl SomeGenericTrait<u64> for i32 { // For the non-generic foo(), we should generate a codegen-item even if it // is not called anywhere - //~ MONO_ITEM fn <i32 as SomeGenericTrait<T1>>::foo + //~ MONO_ITEM fn <i32 as SomeGenericTrait<u64>>::foo } // Non-generic impl of generic trait diff --git a/tests/codegen-units/polymorphization/auxiliary/poly-dep.rs b/tests/codegen-units/polymorphization/auxiliary/poly-dep.rs deleted file mode 100644 index d6cbd282ec1..00000000000 --- a/tests/codegen-units/polymorphization/auxiliary/poly-dep.rs +++ /dev/null @@ -1,4 +0,0 @@ -//@ compile-flags: -Zpolymorphize=on - -#[inline(never)] -pub fn foo<T>() {} diff --git a/tests/codegen-units/polymorphization/poly-foreign.rs b/tests/codegen-units/polymorphization/poly-foreign.rs deleted file mode 100644 index 05dbac46d36..00000000000 --- a/tests/codegen-units/polymorphization/poly-foreign.rs +++ /dev/null @@ -1,11 +0,0 @@ -//@ aux-build:poly-dep.rs -//@ compile-flags: --crate-type=lib -Zprint-mono-items=eager -Zpolymorphize=on - -extern crate poly_dep; - -pub static FN1: fn() = poly_dep::foo::<i32>; -pub static FN2: fn() = poly_dep::foo::<u32>; - -//~ MONO_ITEM static FN1 -//~ MONO_ITEM static FN2 -//~ MONO_ITEM fn poly_dep::foo::<T> diff --git a/tests/codegen-units/polymorphization/unused_type_parameters.rs b/tests/codegen-units/polymorphization/unused_type_parameters.rs deleted file mode 100644 index 438305f112f..00000000000 --- a/tests/codegen-units/polymorphization/unused_type_parameters.rs +++ /dev/null @@ -1,315 +0,0 @@ -//@ compile-flags:-Zpolymorphize=on -Zprint-mono-items=lazy -Copt-level=1 - -#![crate_type = "rlib"] - -// This test checks that the polymorphization analysis correctly reduces the -// generated mono items. - -mod functions { - // Function doesn't have any type parameters to be unused. - pub fn no_parameters() {} - - //~ MONO_ITEM fn functions::no_parameters - - // Function has an unused type parameter. - pub fn unused<T>() {} - - //~ MONO_ITEM fn functions::unused::<T> - - // Function uses type parameter in value of a binding. - pub fn used_binding_value<T: Default>() { - let _: T = Default::default(); - } - - //~ MONO_ITEM fn functions::used_binding_value::<u32> - //~ MONO_ITEM fn functions::used_binding_value::<u64> - - // Function uses type parameter in type of a binding. - pub fn used_binding_type<T>() { - let _: Option<T> = None; - } - - //~ MONO_ITEM fn functions::used_binding_type::<u32> - //~ MONO_ITEM fn functions::used_binding_type::<u64> - - // Function uses type parameter in argument. - pub fn used_argument<T>(_: T) {} - - //~ MONO_ITEM fn functions::used_argument::<u32> - //~ MONO_ITEM fn functions::used_argument::<u64> - // - // Function uses type parameter in substitutions to another function. - pub fn used_substs<T>() { - unused::<T>() - } - - //~ MONO_ITEM fn functions::used_substs::<u32> - //~ MONO_ITEM fn functions::used_substs::<u64> -} - -mod closures { - // Function doesn't have any type parameters to be unused. - pub fn no_parameters() { - let _ = || {}; - } - - //~ MONO_ITEM fn closures::no_parameters - - // Function has an unused type parameter in parent and closure. - pub fn unused<T>() -> u32 { - let add_one = |x: u32| x + 1; - add_one(3) - } - - //~ MONO_ITEM fn closures::unused::<T>::{closure#0} - //~ MONO_ITEM fn closures::unused::<T> - - // Function has an unused type parameter in closure, but not in parent. - pub fn used_parent<T: Default>() -> u32 { - let _: T = Default::default(); - let add_one = |x: u32| x + 1; - add_one(3) - } - - //~ MONO_ITEM fn closures::used_parent::<T>::{closure#0} - //~ MONO_ITEM fn closures::used_parent::<u32> - //~ MONO_ITEM fn closures::used_parent::<u64> - - // Function uses type parameter in value of a binding in closure. - pub fn used_binding_value<T: Default>() -> T { - let x = || { - let y: T = Default::default(); - y - }; - - x() - } - - //~ MONO_ITEM fn closures::used_binding_value::<u32>::{closure#0} - //~ MONO_ITEM fn closures::used_binding_value::<u64>::{closure#0} - //~ MONO_ITEM fn closures::used_binding_value::<u32> - //~ MONO_ITEM fn closures::used_binding_value::<u64> - - // Function uses type parameter in type of a binding in closure. - pub fn used_binding_type<T>() -> Option<T> { - let x = || { - let y: Option<T> = None; - y - }; - - x() - } - - //~ MONO_ITEM fn closures::used_binding_type::<u32>::{closure#0} - //~ MONO_ITEM fn closures::used_binding_type::<u64>::{closure#0} - //~ MONO_ITEM fn closures::used_binding_type::<u32> - //~ MONO_ITEM fn closures::used_binding_type::<u64> - - // Function and closure uses type parameter in argument. - pub fn used_argument<T>(t: T) -> u32 { - let x = |_: T| 3; - x(t) - } - - //~ MONO_ITEM fn closures::used_argument::<u32>::{closure#0} - //~ MONO_ITEM fn closures::used_argument::<u64>::{closure#0} - //~ MONO_ITEM fn closures::used_argument::<u32> - //~ MONO_ITEM fn closures::used_argument::<u64> - - // Closure uses type parameter in argument. - pub fn used_argument_closure<T: Default>() -> u32 { - let t: T = Default::default(); - let x = |_: T| 3; - x(t) - } - - //~ MONO_ITEM fn closures::used_argument_closure::<u32>::{closure#0} - //~ MONO_ITEM fn closures::used_argument_closure::<u64>::{closure#0} - //~ MONO_ITEM fn closures::used_argument_closure::<u32> - //~ MONO_ITEM fn closures::used_argument_closure::<u64> - - // Closure uses type parameter as upvar. - pub fn used_upvar<T: Default>() -> T { - let x: T = Default::default(); - let y = || x; - y() - } - - //~ MONO_ITEM fn closures::used_upvar::<u32>::{closure#0} - //~ MONO_ITEM fn closures::used_upvar::<u64>::{closure#0} - //~ MONO_ITEM fn closures::used_upvar::<u32> - //~ MONO_ITEM fn closures::used_upvar::<u64> - - // Closure uses type parameter in substitutions to another function. - pub fn used_substs<T>() { - let x = || super::functions::unused::<T>(); - x() - } - - //~ MONO_ITEM fn closures::used_substs::<u32>::{closure#0} - //~ MONO_ITEM fn closures::used_substs::<u64>::{closure#0} - //~ MONO_ITEM fn closures::used_substs::<u32> - //~ MONO_ITEM fn closures::used_substs::<u64> -} - -mod methods { - pub struct Foo<F>(F); - - impl<F: Default> Foo<F> { - // Function has an unused type parameter from impl. - pub fn unused_impl() {} - - //~ MONO_ITEM fn methods::Foo::<F>::unused_impl - - // Function has an unused type parameter from impl and fn. - pub fn unused_both<G: Default>() {} - - //~ MONO_ITEM fn methods::Foo::<F>::unused_both::<G> - - // Function uses type parameter from impl. - pub fn used_impl() { - let _: F = Default::default(); - } - - //~ MONO_ITEM fn methods::Foo::<u32>::used_impl - //~ MONO_ITEM fn methods::Foo::<u64>::used_impl - - // Function uses type parameter from impl. - pub fn used_fn<G: Default>() { - let _: G = Default::default(); - } - - //~ MONO_ITEM fn methods::Foo::<F>::used_fn::<u32> - //~ MONO_ITEM fn methods::Foo::<F>::used_fn::<u64> - - // Function uses type parameter from impl. - pub fn used_both<G: Default>() { - let _: F = Default::default(); - let _: G = Default::default(); - } - - //~ MONO_ITEM fn methods::Foo::<u32>::used_both::<u32> - //~ MONO_ITEM fn methods::Foo::<u64>::used_both::<u64> - - // Function uses type parameter in substitutions to another function. - pub fn used_substs() { - super::functions::unused::<F>() - } - - //~ MONO_ITEM fn methods::Foo::<u32>::used_substs - //~ MONO_ITEM fn methods::Foo::<u64>::used_substs - - // Function has an unused type parameter from impl and fn. - pub fn closure_unused_all<G: Default>() -> u32 { - let add_one = |x: u32| x + 1; - add_one(3) - } - - //~ MONO_ITEM fn methods::Foo::<F>::closure_unused_all::<G>::{closure#0} - //~ MONO_ITEM fn methods::Foo::<F>::closure_unused_all::<G> - - // Function uses type parameter from impl and fn in closure. - pub fn closure_used_both<G: Default>() -> u32 { - let add_one = |x: u32| { - let _: F = Default::default(); - let _: G = Default::default(); - x + 1 - }; - - add_one(3) - } - - //~ MONO_ITEM fn methods::Foo::<u32>::closure_used_both::<u32>::{closure#0} - //~ MONO_ITEM fn methods::Foo::<u64>::closure_used_both::<u64>::{closure#0} - //~ MONO_ITEM fn methods::Foo::<u32>::closure_used_both::<u32> - //~ MONO_ITEM fn methods::Foo::<u64>::closure_used_both::<u64> - - // Function uses type parameter from fn in closure. - pub fn closure_used_fn<G: Default>() -> u32 { - let add_one = |x: u32| { - let _: G = Default::default(); - x + 1 - }; - - add_one(3) - } - - //~ MONO_ITEM fn methods::Foo::<F>::closure_used_fn::<u32>::{closure#0} - //~ MONO_ITEM fn methods::Foo::<F>::closure_used_fn::<u64>::{closure#0} - //~ MONO_ITEM fn methods::Foo::<F>::closure_used_fn::<u32> - //~ MONO_ITEM fn methods::Foo::<F>::closure_used_fn::<u64> - - // Function uses type parameter from impl in closure. - pub fn closure_used_impl<G: Default>() -> u32 { - let add_one = |x: u32| { - let _: F = Default::default(); - x + 1 - }; - - add_one(3) - } - - //~ MONO_ITEM fn methods::Foo::<u32>::closure_used_impl::<G>::{closure#0} - //~ MONO_ITEM fn methods::Foo::<u64>::closure_used_impl::<G>::{closure#0} - //~ MONO_ITEM fn methods::Foo::<u32>::closure_used_impl::<G> - //~ MONO_ITEM fn methods::Foo::<u64>::closure_used_impl::<G> - - // Closure uses type parameter in substitutions to another function. - pub fn closure_used_substs() { - let x = || super::functions::unused::<F>(); - x() - } - - //~ MONO_ITEM fn methods::Foo::<u32>::closure_used_substs::{closure#0} - //~ MONO_ITEM fn methods::Foo::<u64>::closure_used_substs::{closure#0} - //~ MONO_ITEM fn methods::Foo::<u32>::closure_used_substs - //~ MONO_ITEM fn methods::Foo::<u64>::closure_used_substs - } -} - -fn dispatch<T: Default>() { - functions::no_parameters(); - functions::unused::<T>(); - functions::used_binding_value::<T>(); - functions::used_binding_type::<T>(); - functions::used_argument::<T>(Default::default()); - functions::used_substs::<T>(); - - closures::no_parameters(); - let _ = closures::unused::<T>(); - let _ = closures::used_parent::<T>(); - let _ = closures::used_binding_value::<T>(); - let _ = closures::used_binding_type::<T>(); - let _ = closures::used_argument::<T>(Default::default()); - let _ = closures::used_argument_closure::<T>(); - let _ = closures::used_upvar::<T>(); - let _ = closures::used_substs::<T>(); - - methods::Foo::<T>::unused_impl(); - methods::Foo::<T>::unused_both::<T>(); - methods::Foo::<T>::used_impl(); - methods::Foo::<T>::used_fn::<T>(); - methods::Foo::<T>::used_both::<T>(); - methods::Foo::<T>::used_substs(); - let _ = methods::Foo::<T>::closure_unused_all::<T>(); - let _ = methods::Foo::<T>::closure_used_both::<T>(); - let _ = methods::Foo::<T>::closure_used_impl::<T>(); - let _ = methods::Foo::<T>::closure_used_fn::<T>(); - let _ = methods::Foo::<T>::closure_used_substs(); -} - -//~ MONO_ITEM fn dispatch::<u32> -//~ MONO_ITEM fn dispatch::<u64> - -pub fn foo() { - // Generate two copies of each function to check that where the type parameter is unused, - // there is only a single copy. - dispatch::<u32>(); - dispatch::<u64>(); -} - -//~ MONO_ITEM fn foo @@ unused_type_parameters-cgu.0[External] - -// These are all the items that aren't relevant to the test. -//~ MONO_ITEM fn <u32 as std::default::Default>::default -//~ MONO_ITEM fn <u64 as std::default::Default>::default diff --git a/tests/codegen/emcripten-catch-unwind.rs b/tests/codegen/emcripten-catch-unwind.rs index 35444db9558..b15fb40b68f 100644 --- a/tests/codegen/emcripten-catch-unwind.rs +++ b/tests/codegen/emcripten-catch-unwind.rs @@ -57,7 +57,7 @@ pub unsafe fn test_catch_unwind( // CHECK: [[IS_RUST_EXN_I8:%.*]] = zext i1 [[IS_RUST_EXN]] to i8 // CHECK: store ptr [[EXCEPTION]], ptr [[ALLOCA]] - // CHECK: [[IS_RUST_SLOT:%.*]] = getelementptr inbounds i8, ptr [[ALLOCA]], [[PTR_SIZE]] + // CHECK: [[IS_RUST_SLOT:%.*]] = getelementptr inbounds{{( nuw)?}} i8, ptr [[ALLOCA]], [[PTR_SIZE]] // CHECK: store i8 [[IS_RUST_EXN_I8]], ptr [[IS_RUST_SLOT]] // CHECK: call void %catch_fn(ptr %data, ptr nonnull [[ALLOCA]]) diff --git a/tests/codegen/issues/issue-118306.rs b/tests/codegen/issues/issue-118306.rs index 8af1c6a971c..0778ab3fde9 100644 --- a/tests/codegen/issues/issue-118306.rs +++ b/tests/codegen/issues/issue-118306.rs @@ -12,7 +12,7 @@ pub fn branchy(input: u64) -> u64 { // CHECK-LABEL: @branchy( // CHECK-NEXT: start: // CHECK-NEXT: [[_2:%.*]] = and i64 [[INPUT:%.*]], 3 - // CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [4 x i64], ptr @switch.table.branchy, i64 0, i64 [[_2]] + // CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds{{( nuw)?}} [4 x i64], ptr @switch.table.branchy, i64 0, i64 [[_2]] // CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i64, ptr [[SWITCH_GEP]] // CHECK-NEXT: ret i64 [[SWITCH_LOAD]] match input % 4 { diff --git a/tests/codegen/issues/issue-122805.rs b/tests/codegen/issues/issue-122805.rs index 8e03c6c8884..16dae801ee4 100644 --- a/tests/codegen/issues/issue-122805.rs +++ b/tests/codegen/issues/issue-122805.rs @@ -17,19 +17,19 @@ // CHECK-LABEL: define{{.*}}void @convert( // CHECK-NOT: shufflevector // OPT2: store i16 -// OPT2-NEXT: getelementptr inbounds i8, {{.+}} 2 +// OPT2-NEXT: getelementptr inbounds{{( nuw)?}} i8, {{.+}} 2 // OPT2-NEXT: store i16 -// OPT2-NEXT: getelementptr inbounds i8, {{.+}} 4 +// OPT2-NEXT: getelementptr inbounds{{( nuw)?}} i8, {{.+}} 4 // OPT2-NEXT: store i16 -// OPT2-NEXT: getelementptr inbounds i8, {{.+}} 6 +// OPT2-NEXT: getelementptr inbounds{{( nuw)?}} i8, {{.+}} 6 // OPT2-NEXT: store i16 -// OPT2-NEXT: getelementptr inbounds i8, {{.+}} 8 +// OPT2-NEXT: getelementptr inbounds{{( nuw)?}} i8, {{.+}} 8 // OPT2-NEXT: store i16 -// OPT2-NEXT: getelementptr inbounds i8, {{.+}} 10 +// OPT2-NEXT: getelementptr inbounds{{( nuw)?}} i8, {{.+}} 10 // OPT2-NEXT: store i16 -// OPT2-NEXT: getelementptr inbounds i8, {{.+}} 12 +// OPT2-NEXT: getelementptr inbounds{{( nuw)?}} i8, {{.+}} 12 // OPT2-NEXT: store i16 -// OPT2-NEXT: getelementptr inbounds i8, {{.+}} 14 +// OPT2-NEXT: getelementptr inbounds{{( nuw)?}} i8, {{.+}} 14 // OPT2-NEXT: store i16 // OPT3LINX64: load <8 x i16> // OPT3LINX64-NEXT: call <8 x i16> @llvm.bswap diff --git a/tests/codegen/reg-struct-return.rs b/tests/codegen/reg-struct-return.rs new file mode 100644 index 00000000000..73816745ea8 --- /dev/null +++ b/tests/codegen/reg-struct-return.rs @@ -0,0 +1,206 @@ +// Checks how `reg-struct-return` flag works with different calling conventions: +// Return struct with 8/16/32/64 bit size will be converted into i8/i16/i32/i64 +// (like abi_return_struct_as_int target spec). +// x86 only. + +//@ revisions: ENABLED DISABLED +//@ add-core-stubs +//@ compile-flags: --target i686-unknown-linux-gnu -O -C no-prepopulate-passes +//@ [ENABLED] compile-flags: -Zreg-struct-return +//@ needs-llvm-components: x86 + +#![crate_type = "lib"] +#![no_std] +#![no_core] +#![feature(no_core, lang_items)] + +extern crate minicore; +use minicore::*; + +#[repr(C)] +pub struct Foo { + x: u32, + y: u32, +} + +#[repr(C)] +pub struct Foo1 { + x: u32, +} + +#[repr(C)] +pub struct Foo2 { + x: bool, + y: bool, + z: i16, +} + +#[repr(C)] +pub struct Foo3 { + x: i16, + y: bool, + z: bool, +} + +#[repr(C)] +pub struct Foo4 { + x: char, + y: bool, + z: u8, +} + +#[repr(C)] +pub struct Foo5 { + x: u32, + y: u16, + z: u8, + a: bool, +} + +#[repr(C)] +pub struct FooOversize1 { + x: u32, + y: u32, + z: u32, +} + +#[repr(C)] +pub struct FooOversize2 { + f0: u16, + f1: u16, + f2: u16, + f3: u16, + f4: u16, +} + +#[repr(C)] +pub struct FooFloat1 { + x: f32, + y: f32, +} + +#[repr(C)] +pub struct FooFloat2 { + x: f64, +} + +#[repr(C)] +pub struct FooFloat3 { + x: f32, +} + +pub mod tests { + use { + Foo, Foo1, Foo2, Foo3, Foo4, Foo5, FooFloat1, FooFloat2, FooFloat3, FooOversize1, + FooOversize2, + }; + + // ENABLED: i64 @f1() + // DISABLED: void @f1(ptr {{.*}}sret + #[no_mangle] + pub extern "fastcall" fn f1() -> Foo { + Foo { x: 1, y: 2 } + } + + // CHECK: { i32, i32 } @f2() + #[no_mangle] + pub extern "Rust" fn f2() -> Foo { + Foo { x: 1, y: 2 } + } + + // ENABLED: i64 @f3() + // DISABLED: void @f3(ptr {{.*}}sret + #[no_mangle] + pub extern "C" fn f3() -> Foo { + Foo { x: 1, y: 2 } + } + + // ENABLED: i64 @f4() + // DISABLED: void @f4(ptr {{.*}}sret + #[no_mangle] + pub extern "cdecl" fn f4() -> Foo { + Foo { x: 1, y: 2 } + } + + // ENABLED: i64 @f5() + // DISABLED: void @f5(ptr {{.*}}sret + #[no_mangle] + pub extern "stdcall" fn f5() -> Foo { + Foo { x: 1, y: 2 } + } + + // ENABLED: i64 @f6() + // DISABLED: void @f6(ptr {{.*}}sret + #[no_mangle] + pub extern "thiscall" fn f6() -> Foo { + Foo { x: 1, y: 2 } + } + + // ENABLED: i32 @f7() + // DISABLED: void @f7(ptr {{.*}}sret + #[no_mangle] + pub extern "C" fn f7() -> Foo1 { + Foo1 { x: 1 } + } + + // ENABLED: i32 @f8() + // DISABLED: void @f8(ptr {{.*}}sret + #[no_mangle] + pub extern "C" fn f8() -> Foo2 { + Foo2 { x: true, y: false, z: 5 } + } + + // ENABLED: i32 @f9() + // DISABLED: void @f9(ptr {{.*}}sret + #[no_mangle] + pub extern "C" fn f9() -> Foo3 { + Foo3 { x: 5, y: false, z: true } + } + + // ENABLED: i64 @f10() + // DISABLED: void @f10(ptr {{.*}}sret + #[no_mangle] + pub extern "C" fn f10() -> Foo4 { + Foo4 { x: 'x', y: true, z: 170 } + } + + // ENABLED: i64 @f11() + // DISABLED: void @f11(ptr {{.*}}sret + #[no_mangle] + pub extern "C" fn f11() -> Foo5 { + Foo5 { x: 1, y: 2, z: 3, a: true } + } + + // CHECK: void @f12(ptr {{.*}}sret + #[no_mangle] + pub extern "C" fn f12() -> FooOversize1 { + FooOversize1 { x: 1, y: 2, z: 3 } + } + + // CHECK: void @f13(ptr {{.*}}sret + #[no_mangle] + pub extern "C" fn f13() -> FooOversize2 { + FooOversize2 { f0: 1, f1: 2, f2: 3, f3: 4, f4: 5 } + } + + // ENABLED: i64 @f14() + // DISABLED: void @f14(ptr {{.*}}sret + #[no_mangle] + pub extern "C" fn f14() -> FooFloat1 { + FooFloat1 { x: 1.0, y: 1.0 } + } + + // ENABLED: double @f15() + // DISABLED: void @f15(ptr {{.*}}sret + #[no_mangle] + pub extern "C" fn f15() -> FooFloat2 { + FooFloat2 { x: 1.0 } + } + + // ENABLED: float @f16() + // DISABLED: void @f16(ptr {{.*}}sret + #[no_mangle] + pub extern "C" fn f16() -> FooFloat3 { + FooFloat3 { x: 1.0 } + } +} diff --git a/tests/codegen/slice-iter-nonnull.rs b/tests/codegen/slice-iter-nonnull.rs index eda807d3682..307020b42c0 100644 --- a/tests/codegen/slice-iter-nonnull.rs +++ b/tests/codegen/slice-iter-nonnull.rs @@ -14,7 +14,7 @@ // CHECK-LABEL: @slice_iter_next( #[no_mangle] pub fn slice_iter_next<'a>(it: &mut std::slice::Iter<'a, u32>) -> Option<&'a u32> { - // CHECK: %[[ENDP:.+]] = getelementptr inbounds i8, ptr %it, {{i32 4|i64 8}} + // CHECK: %[[ENDP:.+]] = getelementptr inbounds{{( nuw)?}} i8, ptr %it, {{i32 4|i64 8}} // CHECK: %[[END:.+]] = load ptr, ptr %[[ENDP]] // CHECK-SAME: !nonnull // CHECK-SAME: !noundef @@ -31,7 +31,7 @@ pub fn slice_iter_next<'a>(it: &mut std::slice::Iter<'a, u32>) -> Option<&'a u32 // CHECK-LABEL: @slice_iter_next_back( #[no_mangle] pub fn slice_iter_next_back<'a>(it: &mut std::slice::Iter<'a, u32>) -> Option<&'a u32> { - // CHECK: %[[ENDP:.+]] = getelementptr inbounds i8, ptr %it, {{i32 4|i64 8}} + // CHECK: %[[ENDP:.+]] = getelementptr inbounds{{( nuw)?}} i8, ptr %it, {{i32 4|i64 8}} // CHECK: %[[END:.+]] = load ptr, ptr %[[ENDP]] // CHECK-SAME: !nonnull // CHECK-SAME: !noundef @@ -55,7 +55,7 @@ pub fn slice_iter_next_back<'a>(it: &mut std::slice::Iter<'a, u32>) -> Option<&' #[no_mangle] pub fn slice_iter_new(slice: &[u32]) -> std::slice::Iter<'_, u32> { // CHECK-NOT: slice - // CHECK: %[[END:.+]] = getelementptr inbounds i32{{.+}} %slice.0{{.+}} %slice.1 + // CHECK: %[[END:.+]] = getelementptr inbounds{{( nuw)?}} i32{{.+}} %slice.0{{.+}} %slice.1 // CHECK-NOT: slice // CHECK: insertvalue {{.+}} ptr %slice.0, 0 // CHECK-NOT: slice @@ -70,7 +70,7 @@ pub fn slice_iter_new(slice: &[u32]) -> std::slice::Iter<'_, u32> { #[no_mangle] pub fn slice_iter_mut_new(slice: &mut [u32]) -> std::slice::IterMut<'_, u32> { // CHECK-NOT: slice - // CHECK: %[[END:.+]] = getelementptr inbounds i32{{.+}} %slice.0{{.+}} %slice.1 + // CHECK: %[[END:.+]] = getelementptr inbounds{{( nuw)?}} i32{{.+}} %slice.0{{.+}} %slice.1 // CHECK-NOT: slice // CHECK: insertvalue {{.+}} ptr %slice.0, 0 // CHECK-NOT: slice @@ -83,7 +83,7 @@ pub fn slice_iter_mut_new(slice: &mut [u32]) -> std::slice::IterMut<'_, u32> { // CHECK-LABEL: @slice_iter_is_empty #[no_mangle] pub fn slice_iter_is_empty(it: &std::slice::Iter<'_, u32>) -> bool { - // CHECK: %[[ENDP:.+]] = getelementptr inbounds i8, ptr %it, {{i32 4|i64 8}} + // CHECK: %[[ENDP:.+]] = getelementptr inbounds{{( nuw)?}} i8, ptr %it, {{i32 4|i64 8}} // CHECK: %[[END:.+]] = load ptr, ptr %[[ENDP]] // CHECK-SAME: !nonnull // CHECK-SAME: !noundef @@ -99,7 +99,7 @@ pub fn slice_iter_is_empty(it: &std::slice::Iter<'_, u32>) -> bool { // CHECK-LABEL: @slice_iter_len #[no_mangle] pub fn slice_iter_len(it: &std::slice::Iter<'_, u32>) -> usize { - // CHECK: %[[ENDP:.+]] = getelementptr inbounds i8, ptr %it, {{i32 4|i64 8}} + // CHECK: %[[ENDP:.+]] = getelementptr inbounds{{( nuw)?}} i8, ptr %it, {{i32 4|i64 8}} // CHECK: %[[END:.+]] = load ptr, ptr %[[ENDP]] // CHECK-SAME: !nonnull // CHECK-SAME: !noundef diff --git a/tests/coverage/async.cov-map b/tests/coverage/async.cov-map index c51bc6eb621..d3eed6c4f2a 100644 --- a/tests/coverage/async.cov-map +++ b/tests/coverage/async.cov-map @@ -1,20 +1,20 @@ Function name: async::c -Raw bytes (9): 0x[01, 01, 00, 01, 01, 0c, 01, 00, 19] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 01, 00, 19] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 12, 1) to (start + 0, 25) +- Code(Counter(0)) at (prev + 11, 1) to (start + 0, 25) Highest counter ID seen: c0 Function name: async::c::{closure#0} -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 0c, 19, 01, 0e, 05, 02, 09, 00, 0a, 02, 02, 09, 00, 0a, 01, 02, 01, 00, 02] +Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 0b, 19, 01, 0e, 05, 02, 09, 00, 0a, 02, 02, 09, 00, 0a, 01, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 12, 25) to (start + 1, 14) +- Code(Counter(0)) at (prev + 11, 25) to (start + 1, 14) - Code(Counter(1)) at (prev + 2, 9) to (start + 0, 10) - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 10) = (c0 - c1) @@ -22,93 +22,93 @@ Number of file 0 mappings: 4 Highest counter ID seen: c1 Function name: async::d -Raw bytes (9): 0x[01, 01, 00, 01, 01, 14, 01, 00, 14] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 13, 01, 00, 14] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 20, 1) to (start + 0, 20) +- Code(Counter(0)) at (prev + 19, 1) to (start + 0, 20) Highest counter ID seen: c0 Function name: async::d::{closure#0} -Raw bytes (9): 0x[01, 01, 00, 01, 01, 14, 14, 00, 19] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 13, 14, 00, 19] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 20, 20) to (start + 0, 25) +- Code(Counter(0)) at (prev + 19, 20) to (start + 0, 25) Highest counter ID seen: c0 Function name: async::e (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 16, 01, 00, 14] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 15, 01, 00, 14] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 22, 1) to (start + 0, 20) +- Code(Zero) at (prev + 21, 1) to (start + 0, 20) Highest counter ID seen: (none) Function name: async::e::{closure#0} (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 16, 14, 00, 19] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 15, 14, 00, 19] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 22, 20) to (start + 0, 25) +- Code(Zero) at (prev + 21, 20) to (start + 0, 25) Highest counter ID seen: (none) Function name: async::f -Raw bytes (9): 0x[01, 01, 00, 01, 01, 18, 01, 00, 14] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 17, 01, 00, 14] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 24, 1) to (start + 0, 20) +- Code(Counter(0)) at (prev + 23, 1) to (start + 0, 20) Highest counter ID seen: c0 Function name: async::f::{closure#0} -Raw bytes (9): 0x[01, 01, 00, 01, 01, 18, 14, 00, 19] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 17, 14, 00, 19] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 24, 20) to (start + 0, 25) +- Code(Counter(0)) at (prev + 23, 20) to (start + 0, 25) Highest counter ID seen: c0 Function name: async::foo (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 1a, 01, 00, 1e] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 19, 01, 00, 1e] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 26, 1) to (start + 0, 30) +- Code(Zero) at (prev + 25, 1) to (start + 0, 30) Highest counter ID seen: (none) Function name: async::foo::{closure#0} (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 1a, 1e, 00, 2d] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 19, 1e, 00, 2d] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 26, 30) to (start + 0, 45) +- Code(Zero) at (prev + 25, 30) to (start + 0, 45) Highest counter ID seen: (none) Function name: async::g -Raw bytes (9): 0x[01, 01, 00, 01, 01, 1c, 01, 00, 17] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 1b, 01, 00, 17] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 28, 1) to (start + 0, 23) +- Code(Counter(0)) at (prev + 27, 1) to (start + 0, 23) Highest counter ID seen: c0 Function name: async::g::{closure#0} (unused) -Raw bytes (59): 0x[01, 01, 00, 0b, 00, 1c, 17, 01, 0c, 00, 02, 09, 00, 0a, 00, 00, 0e, 00, 17, 00, 00, 1b, 00, 1c, 00, 00, 20, 00, 22, 00, 01, 09, 00, 0a, 00, 00, 0e, 00, 17, 00, 00, 1b, 00, 1c, 00, 00, 20, 00, 22, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02] +Raw bytes (59): 0x[01, 01, 00, 0b, 00, 1b, 17, 01, 0c, 00, 02, 09, 00, 0a, 00, 00, 0e, 00, 17, 00, 00, 1b, 00, 1c, 00, 00, 20, 00, 22, 00, 01, 09, 00, 0a, 00, 00, 0e, 00, 17, 00, 00, 1b, 00, 1c, 00, 00, 20, 00, 22, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 11 -- Code(Zero) at (prev + 28, 23) to (start + 1, 12) +- Code(Zero) at (prev + 27, 23) to (start + 1, 12) - Code(Zero) at (prev + 2, 9) to (start + 0, 10) - Code(Zero) at (prev + 0, 14) to (start + 0, 23) - Code(Zero) at (prev + 0, 27) to (start + 0, 28) @@ -122,21 +122,21 @@ Number of file 0 mappings: 11 Highest counter ID seen: (none) Function name: async::h -Raw bytes (9): 0x[01, 01, 00, 01, 01, 24, 01, 00, 16] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 23, 01, 00, 16] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 36, 1) to (start + 0, 22) +- Code(Counter(0)) at (prev + 35, 1) to (start + 0, 22) Highest counter ID seen: c0 Function name: async::h::{closure#0} (unused) -Raw bytes (39): 0x[01, 01, 00, 07, 00, 24, 16, 03, 0c, 00, 04, 09, 00, 0a, 00, 00, 0e, 00, 19, 00, 00, 1a, 00, 1b, 00, 00, 20, 00, 22, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02] +Raw bytes (39): 0x[01, 01, 00, 07, 00, 23, 16, 03, 0c, 00, 04, 09, 00, 0a, 00, 00, 0e, 00, 19, 00, 00, 1a, 00, 1b, 00, 00, 20, 00, 22, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 7 -- Code(Zero) at (prev + 36, 22) to (start + 3, 12) +- Code(Zero) at (prev + 35, 22) to (start + 3, 12) - Code(Zero) at (prev + 4, 9) to (start + 0, 10) - Code(Zero) at (prev + 0, 14) to (start + 0, 25) - Code(Zero) at (prev + 0, 26) to (start + 0, 27) @@ -146,23 +146,23 @@ Number of file 0 mappings: 7 Highest counter ID seen: (none) Function name: async::i -Raw bytes (9): 0x[01, 01, 00, 01, 01, 2d, 01, 00, 13] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 2c, 01, 00, 13] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 45, 1) to (start + 0, 19) +- Code(Counter(0)) at (prev + 44, 1) to (start + 0, 19) Highest counter ID seen: c0 Function name: async::i::{closure#0} -Raw bytes (63): 0x[01, 01, 02, 07, 15, 0d, 11, 0b, 01, 2d, 13, 04, 0c, 09, 05, 09, 00, 0a, 01, 00, 0e, 00, 18, 05, 00, 1c, 00, 21, 09, 00, 27, 00, 30, 11, 01, 09, 00, 0a, 19, 00, 0e, 00, 17, 1d, 00, 1b, 00, 20, 11, 00, 24, 00, 26, 15, 01, 0e, 00, 10, 03, 02, 01, 00, 02] +Raw bytes (63): 0x[01, 01, 02, 07, 15, 0d, 11, 0b, 01, 2c, 13, 04, 0c, 09, 05, 09, 00, 0a, 01, 00, 0e, 00, 18, 05, 00, 1c, 00, 21, 09, 00, 27, 00, 30, 11, 01, 09, 00, 0a, 19, 00, 0e, 00, 17, 1d, 00, 1b, 00, 20, 11, 00, 24, 00, 26, 15, 01, 0e, 00, 10, 03, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Expression(1, Add), rhs = Counter(5) - expression 1 operands: lhs = Counter(3), rhs = Counter(4) Number of file 0 mappings: 11 -- Code(Counter(0)) at (prev + 45, 19) to (start + 4, 12) +- Code(Counter(0)) at (prev + 44, 19) to (start + 4, 12) - Code(Counter(2)) at (prev + 5, 9) to (start + 0, 10) - Code(Counter(0)) at (prev + 0, 14) to (start + 0, 24) - Code(Counter(1)) at (prev + 0, 28) to (start + 0, 33) @@ -177,14 +177,14 @@ Number of file 0 mappings: 11 Highest counter ID seen: c7 Function name: async::j -Raw bytes (58): 0x[01, 01, 02, 07, 0d, 05, 09, 0a, 01, 38, 01, 00, 0d, 01, 0b, 0b, 00, 0c, 05, 01, 09, 00, 0a, 01, 00, 0e, 00, 1b, 05, 00, 1f, 00, 27, 09, 01, 09, 00, 0a, 11, 00, 0e, 00, 1a, 09, 00, 1e, 00, 20, 0d, 01, 0e, 00, 10, 03, 02, 01, 00, 02] +Raw bytes (58): 0x[01, 01, 02, 07, 0d, 05, 09, 0a, 01, 37, 01, 00, 0d, 01, 0b, 0b, 00, 0c, 05, 01, 09, 00, 0a, 01, 00, 0e, 00, 1b, 05, 00, 1f, 00, 27, 09, 01, 09, 00, 0a, 11, 00, 0e, 00, 1a, 09, 00, 1e, 00, 20, 0d, 01, 0e, 00, 10, 03, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Expression(1, Add), rhs = Counter(3) - expression 1 operands: lhs = Counter(1), rhs = Counter(2) Number of file 0 mappings: 10 -- Code(Counter(0)) at (prev + 56, 1) to (start + 0, 13) +- Code(Counter(0)) at (prev + 55, 1) to (start + 0, 13) - Code(Counter(0)) at (prev + 11, 11) to (start + 0, 12) - Code(Counter(1)) at (prev + 1, 9) to (start + 0, 10) - Code(Counter(0)) at (prev + 0, 14) to (start + 0, 27) @@ -198,13 +198,13 @@ Number of file 0 mappings: 10 Highest counter ID seen: c4 Function name: async::j::c -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 3a, 05, 01, 12, 05, 02, 0d, 00, 0e, 02, 02, 0d, 00, 0e, 01, 02, 05, 00, 06] +Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 39, 05, 01, 12, 05, 02, 0d, 00, 0e, 02, 02, 0d, 00, 0e, 01, 02, 05, 00, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 58, 5) to (start + 1, 18) +- Code(Counter(0)) at (prev + 57, 5) to (start + 1, 18) - Code(Counter(1)) at (prev + 2, 13) to (start + 0, 14) - Code(Expression(0, Sub)) at (prev + 2, 13) to (start + 0, 14) = (c0 - c1) @@ -212,30 +212,30 @@ Number of file 0 mappings: 4 Highest counter ID seen: c1 Function name: async::j::d -Raw bytes (9): 0x[01, 01, 00, 01, 01, 41, 05, 00, 17] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 40, 05, 00, 17] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 65, 5) to (start + 0, 23) +- Code(Counter(0)) at (prev + 64, 5) to (start + 0, 23) Highest counter ID seen: c0 Function name: async::j::f -Raw bytes (9): 0x[01, 01, 00, 01, 01, 42, 05, 00, 17] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 41, 05, 00, 17] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 66, 5) to (start + 0, 23) +- Code(Counter(0)) at (prev + 65, 5) to (start + 0, 23) Highest counter ID seen: c0 Function name: async::k (unused) -Raw bytes (29): 0x[01, 01, 00, 05, 00, 4a, 01, 01, 0c, 00, 02, 0e, 00, 10, 00, 01, 0e, 00, 10, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02] +Raw bytes (29): 0x[01, 01, 00, 05, 00, 49, 01, 01, 0c, 00, 02, 0e, 00, 10, 00, 01, 0e, 00, 10, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 5 -- Code(Zero) at (prev + 74, 1) to (start + 1, 12) +- Code(Zero) at (prev + 73, 1) to (start + 1, 12) - Code(Zero) at (prev + 2, 14) to (start + 0, 16) - Code(Zero) at (prev + 1, 14) to (start + 0, 16) - Code(Zero) at (prev + 1, 14) to (start + 0, 16) @@ -243,14 +243,14 @@ Number of file 0 mappings: 5 Highest counter ID seen: (none) Function name: async::l -Raw bytes (33): 0x[01, 01, 02, 01, 07, 05, 09, 05, 01, 52, 01, 01, 0c, 02, 02, 0e, 00, 10, 09, 01, 0e, 00, 10, 05, 01, 0e, 00, 10, 01, 02, 01, 00, 02] +Raw bytes (33): 0x[01, 01, 02, 01, 07, 05, 09, 05, 01, 51, 01, 01, 0c, 02, 02, 0e, 00, 10, 09, 01, 0e, 00, 10, 05, 01, 0e, 00, 10, 01, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Expression(1, Add) - expression 1 operands: lhs = Counter(1), rhs = Counter(2) Number of file 0 mappings: 5 -- Code(Counter(0)) at (prev + 82, 1) to (start + 1, 12) +- Code(Counter(0)) at (prev + 81, 1) to (start + 1, 12) - Code(Expression(0, Sub)) at (prev + 2, 14) to (start + 0, 16) = (c0 - (c1 + c2)) - Code(Counter(2)) at (prev + 1, 14) to (start + 0, 16) @@ -259,29 +259,29 @@ Number of file 0 mappings: 5 Highest counter ID seen: c2 Function name: async::m -Raw bytes (9): 0x[01, 01, 00, 01, 01, 5a, 01, 00, 19] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 59, 01, 00, 19] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 90, 1) to (start + 0, 25) +- Code(Counter(0)) at (prev + 89, 1) to (start + 0, 25) Highest counter ID seen: c0 Function name: async::m::{closure#0} (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 5a, 19, 00, 22] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 59, 19, 00, 22] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 90, 25) to (start + 0, 34) +- Code(Zero) at (prev + 89, 25) to (start + 0, 34) Highest counter ID seen: (none) Function name: async::main -Raw bytes (9): 0x[01, 01, 00, 01, 01, 5c, 01, 08, 02] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 5b, 01, 08, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 92, 1) to (start + 8, 2) +- Code(Counter(0)) at (prev + 91, 1) to (start + 8, 2) Highest counter ID seen: c0 diff --git a/tests/coverage/async.coverage b/tests/coverage/async.coverage index 429fb112f33..aee76b05fb7 100644 --- a/tests/coverage/async.coverage +++ b/tests/coverage/async.coverage @@ -1,6 +1,5 @@ LL| |#![feature(coverage_attribute)] LL| |#![feature(custom_inner_attributes)] // for #![rustfmt::skip] - LL| |#![feature(noop_waker)] LL| |#![allow(unused_assignments, dead_code)] LL| |#![rustfmt::skip] LL| |//@ edition: 2018 diff --git a/tests/coverage/async.rs b/tests/coverage/async.rs index a7f3c7cec41..da0a1c0b6f0 100644 --- a/tests/coverage/async.rs +++ b/tests/coverage/async.rs @@ -1,6 +1,5 @@ #![feature(coverage_attribute)] #![feature(custom_inner_attributes)] // for #![rustfmt::skip] -#![feature(noop_waker)] #![allow(unused_assignments, dead_code)] #![rustfmt::skip] //@ edition: 2018 diff --git a/tests/coverage/async2.cov-map b/tests/coverage/async2.cov-map index d6462fded13..7660f917b65 100644 --- a/tests/coverage/async2.cov-map +++ b/tests/coverage/async2.cov-map @@ -1,58 +1,58 @@ Function name: async2::async_func -Raw bytes (9): 0x[01, 01, 00, 01, 01, 10, 01, 00, 17] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 0f, 01, 00, 17] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 16, 1) to (start + 0, 23) +- Code(Counter(0)) at (prev + 15, 1) to (start + 0, 23) Highest counter ID seen: c0 Function name: async2::async_func::{closure#0} -Raw bytes (24): 0x[01, 01, 00, 04, 01, 10, 17, 03, 09, 05, 03, 0a, 02, 06, 00, 02, 05, 00, 06, 01, 01, 01, 00, 02] +Raw bytes (24): 0x[01, 01, 00, 04, 01, 0f, 17, 03, 09, 05, 03, 0a, 02, 06, 00, 02, 05, 00, 06, 01, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 16, 23) to (start + 3, 9) +- Code(Counter(0)) at (prev + 15, 23) to (start + 3, 9) - Code(Counter(1)) at (prev + 3, 10) to (start + 2, 6) - Code(Zero) at (prev + 2, 5) to (start + 0, 6) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Highest counter ID seen: c1 Function name: async2::async_func_just_println -Raw bytes (9): 0x[01, 01, 00, 01, 01, 18, 01, 00, 24] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 17, 01, 00, 24] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 24, 1) to (start + 0, 36) +- Code(Counter(0)) at (prev + 23, 1) to (start + 0, 36) Highest counter ID seen: c0 Function name: async2::async_func_just_println::{closure#0} -Raw bytes (9): 0x[01, 01, 00, 01, 01, 18, 24, 02, 02] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 17, 24, 02, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 24, 36) to (start + 2, 2) +- Code(Counter(0)) at (prev + 23, 36) to (start + 2, 2) Highest counter ID seen: c0 Function name: async2::main -Raw bytes (9): 0x[01, 01, 00, 01, 01, 1c, 01, 07, 02] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 1b, 01, 07, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 28, 1) to (start + 7, 2) +- Code(Counter(0)) at (prev + 27, 1) to (start + 7, 2) Highest counter ID seen: c0 Function name: async2::non_async_func -Raw bytes (24): 0x[01, 01, 00, 04, 01, 08, 01, 03, 09, 05, 03, 0a, 02, 06, 00, 02, 05, 00, 06, 01, 01, 01, 00, 02] +Raw bytes (24): 0x[01, 01, 00, 04, 01, 07, 01, 03, 09, 05, 03, 0a, 02, 06, 00, 02, 05, 00, 06, 01, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 8, 1) to (start + 3, 9) +- Code(Counter(0)) at (prev + 7, 1) to (start + 3, 9) - Code(Counter(1)) at (prev + 3, 10) to (start + 2, 6) - Code(Zero) at (prev + 2, 5) to (start + 0, 6) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) diff --git a/tests/coverage/async2.coverage b/tests/coverage/async2.coverage index cdc171180b8..fa56072924b 100644 --- a/tests/coverage/async2.coverage +++ b/tests/coverage/async2.coverage @@ -1,5 +1,4 @@ LL| |#![feature(coverage_attribute)] - LL| |#![feature(noop_waker)] LL| |//@ edition: 2018 LL| | LL| |//@ aux-build: executor.rs diff --git a/tests/coverage/async2.rs b/tests/coverage/async2.rs index f52c848f6f2..9bd4821518a 100644 --- a/tests/coverage/async2.rs +++ b/tests/coverage/async2.rs @@ -1,5 +1,4 @@ #![feature(coverage_attribute)] -#![feature(noop_waker)] //@ edition: 2018 //@ aux-build: executor.rs diff --git a/tests/coverage/async_block.cov-map b/tests/coverage/async_block.cov-map index e3309bd51b4..14ed4850d4a 100644 --- a/tests/coverage/async_block.cov-map +++ b/tests/coverage/async_block.cov-map @@ -1,11 +1,11 @@ Function name: async_block::main -Raw bytes (36): 0x[01, 01, 01, 01, 05, 06, 01, 08, 01, 00, 0b, 05, 01, 09, 00, 0a, 03, 00, 0e, 00, 13, 05, 00, 14, 01, 16, 05, 07, 0a, 02, 06, 01, 03, 01, 00, 02] +Raw bytes (36): 0x[01, 01, 01, 01, 05, 06, 01, 07, 01, 00, 0b, 05, 01, 09, 00, 0a, 03, 00, 0e, 00, 13, 05, 00, 14, 01, 16, 05, 07, 0a, 02, 06, 01, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 6 -- Code(Counter(0)) at (prev + 8, 1) to (start + 0, 11) +- Code(Counter(0)) at (prev + 7, 1) to (start + 0, 11) - Code(Counter(1)) at (prev + 1, 9) to (start + 0, 10) - Code(Expression(0, Add)) at (prev + 0, 14) to (start + 0, 19) = (c0 + c1) @@ -15,13 +15,13 @@ Number of file 0 mappings: 6 Highest counter ID seen: c1 Function name: async_block::main::{closure#0} -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 0a, 1c, 01, 17, 05, 01, 18, 02, 0e, 02, 02, 14, 02, 0e, 01, 03, 09, 00, 0a] +Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 09, 1c, 01, 17, 05, 01, 18, 02, 0e, 02, 02, 14, 02, 0e, 01, 03, 09, 00, 0a] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 10, 28) to (start + 1, 23) +- Code(Counter(0)) at (prev + 9, 28) to (start + 1, 23) - Code(Counter(1)) at (prev + 1, 24) to (start + 2, 14) - Code(Expression(0, Sub)) at (prev + 2, 20) to (start + 2, 14) = (c0 - c1) diff --git a/tests/coverage/async_block.coverage b/tests/coverage/async_block.coverage index d9be8480d80..9e3294492cd 100644 --- a/tests/coverage/async_block.coverage +++ b/tests/coverage/async_block.coverage @@ -1,5 +1,4 @@ LL| |#![feature(coverage_attribute)] - LL| |#![feature(noop_waker)] LL| |//@ edition: 2021 LL| | LL| |//@ aux-build: executor.rs diff --git a/tests/coverage/async_block.rs b/tests/coverage/async_block.rs index 7ae8241aa77..d1e37ab7505 100644 --- a/tests/coverage/async_block.rs +++ b/tests/coverage/async_block.rs @@ -1,5 +1,4 @@ #![feature(coverage_attribute)] -#![feature(noop_waker)] //@ edition: 2021 //@ aux-build: executor.rs diff --git a/tests/coverage/auxiliary/executor.rs b/tests/coverage/auxiliary/executor.rs index fb07c8ce304..c282414fb8e 100644 --- a/tests/coverage/auxiliary/executor.rs +++ b/tests/coverage/auxiliary/executor.rs @@ -1,4 +1,4 @@ -#![feature(coverage_attribute, noop_waker)] +#![feature(coverage_attribute)] //@ edition: 2021 use core::future::Future; diff --git a/tests/coverage/await_ready.cov-map b/tests/coverage/await_ready.cov-map index 95dbf68a191..bc1af4e42e8 100644 --- a/tests/coverage/await_ready.cov-map +++ b/tests/coverage/await_ready.cov-map @@ -1,19 +1,19 @@ Function name: await_ready::await_ready -Raw bytes (9): 0x[01, 01, 00, 01, 01, 0f, 01, 00, 1e] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 0e, 01, 00, 1e] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 15, 1) to (start + 0, 30) +- Code(Counter(0)) at (prev + 14, 1) to (start + 0, 30) Highest counter ID seen: c0 Function name: await_ready::await_ready::{closure#0} -Raw bytes (14): 0x[01, 01, 00, 02, 01, 0f, 1e, 03, 0f, 05, 04, 01, 00, 02] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 0e, 1e, 03, 0f, 05, 04, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 15, 30) to (start + 3, 15) +- Code(Counter(0)) at (prev + 14, 30) to (start + 3, 15) - Code(Counter(1)) at (prev + 4, 1) to (start + 0, 2) Highest counter ID seen: c1 diff --git a/tests/coverage/await_ready.coverage b/tests/coverage/await_ready.coverage index 7ab03e6d3de..1150d807e76 100644 --- a/tests/coverage/await_ready.coverage +++ b/tests/coverage/await_ready.coverage @@ -1,5 +1,4 @@ LL| |#![feature(coverage_attribute)] - LL| |#![feature(noop_waker)] LL| |#![coverage(off)] LL| |//@ edition: 2021 LL| | diff --git a/tests/coverage/await_ready.rs b/tests/coverage/await_ready.rs index 27ee99d3989..9eaa31dedda 100644 --- a/tests/coverage/await_ready.rs +++ b/tests/coverage/await_ready.rs @@ -1,5 +1,4 @@ #![feature(coverage_attribute)] -#![feature(noop_waker)] #![coverage(off)] //@ edition: 2021 diff --git a/tests/coverage/closure_macro_async.cov-map b/tests/coverage/closure_macro_async.cov-map index 5b99889514c..df4652ac9ce 100644 --- a/tests/coverage/closure_macro_async.cov-map +++ b/tests/coverage/closure_macro_async.cov-map @@ -1,29 +1,29 @@ Function name: closure_macro_async::load_configuration_files -Raw bytes (9): 0x[01, 01, 00, 01, 01, 22, 01, 02, 02] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 21, 01, 02, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 34, 1) to (start + 2, 2) +- Code(Counter(0)) at (prev + 33, 1) to (start + 2, 2) Highest counter ID seen: c0 Function name: closure_macro_async::test -Raw bytes (9): 0x[01, 01, 00, 01, 01, 26, 01, 00, 2b] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 25, 01, 00, 2b] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 38, 1) to (start + 0, 43) +- Code(Counter(0)) at (prev + 37, 1) to (start + 0, 43) Highest counter ID seen: c0 Function name: closure_macro_async::test::{closure#0} -Raw bytes (36): 0x[01, 01, 01, 01, 05, 06, 01, 26, 2b, 01, 21, 02, 02, 09, 00, 0f, 01, 00, 12, 00, 54, 05, 00, 54, 00, 55, 02, 02, 09, 02, 0b, 01, 03, 01, 00, 02] +Raw bytes (36): 0x[01, 01, 01, 01, 05, 06, 01, 25, 2b, 01, 21, 02, 02, 09, 00, 0f, 01, 00, 12, 00, 54, 05, 00, 54, 00, 55, 02, 02, 09, 02, 0b, 01, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 6 -- Code(Counter(0)) at (prev + 38, 43) to (start + 1, 33) +- Code(Counter(0)) at (prev + 37, 43) to (start + 1, 33) - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 15) = (c0 - c1) - Code(Counter(0)) at (prev + 0, 18) to (start + 0, 84) @@ -34,7 +34,7 @@ Number of file 0 mappings: 6 Highest counter ID seen: c1 Function name: closure_macro_async::test::{closure#0}::{closure#0} -Raw bytes (35): 0x[01, 01, 03, 01, 05, 0b, 0d, 05, 09, 05, 01, 15, 1c, 03, 21, 05, 04, 11, 01, 27, 02, 03, 11, 00, 16, 0d, 00, 17, 00, 1e, 07, 02, 09, 00, 0a] +Raw bytes (35): 0x[01, 01, 03, 01, 05, 0b, 0d, 05, 09, 05, 01, 14, 1c, 03, 21, 05, 04, 11, 01, 27, 02, 03, 11, 00, 16, 0d, 00, 17, 00, 1e, 07, 02, 09, 00, 0a] Number of files: 1 - file 0 => global file 1 Number of expressions: 3 @@ -42,7 +42,7 @@ Number of expressions: 3 - expression 1 operands: lhs = Expression(2, Add), rhs = Counter(3) - expression 2 operands: lhs = Counter(1), rhs = Counter(2) Number of file 0 mappings: 5 -- Code(Counter(0)) at (prev + 21, 28) to (start + 3, 33) +- Code(Counter(0)) at (prev + 20, 28) to (start + 3, 33) - Code(Counter(1)) at (prev + 4, 17) to (start + 1, 39) - Code(Expression(0, Sub)) at (prev + 3, 17) to (start + 0, 22) = (c0 - c1) diff --git a/tests/coverage/closure_macro_async.coverage b/tests/coverage/closure_macro_async.coverage index a8c72efac66..1e1ffec9f76 100644 --- a/tests/coverage/closure_macro_async.coverage +++ b/tests/coverage/closure_macro_async.coverage @@ -1,5 +1,4 @@ LL| |#![feature(coverage_attribute)] - LL| |#![feature(noop_waker)] LL| |//@ edition: 2018 LL| | LL| |//@ aux-build: executor.rs diff --git a/tests/coverage/closure_macro_async.rs b/tests/coverage/closure_macro_async.rs index defd1b6d632..5dbb438424d 100644 --- a/tests/coverage/closure_macro_async.rs +++ b/tests/coverage/closure_macro_async.rs @@ -1,5 +1,4 @@ #![feature(coverage_attribute)] -#![feature(noop_waker)] //@ edition: 2018 //@ aux-build: executor.rs diff --git a/tests/crashes/105249.rs b/tests/crashes/105249.rs deleted file mode 100644 index 592ed5b6dbc..00000000000 --- a/tests/crashes/105249.rs +++ /dev/null @@ -1,16 +0,0 @@ -//@ known-bug: #105249 -//@ compile-flags: -Zpolymorphize=on - -trait Foo<T> { - fn print<'a>(&'a self) where T: 'a { println!("foo"); } -} - -impl<'a> Foo<&'a ()> for () { } - -trait Bar: for<'a> Foo<&'a ()> { } - -impl Bar for () {} - -fn main() { - (&() as &dyn Bar).print(); // Segfault -} diff --git a/tests/crashes/123809.rs b/tests/crashes/123809.rs deleted file mode 100644 index 75abe6dc0cd..00000000000 --- a/tests/crashes/123809.rs +++ /dev/null @@ -1,4 +0,0 @@ -//@ known-bug: #123809 -type Positive = std::pat::pattern_type!(std::pat is 0..); - -pub fn main() {} diff --git a/tests/crashes/123893.rs b/tests/crashes/123893.rs deleted file mode 100644 index 05237d002b8..00000000000 --- a/tests/crashes/123893.rs +++ /dev/null @@ -1,24 +0,0 @@ -//@ known-bug: #123893 -//@ compile-flags: -Zpolymorphize=on -Zinline-mir=yes -Zinline-mir-threshold=20 -pub fn main() { - generic_impl::<bool>(); -} - -fn generic_impl<T>() { - trait MagicTrait { - const IS_BIG: bool; - } - impl<T> MagicTrait for T { - const IS_BIG: bool = true; - } - more_cost(); - if T::IS_BIG { - big_impl::<i32>(); - } -} - -#[inline(never)] -fn big_impl<T>() {} - -#[inline(never)] -fn more_cost() {} diff --git a/tests/crashes/124020.rs b/tests/crashes/124020.rs deleted file mode 100644 index 1b875497465..00000000000 --- a/tests/crashes/124020.rs +++ /dev/null @@ -1,33 +0,0 @@ -//@ known-bug: #124020 -//@ compile-flags: -Zpolymorphize=on --edition=2018 --crate-type=lib - -#![feature(async_closure, noop_waker, async_trait_bounds)] - -use std::future::Future; -use std::pin::pin; -use std::task::*; - -pub fn block_on<T>(fut: impl Future<Output = T>) -> T { - let mut fut = pin!(fut); - let ctx = &mut Context::from_waker(Waker::noop()); - - loop { - match fut.as_mut().poll(ctx) { - Poll::Pending => {} - Poll::Ready(t) => break t, - } - } -} - -async fn call_once(f: impl AsyncFnOnce(DropMe)) { - f(DropMe("world")).await; -} - -struct DropMe(&'static str); - -pub fn future() { - block_on(async { - let async_closure = async move |a: DropMe| {}; - call_once(async_closure).await; - }); -} diff --git a/tests/crashes/124436.rs b/tests/crashes/124436.rs deleted file mode 100644 index aed830e8f0e..00000000000 --- a/tests/crashes/124436.rs +++ /dev/null @@ -1,7 +0,0 @@ -//@ known-bug: rust-lang/rust#124436 -//@ compile-flags: -Zdump-mir=all -Zpolymorphize=on - -pub trait TraitCat {} -pub trait TraitDog {} - -pub fn gamma<T: TraitCat + TraitDog>(t: [TraitDog; 32]) {} diff --git a/tests/crashes/130425.rs b/tests/crashes/130425.rs deleted file mode 100644 index 559b86f7bc2..00000000000 --- a/tests/crashes/130425.rs +++ /dev/null @@ -1,13 +0,0 @@ -//@ known-bug: #130425 -//@ compile-flags: -Zmir-opt-level=5 -Zpolymorphize=on - -struct S<T>(T) -where - [T; ( - |_: u8| { - static FOO: Sync = AtomicUsize::new(0); - unsafe { &*(&FOO as *const _ as *const usize) } - }, - 1, - ) - .1]: Copy; diff --git a/tests/debuginfo/auxiliary/dependency-with-embedded-visualizers.py b/tests/debuginfo/auxiliary/dependency-with-embedded-visualizers.py index 2635ed487c8..9e801699fcc 100644 --- a/tests/debuginfo/auxiliary/dependency-with-embedded-visualizers.py +++ b/tests/debuginfo/auxiliary/dependency-with-embedded-visualizers.py @@ -1,5 +1,6 @@ import gdb + class PersonPrinter: "Print a Person" @@ -11,6 +12,7 @@ class PersonPrinter: def to_string(self): return "{} is {} years old.".format(self.name, self.age) + def lookup(val): lookup_tag = val.type.tag if lookup_tag is None: @@ -20,4 +22,5 @@ def lookup(val): return None + gdb.current_objfile().pretty_printers.append(lookup) diff --git a/tests/debuginfo/embedded-visualizer-point.py b/tests/debuginfo/embedded-visualizer-point.py index d6b1af00785..5f42957b1f8 100644 --- a/tests/debuginfo/embedded-visualizer-point.py +++ b/tests/debuginfo/embedded-visualizer-point.py @@ -1,5 +1,6 @@ import gdb + class PointPrinter: "Print a Point" @@ -11,6 +12,7 @@ class PointPrinter: def to_string(self): return "({}, {})".format(self.x, self.y) + def lookup(val): lookup_tag = val.type.tag if lookup_tag is None: @@ -20,4 +22,5 @@ def lookup(val): return None + gdb.current_objfile().pretty_printers.append(lookup) diff --git a/tests/debuginfo/embedded-visualizer.py b/tests/debuginfo/embedded-visualizer.py index 8e4fab61614..5fdbbda2188 100644 --- a/tests/debuginfo/embedded-visualizer.py +++ b/tests/debuginfo/embedded-visualizer.py @@ -1,5 +1,6 @@ import gdb + class LinePrinter: "Print a Line" @@ -11,6 +12,7 @@ class LinePrinter: def to_string(self): return "({}, {})".format(self.a, self.b) + def lookup(val): lookup_tag = val.type.tag if lookup_tag is None: @@ -20,4 +22,5 @@ def lookup(val): return None + gdb.current_objfile().pretty_printers.append(lookup) diff --git a/tests/mir-opt/async_closure_shims.rs b/tests/mir-opt/async_closure_shims.rs index b2168ba0c46..f28400e298f 100644 --- a/tests/mir-opt/async_closure_shims.rs +++ b/tests/mir-opt/async_closure_shims.rs @@ -1,7 +1,7 @@ //@ edition:2021 // skip-filecheck -#![feature(async_closure, noop_waker, async_fn_traits)] +#![feature(async_closure, async_fn_traits)] #![allow(unused)] use std::future::Future; diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-abort.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-abort.diff index ed72ca72629..a1be927e1c0 100644 --- a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-abort.diff +++ b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-abort.diff @@ -42,7 +42,7 @@ StorageLive(_4); StorageLive(_20); StorageLive(_21); - _21 = copy ((*_1).0: u32); + _21 = copy (((*_1).0: std::fmt::FormattingOptions).0: u32); _20 = BitAnd(move _21, const 1_u32); StorageDead(_21); _4 = Ne(move _20, const 0_u32); @@ -58,14 +58,14 @@ } bb2: { -- _5 = Minus; -+ _5 = const Minus; +- _5 = core::num::flt2dec::Sign::Minus; ++ _5 = const core::num::flt2dec::Sign::Minus; goto -> bb3; } bb3: { StorageLive(_6); - _6 = copy ((*_1).4: std::option::Option<usize>); + _6 = copy (((*_1).0: std::fmt::FormattingOptions).4: std::option::Option<usize>); _7 = discriminant(_6); switchInt(move _7) -> [1: bb4, 0: bb6, otherwise: bb9]; } diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-unwind.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-unwind.diff index 42d99883749..87ab71feb2f 100644 --- a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-unwind.diff +++ b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-unwind.diff @@ -42,7 +42,7 @@ StorageLive(_4); StorageLive(_20); StorageLive(_21); - _21 = copy ((*_1).0: u32); + _21 = copy (((*_1).0: std::fmt::FormattingOptions).0: u32); _20 = BitAnd(move _21, const 1_u32); StorageDead(_21); _4 = Ne(move _20, const 0_u32); @@ -58,14 +58,14 @@ } bb2: { -- _5 = Minus; -+ _5 = const Minus; +- _5 = core::num::flt2dec::Sign::Minus; ++ _5 = const core::num::flt2dec::Sign::Minus; goto -> bb3; } bb3: { StorageLive(_6); - _6 = copy ((*_1).4: std::option::Option<usize>); + _6 = copy (((*_1).0: std::fmt::FormattingOptions).4: std::option::Option<usize>); _7 = discriminant(_6); switchInt(move _7) -> [1: bb4, 0: bb6, otherwise: bb9]; } diff --git a/tests/run-make/missing-unstable-trait-bound/missing-bound.rs b/tests/run-make/missing-unstable-trait-bound/missing-bound.rs new file mode 100644 index 00000000000..65d0745f494 --- /dev/null +++ b/tests/run-make/missing-unstable-trait-bound/missing-bound.rs @@ -0,0 +1,4 @@ +pub fn baz<T>(t: std::ops::Range<T>) { + for _ in t {} +} +fn main() {} diff --git a/tests/run-make/missing-unstable-trait-bound/missing-bound.stderr b/tests/run-make/missing-unstable-trait-bound/missing-bound.stderr new file mode 100644 index 00000000000..7196a1a6fed --- /dev/null +++ b/tests/run-make/missing-unstable-trait-bound/missing-bound.stderr @@ -0,0 +1,12 @@ +error[E0277]: the trait bound `T: Step` is not satisfied + --> missing-bound.rs:2:14 + | +2 | for _ in t {} + | ^ the trait `Step` is not implemented for `T` + | + = note: required for `std::ops::Range<T>` to implement `Iterator` + = note: required for `std::ops::Range<T>` to implement `IntoIterator` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/run-make/missing-unstable-trait-bound/rmake.rs b/tests/run-make/missing-unstable-trait-bound/rmake.rs new file mode 100644 index 00000000000..20f77f7c9aa --- /dev/null +++ b/tests/run-make/missing-unstable-trait-bound/rmake.rs @@ -0,0 +1,24 @@ +//@ only-linux +//@ ignore-wasm32 +//@ ignore-wasm64 +// ignore-tidy-linelength + +// Ensure that on stable we don't suggest restricting with an unsafe trait and we continue +// mentioning the rest of the obligation chain. + +use run_make_support::{diff, rust_lib_name, rustc}; + +fn main() { + let out = rustc() + .env("RUSTC_BOOTSTRAP", "-1") + .input("missing-bound.rs") + .run_fail() + .assert_stderr_not_contains("help: consider restricting type parameter `T`") + .assert_stderr_contains( + r#" + = note: required for `std::ops::Range<T>` to implement `Iterator` + = note: required for `std::ops::Range<T>` to implement `IntoIterator`"#, + ) + .stderr_utf8(); + diff().expected_file("missing-bound.stderr").actual_text("(stable rustc)", &out).run() +} diff --git a/tests/rustdoc-gui/docblock-table-overflow.goml b/tests/rustdoc-gui/docblock-table-overflow.goml index abfa820ef27..18e5b4d7f35 100644 --- a/tests/rustdoc-gui/docblock-table-overflow.goml +++ b/tests/rustdoc-gui/docblock-table-overflow.goml @@ -10,12 +10,8 @@ assert-property: (".top-doc .docblock table", {"scrollWidth": "1572"}) // Checking it works on other doc blocks as well... -// Logically, the ".docblock" and the "<p>" should have the same scroll width. -compare-elements-property: ( - "#implementations-list > details .docblock", - "#implementations-list > details .docblock > p", - ["scrollWidth"], -) -assert-property: ("#implementations-list > details .docblock", {"scrollWidth": "835"}) +// Logically, the ".docblock" and the "<p>" should have the same scroll width (if we exclude the margin). +assert-property: ("#implementations-list > details .docblock", {"scrollWidth": 816}) +assert-property: ("#implementations-list > details .docblock > p", {"scrollWidth": 835}) // However, since there is overflow in the <table>, its scroll width is bigger. assert-property: ("#implementations-list > details .docblock table", {"scrollWidth": "1572"}) diff --git a/tests/rustdoc-gui/impl-block-doc.goml b/tests/rustdoc-gui/impl-block-doc.goml new file mode 100644 index 00000000000..906ce1a37c6 --- /dev/null +++ b/tests/rustdoc-gui/impl-block-doc.goml @@ -0,0 +1,42 @@ +// Checks that the first sentence of an impl block doc is always visible even when the impl +// block is collapsed. +go-to: "file://" + |DOC_PATH| + "/test_docs/struct.ImplDoc.html" + +set-window-size: (900, 600) + +define-function: ( + "compare-size-and-pos", + [nth_impl], + block { + // First we collapse the impl block. + store-value: (impl_path, "#implementations-list details:nth-of-type(" + |nth_impl| + ")") + set-property: (|impl_path|, {"open": false}) + wait-for: |impl_path| + ":not([open])" + + store-value: (impl_path, |impl_path| + " summary") + store-size: (|impl_path|, {"height": impl_height}) + store-position: (|impl_path|, {"y": impl_y}) + + store-size: (|impl_path| + " .docblock", {"height": doc_height}) + store-position: (|impl_path| + " .docblock", {"y": doc_y}) + + assert: |impl_y| + |impl_height| >= |doc_y| + } +) + +call-function: ("compare-size-and-pos", {"nth_impl": 1}) +// Since the first impl block has a long line, we ensure that it doesn't display all of it. +assert: (|impl_y| + |impl_height|) <= (|doc_y| + |doc_height|) + +call-function: ("compare-size-and-pos", {"nth_impl": 2}) +// The second impl block has a short line. +assert: (|impl_y| + |impl_height|) >= (|doc_y| + |doc_height|) + +// FIXME: Needs `if` condition to make this test check that `padding-top` on the "..." element +// is as expected for tables. +call-function: ("compare-size-and-pos", {"nth_impl": 3}) +assert: (|impl_y| + |impl_height|) >= (|doc_y| + |doc_height|) +call-function: ("compare-size-and-pos", {"nth_impl": 4}) +assert: (|impl_y| + |impl_height|) >= (|doc_y| + |doc_height|) +call-function: ("compare-size-and-pos", {"nth_impl": 5}) +assert: (|impl_y| + |impl_height|) >= (|doc_y| + |doc_height|) diff --git a/tests/rustdoc-gui/impl-doc.goml b/tests/rustdoc-gui/impl-doc.goml index 4ec46de404f..1845255178a 100644 --- a/tests/rustdoc-gui/impl-doc.goml +++ b/tests/rustdoc-gui/impl-doc.goml @@ -3,7 +3,7 @@ go-to: "file://" + |DOC_PATH| + "/test_docs/struct.TypeWithImplDoc.html" // The text is about 24px tall, so if there's a margin, then their position will be >24px apart compare-elements-position-near-false: ( - "#implementations-list > .implementors-toggle > .docblock > p", + "#implementations-list > .implementors-toggle .docblock > p", "#implementations-list > .implementors-toggle > .impl-items", {"y": 24} ) diff --git a/tests/rustdoc-gui/item-info-overflow.goml b/tests/rustdoc-gui/item-info-overflow.goml index 23c53c03762..c325beb6d06 100644 --- a/tests/rustdoc-gui/item-info-overflow.goml +++ b/tests/rustdoc-gui/item-info-overflow.goml @@ -16,7 +16,7 @@ assert-text: ( go-to: "file://" + |DOC_PATH| + "/lib2/struct.LongItemInfo2.html" compare-elements-property: ( "#impl-SimpleTrait-for-LongItemInfo2 .item-info", - "#impl-SimpleTrait-for-LongItemInfo2 + .docblock", + "#impl-SimpleTrait-for-LongItemInfo2 .docblock", ["scrollWidth"], ) assert-property: ( diff --git a/tests/rustdoc-gui/source-code-page-code-scroll.goml b/tests/rustdoc-gui/source-code-page-code-scroll.goml index 31ab281d6ce..60012db6c8c 100644 --- a/tests/rustdoc-gui/source-code-page-code-scroll.goml +++ b/tests/rustdoc-gui/source-code-page-code-scroll.goml @@ -2,7 +2,7 @@ go-to: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html" set-window-size: (800, 1000) // "scrollWidth" should be superior than "clientWidth". -assert-property: ("body", {"scrollWidth": 1114, "clientWidth": 800}) +assert-property: ("body", {"scrollWidth": 1776, "clientWidth": 800}) // Both properties should be equal (ie, no scroll on the code block). -assert-property: (".example-wrap .rust", {"scrollWidth": 1000, "clientWidth": 1000}) +assert-property: (".example-wrap .rust", {"scrollWidth": 1662, "clientWidth": 1662}) diff --git a/tests/rustdoc-gui/src/test_docs/lib.rs b/tests/rustdoc-gui/src/test_docs/lib.rs index 352995c4903..91aa2c3fae5 100644 --- a/tests/rustdoc-gui/src/test_docs/lib.rs +++ b/tests/rustdoc-gui/src/test_docs/lib.rs @@ -652,3 +652,42 @@ pub mod long_list { //! * [`FromBytes`](#a) indicates that a type may safely be converted from an arbitrary byte //! sequence } + +pub struct ImplDoc; + +/// bla sondfosdnf sdfasd fadsd fdsa f ads fad sf sad f sad fasdfsafsa df dsafasdasd fsa dfadsfasd +/// fads fadfadd +/// +/// bla +impl ImplDoc { + pub fn bar() {} +} + +/// bla +/// +/// bla +impl ImplDoc { + pub fn bar2() {} +} + +// ignore-tidy-linelength +/// | this::is::a::kinda::very::long::header::number::one | this::is::a::kinda::very::long::header::number::two | this::is::a::kinda::very::long::header::number::three | +/// |-|-|-| +/// | bla | bli | blob | +impl ImplDoc { + pub fn bar3() {} +} + +/// # h1 +/// +/// bla +impl ImplDoc { + pub fn bar4() {} +} + +/// * list +/// * list +/// * list +impl ImplDoc { + pub fn bar5() {} +} diff --git a/tests/rustdoc-ui/issues/issue-96287.stderr b/tests/rustdoc-ui/issues/issue-96287.stderr index 9aba0332164..40dc1cc0e70 100644 --- a/tests/rustdoc-ui/issues/issue-96287.stderr +++ b/tests/rustdoc-ui/issues/issue-96287.stderr @@ -4,7 +4,7 @@ error[E0220]: associated type `Assoc` not found for `V` LL | pub type Foo<V> = impl Trait<V::Assoc>; | ^^^^^ there is an associated type `Assoc` in the trait `TraitWithAssoc` | -help: consider restricting type parameter `V` +help: consider restricting type parameter `V` with trait `TraitWithAssoc` | LL | pub type Foo<V: TraitWithAssoc> = impl Trait<V::Assoc>; | ++++++++++++++++ @@ -16,7 +16,7 @@ LL | pub type Foo<V> = impl Trait<V::Assoc>; | ^^^^^ there is an associated type `Assoc` in the trait `TraitWithAssoc` | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: consider restricting type parameter `V` +help: consider restricting type parameter `V` with trait `TraitWithAssoc` | LL | pub type Foo<V: TraitWithAssoc> = impl Trait<V::Assoc>; | ++++++++++++++++ diff --git a/tests/rustdoc-ui/synthetic-auto-trait-impls/projections-in-super-trait-bound-unsatisfied.stderr b/tests/rustdoc-ui/synthetic-auto-trait-impls/projections-in-super-trait-bound-unsatisfied.stderr index d87e769b505..045516d7d2f 100644 --- a/tests/rustdoc-ui/synthetic-auto-trait-impls/projections-in-super-trait-bound-unsatisfied.stderr +++ b/tests/rustdoc-ui/synthetic-auto-trait-impls/projections-in-super-trait-bound-unsatisfied.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `C: Bar<5>` is not satisfied LL | pub struct Structure<C: Tec> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar<5>` is not implemented for `C` | -help: consider further restricting this bound +help: consider further restricting type parameter `C` with trait `Bar` | LL | pub struct Structure<C: Tec + Bar<5>> { | ++++++++ @@ -15,7 +15,7 @@ error[E0277]: the trait bound `C: Bar<5>` is not satisfied LL | _field: C::BarType, | ^^^^^^^^^^ the trait `Bar<5>` is not implemented for `C` | -help: consider further restricting this bound +help: consider further restricting type parameter `C` with trait `Bar` | LL | pub struct Structure<C: Tec + Bar<5>> { | ++++++++ diff --git a/tests/ui/associated-consts/assoc-const-eq-ambiguity.stderr b/tests/ui/associated-consts/assoc-const-eq-ambiguity.stderr index ba3a8701316..aa1db4cb032 100644 --- a/tests/ui/associated-consts/assoc-const-eq-ambiguity.stderr +++ b/tests/ui/associated-consts/assoc-const-eq-ambiguity.stderr @@ -26,12 +26,6 @@ LL | trait Parent2 { const C: &'static str; } LL | LL | fn take1(_: impl Trait1<C = "?">) {} | ^^^^^^^ ambiguous associated constant `C` - | - = help: consider introducing a new type parameter `T` and adding `where` constraints: - where - T: Trait1, - T: Parent2::C = "?", - T: Parent1::C = "?" error: aborting due to 2 previous errors diff --git a/tests/ui/associated-types/associated-types-no-suitable-bound.stderr b/tests/ui/associated-types/associated-types-no-suitable-bound.stderr index 9713051d973..4f951ee4b4e 100644 --- a/tests/ui/associated-types/associated-types-no-suitable-bound.stderr +++ b/tests/ui/associated-types/associated-types-no-suitable-bound.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `T: Get` is not satisfied LL | fn uhoh<T>(foo: <T as Get>::Value) {} | ^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `T` | -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Get` | LL | fn uhoh<T: Get>(foo: <T as Get>::Value) {} | +++++ @@ -15,7 +15,7 @@ error[E0277]: the trait bound `T: Get` is not satisfied LL | fn uhoh<T>(foo: <T as Get>::Value) {} | ^^ the trait `Get` is not implemented for `T` | -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Get` | LL | fn uhoh<T: Get>(foo: <T as Get>::Value) {} | +++++ diff --git a/tests/ui/associated-types/defaults-suitability.current.stderr b/tests/ui/associated-types/defaults-suitability.current.stderr index 9c0ae59ae43..61247cee1f3 100644 --- a/tests/ui/associated-types/defaults-suitability.current.stderr +++ b/tests/ui/associated-types/defaults-suitability.current.stderr @@ -47,7 +47,7 @@ note: required by a bound in `Foo::Bar` | LL | type Bar: Clone = Vec<T>; | ^^^^^ required by this bound in `Foo::Bar` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Clone` | LL | trait Foo<T: std::clone::Clone> { | +++++++++++++++++++ @@ -132,7 +132,7 @@ LL | Self::Baz: Clone, ... LL | type Baz = T; | --- required by a bound in this associated type -help: consider further restricting type parameter `T` +help: consider further restricting type parameter `T` with trait `Clone` | LL | Self::Baz: Clone, T: std::clone::Clone | ~~~~~~~~~~~~~~~~~~~~~~ diff --git a/tests/ui/associated-types/defaults-suitability.next.stderr b/tests/ui/associated-types/defaults-suitability.next.stderr index 9c0ae59ae43..61247cee1f3 100644 --- a/tests/ui/associated-types/defaults-suitability.next.stderr +++ b/tests/ui/associated-types/defaults-suitability.next.stderr @@ -47,7 +47,7 @@ note: required by a bound in `Foo::Bar` | LL | type Bar: Clone = Vec<T>; | ^^^^^ required by this bound in `Foo::Bar` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Clone` | LL | trait Foo<T: std::clone::Clone> { | +++++++++++++++++++ @@ -132,7 +132,7 @@ LL | Self::Baz: Clone, ... LL | type Baz = T; | --- required by a bound in this associated type -help: consider further restricting type parameter `T` +help: consider further restricting type parameter `T` with trait `Clone` | LL | Self::Baz: Clone, T: std::clone::Clone | ~~~~~~~~~~~~~~~~~~~~~~ diff --git a/tests/ui/associated-types/hr-associated-type-bound-param-6.stderr b/tests/ui/associated-types/hr-associated-type-bound-param-6.stderr index 5278bdb7a5c..b2a86bb7f75 100644 --- a/tests/ui/associated-types/hr-associated-type-bound-param-6.stderr +++ b/tests/ui/associated-types/hr-associated-type-bound-param-6.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `for<'b> T: X<'b, T>` is not satisfied LL | impl<S, T> X<'_, T> for (S,) { | ^^^^^^^^ the trait `for<'b> X<'b, T>` is not implemented for `T` | -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `X` | LL | impl<S, T: for<'b> X<'b, T>> X<'_, T> for (S,) { | ++++++++++++++++++ diff --git a/tests/ui/associated-types/issue-27675-unchecked-bounds.stderr b/tests/ui/associated-types/issue-27675-unchecked-bounds.stderr index 70bf90150b8..0815bdce16f 100644 --- a/tests/ui/associated-types/issue-27675-unchecked-bounds.stderr +++ b/tests/ui/associated-types/issue-27675-unchecked-bounds.stderr @@ -9,7 +9,7 @@ note: required by a bound in `copy` | LL | fn copy<U: Setup + ?Sized>(from: &U::From) -> U::From { | ^^^^^ required by this bound in `copy` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | pub fn copy_any<T: std::marker::Copy>(t: &T) -> T { | +++++++++++++++++++ diff --git a/tests/ui/associated-types/issue-43784-associated-type.stderr b/tests/ui/associated-types/issue-43784-associated-type.stderr index 529fc1f119a..ba4e683194f 100644 --- a/tests/ui/associated-types/issue-43784-associated-type.stderr +++ b/tests/ui/associated-types/issue-43784-associated-type.stderr @@ -14,7 +14,7 @@ note: required by a bound in `Complete::Assoc` | LL | type Assoc: Partial<Self>; | ^^^^^^^^^^^^^ required by this bound in `Complete::Assoc` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | impl<T: std::marker::Copy> Complete for T { | +++++++++++++++++++ diff --git a/tests/ui/associated-types/issue-59324.stderr b/tests/ui/associated-types/issue-59324.stderr index 6c77ee6044f..ec2890cc8e7 100644 --- a/tests/ui/associated-types/issue-59324.stderr +++ b/tests/ui/associated-types/issue-59324.stderr @@ -7,7 +7,7 @@ LL | | LL | | Service<AssocType = <Bug as Foo>::OnlyFoo> | |______________________________________________^ the trait `Foo` is not implemented for `Bug` | -help: consider further restricting this bound +help: consider further restricting type parameter `Bug` with trait `Foo` | LL | pub trait ThriftService<Bug: NotFoo + Foo>: | +++++ @@ -24,7 +24,7 @@ LL | | LL | | } | |_^ the trait `Foo` is not implemented for `Bug` | -help: consider further restricting this bound +help: consider further restricting type parameter `Bug` with trait `Foo` | LL | pub trait ThriftService<Bug: NotFoo + Foo>: | +++++ @@ -38,7 +38,7 @@ LL | | &self, LL | | ) -> Self::AssocType; | |_________________________^ the trait `Foo` is not implemented for `Bug` | -help: consider further restricting this bound +help: consider further restricting type parameter `Bug` with trait `Foo` | LL | pub trait ThriftService<Bug: NotFoo + Foo>: | +++++ @@ -61,7 +61,7 @@ error[E0277]: the trait bound `Bug: Foo` is not satisfied LL | ) -> Self::AssocType; | ^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `Bug` | -help: consider further restricting this bound +help: consider further restricting type parameter `Bug` with trait `Foo` | LL | pub trait ThriftService<Bug: NotFoo + Foo>: | +++++ diff --git a/tests/ui/async-await/async-closures/auxiliary/block-on.rs b/tests/ui/async-await/async-closures/auxiliary/block-on.rs index dcb710fc97c..8b50c5571c1 100644 --- a/tests/ui/async-await/async-closures/auxiliary/block-on.rs +++ b/tests/ui/async-await/async-closures/auxiliary/block-on.rs @@ -1,6 +1,6 @@ //@ edition: 2021 -#![feature(async_closure, noop_waker)] +#![feature(async_closure)] use std::future::Future; use std::pin::pin; diff --git a/tests/ui/async-await/async-closures/inline-body.rs b/tests/ui/async-await/async-closures/inline-body.rs index 1bd2da6e899..b7d7102c287 100644 --- a/tests/ui/async-await/async-closures/inline-body.rs +++ b/tests/ui/async-await/async-closures/inline-body.rs @@ -6,7 +6,7 @@ // `mir_inliner_callees` for the synthetic by-move coroutine body since // its def-id wasn't previously being considered. -#![feature(async_closure, noop_waker)] +#![feature(async_closure)] use std::future::Future; use std::pin::pin; diff --git a/tests/ui/async-await/async-closures/mangle.rs b/tests/ui/async-await/async-closures/mangle.rs index 3032ca3c02b..1790f369c57 100644 --- a/tests/ui/async-await/async-closures/mangle.rs +++ b/tests/ui/async-await/async-closures/mangle.rs @@ -5,7 +5,7 @@ //@[v0] compile-flags: -Csymbol-mangling-version=v0 //@[legacy] compile-flags: -Csymbol-mangling-version=legacy -Zunstable-options -#![feature(async_closure, noop_waker)] +#![feature(async_closure)] extern crate block_on; diff --git a/tests/ui/async-await/async-drop.rs b/tests/ui/async-await/async-drop.rs index 4e60598661f..d3884680e51 100644 --- a/tests/ui/async-await/async-drop.rs +++ b/tests/ui/async-await/async-drop.rs @@ -5,7 +5,7 @@ // please consider modifying miri's async drop test at // `src/tools/miri/tests/pass/async-drop.rs`. -#![feature(async_drop, impl_trait_in_assoc_type, noop_waker, async_closure)] +#![feature(async_drop, impl_trait_in_assoc_type, async_closure)] #![allow(incomplete_features, dead_code)] //@ edition: 2021 diff --git a/tests/ui/async-await/async-fn/auxiliary/block-on.rs b/tests/ui/async-await/async-fn/auxiliary/block-on.rs index dcb710fc97c..8b50c5571c1 100644 --- a/tests/ui/async-await/async-fn/auxiliary/block-on.rs +++ b/tests/ui/async-await/async-fn/auxiliary/block-on.rs @@ -1,6 +1,6 @@ //@ edition: 2021 -#![feature(async_closure, noop_waker)] +#![feature(async_closure)] use std::future::Future; use std::pin::pin; diff --git a/tests/ui/async-await/for-await-consumes-iter.rs b/tests/ui/async-await/for-await-consumes-iter.rs index 7ea88c14cb5..fd9bbe1c115 100644 --- a/tests/ui/async-await/for-await-consumes-iter.rs +++ b/tests/ui/async-await/for-await-consumes-iter.rs @@ -1,5 +1,5 @@ //@ edition: 2021 -#![feature(async_iterator, async_iter_from_iter, async_for_loop, noop_waker)] +#![feature(async_iterator, async_iter_from_iter, async_for_loop)] use std::future::Future; diff --git a/tests/ui/async-await/for-await-passthrough.rs b/tests/ui/async-await/for-await-passthrough.rs index 1918e2f61aa..0b9078ae046 100644 --- a/tests/ui/async-await/for-await-passthrough.rs +++ b/tests/ui/async-await/for-await-passthrough.rs @@ -1,7 +1,6 @@ //@ run-pass //@ edition: 2024 -#![feature(async_iterator, async_iter_from_iter, async_for_loop, noop_waker, - gen_blocks)] +#![feature(async_iterator, async_iter_from_iter, async_for_loop, gen_blocks)] async gen fn async_iter() -> i32 { let iter = core::async_iter::from_iter(0..3); diff --git a/tests/ui/async-await/for-await.rs b/tests/ui/async-await/for-await.rs index b4af38a82b3..e69fe649fca 100644 --- a/tests/ui/async-await/for-await.rs +++ b/tests/ui/async-await/for-await.rs @@ -1,6 +1,6 @@ //@ run-pass //@ edition: 2021 -#![feature(async_iterator, async_iter_from_iter, async_for_loop, noop_waker)] +#![feature(async_iterator, async_iter_from_iter, async_for_loop)] use std::future::Future; diff --git a/tests/ui/async-await/in-trait/async-default-fn-overridden.rs b/tests/ui/async-await/in-trait/async-default-fn-overridden.rs index 9b0ce8663c2..6e36818f04f 100644 --- a/tests/ui/async-await/in-trait/async-default-fn-overridden.rs +++ b/tests/ui/async-await/in-trait/async-default-fn-overridden.rs @@ -1,8 +1,6 @@ //@ run-pass //@ edition:2021 -#![feature(noop_waker)] - use std::future::Future; trait AsyncTrait { diff --git a/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.rs b/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.rs index e0901dc6886..4bafb39f600 100644 --- a/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.rs +++ b/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.rs @@ -2,7 +2,6 @@ //@ known-bug: #108309 #![feature(min_specialization)] -#![feature(noop_waker)] struct MyStruct; diff --git a/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr b/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr index 3d82f572a1a..62cca41f6cf 100644 --- a/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr +++ b/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr @@ -1,11 +1,11 @@ error[E0053]: method `foo` has an incompatible type for trait - --> $DIR/dont-project-to-specializable-projection.rs:14:5 + --> $DIR/dont-project-to-specializable-projection.rs:13:5 | LL | default async fn foo(_: T) -> &'static str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found future | note: type in trait - --> $DIR/dont-project-to-specializable-projection.rs:10:5 + --> $DIR/dont-project-to-specializable-projection.rs:9:5 | LL | async fn foo(_: T) -> &'static str; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,7 +13,7 @@ LL | async fn foo(_: T) -> &'static str; found signature `fn(_) -> impl Future<Output = &'static str>` error: async associated function in trait cannot be specialized - --> $DIR/dont-project-to-specializable-projection.rs:14:5 + --> $DIR/dont-project-to-specializable-projection.rs:13:5 | LL | default async fn foo(_: T) -> &'static str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -21,7 +21,7 @@ LL | default async fn foo(_: T) -> &'static str { = note: specialization behaves in inconsistent and surprising ways with async functions in traits, and for now is disallowed error[E0599]: no method named `poll` found for struct `Pin<&mut impl Future<Output = ()>>` in the current scope - --> $DIR/dont-project-to-specializable-projection.rs:49:28 + --> $DIR/dont-project-to-specializable-projection.rs:48:28 | LL | match fut.as_mut().poll(ctx) { | ^^^^ method not found in `Pin<&mut impl Future<Output = ()>>` diff --git a/tests/ui/async-await/issue-70818.stderr b/tests/ui/async-await/issue-70818.stderr index 317c04d2c74..8de6a825042 100644 --- a/tests/ui/async-await/issue-70818.stderr +++ b/tests/ui/async-await/issue-70818.stderr @@ -9,7 +9,7 @@ note: captured value is not `Send` | LL | async { (ty, ty1) } | ^^^ has type `U` which is not `Send` -help: consider restricting type parameter `U` +help: consider restricting type parameter `U` with trait `Send` | LL | fn foo<T: Send, U: std::marker::Send>(ty: T, ty1: U) -> impl Future<Output = (T, U)> + Send { | +++++++++++++++++++ diff --git a/tests/ui/async-await/issue-86507.stderr b/tests/ui/async-await/issue-86507.stderr index f4cd7c42706..6385a8c975e 100644 --- a/tests/ui/async-await/issue-86507.stderr +++ b/tests/ui/async-await/issue-86507.stderr @@ -14,7 +14,7 @@ note: captured value is not `Send` because `&` references cannot be sent unless LL | let x = x; | ^ has type `&T` which is not `Send`, because `T` is not `Sync` = note: required for the cast from `Pin<Box<{async block@$DIR/issue-86507.rs:18:17: 18:27}>>` to `Pin<Box<(dyn Future<Output = ()> + Send + 'async_trait)>>` -help: consider further restricting this bound +help: consider further restricting type parameter `T` with trait `Sync` | LL | fn bar<'me, 'async_trait, T: Send + std::marker::Sync>(x: &'me T) | +++++++++++++++++++ diff --git a/tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr b/tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr index 4c1de72798c..27e38ce06a4 100644 --- a/tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr +++ b/tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr @@ -30,7 +30,7 @@ LL | fn copy<T: Magic>(x: T) -> (T, T) { (x, x) } | ^ - you could clone this value | | | consider constraining this type parameter with `Clone` -help: consider further restricting this bound +help: consider further restricting type parameter `T` with trait `Copy` | LL | fn copy<T: Magic + Copy>(x: T) -> (T, T) { (x, x) } | ++++++ diff --git a/tests/ui/binop/binop-consume-args.stderr b/tests/ui/binop/binop-consume-args.stderr index 1b59216b3c7..d9d92a44766 100644 --- a/tests/ui/binop/binop-consume-args.stderr +++ b/tests/ui/binop/binop-consume-args.stderr @@ -17,7 +17,7 @@ LL | lhs + rhs; | --- you could clone this value note: calling this operator moves the left-hand side --> $SRC_DIR/core/src/ops/arith.rs:LL:COL -help: consider further restricting this bound +help: consider further restricting type parameter `A` with trait `Copy` | LL | fn add<A: Add<B, Output=()> + Copy, B>(lhs: A, rhs: B) { | ++++++ @@ -40,7 +40,7 @@ LL | fn add<A: Add<B, Output=()>, B>(lhs: A, rhs: B) { | ^ consider constraining this type parameter with `Clone` LL | lhs + rhs; | --- you could clone this value -help: consider restricting type parameter `B` +help: consider restricting type parameter `B` with trait `Copy` | LL | fn add<A: Add<B, Output=()>, B: Copy>(lhs: A, rhs: B) { | ++++++ @@ -64,7 +64,7 @@ LL | lhs - rhs; | --- you could clone this value note: calling this operator moves the left-hand side --> $SRC_DIR/core/src/ops/arith.rs:LL:COL -help: consider further restricting this bound +help: consider further restricting type parameter `A` with trait `Copy` | LL | fn sub<A: Sub<B, Output=()> + Copy, B>(lhs: A, rhs: B) { | ++++++ @@ -87,7 +87,7 @@ LL | fn sub<A: Sub<B, Output=()>, B>(lhs: A, rhs: B) { | ^ consider constraining this type parameter with `Clone` LL | lhs - rhs; | --- you could clone this value -help: consider restricting type parameter `B` +help: consider restricting type parameter `B` with trait `Copy` | LL | fn sub<A: Sub<B, Output=()>, B: Copy>(lhs: A, rhs: B) { | ++++++ @@ -111,7 +111,7 @@ LL | lhs * rhs; | --- you could clone this value note: calling this operator moves the left-hand side --> $SRC_DIR/core/src/ops/arith.rs:LL:COL -help: consider further restricting this bound +help: consider further restricting type parameter `A` with trait `Copy` | LL | fn mul<A: Mul<B, Output=()> + Copy, B>(lhs: A, rhs: B) { | ++++++ @@ -134,7 +134,7 @@ LL | fn mul<A: Mul<B, Output=()>, B>(lhs: A, rhs: B) { | ^ consider constraining this type parameter with `Clone` LL | lhs * rhs; | --- you could clone this value -help: consider restricting type parameter `B` +help: consider restricting type parameter `B` with trait `Copy` | LL | fn mul<A: Mul<B, Output=()>, B: Copy>(lhs: A, rhs: B) { | ++++++ @@ -158,7 +158,7 @@ LL | lhs / rhs; | --- you could clone this value note: calling this operator moves the left-hand side --> $SRC_DIR/core/src/ops/arith.rs:LL:COL -help: consider further restricting this bound +help: consider further restricting type parameter `A` with trait `Copy` | LL | fn div<A: Div<B, Output=()> + Copy, B>(lhs: A, rhs: B) { | ++++++ @@ -181,7 +181,7 @@ LL | fn div<A: Div<B, Output=()>, B>(lhs: A, rhs: B) { | ^ consider constraining this type parameter with `Clone` LL | lhs / rhs; | --- you could clone this value -help: consider restricting type parameter `B` +help: consider restricting type parameter `B` with trait `Copy` | LL | fn div<A: Div<B, Output=()>, B: Copy>(lhs: A, rhs: B) { | ++++++ @@ -205,7 +205,7 @@ LL | lhs % rhs; | --- you could clone this value note: calling this operator moves the left-hand side --> $SRC_DIR/core/src/ops/arith.rs:LL:COL -help: consider further restricting this bound +help: consider further restricting type parameter `A` with trait `Copy` | LL | fn rem<A: Rem<B, Output=()> + Copy, B>(lhs: A, rhs: B) { | ++++++ @@ -228,7 +228,7 @@ LL | fn rem<A: Rem<B, Output=()>, B>(lhs: A, rhs: B) { | ^ consider constraining this type parameter with `Clone` LL | lhs % rhs; | --- you could clone this value -help: consider restricting type parameter `B` +help: consider restricting type parameter `B` with trait `Copy` | LL | fn rem<A: Rem<B, Output=()>, B: Copy>(lhs: A, rhs: B) { | ++++++ @@ -252,7 +252,7 @@ LL | lhs & rhs; | --- you could clone this value note: calling this operator moves the left-hand side --> $SRC_DIR/core/src/ops/bit.rs:LL:COL -help: consider further restricting this bound +help: consider further restricting type parameter `A` with trait `Copy` | LL | fn bitand<A: BitAnd<B, Output=()> + Copy, B>(lhs: A, rhs: B) { | ++++++ @@ -275,7 +275,7 @@ LL | fn bitand<A: BitAnd<B, Output=()>, B>(lhs: A, rhs: B) { | ^ consider constraining this type parameter with `Clone` LL | lhs & rhs; | --- you could clone this value -help: consider restricting type parameter `B` +help: consider restricting type parameter `B` with trait `Copy` | LL | fn bitand<A: BitAnd<B, Output=()>, B: Copy>(lhs: A, rhs: B) { | ++++++ @@ -299,7 +299,7 @@ LL | lhs | rhs; | --- you could clone this value note: calling this operator moves the left-hand side --> $SRC_DIR/core/src/ops/bit.rs:LL:COL -help: consider further restricting this bound +help: consider further restricting type parameter `A` with trait `Copy` | LL | fn bitor<A: BitOr<B, Output=()> + Copy, B>(lhs: A, rhs: B) { | ++++++ @@ -322,7 +322,7 @@ LL | fn bitor<A: BitOr<B, Output=()>, B>(lhs: A, rhs: B) { | ^ consider constraining this type parameter with `Clone` LL | lhs | rhs; | --- you could clone this value -help: consider restricting type parameter `B` +help: consider restricting type parameter `B` with trait `Copy` | LL | fn bitor<A: BitOr<B, Output=()>, B: Copy>(lhs: A, rhs: B) { | ++++++ @@ -346,7 +346,7 @@ LL | lhs ^ rhs; | --- you could clone this value note: calling this operator moves the left-hand side --> $SRC_DIR/core/src/ops/bit.rs:LL:COL -help: consider further restricting this bound +help: consider further restricting type parameter `A` with trait `Copy` | LL | fn bitxor<A: BitXor<B, Output=()> + Copy, B>(lhs: A, rhs: B) { | ++++++ @@ -369,7 +369,7 @@ LL | fn bitxor<A: BitXor<B, Output=()>, B>(lhs: A, rhs: B) { | ^ consider constraining this type parameter with `Clone` LL | lhs ^ rhs; | --- you could clone this value -help: consider restricting type parameter `B` +help: consider restricting type parameter `B` with trait `Copy` | LL | fn bitxor<A: BitXor<B, Output=()>, B: Copy>(lhs: A, rhs: B) { | ++++++ @@ -393,7 +393,7 @@ LL | lhs << rhs; | --- you could clone this value note: calling this operator moves the left-hand side --> $SRC_DIR/core/src/ops/bit.rs:LL:COL -help: consider further restricting this bound +help: consider further restricting type parameter `A` with trait `Copy` | LL | fn shl<A: Shl<B, Output=()> + Copy, B>(lhs: A, rhs: B) { | ++++++ @@ -416,7 +416,7 @@ LL | fn shl<A: Shl<B, Output=()>, B>(lhs: A, rhs: B) { | ^ consider constraining this type parameter with `Clone` LL | lhs << rhs; | --- you could clone this value -help: consider restricting type parameter `B` +help: consider restricting type parameter `B` with trait `Copy` | LL | fn shl<A: Shl<B, Output=()>, B: Copy>(lhs: A, rhs: B) { | ++++++ @@ -440,7 +440,7 @@ LL | lhs >> rhs; | --- you could clone this value note: calling this operator moves the left-hand side --> $SRC_DIR/core/src/ops/bit.rs:LL:COL -help: consider further restricting this bound +help: consider further restricting type parameter `A` with trait `Copy` | LL | fn shr<A: Shr<B, Output=()> + Copy, B>(lhs: A, rhs: B) { | ++++++ @@ -463,7 +463,7 @@ LL | fn shr<A: Shr<B, Output=()>, B>(lhs: A, rhs: B) { | ^ consider constraining this type parameter with `Clone` LL | lhs >> rhs; | --- you could clone this value -help: consider restricting type parameter `B` +help: consider restricting type parameter `B` with trait `Copy` | LL | fn shr<A: Shr<B, Output=()>, B: Copy>(lhs: A, rhs: B) { | ++++++ diff --git a/tests/ui/binop/binop-move-semantics.stderr b/tests/ui/binop/binop-move-semantics.stderr index 45c7f110406..2e661c44abd 100644 --- a/tests/ui/binop/binop-move-semantics.stderr +++ b/tests/ui/binop/binop-move-semantics.stderr @@ -20,7 +20,7 @@ LL | x | - you could clone this value note: calling this operator moves the left-hand side --> $SRC_DIR/core/src/ops/arith.rs:LL:COL -help: consider further restricting this bound +help: consider further restricting type parameter `T` with trait `Copy` | LL | fn double_move<T: Add<Output=()> + Copy>(x: T) { | ++++++ @@ -40,7 +40,7 @@ help: consider cloning the value if the performance cost is acceptable | LL | x.clone() | ++++++++ -help: consider further restricting this bound +help: consider further restricting type parameter `T` with trait `Copy` | LL | fn move_then_borrow<T: Add<Output=()> + Clone + Copy>(x: T) { | ++++++ diff --git a/tests/ui/binop/issue-93927.stderr b/tests/ui/binop/issue-93927.stderr index 9bcf2b17357..ff5ecf66be6 100644 --- a/tests/ui/binop/issue-93927.stderr +++ b/tests/ui/binop/issue-93927.stderr @@ -6,7 +6,7 @@ LL | val == val | | | MyType<T> | -help: consider further restricting this bound +help: consider further restricting type parameter `T` with trait `Eq` | LL | fn cond<T: PartialEq + std::cmp::Eq>(val: MyType<T>) -> bool { | ++++++++++++++ diff --git a/tests/ui/borrowck/clone-on-ref.stderr b/tests/ui/borrowck/clone-on-ref.stderr index d5d21296a3f..911c136086c 100644 --- a/tests/ui/borrowck/clone-on-ref.stderr +++ b/tests/ui/borrowck/clone-on-ref.stderr @@ -12,7 +12,7 @@ LL | LL | drop(cloned_items); | ------------ immutable borrow later used here | -help: consider further restricting this bound +help: consider further restricting type parameter `T` with trait `Clone` | LL | fn foo<T: Default + Clone>(list: &mut Vec<T>) { | +++++++ @@ -39,7 +39,7 @@ LL | fn bar<T: std::fmt::Display>(x: T) { | ^ consider constraining this type parameter with `Clone` LL | let a = &x; | - you could clone this value -help: consider further restricting this bound +help: consider further restricting type parameter `T` with trait `Clone` | LL | fn bar<T: std::fmt::Display + Clone>(x: T) { | +++++++ diff --git a/tests/ui/borrowck/move-error-suggest-clone-panic-issue-127915.stderr b/tests/ui/borrowck/move-error-suggest-clone-panic-issue-127915.stderr index 6997710ec89..e32a0c54dfe 100644 --- a/tests/ui/borrowck/move-error-suggest-clone-panic-issue-127915.stderr +++ b/tests/ui/borrowck/move-error-suggest-clone-panic-issue-127915.stderr @@ -15,7 +15,7 @@ LL | fn test<T, U>(a: i64, b: i64, c: i64, d: i64, e: i64, f: T, g: U) -> i64 { ... LL | 6, a as f64, b, b as f64, f, c as f64, d, d as f64, e, e as f64, f, g, | - you could clone this value -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | fn test<T: Copy, U>(a: i64, b: i64, c: i64, d: i64, e: i64, f: T, g: U) -> i64 { | ++++++ diff --git a/tests/ui/builtin-superkinds/builtin-superkinds-double-superkind.stderr b/tests/ui/builtin-superkinds/builtin-superkinds-double-superkind.stderr index 592aa4369ce..9915b772afa 100644 --- a/tests/ui/builtin-superkinds/builtin-superkinds-double-superkind.stderr +++ b/tests/ui/builtin-superkinds/builtin-superkinds-double-superkind.stderr @@ -10,7 +10,7 @@ note: required by a bound in `Foo` | LL | trait Foo : Send+Sync { } | ^^^^ required by this bound in `Foo` -help: consider further restricting this bound +help: consider further restricting type parameter `T` with trait `Send` | LL | impl <T: Sync+'static + std::marker::Send> Foo for (T,) { } | +++++++++++++++++++ @@ -27,7 +27,7 @@ note: required by a bound in `Foo` | LL | trait Foo : Send+Sync { } | ^^^^ required by this bound in `Foo` -help: consider further restricting this bound +help: consider further restricting type parameter `T` with trait `Sync` | LL | impl <T: Send + std::marker::Sync> Foo for (T,T) { } | +++++++++++++++++++ diff --git a/tests/ui/builtin-superkinds/builtin-superkinds-in-metadata.stderr b/tests/ui/builtin-superkinds/builtin-superkinds-in-metadata.stderr index 251651df4f9..39a04186981 100644 --- a/tests/ui/builtin-superkinds/builtin-superkinds-in-metadata.stderr +++ b/tests/ui/builtin-superkinds/builtin-superkinds-in-metadata.stderr @@ -14,7 +14,7 @@ note: required by a bound in `RequiresRequiresShareAndSend` | LL | pub trait RequiresRequiresShareAndSend : RequiresShare + Send { } | ^^^^ required by this bound in `RequiresRequiresShareAndSend` -help: consider further restricting this bound +help: consider further restricting type parameter `T` with trait `Send` | LL | impl <T:Sync+'static + std::marker::Send> RequiresRequiresShareAndSend for X<T> { } | +++++++++++++++++++ diff --git a/tests/ui/builtin-superkinds/builtin-superkinds-typaram-not-send.stderr b/tests/ui/builtin-superkinds/builtin-superkinds-typaram-not-send.stderr index 4a25c42b583..dd273b875ae 100644 --- a/tests/ui/builtin-superkinds/builtin-superkinds-typaram-not-send.stderr +++ b/tests/ui/builtin-superkinds/builtin-superkinds-typaram-not-send.stderr @@ -9,7 +9,7 @@ note: required by a bound in `Foo` | LL | trait Foo : Send { } | ^^^^ required by this bound in `Foo` -help: consider further restricting this bound +help: consider further restricting type parameter `T` with trait `Send` | LL | impl <T: Sync+'static + std::marker::Send> Foo for T { } | +++++++++++++++++++ diff --git a/tests/ui/closures/closure-bounds-cant-promote-superkind-in-struct.stderr b/tests/ui/closures/closure-bounds-cant-promote-superkind-in-struct.stderr index 8157590bd9e..9ceee477856 100644 --- a/tests/ui/closures/closure-bounds-cant-promote-superkind-in-struct.stderr +++ b/tests/ui/closures/closure-bounds-cant-promote-superkind-in-struct.stderr @@ -9,7 +9,7 @@ note: required by a bound in `X` | LL | struct X<F> where F: FnOnce() + 'static + Send { | ^^^^ required by this bound in `X` -help: consider further restricting this bound +help: consider further restricting type parameter `F` with trait `Send` | LL | fn foo<F>(blk: F) -> X<F> where F: FnOnce() + 'static + std::marker::Send { | +++++++++++++++++++ @@ -25,7 +25,7 @@ note: required by a bound in `X` | LL | struct X<F> where F: FnOnce() + 'static + Send { | ^^^^ required by this bound in `X` -help: consider further restricting this bound +help: consider further restricting type parameter `F` with trait `Send` | LL | fn foo<F>(blk: F) -> X<F> where F: FnOnce() + 'static + std::marker::Send { | +++++++++++++++++++ diff --git a/tests/ui/closures/closure-bounds-subtype.stderr b/tests/ui/closures/closure-bounds-subtype.stderr index 42588668e8a..34c5e0299a7 100644 --- a/tests/ui/closures/closure-bounds-subtype.stderr +++ b/tests/ui/closures/closure-bounds-subtype.stderr @@ -15,7 +15,7 @@ help: use parentheses to call this type parameter | LL | take_const_owned(f()); | ++ -help: consider further restricting this bound +help: consider further restricting type parameter `F` with trait `Sync` | LL | fn give_owned<F>(f: F) where F: FnOnce() + Send + std::marker::Sync { | +++++++++++++++++++ diff --git a/tests/ui/closures/issue-67123.stderr b/tests/ui/closures/issue-67123.stderr index bdafeaef15f..7db82845ea5 100644 --- a/tests/ui/closures/issue-67123.stderr +++ b/tests/ui/closures/issue-67123.stderr @@ -7,7 +7,7 @@ LL | || { t; t; }; | value moved here | = note: move occurs because `t` has type `T`, which does not implement the `Copy` trait -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | fn foo<T: Copy>(t: T) { | ++++++ diff --git a/tests/ui/codegen/target-cpus.rs b/tests/ui/codegen/target-cpus.rs index 2d46e00f803..363915c6419 100644 --- a/tests/ui/codegen/target-cpus.rs +++ b/tests/ui/codegen/target-cpus.rs @@ -1,3 +1,9 @@ //@ needs-llvm-components: webassembly //@ compile-flags: --print=target-cpus --target=wasm32-unknown-unknown //@ check-pass + +// LLVM at HEAD has added support for the `lime1` CPU. Remove it from the +// output so that the stdout with LLVM-at-HEAD matches the output of the LLVM +// versions currently used by default. +// FIXME(#133919): Once Rust upgrades to LLVM 20, remove this. +//@ normalize-stdout-test: "(?m)^ *lime1\n" -> "" diff --git a/tests/ui/coherence/fuzzing/best-obligation-ICE.stderr b/tests/ui/coherence/fuzzing/best-obligation-ICE.stderr index 88de8023f6d..01b6eaf422e 100644 --- a/tests/ui/coherence/fuzzing/best-obligation-ICE.stderr +++ b/tests/ui/coherence/fuzzing/best-obligation-ICE.stderr @@ -41,7 +41,7 @@ note: required by a bound in `W` | LL | struct W<T: Trait>(*mut T); | ^^^^^ required by this bound in `W` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Trait` | LL | impl<T: Trait> Trait for W<W<W<T>>> {} | +++++++ diff --git a/tests/ui/const-generics/generic_const_exprs/auxiliary/issue-94287-aux.rs b/tests/ui/const-generics/generic_const_exprs/auxiliary/issue-94287-aux.rs deleted file mode 100644 index df454dae725..00000000000 --- a/tests/ui/const-generics/generic_const_exprs/auxiliary/issue-94287-aux.rs +++ /dev/null @@ -1,21 +0,0 @@ -#![feature(generic_const_exprs)] - -use std::str::FromStr; - -pub struct If<const CONDITION: bool>; - -pub trait True {} - -impl True for If<true> {} - -pub struct FixedI32<const FRAC: u32>; - -impl<const FRAC: u32> FromStr for FixedI32<FRAC> -where - If<{ FRAC <= 32 }>: True, -{ - type Err = (); - fn from_str(_s: &str) -> Result<Self, Self::Err> { - unimplemented!() - } -} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-94287.rs b/tests/ui/const-generics/generic_const_exprs/issue-94287.rs deleted file mode 100644 index 4b2fa1dac9b..00000000000 --- a/tests/ui/const-generics/generic_const_exprs/issue-94287.rs +++ /dev/null @@ -1,10 +0,0 @@ -//@ aux-build:issue-94287-aux.rs -//@ build-fail - -extern crate issue_94287_aux; - -use std::str::FromStr; - -fn main() { - let _ = <issue_94287_aux::FixedI32<16>>::from_str(""); -} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-94287.stderr b/tests/ui/const-generics/generic_const_exprs/issue-94287.stderr deleted file mode 100644 index b57779739a5..00000000000 --- a/tests/ui/const-generics/generic_const_exprs/issue-94287.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error: failed to evaluate generic const expression - --> $DIR/auxiliary/issue-94287-aux.rs:15:8 - | -LL | If<{ FRAC <= 32 }>: True, - | ^^^^^^^^^^^^^^ - | - = note: the crate this constant originates from uses `#![feature(generic_const_exprs)]` -help: consider enabling this feature - --> $DIR/issue-94287.rs:1:1 - | -LL + #![feature(generic_const_exprs)] - | - -error: aborting due to 1 previous error - diff --git a/tests/ui/const-generics/issues/issue-61336-2.stderr b/tests/ui/const-generics/issues/issue-61336-2.stderr index b0864689f74..92a704da8b4 100644 --- a/tests/ui/const-generics/issues/issue-61336-2.stderr +++ b/tests/ui/const-generics/issues/issue-61336-2.stderr @@ -7,7 +7,7 @@ LL | [x; { N }] = note: the `Copy` trait is required because this value will be copied for each element of the array = help: consider using `core::array::from_fn` to initialize the array = help: see https://doc.rust-lang.org/stable/std/array/fn.from_fn.html for more information -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | fn g<T: std::marker::Copy, const N: usize>(x: T) -> [T; N] { | +++++++++++++++++++ diff --git a/tests/ui/const-generics/issues/issue-61336.stderr b/tests/ui/const-generics/issues/issue-61336.stderr index 111afbda343..43e8f5c044a 100644 --- a/tests/ui/const-generics/issues/issue-61336.stderr +++ b/tests/ui/const-generics/issues/issue-61336.stderr @@ -7,7 +7,7 @@ LL | [x; N] = note: the `Copy` trait is required because this value will be copied for each element of the array = help: consider using `core::array::from_fn` to initialize the array = help: see https://doc.rust-lang.org/stable/std/array/fn.from_fn.html for more information -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | fn g<T: std::marker::Copy, const N: usize>(x: T) -> [T; N] { | +++++++++++++++++++ diff --git a/tests/ui/consts/ct-var-in-collect_all_mismatches.stderr b/tests/ui/consts/ct-var-in-collect_all_mismatches.stderr index 24572040b91..74ec052f6ec 100644 --- a/tests/ui/consts/ct-var-in-collect_all_mismatches.stderr +++ b/tests/ui/consts/ct-var-in-collect_all_mismatches.stderr @@ -12,7 +12,7 @@ LL | fn unsatisfied(self) LL | where LL | T: Bar<N>, | ^^^^^^ required by this bound in `Foo::<T, N>::unsatisfied` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Bar` | LL | impl<T: Bar<N>, const N: usize> Foo<T, N> { | ++++++++ diff --git a/tests/ui/consts/fn_trait_refs.stderr b/tests/ui/consts/fn_trait_refs.stderr index 11e13c3efdd..bb7ff76b125 100644 --- a/tests/ui/consts/fn_trait_refs.stderr +++ b/tests/ui/consts/fn_trait_refs.stderr @@ -212,10 +212,6 @@ LL | f() | ^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: consider further restricting this bound - | -LL | T: ~const Fn<()> + ~const Destruct + ~const Fn(), - | +++++++++++++ error[E0015]: cannot call non-const closure in constant functions --> $DIR/fn_trait_refs.rs:23:5 @@ -224,10 +220,6 @@ LL | f() | ^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: consider further restricting this bound - | -LL | T: ~const FnMut<()> + ~const Destruct + ~const FnMut(), - | ++++++++++++++++ error[E0015]: cannot call non-const closure in constant functions --> $DIR/fn_trait_refs.rs:30:5 @@ -236,10 +228,6 @@ LL | f() | ^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: consider further restricting this bound - | -LL | T: ~const FnOnce<()> + ~const FnOnce(), - | +++++++++++++++++ error: aborting due to 25 previous errors diff --git a/tests/ui/consts/unstable-const-fn-in-libcore.stderr b/tests/ui/consts/unstable-const-fn-in-libcore.stderr index 2bdec1bf41b..f40c1871e90 100644 --- a/tests/ui/consts/unstable-const-fn-in-libcore.stderr +++ b/tests/ui/consts/unstable-const-fn-in-libcore.stderr @@ -19,10 +19,6 @@ LL | Opt::None => f(), | ^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: consider further restricting this bound - | -LL | const fn unwrap_or_else<F: ~const FnOnce() -> T + ~const FnOnce()>(self, f: F) -> T { - | +++++++++++++++++ error[E0493]: destructor of `F` cannot be evaluated at compile-time --> $DIR/unstable-const-fn-in-libcore.rs:19:60 diff --git a/tests/ui/coroutine/async-gen-yield-ty-is-unit.rs b/tests/ui/coroutine/async-gen-yield-ty-is-unit.rs index 3875e26b544..583820c7aa3 100644 --- a/tests/ui/coroutine/async-gen-yield-ty-is-unit.rs +++ b/tests/ui/coroutine/async-gen-yield-ty-is-unit.rs @@ -1,7 +1,7 @@ //@ compile-flags: --edition 2024 //@ check-pass -#![feature(async_iterator, gen_blocks, noop_waker)] +#![feature(async_iterator, gen_blocks)] use std::{async_iter::AsyncIterator, pin::pin, task::{Context, Waker}}; diff --git a/tests/ui/coroutine/async_gen_fn_iter.rs b/tests/ui/coroutine/async_gen_fn_iter.rs index 3f7e7aa0ac2..81adb618aa5 100644 --- a/tests/ui/coroutine/async_gen_fn_iter.rs +++ b/tests/ui/coroutine/async_gen_fn_iter.rs @@ -2,7 +2,6 @@ //@ run-pass #![feature(gen_blocks, async_iterator)] -#![feature(noop_waker)] // make sure that a ridiculously simple async gen fn works as an iterator. diff --git a/tests/ui/coroutine/polymorphize-args.rs b/tests/ui/coroutine/polymorphize-args.rs deleted file mode 100644 index 5123bf412b5..00000000000 --- a/tests/ui/coroutine/polymorphize-args.rs +++ /dev/null @@ -1,18 +0,0 @@ -//@ compile-flags: -Zpolymorphize=on -//@ build-pass - -#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] - -use std::ops::Coroutine; -use std::pin::Pin; -use std::thread; - -fn main() { - let mut foo = #[coroutine] - || yield; - thread::spawn(move || match Pin::new(&mut foo).resume(()) { - s => panic!("bad state: {:?}", s), - }) - .join() - .unwrap(); -} diff --git a/tests/ui/dropck/explicit-drop-bounds.bad1.stderr b/tests/ui/dropck/explicit-drop-bounds.bad1.stderr index 3ef11e2c0bb..2caa779ffab 100644 --- a/tests/ui/dropck/explicit-drop-bounds.bad1.stderr +++ b/tests/ui/dropck/explicit-drop-bounds.bad1.stderr @@ -9,7 +9,7 @@ note: required by a bound in `DropMe` | LL | struct DropMe<T: Copy>(T); | ^^^^ required by this bound in `DropMe` -help: consider further restricting type parameter `T` +help: consider further restricting type parameter `T` with trait `Copy` | LL | [T; 1]: Copy, T: std::marker::Copy // But `[T; 1]: Copy` does not imply `T: Copy` | ~~~~~~~~~~~~~~~~~~~~~~ @@ -25,7 +25,7 @@ note: required by a bound in `DropMe` | LL | struct DropMe<T: Copy>(T); | ^^^^ required by this bound in `DropMe` -help: consider further restricting type parameter `T` +help: consider further restricting type parameter `T` with trait `Copy` | LL | [T; 1]: Copy, T: std::marker::Copy // But `[T; 1]: Copy` does not imply `T: Copy` | ~~~~~~~~~~~~~~~~~~~~~~ diff --git a/tests/ui/dropck/explicit-drop-bounds.bad2.stderr b/tests/ui/dropck/explicit-drop-bounds.bad2.stderr index 8138b86ddea..5851731e834 100644 --- a/tests/ui/dropck/explicit-drop-bounds.bad2.stderr +++ b/tests/ui/dropck/explicit-drop-bounds.bad2.stderr @@ -9,7 +9,7 @@ note: required by a bound in `DropMe` | LL | struct DropMe<T: Copy>(T); | ^^^^ required by this bound in `DropMe` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | impl<T: std::marker::Copy> Drop for DropMe<T> | +++++++++++++++++++ @@ -25,7 +25,7 @@ note: required by a bound in `DropMe` | LL | struct DropMe<T: Copy>(T); | ^^^^ required by this bound in `DropMe` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | impl<T: std::marker::Copy> Drop for DropMe<T> | +++++++++++++++++++ diff --git a/tests/ui/dyn-star/dispatch-on-pin-mut.rs b/tests/ui/dyn-star/dispatch-on-pin-mut.rs index e17aef47634..be40fa30f0d 100644 --- a/tests/ui/dyn-star/dispatch-on-pin-mut.rs +++ b/tests/ui/dyn-star/dispatch-on-pin-mut.rs @@ -4,7 +4,6 @@ #![feature(dyn_star)] //~^ WARN the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes -#![feature(noop_waker)] use std::future::Future; diff --git a/tests/ui/error-codes/E0229.stderr b/tests/ui/error-codes/E0229.stderr index 038f44e8b14..ab2536cc0c9 100644 --- a/tests/ui/error-codes/E0229.stderr +++ b/tests/ui/error-codes/E0229.stderr @@ -42,7 +42,7 @@ error[E0277]: the trait bound `I: Foo` is not satisfied LL | fn baz<I>(x: &<I as Foo<A = Bar>>::A) {} | ^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `I` | -help: consider restricting type parameter `I` +help: consider restricting type parameter `I` with trait `Foo` | LL | fn baz<I: Foo>(x: &<I as Foo<A = Bar>>::A) {} | +++++ @@ -53,7 +53,7 @@ error[E0277]: the trait bound `I: Foo` is not satisfied LL | fn baz<I>(x: &<I as Foo<A = Bar>>::A) {} | ^^ the trait `Foo` is not implemented for `I` | -help: consider restricting type parameter `I` +help: consider restricting type parameter `I` with trait `Foo` | LL | fn baz<I: Foo>(x: &<I as Foo<A = Bar>>::A) {} | +++++ diff --git a/tests/ui/errors/trait-bound-error-spans/blame-trait-error.stderr b/tests/ui/errors/trait-bound-error-spans/blame-trait-error.stderr index 9228a047e87..b221195a7bd 100644 --- a/tests/ui/errors/trait-bound-error-spans/blame-trait-error.stderr +++ b/tests/ui/errors/trait-bound-error-spans/blame-trait-error.stderr @@ -25,7 +25,7 @@ note: required by a bound in `want` | LL | fn want<V: T1>(_x: V) {} | ^^ required by this bound in `want` -help: consider restricting type parameter `Q` +help: consider restricting type parameter `Q` with trait `T3` | LL | fn example<Q: T3>(q: Q) { | ++++ @@ -73,7 +73,7 @@ note: required by a bound in `want` | LL | fn want<V: T1>(_x: V) {} | ^^ required by this bound in `want` -help: consider restricting type parameter `Q` +help: consider restricting type parameter `Q` with trait `Iterator` | LL | fn example<Q: std::iter::Iterator>(q: Q) { | +++++++++++++++++++++ @@ -100,7 +100,7 @@ note: required by a bound in `want` | LL | fn want<V: T1>(_x: V) {} | ^^ required by this bound in `want` -help: consider restricting type parameter `Q` +help: consider restricting type parameter `Q` with trait `Iterator` | LL | fn example<Q: std::iter::Iterator>(q: Q) { | +++++++++++++++++++++ @@ -125,7 +125,7 @@ note: required by a bound in `want` | LL | fn want<V: T1>(_x: V) {} | ^^ required by this bound in `want` -help: consider restricting type parameter `Q` +help: consider restricting type parameter `Q` with trait `T3` | LL | fn example<Q: T3>(q: Q) { | ++++ @@ -150,7 +150,7 @@ note: required by a bound in `want` | LL | fn want<V: T1>(_x: V) {} | ^^ required by this bound in `want` -help: consider restricting type parameter `Q` +help: consider restricting type parameter `Q` with trait `T3` | LL | fn example<Q: T3>(q: Q) { | ++++ @@ -175,7 +175,7 @@ note: required by a bound in `want` | LL | fn want<V: T1>(_x: V) {} | ^^ required by this bound in `want` -help: consider restricting type parameter `Q` +help: consider restricting type parameter `Q` with trait `T3` | LL | fn example<Q: T3>(q: Q) { | ++++ @@ -200,7 +200,7 @@ note: required by a bound in `want` | LL | fn want<V: T1>(_x: V) {} | ^^ required by this bound in `want` -help: consider restricting type parameter `Q` +help: consider restricting type parameter `Q` with trait `T3` | LL | fn example<Q: T3>(q: Q) { | ++++ @@ -225,7 +225,7 @@ note: required by a bound in `want` | LL | fn want<V: T1>(_x: V) {} | ^^ required by this bound in `want` -help: consider restricting type parameter `Q` +help: consider restricting type parameter `Q` with trait `T3` | LL | fn example<Q: T3>(q: Q) { | ++++ @@ -248,7 +248,7 @@ note: required by a bound in `want` | LL | fn want<V: T1>(_x: V) {} | ^^ required by this bound in `want` -help: consider restricting type parameter `Q` +help: consider restricting type parameter `Q` with trait `T3` | LL | fn example<Q: T3>(q: Q) { | ++++ @@ -273,7 +273,7 @@ note: required by a bound in `want` | LL | fn want<V: T1>(_x: V) {} | ^^ required by this bound in `want` -help: consider restricting type parameter `Q` +help: consider restricting type parameter `Q` with trait `T3` | LL | fn example<Q: T3>(q: Q) { | ++++ @@ -296,7 +296,7 @@ note: required by a bound in `want` | LL | fn want<V: T1>(_x: V) {} | ^^ required by this bound in `want` -help: consider restricting type parameter `Q` +help: consider restricting type parameter `Q` with trait `T3` | LL | fn example<Q: T3>(q: Q) { | ++++ @@ -319,7 +319,7 @@ note: required by a bound in `want` | LL | fn want<V: T1>(_x: V) {} | ^^ required by this bound in `want` -help: consider restricting type parameter `Q` +help: consider restricting type parameter `Q` with trait `T3` | LL | fn example<Q: T3>(q: Q) { | ++++ @@ -342,7 +342,7 @@ note: required by a bound in `want` | LL | fn want<V: T1>(_x: V) {} | ^^ required by this bound in `want` -help: consider restricting type parameter `Q` +help: consider restricting type parameter `Q` with trait `T3` | LL | fn example<Q: T3>(q: Q) { | ++++ @@ -367,7 +367,7 @@ note: required by a bound in `want` | LL | fn want<V: T1>(_x: V) {} | ^^ required by this bound in `want` -help: consider restricting type parameter `Q` +help: consider restricting type parameter `Q` with trait `T3` | LL | fn example<Q: T3>(q: Q) { | ++++ @@ -392,7 +392,7 @@ note: required by a bound in `want` | LL | fn want<V: T1>(_x: V) {} | ^^ required by this bound in `want` -help: consider restricting type parameter `Q` +help: consider restricting type parameter `Q` with trait `T3` | LL | fn example<Q: T3>(q: Q) { | ++++ diff --git a/tests/ui/errors/traits/blame-trait-error-spans-on-exprs.stderr b/tests/ui/errors/traits/blame-trait-error-spans-on-exprs.stderr index b6a24e12bcc..90380091c50 100644 --- a/tests/ui/errors/traits/blame-trait-error-spans-on-exprs.stderr +++ b/tests/ui/errors/traits/blame-trait-error-spans-on-exprs.stderr @@ -23,7 +23,7 @@ note: required by a bound in `want` | LL | fn want<V: T1>(_x: V) {} | ^^ required by this bound in `want` -help: consider restricting type parameter `Q` +help: consider restricting type parameter `Q` with trait `T3` | LL | fn example<Q: T3>(q: Q) { | ++++ @@ -53,7 +53,7 @@ note: required by a bound in `want` | LL | fn want<V: T1>(_x: V) {} | ^^ required by this bound in `want` -help: consider restricting type parameter `Q` +help: consider restricting type parameter `Q` with trait `T3` | LL | fn example<Q: T3>(q: Q) { | ++++ @@ -85,7 +85,7 @@ note: required by a bound in `want` | LL | fn want<V: T1>(_x: V) {} | ^^ required by this bound in `want` -help: consider restricting type parameter `Q` +help: consider restricting type parameter `Q` with trait `T3` | LL | fn example<Q: T3>(q: Q) { | ++++ @@ -117,7 +117,7 @@ note: required by a bound in `want` | LL | fn want<V: T1>(_x: V) {} | ^^ required by this bound in `want` -help: consider restricting type parameter `Q` +help: consider restricting type parameter `Q` with trait `T3` | LL | fn example<Q: T3>(q: Q) { | ++++ @@ -147,7 +147,7 @@ note: required by a bound in `want` | LL | fn want<V: T1>(_x: V) {} | ^^ required by this bound in `want` -help: consider restricting type parameter `Q` +help: consider restricting type parameter `Q` with trait `T3` | LL | fn example<Q: T3>(q: Q) { | ++++ @@ -172,7 +172,7 @@ note: required by a bound in `want` | LL | fn want<V: T1>(_x: V) {} | ^^ required by this bound in `want` -help: consider restricting type parameter `Q` +help: consider restricting type parameter `Q` with trait `T2` | LL | fn example<Q: T2>(q: Q) { | ++++ @@ -204,7 +204,7 @@ note: required by a bound in `want` | LL | fn want<V: T1>(_x: V) {} | ^^ required by this bound in `want` -help: consider restricting type parameter `Q` +help: consider restricting type parameter `Q` with trait `T3` | LL | fn example<Q: T3>(q: Q) { | ++++ @@ -236,7 +236,7 @@ note: required by a bound in `want` | LL | fn want<V: T1>(_x: V) {} | ^^ required by this bound in `want` -help: consider restricting type parameter `Q` +help: consider restricting type parameter `Q` with trait `T3` | LL | fn example<Q: T3>(q: Q) { | ++++ @@ -261,7 +261,7 @@ note: required by a bound in `want` | LL | fn want<V: T1>(_x: V) {} | ^^ required by this bound in `want` -help: consider restricting type parameter `Q` +help: consider restricting type parameter `Q` with trait `T1` | LL | fn example<Q: T1>(q: Q) { | ++++ @@ -286,7 +286,7 @@ note: required by a bound in `want` | LL | fn want<V: T1>(_x: V) {} | ^^ required by this bound in `want` -help: consider restricting type parameter `Q` +help: consider restricting type parameter `Q` with trait `T1` | LL | fn example<Q: T1>(q: Q) { | ++++ @@ -318,7 +318,7 @@ note: required by a bound in `want` | LL | fn want<V: T1>(_x: V) {} | ^^ required by this bound in `want` -help: consider restricting type parameter `Q` +help: consider restricting type parameter `Q` with trait `T3` | LL | fn example<Q: T3>(q: Q) { | ++++ @@ -343,7 +343,7 @@ note: required by a bound in `want` | LL | fn want<V: T1>(_x: V) {} | ^^ required by this bound in `want` -help: consider restricting type parameter `Q` +help: consider restricting type parameter `Q` with trait `T1` | LL | fn example<Q: T1>(q: Q) { | ++++ @@ -370,7 +370,7 @@ note: required by a bound in `want` | LL | fn want<V: T1>(_x: V) {} | ^^ required by this bound in `want` -help: consider restricting type parameter `Q` +help: consider restricting type parameter `Q` with trait `T1` | LL | fn example<Q: T1>(q: Q) { | ++++ @@ -402,7 +402,7 @@ note: required by a bound in `want` | LL | fn want<V: T1>(_x: V) {} | ^^ required by this bound in `want` -help: consider restricting type parameter `Q` +help: consider restricting type parameter `Q` with trait `T3` | LL | fn example<Q: T3>(q: Q) { | ++++ diff --git a/tests/ui/explicit-tail-calls/become-macro.rs b/tests/ui/explicit-tail-calls/become-macro.rs new file mode 100644 index 00000000000..0a9d069ceb3 --- /dev/null +++ b/tests/ui/explicit-tail-calls/become-macro.rs @@ -0,0 +1,13 @@ +//@ check-pass +#![expect(incomplete_features)] +#![feature(explicit_tail_calls, decl_macro)] + +macro call($f:expr $(, $args:expr)* $(,)?) { + ($f)($($args),*) +} + +fn main() { + become call!(f); +} + +fn f() {} diff --git a/tests/ui/explicit-tail-calls/become-operator.fixed b/tests/ui/explicit-tail-calls/become-operator.fixed new file mode 100644 index 00000000000..24baef42d69 --- /dev/null +++ b/tests/ui/explicit-tail-calls/become-operator.fixed @@ -0,0 +1,42 @@ +//@ run-rustfix +#![expect(incomplete_features)] +#![feature(explicit_tail_calls)] +#![allow(unused)] +use std::num::Wrapping; +use std::ops::{Not, Add, BitXorAssign}; + +// built-ins and overloaded operators are handled differently + +fn f(a: u64, b: u64) -> u64 { + return a + b; //~ error: `become` does not support operators +} + +fn g(a: String, b: &str) -> String { + become (a).add(b); //~ error: `become` does not support operators +} + +fn h(x: u64) -> u64 { + return !x; //~ error: `become` does not support operators +} + +fn i_do_not_know_any_more_letters(x: Wrapping<u32>) -> Wrapping<u32> { + become (x).not(); //~ error: `become` does not support operators +} + +fn builtin_index(x: &[u8], i: usize) -> u8 { + return x[i] //~ error: `become` does not support operators +} + +// FIXME(explicit_tail_calls): overloaded index is represented like `[&]*x.index(i)`, +// and so need additional handling + +fn a(a: &mut u8, _: u8) { + return *a ^= 1; //~ error: `become` does not support operators +} + +fn b(b: &mut Wrapping<u8>, _: u8) { + become (*b).bitxor_assign(1); //~ error: `become` does not support operators +} + + +fn main() {} diff --git a/tests/ui/explicit-tail-calls/become-operator.rs b/tests/ui/explicit-tail-calls/become-operator.rs new file mode 100644 index 00000000000..e547e979b64 --- /dev/null +++ b/tests/ui/explicit-tail-calls/become-operator.rs @@ -0,0 +1,42 @@ +//@ run-rustfix +#![expect(incomplete_features)] +#![feature(explicit_tail_calls)] +#![allow(unused)] +use std::num::Wrapping; +use std::ops::{Not, Add, BitXorAssign}; + +// built-ins and overloaded operators are handled differently + +fn f(a: u64, b: u64) -> u64 { + become a + b; //~ error: `become` does not support operators +} + +fn g(a: String, b: &str) -> String { + become a + b; //~ error: `become` does not support operators +} + +fn h(x: u64) -> u64 { + become !x; //~ error: `become` does not support operators +} + +fn i_do_not_know_any_more_letters(x: Wrapping<u32>) -> Wrapping<u32> { + become !x; //~ error: `become` does not support operators +} + +fn builtin_index(x: &[u8], i: usize) -> u8 { + become x[i] //~ error: `become` does not support operators +} + +// FIXME(explicit_tail_calls): overloaded index is represented like `[&]*x.index(i)`, +// and so need additional handling + +fn a(a: &mut u8, _: u8) { + become *a ^= 1; //~ error: `become` does not support operators +} + +fn b(b: &mut Wrapping<u8>, _: u8) { + become *b ^= 1; //~ error: `become` does not support operators +} + + +fn main() {} diff --git a/tests/ui/explicit-tail-calls/become-operator.stderr b/tests/ui/explicit-tail-calls/become-operator.stderr new file mode 100644 index 00000000000..26e4343faae --- /dev/null +++ b/tests/ui/explicit-tail-calls/become-operator.stderr @@ -0,0 +1,75 @@ +error: `become` does not support operators + --> $DIR/become-operator.rs:11:12 + | +LL | become a + b; + | -------^^^^^ + | | + | help: try using `return` instead: `return` + | + = note: using `become` on a builtin operator is not useful + +error: `become` does not support operators + --> $DIR/become-operator.rs:15:12 + | +LL | become a + b; + | ^^^^^ + | +help: try using the method directly + | +LL | become (a).add(b); + | + ~~~~~~ + + +error: `become` does not support operators + --> $DIR/become-operator.rs:19:12 + | +LL | become !x; + | -------^^ + | | + | help: try using `return` instead: `return` + | + = note: using `become` on a builtin operator is not useful + +error: `become` does not support operators + --> $DIR/become-operator.rs:23:12 + | +LL | become !x; + | ^^ + | +help: try using the method directly + | +LL | become (x).not(); + | ~ +++++++ + +error: `become` does not support operators + --> $DIR/become-operator.rs:27:12 + | +LL | become x[i] + | -------^^^^ + | | + | help: try using `return` instead: `return` + | + = note: using `become` on a builtin operator is not useful + +error: `become` does not support operators + --> $DIR/become-operator.rs:34:12 + | +LL | become *a ^= 1; + | -------^^^^^^^ + | | + | help: try using `return` instead: `return` + | + = note: using `become` on a builtin operator is not useful + +error: `become` does not support operators + --> $DIR/become-operator.rs:38:12 + | +LL | become *b ^= 1; + | ^^^^^^^ + | +help: try using the method directly + | +LL | become (*b).bitxor_assign(1); + | + ~~~~~~~~~~~~~~~~ + + +error: aborting due to 7 previous errors + diff --git a/tests/ui/explicit-tail-calls/become-outside.rs b/tests/ui/explicit-tail-calls/become-outside.rs index 9c90d929111..29738bb9a29 100644 --- a/tests/ui/explicit-tail-calls/become-outside.rs +++ b/tests/ui/explicit-tail-calls/become-outside.rs @@ -1,5 +1,5 @@ //@ revisions: constant array -#![allow(incomplete_features)] +#![expect(incomplete_features)] #![feature(explicit_tail_calls)] #[cfg(constant)] diff --git a/tests/ui/explicit-tail-calls/become-uncallable.fixed b/tests/ui/explicit-tail-calls/become-uncallable.fixed new file mode 100644 index 00000000000..b77c46ea435 --- /dev/null +++ b/tests/ui/explicit-tail-calls/become-uncallable.fixed @@ -0,0 +1,18 @@ +//@ run-rustfix +#![expect(incomplete_features)] +#![feature(explicit_tail_calls)] +#![allow(unused)] + +fn f() -> u64 { + return 1; //~ error: `become` requires a function call +} + +fn g() { + return { h() }; //~ error: `become` requires a function call +} + +fn h() { + return *&g(); //~ error: `become` requires a function call +} + +fn main() {} diff --git a/tests/ui/explicit-tail-calls/become-uncallable.rs b/tests/ui/explicit-tail-calls/become-uncallable.rs new file mode 100644 index 00000000000..a73b9258aaa --- /dev/null +++ b/tests/ui/explicit-tail-calls/become-uncallable.rs @@ -0,0 +1,18 @@ +//@ run-rustfix +#![expect(incomplete_features)] +#![feature(explicit_tail_calls)] +#![allow(unused)] + +fn f() -> u64 { + become 1; //~ error: `become` requires a function call +} + +fn g() { + become { h() }; //~ error: `become` requires a function call +} + +fn h() { + become *&g(); //~ error: `become` requires a function call +} + +fn main() {} diff --git a/tests/ui/explicit-tail-calls/become-uncallable.stderr b/tests/ui/explicit-tail-calls/become-uncallable.stderr new file mode 100644 index 00000000000..90f10b05d2a --- /dev/null +++ b/tests/ui/explicit-tail-calls/become-uncallable.stderr @@ -0,0 +1,44 @@ +error: `become` requires a function call + --> $DIR/become-uncallable.rs:7:12 + | +LL | become 1; + | -------^ + | | + | help: try using `return` instead: `return` + | +note: not a function call + --> $DIR/become-uncallable.rs:7:12 + | +LL | become 1; + | ^ + +error: `become` requires a function call + --> $DIR/become-uncallable.rs:11:12 + | +LL | become { h() }; + | -------^^^^^^^ + | | + | help: try using `return` instead: `return` + | +note: not a function call + --> $DIR/become-uncallable.rs:11:12 + | +LL | become { h() }; + | ^^^^^^^ + +error: `become` requires a function call + --> $DIR/become-uncallable.rs:15:12 + | +LL | become *&g(); + | -------^^^^^ + | | + | help: try using `return` instead: `return` + | +note: not a function call + --> $DIR/become-uncallable.rs:15:12 + | +LL | become *&g(); + | ^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/explicit-tail-calls/closure.fixed b/tests/ui/explicit-tail-calls/closure.fixed new file mode 100644 index 00000000000..4af71c5d4cc --- /dev/null +++ b/tests/ui/explicit-tail-calls/closure.fixed @@ -0,0 +1,31 @@ +//@ run-rustfix +#![expect(incomplete_features)] +#![feature(explicit_tail_calls)] + +fn a() { + become ((|| ()) as fn() -> _)(); + //~^ ERROR: tail calling closures directly is not allowed +} + +fn aa((): ()) { + become ((|()| ()) as fn(_) -> _)(()); + //~^ ERROR: tail calling closures directly is not allowed +} + +fn aaa((): (), _: i32) { + become ((|(), _| ()) as fn(_, _) -> _)((), 1); + //~^ ERROR: tail calling closures directly is not allowed +} + +fn v((): (), ((), ()): ((), ())) -> (((), ()), ()) { + let f = |(), ((), ())| (((), ()), ()); + become (f as fn(_, _) -> _)((), ((), ())); + //~^ ERROR: tail calling closures directly is not allowed +} + +fn main() { + a(); + aa(()); + aaa((), 1); + v((), ((), ())); +} diff --git a/tests/ui/explicit-tail-calls/closure.rs b/tests/ui/explicit-tail-calls/closure.rs new file mode 100644 index 00000000000..79a1b5296b0 --- /dev/null +++ b/tests/ui/explicit-tail-calls/closure.rs @@ -0,0 +1,31 @@ +//@ run-rustfix +#![expect(incomplete_features)] +#![feature(explicit_tail_calls)] + +fn a() { + become (|| ())(); + //~^ ERROR: tail calling closures directly is not allowed +} + +fn aa((): ()) { + become (|()| ())(()); + //~^ ERROR: tail calling closures directly is not allowed +} + +fn aaa((): (), _: i32) { + become (|(), _| ())((), 1); + //~^ ERROR: tail calling closures directly is not allowed +} + +fn v((): (), ((), ()): ((), ())) -> (((), ()), ()) { + let f = |(), ((), ())| (((), ()), ()); + become f((), ((), ())); + //~^ ERROR: tail calling closures directly is not allowed +} + +fn main() { + a(); + aa(()); + aaa((), 1); + v((), ((), ())); +} diff --git a/tests/ui/explicit-tail-calls/closure.stderr b/tests/ui/explicit-tail-calls/closure.stderr new file mode 100644 index 00000000000..5d57bece68e --- /dev/null +++ b/tests/ui/explicit-tail-calls/closure.stderr @@ -0,0 +1,46 @@ +error: tail calling closures directly is not allowed + --> $DIR/closure.rs:6:5 + | +LL | become (|| ())(); + | ^^^^^^^^^^^^^^^^ + | +help: try casting the closure to a function pointer type + | +LL | become ((|| ()) as fn() -> _)(); + | + +++++++++++++ + +error: tail calling closures directly is not allowed + --> $DIR/closure.rs:11:5 + | +LL | become (|()| ())(()); + | ^^^^^^^^^^^^^^^^^^^^ + | +help: try casting the closure to a function pointer type + | +LL | become ((|()| ()) as fn(_) -> _)(()); + | + ++++++++++++++ + +error: tail calling closures directly is not allowed + --> $DIR/closure.rs:16:5 + | +LL | become (|(), _| ())((), 1); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try casting the closure to a function pointer type + | +LL | become ((|(), _| ()) as fn(_, _) -> _)((), 1); + | + +++++++++++++++++ + +error: tail calling closures directly is not allowed + --> $DIR/closure.rs:22:5 + | +LL | become f((), ((), ())); + | ^^^^^^^^^^^^^^^^^^^^^^ + | +help: try casting the closure to a function pointer type + | +LL | become (f as fn(_, _) -> _)((), ((), ())); + | + +++++++++++++++++ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/explicit-tail-calls/constck.rs b/tests/ui/explicit-tail-calls/constck.rs index 938f15f12c0..36fc3ef6f99 100644 --- a/tests/ui/explicit-tail-calls/constck.rs +++ b/tests/ui/explicit-tail-calls/constck.rs @@ -1,4 +1,4 @@ -#![allow(incomplete_features)] +#![expect(incomplete_features)] #![feature(explicit_tail_calls)] const fn f() { diff --git a/tests/ui/explicit-tail-calls/ctfe-arg-bad-borrow.rs b/tests/ui/explicit-tail-calls/ctfe-arg-bad-borrow.rs index 5a105ee4eb5..0a61c90bd00 100644 --- a/tests/ui/explicit-tail-calls/ctfe-arg-bad-borrow.rs +++ b/tests/ui/explicit-tail-calls/ctfe-arg-bad-borrow.rs @@ -1,4 +1,4 @@ -#![allow(incomplete_features)] +#![expect(incomplete_features)] #![feature(explicit_tail_calls)] pub const fn test(_: &Type) { diff --git a/tests/ui/explicit-tail-calls/ctfe-arg-good-borrow.rs b/tests/ui/explicit-tail-calls/ctfe-arg-good-borrow.rs index 50bf6c946ca..a34482a3527 100644 --- a/tests/ui/explicit-tail-calls/ctfe-arg-good-borrow.rs +++ b/tests/ui/explicit-tail-calls/ctfe-arg-good-borrow.rs @@ -1,5 +1,5 @@ //@ check-pass -#![allow(incomplete_features)] +#![expect(incomplete_features)] #![feature(explicit_tail_calls)] pub const fn test(x: &Type) { diff --git a/tests/ui/explicit-tail-calls/ctfe-arg-move.rs b/tests/ui/explicit-tail-calls/ctfe-arg-move.rs index 88ff3a4a5ad..610eb74a91e 100644 --- a/tests/ui/explicit-tail-calls/ctfe-arg-move.rs +++ b/tests/ui/explicit-tail-calls/ctfe-arg-move.rs @@ -1,5 +1,5 @@ //@ check-pass -#![allow(incomplete_features)] +#![expect(incomplete_features)] #![feature(explicit_tail_calls)] pub const fn test(s: String) -> String { diff --git a/tests/ui/explicit-tail-calls/ctfe-collatz-multi-rec.rs b/tests/ui/explicit-tail-calls/ctfe-collatz-multi-rec.rs index 86041b66960..53d46d92bd7 100644 --- a/tests/ui/explicit-tail-calls/ctfe-collatz-multi-rec.rs +++ b/tests/ui/explicit-tail-calls/ctfe-collatz-multi-rec.rs @@ -1,5 +1,5 @@ //@ run-pass -#![allow(incomplete_features)] +#![expect(incomplete_features)] #![feature(explicit_tail_calls)] /// A very unnecessarily complicated "implementation" of the Collatz conjecture. diff --git a/tests/ui/explicit-tail-calls/ctfe-id-unlimited.rs b/tests/ui/explicit-tail-calls/ctfe-id-unlimited.rs index 54e68b2b7f7..2a04d4893e6 100644 --- a/tests/ui/explicit-tail-calls/ctfe-id-unlimited.rs +++ b/tests/ui/explicit-tail-calls/ctfe-id-unlimited.rs @@ -1,6 +1,6 @@ //@ revisions: become return //@ [become] run-pass -#![allow(incomplete_features)] +#![expect(incomplete_features)] #![feature(explicit_tail_calls)] // This is an identity function (`|x| x`), but implemented using recursion. diff --git a/tests/ui/explicit-tail-calls/ctfe-tail-call-panic.rs b/tests/ui/explicit-tail-calls/ctfe-tail-call-panic.rs index 3d69cde2989..fba4a2692af 100644 --- a/tests/ui/explicit-tail-calls/ctfe-tail-call-panic.rs +++ b/tests/ui/explicit-tail-calls/ctfe-tail-call-panic.rs @@ -1,4 +1,4 @@ -#![allow(incomplete_features)] +#![expect(incomplete_features)] #![feature(explicit_tail_calls)] pub const fn f() { diff --git a/tests/ui/explicit-tail-calls/drop-order.rs b/tests/ui/explicit-tail-calls/drop-order.rs index e20730446ec..242336be484 100644 --- a/tests/ui/explicit-tail-calls/drop-order.rs +++ b/tests/ui/explicit-tail-calls/drop-order.rs @@ -1,7 +1,7 @@ // FIXME(explicit_tail_calls): enable this test once rustc_codegen_ssa supports tail calls //@ ignore-test: tail calls are not implemented in rustc_codegen_ssa yet, so this causes 🧊 //@ run-pass -#![allow(incomplete_features)] +#![expect(incomplete_features)] #![feature(explicit_tail_calls)] use std::cell::RefCell; diff --git a/tests/ui/explicit-tail-calls/in-closure.rs b/tests/ui/explicit-tail-calls/in-closure.rs new file mode 100644 index 00000000000..b23ff5a1e05 --- /dev/null +++ b/tests/ui/explicit-tail-calls/in-closure.rs @@ -0,0 +1,8 @@ +#![expect(incomplete_features)] +#![feature(explicit_tail_calls)] + +fn main() { + || become f(); //~ error: `become` is not allowed in closures +} + +fn f() {} diff --git a/tests/ui/explicit-tail-calls/in-closure.stderr b/tests/ui/explicit-tail-calls/in-closure.stderr new file mode 100644 index 00000000000..d221f732e93 --- /dev/null +++ b/tests/ui/explicit-tail-calls/in-closure.stderr @@ -0,0 +1,8 @@ +error: `become` is not allowed in closures + --> $DIR/in-closure.rs:5:8 + | +LL | || become f(); + | ^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/explicit-tail-calls/return-lifetime-sub.rs b/tests/ui/explicit-tail-calls/return-lifetime-sub.rs index 1243fba9b58..df0982cc02b 100644 --- a/tests/ui/explicit-tail-calls/return-lifetime-sub.rs +++ b/tests/ui/explicit-tail-calls/return-lifetime-sub.rs @@ -1,5 +1,5 @@ //@ check-pass -#![allow(incomplete_features)] +#![expect(incomplete_features)] #![feature(explicit_tail_calls)] fn _f<'a>() -> &'a [u8] { diff --git a/tests/ui/explicit-tail-calls/return-mismatches.rs b/tests/ui/explicit-tail-calls/return-mismatches.rs index 935a1a1d28b..e48766b89b0 100644 --- a/tests/ui/explicit-tail-calls/return-mismatches.rs +++ b/tests/ui/explicit-tail-calls/return-mismatches.rs @@ -1,4 +1,4 @@ -#![allow(incomplete_features)] +#![expect(incomplete_features)] #![feature(explicit_tail_calls)] fn _f0<'a>() -> &'static [u8] { diff --git a/tests/ui/explicit-tail-calls/signature-mismatch.rs b/tests/ui/explicit-tail-calls/signature-mismatch.rs new file mode 100644 index 00000000000..a32ac9d8bfe --- /dev/null +++ b/tests/ui/explicit-tail-calls/signature-mismatch.rs @@ -0,0 +1,33 @@ +#![expect(incomplete_features)] +#![feature(explicit_tail_calls)] +#![feature(c_variadic)] + +fn _f0((): ()) { + become _g0(); //~ error: mismatched signatures +} + +fn _g0() {} + + +fn _f1() { + become _g1(()); //~ error: mismatched signatures +} + +fn _g1((): ()) {} + + +extern "C" fn _f2() { + become _g2(); //~ error: mismatched function ABIs +} + +fn _g2() {} + + +fn _f3() { + become _g3(); //~ error: mismatched function ABIs +} + +extern "C" fn _g3() {} + + +fn main() {} diff --git a/tests/ui/explicit-tail-calls/signature-mismatch.stderr b/tests/ui/explicit-tail-calls/signature-mismatch.stderr new file mode 100644 index 00000000000..ba9e9dcb984 --- /dev/null +++ b/tests/ui/explicit-tail-calls/signature-mismatch.stderr @@ -0,0 +1,40 @@ +error: mismatched signatures + --> $DIR/signature-mismatch.rs:6:5 + | +LL | become _g0(); + | ^^^^^^^^^^^^ + | + = note: `become` requires caller and callee to have matching signatures + = note: caller signature: `fn(())` + = note: callee signature: `fn()` + +error: mismatched signatures + --> $DIR/signature-mismatch.rs:13:5 + | +LL | become _g1(()); + | ^^^^^^^^^^^^^^ + | + = note: `become` requires caller and callee to have matching signatures + = note: caller signature: `fn()` + = note: callee signature: `fn(())` + +error: mismatched function ABIs + --> $DIR/signature-mismatch.rs:20:5 + | +LL | become _g2(); + | ^^^^^^^^^^^^ + | + = note: `become` requires caller and callee to have the same ABI + = note: caller ABI is `"C"`, while callee ABI is `"Rust"` + +error: mismatched function ABIs + --> $DIR/signature-mismatch.rs:27:5 + | +LL | become _g3(); + | ^^^^^^^^^^^^ + | + = note: `become` requires caller and callee to have the same ABI + = note: caller ABI is `"Rust"`, while callee ABI is `"C"` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/explicit-tail-calls/unsafeck.rs b/tests/ui/explicit-tail-calls/unsafeck.rs index 872a70ca3a0..f8a8140cedc 100644 --- a/tests/ui/explicit-tail-calls/unsafeck.rs +++ b/tests/ui/explicit-tail-calls/unsafeck.rs @@ -1,4 +1,4 @@ -#![allow(incomplete_features)] +#![expect(incomplete_features)] #![feature(explicit_tail_calls)] const fn f() { diff --git a/tests/ui/generic-associated-types/generic-associated-types-where.stderr b/tests/ui/generic-associated-types/generic-associated-types-where.stderr index 9a745c099c0..7dce34650d7 100644 --- a/tests/ui/generic-associated-types/generic-associated-types-where.stderr +++ b/tests/ui/generic-associated-types/generic-associated-types-where.stderr @@ -5,7 +5,7 @@ LL | type Assoc2<T> = Vec<T>; | ^^^^^^ `T` cannot be formatted with the default formatter | = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Display` | LL | type Assoc2<T: std::fmt::Display> = Vec<T>; | +++++++++++++++++++ diff --git a/tests/ui/generic-associated-types/impl_bounds.stderr b/tests/ui/generic-associated-types/impl_bounds.stderr index 261070d1db4..aa56505dd30 100644 --- a/tests/ui/generic-associated-types/impl_bounds.stderr +++ b/tests/ui/generic-associated-types/impl_bounds.stderr @@ -41,7 +41,7 @@ LL | trait Foo { LL | type C where Self: Clone; | ^ this trait's associated type doesn't have the requirement `Fooy<T>: Copy` = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | impl<T: std::marker::Copy> Foo for Fooy<T> { | +++++++++++++++++++ @@ -66,7 +66,7 @@ LL | trait Foo { LL | fn d() where Self: Clone; | ^ this trait's method doesn't have the requirement `Fooy<T>: Copy` = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | impl<T: std::marker::Copy> Foo for Fooy<T> { | +++++++++++++++++++ diff --git a/tests/ui/generic-associated-types/issue-68641-check-gat-bounds.stderr b/tests/ui/generic-associated-types/issue-68641-check-gat-bounds.stderr index 55901cf450b..ac91bdcf3e9 100644 --- a/tests/ui/generic-associated-types/issue-68641-check-gat-bounds.stderr +++ b/tests/ui/generic-associated-types/issue-68641-check-gat-bounds.stderr @@ -9,7 +9,7 @@ note: required by a bound in `UnsafeCopy::Item` | LL | type Item<'a>: Copy; | ^^^^ required by this bound in `UnsafeCopy::Item` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | impl<T: std::marker::Copy> UnsafeCopy for T { | +++++++++++++++++++ diff --git a/tests/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr b/tests/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr index 3929e66a25a..d98071efe83 100644 --- a/tests/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr +++ b/tests/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr @@ -10,7 +10,7 @@ note: required by a bound in `Fun::F` | LL | type F<'a>: Fn() -> u32; | ^^^^^^^^^^^ required by this bound in `Fun::F` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Fn` | LL | impl<T: Fn()> Fun for T { | ++++++ diff --git a/tests/ui/generic-associated-types/issue-68643-broken-mir.stderr b/tests/ui/generic-associated-types/issue-68643-broken-mir.stderr index 662726b8993..cd4c06a8660 100644 --- a/tests/ui/generic-associated-types/issue-68643-broken-mir.stderr +++ b/tests/ui/generic-associated-types/issue-68643-broken-mir.stderr @@ -10,7 +10,7 @@ note: required by a bound in `Fun::F` | LL | type F<'a>: Fn() -> u32; | ^^^^^^^^^^^ required by this bound in `Fun::F` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Fn` | LL | impl<T: Fn()> Fun for T { | ++++++ diff --git a/tests/ui/generic-associated-types/issue-68644-codegen-selection.stderr b/tests/ui/generic-associated-types/issue-68644-codegen-selection.stderr index 34278249e35..12f9949a0d3 100644 --- a/tests/ui/generic-associated-types/issue-68644-codegen-selection.stderr +++ b/tests/ui/generic-associated-types/issue-68644-codegen-selection.stderr @@ -10,7 +10,7 @@ note: required by a bound in `Fun::F` | LL | type F<'a>: Fn() -> u32; | ^^^^^^^^^^^ required by this bound in `Fun::F` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Fn` | LL | impl<T: Fn()> Fun for T { | ++++++ diff --git a/tests/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr b/tests/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr index dafe1c1d395..8b23f609530 100644 --- a/tests/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr +++ b/tests/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr @@ -10,7 +10,7 @@ note: required by a bound in `Fun::F` | LL | type F<'a>: Fn() -> u32; | ^^^^^^^^^^^ required by this bound in `Fun::F` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Fn` | LL | impl<T: Fn()> Fun for T { | ++++++ diff --git a/tests/ui/generic-associated-types/issue-74824.current.stderr b/tests/ui/generic-associated-types/issue-74824.current.stderr index 231136612a0..3a72db27097 100644 --- a/tests/ui/generic-associated-types/issue-74824.current.stderr +++ b/tests/ui/generic-associated-types/issue-74824.current.stderr @@ -23,7 +23,7 @@ note: required by a bound in `UnsafeCopy::Copy` | LL | type Copy<T>: Copy = Box<T>; | ^^^^ required by this bound in `UnsafeCopy::Copy` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Clone` | LL | type Copy<T: std::clone::Clone>: Copy = Box<T>; | +++++++++++++++++++ diff --git a/tests/ui/generic-associated-types/issue-74824.next.stderr b/tests/ui/generic-associated-types/issue-74824.next.stderr index 231136612a0..3a72db27097 100644 --- a/tests/ui/generic-associated-types/issue-74824.next.stderr +++ b/tests/ui/generic-associated-types/issue-74824.next.stderr @@ -23,7 +23,7 @@ note: required by a bound in `UnsafeCopy::Copy` | LL | type Copy<T>: Copy = Box<T>; | ^^^^ required by this bound in `UnsafeCopy::Copy` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Clone` | LL | type Copy<T: std::clone::Clone>: Copy = Box<T>; | +++++++++++++++++++ diff --git a/tests/ui/generic-associated-types/missing-bounds.stderr b/tests/ui/generic-associated-types/missing-bounds.stderr index 1d7d80d1b07..6e0700639e9 100644 --- a/tests/ui/generic-associated-types/missing-bounds.stderr +++ b/tests/ui/generic-associated-types/missing-bounds.stderr @@ -71,7 +71,7 @@ LL | Self(self.0 + rhs.0) | | | B | -help: consider restricting type parameter `B` +help: consider restricting type parameter `B` with trait `Add` | LL | impl<B: std::ops::Add<Output = B>> Add for D<B> { | +++++++++++++++++++++++++++ diff --git a/tests/ui/higher-ranked/structually-relate-aliases.stderr b/tests/ui/higher-ranked/structually-relate-aliases.stderr index cf3e4cc85b9..025fcc5e170 100644 --- a/tests/ui/higher-ranked/structually-relate-aliases.stderr +++ b/tests/ui/higher-ranked/structually-relate-aliases.stderr @@ -5,7 +5,7 @@ error[E0277]: the trait bound `for<'a> T: ToUnit<'a>` is not satisfied LL | impl<T> Overlap<for<'a> fn(&'a (), Assoc<'a, T>)> for T {} | ^^^^^^^^^^^^ the trait `for<'a> ToUnit<'a>` is not implemented for `T` | -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `ToUnit` | LL | impl<T: for<'a> ToUnit<'a>> Overlap<for<'a> fn(&'a (), Assoc<'a, T>)> for T {} | ++++++++++++++++++++ diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits-transitive.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits-transitive.stderr index e10da26665e..da6013a4af3 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits-transitive.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits-transitive.stderr @@ -13,7 +13,7 @@ LL | fn want_bar_for_any_ccx<B>(b: &B) | -------------------- required by a bound in this function LL | where B : for<'ccx> Bar<'ccx> | ^^^^^^^^^^^^^^^^^^^ required by this bound in `want_bar_for_any_ccx` -help: consider further restricting this bound +help: consider further restricting type parameter `B` with trait `Bar` | LL | where B : Qux + for<'ccx> Bar<'ccx> | +++++++++++++++++++++ diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-85455.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-85455.stderr index e60531a876b..5080d35bdde 100644 --- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-85455.stderr +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-85455.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `for<'a> T: SomeTrait<'a>` is not satisfied LL | callee::<fn(&()) -> <T as SomeTrait<'_>>::Associated>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> SomeTrait<'a>` is not implemented for `T` | -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `SomeTrait` | LL | fn give_me_ice<T: for<'a> SomeTrait<'a>>() { | +++++++++++++++++++++++ @@ -15,7 +15,7 @@ error[E0277]: the trait bound `for<'a> T: SomeTrait<'a>` is not satisfied LL | callee::<fn(&()) -> <T as SomeTrait<'_>>::Associated>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> SomeTrait<'a>` is not implemented for `T` | -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `SomeTrait` | LL | fn give_me_ice<T: for<'a> SomeTrait<'a>>() { | +++++++++++++++++++++++ diff --git a/tests/ui/impl-trait/auto-trait-selection-freeze.next.stderr b/tests/ui/impl-trait/auto-trait-selection-freeze.next.stderr index 5caf0eb2fd4..54ceec0aff5 100644 --- a/tests/ui/impl-trait/auto-trait-selection-freeze.next.stderr +++ b/tests/ui/impl-trait/auto-trait-selection-freeze.next.stderr @@ -1,22 +1,9 @@ -error[E0283]: type annotations needed - --> $DIR/auto-trait-selection-freeze.rs:19:16 +error[E0284]: type annotations needed: cannot satisfy `impl Sized == _` + --> $DIR/auto-trait-selection-freeze.rs:19:5 | LL | if false { is_trait(foo()) } else { Default::default() } - | ^^^^^^^^ ----- type must be known at this point - | | - | cannot infer type of the type parameter `T` declared on the function `is_trait` - | - = note: cannot satisfy `_: Trait<_>` -note: required by a bound in `is_trait` - --> $DIR/auto-trait-selection-freeze.rs:11:16 - | -LL | fn is_trait<T: Trait<U>, U: Default>(_: T) -> U { - | ^^^^^^^^ required by this bound in `is_trait` -help: consider specifying the generic arguments - | -LL | if false { is_trait::<T, U>(foo()) } else { Default::default() } - | ++++++++ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `impl Sized == _` error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0283`. +For more information about this error, try `rustc --explain E0284`. diff --git a/tests/ui/impl-trait/auto-trait-selection.next.stderr b/tests/ui/impl-trait/auto-trait-selection.next.stderr index d34fdcc4496..7acb9fd41b7 100644 --- a/tests/ui/impl-trait/auto-trait-selection.next.stderr +++ b/tests/ui/impl-trait/auto-trait-selection.next.stderr @@ -1,22 +1,9 @@ -error[E0283]: type annotations needed - --> $DIR/auto-trait-selection.rs:15:16 +error[E0284]: type annotations needed: cannot satisfy `impl Sized == _` + --> $DIR/auto-trait-selection.rs:15:5 | LL | if false { is_trait(foo()) } else { Default::default() } - | ^^^^^^^^ ----- type must be known at this point - | | - | cannot infer type of the type parameter `T` declared on the function `is_trait` - | - = note: cannot satisfy `_: Trait<_>` -note: required by a bound in `is_trait` - --> $DIR/auto-trait-selection.rs:7:16 - | -LL | fn is_trait<T: Trait<U>, U: Default>(_: T) -> U { - | ^^^^^^^^ required by this bound in `is_trait` -help: consider specifying the generic arguments - | -LL | if false { is_trait::<T, U>(foo()) } else { Default::default() } - | ++++++++ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `impl Sized == _` error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0283`. +For more information about this error, try `rustc --explain E0284`. diff --git a/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.current.stderr b/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.current.stderr index 38c7a9ea16e..1ddbd75142f 100644 --- a/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.current.stderr +++ b/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.current.stderr @@ -17,7 +17,7 @@ LL | impl<A, F: MyFn<A>> Callback<A> for F { | ------- ^^^^^^^^^^^ ^ | | | unsatisfied trait bound introduced here -help: consider further restricting this bound +help: consider further restricting type parameter `F` with trait `MyFn` | LL | F: Callback<Self::CallbackArg> + MyFn<i32>, | +++++++++++ @@ -43,7 +43,7 @@ LL | fn autobatch<F>(self) -> impl Trait ... LL | F: Callback<Self::CallbackArg>, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `<Sender as ChannelSender>::autobatch` -help: consider further restricting this bound +help: consider further restricting type parameter `F` with trait `MyFn` | LL | F: Callback<Self::CallbackArg> + MyFn<i32>, | +++++++++++ @@ -68,7 +68,7 @@ LL | impl<A, F: MyFn<A>> Callback<A> for F { | | | unsatisfied trait bound introduced here = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: consider further restricting this bound +help: consider further restricting type parameter `F` with trait `MyFn` | LL | F: Callback<Self::CallbackArg> + MyFn<i32>, | +++++++++++ @@ -121,7 +121,7 @@ LL | impl<A, F: MyFn<A>> Callback<A> for F { | | | unsatisfied trait bound introduced here = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: consider further restricting this bound +help: consider further restricting type parameter `F` with trait `MyFn` | LL | F: Callback<Self::CallbackArg> + MyFn<i32>, | +++++++++++ @@ -137,7 +137,7 @@ note: required by a bound in `Callback` | LL | trait Callback<A>: MyFn<A, Output = Self::Ret> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Callback` -help: consider further restricting this bound +help: consider further restricting type parameter `F` with trait `MyFn` | LL | F: Callback<Self::CallbackArg> + MyFn<i32>, | +++++++++++ diff --git a/tests/ui/impl-trait/issue-55872-1.stderr b/tests/ui/impl-trait/issue-55872-1.stderr index 2ccca0b562c..81759760bf1 100644 --- a/tests/ui/impl-trait/issue-55872-1.stderr +++ b/tests/ui/impl-trait/issue-55872-1.stderr @@ -17,7 +17,7 @@ LL | (S::default(), T::default()) | ---------------------------- return type was inferred to be `(S, T)` here | = note: required because it appears within the type `(S, T)` -help: consider further restricting this bound +help: consider further restricting type parameter `S` with trait `Copy` | LL | impl<S: Default + std::marker::Copy> Bar for S { | +++++++++++++++++++ @@ -32,7 +32,7 @@ LL | (S::default(), T::default()) | ---------------------------- return type was inferred to be `(S, T)` here | = note: required because it appears within the type `(S, T)` -help: consider further restricting this bound +help: consider further restricting type parameter `T` with trait `Copy` | LL | fn foo<T: Default + std::marker::Copy>() -> Self::E { | +++++++++++++++++++ diff --git a/tests/ui/impl-trait/normalize-tait-in-const.stderr b/tests/ui/impl-trait/normalize-tait-in-const.stderr index 203fbfc1d2c..1dd84f10ad8 100644 --- a/tests/ui/impl-trait/normalize-tait-in-const.stderr +++ b/tests/ui/impl-trait/normalize-tait-in-const.stderr @@ -33,10 +33,6 @@ LL | fun(filter_positive()); | ^^^^^^^^^^^^^^^^^^^^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: consider further restricting this bound - | -LL | const fn with_positive<F: for<'a> ~const Fn(&'a Alias<'a>) + ~const Destruct + ~const Fn(&foo::Alias<'_>)>(fun: F) { - | ++++++++++++++++++++++++++++ error: aborting due to 4 previous errors diff --git a/tests/ui/invalid-compile-flags/reg-struct-return/requires-x86.aarch64.stderr b/tests/ui/invalid-compile-flags/reg-struct-return/requires-x86.aarch64.stderr new file mode 100644 index 00000000000..9bc85cc7e62 --- /dev/null +++ b/tests/ui/invalid-compile-flags/reg-struct-return/requires-x86.aarch64.stderr @@ -0,0 +1,4 @@ +error: `-Zreg-struct-return` is only supported on x86 + +error: aborting due to 1 previous error + diff --git a/tests/ui/invalid-compile-flags/reg-struct-return/requires-x86.rs b/tests/ui/invalid-compile-flags/reg-struct-return/requires-x86.rs new file mode 100644 index 00000000000..b5e34bece32 --- /dev/null +++ b/tests/ui/invalid-compile-flags/reg-struct-return/requires-x86.rs @@ -0,0 +1,21 @@ +//@ revisions: x86 x86_64 aarch64 + +//@ compile-flags: -Zreg-struct-return + +//@[x86] check-pass +//@[x86] needs-llvm-components: x86 +//@[x86] compile-flags: --target i686-unknown-linux-gnu + +//@[x86_64] check-fail +//@[x86_64] needs-llvm-components: x86 +//@[x86_64] compile-flags: --target x86_64-unknown-linux-gnu +//@[x86_64] error-pattern: `-Zreg-struct-return` is only supported on x86 + +//@[aarch64] check-fail +//@[aarch64] needs-llvm-components: aarch64 +//@[aarch64] compile-flags: --target aarch64-unknown-linux-gnu +//@[aarch64] error-pattern: `-Zreg-struct-return` is only supported on x86 + +#![feature(no_core)] +#![no_core] +#![no_main] diff --git a/tests/ui/invalid-compile-flags/reg-struct-return/requires-x86.x86_64.stderr b/tests/ui/invalid-compile-flags/reg-struct-return/requires-x86.x86_64.stderr new file mode 100644 index 00000000000..9bc85cc7e62 --- /dev/null +++ b/tests/ui/invalid-compile-flags/reg-struct-return/requires-x86.x86_64.stderr @@ -0,0 +1,4 @@ +error: `-Zreg-struct-return` is only supported on x86 + +error: aborting due to 1 previous error + diff --git a/tests/ui/issues/issue-6738.stderr b/tests/ui/issues/issue-6738.stderr index 9c25c0fd9a1..f22d6a2e468 100644 --- a/tests/ui/issues/issue-6738.stderr +++ b/tests/ui/issues/issue-6738.stderr @@ -6,7 +6,7 @@ LL | self.x += v.x; | | | cannot use `+=` on type `T` | -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `AddAssign` | LL | impl<T: std::ops::AddAssign> Foo<T> { | +++++++++++++++++++++ diff --git a/tests/ui/kindck/kindck-impl-type-params.stderr b/tests/ui/kindck/kindck-impl-type-params.stderr index da9a8e5532c..a0a4ef09216 100644 --- a/tests/ui/kindck/kindck-impl-type-params.stderr +++ b/tests/ui/kindck/kindck-impl-type-params.stderr @@ -12,7 +12,7 @@ LL | impl<T: Send + Copy + 'static> Gettable<T> for S<T> {} | | | unsatisfied trait bound introduced here = note: required for the cast from `&S<T>` to `&dyn Gettable<T>` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Send` | LL | fn f<T: std::marker::Send>(val: T) { | +++++++++++++++++++ @@ -31,7 +31,7 @@ LL | impl<T: Send + Copy + 'static> Gettable<T> for S<T> {} | | | unsatisfied trait bound introduced here = note: required for the cast from `&S<T>` to `&dyn Gettable<T>` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | fn f<T: std::marker::Copy>(val: T) { | +++++++++++++++++++ @@ -50,7 +50,7 @@ LL | impl<T: Send + Copy + 'static> Gettable<T> for S<T> {} | | | unsatisfied trait bound introduced here = note: required for the cast from `&S<T>` to `&dyn Gettable<T>` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Send` | LL | fn g<T: std::marker::Send>(val: T) { | +++++++++++++++++++ @@ -69,7 +69,7 @@ LL | impl<T: Send + Copy + 'static> Gettable<T> for S<T> {} | | | unsatisfied trait bound introduced here = note: required for the cast from `&S<T>` to `&dyn Gettable<T>` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | fn g<T: std::marker::Copy>(val: T) { | +++++++++++++++++++ diff --git a/tests/ui/layout/post-mono-layout-cycle-2.rs b/tests/ui/layout/post-mono-layout-cycle-2.rs index e9a5292fbbd..2159dee7463 100644 --- a/tests/ui/layout/post-mono-layout-cycle-2.rs +++ b/tests/ui/layout/post-mono-layout-cycle-2.rs @@ -1,7 +1,7 @@ //@ build-fail //@ edition: 2021 -#![feature(async_closure, noop_waker)] +#![feature(async_closure)] use std::future::Future; use std::pin::pin; diff --git a/tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.stderr b/tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.stderr index 206a6801065..3b051ef9a88 100644 --- a/tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.stderr +++ b/tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.stderr @@ -6,7 +6,7 @@ LL | impl<A, B> FnOnce<A> for CachedFun<A, B> | note: required by a bound in `FnOnce` --> $SRC_DIR/core/src/ops/function.rs:LL:COL -help: consider further restricting this bound +help: consider further restricting type parameter `A` with unstable trait `Tuple` | LL | A: Eq + Hash + Clone + std::marker::Tuple, | ++++++++++++++++++++ @@ -19,7 +19,7 @@ LL | impl<A, B> FnMut<A> for CachedFun<A, B> | note: required by a bound in `FnMut` --> $SRC_DIR/core/src/ops/function.rs:LL:COL -help: consider further restricting this bound +help: consider further restricting type parameter `A` with unstable trait `Tuple` | LL | A: Eq + Hash + Clone + std::marker::Tuple, | ++++++++++++++++++++ @@ -30,7 +30,7 @@ error[E0277]: functions with the "rust-call" ABI must take a single non-self tup LL | extern "rust-call" fn call_once(mut self, a: A) -> Self::Output { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Tuple` is not implemented for `A` | -help: consider further restricting this bound +help: consider further restricting type parameter `A` with unstable trait `Tuple` | LL | A: Eq + Hash + Clone + std::marker::Tuple, | ++++++++++++++++++++ @@ -41,7 +41,7 @@ error[E0277]: functions with the "rust-call" ABI must take a single non-self tup LL | extern "rust-call" fn call_mut(&mut self, a: A) -> Self::Output { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Tuple` is not implemented for `A` | -help: consider further restricting this bound +help: consider further restricting type parameter `A` with unstable trait `Tuple` | LL | A: Eq + Hash + Clone + std::marker::Tuple, | ++++++++++++++++++++ @@ -56,7 +56,7 @@ LL | self.call_mut(a) | note: required by a bound in `call_mut` --> $SRC_DIR/core/src/ops/function.rs:LL:COL -help: consider further restricting this bound +help: consider further restricting type parameter `A` with unstable trait `Tuple` | LL | A: Eq + Hash + Clone + std::marker::Tuple, | ++++++++++++++++++++ diff --git a/tests/ui/lazy-type-alias/unsatisfied-bounds-type-alias-body.stderr b/tests/ui/lazy-type-alias/unsatisfied-bounds-type-alias-body.stderr index bd8095224a7..d0d4d04e28a 100644 --- a/tests/ui/lazy-type-alias/unsatisfied-bounds-type-alias-body.stderr +++ b/tests/ui/lazy-type-alias/unsatisfied-bounds-type-alias-body.stderr @@ -4,7 +4,7 @@ error[E0277]: cannot multiply `T` by `T` LL | type Alias<T> = <T as std::ops::Mul>::Output; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `T * T` | -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Mul` | LL | type Alias<T: std::ops::Mul> = <T as std::ops::Mul>::Output; | +++++++++++++++ diff --git a/tests/ui/methods/filter-relevant-fn-bounds.stderr b/tests/ui/methods/filter-relevant-fn-bounds.stderr index b737c0ab11f..0e00adf6ea6 100644 --- a/tests/ui/methods/filter-relevant-fn-bounds.stderr +++ b/tests/ui/methods/filter-relevant-fn-bounds.stderr @@ -8,7 +8,7 @@ LL | | where LL | | F: for<'a> FnOnce(<F as Output<'a>>::Type), | |___________________________________________________^ the trait `for<'a> Output<'a>` is not implemented for `F` | -help: consider further restricting this bound +help: consider further restricting type parameter `F` with trait `Output` | LL | F: for<'a> FnOnce(<F as Output<'a>>::Type) + for<'a> Output<'a>, | ++++++++++++++++++++ @@ -19,7 +19,7 @@ error[E0277]: the trait bound `for<'a> F: Output<'a>` is not satisfied LL | fn do_something_wrapper<O, F>(self, _: F) | ^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> Output<'a>` is not implemented for `F` | -help: consider further restricting this bound +help: consider further restricting type parameter `F` with trait `Output` | LL | F: for<'a> FnOnce(<F as Output<'a>>::Type) + for<'a> Output<'a>, | ++++++++++++++++++++ @@ -30,7 +30,7 @@ error[E0277]: the trait bound `F: Output<'_>` is not satisfied LL | F: for<'a> FnOnce(<F as Output<'a>>::Type), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Output<'_>` is not implemented for `F` | -help: consider further restricting this bound +help: consider further restricting type parameter `F` with trait `Output` | LL | F: for<'a> FnOnce(<F as Output<'a>>::Type) + Output<'_>, | ++++++++++++ @@ -41,7 +41,7 @@ error[E0277]: the trait bound `F: Output<'_>` is not satisfied LL | F: for<'a> FnOnce(<F as Output<'a>>::Type), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Output<'_>` is not implemented for `F` | -help: consider further restricting this bound +help: consider further restricting type parameter `F` with trait `Output` | LL | F: for<'a> FnOnce(<F as Output<'a>>::Type) + Output<'_>, | ++++++++++++ diff --git a/tests/ui/mir/inline-wrong-abi.rs b/tests/ui/mir/inline-wrong-abi.rs index 8ef0b86a26b..f015463846f 100644 --- a/tests/ui/mir/inline-wrong-abi.rs +++ b/tests/ui/mir/inline-wrong-abi.rs @@ -1,4 +1,4 @@ -//@ compile-flags: -Zpolymorphize=on -Zinline-mir=yes -Zmir-opt-level=0 +//@ compile-flags: -Zinline-mir=yes -Zmir-opt-level=0 -Zvalidate-mir #![feature(fn_traits, unboxed_closures)] struct Foo<T>(T); diff --git a/tests/ui/mir/validate/validate-unsize-cast.stderr b/tests/ui/mir/validate/validate-unsize-cast.stderr index cfb47b34e98..8449c6a24bd 100644 --- a/tests/ui/mir/validate/validate-unsize-cast.stderr +++ b/tests/ui/mir/validate/validate-unsize-cast.stderr @@ -10,7 +10,7 @@ note: required by a bound in `CastTo` | LL | pub trait CastTo<U: ?Sized>: Unsize<U> {} | ^^^^^^^^^ required by this bound in `CastTo` -help: consider further restricting this bound +help: consider further restricting type parameter `T` with unstable trait `Unsize` | LL | impl<T: ?Sized + std::marker::Unsize<U>, U: ?Sized> CastTo<U> for T {} | ++++++++++++++++++++++++ diff --git a/tests/ui/missing-trait-bounds/missing-trait-bound-for-op.stderr b/tests/ui/missing-trait-bounds/missing-trait-bound-for-op.stderr index b3089cecfbb..80b003bbcc5 100644 --- a/tests/ui/missing-trait-bounds/missing-trait-bound-for-op.stderr +++ b/tests/ui/missing-trait-bounds/missing-trait-bound-for-op.stderr @@ -6,7 +6,7 @@ LL | let _ = s == t; | | | &[T] | -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `PartialEq` | LL | pub fn foo<T: std::cmp::PartialEq>(s: &[T], t: &[T]) { | +++++++++++++++++++++ diff --git a/tests/ui/moves/issue-34721.stderr b/tests/ui/moves/issue-34721.stderr index 94780a04c1f..9834d009d22 100644 --- a/tests/ui/moves/issue-34721.stderr +++ b/tests/ui/moves/issue-34721.stderr @@ -18,7 +18,7 @@ note: `Foo::zero` takes ownership of the receiver `self`, which moves `x` | LL | fn zero(self) -> Self; | ^^^^ -help: consider further restricting this bound +help: consider further restricting type parameter `T` with trait `Copy` | LL | pub fn baz<T: Foo + Copy>(x: T) -> T { | ++++++ diff --git a/tests/ui/moves/use_of_moved_value_copy_suggestions.fixed b/tests/ui/moves/use_of_moved_value_copy_suggestions.fixed index bfb855c7fb1..a5e0dd819b4 100644 --- a/tests/ui/moves/use_of_moved_value_copy_suggestions.fixed +++ b/tests/ui/moves/use_of_moved_value_copy_suggestions.fixed @@ -48,7 +48,7 @@ fn duplicate_custom_1<T: Copy + Trait>(t: S<T>) -> (S<T>, S<T>) where { fn duplicate_custom_2<T>(t: S<T>) -> (S<T>, S<T>) where T: A + Copy + Trait, - //~^ HELP consider further restricting this bound + //~^ HELP consider further restricting { (t, t) //~ use of moved value: `t` } @@ -56,14 +56,14 @@ where fn duplicate_custom_3<T>(t: S<T>) -> (S<T>, S<T>) where T: A + Copy + Trait, - //~^ HELP consider further restricting this bound + //~^ HELP consider further restricting T: B, { (t, t) //~ use of moved value: `t` } fn duplicate_custom_4<T: A + Copy + Trait>(t: S<T>) -> (S<T>, S<T>) -//~^ HELP consider further restricting this bound +//~^ HELP consider further restricting where T: B, { diff --git a/tests/ui/moves/use_of_moved_value_copy_suggestions.rs b/tests/ui/moves/use_of_moved_value_copy_suggestions.rs index fbe5a1d74c3..60ca03ed698 100644 --- a/tests/ui/moves/use_of_moved_value_copy_suggestions.rs +++ b/tests/ui/moves/use_of_moved_value_copy_suggestions.rs @@ -48,7 +48,7 @@ fn duplicate_custom_1<T>(t: S<T>) -> (S<T>, S<T>) where { fn duplicate_custom_2<T>(t: S<T>) -> (S<T>, S<T>) where T: A, - //~^ HELP consider further restricting this bound + //~^ HELP consider further restricting { (t, t) //~ use of moved value: `t` } @@ -56,14 +56,14 @@ where fn duplicate_custom_3<T>(t: S<T>) -> (S<T>, S<T>) where T: A, - //~^ HELP consider further restricting this bound + //~^ HELP consider further restricting T: B, { (t, t) //~ use of moved value: `t` } fn duplicate_custom_4<T: A>(t: S<T>) -> (S<T>, S<T>) -//~^ HELP consider further restricting this bound +//~^ HELP consider further restricting where T: B, { diff --git a/tests/ui/moves/use_of_moved_value_copy_suggestions.stderr b/tests/ui/moves/use_of_moved_value_copy_suggestions.stderr index c03204c7b9f..784945dbbae 100644 --- a/tests/ui/moves/use_of_moved_value_copy_suggestions.stderr +++ b/tests/ui/moves/use_of_moved_value_copy_suggestions.stderr @@ -17,7 +17,7 @@ LL | fn duplicate_t<T>(t: T) -> (T, T) { ... LL | (t, t) | - you could clone this value -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | fn duplicate_t<T: Copy>(t: T) -> (T, T) { | ++++++ @@ -33,7 +33,7 @@ LL | (t, t) | | | value moved here | -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | fn duplicate_opt<T: Copy>(t: Option<T>) -> (Option<T>, Option<T>) { | ++++++ @@ -49,7 +49,7 @@ LL | (t, t) | | | value moved here | -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | fn duplicate_tup1<T: Copy>(t: (T,)) -> ((T,), (T,)) { | ++++++ @@ -81,7 +81,7 @@ LL | (t, t) | | | value moved here | -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with traits `Copy` and `Trait` | LL | fn duplicate_custom<T: Copy + Trait>(t: S<T>) -> (S<T>, S<T>) { | ++++++++++++++ @@ -97,7 +97,7 @@ LL | (t, t) | | | value moved here | -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with traits `Copy` and `Trait` | LL | fn duplicate_custom_1<T: Copy + Trait>(t: S<T>) -> (S<T>, S<T>) where { | ++++++++++++++ @@ -113,7 +113,7 @@ LL | (t, t) | | | value moved here | -help: consider further restricting this bound +help: consider further restricting type parameter `T` with traits `Copy` and `Trait` | LL | T: A + Copy + Trait, | ++++++++++++++ @@ -129,7 +129,7 @@ LL | (t, t) | | | value moved here | -help: consider further restricting this bound +help: consider further restricting type parameter `T` with traits `Copy` and `Trait` | LL | T: A + Copy + Trait, | ++++++++++++++ @@ -145,7 +145,7 @@ LL | (t, t) | | | value moved here | -help: consider further restricting this bound +help: consider further restricting type parameter `T` with traits `Copy` and `Trait` | LL | fn duplicate_custom_4<T: A + Copy + Trait>(t: S<T>) -> (S<T>, S<T>) | ++++++++++++++ @@ -169,7 +169,7 @@ LL | fn existing_colon<T:>(t: T) { ... LL | [t, t]; | - you could clone this value -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | fn existing_colon<T: Copy>(t: T) { | ++++ @@ -193,7 +193,7 @@ LL | fn existing_colon_in_where<T>(t: T) ... LL | [t, t]; | - you could clone this value -help: consider further restricting type parameter `T` +help: consider further restricting type parameter `T` with trait `Copy` | LL | T:, T: Copy | ~~~~~~~~~ diff --git a/tests/ui/phantom-auto-trait.stderr b/tests/ui/phantom-auto-trait.stderr index 5af648f6a0c..ffd4c3a0e1a 100644 --- a/tests/ui/phantom-auto-trait.stderr +++ b/tests/ui/phantom-auto-trait.stderr @@ -23,7 +23,7 @@ note: required by a bound in `is_zen` | LL | fn is_zen<T: Zen>(_: T) {} | ^^^ required by this bound in `is_zen` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Sync` | LL | fn not_sync<T: std::marker::Sync>(x: Guard<T>) { | +++++++++++++++++++ @@ -58,7 +58,7 @@ note: required by a bound in `is_zen` | LL | fn is_zen<T: Zen>(_: T) {} | ^^^ required by this bound in `is_zen` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Sync` | LL | fn nested_not_sync<T: std::marker::Sync>(x: Nested<Guard<T>>) { | +++++++++++++++++++ diff --git a/tests/ui/polymorphization/abi_mismatch.rs b/tests/ui/polymorphization/abi_mismatch.rs deleted file mode 100644 index 22c2c162d1c..00000000000 --- a/tests/ui/polymorphization/abi_mismatch.rs +++ /dev/null @@ -1,20 +0,0 @@ -//! This test used to ICE: #123917 -//! The reason was that while the AST knows about two fields -//! named `ptr`, only one exists at the layout level, so accessing -//! `_extra_field` would use an oob index -//@ compile-flags: -Zmir-opt-level=5 -Zpolymorphize=on - -struct NonNull<T>(*mut T); - -struct Token<T> { - ptr: *mut T, - ptr: NonNull<T>, - //~^ ERROR: `ptr` is already declared - _extra_field: (), -} - -fn tokenize<T>(item: *mut T) -> Token<T> { - Token { ptr: NonNull(item), _extra_field: () } -} - -fn main() {} diff --git a/tests/ui/polymorphization/abi_mismatch.stderr b/tests/ui/polymorphization/abi_mismatch.stderr deleted file mode 100644 index e96c737f777..00000000000 --- a/tests/ui/polymorphization/abi_mismatch.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0124]: field `ptr` is already declared - --> $DIR/abi_mismatch.rs:11:5 - | -LL | ptr: *mut T, - | ----------- `ptr` first declared here -LL | ptr: NonNull<T>, - | ^^^^^^^^^^^^^^^ field already declared - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0124`. diff --git a/tests/ui/polymorphization/closure_in_upvar/fn.rs b/tests/ui/polymorphization/closure_in_upvar/fn.rs deleted file mode 100644 index 87f7bc9562b..00000000000 --- a/tests/ui/polymorphization/closure_in_upvar/fn.rs +++ /dev/null @@ -1,29 +0,0 @@ -//@ build-pass -//@ compile-flags:-Zpolymorphize=on -Csymbol-mangling-version=v0 - -fn foo(f: impl Fn()) { - let x = |_: ()| (); - - // Don't use `f` in `y`, but refer to `x` so that the closure substs contain a reference to - // `x` that will differ for each instantiation despite polymorphisation of the varying - // argument. - let y = || x(()); - - // Consider `f` used in `foo`. - f(); - // Use `y` so that it is visited in monomorphisation collection. - y(); -} - -fn entry_a() { - foo(|| ()); -} - -fn entry_b() { - foo(|| ()); -} - -fn main() { - entry_a(); - entry_b(); -} diff --git a/tests/ui/polymorphization/closure_in_upvar/fnmut.rs b/tests/ui/polymorphization/closure_in_upvar/fnmut.rs deleted file mode 100644 index 0f49c0426ee..00000000000 --- a/tests/ui/polymorphization/closure_in_upvar/fnmut.rs +++ /dev/null @@ -1,34 +0,0 @@ -//@ build-pass -//@ compile-flags:-Zpolymorphize=on -Csymbol-mangling-version=v0 - -fn foo(f: impl Fn()) { - // Mutate an upvar from `x` so that it implements `FnMut`. - let mut outer = 3; - let mut x = |_: ()| { - outer = 4; - () - }; - - // Don't use `f` in `y`, but refer to `x` so that the closure substs contain a reference to - // `x` that will differ for each instantiation despite polymorphisation of the varying - // argument. - let mut y = || x(()); - - // Consider `f` used in `foo`. - f(); - // Use `y` so that it is visited in monomorphisation collection. - y(); -} - -fn entry_a() { - foo(|| ()); -} - -fn entry_b() { - foo(|| ()); -} - -fn main() { - entry_a(); - entry_b(); -} diff --git a/tests/ui/polymorphization/closure_in_upvar/fnonce.rs b/tests/ui/polymorphization/closure_in_upvar/fnonce.rs deleted file mode 100644 index 85c7ce2ce27..00000000000 --- a/tests/ui/polymorphization/closure_in_upvar/fnonce.rs +++ /dev/null @@ -1,34 +0,0 @@ -//@ build-pass -//@ compile-flags:-Zpolymorphize=on -Csymbol-mangling-version=v0 - -fn foo(f: impl Fn()) { - // Move a non-copy type into `x` so that it implements `FnOnce`. - let outer = Vec::<u32>::new(); - let x = move |_: ()| { - let inner = outer; - () - }; - - // Don't use `f` in `y`, but refer to `x` so that the closure substs contain a reference to - // `x` that will differ for each instantiation despite polymorphisation of the varying - // argument. - let y = || x(()); - - // Consider `f` used in `foo`. - f(); - // Use `y` so that it is visited in monomorphisation collection. - y(); -} - -fn entry_a() { - foo(|| ()); -} - -fn entry_b() { - foo(|| ()); -} - -fn main() { - entry_a(); - entry_b(); -} diff --git a/tests/ui/polymorphization/closure_in_upvar/other.rs b/tests/ui/polymorphization/closure_in_upvar/other.rs deleted file mode 100644 index b008fc49af4..00000000000 --- a/tests/ui/polymorphization/closure_in_upvar/other.rs +++ /dev/null @@ -1,38 +0,0 @@ -//@ build-pass -//@ compile-flags:-Zpolymorphize=on -Csymbol-mangling-version=v0 - -fn y_uses_f(f: impl Fn()) { - let x = |_: ()| (); - - let y = || { - f(); - x(()); - }; - - f(); - y(); -} - -fn x_uses_f(f: impl Fn()) { - let x = |_: ()| { f(); }; - - let y = || x(()); - - f(); - y(); -} - -fn entry_a() { - x_uses_f(|| ()); - y_uses_f(|| ()); -} - -fn entry_b() { - x_uses_f(|| ()); - y_uses_f(|| ()); -} - -fn main() { - entry_a(); - entry_b(); -} diff --git a/tests/ui/polymorphization/const_parameters/closures.rs b/tests/ui/polymorphization/const_parameters/closures.rs deleted file mode 100644 index 8bdb7381454..00000000000 --- a/tests/ui/polymorphization/const_parameters/closures.rs +++ /dev/null @@ -1,67 +0,0 @@ -//@ build-fail -//@ compile-flags:-Zpolymorphize=on -#![feature(generic_const_exprs, rustc_attrs)] -//~^ WARN the feature `generic_const_exprs` is incomplete - -// This test checks that the polymorphization analysis correctly detects unused const -// parameters in closures. - -// Function doesn't have any generic parameters to be unused. -#[rustc_polymorphize_error] -pub fn no_parameters() { - let _ = || {}; -} - -// Function has an unused generic parameter in parent and closure. -#[rustc_polymorphize_error] -pub fn unused<const T: usize>() -> usize { - //~^ ERROR item has unused generic parameters - let add_one = |x: usize| x + 1; - //~^ ERROR item has unused generic parameters - add_one(3) -} - -// Function has an unused generic parameter in closure, but not in parent. -#[rustc_polymorphize_error] -pub fn used_parent<const T: usize>() -> usize { - let x: usize = T; - let add_one = |x: usize| x + 1; - //~^ ERROR item has unused generic parameters - x + add_one(3) -} - -// Function uses generic parameter in value of a binding in closure. -#[rustc_polymorphize_error] -pub fn used_binding<const T: usize>() -> usize { - let x = || { - let y: usize = T; - y - }; - - x() -} - -// Closure uses a value as an upvar, which used the generic parameter. -#[rustc_polymorphize_error] -pub fn unused_upvar<const T: usize>() -> usize { - let x: usize = T; - let y = || x; - //~^ ERROR item has unused generic parameters - y() -} - -// Closure uses generic parameter in substitutions to another function. -#[rustc_polymorphize_error] -pub fn used_substs<const T: usize>() -> usize { - let x = || unused::<T>(); - x() -} - -fn main() { - no_parameters(); - let _ = unused::<1>(); - let _ = used_parent::<1>(); - let _ = used_binding::<1>(); - let _ = unused_upvar::<1>(); - let _ = used_substs::<1>(); -} diff --git a/tests/ui/polymorphization/const_parameters/closures.stderr b/tests/ui/polymorphization/const_parameters/closures.stderr deleted file mode 100644 index 4e927f7732f..00000000000 --- a/tests/ui/polymorphization/const_parameters/closures.stderr +++ /dev/null @@ -1,44 +0,0 @@ -warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/closures.rs:3:12 - | -LL | #![feature(generic_const_exprs, rustc_attrs)] - | ^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information - = note: `#[warn(incomplete_features)]` on by default - -error: item has unused generic parameters - --> $DIR/closures.rs:19:19 - | -LL | pub fn unused<const T: usize>() -> usize { - | -------------- generic parameter `T` is unused -LL | -LL | let add_one = |x: usize| x + 1; - | ^^^^^^^^^^ - -error: item has unused generic parameters - --> $DIR/closures.rs:17:8 - | -LL | pub fn unused<const T: usize>() -> usize { - | ^^^^^^ -------------- generic parameter `T` is unused - -error: item has unused generic parameters - --> $DIR/closures.rs:28:19 - | -LL | pub fn used_parent<const T: usize>() -> usize { - | -------------- generic parameter `T` is unused -LL | let x: usize = T; -LL | let add_one = |x: usize| x + 1; - | ^^^^^^^^^^ - -error: item has unused generic parameters - --> $DIR/closures.rs:48:13 - | -LL | pub fn unused_upvar<const T: usize>() -> usize { - | -------------- generic parameter `T` is unused -LL | let x: usize = T; -LL | let y = || x; - | ^^ - -error: aborting due to 4 previous errors; 1 warning emitted - diff --git a/tests/ui/polymorphization/const_parameters/functions.rs b/tests/ui/polymorphization/const_parameters/functions.rs deleted file mode 100644 index 6535e3f081d..00000000000 --- a/tests/ui/polymorphization/const_parameters/functions.rs +++ /dev/null @@ -1,37 +0,0 @@ -//@ build-fail -//@ compile-flags:-Zpolymorphize=on -#![feature(generic_const_exprs, rustc_attrs)] -//~^ WARN the feature `generic_const_exprs` is incomplete - -// This test checks that the polymorphization analysis correctly detects unused const -// parameters in functions. - -// Function doesn't have any generic parameters to be unused. -#[rustc_polymorphize_error] -pub fn no_parameters() {} - -// Function has an unused generic parameter. -#[rustc_polymorphize_error] -pub fn unused<const T: usize>() { - //~^ ERROR item has unused generic parameters -} - -// Function uses generic parameter in value of a binding. -#[rustc_polymorphize_error] -pub fn used_binding<const T: usize>() -> usize { - let x: usize = T; - x -} - -// Function uses generic parameter in substitutions to another function. -#[rustc_polymorphize_error] -pub fn used_substs<const T: usize>() { - unused::<T>() -} - -fn main() { - no_parameters(); - unused::<1>(); - used_binding::<1>(); - used_substs::<1>(); -} diff --git a/tests/ui/polymorphization/const_parameters/functions.stderr b/tests/ui/polymorphization/const_parameters/functions.stderr deleted file mode 100644 index a3033d1dcab..00000000000 --- a/tests/ui/polymorphization/const_parameters/functions.stderr +++ /dev/null @@ -1,17 +0,0 @@ -warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/functions.rs:3:12 - | -LL | #![feature(generic_const_exprs, rustc_attrs)] - | ^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information - = note: `#[warn(incomplete_features)]` on by default - -error: item has unused generic parameters - --> $DIR/functions.rs:15:8 - | -LL | pub fn unused<const T: usize>() { - | ^^^^^^ -------------- generic parameter `T` is unused - -error: aborting due to 1 previous error; 1 warning emitted - diff --git a/tests/ui/polymorphization/coroutine.rs b/tests/ui/polymorphization/coroutine.rs deleted file mode 100644 index 22ceadfb194..00000000000 --- a/tests/ui/polymorphization/coroutine.rs +++ /dev/null @@ -1,98 +0,0 @@ -//@ build-fail -//@ compile-flags:-Zpolymorphize=on -Zinline-mir=off -#![feature(generic_const_exprs, coroutines, coroutine_trait, rustc_attrs)] -//~^ WARN the feature `generic_const_exprs` is incomplete - -use std::marker::Unpin; -use std::ops::{Coroutine, CoroutineState}; -use std::pin::Pin; - -enum YieldOrReturn<Y, R> { - Yield(Y), - Return(R), -} - -fn finish<T, Y, R>(mut t: T) -> Vec<YieldOrReturn<Y, R>> -where - T: Coroutine<(), Yield = Y, Return = R> + Unpin, -{ - let mut results = Vec::new(); - loop { - match Pin::new(&mut t).resume(()) { - CoroutineState::Yielded(yielded) => results.push(YieldOrReturn::Yield(yielded)), - CoroutineState::Complete(returned) => { - results.push(YieldOrReturn::Return(returned)); - return results; - } - } - } -} - -// This test checks that the polymorphization analysis functions on coroutines. - -#[rustc_polymorphize_error] -pub fn unused_type<T>() -> impl Coroutine<(), Yield = u32, Return = u32> + Unpin { - #[coroutine] - || { - //~^ ERROR item has unused generic parameters - yield 1; - 2 - } -} - -#[rustc_polymorphize_error] -pub fn used_type_in_yield<Y: Default>() -> impl Coroutine<(), Yield = Y, Return = u32> + Unpin { - #[coroutine] - || { - yield Y::default(); - 2 - } -} - -#[rustc_polymorphize_error] -pub fn used_type_in_return<R: Default>() -> impl Coroutine<(), Yield = u32, Return = R> + Unpin { - #[coroutine] - || { - yield 3; - R::default() - } -} - -#[rustc_polymorphize_error] -pub fn unused_const<const T: u32>() -> impl Coroutine<(), Yield = u32, Return = u32> + Unpin { - #[coroutine] - || { - //~^ ERROR item has unused generic parameters - yield 1; - 2 - } -} - -#[rustc_polymorphize_error] -pub fn used_const_in_yield<const Y: u32>() -> impl Coroutine<(), Yield = u32, Return = u32> + Unpin -{ - #[coroutine] - || { - yield Y; - 2 - } -} - -#[rustc_polymorphize_error] -pub fn used_const_in_return<const R: u32>() -> impl Coroutine<(), Yield = u32, Return = u32> + Unpin -{ - #[coroutine] - || { - yield 4; - R - } -} - -fn main() { - finish(unused_type::<u32>()); - finish(used_type_in_yield::<u32>()); - finish(used_type_in_return::<u32>()); - finish(unused_const::<1u32>()); - finish(used_const_in_yield::<1u32>()); - finish(used_const_in_return::<1u32>()); -} diff --git a/tests/ui/polymorphization/coroutine.stderr b/tests/ui/polymorphization/coroutine.stderr deleted file mode 100644 index 07e29184226..00000000000 --- a/tests/ui/polymorphization/coroutine.stderr +++ /dev/null @@ -1,29 +0,0 @@ -warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/coroutine.rs:3:12 - | -LL | #![feature(generic_const_exprs, coroutines, coroutine_trait, rustc_attrs)] - | ^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information - = note: `#[warn(incomplete_features)]` on by default - -error: item has unused generic parameters - --> $DIR/coroutine.rs:36:5 - | -LL | pub fn unused_type<T>() -> impl Coroutine<(), Yield = u32, Return = u32> + Unpin { - | - generic parameter `T` is unused -LL | #[coroutine] -LL | || { - | ^^ - -error: item has unused generic parameters - --> $DIR/coroutine.rs:64:5 - | -LL | pub fn unused_const<const T: u32>() -> impl Coroutine<(), Yield = u32, Return = u32> + Unpin { - | ------------ generic parameter `T` is unused -LL | #[coroutine] -LL | || { - | ^^ - -error: aborting due to 2 previous errors; 1 warning emitted - diff --git a/tests/ui/polymorphization/drop_shims/simple.rs b/tests/ui/polymorphization/drop_shims/simple.rs deleted file mode 100644 index e51765bf432..00000000000 --- a/tests/ui/polymorphization/drop_shims/simple.rs +++ /dev/null @@ -1,22 +0,0 @@ -//@ check-pass -//@ compile-flags:-Zpolymorphize=on - -pub struct OnDrop<F: Fn()>(pub F); - -impl<F: Fn()> Drop for OnDrop<F> { - fn drop(&mut self) { } -} - -fn foo<R, S: FnOnce()>( - _: R, - _: S, -) { - let bar = || { - let _ = OnDrop(|| ()); - }; - bar(); -} - -fn main() { - foo(3u32, || {}); -} diff --git a/tests/ui/polymorphization/drop_shims/transitive.rs b/tests/ui/polymorphization/drop_shims/transitive.rs deleted file mode 100644 index 331451e1a15..00000000000 --- a/tests/ui/polymorphization/drop_shims/transitive.rs +++ /dev/null @@ -1,27 +0,0 @@ -//@ check-pass -//@ compile-flags:-Zpolymorphize=on - -pub struct OnDrop<F: Fn()>(pub F); - -impl<F: Fn()> Drop for OnDrop<F> { - fn drop(&mut self) { } -} - -fn bar<F: FnOnce()>(f: F) { - let _ = OnDrop(|| ()); - f() -} - -fn foo<R, S: FnOnce()>( - _: R, - _: S, -) { - let bar = || { - bar(|| {}) - }; - bar(); -} - -fn main() { - foo(3u32, || {}); -} diff --git a/tests/ui/polymorphization/ice-poly-with-mir-opts-90192.rs b/tests/ui/polymorphization/ice-poly-with-mir-opts-90192.rs deleted file mode 100644 index 4557c7e517c..00000000000 --- a/tests/ui/polymorphization/ice-poly-with-mir-opts-90192.rs +++ /dev/null @@ -1,20 +0,0 @@ -// issue: rust-lang/rust#90192 -// ICE assertion failed: matches!(ty.kind(), ty :: Param(_)) -//@ compile-flags:-Zpolymorphize=on -Zmir-opt-level=3 -//@ build-pass - -fn test<T>() { - std::mem::size_of::<T>(); -} - -pub fn foo<T>(_: T) -> &'static fn() { - &(test::<T> as fn()) -} - -fn outer<T>() { - foo(|| ()); -} - -fn main() { - outer::<u8>(); -} diff --git a/tests/ui/polymorphization/inline-incorrect-early-bound.rs b/tests/ui/polymorphization/inline-incorrect-early-bound.rs deleted file mode 100644 index e69e4a4faa0..00000000000 --- a/tests/ui/polymorphization/inline-incorrect-early-bound.rs +++ /dev/null @@ -1,27 +0,0 @@ -// This test demonstrates an ICE that may occur when we try to resolve the instance -// of a impl that has different generics than the trait it's implementing. This ensures -// we first check that the args are compatible before resolving the body, just like -// we do in projection before substituting a GAT. -// -// When polymorphization is enabled, we check the optimized MIR for unused parameters. -// This will invoke the inliner, leading to this ICE. - -//@ compile-flags: -Zpolymorphize=on -Zinline-mir=yes - -trait Trait { - fn foo<'a, K: 'a>(self, _: K); -} - -impl Trait for () { - #[inline] - fn foo<K>(self, _: K) { - //~^ ERROR lifetime parameters or bounds on method `foo` do not match the trait declaration - todo!(); - } -} - -pub fn qux<T>() { - ().foo(()); -} - -fn main() {} diff --git a/tests/ui/polymorphization/inline-incorrect-early-bound.stderr b/tests/ui/polymorphization/inline-incorrect-early-bound.stderr deleted file mode 100644 index 3a1d05e8a36..00000000000 --- a/tests/ui/polymorphization/inline-incorrect-early-bound.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0195]: lifetime parameters or bounds on method `foo` do not match the trait declaration - --> $DIR/inline-incorrect-early-bound.rs:17:11 - | -LL | fn foo<'a, K: 'a>(self, _: K); - | ----------- - | | | - | | this bound might be missing in the impl - | lifetimes in impl do not match this method in trait -... -LL | fn foo<K>(self, _: K) { - | ^^^ lifetimes do not match method in trait - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0195`. diff --git a/tests/ui/polymorphization/inline-tainted-body.rs b/tests/ui/polymorphization/inline-tainted-body.rs deleted file mode 100644 index 13aec97e22b..00000000000 --- a/tests/ui/polymorphization/inline-tainted-body.rs +++ /dev/null @@ -1,21 +0,0 @@ -//@ compile-flags: -Zvalidate-mir -Zinline-mir=yes - -#![feature(unboxed_closures)] - -use std::sync::Arc; - -pub struct WeakOnce<T>(); -//~^ ERROR type parameter `T` is never used - -impl<T> WeakOnce<T> { - extern "rust-call" fn try_get(&self) -> Option<Arc<T>> {} - //~^ ERROR functions with the "rust-call" ABI must take a single non-self tuple argument - //~| ERROR mismatched types - - pub fn get(&self) -> Arc<T> { - self.try_get() - .unwrap_or_else(|| panic!("Singleton {} not available", std::any::type_name::<T>())) - } -} - -fn main() {} diff --git a/tests/ui/polymorphization/inline-tainted-body.stderr b/tests/ui/polymorphization/inline-tainted-body.stderr deleted file mode 100644 index 5c3bd70adae..00000000000 --- a/tests/ui/polymorphization/inline-tainted-body.stderr +++ /dev/null @@ -1,30 +0,0 @@ -error[E0392]: type parameter `T` is never used - --> $DIR/inline-tainted-body.rs:7:21 - | -LL | pub struct WeakOnce<T>(); - | ^ unused type parameter - | - = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` - = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead - -error: functions with the "rust-call" ABI must take a single non-self tuple argument - --> $DIR/inline-tainted-body.rs:11:35 - | -LL | extern "rust-call" fn try_get(&self) -> Option<Arc<T>> {} - | ^^^^^ - -error[E0308]: mismatched types - --> $DIR/inline-tainted-body.rs:11:45 - | -LL | extern "rust-call" fn try_get(&self) -> Option<Arc<T>> {} - | ------- ^^^^^^^^^^^^^^ expected `Option<Arc<T>>`, found `()` - | | - | implicitly returns `()` as its body has no tail or `return` expression - | - = note: expected enum `Option<Arc<T>>` - found unit type `()` - -error: aborting due to 3 previous errors - -Some errors have detailed explanations: E0308, E0392. -For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/polymorphization/issue-74614.rs b/tests/ui/polymorphization/issue-74614.rs deleted file mode 100644 index 3ed030b5778..00000000000 --- a/tests/ui/polymorphization/issue-74614.rs +++ /dev/null @@ -1,18 +0,0 @@ -//@ compile-flags:-Zpolymorphize=on -//@ build-pass - -fn test<T>() { - std::mem::size_of::<T>(); -} - -pub fn foo<T>(_: T) -> &'static fn() { - &(test::<T> as fn()) -} - -fn outer<T>() { - foo(|| ()); -} - -fn main() { - outer::<u8>(); -} diff --git a/tests/ui/polymorphization/issue-74636.rs b/tests/ui/polymorphization/issue-74636.rs deleted file mode 100644 index b06b5fdb004..00000000000 --- a/tests/ui/polymorphization/issue-74636.rs +++ /dev/null @@ -1,16 +0,0 @@ -//@ compile-flags:-Zpolymorphize=on -//@ build-pass - -use std::any::TypeId; - -pub fn foo<T: 'static>(_: T) -> TypeId { - TypeId::of::<T>() -} - -fn outer<T: 'static>() { - foo(|| ()); -} - -fn main() { - outer::<u8>(); -} diff --git a/tests/ui/polymorphization/lifetimes.rs b/tests/ui/polymorphization/lifetimes.rs deleted file mode 100644 index 5f8aa13d61d..00000000000 --- a/tests/ui/polymorphization/lifetimes.rs +++ /dev/null @@ -1,25 +0,0 @@ -//@ build-fail -//@ compile-flags:-Zpolymorphize=on -#![feature(rustc_attrs)] - -// This test checks that the polymorphization analysis doesn't break when the -// function/closure doesn't just have generic parameters. - -// Function has an unused generic parameter. -#[rustc_polymorphize_error] -pub fn unused<'a, T>(_: &'a u32) { - //~^ ERROR item has unused generic parameters -} - -#[rustc_polymorphize_error] -pub fn used<'a, T: Default>(_: &'a u32) -> u32 { - let _: T = Default::default(); - let add_one = |x: u32| x + 1; - //~^ ERROR item has unused generic parameters - add_one(3) -} - -fn main() { - unused::<u32>(&3); - used::<u32>(&3); -} diff --git a/tests/ui/polymorphization/lifetimes.stderr b/tests/ui/polymorphization/lifetimes.stderr deleted file mode 100644 index 4773dd4fa2e..00000000000 --- a/tests/ui/polymorphization/lifetimes.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error: item has unused generic parameters - --> $DIR/lifetimes.rs:10:8 - | -LL | pub fn unused<'a, T>(_: &'a u32) { - | ^^^^^^ - generic parameter `T` is unused - -error: item has unused generic parameters - --> $DIR/lifetimes.rs:17:19 - | -LL | pub fn used<'a, T: Default>(_: &'a u32) -> u32 { - | - generic parameter `T` is unused -LL | let _: T = Default::default(); -LL | let add_one = |x: u32| x + 1; - | ^^^^^^^^ - -error: aborting due to 2 previous errors - diff --git a/tests/ui/polymorphization/normalized_sig_types.rs b/tests/ui/polymorphization/normalized_sig_types.rs deleted file mode 100644 index c8a5b3e9295..00000000000 --- a/tests/ui/polymorphization/normalized_sig_types.rs +++ /dev/null @@ -1,26 +0,0 @@ -//@ build-pass -//@ compile-flags:-Zpolymorphize=on - -pub trait ParallelIterator: Sized { - fn drive<C: Consumer<()>>(_: C) { - C::into_folder(); - } -} - -pub trait Consumer<T>: Sized { - type Result; - fn into_folder() -> Self::Result; -} - -impl ParallelIterator for () {} - -impl<F: Fn(), T> Consumer<T> for F { - type Result = (); - fn into_folder() -> Self::Result { - unimplemented!() - } -} - -fn main() { - <()>::drive(|| ()); -} diff --git a/tests/ui/polymorphization/predicates.rs b/tests/ui/polymorphization/predicates.rs deleted file mode 100644 index 1ba68f2698e..00000000000 --- a/tests/ui/polymorphization/predicates.rs +++ /dev/null @@ -1,95 +0,0 @@ -//@ build-fail -//@ compile-flags: -Copt-level=0 -Zpolymorphize=on - -#![feature(rustc_attrs)] - -// This test checks that `T` is considered used in `foo`, because it is used in a predicate for -// `I`, which is used. - -#[rustc_polymorphize_error] -fn bar<I>() { - //~^ ERROR item has unused generic parameters -} - -#[rustc_polymorphize_error] -fn foo<I, T>(_: I) -//~^ ERROR item has unused generic parameters -where - I: Iterator<Item = T>, -{ - bar::<I>() -} - -#[rustc_polymorphize_error] -fn baz<I, T>(_: I) -//~^ ERROR item has unused generic parameters -where - std::iter::Repeat<I>: Iterator<Item = T>, -{ - bar::<I>() -} - -// In addition, check that `I` is considered used in `next::{{closure}}`, because `T` is used and -// `T` is really just `I::Item`. `E` is used due to the fixed-point marking of predicates. - -pub(crate) struct Foo<'a, I, E>(I, &'a E); - -impl<'a, I, T: 'a, E> Iterator for Foo<'a, I, E> -where - I: Iterator<Item = &'a (T, E)>, -{ - type Item = T; - - #[rustc_polymorphize_error] - fn next(&mut self) -> Option<Self::Item> { - self.find(|_| true) - //~^ ERROR item has unused generic parameters - } -} - -// Furthermore, check that `B` is considered used because `C` is used, and that `A` is considered -// used because `B` is now used. - -trait Baz<Z> {} - -impl Baz<u16> for u8 {} -impl Baz<u32> for u16 {} - -#[rustc_polymorphize_error] -fn quux<A, B, C: Default>() -> usize -//~^ ERROR item has unused generic parameters -where - A: Baz<B>, - B: Baz<C>, -{ - std::mem::size_of::<C>() -} - -// Finally, check that `F` is considered used because `G` is used when neither are in the self-ty -// of the predicate. - -trait Foobar<F, G> {} - -impl Foobar<u32, u32> for () {} - -#[rustc_polymorphize_error] -fn foobar<F, G>() -> usize -//~^ ERROR item has unused generic parameters -where - (): Foobar<F, G>, -{ - std::mem::size_of::<G>() -} - -fn main() { - let x = &[2u32]; - foo(x.iter()); - baz(x.iter()); - - let mut a = Foo([(1u32, 1u16)].iter(), &1u16); - let _ = a.next(); - - let _ = quux::<u8, u16, u32>(); - - let _ = foobar::<u32, u32>(); -} diff --git a/tests/ui/polymorphization/predicates.stderr b/tests/ui/polymorphization/predicates.stderr deleted file mode 100644 index a3b2f75b12d..00000000000 --- a/tests/ui/polymorphization/predicates.stderr +++ /dev/null @@ -1,45 +0,0 @@ -error: item has unused generic parameters - --> $DIR/predicates.rs:10:4 - | -LL | fn bar<I>() { - | ^^^ - generic parameter `I` is unused - -error: item has unused generic parameters - --> $DIR/predicates.rs:15:4 - | -LL | fn foo<I, T>(_: I) - | ^^^ - generic parameter `T` is unused - -error: item has unused generic parameters - --> $DIR/predicates.rs:24:4 - | -LL | fn baz<I, T>(_: I) - | ^^^ - generic parameter `T` is unused - -error: item has unused generic parameters - --> $DIR/predicates.rs:45:19 - | -LL | impl<'a, I, T: 'a, E> Iterator for Foo<'a, I, E> - | - - generic parameter `E` is unused - | | - | generic parameter `I` is unused -... -LL | self.find(|_| true) - | ^^^ - -error: item has unused generic parameters - --> $DIR/predicates.rs:59:4 - | -LL | fn quux<A, B, C: Default>() -> usize - | ^^^^ - - generic parameter `B` is unused - | | - | generic parameter `A` is unused - -error: item has unused generic parameters - --> $DIR/predicates.rs:76:4 - | -LL | fn foobar<F, G>() -> usize - | ^^^^^^ - generic parameter `F` is unused - -error: aborting due to 6 previous errors - diff --git a/tests/ui/polymorphization/promoted-function-1.rs b/tests/ui/polymorphization/promoted-function-1.rs deleted file mode 100644 index 8c2ed621249..00000000000 --- a/tests/ui/polymorphization/promoted-function-1.rs +++ /dev/null @@ -1,12 +0,0 @@ -//@ build-fail -//@ compile-flags: -Zpolymorphize=on -#![crate_type = "lib"] -#![feature(rustc_attrs)] - -fn foo<'a>(_: &'a ()) {} - -#[rustc_polymorphize_error] -pub fn test<T>() { - //~^ ERROR item has unused generic parameters - foo(&()); -} diff --git a/tests/ui/polymorphization/promoted-function-1.stderr b/tests/ui/polymorphization/promoted-function-1.stderr deleted file mode 100644 index 8ab0320aafe..00000000000 --- a/tests/ui/polymorphization/promoted-function-1.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: item has unused generic parameters - --> $DIR/promoted-function-1.rs:9:8 - | -LL | pub fn test<T>() { - | ^^^^ - generic parameter `T` is unused - -error: aborting due to 1 previous error - diff --git a/tests/ui/polymorphization/promoted-function-2.rs b/tests/ui/polymorphization/promoted-function-2.rs deleted file mode 100644 index aaae7064f37..00000000000 --- a/tests/ui/polymorphization/promoted-function-2.rs +++ /dev/null @@ -1,16 +0,0 @@ -//@ build-fail -//@ compile-flags:-Zpolymorphize=on -#![crate_type = "lib"] -#![feature(generic_const_exprs, rustc_attrs)] -//~^ WARN the feature `generic_const_exprs` is incomplete - -#[rustc_polymorphize_error] -fn test<T>() { - //~^ ERROR item has unused generic parameters - let x = [0; 3 + 4]; -} - -pub fn caller() { - test::<String>(); - test::<Vec<String>>(); -} diff --git a/tests/ui/polymorphization/promoted-function-2.stderr b/tests/ui/polymorphization/promoted-function-2.stderr deleted file mode 100644 index a5d3bee11d9..00000000000 --- a/tests/ui/polymorphization/promoted-function-2.stderr +++ /dev/null @@ -1,17 +0,0 @@ -warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/promoted-function-2.rs:4:12 - | -LL | #![feature(generic_const_exprs, rustc_attrs)] - | ^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information - = note: `#[warn(incomplete_features)]` on by default - -error: item has unused generic parameters - --> $DIR/promoted-function-2.rs:8:4 - | -LL | fn test<T>() { - | ^^^^ - generic parameter `T` is unused - -error: aborting due to 1 previous error; 1 warning emitted - diff --git a/tests/ui/polymorphization/promoted-function-3.rs b/tests/ui/polymorphization/promoted-function-3.rs deleted file mode 100644 index 2ac06d5a139..00000000000 --- a/tests/ui/polymorphization/promoted-function-3.rs +++ /dev/null @@ -1,14 +0,0 @@ -//@ run-pass -//@ compile-flags: -Zpolymorphize=on -Zmir-opt-level=4 - -fn caller<T, U>() -> &'static usize { - callee::<U>() -} - -fn callee<T>() -> &'static usize { - &std::mem::size_of::<T>() -} - -fn main() { - assert_eq!(caller::<(), ()>(), &0); -} diff --git a/tests/ui/polymorphization/promoted-function.rs b/tests/ui/polymorphization/promoted-function.rs deleted file mode 100644 index 057daf4e757..00000000000 --- a/tests/ui/polymorphization/promoted-function.rs +++ /dev/null @@ -1,15 +0,0 @@ -//@ run-pass -//@ compile-flags:-Zpolymorphize=on - -fn fop<T>() {} - -fn bar<T>() -> &'static fn() { - &(fop::<T> as fn()) -} -pub const FN: &'static fn() = &(fop::<i32> as fn()); - -fn main() { - bar::<u32>(); - bar::<i32>(); - (FN)(); -} diff --git a/tests/ui/polymorphization/symbol-ambiguity.rs b/tests/ui/polymorphization/symbol-ambiguity.rs deleted file mode 100644 index 183837f9961..00000000000 --- a/tests/ui/polymorphization/symbol-ambiguity.rs +++ /dev/null @@ -1,22 +0,0 @@ -//@ build-pass -//@ compile-flags: -Zpolymorphize=on -Csymbol-mangling-version=v0 - -pub(crate) struct Foo<'a, I, E>(I, &'a E); - -impl<'a, I, T: 'a, E> Iterator for Foo<'a, I, E> -where - I: Iterator<Item = &'a (T, E)>, -{ - type Item = T; - - fn next(&mut self) -> Option<Self::Item> { - self.find(|_| true) - } -} - -fn main() { - let mut a = Foo([(1u32, 1u16)].iter(), &1u16); - let mut b = Foo([(1u16, 1u32)].iter(), &1u32); - let _ = a.next(); - let _ = b.next(); -} diff --git a/tests/ui/polymorphization/too-many-generic-params.rs b/tests/ui/polymorphization/too-many-generic-params.rs deleted file mode 100644 index db160c336e0..00000000000 --- a/tests/ui/polymorphization/too-many-generic-params.rs +++ /dev/null @@ -1,85 +0,0 @@ -//@ build-pass -#![feature(rustc_attrs)] - -// This test checks that the analysis doesn't panic when there are >64 generic parameters, but -// instead considers those parameters used. - -#[rustc_polymorphize_error] -fn bar<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, AA, - AB, AC, AD, AE, AF, AG, AH, AI, AJ, AK, AL, AM, AN, AO, AP, AQ, AR, AS, AT, AU, AV, AW, - AX, AY, AZ, BA, BB, BC, BD, BE, BF, BG, BH, BI, BJ, BK, BL, BM>() -{ - let _: Option<A> = None; - let _: Option<B> = None; - let _: Option<C> = None; - let _: Option<D> = None; - let _: Option<E> = None; - let _: Option<F> = None; - let _: Option<G> = None; - let _: Option<H> = None; - let _: Option<I> = None; - let _: Option<J> = None; - let _: Option<K> = None; - let _: Option<L> = None; - let _: Option<M> = None; - let _: Option<N> = None; - let _: Option<O> = None; - let _: Option<P> = None; - let _: Option<Q> = None; - let _: Option<R> = None; - let _: Option<S> = None; - let _: Option<T> = None; - let _: Option<U> = None; - let _: Option<V> = None; - let _: Option<W> = None; - let _: Option<X> = None; - let _: Option<Y> = None; - let _: Option<Z> = None; - let _: Option<AA> = None; - let _: Option<AB> = None; - let _: Option<AC> = None; - let _: Option<AD> = None; - let _: Option<AE> = None; - let _: Option<AF> = None; - let _: Option<AG> = None; - let _: Option<AH> = None; - let _: Option<AI> = None; - let _: Option<AJ> = None; - let _: Option<AK> = None; - let _: Option<AL> = None; - let _: Option<AM> = None; - let _: Option<AN> = None; - let _: Option<AO> = None; - let _: Option<AP> = None; - let _: Option<AQ> = None; - let _: Option<AR> = None; - let _: Option<AS> = None; - let _: Option<AT> = None; - let _: Option<AU> = None; - let _: Option<AV> = None; - let _: Option<AW> = None; - let _: Option<AX> = None; - let _: Option<AY> = None; - let _: Option<AZ> = None; - let _: Option<BA> = None; - let _: Option<BB> = None; - let _: Option<BC> = None; - let _: Option<BD> = None; - let _: Option<BE> = None; - let _: Option<BF> = None; - let _: Option<BG> = None; - let _: Option<BH> = None; - let _: Option<BI> = None; - let _: Option<BJ> = None; - let _: Option<BK> = None; - let _: Option<BL> = None; - let _: Option<BM> = None; -} - -fn main() { - bar::<u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, - u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, - u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, - u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, - u32>(); -} diff --git a/tests/ui/polymorphization/type_parameters/closures.rs b/tests/ui/polymorphization/type_parameters/closures.rs deleted file mode 100644 index 552c5cb8980..00000000000 --- a/tests/ui/polymorphization/type_parameters/closures.rs +++ /dev/null @@ -1,161 +0,0 @@ -//@ build-fail -//@ compile-flags:-Zpolymorphize=on -#![feature(stmt_expr_attributes, rustc_attrs)] - -// This test checks that the polymorphization analysis correctly detects unused type -// parameters in closures. - -// Function doesn't have any generic parameters to be unused. -#[rustc_polymorphize_error] -pub fn no_parameters() { - let _ = || {}; -} - -// Function has an unused generic parameter in parent and closure. -#[rustc_polymorphize_error] -pub fn unused<T>() -> u32 { - //~^ ERROR item has unused generic parameters - - let add_one = |x: u32| x + 1; - //~^ ERROR item has unused generic parameters - add_one(3) -} - -// Function has an unused generic parameter in closure, but not in parent. -#[rustc_polymorphize_error] -pub fn used_parent<T: Default>() -> u32 { - let _: T = Default::default(); - let add_one = |x: u32| x + 1; - //~^ ERROR item has unused generic parameters - add_one(3) -} - -// Function uses generic parameter in value of a binding in closure. -#[rustc_polymorphize_error] -pub fn used_binding_value<T: Default>() -> T { - let x = || { - let y: T = Default::default(); - y - }; - - x() -} - -// Function uses generic parameter in generic of a binding in closure. -#[rustc_polymorphize_error] -pub fn used_binding_generic<T>() -> Option<T> { - let x = || { - let y: Option<T> = None; - y - }; - - x() -} - -// Function and closure uses generic parameter in argument. -#[rustc_polymorphize_error] -pub fn used_argument<T>(t: T) -> u32 { - let x = |_: T| 3; - x(t) -} - -// Closure uses generic parameter in argument. -#[rustc_polymorphize_error] -pub fn used_argument_closure<T: Default>() -> u32 { - let t: T = Default::default(); - - let x = |_: T| 3; - x(t) -} - -// Closure uses generic parameter as upvar. -#[rustc_polymorphize_error] -pub fn used_upvar<T: Default>() -> T { - let x: T = Default::default(); - - let y = || x; - y() -} - -// Closure uses generic parameter in substitutions to another function. -#[rustc_polymorphize_error] -pub fn used_substs<T>() -> u32 { - let x = || unused::<T>(); - x() -} - -struct Foo<F>(F); - -impl<F: Default> Foo<F> { - // Function has an unused generic parameter from impl and fn. - #[rustc_polymorphize_error] - pub fn unused_all<G: Default>() -> u32 { - //~^ ERROR item has unused generic parameters - let add_one = |x: u32| x + 1; - //~^ ERROR item has unused generic parameters - add_one(3) - } - - // Function uses generic parameter from impl and fn in closure. - #[rustc_polymorphize_error] - pub fn used_both<G: Default>() -> u32 { - let add_one = |x: u32| { - let _: F = Default::default(); - let _: G = Default::default(); - x + 1 - }; - - add_one(3) - } - - // Function uses generic parameter from fn in closure. - #[rustc_polymorphize_error] - pub fn used_fn<G: Default>() -> u32 { - //~^ ERROR item has unused generic parameters - let add_one = |x: u32| { - //~^ ERROR item has unused generic parameters - let _: G = Default::default(); - x + 1 - }; - - add_one(3) - } - - // Function uses generic parameter from impl in closure. - #[rustc_polymorphize_error] - pub fn used_impl<G: Default>() -> u32 { - //~^ ERROR item has unused generic parameters - let add_one = |x: u32| { - //~^ ERROR item has unused generic parameters - let _: F = Default::default(); - x + 1 - }; - - add_one(3) - } - - // Closure uses generic parameter in substitutions to another function. - #[rustc_polymorphize_error] - pub fn used_substs() -> u32 { - let x = || unused::<F>(); - x() - } -} - -fn main() { - no_parameters(); - let _ = unused::<u32>(); - let _ = used_parent::<u32>(); - let _ = used_binding_value::<u32>(); - let _ = used_binding_generic::<u32>(); - let _ = used_argument(3u32); - let _ = used_argument_closure::<u32>(); - let _ = used_upvar::<u32>(); - let _ = used_substs::<u32>(); - - let _ = Foo::<u32>::unused_all::<u32>(); - let _ = Foo::<u32>::used_both::<u32>(); - let _ = Foo::<u32>::used_impl::<u32>(); - let _ = Foo::<u32>::used_fn::<u32>(); - let _ = Foo::<u32>::used_substs(); -} diff --git a/tests/ui/polymorphization/type_parameters/closures.stderr b/tests/ui/polymorphization/type_parameters/closures.stderr deleted file mode 100644 index 5c3b46c6041..00000000000 --- a/tests/ui/polymorphization/type_parameters/closures.stderr +++ /dev/null @@ -1,80 +0,0 @@ -error: item has unused generic parameters - --> $DIR/closures.rs:19:19 - | -LL | pub fn unused<T>() -> u32 { - | - generic parameter `T` is unused -... -LL | let add_one = |x: u32| x + 1; - | ^^^^^^^^ - -error: item has unused generic parameters - --> $DIR/closures.rs:16:8 - | -LL | pub fn unused<T>() -> u32 { - | ^^^^^^ - generic parameter `T` is unused - -error: item has unused generic parameters - --> $DIR/closures.rs:28:19 - | -LL | pub fn used_parent<T: Default>() -> u32 { - | - generic parameter `T` is unused -LL | let _: T = Default::default(); -LL | let add_one = |x: u32| x + 1; - | ^^^^^^^^ - -error: item has unused generic parameters - --> $DIR/closures.rs:94:23 - | -LL | impl<F: Default> Foo<F> { - | - generic parameter `F` is unused -... -LL | pub fn unused_all<G: Default>() -> u32 { - | - generic parameter `G` is unused -LL | -LL | let add_one = |x: u32| x + 1; - | ^^^^^^^^ - -error: item has unused generic parameters - --> $DIR/closures.rs:92:12 - | -LL | impl<F: Default> Foo<F> { - | - generic parameter `F` is unused -... -LL | pub fn unused_all<G: Default>() -> u32 { - | ^^^^^^^^^^ - generic parameter `G` is unused - -error: item has unused generic parameters - --> $DIR/closures.rs:115:23 - | -LL | impl<F: Default> Foo<F> { - | - generic parameter `F` is unused -... -LL | let add_one = |x: u32| { - | ^^^^^^^^ - -error: item has unused generic parameters - --> $DIR/closures.rs:113:12 - | -LL | impl<F: Default> Foo<F> { - | - generic parameter `F` is unused -... -LL | pub fn used_fn<G: Default>() -> u32 { - | ^^^^^^^ - -error: item has unused generic parameters - --> $DIR/closures.rs:128:23 - | -LL | pub fn used_impl<G: Default>() -> u32 { - | - generic parameter `G` is unused -LL | -LL | let add_one = |x: u32| { - | ^^^^^^^^ - -error: item has unused generic parameters - --> $DIR/closures.rs:126:12 - | -LL | pub fn used_impl<G: Default>() -> u32 { - | ^^^^^^^^^ - generic parameter `G` is unused - -error: aborting due to 9 previous errors - diff --git a/tests/ui/polymorphization/type_parameters/functions.rs b/tests/ui/polymorphization/type_parameters/functions.rs deleted file mode 100644 index 548993fbca9..00000000000 --- a/tests/ui/polymorphization/type_parameters/functions.rs +++ /dev/null @@ -1,96 +0,0 @@ -//@ build-fail -//@ compile-flags:-Zpolymorphize=on -#![feature(rustc_attrs)] - -// This test checks that the polymorphization analysis correctly detects unused type -// parameters in functions. - -// Function doesn't have any generic parameters to be unused. -#[rustc_polymorphize_error] -pub fn no_parameters() {} - -// Function has an unused generic parameter. -#[rustc_polymorphize_error] -pub fn unused<T>() { - //~^ ERROR item has unused generic parameters -} - -// Function uses generic parameter in value of a binding. -#[rustc_polymorphize_error] -pub fn used_binding_value<T: Default>() { - let _: T = Default::default(); -} - -// Function uses generic parameter in generic of a binding. -#[rustc_polymorphize_error] -pub fn used_binding_generic<T>() { - let _: Option<T> = None; -} - -// Function uses generic parameter in argument. -#[rustc_polymorphize_error] -pub fn used_argument<T>(_: T) {} - -// Function uses generic parameter in substitutions to another function. -#[rustc_polymorphize_error] -pub fn used_substs<T>() { - unused::<T>() -} - -struct Foo<F>(F); - -impl<F: Default> Foo<F> { - // Function has an unused generic parameter from impl. - #[rustc_polymorphize_error] - pub fn unused_impl() { - //~^ ERROR item has unused generic parameters - } - - // Function has an unused generic parameter from impl and fn. - #[rustc_polymorphize_error] - pub fn unused_both<G: Default>() { - //~^ ERROR item has unused generic parameters - } - - // Function uses generic parameter from impl. - #[rustc_polymorphize_error] - pub fn used_impl() { - let _: F = Default::default(); - } - - // Function uses generic parameter from impl. - #[rustc_polymorphize_error] - pub fn used_fn<G: Default>() { - //~^ ERROR item has unused generic parameters - let _: G = Default::default(); - } - - // Function uses generic parameter from impl. - #[rustc_polymorphize_error] - pub fn used_both<G: Default>() { - let _: F = Default::default(); - let _: G = Default::default(); - } - - // Function uses generic parameter in substitutions to another function. - #[rustc_polymorphize_error] - pub fn used_substs() { - unused::<F>() - } -} - -fn main() { - no_parameters(); - unused::<u32>(); - used_binding_value::<u32>(); - used_binding_generic::<u32>(); - used_argument(3u32); - used_substs::<u32>(); - - Foo::<u32>::unused_impl(); - Foo::<u32>::unused_both::<u32>(); - Foo::<u32>::used_impl(); - Foo::<u32>::used_fn::<u32>(); - Foo::<u32>::used_both::<u32>(); - Foo::<u32>::used_substs(); -} diff --git a/tests/ui/polymorphization/type_parameters/functions.stderr b/tests/ui/polymorphization/type_parameters/functions.stderr deleted file mode 100644 index d629ff7bb4d..00000000000 --- a/tests/ui/polymorphization/type_parameters/functions.stderr +++ /dev/null @@ -1,35 +0,0 @@ -error: item has unused generic parameters - --> $DIR/functions.rs:14:8 - | -LL | pub fn unused<T>() { - | ^^^^^^ - generic parameter `T` is unused - -error: item has unused generic parameters - --> $DIR/functions.rs:45:12 - | -LL | impl<F: Default> Foo<F> { - | - generic parameter `F` is unused -... -LL | pub fn unused_impl() { - | ^^^^^^^^^^^ - -error: item has unused generic parameters - --> $DIR/functions.rs:51:12 - | -LL | impl<F: Default> Foo<F> { - | - generic parameter `F` is unused -... -LL | pub fn unused_both<G: Default>() { - | ^^^^^^^^^^^ - generic parameter `G` is unused - -error: item has unused generic parameters - --> $DIR/functions.rs:63:12 - | -LL | impl<F: Default> Foo<F> { - | - generic parameter `F` is unused -... -LL | pub fn used_fn<G: Default>() { - | ^^^^^^^ - -error: aborting due to 4 previous errors - diff --git a/tests/ui/polymorphization/unsized_cast.rs b/tests/ui/polymorphization/unsized_cast.rs deleted file mode 100644 index 749e21f4e5b..00000000000 --- a/tests/ui/polymorphization/unsized_cast.rs +++ /dev/null @@ -1,30 +0,0 @@ -//@ build-fail -//@ compile-flags:-Zpolymorphize=on -#![feature(fn_traits, rustc_attrs, unboxed_closures)] - -// This test checks that the polymorphization analysis considers a closure -// as using all generic parameters if it does an unsizing cast. - -#[rustc_polymorphize_error] -fn foo<T: Default>() { - let _: T = Default::default(); - (|| Box::new(|| {}) as Box<dyn Fn()>)(); - //~^ ERROR item has unused generic parameters - //~^^ ERROR item has unused generic parameters -} - -#[rustc_polymorphize_error] -fn foo2<T: Default>() { - let _: T = Default::default(); - (|| { - //~^ ERROR item has unused generic parameters - let call: extern "rust-call" fn(_, _) = Fn::call; - call(&|| {}, ()); - //~^ ERROR item has unused generic parameters - })(); -} - -fn main() { - foo::<u32>(); - foo2::<u32>(); -} diff --git a/tests/ui/polymorphization/unsized_cast.stderr b/tests/ui/polymorphization/unsized_cast.stderr deleted file mode 100644 index 27f88d28174..00000000000 --- a/tests/ui/polymorphization/unsized_cast.stderr +++ /dev/null @@ -1,38 +0,0 @@ -error: item has unused generic parameters - --> $DIR/unsized_cast.rs:11:18 - | -LL | fn foo<T: Default>() { - | - generic parameter `T` is unused -LL | let _: T = Default::default(); -LL | (|| Box::new(|| {}) as Box<dyn Fn()>)(); - | ^^ - -error: item has unused generic parameters - --> $DIR/unsized_cast.rs:11:6 - | -LL | fn foo<T: Default>() { - | - generic parameter `T` is unused -LL | let _: T = Default::default(); -LL | (|| Box::new(|| {}) as Box<dyn Fn()>)(); - | ^^ - -error: item has unused generic parameters - --> $DIR/unsized_cast.rs:22:15 - | -LL | fn foo2<T: Default>() { - | - generic parameter `T` is unused -... -LL | call(&|| {}, ()); - | ^^ - -error: item has unused generic parameters - --> $DIR/unsized_cast.rs:19:6 - | -LL | fn foo2<T: Default>() { - | - generic parameter `T` is unused -LL | let _: T = Default::default(); -LL | (|| { - | ^^ - -error: aborting due to 4 previous errors - diff --git a/tests/ui/recursion/issue-38591-non-regular-dropck-recursion.rs b/tests/ui/recursion/issue-38591-non-regular-dropck-recursion.rs index 5c6eef46103..7b7b1a9580b 100644 --- a/tests/ui/recursion/issue-38591-non-regular-dropck-recursion.rs +++ b/tests/ui/recursion/issue-38591-non-regular-dropck-recursion.rs @@ -1,5 +1,5 @@ // `S` is infinitely recursing so it's not possible to generate a finite -// drop impl (ignoring polymorphization). +// drop impl. // // Dropck should therefore detect that this is the case and eagerly error. diff --git a/tests/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr b/tests/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr index b17d1e0ab11..87f0f47f240 100644 --- a/tests/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr +++ b/tests/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `for<'z> T: Trait2<'y, 'z>` is not satisfied LL | fn callee<'x, 'y, T>(t: &'x dyn for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'z> Trait2<'y, 'z>` is not implemented for `T` | -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Trait2` | LL | fn callee<'x, 'y, T: for<'z> Trait2<'y, 'z>>(t: &'x dyn for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >) | ++++++++++++++++++++++++ @@ -17,7 +17,7 @@ LL | | LL | | } | |_^ the trait `for<'z> Trait2<'y, 'z>` is not implemented for `T` | -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Trait2` | LL | fn callee<'x, 'y, T: for<'z> Trait2<'y, 'z>>(t: &'x dyn for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >) | ++++++++++++++++++++++++ diff --git a/tests/ui/resolve/issue-55673.stderr b/tests/ui/resolve/issue-55673.stderr index 4069b35a998..7d420126199 100644 --- a/tests/ui/resolve/issue-55673.stderr +++ b/tests/ui/resolve/issue-55673.stderr @@ -15,7 +15,7 @@ error[E0220]: associated type `Baa` not found for `T` LL | T::Baa: std::fmt::Debug, | ^^^ there is a similarly named associated type `Bar` in the trait `Foo` | -help: consider further restricting type parameter `T` +help: consider further restricting type parameter `T` with trait `Foo` | LL | T::Baa: std::fmt::Debug, T: Foo | ~~~~~~~~ diff --git a/tests/ui/sanitizer/cfi/coroutine.rs b/tests/ui/sanitizer/cfi/coroutine.rs index ec7c5888968..3ad896afd00 100644 --- a/tests/ui/sanitizer/cfi/coroutine.rs +++ b/tests/ui/sanitizer/cfi/coroutine.rs @@ -16,7 +16,6 @@ #![feature(coroutines, stmt_expr_attributes)] #![feature(coroutine_trait)] -#![feature(noop_waker)] #![feature(gen_blocks)] #![feature(async_iterator)] diff --git a/tests/ui/specialization/default-generic-associated-type-bound.stderr b/tests/ui/specialization/default-generic-associated-type-bound.stderr index afdbe2eb226..57d67ac526a 100644 --- a/tests/ui/specialization/default-generic-associated-type-bound.stderr +++ b/tests/ui/specialization/default-generic-associated-type-bound.stderr @@ -20,7 +20,7 @@ note: required by a bound in `X::U` | LL | type U<'a>: PartialEq<&'a Self> where Self: 'a; | ^^^^^^^^^^^^^^^^^^^ required by this bound in `X::U` -help: consider further restricting this bound +help: consider further restricting type parameter `T` with trait `PartialEq` | LL | impl<T: 'static + std::cmp::PartialEq> X for T { | +++++++++++++++++++++ diff --git a/tests/ui/specialization/defaultimpl/specialization-wfcheck.stderr b/tests/ui/specialization/defaultimpl/specialization-wfcheck.stderr index 01188e293bd..4a51a7dfa47 100644 --- a/tests/ui/specialization/defaultimpl/specialization-wfcheck.stderr +++ b/tests/ui/specialization/defaultimpl/specialization-wfcheck.stderr @@ -19,7 +19,7 @@ note: required by a bound in `Foo` | LL | trait Foo<'a, T: Eq + 'a> { } | ^^ required by this bound in `Foo` -help: consider restricting type parameter `U` +help: consider restricting type parameter `U` with trait `Eq` | LL | default impl<U: std::cmp::Eq> Foo<'static, U> for () {} | ++++++++++++++ diff --git a/tests/ui/specialization/issue-33017.stderr b/tests/ui/specialization/issue-33017.stderr index 2c20077078f..29a82a4d875 100644 --- a/tests/ui/specialization/issue-33017.stderr +++ b/tests/ui/specialization/issue-33017.stderr @@ -9,7 +9,7 @@ note: required by a bound in `UncheckedCopy::Output` | LL | type Output: From<Self> + Copy + Into<Self>; | ^^^^ required by this bound in `UncheckedCopy::Output` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | impl<T: std::marker::Copy> UncheckedCopy for T { | +++++++++++++++++++ diff --git a/tests/ui/specialization/min_specialization/issue-79224.stderr b/tests/ui/specialization/min_specialization/issue-79224.stderr index 268fc3a9591..84e526f4597 100644 --- a/tests/ui/specialization/min_specialization/issue-79224.stderr +++ b/tests/ui/specialization/min_specialization/issue-79224.stderr @@ -5,7 +5,7 @@ LL | impl<B: ?Sized> Display for Cow<'_, B> { | ^^^^^^^^^^ the trait `Clone` is not implemented for `B` | = note: required for `B` to implement `ToOwned` -help: consider further restricting this bound +help: consider further restricting type parameter `B` with trait `Clone` | LL | impl<B: ?Sized + std::clone::Clone> Display for Cow<'_, B> { | +++++++++++++++++++ @@ -17,7 +17,7 @@ LL | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `B` | = note: required for `B` to implement `ToOwned` -help: consider further restricting this bound +help: consider further restricting type parameter `B` with trait `Clone` | LL | impl<B: ?Sized + std::clone::Clone> Display for Cow<'_, B> { | +++++++++++++++++++ @@ -29,7 +29,7 @@ LL | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ^^^^ the trait `Clone` is not implemented for `B` | = note: required for `B` to implement `ToOwned` -help: consider further restricting this bound +help: consider further restricting type parameter `B` with trait `Clone` | LL | impl<B: ?Sized + std::clone::Clone> Display for Cow<'_, B> { | +++++++++++++++++++ @@ -47,7 +47,7 @@ LL | | } | |_____^ the trait `Clone` is not implemented for `B` | = note: required for `B` to implement `ToOwned` -help: consider further restricting this bound +help: consider further restricting type parameter `B` with trait `Clone` | LL | impl<B: ?Sized + std::clone::Clone> Display for Cow<'_, B> { | +++++++++++++++++++ diff --git a/tests/ui/suggestions/assoc-const-as-fn.stderr b/tests/ui/suggestions/assoc-const-as-fn.stderr index 69e9af72647..6732033e774 100644 --- a/tests/ui/suggestions/assoc-const-as-fn.stderr +++ b/tests/ui/suggestions/assoc-const-as-fn.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `T: GlUniformScalar` is not satisfied LL | <T as GlUniformScalar>::FACTORY(1, value); | ^ the trait `GlUniformScalar` is not implemented for `T` | -help: consider further restricting this bound +help: consider further restricting type parameter `T` with trait `GlUniformScalar` | LL | pub fn foo<T: UniformScalar + GlUniformScalar>(value: T) { | +++++++++++++++++ diff --git a/tests/ui/suggestions/bound-suggestions.stderr b/tests/ui/suggestions/bound-suggestions.stderr index 4965e7439f8..e30deb11398 100644 --- a/tests/ui/suggestions/bound-suggestions.stderr +++ b/tests/ui/suggestions/bound-suggestions.stderr @@ -5,7 +5,7 @@ LL | println!("{:?}", t); | ^ `impl Sized` cannot be formatted using `{:?}` because it doesn't implement `Debug` | = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider further restricting this bound +help: consider restricting opaque type `impl Sized` with trait `Debug` | LL | fn test_impl(t: impl Sized + std::fmt::Debug) { | +++++++++++++++++ @@ -17,7 +17,7 @@ LL | println!("{:?}", t); | ^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` | = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Debug` | LL | fn test_no_bounds<T: std::fmt::Debug>(t: T) { | +++++++++++++++++ @@ -29,7 +29,7 @@ LL | println!("{:?}", t); | ^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` | = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider further restricting this bound +help: consider further restricting type parameter `T` with trait `Debug` | LL | fn test_one_bound<T: Sized + std::fmt::Debug>(t: T) { | +++++++++++++++++ @@ -41,7 +41,7 @@ LL | println!("{:?} {:?}", x, y); | ^ `Y` cannot be formatted using `{:?}` because it doesn't implement `Debug` | = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider further restricting type parameter `Y` +help: consider further restricting type parameter `Y` with trait `Debug` | LL | fn test_no_bounds_where<X, Y>(x: X, y: Y) where X: std::fmt::Debug, Y: std::fmt::Debug { | ~~~~~~~~~~~~~~~~~~~~ @@ -53,7 +53,7 @@ LL | println!("{:?}", x); | ^ `X` cannot be formatted using `{:?}` because it doesn't implement `Debug` | = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider further restricting this bound +help: consider further restricting type parameter `X` with trait `Debug` | LL | fn test_one_bound_where<X>(x: X) where X: Sized + std::fmt::Debug { | +++++++++++++++++ @@ -65,7 +65,7 @@ LL | println!("{:?}", x); | ^ `X` cannot be formatted using `{:?}` because it doesn't implement `Debug` | = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider further restricting this bound +help: consider further restricting type parameter `X` with trait `Debug` | LL | fn test_many_bounds_where<X>(x: X) where X: Sized + std::fmt::Debug, X: Sized { | +++++++++++++++++ diff --git a/tests/ui/suggestions/clone-bounds-121524.rs b/tests/ui/suggestions/clone-bounds-121524.rs index 8cd60b452de..b7760584ebb 100644 --- a/tests/ui/suggestions/clone-bounds-121524.rs +++ b/tests/ui/suggestions/clone-bounds-121524.rs @@ -6,7 +6,7 @@ trait DoesAThing {} impl DoesAThing for ThingThatDoesAThing {} fn clones_impl_ref_inline(thing: &impl DoesAThing) { - //~^ HELP consider further restricting this bound + //~^ HELP consider restricting opaque type `impl DoesAThing` with trait `Clone` drops_impl_owned(thing.clone()); //~ ERROR E0277 //~^ NOTE copies the reference //~| NOTE the trait `DoesAThing` is not implemented for `&impl DoesAThing` diff --git a/tests/ui/suggestions/clone-bounds-121524.stderr b/tests/ui/suggestions/clone-bounds-121524.stderr index 6d60508a4a1..bdba8d7e472 100644 --- a/tests/ui/suggestions/clone-bounds-121524.stderr +++ b/tests/ui/suggestions/clone-bounds-121524.stderr @@ -9,7 +9,7 @@ note: this `clone()` copies the reference, which does not do anything, because ` | LL | drops_impl_owned(thing.clone()); | ^^^^^ -help: consider further restricting this bound +help: consider restricting opaque type `impl DoesAThing` with trait `Clone` | LL | fn clones_impl_ref_inline(thing: &impl DoesAThing + Clone) { | +++++++ diff --git a/tests/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr b/tests/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr index afbb9c32d51..03a14b03781 100644 --- a/tests/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr +++ b/tests/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr @@ -15,7 +15,7 @@ note: `T` does not implement `Clone`, so `&T` was cloned instead | LL | t.clone() | ^ -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Clone` | LL | fn wat<T: Clone>(t: &T) -> T { | +++++++ diff --git a/tests/ui/suggestions/derive-clone-for-eq.stderr b/tests/ui/suggestions/derive-clone-for-eq.stderr index 680890e880c..eae0b0ae817 100644 --- a/tests/ui/suggestions/derive-clone-for-eq.stderr +++ b/tests/ui/suggestions/derive-clone-for-eq.stderr @@ -14,7 +14,7 @@ LL | impl<T: Clone, U> PartialEq<U> for Struct<T> note: required by a bound in `Eq` --> $SRC_DIR/core/src/cmp.rs:LL:COL = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Clone` | LL | pub struct Struct<T: std::clone::Clone>(T); | +++++++++++++++++++ diff --git a/tests/ui/suggestions/derive-macro-missing-bounds.stderr b/tests/ui/suggestions/derive-macro-missing-bounds.stderr index bffcb1af487..37a5f4932ff 100644 --- a/tests/ui/suggestions/derive-macro-missing-bounds.stderr +++ b/tests/ui/suggestions/derive-macro-missing-bounds.stderr @@ -38,7 +38,7 @@ LL | impl<T: Debug + Trait> Debug for Inner<T> { = note: required for `&c::Inner<T>` to implement `Debug` = note: required for the cast from `&&c::Inner<T>` to `&dyn Debug` = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Trait` | LL | struct Outer<T: c::Trait>(Inner<T>); | ++++++++++ @@ -60,7 +60,7 @@ LL | impl<T> Debug for Inner<T> where T: Debug, T: Trait { = note: required for `&d::Inner<T>` to implement `Debug` = note: required for the cast from `&&d::Inner<T>` to `&dyn Debug` = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Trait` | LL | struct Outer<T: d::Trait>(Inner<T>); | ++++++++++ @@ -82,7 +82,7 @@ LL | impl<T> Debug for Inner<T> where T: Debug + Trait { = note: required for `&e::Inner<T>` to implement `Debug` = note: required for the cast from `&&e::Inner<T>` to `&dyn Debug` = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Trait` | LL | struct Outer<T: e::Trait>(Inner<T>); | ++++++++++ @@ -104,7 +104,7 @@ LL | impl<T: Debug> Debug for Inner<T> where T: Trait { = note: required for `&f::Inner<T>` to implement `Debug` = note: required for the cast from `&&f::Inner<T>` to `&dyn Debug` = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Trait` | LL | struct Outer<T: f::Trait>(Inner<T>); | ++++++++++ diff --git a/tests/ui/suggestions/issue-106443-sugg-clone-for-bound.stderr b/tests/ui/suggestions/issue-106443-sugg-clone-for-bound.stderr index 8607917ede6..8b1c0b9a77a 100644 --- a/tests/ui/suggestions/issue-106443-sugg-clone-for-bound.stderr +++ b/tests/ui/suggestions/issue-106443-sugg-clone-for-bound.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `&T: X` is not satisfied LL | foo(s); | ^ the trait `X` is not implemented for `&T` | -help: consider further restricting this bound +help: consider further restricting type parameter `T` with trait `Clone` | LL | fn bar<T: X + Clone>(s: &T) { | +++++++ diff --git a/tests/ui/suggestions/issue-97677.stderr b/tests/ui/suggestions/issue-97677.stderr index 0e95167d851..7fe091ef71c 100644 --- a/tests/ui/suggestions/issue-97677.stderr +++ b/tests/ui/suggestions/issue-97677.stderr @@ -6,7 +6,7 @@ LL | n + 10 | | | N | -help: consider restricting type parameter `N` +help: consider restricting type parameter `N` with trait `Add` | LL | fn add_ten<N: std::ops::Add<i32, Output = N>>(n: N) -> N { | ++++++++++++++++++++++++++++++++ diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr index d65ad109241..4408fe0a0a4 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr @@ -9,7 +9,7 @@ note: required by a bound in `Vector2` | LL | pub struct Vector2<T: Debug + Copy + Clone> { | ^^^^ required by this bound in `Vector2` -help: consider further restricting this bound +help: consider further restricting type parameter `K` with trait `Copy` | LL | pub struct AABB<K: Debug + std::marker::Copy> { | +++++++++++++++++++ @@ -32,7 +32,7 @@ LL | pub struct Vector2<T: Debug + Copy + Clone> { | ---- unsatisfied trait bound introduced in this `derive` macro = note: required for the cast from `&Vector2<K>` to `&dyn Debug` = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider further restricting this bound +help: consider further restricting type parameter `K` with trait `Copy` | LL | pub struct AABB<K: Debug + std::marker::Copy> { | +++++++++++++++++++ @@ -52,7 +52,7 @@ note: required by a bound in `Vector2` LL | pub struct Vector2<T: Debug + Copy + Clone> { | ^^^^ required by this bound in `Vector2` = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider further restricting this bound +help: consider further restricting type parameter `K` with trait `Copy` | LL | pub struct AABB<K: Debug + std::marker::Copy> { | +++++++++++++++++++ @@ -74,7 +74,7 @@ LL | #[derive(Debug, Copy, Clone)] LL | pub struct Vector2<T: Debug + Copy + Clone> { | ---- unsatisfied trait bound introduced in this `derive` macro = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider further restricting this bound +help: consider further restricting type parameter `K` with trait `Copy` | LL | pub struct AABB<K: Debug + std::marker::Copy> { | +++++++++++++++++++ diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr index 2ade0e974e4..1bbf6f66ab2 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr @@ -13,7 +13,7 @@ note: the `Copy` impl for `Vector2<K>` requires that `K: Debug` LL | pub loc: Vector2<K>, | ^^^^^^^^^^ = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider further restricting this bound +help: consider further restricting type parameter `K` with trait `Debug` | LL | pub struct AABB<K: Copy + Debug>{ | +++++++ @@ -29,7 +29,7 @@ note: required by a bound in `Vector2` | LL | pub struct Vector2<T: Debug + Copy + Clone>{ | ^^^^^ required by this bound in `Vector2` -help: consider further restricting this bound +help: consider further restricting type parameter `K` with trait `Debug` | LL | pub struct AABB<K: Copy + std::fmt::Debug>{ | +++++++++++++++++ @@ -44,7 +44,7 @@ LL | pub loc: Vector2<K>, | ^^^^^^^^^^^^^^^^^^^ `K` cannot be formatted using `{:?}` because it doesn't implement `Debug` | = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider further restricting this bound +help: consider further restricting type parameter `K` with trait `Debug` | LL | pub struct AABB<K: Copy + std::fmt::Debug>{ | +++++++++++++++++ @@ -59,7 +59,7 @@ LL | pub size: Vector2<K> | ^^^^^^^^^^^^^^^^^^^^ `K` cannot be formatted using `{:?}` because it doesn't implement `Debug` | = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider further restricting this bound +help: consider further restricting type parameter `K` with trait `Debug` | LL | pub struct AABB<K: Copy + std::fmt::Debug>{ | +++++++++++++++++ diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr index 316c2fa0fc9..8b5cced4c4a 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr @@ -13,7 +13,7 @@ note: the `Copy` impl for `Vector2<K>` requires that `K: Debug` LL | pub loc: Vector2<K>, | ^^^^^^^^^^ = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider restricting type parameter `K` +help: consider restricting type parameter `K` with trait `Debug` | LL | pub struct AABB<K: Debug> { | +++++++ @@ -29,7 +29,7 @@ note: required by a bound in `Vector2` | LL | pub struct Vector2<T: Debug + Copy + Clone> { | ^^^^^ required by this bound in `Vector2` -help: consider restricting type parameter `K` +help: consider restricting type parameter `K` with trait `Debug` | LL | pub struct AABB<K: std::fmt::Debug> { | +++++++++++++++++ @@ -45,7 +45,7 @@ note: required by a bound in `Vector2` | LL | pub struct Vector2<T: Debug + Copy + Clone> { | ^^^^ required by this bound in `Vector2` -help: consider restricting type parameter `K` +help: consider restricting type parameter `K` with trait `Copy` | LL | pub struct AABB<K: std::marker::Copy> { | +++++++++++++++++++ @@ -68,7 +68,7 @@ LL | pub struct Vector2<T: Debug + Copy + Clone> { | ---- unsatisfied trait bound introduced in this `derive` macro = note: required for the cast from `&Vector2<K>` to `&dyn Debug` = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider restricting type parameter `K` +help: consider restricting type parameter `K` with trait `Copy` | LL | pub struct AABB<K: std::marker::Copy> { | +++++++++++++++++++ @@ -83,7 +83,7 @@ LL | pub loc: Vector2<K>, | ^^^^^^^^^^^^^^^^^^^ `K` cannot be formatted using `{:?}` because it doesn't implement `Debug` | = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider restricting type parameter `K` +help: consider restricting type parameter `K` with trait `Debug` | LL | pub struct AABB<K: std::fmt::Debug> { | +++++++++++++++++ @@ -103,7 +103,7 @@ note: required by a bound in `Vector2` LL | pub struct Vector2<T: Debug + Copy + Clone> { | ^^^^ required by this bound in `Vector2` = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider restricting type parameter `K` +help: consider restricting type parameter `K` with trait `Copy` | LL | pub struct AABB<K: std::marker::Copy> { | +++++++++++++++++++ @@ -118,7 +118,7 @@ LL | pub size: Vector2<K>, | ^^^^^^^^^^^^^^^^^^^^ `K` cannot be formatted using `{:?}` because it doesn't implement `Debug` | = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider restricting type parameter `K` +help: consider restricting type parameter `K` with trait `Debug` | LL | pub struct AABB<K: std::fmt::Debug> { | +++++++++++++++++ @@ -140,7 +140,7 @@ LL | #[derive(Debug, Copy, Clone)] LL | pub struct Vector2<T: Debug + Copy + Clone> { | ---- unsatisfied trait bound introduced in this `derive` macro = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider restricting type parameter `K` +help: consider restricting type parameter `K` with trait `Copy` | LL | pub struct AABB<K: std::marker::Copy> { | +++++++++++++++++++ diff --git a/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr b/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr index 23a75154f20..600e5ae63d3 100644 --- a/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr +++ b/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr @@ -12,7 +12,7 @@ note: the `Copy` impl for `OnlyCopyIfDisplay<S>` requires that `S: std::fmt::Dis | LL | struct Wrapper<T>(T); | ^ -help: consider restricting type parameter `S` +help: consider restricting type parameter `S` with trait `Display` | LL | impl<S: std::fmt::Display> Copy for Wrapper<OnlyCopyIfDisplay<S>> {} | +++++++++++++++++++ diff --git a/tests/ui/suggestions/missing-bound-in-manual-copy-impl.stderr b/tests/ui/suggestions/missing-bound-in-manual-copy-impl.stderr index c9f277fb350..b22aa35ef6d 100644 --- a/tests/ui/suggestions/missing-bound-in-manual-copy-impl.stderr +++ b/tests/ui/suggestions/missing-bound-in-manual-copy-impl.stderr @@ -7,7 +7,7 @@ LL | LL | impl<S> Copy for Wrapper<S> {} | ^^^^^^^^^^ | -help: consider restricting type parameter `S` +help: consider restricting type parameter `S` with trait `Copy` | LL | impl<S: Copy> Copy for Wrapper<S> {} | ++++++ diff --git a/tests/ui/suggestions/restrict-type-argument.stderr b/tests/ui/suggestions/restrict-type-argument.stderr index 01c2de79864..4b6da8a9cd9 100644 --- a/tests/ui/suggestions/restrict-type-argument.stderr +++ b/tests/ui/suggestions/restrict-type-argument.stderr @@ -11,7 +11,7 @@ note: required by a bound in `is_send` | LL | fn is_send<T: Send>(val: T) {} | ^^^^ required by this bound in `is_send` -help: consider further restricting this bound +help: consider restricting opaque type `impl Sync` with trait `Send` | LL | fn use_impl_sync(val: impl Sync + std::marker::Send) { | +++++++++++++++++++ @@ -29,7 +29,7 @@ note: required by a bound in `is_send` | LL | fn is_send<T: Send>(val: T) {} | ^^^^ required by this bound in `is_send` -help: consider further restricting this bound +help: consider further restricting type parameter `S` with trait `Send` | LL | fn use_where<S>(val: S) where S: Sync + std::marker::Send { | +++++++++++++++++++ @@ -47,7 +47,7 @@ note: required by a bound in `is_send` | LL | fn is_send<T: Send>(val: T) {} | ^^^^ required by this bound in `is_send` -help: consider further restricting this bound +help: consider further restricting type parameter `S` with trait `Send` | LL | fn use_bound<S: Sync + std::marker::Send>(val: S) { | +++++++++++++++++++ @@ -65,7 +65,7 @@ note: required by a bound in `is_send` | LL | fn is_send<T: Send>(val: T) {} | ^^^^ required by this bound in `is_send` -help: consider further restricting this bound +help: consider further restricting type parameter `S` with trait `Send` | LL | Sync + std::marker::Send | +++++++++++++++++++ @@ -83,7 +83,7 @@ note: required by a bound in `is_send` | LL | fn is_send<T: Send>(val: T) {} | ^^^^ required by this bound in `is_send` -help: consider further restricting this bound +help: consider further restricting type parameter `S` with trait `Send` | LL | fn use_bound_and_where<S: Sync + std::marker::Send>(val: S) where S: std::fmt::Debug { | +++++++++++++++++++ @@ -101,7 +101,7 @@ note: required by a bound in `is_send` | LL | fn is_send<T: Send>(val: T) {} | ^^^^ required by this bound in `is_send` -help: consider restricting type parameter `S` +help: consider restricting type parameter `S` with trait `Send` | LL | fn use_unbound<S: std::marker::Send>(val: S) { | +++++++++++++++++++ diff --git a/tests/ui/suggestions/trait-impl-bound-suggestions.stderr b/tests/ui/suggestions/trait-impl-bound-suggestions.stderr index 6a75cbdf639..346d19f1b77 100644 --- a/tests/ui/suggestions/trait-impl-bound-suggestions.stderr +++ b/tests/ui/suggestions/trait-impl-bound-suggestions.stderr @@ -9,7 +9,7 @@ note: required by a bound in `ConstrainedStruct` | LL | struct ConstrainedStruct<X: Copy> { | ^^^^ required by this bound in `ConstrainedStruct` -help: consider further restricting type parameter `X` +help: consider further restricting type parameter `X` with trait `Copy` | LL | trait InsufficientlyConstrainedGeneric<X=()> where Self: Sized, X: std::marker::Copy { | ++++++++++++++++++++++ @@ -25,7 +25,7 @@ note: required by a bound in `ConstrainedStruct` | LL | struct ConstrainedStruct<X: Copy> { | ^^^^ required by this bound in `ConstrainedStruct` -help: consider further restricting type parameter `X` +help: consider further restricting type parameter `X` with trait `Copy` | LL | trait InsufficientlyConstrainedGenericWithEmptyWhere<X=()> where Self: Sized, X: std::marker::Copy { | ++++++++++++++++++++++ @@ -41,7 +41,7 @@ note: required by a bound in `ConstrainedStruct` | LL | struct ConstrainedStruct<X: Copy> { | ^^^^ required by this bound in `ConstrainedStruct` -help: consider further restricting type parameter `X` +help: consider further restricting type parameter `X` with trait `Copy` | LL | trait InsufficientlyConstrainedGeneric<X=()> where Self: Sized, X: std::marker::Copy { | ++++++++++++++++++++++ @@ -57,7 +57,7 @@ note: required by a bound in `ConstrainedStruct` | LL | struct ConstrainedStruct<X: Copy> { | ^^^^ required by this bound in `ConstrainedStruct` -help: consider further restricting type parameter `X` +help: consider further restricting type parameter `X` with trait `Copy` | LL | trait InsufficientlyConstrainedGenericWithEmptyWhere<X=()> where Self: Sized, X: std::marker::Copy { | ++++++++++++++++++++++ diff --git a/tests/ui/trait-bounds/unstable-trait-suggestion.rs b/tests/ui/trait-bounds/unstable-trait-suggestion.rs new file mode 100644 index 00000000000..ba96b4f3f97 --- /dev/null +++ b/tests/ui/trait-bounds/unstable-trait-suggestion.rs @@ -0,0 +1,19 @@ +#![feature(staged_api)] +#![allow(internal_features)] +#![stable(feature = "unit_test", since = "1.0.0")] + +#[unstable(feature = "step_trait", issue = "42168")] +pub trait Unstable {} + +#[stable(feature = "unit_test", since = "1.0.0")] +fn foo<T: Unstable>(_: T) {} + +#[stable(feature = "unit_test", since = "1.0.0")] +pub fn bar<T>(t: T) { //~ HELP consider restricting type parameter `T` with unstable trait `Unstable` + foo(t) //~ ERROR E0277 +} +#[stable(feature = "unit_test", since = "1.0.0")] +pub fn baz<T>(t: std::ops::Range<T>) { //~ HELP consider restricting type parameter `T` with unstable trait + for _ in t {} //~ ERROR E0277 +} +fn main() {} diff --git a/tests/ui/trait-bounds/unstable-trait-suggestion.stderr b/tests/ui/trait-bounds/unstable-trait-suggestion.stderr new file mode 100644 index 00000000000..dfa47f2ab46 --- /dev/null +++ b/tests/ui/trait-bounds/unstable-trait-suggestion.stderr @@ -0,0 +1,34 @@ +error[E0277]: the trait bound `T: Unstable` is not satisfied + --> $DIR/unstable-trait-suggestion.rs:13:9 + | +LL | foo(t) + | --- ^ the trait `Unstable` is not implemented for `T` + | | + | required by a bound introduced by this call + | +note: required by a bound in `foo` + --> $DIR/unstable-trait-suggestion.rs:9:11 + | +LL | fn foo<T: Unstable>(_: T) {} + | ^^^^^^^^ required by this bound in `foo` +help: consider restricting type parameter `T` with unstable trait `Unstable` + | +LL | pub fn bar<T: Unstable>(t: T) { + | ++++++++++ + +error[E0277]: the trait bound `T: Step` is not satisfied + --> $DIR/unstable-trait-suggestion.rs:17:14 + | +LL | for _ in t {} + | ^ the trait `Step` is not implemented for `T` + | + = note: required for `std::ops::Range<T>` to implement `Iterator` + = note: required for `std::ops::Range<T>` to implement `IntoIterator` +help: consider restricting type parameter `T` with unstable trait `Step` + | +LL | pub fn baz<T: std::iter::Step>(t: std::ops::Range<T>) { + | +++++++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/alias/wf.stderr b/tests/ui/traits/alias/wf.stderr index 3be6e8a49d6..42b0104e865 100644 --- a/tests/ui/traits/alias/wf.stderr +++ b/tests/ui/traits/alias/wf.stderr @@ -9,7 +9,7 @@ note: required by a bound in `A` | LL | trait A<T: Foo> {} | ^^^ required by this bound in `A` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Foo` | LL | trait B<T: Foo> = A<T>; | +++++ diff --git a/tests/ui/traits/bad-method-typaram-kind.stderr b/tests/ui/traits/bad-method-typaram-kind.stderr index 376a83e58a7..3b3d6e5f832 100644 --- a/tests/ui/traits/bad-method-typaram-kind.stderr +++ b/tests/ui/traits/bad-method-typaram-kind.stderr @@ -11,7 +11,7 @@ note: required by a bound in `Bar::bar` | LL | fn bar<T:Send>(&self); | ^^^^ required by this bound in `Bar::bar` -help: consider further restricting this bound +help: consider further restricting type parameter `T` with trait `Send` | LL | fn foo<T:'static + std::marker::Send>() { | +++++++++++++++++++ diff --git a/tests/ui/traits/bound/on-structs-and-enums.stderr b/tests/ui/traits/bound/on-structs-and-enums.stderr index 606f764852f..7d6420c6482 100644 --- a/tests/ui/traits/bound/on-structs-and-enums.stderr +++ b/tests/ui/traits/bound/on-structs-and-enums.stderr @@ -9,7 +9,7 @@ note: required by a bound in `Foo` | LL | struct Foo<T:Trait> { | ^^^^^ required by this bound in `Foo` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Trait` | LL | impl<T: Trait> Foo<T> { | +++++++ @@ -59,7 +59,7 @@ note: required by a bound in `Foo` | LL | struct Foo<T:Trait> { | ^^^^^ required by this bound in `Foo` -help: consider restricting type parameter `U` +help: consider restricting type parameter `U` with trait `Trait` | LL | struct Badness<U: Trait> { | +++++++ @@ -75,7 +75,7 @@ note: required by a bound in `Bar` | LL | enum Bar<T:Trait> { | ^^^^^ required by this bound in `Bar` -help: consider restricting type parameter `V` +help: consider restricting type parameter `V` with trait `Trait` | LL | enum MoreBadness<V: Trait> { | +++++++ diff --git a/tests/ui/traits/const-traits/call-generic-method-chain.stderr b/tests/ui/traits/const-traits/call-generic-method-chain.stderr index 9a53c61d019..21fb19daad4 100644 --- a/tests/ui/traits/const-traits/call-generic-method-chain.stderr +++ b/tests/ui/traits/const-traits/call-generic-method-chain.stderr @@ -42,10 +42,6 @@ LL | *t == *t | ^^^^^^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: consider further restricting this bound - | -LL | const fn equals_self<T: ~const PartialEq + ~const std::cmp::PartialEq>(t: &T) -> bool { - | ++++++++++++++++++++++++++++ error[E0015]: cannot call non-const fn `<S as PartialEq>::eq` in constant functions --> $DIR/call-generic-method-chain.rs:16:15 diff --git a/tests/ui/traits/const-traits/call-generic-method-dup-bound.stderr b/tests/ui/traits/const-traits/call-generic-method-dup-bound.stderr index a168171cfe8..845949a38bf 100644 --- a/tests/ui/traits/const-traits/call-generic-method-dup-bound.stderr +++ b/tests/ui/traits/const-traits/call-generic-method-dup-bound.stderr @@ -42,10 +42,6 @@ LL | *t == *t | ^^^^^^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: consider further restricting this bound - | -LL | const fn equals_self<T: PartialEq + ~const PartialEq + ~const std::cmp::PartialEq>(t: &T) -> bool { - | ++++++++++++++++++++++++++++ error[E0015]: cannot call non-const fn `<S as PartialEq>::eq` in constant functions --> $DIR/call-generic-method-dup-bound.rs:14:15 @@ -62,10 +58,6 @@ LL | *t == *t | ^^^^^^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: consider further restricting this bound - | -LL | const fn equals_self2<T: A + ~const PartialEq + ~const std::cmp::PartialEq>(t: &T) -> bool { - | ++++++++++++++++++++++++++++ error: aborting due to 8 previous errors diff --git a/tests/ui/traits/const-traits/call-generic-method-fail.stderr b/tests/ui/traits/const-traits/call-generic-method-fail.stderr index 07e50a7f7da..6bacb986fef 100644 --- a/tests/ui/traits/const-traits/call-generic-method-fail.stderr +++ b/tests/ui/traits/const-traits/call-generic-method-fail.stderr @@ -5,10 +5,6 @@ LL | *t == *t | ^^^^^^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: consider further restricting this bound - | -LL | pub const fn equals_self<T: PartialEq + ~const std::cmp::PartialEq>(t: &T) -> bool { - | ++++++++++++++++++++++++++++ error: aborting due to 1 previous error diff --git a/tests/ui/traits/const-traits/call-generic-method-pass.stderr b/tests/ui/traits/const-traits/call-generic-method-pass.stderr index af6e6d25dc9..0c0037e36b8 100644 --- a/tests/ui/traits/const-traits/call-generic-method-pass.stderr +++ b/tests/ui/traits/const-traits/call-generic-method-pass.stderr @@ -28,10 +28,6 @@ LL | *t == *t | ^^^^^^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: consider further restricting this bound - | -LL | const fn equals_self<T: ~const PartialEq + ~const std::cmp::PartialEq>(t: &T) -> bool { - | ++++++++++++++++++++++++++++ error[E0015]: cannot call non-const fn `<S as PartialEq>::eq` in constant functions --> $DIR/call-generic-method-pass.rs:16:15 diff --git a/tests/ui/traits/const-traits/const-closure-trait-method-fail.stderr b/tests/ui/traits/const-traits/const-closure-trait-method-fail.stderr index cb4c994bc2f..a76dc3e82af 100644 --- a/tests/ui/traits/const-traits/const-closure-trait-method-fail.stderr +++ b/tests/ui/traits/const-traits/const-closure-trait-method-fail.stderr @@ -19,10 +19,6 @@ LL | x(()) | ^^^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: consider further restricting this bound - | -LL | const fn need_const_closure<T: ~const FnOnce(()) -> i32 + ~const FnOnce(())>(x: T) -> i32 { - | +++++++++++++++++++ error: aborting due to 3 previous errors diff --git a/tests/ui/traits/const-traits/const-closure-trait-method.stderr b/tests/ui/traits/const-traits/const-closure-trait-method.stderr index 43af435ae64..d37ff3d727c 100644 --- a/tests/ui/traits/const-traits/const-closure-trait-method.stderr +++ b/tests/ui/traits/const-traits/const-closure-trait-method.stderr @@ -19,10 +19,6 @@ LL | x(()) | ^^^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: consider further restricting this bound - | -LL | const fn need_const_closure<T: ~const FnOnce(()) -> i32 + ~const FnOnce(())>(x: T) -> i32 { - | +++++++++++++++++++ error: aborting due to 3 previous errors diff --git a/tests/ui/traits/const-traits/const-closures.stderr b/tests/ui/traits/const-traits/const-closures.stderr index 2e9e37ba321..8ceaae16d8e 100644 --- a/tests/ui/traits/const-traits/const-closures.stderr +++ b/tests/ui/traits/const-traits/const-closures.stderr @@ -61,10 +61,6 @@ LL | f() + f() | ^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: consider further restricting this bound - | -LL | const fn answer<F: ~const Fn() -> u8 + ~const Fn()>(f: &F) -> u8 { - | +++++++++++++ error[E0015]: cannot call non-const closure in constant functions --> $DIR/const-closures.rs:24:11 @@ -73,10 +69,6 @@ LL | f() + f() | ^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: consider further restricting this bound - | -LL | const fn answer<F: ~const Fn() -> u8 + ~const Fn()>(f: &F) -> u8 { - | +++++++++++++ error[E0015]: cannot call non-const closure in constant functions --> $DIR/const-closures.rs:12:5 @@ -85,10 +77,6 @@ LL | f() * 7 | ^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: consider further restricting this bound - | -LL | F: ~const FnOnce() -> u8 + ~const Fn(), - | +++++++++++++ error: aborting due to 11 previous errors diff --git a/tests/ui/traits/const-traits/trait-where-clause.stderr b/tests/ui/traits/const-traits/trait-where-clause.stderr index abe24b662a2..3a15cc63f32 100644 --- a/tests/ui/traits/const-traits/trait-where-clause.stderr +++ b/tests/ui/traits/const-traits/trait-where-clause.stderr @@ -33,7 +33,7 @@ note: required by a bound in `Foo::b` | LL | fn b() where Self: ~const Bar; | ^^^^^^^^^^ required by this bound in `Foo::b` -help: consider further restricting this bound +help: consider further restricting type parameter `T` with trait `Bar` | LL | fn test1<T: Foo + Bar>() { | +++++ @@ -49,7 +49,7 @@ note: required by a bound in `Foo::c` | LL | fn c<T: ~const Bar>(); | ^^^^^^^^^^ required by this bound in `Foo::c` -help: consider further restricting this bound +help: consider further restricting type parameter `T` with trait `Bar` | LL | fn test1<T: Foo + Bar>() { | +++++ diff --git a/tests/ui/traits/copy-impl-cannot-normalize.stderr b/tests/ui/traits/copy-impl-cannot-normalize.stderr index 3bdb8b70172..45c26ac9ef4 100644 --- a/tests/ui/traits/copy-impl-cannot-normalize.stderr +++ b/tests/ui/traits/copy-impl-cannot-normalize.stderr @@ -14,7 +14,7 @@ LL | T: TraitFoo, | -------- unsatisfied trait bound introduced here note: required by a bound in `Copy` --> $SRC_DIR/core/src/marker.rs:LL:COL -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `TraitFoo` | LL | impl<T: TraitFoo> Copy for Foo<T> {} | ++++++++++ diff --git a/tests/ui/traits/copy-is-not-modulo-regions.not_static.stderr b/tests/ui/traits/copy-is-not-modulo-regions.not_static.stderr index 56544dd4def..02170a127db 100644 --- a/tests/ui/traits/copy-is-not-modulo-regions.not_static.stderr +++ b/tests/ui/traits/copy-is-not-modulo-regions.not_static.stderr @@ -12,7 +12,7 @@ note: the `Copy` impl for `Foo<'any>` requires that `'any: 'static` | LL | struct Bar<'lt>(Foo<'lt>); | ^^^^^^^^ -help: consider restricting type parameter `'any` +help: consider restricting type parameter `'any` with `'static` | LL | impl<'any: 'static> Copy for Bar<'any> {} | +++++++++ diff --git a/tests/ui/traits/inductive-overflow/two-traits.stderr b/tests/ui/traits/inductive-overflow/two-traits.stderr index 6092c194a87..1816e029f18 100644 --- a/tests/ui/traits/inductive-overflow/two-traits.stderr +++ b/tests/ui/traits/inductive-overflow/two-traits.stderr @@ -9,7 +9,7 @@ note: required by a bound in `Magic::X` | LL | type X: Trait; | ^^^^^ required by this bound in `Magic::X` -help: consider further restricting this bound +help: consider further restricting type parameter `T` with trait `Sync` | LL | impl<T: Magic + std::marker::Sync> Magic for T { | +++++++++++++++++++ diff --git a/tests/ui/traits/inheritance/repeated-supertrait-ambig.stderr b/tests/ui/traits/inheritance/repeated-supertrait-ambig.stderr index 6f7c9fa11d4..fdf0b1722be 100644 --- a/tests/ui/traits/inheritance/repeated-supertrait-ambig.stderr +++ b/tests/ui/traits/inheritance/repeated-supertrait-ambig.stderr @@ -18,7 +18,7 @@ LL | c.same_as(22) | | | required by a bound introduced by this call | -help: consider further restricting this bound +help: consider further restricting type parameter `C` with trait `CompareTo` | LL | fn with_trait<C:CompareToInts + CompareTo<i32>>(c: &C) -> bool { | ++++++++++++++++ @@ -41,7 +41,7 @@ LL | CompareTo::same_as(c, 22) | | | required by a bound introduced by this call | -help: consider further restricting this bound +help: consider further restricting type parameter `C` with trait `CompareTo` | LL | fn with_ufcs2<C:CompareToInts + CompareTo<i32>>(c: &C) -> bool { | ++++++++++++++++ diff --git a/tests/ui/traits/issue-21837.stderr b/tests/ui/traits/issue-21837.stderr index f1989392688..06e79d40c7d 100644 --- a/tests/ui/traits/issue-21837.stderr +++ b/tests/ui/traits/issue-21837.stderr @@ -9,7 +9,7 @@ note: required by a bound in `Foo` | LL | pub struct Foo<T: Bound>(T); | ^^^^^ required by this bound in `Foo` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Bound` | LL | impl<T: Bound> Trait2 for Foo<T> {} | +++++++ diff --git a/tests/ui/traits/issue-43784-supertrait.stderr b/tests/ui/traits/issue-43784-supertrait.stderr index 2bf365745a6..1a6da70d76d 100644 --- a/tests/ui/traits/issue-43784-supertrait.stderr +++ b/tests/ui/traits/issue-43784-supertrait.stderr @@ -14,7 +14,7 @@ note: required by a bound in `Complete` | LL | pub trait Complete: Partial { | ^^^^^^^ required by this bound in `Complete` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | impl<T: std::marker::Copy> Complete for T {} | +++++++++++++++++++ diff --git a/tests/ui/traits/next-solver/diagnostics/projection-trait-ref.stderr b/tests/ui/traits/next-solver/diagnostics/projection-trait-ref.stderr index cd8d8b3ffcd..463e50a2553 100644 --- a/tests/ui/traits/next-solver/diagnostics/projection-trait-ref.stderr +++ b/tests/ui/traits/next-solver/diagnostics/projection-trait-ref.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `T: Trait` is not satisfied LL | let x: <T as Trait>::Assoc = (); | ^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `T` | -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Trait` | LL | fn test_poly<T: Trait>() { | +++++++ diff --git a/tests/ui/traits/next-solver/dyn-incompatibility.stderr b/tests/ui/traits/next-solver/dyn-incompatibility.stderr index a720797efc4..6398fbddca5 100644 --- a/tests/ui/traits/next-solver/dyn-incompatibility.stderr +++ b/tests/ui/traits/next-solver/dyn-incompatibility.stderr @@ -10,7 +10,7 @@ note: required by a bound in `copy` | LL | fn copy<U: Setup + ?Sized>(from: &U::From) -> U::From { | ^^^^^ required by this bound in `copy` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | pub fn copy_any<T: std::marker::Copy>(t: &T) -> T { | +++++++++++++++++++ @@ -38,7 +38,7 @@ LL | copy::<dyn Setup<From=T>>(t) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `dyn Setup<From = T>`, the trait `Copy` is not implemented for `T` | = note: required because it appears within the type `dyn Setup<From = T>` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | pub fn copy_any<T: std::marker::Copy>(t: &T) -> T { | +++++++++++++++++++ diff --git a/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.stderr b/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.stderr index 1f319cc6743..da269bbeae4 100644 --- a/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.stderr +++ b/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.stderr @@ -14,7 +14,7 @@ LL | impl<T: Clone, U> PartialEq<U> for Struct<T> note: required by a bound in `Eq` --> $SRC_DIR/core/src/cmp.rs:LL:COL = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Clone` | LL | pub struct Struct<T: std::clone::Clone>(T); | +++++++++++++++++++ diff --git a/tests/ui/traits/next-solver/issue-118950-root-region.stderr b/tests/ui/traits/next-solver/issue-118950-root-region.stderr index 09162970d33..d2a58e95629 100644 --- a/tests/ui/traits/next-solver/issue-118950-root-region.stderr +++ b/tests/ui/traits/next-solver/issue-118950-root-region.stderr @@ -32,7 +32,7 @@ error[E0277]: the trait bound `T: Overlap<for<'a> fn(Assoc<'a, T>)>` is not sati LL | impl<T> Overlap<for<'a> fn(Assoc<'a, T>)> for T where Missing: Overlap<T> {} | ^ the trait `Overlap<for<'a> fn(Assoc<'a, T>)>` is not implemented for `T` | -help: consider further restricting type parameter `T` +help: consider further restricting type parameter `T` with trait `Overlap` | LL | impl<T> Overlap<for<'a> fn(Assoc<'a, T>)> for T where Missing: Overlap<T>, T: Overlap<for<'a> fn(Assoc<'a, T>)> {} | ++++++++++++++++++++++++++++++++++++++ diff --git a/tests/ui/traits/next-solver/typeck/resolve-expectations.rs b/tests/ui/traits/next-solver/typeck/resolve-expectations.rs new file mode 100644 index 00000000000..d6b3816b9eb --- /dev/null +++ b/tests/ui/traits/next-solver/typeck/resolve-expectations.rs @@ -0,0 +1,26 @@ +//@ check-pass +//@ compile-flags: -Znext-solver + +trait Mirror { + type Assoc; +} +impl<T> Mirror for T { + type Assoc = T; +} + +fn id<T>(t: T) -> T { t } + +trait Foo {} +impl Foo for i32 {} +impl Foo for u32 {} + +fn main() { + // Make sure we resolve expected pointee of addr-of. + id::<<&&dyn Foo as Mirror>::Assoc>(&id(&1)); + + // Make sure we resolve expected element of array. + id::<<[Box<dyn Foo>; 2] as Mirror>::Assoc>([Box::new(1i32), Box::new(1u32)]); + + // Make sure we resolve expected element of tuple. + id::<<(Box<dyn Foo>,) as Mirror>::Assoc>((Box::new(1i32),)); +} diff --git a/tests/ui/traits/next-solver/typeck/structurally-resolve-in-resolve_for_branch.rs b/tests/ui/traits/next-solver/typeck/structurally-resolve-in-resolve_for_branch.rs new file mode 100644 index 00000000000..d406f3949a2 --- /dev/null +++ b/tests/ui/traits/next-solver/typeck/structurally-resolve-in-resolve_for_branch.rs @@ -0,0 +1,8 @@ +//@ compile-flags: -Znext-solver +//@ check-pass + +pub fn repro() -> impl FnMut() { + if true { || () } else { || () } +} + +fn main() {} diff --git a/tests/ui/tuple/builtin-fail.stderr b/tests/ui/tuple/builtin-fail.stderr index e3e29a73fdc..ccbc5ae2b75 100644 --- a/tests/ui/tuple/builtin-fail.stderr +++ b/tests/ui/tuple/builtin-fail.stderr @@ -9,7 +9,7 @@ note: required by a bound in `assert_is_tuple` | LL | fn assert_is_tuple<T: std::marker::Tuple + ?Sized>() {} | ^^^^^^^^^^^^^^^^^^ required by this bound in `assert_is_tuple` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with unstable trait `Tuple` | LL | fn from_param_env<T: std::marker::Tuple>() { | ++++++++++++++++++++ diff --git a/tests/ui/type-alias-impl-trait/bounds-are-checked-2.stderr b/tests/ui/type-alias-impl-trait/bounds-are-checked-2.stderr index 8f887a6ac68..bbb32b2d604 100644 --- a/tests/ui/type-alias-impl-trait/bounds-are-checked-2.stderr +++ b/tests/ui/type-alias-impl-trait/bounds-are-checked-2.stderr @@ -14,7 +14,7 @@ note: this definition site has more where clauses than the opaque type | LL | fn f<T: Clone>(t: T) -> X<T> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Clone` | LL | pub type X<T: std::clone::Clone> = impl Clone; | +++++++++++++++++++ diff --git a/tests/ui/type-alias-impl-trait/bounds-are-checked3.stderr b/tests/ui/type-alias-impl-trait/bounds-are-checked3.stderr index bca88b5fae1..c0f6d678097 100644 --- a/tests/ui/type-alias-impl-trait/bounds-are-checked3.stderr +++ b/tests/ui/type-alias-impl-trait/bounds-are-checked3.stderr @@ -10,7 +10,7 @@ note: required by a bound in `Struct` | LL | struct Struct<V: Display>(Option<V>); | ^^^^^^^ required by this bound in `Struct` -help: consider further restricting this bound +help: consider further restricting type parameter `T` with trait `Display` | LL | type Foo<T: Debug + std::fmt::Display> = (impl Debug, Struct<T>); | +++++++++++++++++++ diff --git a/tests/ui/type-alias-impl-trait/future.stderr b/tests/ui/type-alias-impl-trait/future.stderr index b20073fcdfc..047ad164239 100644 --- a/tests/ui/type-alias-impl-trait/future.stderr +++ b/tests/ui/type-alias-impl-trait/future.stderr @@ -9,7 +9,7 @@ note: required by a bound in `foo` | LL | fn foo<B: Bar>(bar: B) -> FooFuture<B> { | ^^^ required by this bound in `foo` -help: consider restricting type parameter `B` +help: consider restricting type parameter `B` with trait `Bar` | LL | type FooFuture<B: Bar> = impl Future<Output = ()>; | +++++ diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr index af6e6e1e66e..cd6e85764bd 100644 --- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr @@ -14,7 +14,7 @@ note: this definition site has more where clauses than the opaque type | LL | fn two<T: Debug, U>(t: T, _: U) -> Two<T, U> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Debug` | LL | type Two<T: std::fmt::Debug, U> = impl Debug; | +++++++++++++++++ diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr index a847bed93da..bf3c4a0e04f 100644 --- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr @@ -14,7 +14,7 @@ note: this definition site has more where clauses than the opaque type | LL | fn three<T, U: Debug>(_: T, u: U) -> Two<T, U> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: consider restricting type parameter `U` +help: consider restricting type parameter `U` with trait `Debug` | LL | type Two<T, U: std::fmt::Debug> = impl Debug; | +++++++++++++++++ diff --git a/tests/ui/type-alias-impl-trait/generic_underconstrained.stderr b/tests/ui/type-alias-impl-trait/generic_underconstrained.stderr index 88529b370f1..98f99cdbfbd 100644 --- a/tests/ui/type-alias-impl-trait/generic_underconstrained.stderr +++ b/tests/ui/type-alias-impl-trait/generic_underconstrained.stderr @@ -9,7 +9,7 @@ note: required by a bound on the type alias `Underconstrained` | LL | type Underconstrained<T: Trait> = impl Send; | ^^^^^ required by this bound -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Trait` | LL | fn underconstrain<T: Trait>(_: T) -> Underconstrained<T> { | +++++++ @@ -30,7 +30,7 @@ note: required by a bound on the type alias `Underconstrained` | LL | type Underconstrained<T: Trait> = impl Send; | ^^^^^ required by this bound -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Trait` | LL | fn underconstrain<T: Trait>(_: T) -> Underconstrained<T> { | +++++++ diff --git a/tests/ui/type-alias-impl-trait/generic_underconstrained2.stderr b/tests/ui/type-alias-impl-trait/generic_underconstrained2.stderr index b3b9cbca968..5506977a3e7 100644 --- a/tests/ui/type-alias-impl-trait/generic_underconstrained2.stderr +++ b/tests/ui/type-alias-impl-trait/generic_underconstrained2.stderr @@ -9,7 +9,7 @@ note: required by a bound on the type alias `Underconstrained` | LL | type Underconstrained<T: std::fmt::Debug> = impl Send; | ^^^^^^^^^^^^^^^ required by this bound -help: consider restricting type parameter `U` +help: consider restricting type parameter `U` with trait `Debug` | LL | fn underconstrained<U: std::fmt::Debug>(_: U) -> Underconstrained<U> { | +++++++++++++++++ @@ -25,7 +25,7 @@ note: required by a bound on the type alias `Underconstrained2` | LL | type Underconstrained2<T: std::fmt::Debug> = impl Send; | ^^^^^^^^^^^^^^^ required by this bound -help: consider restricting type parameter `V` +help: consider restricting type parameter `V` with trait `Debug` | LL | fn underconstrained2<U, V: std::fmt::Debug>(_: U, _: V) -> Underconstrained2<V> { | +++++++++++++++++ @@ -46,7 +46,7 @@ note: required by a bound on the type alias `Underconstrained` | LL | type Underconstrained<T: std::fmt::Debug> = impl Send; | ^^^^^^^^^^^^^^^ required by this bound -help: consider restricting type parameter `U` +help: consider restricting type parameter `U` with trait `Debug` | LL | fn underconstrained<U: std::fmt::Debug>(_: U) -> Underconstrained<U> { | +++++++++++++++++ @@ -67,7 +67,7 @@ note: required by a bound on the type alias `Underconstrained2` | LL | type Underconstrained2<T: std::fmt::Debug> = impl Send; | ^^^^^^^^^^^^^^^ required by this bound -help: consider restricting type parameter `V` +help: consider restricting type parameter `V` with trait `Debug` | LL | fn underconstrained2<U, V: std::fmt::Debug>(_: U, _: V) -> Underconstrained2<V> { | +++++++++++++++++ diff --git a/tests/ui/type-alias-impl-trait/issue-52843.stderr b/tests/ui/type-alias-impl-trait/issue-52843.stderr index a6bdddbc98c..6673b03525d 100644 --- a/tests/ui/type-alias-impl-trait/issue-52843.stderr +++ b/tests/ui/type-alias-impl-trait/issue-52843.stderr @@ -14,7 +14,7 @@ note: this definition site has more where clauses than the opaque type | LL | fn foo<T: Default>(t: T) -> Foo<T> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Default` | LL | type Foo<T: std::default::Default> = impl Default; | +++++++++++++++++++++++ diff --git a/tests/ui/type-alias-impl-trait/issue-53092.stderr b/tests/ui/type-alias-impl-trait/issue-53092.stderr index f04750866c7..579902aa3ab 100644 --- a/tests/ui/type-alias-impl-trait/issue-53092.stderr +++ b/tests/ui/type-alias-impl-trait/issue-53092.stderr @@ -9,7 +9,7 @@ note: required by a bound in `make_bug` | LL | fn make_bug<T, U: From<T>>() -> Bug<T, U> { | ^^^^^^^ required by this bound in `make_bug` -help: consider restricting type parameter `U` +help: consider restricting type parameter `U` with trait `From` | LL | pub type Bug<T, U: std::convert::From<T>> = impl Fn(T) -> U + Copy; | +++++++++++++++++++++++ diff --git a/tests/ui/type-alias-impl-trait/issue-89686.stderr b/tests/ui/type-alias-impl-trait/issue-89686.stderr index 91d71339a08..6fa7e197c40 100644 --- a/tests/ui/type-alias-impl-trait/issue-89686.stderr +++ b/tests/ui/type-alias-impl-trait/issue-89686.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `T: Trait` is not satisfied LL | async move { self.f().await } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `T` | -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Trait` | LL | type G<'a, T: Trait> = impl Future<Output = ()>; | +++++++ diff --git a/tests/ui/type-alias-impl-trait/issue-90400-1.stderr b/tests/ui/type-alias-impl-trait/issue-90400-1.stderr index bc233a53214..afdccd56a50 100644 --- a/tests/ui/type-alias-impl-trait/issue-90400-1.stderr +++ b/tests/ui/type-alias-impl-trait/issue-90400-1.stderr @@ -9,7 +9,7 @@ note: required by a bound in `<MyFoo as Foo>::foo` | LL | fn foo<B: Bar>(&self, bar: B) -> Self::FooFn<B> { | ^^^ required by this bound in `<MyFoo as Foo>::foo` -help: consider restricting type parameter `B` +help: consider restricting type parameter `B` with trait `Bar` | LL | type FooFn<B: Bar> = impl FnOnce(); | +++++ diff --git a/tests/ui/type-alias-impl-trait/issue-90400-2.stderr b/tests/ui/type-alias-impl-trait/issue-90400-2.stderr index 4a6a62bdf96..d4faa6e9392 100644 --- a/tests/ui/type-alias-impl-trait/issue-90400-2.stderr +++ b/tests/ui/type-alias-impl-trait/issue-90400-2.stderr @@ -21,7 +21,7 @@ note: this definition site has more where clauses than the opaque type | LL | fn foo<B: Bar>(&self, bar: B) -> Self::FooFn<B> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: consider restricting type parameter `B` +help: consider restricting type parameter `B` with trait `Bar` | LL | type FooFn<B: Bar> = impl Baz; | +++++ diff --git a/tests/ui/type-alias-impl-trait/not_well_formed.stderr b/tests/ui/type-alias-impl-trait/not_well_formed.stderr index a2944a1acb9..e2fa9442323 100644 --- a/tests/ui/type-alias-impl-trait/not_well_formed.stderr +++ b/tests/ui/type-alias-impl-trait/not_well_formed.stderr @@ -4,7 +4,7 @@ error[E0220]: associated type `Assoc` not found for `V` LL | type Foo<V> = impl Trait<V::Assoc>; | ^^^^^ there is an associated type `Assoc` in the trait `TraitWithAssoc` | -help: consider restricting type parameter `V` +help: consider restricting type parameter `V` with trait `TraitWithAssoc` | LL | type Foo<V: TraitWithAssoc> = impl Trait<V::Assoc>; | ++++++++++++++++ @@ -16,7 +16,7 @@ LL | type Foo<V> = impl Trait<V::Assoc>; | ^^^^^ there is an associated type `Assoc` in the trait `TraitWithAssoc` | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: consider restricting type parameter `V` +help: consider restricting type parameter `V` with trait `TraitWithAssoc` | LL | type Foo<V: TraitWithAssoc> = impl Trait<V::Assoc>; | ++++++++++++++++ diff --git a/tests/ui/type-alias-impl-trait/underconstrained_generic.stderr b/tests/ui/type-alias-impl-trait/underconstrained_generic.stderr index 48cef847fbb..e50949ed8f3 100644 --- a/tests/ui/type-alias-impl-trait/underconstrained_generic.stderr +++ b/tests/ui/type-alias-impl-trait/underconstrained_generic.stderr @@ -21,7 +21,7 @@ note: this definition site has more where clauses than the opaque type | LL | fn _defining_use<T: Trait>() -> Converter<T> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Trait` | LL | type Converter<T: Trait> = impl ProofForConversion<T>; | +++++++ diff --git a/tests/ui/type-alias-impl-trait/wf-check-fn-def.stderr b/tests/ui/type-alias-impl-trait/wf-check-fn-def.stderr index 47bea7bbe60..9046a8a76b8 100644 --- a/tests/ui/type-alias-impl-trait/wf-check-fn-def.stderr +++ b/tests/ui/type-alias-impl-trait/wf-check-fn-def.stderr @@ -9,7 +9,7 @@ note: required by a bound in `mop` | LL | fn mop<B: Bar>(bar: B) { bar.bar() } | ^^^ required by this bound in `mop` -help: consider restricting type parameter `B` +help: consider restricting type parameter `B` with trait `Bar` | LL | type FooFn<B: Bar> = impl FnOnce(B); | +++++ diff --git a/tests/ui/type-alias-impl-trait/wf_check_closures.stderr b/tests/ui/type-alias-impl-trait/wf_check_closures.stderr index 09a42f73490..4156f0ca96a 100644 --- a/tests/ui/type-alias-impl-trait/wf_check_closures.stderr +++ b/tests/ui/type-alias-impl-trait/wf_check_closures.stderr @@ -9,7 +9,7 @@ note: required by a bound in `foo` | LL | fn foo<B: Bar>(bar: B) -> FooFn<B> { | ^^^ required by this bound in `foo` -help: consider restricting type parameter `B` +help: consider restricting type parameter `B` with trait `Bar` | LL | type FooFn<B: Bar> = impl FnOnce(); | +++++ diff --git a/tests/ui/type-alias/unresolved-assoc-ty-suggest-trait.lazy.stderr b/tests/ui/type-alias/unresolved-assoc-ty-suggest-trait.lazy.stderr index 96179a7b484..885c6ec9d8e 100644 --- a/tests/ui/type-alias/unresolved-assoc-ty-suggest-trait.lazy.stderr +++ b/tests/ui/type-alias/unresolved-assoc-ty-suggest-trait.lazy.stderr @@ -4,7 +4,7 @@ error[E0220]: associated type `Assoc` not found for `T` LL | type AssocOf<T> = T::Assoc; | ^^^^^ there is an associated type `Assoc` in the trait `Trait` | -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Trait` | LL | type AssocOf<T: Trait> = T::Assoc; | +++++++ @@ -15,7 +15,7 @@ error[E0220]: associated type `Assok` not found for `T` LL | type AssokOf<T> = T::Assok; | ^^^^^ there is a similarly named associated type `Assoc` in the trait `Trait` | -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Trait` | LL | type AssokOf<T: Trait> = T::Assok; | +++++++ @@ -30,7 +30,7 @@ error[E0220]: associated type `Proj` not found for `T` LL | type ProjOf<T> = T::Proj; | ^^^^ there is an associated type `Proj` in the trait `Parametrized` | -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Parametrized` | LL | type ProjOf<T: Parametrized</* 'a, T, N */>> = T::Proj; | ++++++++++++++++++++++++++++++ diff --git a/tests/ui/type/type-check-defaults.stderr b/tests/ui/type/type-check-defaults.stderr index 9c482506129..ab3378eaa4a 100644 --- a/tests/ui/type/type-check-defaults.stderr +++ b/tests/ui/type/type-check-defaults.stderr @@ -53,7 +53,7 @@ note: required by a bound in `Super` | LL | trait Super<T: Copy> { } | ^^^^ required by this bound in `Super` -help: consider further restricting type parameter `T` +help: consider further restricting type parameter `T` with trait `Copy` | LL | trait Base<T = String>: Super<T> where T: std::marker::Copy { } | ++++++++++++++++++++++++++ diff --git a/tests/ui/type/type-check/missing_trait_impl.stderr b/tests/ui/type/type-check/missing_trait_impl.stderr index 2b58cd4180b..033b42e6736 100644 --- a/tests/ui/type/type-check/missing_trait_impl.stderr +++ b/tests/ui/type/type-check/missing_trait_impl.stderr @@ -6,7 +6,7 @@ LL | let z = x + y; | | | T | -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Add` | LL | fn foo<T: std::ops::Add>(x: T, y: T) { | +++++++++++++++ @@ -19,7 +19,7 @@ LL | x += x; | | | cannot use `+=` on type `T` | -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `AddAssign` | LL | fn bar<T: std::ops::AddAssign>(x: T) { | +++++++++++++++++++++ @@ -30,7 +30,7 @@ error[E0600]: cannot apply unary operator `-` to type `T` LL | let y = -x; | ^^ cannot apply unary operator `-` | -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Neg` | LL | fn baz<T: std::ops::Neg>(x: T) { | +++++++++++++++ @@ -41,7 +41,7 @@ error[E0600]: cannot apply unary operator `!` to type `T` LL | let y = !x; | ^^ cannot apply unary operator `!` | -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Not` | LL | fn baz<T: std::ops::Not>(x: T) { | +++++++++++++++ diff --git a/tests/ui/typeck/bad-index-due-to-nested.stderr b/tests/ui/typeck/bad-index-due-to-nested.stderr index bd7fd0392c3..dd2ce092368 100644 --- a/tests/ui/typeck/bad-index-due-to-nested.stderr +++ b/tests/ui/typeck/bad-index-due-to-nested.stderr @@ -12,7 +12,7 @@ LL | impl<K, V> Index<&K> for HashMap<K, V> LL | where LL | K: Hash, | ---- unsatisfied trait bound introduced here -help: consider restricting type parameter `K` +help: consider restricting type parameter `K` with trait `Hash` | LL | fn index<'a, K: std::hash::Hash, V>(map: &'a HashMap<K, V>, k: K) -> &'a V { | +++++++++++++++++ @@ -31,7 +31,7 @@ LL | impl<K, V> Index<&K> for HashMap<K, V> ... LL | V: Copy, | ---- unsatisfied trait bound introduced here -help: consider restricting type parameter `V` +help: consider restricting type parameter `V` with trait `Copy` | LL | fn index<'a, K, V: std::marker::Copy>(map: &'a HashMap<K, V>, k: K) -> &'a V { | +++++++++++++++++++ diff --git a/tests/ui/typeck/issue-90164.stderr b/tests/ui/typeck/issue-90164.stderr index 43e96e1adc6..1be9c1a0b6e 100644 --- a/tests/ui/typeck/issue-90164.stderr +++ b/tests/ui/typeck/issue-90164.stderr @@ -13,7 +13,7 @@ note: required by a bound in `copy` | LL | fn copy<R: Unpin, W>(_: R, _: W) {} | ^^^^^ required by this bound in `copy` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Unpin` | LL | fn f<T: std::marker::Unpin>(r: T) { | ++++++++++++++++++++ diff --git a/tests/ui/typeck/typeck-default-trait-impl-send-param.stderr b/tests/ui/typeck/typeck-default-trait-impl-send-param.stderr index 537ae6b2b5f..d72c56ac712 100644 --- a/tests/ui/typeck/typeck-default-trait-impl-send-param.stderr +++ b/tests/ui/typeck/typeck-default-trait-impl-send-param.stderr @@ -9,7 +9,7 @@ note: required by a bound in `is_send` | LL | fn is_send<T:Send>() { | ^^^^ required by this bound in `is_send` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Send` | LL | fn foo<T: std::marker::Send>() { | +++++++++++++++++++ diff --git a/tests/ui/union/issue-81199.stderr b/tests/ui/union/issue-81199.stderr index 0dd894beb2a..8b78ddcf4a5 100644 --- a/tests/ui/union/issue-81199.stderr +++ b/tests/ui/union/issue-81199.stderr @@ -9,7 +9,7 @@ note: required by a bound in `PtrComponents` | LL | struct PtrComponents<T: Pointee + ?Sized> { | ^^^^^^^ required by this bound in `PtrComponents` -help: consider further restricting this bound +help: consider further restricting type parameter `T` with trait `Pointee` | LL | union PtrRepr<T: ?Sized + Pointee> { | +++++++++ diff --git a/tests/ui/unop/unop-move-semantics.stderr b/tests/ui/unop/unop-move-semantics.stderr index 0ae918d434a..5b81feaa578 100644 --- a/tests/ui/unop/unop-move-semantics.stderr +++ b/tests/ui/unop/unop-move-semantics.stderr @@ -15,7 +15,7 @@ help: consider cloning the value if the performance cost is acceptable | LL | !x.clone(); | ++++++++ -help: consider further restricting this bound +help: consider further restricting type parameter `T` with trait `Copy` | LL | fn move_then_borrow<T: Not<Output=T> + Clone + Copy>(x: T) { | ++++++ diff --git a/tests/ui/unsafe-fields/auto-traits.current.stderr b/tests/ui/unsafe-fields/auto-traits.current.stderr new file mode 100644 index 00000000000..53a97458b7c --- /dev/null +++ b/tests/ui/unsafe-fields/auto-traits.current.stderr @@ -0,0 +1,17 @@ +error[E0277]: the trait bound `UnsafeEnum: UnsafeAuto` is not satisfied + --> $DIR/auto-traits.rs:24:22 + | +LL | impl_unsafe_auto(UnsafeEnum::Safe(42)); + | ---------------- ^^^^^^^^^^^^^^^^^^^^ the trait `UnsafeAuto` is not implemented for `UnsafeEnum` + | | + | required by a bound introduced by this call + | +note: required by a bound in `impl_unsafe_auto` + --> $DIR/auto-traits.rs:20:29 + | +LL | fn impl_unsafe_auto(_: impl UnsafeAuto) {} + | ^^^^^^^^^^ required by this bound in `impl_unsafe_auto` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unsafe-fields/auto-traits.next.stderr b/tests/ui/unsafe-fields/auto-traits.next.stderr new file mode 100644 index 00000000000..53a97458b7c --- /dev/null +++ b/tests/ui/unsafe-fields/auto-traits.next.stderr @@ -0,0 +1,17 @@ +error[E0277]: the trait bound `UnsafeEnum: UnsafeAuto` is not satisfied + --> $DIR/auto-traits.rs:24:22 + | +LL | impl_unsafe_auto(UnsafeEnum::Safe(42)); + | ---------------- ^^^^^^^^^^^^^^^^^^^^ the trait `UnsafeAuto` is not implemented for `UnsafeEnum` + | | + | required by a bound introduced by this call + | +note: required by a bound in `impl_unsafe_auto` + --> $DIR/auto-traits.rs:20:29 + | +LL | fn impl_unsafe_auto(_: impl UnsafeAuto) {} + | ^^^^^^^^^^ required by this bound in `impl_unsafe_auto` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unsafe-fields/auto-traits.rs b/tests/ui/unsafe-fields/auto-traits.rs new file mode 100644 index 00000000000..e15d0000079 --- /dev/null +++ b/tests/ui/unsafe-fields/auto-traits.rs @@ -0,0 +1,26 @@ +//@ compile-flags: --crate-type=lib +//@ revisions: current next +//@[next] compile-flags: -Znext-solver + +#![feature(auto_traits)] +#![feature(unsafe_fields)] +#![allow(incomplete_features)] + +enum UnsafeEnum { + Safe(u8), + Unsafe { unsafe field: u8 }, +} + +auto trait SafeAuto {} + +fn impl_safe_auto(_: impl SafeAuto) {} + +unsafe auto trait UnsafeAuto {} + +fn impl_unsafe_auto(_: impl UnsafeAuto) {} + +fn tests() { + impl_safe_auto(UnsafeEnum::Safe(42)); + impl_unsafe_auto(UnsafeEnum::Safe(42)); + //~^ ERROR the trait bound `UnsafeEnum: UnsafeAuto` is not satisfied +} diff --git a/tests/ui/auxiliary/unsafe-fields-crate-dep.rs b/tests/ui/unsafe-fields/auxiliary/unsafe-fields-crate-dep.rs index 95b928402a9..95b928402a9 100644 --- a/tests/ui/auxiliary/unsafe-fields-crate-dep.rs +++ b/tests/ui/unsafe-fields/auxiliary/unsafe-fields-crate-dep.rs diff --git a/tests/ui/unsafe-fields-crate.rs b/tests/ui/unsafe-fields/unsafe-fields-crate.rs index cfb9ad6b544..cfb9ad6b544 100644 --- a/tests/ui/unsafe-fields-crate.rs +++ b/tests/ui/unsafe-fields/unsafe-fields-crate.rs diff --git a/tests/ui/unsafe-fields-crate.stderr b/tests/ui/unsafe-fields/unsafe-fields-crate.stderr index 778c26e0a43..778c26e0a43 100644 --- a/tests/ui/unsafe-fields-crate.stderr +++ b/tests/ui/unsafe-fields/unsafe-fields-crate.stderr diff --git a/tests/ui/unsafe-fields-parse.rs b/tests/ui/unsafe-fields/unsafe-fields-parse.rs index 67277731293..67277731293 100644 --- a/tests/ui/unsafe-fields-parse.rs +++ b/tests/ui/unsafe-fields/unsafe-fields-parse.rs diff --git a/tests/ui/unsafe-fields-parse.stderr b/tests/ui/unsafe-fields/unsafe-fields-parse.stderr index 5a45ab03ffe..5a45ab03ffe 100644 --- a/tests/ui/unsafe-fields-parse.stderr +++ b/tests/ui/unsafe-fields/unsafe-fields-parse.stderr diff --git a/tests/ui/unsafe-fields.rs b/tests/ui/unsafe-fields/unsafe-fields.rs index 637471582d7..637471582d7 100644 --- a/tests/ui/unsafe-fields.rs +++ b/tests/ui/unsafe-fields/unsafe-fields.rs diff --git a/tests/ui/unsafe-fields.stderr b/tests/ui/unsafe-fields/unsafe-fields.stderr index a1c5d2b44cd..a1c5d2b44cd 100644 --- a/tests/ui/unsafe-fields.stderr +++ b/tests/ui/unsafe-fields/unsafe-fields.stderr diff --git a/tests/ui/unsized/issue-115809.rs b/tests/ui/unsized/issue-115809.rs index 1b1d5234c12..d06b26061f8 100644 --- a/tests/ui/unsized/issue-115809.rs +++ b/tests/ui/unsized/issue-115809.rs @@ -1,4 +1,4 @@ -//@ compile-flags: --emit=link -Zmir-opt-level=2 -Zpolymorphize=on +//@ compile-flags: --emit=link -Zmir-opt-level=2 -Zvalidate-mir fn foo<T>() { let a: [i32; 0] = []; diff --git a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.rs b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.rs index a953f1818c5..997bee1e600 100644 --- a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.rs +++ b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.rs @@ -3,15 +3,11 @@ trait Foo<const N: Bar<2>> { //~^ WARN trait objects without an explicit `dyn` are deprecated //~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! //~| ERROR cycle detected when computing type of `Foo::N` - //~| ERROR the trait `Foo` cannot be made into an object - //~| ERROR `(dyn Bar<2> + 'static)` is forbidden as the type of a const generic parameter fn func() {} } trait Bar<const M: Foo<2>> {} //~^ WARN trait objects without an explicit `dyn` are deprecated //~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! -//~| ERROR the trait `Foo` cannot be made into an object -//~| ERROR `(dyn Foo<2> + 'static)` is forbidden as the type of a const generic parameter fn main() {} diff --git a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.stderr b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.stderr index f8905437c6e..733b729faf0 100644 --- a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.stderr +++ b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.stderr @@ -13,7 +13,7 @@ LL | trait Foo<const N: dyn Bar<2>> { | +++ warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:11:20 + --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:9:20 | LL | trait Bar<const M: Foo<2>> {} | ^^^^^^ @@ -32,7 +32,7 @@ LL | trait Foo<const N: Bar<2>> { | ^^^^^^^^^^^^^^^ | note: ...which requires computing type of `Bar::M`... - --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:11:11 + --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:9:11 | LL | trait Bar<const M: Foo<2>> {} | ^^^^^^^^^^^^^^^ @@ -44,69 +44,6 @@ LL | trait Foo<const N: Bar<2>> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:2:24 - | -LL | trait Foo<const N: Bar<2>> { - | ^ `Foo` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> - --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:8:8 - | -LL | trait Foo<const N: Bar<2>> { - | --- this trait cannot be made into an object... -... -LL | fn func() {} - | ^^^^ ...because associated function `func` has no `self` parameter -help: consider turning `func` into a method by giving it a `&self` argument - | -LL | fn func(&self) {} - | +++++ -help: alternatively, consider constraining `func` so it does not apply to trait objects - | -LL | fn func() where Self: Sized {} - | +++++++++++++++++ - -error: `(dyn Bar<2> + 'static)` is forbidden as the type of a const generic parameter - --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:2:20 - | -LL | trait Foo<const N: Bar<2>> { - | ^^^^^^ - | - = note: the only supported types are integers, `bool`, and `char` - -error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:11:11 - | -LL | trait Bar<const M: Foo<2>> {} - | ^^^^^^^^^^^^^^^ `Foo` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> - --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:8:8 - | -LL | trait Foo<const N: Bar<2>> { - | --- this trait cannot be made into an object... -... -LL | fn func() {} - | ^^^^ ...because associated function `func` has no `self` parameter -help: consider turning `func` into a method by giving it a `&self` argument - | -LL | fn func(&self) {} - | +++++ -help: alternatively, consider constraining `func` so it does not apply to trait objects - | -LL | fn func() where Self: Sized {} - | +++++++++++++++++ - -error: `(dyn Foo<2> + 'static)` is forbidden as the type of a const generic parameter - --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:11:20 - | -LL | trait Bar<const M: Foo<2>> {} - | ^^^^^^ - | - = note: the only supported types are integers, `bool`, and `char` - -error: aborting due to 5 previous errors; 2 warnings emitted +error: aborting due to 1 previous error; 2 warnings emitted -Some errors have detailed explanations: E0038, E0391. -For more information about an error, try `rustc --explain E0038`. +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/wf/issue-96810.stderr b/tests/ui/wf/issue-96810.stderr index 622d72f791e..3f87d3e0786 100644 --- a/tests/ui/wf/issue-96810.stderr +++ b/tests/ui/wf/issue-96810.stderr @@ -9,7 +9,7 @@ note: required by a bound in `S` | LL | struct S<T: Tr>(T::Assoc); | ^^ required by this bound in `S` -help: consider restricting type parameter `K` +help: consider restricting type parameter `K` with trait `Tr` | LL | struct Hoge<K: Tr> { | ++++ diff --git a/tests/ui/wf/wf-enum-bound.stderr b/tests/ui/wf/wf-enum-bound.stderr index 78b5c6ec20e..1f37dc409fc 100644 --- a/tests/ui/wf/wf-enum-bound.stderr +++ b/tests/ui/wf/wf-enum-bound.stderr @@ -9,7 +9,7 @@ note: required by a bound in `ExtraCopy` | LL | trait ExtraCopy<T:Copy> { } | ^^^^ required by this bound in `ExtraCopy` -help: consider further restricting type parameter `U` +help: consider further restricting type parameter `U` with trait `Copy` | LL | where T: ExtraCopy<U>, U: std::marker::Copy | ++++++++++++++++++++++ diff --git a/tests/ui/wf/wf-enum-fields-struct-variant.stderr b/tests/ui/wf/wf-enum-fields-struct-variant.stderr index 2f2c1c2d266..f15a31887a2 100644 --- a/tests/ui/wf/wf-enum-fields-struct-variant.stderr +++ b/tests/ui/wf/wf-enum-fields-struct-variant.stderr @@ -9,7 +9,7 @@ note: required by a bound in `IsCopy` | LL | struct IsCopy<T:Copy> { | ^^^^ required by this bound in `IsCopy` -help: consider restricting type parameter `A` +help: consider restricting type parameter `A` with trait `Copy` | LL | enum AnotherEnum<A: std::marker::Copy> { | +++++++++++++++++++ diff --git a/tests/ui/wf/wf-enum-fields.stderr b/tests/ui/wf/wf-enum-fields.stderr index a5feaadfc75..3b4de77efdc 100644 --- a/tests/ui/wf/wf-enum-fields.stderr +++ b/tests/ui/wf/wf-enum-fields.stderr @@ -9,7 +9,7 @@ note: required by a bound in `IsCopy` | LL | struct IsCopy<T:Copy> { | ^^^^ required by this bound in `IsCopy` -help: consider restricting type parameter `A` +help: consider restricting type parameter `A` with trait `Copy` | LL | enum SomeEnum<A: std::marker::Copy> { | +++++++++++++++++++ diff --git a/tests/ui/wf/wf-fn-where-clause.stderr b/tests/ui/wf/wf-fn-where-clause.stderr index fbfe42ac624..76671dedabf 100644 --- a/tests/ui/wf/wf-fn-where-clause.stderr +++ b/tests/ui/wf/wf-fn-where-clause.stderr @@ -9,7 +9,7 @@ note: required by a bound in `ExtraCopy` | LL | trait ExtraCopy<T:Copy> { } | ^^^^ required by this bound in `ExtraCopy` -help: consider further restricting type parameter `U` +help: consider further restricting type parameter `U` with trait `Copy` | LL | fn foo<T,U>() where T: ExtraCopy<U>, U: std::marker::Copy | ++++++++++++++++++++++ diff --git a/tests/ui/wf/wf-impl-associated-type-trait.stderr b/tests/ui/wf/wf-impl-associated-type-trait.stderr index 09e255bead0..47962c75d69 100644 --- a/tests/ui/wf/wf-impl-associated-type-trait.stderr +++ b/tests/ui/wf/wf-impl-associated-type-trait.stderr @@ -9,7 +9,7 @@ note: required by a bound in `MySet` | LL | pub struct MySet<T:MyHash> { | ^^^^^^ required by this bound in `MySet` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `MyHash` | LL | impl<T: MyHash> Foo for T { | ++++++++ diff --git a/tests/ui/wf/wf-in-fn-arg.stderr b/tests/ui/wf/wf-in-fn-arg.stderr index 8f22edd17a1..a65f621526b 100644 --- a/tests/ui/wf/wf-in-fn-arg.stderr +++ b/tests/ui/wf/wf-in-fn-arg.stderr @@ -9,7 +9,7 @@ note: required by a bound in `MustBeCopy` | LL | struct MustBeCopy<T:Copy> { | ^^^^ required by this bound in `MustBeCopy` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | fn bar<T: std::marker::Copy>(_: &MustBeCopy<T>) | +++++++++++++++++++ diff --git a/tests/ui/wf/wf-in-fn-ret.stderr b/tests/ui/wf/wf-in-fn-ret.stderr index 1ae49a348cc..3f2b46f8478 100644 --- a/tests/ui/wf/wf-in-fn-ret.stderr +++ b/tests/ui/wf/wf-in-fn-ret.stderr @@ -9,7 +9,7 @@ note: required by a bound in `MustBeCopy` | LL | struct MustBeCopy<T: Copy> { | ^^^^ required by this bound in `MustBeCopy` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | fn bar<T: std::marker::Copy>() -> MustBeCopy<T> | +++++++++++++++++++ diff --git a/tests/ui/wf/wf-in-fn-type-arg.stderr b/tests/ui/wf/wf-in-fn-type-arg.stderr index 17594c813da..4626b90500a 100644 --- a/tests/ui/wf/wf-in-fn-type-arg.stderr +++ b/tests/ui/wf/wf-in-fn-type-arg.stderr @@ -9,7 +9,7 @@ note: required by a bound in `MustBeCopy` | LL | struct MustBeCopy<T:Copy> { | ^^^^ required by this bound in `MustBeCopy` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | struct Bar<T: std::marker::Copy> { | +++++++++++++++++++ diff --git a/tests/ui/wf/wf-in-fn-type-ret.stderr b/tests/ui/wf/wf-in-fn-type-ret.stderr index fac535a1126..2ad405b4451 100644 --- a/tests/ui/wf/wf-in-fn-type-ret.stderr +++ b/tests/ui/wf/wf-in-fn-type-ret.stderr @@ -9,7 +9,7 @@ note: required by a bound in `MustBeCopy` | LL | struct MustBeCopy<T:Copy> { | ^^^^ required by this bound in `MustBeCopy` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | struct Foo<T: std::marker::Copy> { | +++++++++++++++++++ diff --git a/tests/ui/wf/wf-in-fn-where-clause.stderr b/tests/ui/wf/wf-in-fn-where-clause.stderr index 4c556d3d77d..6a56d1c032f 100644 --- a/tests/ui/wf/wf-in-fn-where-clause.stderr +++ b/tests/ui/wf/wf-in-fn-where-clause.stderr @@ -9,7 +9,7 @@ note: required by a bound in `MustBeCopy` | LL | trait MustBeCopy<T:Copy> { | ^^^^ required by this bound in `MustBeCopy` -help: consider further restricting type parameter `U` +help: consider further restricting type parameter `U` with trait `Copy` | LL | where T: MustBeCopy<U>, U: std::marker::Copy | ++++++++++++++++++++++ diff --git a/tests/ui/wf/wf-in-obj-type-trait.stderr b/tests/ui/wf/wf-in-obj-type-trait.stderr index b96f56a12a5..5cd5bf5e24e 100644 --- a/tests/ui/wf/wf-in-obj-type-trait.stderr +++ b/tests/ui/wf/wf-in-obj-type-trait.stderr @@ -9,7 +9,7 @@ note: required by a bound in `MustBeCopy` | LL | struct MustBeCopy<T:Copy> { | ^^^^ required by this bound in `MustBeCopy` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | struct Bar<T: std::marker::Copy> { | +++++++++++++++++++ diff --git a/tests/ui/wf/wf-inherent-impl-method-where-clause.stderr b/tests/ui/wf/wf-inherent-impl-method-where-clause.stderr index 4cfbec12b6e..8b41bb17d2f 100644 --- a/tests/ui/wf/wf-inherent-impl-method-where-clause.stderr +++ b/tests/ui/wf/wf-inherent-impl-method-where-clause.stderr @@ -9,7 +9,7 @@ note: required by a bound in `ExtraCopy` | LL | trait ExtraCopy<T:Copy> { } | ^^^^ required by this bound in `ExtraCopy` -help: consider restricting type parameter `U` +help: consider restricting type parameter `U` with trait `Copy` | LL | impl<T,U: std::marker::Copy> Foo<T,U> { | +++++++++++++++++++ diff --git a/tests/ui/wf/wf-inherent-impl-where-clause.stderr b/tests/ui/wf/wf-inherent-impl-where-clause.stderr index bdc1ee3e0e2..216b7a98b13 100644 --- a/tests/ui/wf/wf-inherent-impl-where-clause.stderr +++ b/tests/ui/wf/wf-inherent-impl-where-clause.stderr @@ -9,7 +9,7 @@ note: required by a bound in `ExtraCopy` | LL | trait ExtraCopy<T:Copy> { } | ^^^^ required by this bound in `ExtraCopy` -help: consider further restricting type parameter `U` +help: consider further restricting type parameter `U` with trait `Copy` | LL | impl<T,U> Foo<T,U> where T: ExtraCopy<U>, U: std::marker::Copy | ++++++++++++++++++++++ diff --git a/tests/ui/wf/wf-struct-bound.stderr b/tests/ui/wf/wf-struct-bound.stderr index 4ac7f4634e4..24b4282538d 100644 --- a/tests/ui/wf/wf-struct-bound.stderr +++ b/tests/ui/wf/wf-struct-bound.stderr @@ -9,7 +9,7 @@ note: required by a bound in `ExtraCopy` | LL | trait ExtraCopy<T:Copy> { } | ^^^^ required by this bound in `ExtraCopy` -help: consider further restricting type parameter `U` +help: consider further restricting type parameter `U` with trait `Copy` | LL | where T: ExtraCopy<U>, U: std::marker::Copy | ++++++++++++++++++++++ diff --git a/tests/ui/wf/wf-struct-field.stderr b/tests/ui/wf/wf-struct-field.stderr index 241ced3c2db..4449b71bd88 100644 --- a/tests/ui/wf/wf-struct-field.stderr +++ b/tests/ui/wf/wf-struct-field.stderr @@ -9,7 +9,7 @@ note: required by a bound in `IsCopy` | LL | struct IsCopy<T:Copy> { | ^^^^ required by this bound in `IsCopy` -help: consider restricting type parameter `A` +help: consider restricting type parameter `A` with trait `Copy` | LL | struct SomeStruct<A: std::marker::Copy> { | +++++++++++++++++++ diff --git a/tests/ui/wf/wf-trait-associated-type-bound.stderr b/tests/ui/wf/wf-trait-associated-type-bound.stderr index 4ea895a9b03..fe6a848f866 100644 --- a/tests/ui/wf/wf-trait-associated-type-bound.stderr +++ b/tests/ui/wf/wf-trait-associated-type-bound.stderr @@ -9,7 +9,7 @@ note: required by a bound in `ExtraCopy` | LL | trait ExtraCopy<T:Copy> { } | ^^^^ required by this bound in `ExtraCopy` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | trait SomeTrait<T: std::marker::Copy> { | +++++++++++++++++++ diff --git a/tests/ui/wf/wf-trait-bound.stderr b/tests/ui/wf/wf-trait-bound.stderr index 5845d05b38e..0a8d9aa7be8 100644 --- a/tests/ui/wf/wf-trait-bound.stderr +++ b/tests/ui/wf/wf-trait-bound.stderr @@ -9,7 +9,7 @@ note: required by a bound in `ExtraCopy` | LL | trait ExtraCopy<T:Copy> { } | ^^^^ required by this bound in `ExtraCopy` -help: consider further restricting type parameter `U` +help: consider further restricting type parameter `U` with trait `Copy` | LL | where T: ExtraCopy<U>, U: std::marker::Copy | ++++++++++++++++++++++ diff --git a/tests/ui/wf/wf-trait-superbound.stderr b/tests/ui/wf/wf-trait-superbound.stderr index 3c05065e57f..9b0205bfe39 100644 --- a/tests/ui/wf/wf-trait-superbound.stderr +++ b/tests/ui/wf/wf-trait-superbound.stderr @@ -9,7 +9,7 @@ note: required by a bound in `ExtraCopy` | LL | trait ExtraCopy<T:Copy> { } | ^^^^ required by this bound in `ExtraCopy` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | trait SomeTrait<T: std::marker::Copy>: ExtraCopy<T> { | +++++++++++++++++++ diff --git a/tests/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr b/tests/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr index 2612cefef28..955ec18f465 100644 --- a/tests/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr +++ b/tests/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr @@ -11,7 +11,7 @@ note: required by a bound in `require_copy` | LL | fn require_copy<T: Copy>(x: T) {} | ^^^^ required by this bound in `require_copy` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | impl<T: std::marker::Copy> Foo<T> { | +++++++++++++++++++ diff --git a/tests/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr b/tests/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr index 090df26a39e..793851a2871 100644 --- a/tests/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr +++ b/tests/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr @@ -11,7 +11,7 @@ note: required by a bound in `require_copy` | LL | fn require_copy<T: Copy>(x: T) {} | ^^^^ required by this bound in `require_copy` -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `Copy` | LL | impl<T: std::marker::Copy> Foo<T> for Bar<T> { | +++++++++++++++++++ diff --git a/x.py b/x.py index 6c4c106817e..928a7496cb7 100755 --- a/x.py +++ b/x.py @@ -6,7 +6,7 @@ # Parts of `bootstrap.py` use the `multiprocessing` module, so this entry point # must use the normal `if __name__ == '__main__':` convention to avoid problems. -if __name__ == '__main__': +if __name__ == "__main__": import os import sys import warnings @@ -32,14 +32,16 @@ if __name__ == '__main__': # soft deprecation of old python versions skip_check = os.environ.get("RUST_IGNORE_OLD_PYTHON") == "1" if not skip_check and (major < 3 or (major == 3 and minor < 6)): - msg = cleandoc(""" + msg = cleandoc( + """ Using python {}.{} but >= 3.6 is recommended. Your python version should continue to work for the near future, but this will eventually change. If python >= 3.6 is not available on your system, please file an issue to help us understand timelines. This message can be suppressed by setting `RUST_IGNORE_OLD_PYTHON=1` - """.format(major, minor)) + """.format(major, minor) + ) warnings.warn(msg, stacklevel=1) rust_dir = os.path.dirname(os.path.abspath(__file__)) @@ -47,4 +49,5 @@ if __name__ == '__main__': sys.path.insert(0, os.path.join(rust_dir, "src", "bootstrap")) import bootstrap + bootstrap.main() |
