diff options
| author | bors <bors@rust-lang.org> | 2023-06-28 07:13:12 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2023-06-28 07:13:12 +0000 |
| commit | 984d29d26069590786b47424c8ca205e4f4560cb (patch) | |
| tree | a400dcb280046d1e426076bd25df1b468aebe6b5 /src | |
| parent | 662388e17fe4f3a4252f63fd84c05cfd54cc13a0 (diff) | |
| parent | de9dc5916456f441286c35452416a3dec0b4c2c0 (diff) | |
| download | rust-984d29d26069590786b47424c8ca205e4f4560cb.tar.gz rust-984d29d26069590786b47424c8ca205e4f4560cb.zip | |
Auto merge of #2944 - oli-obk:rustup, r=oli-obk
Rustup
Diffstat (limited to 'src')
70 files changed, 710 insertions, 611 deletions
diff --git a/src/bootstrap/bin/main.rs b/src/bootstrap/bin/main.rs index a80379e85c1..7ce4599c424 100644 --- a/src/bootstrap/bin/main.rs +++ b/src/bootstrap/bin/main.rs @@ -5,7 +5,9 @@ //! parent directory, and otherwise documentation can be found throughout the `build` //! directory in each respective module. -use std::env; +use std::fs::OpenOptions; +use std::io::Write; +use std::{env, fs, process}; #[cfg(all(any(unix, windows), not(target_os = "solaris")))] use bootstrap::t; @@ -20,22 +22,32 @@ fn main() { #[cfg(all(any(unix, windows), not(target_os = "solaris")))] let _build_lock_guard; #[cfg(all(any(unix, windows), not(target_os = "solaris")))] + // Display PID of process holding the lock + // PID will be stored in a lock file { let path = config.out.join("lock"); - build_lock = fd_lock::RwLock::new(t!(std::fs::File::create(&path))); + let pid = match fs::read_to_string(&path) { + Ok(contents) => contents, + Err(_) => String::new(), + }; + + build_lock = + fd_lock::RwLock::new(t!(OpenOptions::new().write(true).create(true).open(&path))); _build_lock_guard = match build_lock.try_write() { - Ok(lock) => lock, + Ok(mut lock) => { + t!(lock.write(&process::id().to_string().as_ref())); + lock + } err => { drop(err); - if let Some(pid) = get_lock_owner(&path) { - println!("warning: build directory locked by process {pid}, waiting for lock"); - } else { - println!("warning: build directory locked, waiting for lock"); - } - t!(build_lock.write()) + println!("warning: build directory locked by process {pid}, waiting for lock"); + let mut lock = t!(build_lock.write()); + t!(lock.write(&process::id().to_string().as_ref())); + lock } }; } + #[cfg(any(not(any(unix, windows)), target_os = "solaris"))] println!("warning: file locking not supported for target, not locking build directory"); @@ -108,30 +120,3 @@ fn check_version(config: &Config) -> Option<String> { Some(msg) } - -/// Get the PID of the process which took the write lock by -/// parsing `/proc/locks`. -#[cfg(target_os = "linux")] -fn get_lock_owner(f: &std::path::Path) -> Option<u64> { - use std::fs::File; - use std::io::{BufRead, BufReader}; - use std::os::unix::fs::MetadataExt; - - let lock_inode = std::fs::metadata(f).ok()?.ino(); - let lockfile = File::open("/proc/locks").ok()?; - BufReader::new(lockfile).lines().find_map(|line| { - // pid--vvvvvv vvvvvvv--- inode - // 21: FLOCK ADVISORY WRITE 359238 08:02:3719774 0 EOF - let line = line.ok()?; - let parts = line.split_whitespace().collect::<Vec<_>>(); - let (pid, inode) = (parts[4].parse::<u64>().ok()?, &parts[5]); - let inode = inode.rsplit_once(':')?.1.parse::<u64>().ok()?; - if inode == lock_inode { Some(pid) } else { None } - }) -} - -#[cfg(not(any(target_os = "linux", target_os = "solaris")))] -fn get_lock_owner(_: &std::path::Path) -> Option<u64> { - // FIXME: Implement on other OS's - None -} diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 5714613cdf5..149350e62a0 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -323,6 +323,7 @@ def default_build_triple(verbose): cputype_mapper = { 'BePC': 'i686', 'aarch64': 'aarch64', + 'aarch64eb': 'aarch64', 'amd64': 'x86_64', 'arm64': 'aarch64', 'i386': 'i686', @@ -458,23 +459,51 @@ def unpack_component(download_info): verbose=download_info.verbose, ) -class RustBuild(object): - """Provide all the methods required to build Rust""" +class FakeArgs: + """Used for unit tests to avoid updating all call sites""" def __init__(self): - self.checksums_sha256 = {} - self.stage0_compiler = None - self.download_url = '' self.build = '' self.build_dir = '' self.clean = False - self.config_toml = '' - self.rust_root = '' - self.use_locked_deps = False - self.use_vendored_sources = False self.verbose = False + self.json_output = False + self.color = 'auto' + self.warnings = 'default' + +class RustBuild(object): + """Provide all the methods required to build Rust""" + def __init__(self, config_toml="", 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.config_toml = config_toml + + self.clean = args.clean + self.json_output = args.json_output + self.verbose = args.verbose + self.color = args.color + self.warnings = args.warnings + + 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' + + build_dir = args.build_dir or self.get_toml('build-dir', 'build') or 'build' + self.build_dir = os.path.abspath(build_dir) + + with open(os.path.join(self.rust_root, "src", "stage0.json")) as f: + data = json.load(f) + self.checksums_sha256 = data["checksums_sha256"] + self.stage0_compiler = Stage0Toolchain(data["compiler"]) + self.download_url = os.getenv("RUSTUP_DIST_SERVER") or data["config"]["dist_server"] + + self.build = args.build or self.build_triple() + def download_toolchain(self): """Fetch the build system for Rust, written in Rust @@ -704,9 +733,10 @@ class RustBuild(object): """Return the path for .rustc-stamp at the given stage >>> rb = RustBuild() + >>> rb.build = "host" >>> rb.build_dir = "build" - >>> rb.rustc_stamp() == os.path.join("build", "stage0", ".rustc-stamp") - True + >>> 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') @@ -721,15 +751,9 @@ class RustBuild(object): """Return the binary root directory for the given stage >>> rb = RustBuild() - >>> rb.build_dir = "build" - >>> rb.bin_root() == os.path.join("build", "stage0") - True - - When the 'build' property is given should be a nested directory: - >>> rb.build = "devel" - >>> rb.bin_root() == os.path.join("build", "devel", "stage0") - True + >>> expected = os.path.abspath(os.path.join("build", "devel", "stage0")) + >>> assert rb.bin_root() == expected, rb.bin_root() """ subdir = "stage0" return os.path.join(self.build_dir, self.build, subdir) @@ -761,9 +785,12 @@ class RustBuild(object): >>> rb.get_toml("key1") 'true' """ + return RustBuild.get_toml_static(self.config_toml, key, section) + @staticmethod + def get_toml_static(config_toml, key, section=None): cur_section = None - for line in self.config_toml.splitlines(): + for line in config_toml.splitlines(): section_match = re.match(r'^\s*\[(.*)\]\s*$', line) if section_match is not None: cur_section = section_match.group(1) @@ -772,7 +799,7 @@ class RustBuild(object): if match is not None: value = match.group(1) if section is None or section == cur_section: - return self.get_string(value) or value.strip() + return RustBuild.get_string(value) or value.strip() return None def cargo(self): @@ -835,13 +862,23 @@ class RustBuild(object): """ return os.path.join(self.build_dir, "bootstrap", "debug", "bootstrap") - def build_bootstrap(self, color, warnings, verbose_count): + def build_bootstrap(self): """Build bootstrap""" env = os.environ.copy() if "GITHUB_ACTIONS" in env: print("::group::Building bootstrap") else: print("Building bootstrap", file=sys.stderr) + + args = self.build_bootstrap_cmd(env) + # Run this from the source directory so cargo finds .cargo/config + run(args, env=env, verbose=self.verbose, cwd=self.rust_root) + + if "GITHUB_ACTIONS" in env: + print("::endgroup::") + + def build_bootstrap_cmd(self, env): + """For tests.""" build_dir = os.path.join(self.build_dir, "bootstrap") if self.clean and os.path.exists(build_dir): shutil.rmtree(build_dir) @@ -894,10 +931,10 @@ class RustBuild(object): if target_linker is not None: env["RUSTFLAGS"] += " -C linker=" + target_linker env["RUSTFLAGS"] += " -Wrust_2018_idioms -Wunused_lifetimes" - if warnings == "default": + if self.warnings == "default": deny_warnings = self.get_toml("deny-warnings", "rust") != "false" else: - deny_warnings = warnings == "deny" + deny_warnings = self.warnings == "deny" if deny_warnings: env["RUSTFLAGS"] += " -Dwarnings" @@ -908,7 +945,7 @@ class RustBuild(object): self.cargo())) args = [self.cargo(), "build", "--manifest-path", os.path.join(self.rust_root, "src/bootstrap/Cargo.toml")] - args.extend("--verbose" for _ in range(verbose_count)) + args.extend("--verbose" for _ in range(self.verbose)) if self.use_locked_deps: args.append("--locked") if self.use_vendored_sources: @@ -918,20 +955,16 @@ class RustBuild(object): args.append("build-metrics") if self.json_output: args.append("--message-format=json") - if color == "always": + if self.color == "always": args.append("--color=always") - elif color == "never": + elif self.color == "never": args.append("--color=never") try: args += env["CARGOFLAGS"].split() except KeyError: pass - # Run this from the source directory so cargo finds .cargo/config - run(args, env=env, verbose=self.verbose, cwd=self.rust_root) - - if "GITHUB_ACTIONS" in env: - print("::endgroup::") + return args def build_triple(self): """Build triple as in LLVM @@ -981,7 +1014,7 @@ class RustBuild(object): if os.path.exists(cargo_dir): shutil.rmtree(cargo_dir) -def parse_args(): +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') @@ -994,16 +1027,11 @@ def parse_args(): parser.add_argument('--warnings', choices=['deny', 'warn', 'default'], default='default') parser.add_argument('-v', '--verbose', action='count', default=0) - return parser.parse_known_args(sys.argv)[0] + return parser.parse_known_args(args)[0] def bootstrap(args): """Configure, fetch, build and run the initial bootstrap""" - # Configure initial bootstrap - build = RustBuild() - build.rust_root = os.path.abspath(os.path.join(__file__, '../../..')) - build.verbose = args.verbose != 0 - build.clean = args.clean - build.json_output = args.json_output + rust_root = os.path.abspath(os.path.join(__file__, '../../..')) # Read from `--config`, then `RUST_BOOTSTRAP_CONFIG`, then `./config.toml`, # then `config.toml` in the root directory. @@ -1012,52 +1040,43 @@ def bootstrap(args): if using_default_path: toml_path = 'config.toml' if not os.path.exists(toml_path): - toml_path = os.path.join(build.rust_root, toml_path) + toml_path = os.path.join(rust_root, toml_path) # Give a hard error if `--config` or `RUST_BOOTSTRAP_CONFIG` are set to a missing path, # but not if `config.toml` hasn't been created. if not using_default_path or os.path.exists(toml_path): with open(toml_path) as config: - build.config_toml = config.read() + config_toml = config.read() + else: + config_toml = '' - profile = build.get_toml('profile') + profile = RustBuild.get_toml_static(config_toml, 'profile') if profile is not None: - include_file = 'config.{}.toml'.format(profile) - include_dir = os.path.join(build.rust_root, 'src', 'bootstrap', 'defaults') + # 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') include_path = os.path.join(include_dir, include_file) - # HACK: This works because `build.get_toml()` returns the first match it finds for a + # 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 with open(include_path) as included_toml: - build.config_toml += os.linesep + included_toml.read() - - verbose_count = args.verbose - config_verbose_count = build.get_toml('verbose', 'build') - if config_verbose_count is not None: - verbose_count = max(args.verbose, int(config_verbose_count)) - - build.use_vendored_sources = build.get_toml('vendor', 'build') == 'true' - build.use_locked_deps = build.get_toml('locked-deps', 'build') == 'true' + config_toml += os.linesep + included_toml.read() + # Configure initial bootstrap + build = RustBuild(config_toml, args) build.check_vendored_status() - build_dir = args.build_dir or build.get_toml('build-dir', 'build') or 'build' - build.build_dir = os.path.abspath(build_dir) - - with open(os.path.join(build.rust_root, "src", "stage0.json")) as f: - data = json.load(f) - build.checksums_sha256 = data["checksums_sha256"] - build.stage0_compiler = Stage0Toolchain(data["compiler"]) - build.download_url = os.getenv("RUSTUP_DIST_SERVER") or data["config"]["dist_server"] - - build.build = args.build or build.build_triple() - if not os.path.exists(build.build_dir): os.makedirs(build.build_dir) # Fetch/build the bootstrap build.download_toolchain() sys.stdout.flush() - build.build_bootstrap(args.color, args.warnings, verbose_count) + build.build_bootstrap() sys.stdout.flush() # Run the bootstrap @@ -1077,7 +1096,7 @@ def main(): if len(sys.argv) > 1 and sys.argv[1] == 'help': sys.argv[1] = '-h' - args = parse_args() + args = parse_args(sys.argv) help_triggered = args.help or len(sys.argv) == 1 # If the user is asking for help, let them know that the whole download-and-build diff --git a/src/bootstrap/bootstrap_test.py b/src/bootstrap/bootstrap_test.py index 5ecda83ee66..1294ca9df0d 100644 --- a/src/bootstrap/bootstrap_test.py +++ b/src/bootstrap/bootstrap_test.py @@ -1,4 +1,6 @@ -"""Bootstrap tests""" +"""Bootstrap tests + +Run these with `x test bootstrap`, or `python -m unittest bootstrap_test.py`.""" from __future__ import absolute_import, division, print_function import os @@ -13,6 +15,22 @@ from shutil import rmtree import bootstrap import configure +def serialize_and_parse(configure_args, bootstrap_args=bootstrap.FakeArgs()): + from io import StringIO + + section_order, sections, targets = configure.parse_args(configure_args) + buffer = StringIO() + configure.write_config_toml(buffer, section_order, targets, sections) + build = bootstrap.RustBuild(config_toml=buffer.getvalue(), args=bootstrap_args) + + 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) + return build + class VerifyTestCase(unittest.TestCase): """Test Case for verify""" @@ -77,58 +95,58 @@ class ProgramOutOfDate(unittest.TestCase): class GenerateAndParseConfig(unittest.TestCase): """Test that we can serialize and deserialize a config.toml file""" - def serialize_and_parse(self, args): - from io import StringIO - - section_order, sections, targets = configure.parse_args(args) - buffer = StringIO() - configure.write_config_toml(buffer, section_order, targets, sections) - build = bootstrap.RustBuild() - build.config_toml = buffer.getvalue() - - 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) - return build - def test_no_args(self): - build = self.serialize_and_parse([]) + build = serialize_and_parse([]) self.assertEqual(build.get_toml("changelog-seen"), '2') - self.assertEqual(build.get_toml("profile"), 'user') + self.assertEqual(build.get_toml("profile"), 'dist') self.assertIsNone(build.get_toml("llvm.download-ci-llvm")) def test_set_section(self): - build = self.serialize_and_parse(["--set", "llvm.download-ci-llvm"]) + build = serialize_and_parse(["--set", "llvm.download-ci-llvm"]) self.assertEqual(build.get_toml("download-ci-llvm", section="llvm"), 'true') def test_set_target(self): - build = self.serialize_and_parse(["--set", "target.x86_64-unknown-linux-gnu.cc=gcc"]) + 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') def test_set_top_level(self): - build = self.serialize_and_parse(["--set", "profile=compiler"]) + build = serialize_and_parse(["--set", "profile=compiler"]) self.assertEqual(build.get_toml("profile"), 'compiler') def test_set_codegen_backends(self): - build = self.serialize_and_parse(["--set", "rust.codegen-backends=cranelift"]) + build = serialize_and_parse(["--set", "rust.codegen-backends=cranelift"]) self.assertNotEqual(build.config_toml.find("codegen-backends = ['cranelift']"), -1) - build = self.serialize_and_parse(["--set", "rust.codegen-backends=cranelift,llvm"]) + build = serialize_and_parse(["--set", "rust.codegen-backends=cranelift,llvm"]) self.assertNotEqual(build.config_toml.find("codegen-backends = ['cranelift', 'llvm']"), -1) - build = self.serialize_and_parse(["--enable-full-tools"]) + build = serialize_and_parse(["--enable-full-tools"]) self.assertNotEqual(build.config_toml.find("codegen-backends = ['llvm']"), -1) -if __name__ == '__main__': - SUITE = unittest.TestSuite() - TEST_LOADER = unittest.TestLoader() - SUITE.addTest(doctest.DocTestSuite(bootstrap)) - SUITE.addTests([ - TEST_LOADER.loadTestsFromTestCase(VerifyTestCase), - TEST_LOADER.loadTestsFromTestCase(GenerateAndParseConfig), - TEST_LOADER.loadTestsFromTestCase(ProgramOutOfDate)]) - - RUNNER = unittest.TextTestRunner(stream=sys.stdout, verbosity=2) - result = RUNNER.run(SUITE) - sys.exit(0 if result.wasSuccessful() else 1) + +class BuildBootstrap(unittest.TestCase): + """Test that we generate the appropriate arguments when building bootstrap""" + + def build_args(self, configure_args=[], args=[], env={}): + env = env.copy() + env["PATH"] = os.environ["PATH"] + + parsed = bootstrap.parse_args(args) + build = serialize_and_parse(configure_args, parsed) + build.build_dir = os.environ["BUILD_DIR"] + build.build = os.environ["BUILD_PLATFORM"] + return build.build_bootstrap_cmd(env), env + + def test_cargoflags(self): + args, _ = self.build_args(env={"CARGOFLAGS": "--timings"}) + self.assertTrue("--timings" in args) + + def test_warnings(self): + for toml_warnings in ['false', 'true', None]: + configure_args = [] + if toml_warnings is not None: + configure_args = ["--set", "rust.deny-warnings=" + toml_warnings] + + _, env = self.build_args(configure_args, args=["--warnings=warn"]) + self.assertFalse("-Dwarnings" in env["RUSTFLAGS"]) + + _, env = self.build_args(configure_args, args=["--warnings=deny"]) + self.assertTrue("-Dwarnings" in env["RUSTFLAGS"]) diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 8ee63e561ba..b91275e73e9 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -1129,6 +1129,14 @@ impl Config { }; if let Some(include) = &toml.profile { + // Allows creating alias for profile names, allowing + // profiles to be renamed while maintaining back compatibility + // Keep in sync with `profile_aliases` in bootstrap.py + let profile_aliases = HashMap::from([("user", "dist")]); + let include = match profile_aliases.get(include.as_str()) { + Some(alias) => alias, + None => include.as_str(), + }; let mut include_path = config.src.clone(); include_path.push("src"); include_path.push("bootstrap"); diff --git a/src/bootstrap/config/tests.rs b/src/bootstrap/config/tests.rs index 4de84b543ed..3bee659abd1 100644 --- a/src/bootstrap/config/tests.rs +++ b/src/bootstrap/config/tests.rs @@ -1,5 +1,8 @@ +use crate::config::TomlConfig; + use super::{Config, Flags}; use clap::CommandFactory; +use serde::Deserialize; use std::{env, path::Path}; fn parse(config: &str) -> Config { @@ -159,3 +162,19 @@ fn override_toml_duplicate() { |&_| toml::from_str("changelog-seen = 0").unwrap(), ); } + +#[test] +fn profile_user_dist() { + fn get_toml(file: &Path) -> TomlConfig { + let contents = if file.ends_with("config.toml") { + "profile = \"user\"".to_owned() + } else { + assert!(file.ends_with("config.dist.toml")); + std::fs::read_to_string(dbg!(file)).unwrap() + }; + toml::from_str(&contents) + .and_then(|table: toml::Value| TomlConfig::deserialize(table)) + .unwrap() + } + Config::parse_inner(&["check".to_owned()], get_toml); +} diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index a16f77317c8..e8eebdfb5a5 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -280,7 +280,7 @@ def parse_args(args): config = {} - set('build.configure-args', sys.argv[1:], config) + set('build.configure-args', args, config) apply_args(known_args, option_checking, config) return parse_example_config(known_args, config) @@ -400,7 +400,9 @@ def parse_example_config(known_args, config): targets = {} top_level_keys = [] - for line in open(rust_dir + '/config.example.toml').read().split("\n"): + 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] @@ -435,7 +437,7 @@ def parse_example_config(known_args, config): 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', 'user', config) + set('profile', 'dist', config) configure_file(sections, top_level_keys, targets, config) return section_order, sections, targets diff --git a/src/bootstrap/defaults/config.user.toml b/src/bootstrap/defaults/config.dist.toml index 25d9e649f23..25d9e649f23 100644 --- a/src/bootstrap/defaults/config.user.toml +++ b/src/bootstrap/defaults/config.dist.toml diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 8592895423e..1ac52dffe58 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -222,7 +222,7 @@ impl Step for TheBook { let shared_assets = builder.ensure(SharedAssets { target }); // build the redirect pages - builder.info(&format!("Documenting book redirect pages ({})", target)); + builder.msg_doc(compiler, "book redirect pages", target); for file in t!(fs::read_dir(builder.src.join(&relative_path).join("redirects"))) { let file = t!(file); let path = file.path(); @@ -306,7 +306,7 @@ impl Step for Standalone { fn run(self, builder: &Builder<'_>) { let target = self.target; let compiler = self.compiler; - builder.info(&format!("Documenting standalone ({})", target)); + builder.msg_doc(compiler, "standalone", target); let out = builder.doc_out(target); t!(fs::create_dir_all(&out)); @@ -562,7 +562,7 @@ fn doc_std( let description = format!("library{} in {} format", crate_description(&requested_crates), format.as_str()); - let _guard = builder.msg(Kind::Doc, stage, &description, compiler.host, target); + let _guard = builder.msg_doc(compiler, &description, target); let target_doc_dir_name = if format == DocumentationFormat::JSON { "json-doc" } else { "doc" }; let target_dir = @@ -804,14 +804,7 @@ macro_rules! tool_doc { SourceType::Submodule }; - builder.info( - &format!( - "Documenting stage{} {} ({})", - stage, - stringify!($tool).to_lowercase(), - target, - ), - ); + builder.msg_doc(compiler, stringify!($tool).to_lowercase(), target); // Symlink compiler docs to the output directory of rustdoc documentation. let out_dirs = [ diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index d389b568f56..c960053d7a0 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -1009,6 +1009,15 @@ impl Build { self.msg(Kind::Check, self.config.stage, what, self.config.build, target) } + fn msg_doc( + &self, + compiler: Compiler, + what: impl Display, + target: impl Into<Option<TargetSelection>> + Copy, + ) -> Option<gha::Group> { + self.msg(Kind::Doc, compiler.stage, what, compiler.host, target.into()) + } + fn msg_build( &self, compiler: Compiler, diff --git a/src/bootstrap/setup.rs b/src/bootstrap/setup.rs index 7eb70de91f8..34c6ccf1365 100644 --- a/src/bootstrap/setup.rs +++ b/src/bootstrap/setup.rs @@ -20,7 +20,7 @@ pub enum Profile { Codegen, Library, Tools, - User, + Dist, None, } @@ -43,7 +43,7 @@ impl Profile { pub fn all() -> impl Iterator<Item = Self> { use Profile::*; // N.B. these are ordered by how they are displayed, not alphabetically - [Library, Compiler, Codegen, Tools, User, None].iter().copied() + [Library, Compiler, Codegen, Tools, Dist, None].iter().copied() } pub fn purpose(&self) -> String { @@ -53,7 +53,7 @@ impl Profile { Compiler => "Contribute to the compiler itself", Codegen => "Contribute to the compiler, and also modify LLVM or codegen", Tools => "Contribute to tools which depend on the compiler, but do not modify it directly (e.g. rustdoc, clippy, miri)", - User => "Install Rust from source", + Dist => "Install Rust from source", None => "Do not modify `config.toml`" } .to_string() @@ -73,7 +73,7 @@ impl Profile { Profile::Codegen => "codegen", Profile::Library => "library", Profile::Tools => "tools", - Profile::User => "user", + Profile::Dist => "dist", Profile::None => "none", } } @@ -87,7 +87,7 @@ impl FromStr for Profile { "lib" | "library" => Ok(Profile::Library), "compiler" => Ok(Profile::Compiler), "llvm" | "codegen" => Ok(Profile::Codegen), - "maintainer" | "user" => Ok(Profile::User), + "maintainer" | "dist" | "user" => Ok(Profile::Dist), "tools" | "tool" | "rustdoc" | "clippy" | "miri" | "rustfmt" | "rls" => { Ok(Profile::Tools) } @@ -160,7 +160,7 @@ pub fn setup(config: &Config, profile: Profile) { "test src/tools/rustfmt", ], Profile::Library => &["check", "build", "test library/std", "doc"], - Profile::User => &["dist", "build"], + Profile::Dist => &["dist", "build"], }; println!(); @@ -170,7 +170,7 @@ pub fn setup(config: &Config, profile: Profile) { println!("- `x.py {}`", cmd); } - if profile != Profile::User { + if profile != Profile::Dist { println!( "For more suggestions, see https://rustc-dev-guide.rust-lang.org/building/suggested.html" ); @@ -582,7 +582,7 @@ fn create_vscode_settings_maybe(config: &Config) -> io::Result<()> { Some(false) => { // exists and is not current version or outdated, so back it up let mut backup = vscode_settings.clone(); - backup.set_extension("bak"); + backup.set_extension("json.bak"); eprintln!("warning: copying `settings.json` to `settings.json.bak`"); fs::copy(&vscode_settings, &backup)?; "Updated" diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 873ed61daf3..ec447a1cd73 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -1832,11 +1832,13 @@ note: if you're sure you want to do this, please open an issue as to why. In the builder, ); - builder.info(&format!( - "Check compiletest suite={} mode={} ({} -> {})", - suite, mode, &compiler.host, target - )); - let _time = util::timeit(&builder); + let _group = builder.msg( + Kind::Test, + compiler.stage, + &format!("compiletest suite={suite} mode={mode}"), + compiler.host, + target, + ); crate::render_tests::try_run_tests(builder, &mut cmd, false); if let Some(compare_mode) = compare_mode { @@ -2664,7 +2666,12 @@ impl Step for Bootstrap { /// Tests the build system itself. fn run(self, builder: &Builder<'_>) { let mut check_bootstrap = Command::new(&builder.python()); - check_bootstrap.arg("bootstrap_test.py").current_dir(builder.src.join("src/bootstrap/")); + check_bootstrap + .args(["-m", "unittest", "bootstrap_test.py"]) + .env("BUILD_DIR", &builder.out) + .env("BUILD_PLATFORM", &builder.build.build.triple) + .current_dir(builder.src.join("src/bootstrap/")) + .args(builder.config.test_args()); try_run(builder, &mut check_bootstrap).unwrap(); let host = builder.config.build; diff --git a/src/ci/docker/host-x86_64/dist-various-2/build-wasi-toolchain.sh b/src/ci/docker/host-x86_64/dist-various-2/build-wasi-toolchain.sh index 5fbce36c39d..b867db6a1b5 100755 --- a/src/ci/docker/host-x86_64/dist-various-2/build-wasi-toolchain.sh +++ b/src/ci/docker/host-x86_64/dist-various-2/build-wasi-toolchain.sh @@ -10,7 +10,7 @@ bin="$PWD/clang+llvm-15.0.6-x86_64-linux-gnu-ubuntu-18.04/bin" git clone https://github.com/WebAssembly/wasi-libc cd wasi-libc -git reset --hard 4362b1885fd369e042a7c0ecd8df3b6cd47fb4e8 +git reset --hard 7018e24d8fe248596819d2e884761676f3542a04 make -j$(nproc) \ CC="$bin/clang" \ NM="$bin/llvm-nm" \ diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml index a9e42e4a0a0..8907d643182 100644 --- a/src/ci/github-actions/ci.yml +++ b/src/ci/github-actions/ci.yml @@ -147,13 +147,6 @@ x--expand-yaml-anchors--remove: run: src/ci/scripts/verify-channel.sh <<: *step - - name: configure GitHub Actions to kill the build when outdated - uses: rust-lang/simpleinfra/github-actions/cancel-outdated-builds@master - with: - github_token: "${{ secrets.github_token }}" - if: success() && !env.SKIP_JOB && github.ref != 'refs/heads/try' && github.ref != 'refs/heads/try-perf' - <<: *step - - name: collect CPU statistics run: src/ci/scripts/collect-cpu-stats.sh <<: *step @@ -305,10 +298,14 @@ defaults: # shell is PowerShell.) shell: bash +concurrency: + # For a given workflow, if we push to the same PR, cancel all previous builds on that PR. + # If the push is not attached to a PR, we will cancel all builds related to the same commit SHA. + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + jobs: pr: - permissions: - actions: write # for rust-lang/simpleinfra/github-actions/cancel-outdated-builds <<: *base-ci-job name: PR - ${{ matrix.name }} env: @@ -331,8 +328,6 @@ jobs: <<: *job-linux-16c auto: - permissions: - actions: write # for rust-lang/simpleinfra/github-actions/cancel-outdated-builds <<: *base-ci-job name: auto - ${{ matrix.name }} env: @@ -734,8 +729,6 @@ jobs: <<: *job-windows-8c try: - permissions: - actions: write # for rust-lang/simpleinfra/github-actions/cancel-outdated-builds <<: *base-ci-job name: try - ${{ matrix.name }} env: diff --git a/src/doc/book b/src/doc/book -Subproject 8fa6b854d515506d825390fe0d817f5ef0c8935 +Subproject 21cf840842bdf768a798869f06373c96c1cc512 diff --git a/src/doc/nomicon b/src/doc/nomicon -Subproject b5f018fb5930cb733b0a8aaf2eed975d4771e74 +Subproject c369e4b489332f8721fbae630354fa83385d457 diff --git a/src/doc/reference b/src/doc/reference -Subproject 553d99b02a53b4133a40d5bd2e19958c67487c0 +Subproject 5ca365eac678cb0d41a20b3204546d6ed70c717 diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example -Subproject 8ee9528b72b927cff8fd32346db8bbd1198816f +Subproject 57636d6926762861f34e030d52ca25a71e95e5b diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide -Subproject f1e637883fafeb83bdd5906ee7f467e4d35b733 +Subproject 17fe3e948498c50e208047a750f17d6a8d89669 diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index 1e17a90a842..f8af26326a7 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -40,6 +40,7 @@ - [riscv32imac-unknown-xous-elf](platform-support/riscv32imac-unknown-xous-elf.md) - [*-pc-windows-gnullvm](platform-support/pc-windows-gnullvm.md) - [\*-nto-qnx-\*](platform-support/nto-qnx.md) + - [\*-unknown-netbsd\*](platform-support/netbsd.md) - [*-unknown-openbsd](platform-support/openbsd.md) - [\*-unknown-uefi](platform-support/unknown-uefi.md) - [wasm64-unknown-unknown](platform-support/wasm64-unknown-unknown.md) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 62f628f8229..6d1729e57b1 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -224,13 +224,14 @@ target | std | host | notes `aarch64-unknown-freebsd` | ✓ | ✓ | ARM64 FreeBSD `aarch64-unknown-hermit` | ✓ | | ARM64 HermitCore `aarch64-unknown-linux-gnu_ilp32` | ✓ | ✓ | ARM64 Linux (ILP32 ABI) -`aarch64-unknown-netbsd` | ✓ | ✓ | +[`aarch64-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | ARM64 NetBSD [`aarch64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | ARM64 OpenBSD `aarch64-unknown-redox` | ? | | ARM64 Redox OS `aarch64-uwp-windows-msvc` | ? | | `aarch64-wrs-vxworks` | ? | | `aarch64_be-unknown-linux-gnu_ilp32` | ✓ | ✓ | ARM64 Linux (big-endian, ILP32 ABI) `aarch64_be-unknown-linux-gnu` | ✓ | ✓ | ARM64 Linux (big-endian) +[`aarch64_be-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | ARM64 NetBSD (big-endian) [`arm64_32-apple-watchos`](platform-support/apple-watchos.md) | ✓ | | ARM Apple WatchOS 64-bit with 32-bit pointers [`armeb-unknown-linux-gnueabi`](platform-support/armeb-unknown-linux-gnueabi.md) | ✓ | ? | ARM BE8 the default ARM big-endian architecture since [ARMv6](https://developer.arm.com/documentation/101754/0616/armlink-Reference/armlink-Command-line-Options/--be8?lang=en). `armv4t-none-eabi` | * | | ARMv4T A32 @@ -238,7 +239,7 @@ target | std | host | notes [`armv5te-none-eabi`](platform-support/armv5te-none-eabi.md) | * | | ARMv5TE A32 `armv5te-unknown-linux-uclibceabi` | ? | | ARMv5TE Linux with uClibc `armv6-unknown-freebsd` | ✓ | ✓ | ARMv6 FreeBSD -`armv6-unknown-netbsd-eabihf` | ? | | +[`armv6-unknown-netbsd-eabihf`](platform-support/netbsd.md) | ✓ | ✓ | ARMv6 NetBSD w/hard-float [`armv6k-nintendo-3ds`](platform-support/armv6k-nintendo-3ds.md) | ? | | ARMv6K Nintendo 3DS, Horizon (Requires devkitARM toolchain) `armv7-apple-ios` | ✓ | | ARMv7 iOS, Cortex-a8 [`armv7-sony-vita-newlibeabihf`](platform-support/armv7-sony-vita-newlibeabihf.md) | ? | | ARM Cortex-A9 Sony PlayStation Vita (requires VITASDK toolchain) @@ -246,7 +247,7 @@ target | std | host | notes [`armv7-unknown-linux-uclibceabi`](platform-support/armv7-unknown-linux-uclibceabi.md) | ✓ | ✓ | ARMv7 Linux with uClibc, softfloat [`armv7-unknown-linux-uclibceabihf`](platform-support/armv7-unknown-linux-uclibceabihf.md) | ✓ | ? | ARMv7 Linux with uClibc, hardfloat `armv7-unknown-freebsd` | ✓ | ✓ | ARMv7 FreeBSD -`armv7-unknown-netbsd-eabihf` | ✓ | ✓ | +[`armv7-unknown-netbsd-eabihf`](platform-support/netbsd.md) | ✓ | ✓ | ARMv7 NetBSD w/hard-float `armv7-wrs-vxworks-eabihf` | ? | | [`armv7a-kmc-solid_asp3-eabi`](platform-support/kmc-solid.md) | ✓ | | ARM SOLID with TOPPERS/ASP3 [`armv7a-kmc-solid_asp3-eabihf`](platform-support/kmc-solid.md) | ✓ | | ARM SOLID with TOPPERS/ASP3, hardfloat @@ -262,7 +263,7 @@ target | std | host | notes `i686-apple-darwin` | ✓ | ✓ | 32-bit macOS (10.7+, Lion+) `i686-pc-windows-msvc` | * | | 32-bit Windows XP support `i686-unknown-haiku` | ✓ | ✓ | 32-bit Haiku -`i686-unknown-netbsd` | ✓ | ✓ | NetBSD/i386 with SSE2 +[`i686-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | NetBSD/i386 with SSE2 [`i686-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | 32-bit OpenBSD `i686-uwp-windows-gnu` | ? | | `i686-uwp-windows-msvc` | ? | | @@ -283,7 +284,7 @@ target | std | host | notes `msp430-none-elf` | * | | 16-bit MSP430 microcontrollers `powerpc-unknown-linux-gnuspe` | ✓ | | PowerPC SPE Linux `powerpc-unknown-linux-musl` | ? | | -`powerpc-unknown-netbsd` | ✓ | ✓ | +[`powerpc-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | NetBSD 32-bit powerpc systems `powerpc-unknown-openbsd` | ? | | `powerpc-wrs-vxworks-spe` | ? | | `powerpc-wrs-vxworks` | ? | | @@ -307,7 +308,7 @@ target | std | host | notes [`riscv64gc-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/riscv64 `s390x-unknown-linux-musl` | | | S390x Linux (kernel 3.2, MUSL) `sparc-unknown-linux-gnu` | ✓ | | 32-bit SPARC Linux -`sparc64-unknown-netbsd` | ✓ | ✓ | NetBSD/sparc64 +[`sparc64-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | NetBSD/sparc64 [`sparc64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/sparc64 `thumbv4t-none-eabi` | * | | ARMv4T T32 [`thumbv5te-none-eabi`](platform-support/armv5te-none-eabi.md) | * | | ARMv5TE T32 diff --git a/src/doc/rustc/src/platform-support/esp-idf.md b/src/doc/rustc/src/platform-support/esp-idf.md index 4bbe35709b0..8f630fa152c 100644 --- a/src/doc/rustc/src/platform-support/esp-idf.md +++ b/src/doc/rustc/src/platform-support/esp-idf.md @@ -13,10 +13,12 @@ Targets for the [ESP-IDF](https://github.com/espressif/esp-idf) development fram The target names follow this format: `$ARCH-esp-espidf`, where `$ARCH` specifies the target processor architecture. The following targets are currently defined: -| Target name | Target CPU(s) | Minimum ESP-IDF version | -|--------------------------------|-----------------------|-------------------------| -| `riscv32imc-esp-espidf` | [ESP32-C3](https://www.espressif.com/en/products/socs/esp32-c3) | `v4.3` | -| `riscv32imac-esp-espidf` | [ESP32-C6](https://www.espressif.com/en/products/socs/esp32-c6) | `v5.1` | +| Target name | Target CPU(s) | Minimum ESP-IDF version | +| ------------------------ | --------------------------------------------------------------- | ----------------------- | +| `riscv32imc-esp-espidf` | [ESP32-C2](https://www.espressif.com/en/products/socs/esp32-c2) | `v5.0` | +| `riscv32imc-esp-espidf` | [ESP32-C3](https://www.espressif.com/en/products/socs/esp32-c3) | `v4.3` | +| `riscv32imac-esp-espidf` | [ESP32-C6](https://www.espressif.com/en/products/socs/esp32-c6) | `v5.1` | +| `riscv32imac-esp-espidf` | [ESP32-H2](https://www.espressif.com/en/products/socs/esp32-h2) | `v5.1` | It is recommended to use the latest ESP-IDF stable release if possible. diff --git a/src/doc/rustc/src/platform-support/loongarch-linux.md b/src/doc/rustc/src/platform-support/loongarch-linux.md index 999e71f8028..17e85590f2c 100644 --- a/src/doc/rustc/src/platform-support/loongarch-linux.md +++ b/src/doc/rustc/src/platform-support/loongarch-linux.md @@ -28,9 +28,9 @@ While the integer base ABI is implied by the machine field, the floating po ## Target maintainers -- [ZHAI Xiaojuan](https://github.com/zhaixiaojuan) `zhaixiaojuan@loongson.cn` - [WANG Rui](https://github.com/heiher) `wangrui@loongson.cn` - [ZHAI Xiang](https://github.com/xiangzhai) `zhaixiang@loongson.cn` +- [ZHAI Xiaojuan](https://github.com/zhaixiaojuan) `zhaixiaojuan@loongson.cn` - [WANG Xuerui](https://github.com/xen0n) `git@xen0n.name` ## Requirements diff --git a/src/doc/rustc/src/platform-support/netbsd.md b/src/doc/rustc/src/platform-support/netbsd.md new file mode 100644 index 00000000000..a1969524a20 --- /dev/null +++ b/src/doc/rustc/src/platform-support/netbsd.md @@ -0,0 +1,107 @@ +# \*-unknown-netbsd + +**Tier: 3** + +[NetBSD] multi-platform 4.4BSD-based UNIX-like operating system. + +[NetBSD]: https://www.NetBSD.org/ + +The target names follow this format: `$ARCH-unknown-netbsd{-$SUFFIX}`, +where `$ARCH` specifies the target processor architecture and +`-$SUFFIX` (optional) might indicate the ABI. The following targets +are currently defined running NetBSD: + +| Target name | NetBSD Platform | +|--------------------------------|-----------------| +| `amd64-unknown-netbsd` | [amd64 / x86_64 systems](https://wiki.netbsd.org/ports/amd64/) | +| `armv7-unknown-netbsd-eabihf` | [32-bit ARMv7 systems with hard-float](https://wiki.netbsd.org/ports/evbarm/) | +| `armv6-unknown-netbsd-eabihf` | [32-bit ARMv6 systems with hard-float](https://wiki.netbsd.org/ports/evbarm/) | +| `aarch64-unknown-netbsd` | [64-bit ARM systems, little-endian](https://wiki.netbsd.org/ports/evbarm/) | +| `aarch64_be-unknown-netbsd` | [64-bit ARM systems, big-endian](https://wiki.netbsd.org/ports/evbarm/) | +| `i586-unknown-netbsd` | [32-bit i386, restricted to Pentium](https://wiki.netbsd.org/ports/i386/) | +| `i686-unknown-netbsd` | [32-bit i386 with SSE](https://wiki.netbsd.org/ports/i386/) | +| `mipsel-unknown-netbsd` | [32-bit mips, requires mips32 cpu support](https://wiki.netbsd.org/ports/evbmips/) | +| `powerpc-unknown-netbsd` | [Various 32-bit PowerPC systems, e.g. MacPPC](https://wiki.netbsd.org/ports/macppc/) | +| `sparc64-unknown-netbsd` | [Sun UltraSPARC systems](https://wiki.netbsd.org/ports/sparc64/) | + +All use the "native" `stdc++` library which goes along with the natively +supplied GNU C++ compiler for the given OS version. Many of the bootstraps +are built for NetBSD 9.x, although some exceptions exist (some +are built for NetBSD 8.x but also work on newer OS versions). + + +## Designated Developers + +- [@he32](https://github.com/he32), `he@NetBSD.org` +- [NetBSD/pkgsrc-wip's rust](https://github.com/NetBSD/pkgsrc-wip/blob/master/rust/Makefile) maintainer (see MAINTAINER variable). This package is part of "pkgsrc work-in-progress" and is used for deployment and testing of new versions of rust +- [NetBSD's pkgsrc lang/rust](https://github.com/NetBSD/pkgsrc/tree/trunk/lang/rust) for the "proper" package in pkgsrc. +- [NetBSD's pkgsrc lang/rust-bin](https://github.com/NetBSD/pkgsrc/tree/trunk/lang/rust-bin) which re-uses the bootstrap kit as a binary distribution and therefore avoids the rather protracted native build time of rust itself + +Fallback to pkgsrc-users@NetBSD.org, or fault reporting via NetBSD's +bug reporting system. + +## Requirements + +The `amd64-unknown-netbsd` artifacts is being distributed by the +rust project. + +The other targets are built by the designated developers (see above), +and the targets are initially cross-compiled, but many if not most +of them are also built natively as part of testing. + + +## Building + +The default build mode for the packages is a native build. + + +## Cross-compilation + +These targets can be cross-compiled, and we do that via the pkgsrc +package(s). + +Cross-compilation typically requires the "tools" and "dest" trees +resulting from a normal cross-build of NetBSD itself, ref. our main +build script, `build.sh`. + +See e.g. [do-cross.mk +Makefile](https://github.com/NetBSD/pkgsrc/tree/trunk/lang/rust/do-cross.mk) +for the Makefile used to cross-build all the above NetBSD targets +(except for the `amd64` target). + +The major option for the rust build is whether to build rust with +the LLVM rust carries in its distribution, or use the LLVM package +installed from pkgsrc. The `PKG_OPTIONS.rust` option is +`rust-internal-llvm`, ref. [the rust package's options.mk make +fragment](https://github.com/NetBSD/pkgsrc/blob/trunk/lang/rust/options.mk). +It defaults to being set for a few of the above platforms, for +various reasons (see comments), but is otherwise unset and therefore +indicates use of the pkgsrc LLVM. + + +## Testing + +The Rust testsuite could presumably be run natively. + +For the systems where the maintainer can build natively, the rust +compiler itself is re-built natively. This involves the rust compiler +being re-built with the newly self-built rust compiler, so excercises +the result quite extensively. + +Additionally, for some systems we build `librsvg`, and for the more +capable systems we build and test `firefox` (amd64, i386, aarch64). + + +## Building Rust programs + +Rust ships pre-compiled artifacts for the `amd64-unknown-netbsd` +target. + +For the other systems mentioned above, using the `pkgsrc` route is +probably the easiest, possibly via the `rust-bin` package to save +time, see the `RUST_TYPE` variable from the `rust.mk` Makefile +fragment. + +The pkgsrc rust package has a few files to assist with building +pkgsrc packages written in rust, ref. the `rust.mk` and `cargo.mk` +Makefile fragments in the `lang/rust` package. diff --git a/src/doc/style-guide/src/statements.md b/src/doc/style-guide/src/statements.md index 62a5a032f07..9bc521e1c7b 100644 --- a/src/doc/style-guide/src/statements.md +++ b/src/doc/style-guide/src/statements.md @@ -103,22 +103,69 @@ let Foo { #### else blocks (let-else statements) -If a let statement contains an `else` component, also known as a let-else statement, -then the `else` component should be formatted according to the same rules as the `else` block -in [control flow expressions (i.e. if-else, and if-let-else expressions)](./expressions.md#control-flow-expressions). -Apply the same formatting rules to the components preceding -the `else` block (i.e. the `let pattern: Type = initializer_expr ...` portion) -as described [above](#let-statements) - -Similarly to if-else expressions, if the initializer -expression is multi-lined, then the `else` keyword and opening brace of the block (i.e. `else {`) -should be put on the same line as the end of the initializer -expression with a preceding space if all the following are true: +A let statement can contain an `else` component, making it a let-else statement. +In this case, always apply the same formatting rules to the components preceding +the `else` block (i.e. the `let pattern: Type = initializer_expr` portion) +as described [for other let statements](#let-statements). + +The entire let-else statement may be formatted on a single line if all the +following are true: + +* the entire statement is *short* +* the `else` block contains only a single-line expression and no statements +* the `else` block contains no comments +* the let statement components preceding the `else` block can be formatted on a single line + +```rust +let Some(1) = opt else { return }; +``` + +Formatters may allow users to configure the value of the threshold +used to determine whether a let-else statement is *short*. + +Otherwise, the let-else statement requires some line breaks. + +If breaking a let-else statement across multiple lines, never break between the +`else` and the `{`, and always break before the `}`. + +If the let statement components preceding the `else` can be formatted on a +single line, but the let-else does not qualify to be placed entirely on a +single line, put the `else {` on the same line as the initializer expression, +with a space between them, then break the line after the `{`. Indent the +closing `}` to match the `let`, and indent the contained block one step +further. + +```rust +let Some(1) = opt else { + return; +}; + +let Some(1) = opt else { + // nope + return +}; +``` + +If the let statement components preceding the `else` can be formatted on a +single line, but the `else {` does not fit on the same line, break the line +before the `else`. + +```rust + let Some(x) = some_really_really_really_really_really_really_really_really_really_long_name + else { + return; + }; +``` + +If the initializer expression is multi-line, the `else` keyword and opening +brace of the block (i.e. `else {`) should be put on the same line as the end of +the initializer expression, with a space between them, if all the following are +true: * The initializer expression ends with one or more closing parentheses, square brackets, and/or braces * There is nothing else on that line -* That line is not indented beyond the indent of the first line containing the `let` keyword +* That line has the same indentation level as the initial `let` keyword. For example: @@ -135,7 +182,9 @@ let Some(x) = y.foo( } ``` -Otherwise, the `else` keyword and opening brace should be placed on the next line after the end of the initializer expression, and should not be indented (the `else` keyword should be aligned with the `let` keyword). +Otherwise, the `else` keyword and opening brace should be placed on the next +line after the end of the initializer expression, and the `else` keyword should +have the same indentation level as the `let` keyword. For example: @@ -155,11 +204,6 @@ fn main() { return }; - let Some(x) = some_really_really_really_really_really_really_really_really_really_long_name - else { - return; - }; - let Some(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) = bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb else { @@ -168,31 +212,6 @@ fn main() { } ``` -##### Single line let-else statements - -The entire let-else statement may be formatted on a single line if all the following are true: - -* the entire statement is *short* -* the `else` block contains a single-line expression and no statements -* the `else` block contains no comments -* the let statement components preceding the `else` block can be formatted on a single line - -```rust -let Some(1) = opt else { return }; - -let Some(1) = opt else { - return; -}; - -let Some(1) = opt else { - // nope - return -}; -``` - -Formatters may allow users to configure the value of the threshold -used to determine whether a let-else statement is *short*. - ### Macros in statement position A macro use in statement position should use parentheses or square brackets as diff --git a/src/etc/test-float-parse/runtests.py b/src/etc/test-float-parse/runtests.py index cf7279534dc..cc5e31a051f 100755 --- a/src/etc/test-float-parse/runtests.py +++ b/src/etc/test-float-parse/runtests.py @@ -127,7 +127,7 @@ def write_errors(): if not have_seen_error: have_seen_error = True msg("Something is broken:", *args) - msg("Future errors logged to errors.txt") + msg("Future errors will be logged to errors.txt") exit_status = 101 diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index 492b0b79557..92bae551644 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -317,14 +317,14 @@ where lifetime_predicates } - fn extract_for_generics(&self, pred: ty::Predicate<'tcx>) -> FxHashSet<GenericParamDef> { + fn extract_for_generics(&self, pred: ty::Clause<'tcx>) -> FxHashSet<GenericParamDef> { let bound_predicate = pred.kind(); let tcx = self.cx.tcx; let regions = match bound_predicate.skip_binder() { - ty::PredicateKind::Clause(ty::ClauseKind::Trait(poly_trait_pred)) => { + ty::ClauseKind::Trait(poly_trait_pred) => { tcx.collect_referenced_late_bound_regions(&bound_predicate.rebind(poly_trait_pred)) } - ty::PredicateKind::Clause(ty::ClauseKind::Projection(poly_proj_pred)) => { + ty::ClauseKind::Projection(poly_proj_pred) => { tcx.collect_referenced_late_bound_regions(&bound_predicate.rebind(poly_proj_pred)) } _ => return FxHashSet::default(), @@ -449,9 +449,7 @@ where .filter(|p| { !orig_bounds.contains(p) || match p.kind().skip_binder() { - ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => { - pred.def_id() == sized_trait - } + ty::ClauseKind::Trait(pred) => pred.def_id() == sized_trait, _ => false, } }) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index f86c32158e0..b2f9c0bccea 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -326,36 +326,24 @@ fn clean_where_predicate<'tcx>( } pub(crate) fn clean_predicate<'tcx>( - predicate: ty::Predicate<'tcx>, + predicate: ty::Clause<'tcx>, cx: &mut DocContext<'tcx>, ) -> Option<WherePredicate> { let bound_predicate = predicate.kind(); match bound_predicate.skip_binder() { - ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => { - clean_poly_trait_predicate(bound_predicate.rebind(pred), cx) - } - ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(pred)) => { - clean_region_outlives_predicate(pred) - } - ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(pred)) => { + ty::ClauseKind::Trait(pred) => clean_poly_trait_predicate(bound_predicate.rebind(pred), cx), + ty::ClauseKind::RegionOutlives(pred) => clean_region_outlives_predicate(pred), + ty::ClauseKind::TypeOutlives(pred) => { clean_type_outlives_predicate(bound_predicate.rebind(pred), cx) } - ty::PredicateKind::Clause(ty::ClauseKind::Projection(pred)) => { + ty::ClauseKind::Projection(pred) => { Some(clean_projection_predicate(bound_predicate.rebind(pred), cx)) } // FIXME(generic_const_exprs): should this do something? - ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..)) => None, - ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(..)) => None, - ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..)) => None, - - ty::PredicateKind::Subtype(..) - | ty::PredicateKind::AliasRelate(..) - | ty::PredicateKind::Coerce(..) - | ty::PredicateKind::ObjectSafe(..) - | ty::PredicateKind::ClosureKind(..) - | ty::PredicateKind::ConstEquate(..) - | ty::PredicateKind::Ambiguous - | ty::PredicateKind::TypeWellFormedFromEnv(..) => panic!("not user writable"), + ty::ClauseKind::ConstEvaluatable(..) + | ty::ClauseKind::WellFormed(..) + | ty::ClauseKind::ConstArgHasType(..) + | ty::ClauseKind::TypeWellFormedFromEnv(..) => None, } } @@ -791,10 +779,10 @@ fn clean_ty_generics<'tcx>( }) .collect::<ThinVec<GenericParamDef>>(); - // param index -> [(trait DefId, associated type name & generics, type, higher-ranked params)] + // param index -> [(trait DefId, associated type name & generics, term, higher-ranked params)] let mut impl_trait_proj = FxHashMap::< u32, - Vec<(DefId, PathSegment, ty::Binder<'_, Ty<'_>>, Vec<GenericParamDef>)>, + Vec<(DefId, PathSegment, ty::Binder<'_, ty::Term<'_>>, Vec<GenericParamDef>)>, >::default(); let where_predicates = preds @@ -805,19 +793,17 @@ fn clean_ty_generics<'tcx>( let param_idx = (|| { let bound_p = p.kind(); match bound_p.skip_binder() { - ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => { + ty::ClauseKind::Trait(pred) => { if let ty::Param(param) = pred.self_ty().kind() { return Some(param.index); } } - ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives( - ty::OutlivesPredicate(ty, _reg), - )) => { + ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty, _reg)) => { if let ty::Param(param) = ty.kind() { return Some(param.index); } } - ty::PredicateKind::Clause(ty::ClauseKind::Projection(p)) => { + ty::ClauseKind::Projection(p) => { if let ty::Param(param) = p.projection_ty.self_ty().kind() { projection = Some(bound_p.rebind(p)); return Some(param.index); @@ -852,11 +838,10 @@ fn clean_ty_generics<'tcx>( .as_ref() .and_then(|(lhs, rhs): &(Type, _)| Some((lhs.projection()?, rhs))) { - // FIXME(...): Remove this unwrap() impl_trait_proj.entry(param_idx).or_default().push(( trait_did, name, - rhs.map_bound(|rhs| rhs.ty().unwrap()), + *rhs, p.get_bound_params() .into_iter() .flatten() @@ -879,15 +864,8 @@ fn clean_ty_generics<'tcx>( let crate::core::ImplTraitParam::ParamIndex(idx) = param else { unreachable!() }; if let Some(proj) = impl_trait_proj.remove(&idx) { for (trait_did, name, rhs, bound_params) in proj { - let rhs = clean_middle_ty(rhs, cx, None, None); - simplify::merge_bounds( - cx, - &mut bounds, - bound_params, - trait_did, - name, - &Term::Type(rhs), - ); + let rhs = clean_middle_term(rhs, cx); + simplify::merge_bounds(cx, &mut bounds, bound_params, trait_did, name, &rhs); } } @@ -1360,21 +1338,51 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( } } + let mut predicates = tcx.explicit_predicates_of(assoc_item.def_id).predicates; if let ty::TraitContainer = assoc_item.container { - let bounds = tcx - .explicit_item_bounds(assoc_item.def_id) - .subst_identity_iter_copied() - .map(|(c, s)| (c.as_predicate(), s)); - let predicates = tcx.explicit_predicates_of(assoc_item.def_id).predicates; - let predicates = - tcx.arena.alloc_from_iter(bounds.chain(predicates.iter().copied())); - let mut generics = clean_ty_generics( - cx, - tcx.generics_of(assoc_item.def_id), - ty::GenericPredicates { parent: None, predicates }, - ); - // Filter out the bounds that are (likely?) directly attached to the associated type, - // as opposed to being located in the where clause. + let bounds = + tcx.explicit_item_bounds(assoc_item.def_id).subst_identity_iter_copied(); + predicates = tcx.arena.alloc_from_iter(bounds.chain(predicates.iter().copied())); + } + let mut generics = clean_ty_generics( + cx, + tcx.generics_of(assoc_item.def_id), + ty::GenericPredicates { parent: None, predicates }, + ); + // Move bounds that are (likely) directly attached to the parameters of the + // (generic) associated type from the where clause to the respective parameter. + // There is no guarantee that this is what the user actually wrote but we have + // no way of knowing. + let mut where_predicates = ThinVec::new(); + for mut pred in generics.where_predicates { + if let WherePredicate::BoundPredicate { ty: Generic(arg), bounds, .. } = &mut pred + && let Some(GenericParamDef { + kind: GenericParamDefKind::Type { bounds: param_bounds, .. }, + .. + }) = generics.params.iter_mut().find(|param| ¶m.name == arg) + { + param_bounds.append(bounds); + } else if let WherePredicate::RegionPredicate { lifetime: Lifetime(arg), bounds } = &mut pred + && let Some(GenericParamDef { + kind: GenericParamDefKind::Lifetime { outlives: param_bounds }, + .. + }) = generics.params.iter_mut().find(|param| ¶m.name == arg) + { + param_bounds.extend(bounds.drain(..).map(|bound| match bound { + GenericBound::Outlives(lifetime) => lifetime, + _ => unreachable!(), + })); + } else { + where_predicates.push(pred); + } + } + generics.where_predicates = where_predicates; + + if let ty::TraitContainer = assoc_item.container { + // Move bounds that are (likely) directly attached to the associated type + // from the where-clause to the associated type. + // There is no guarantee that this is what the user actually wrote but we have + // no way of knowing. let mut bounds: Vec<GenericBound> = Vec::new(); generics.where_predicates.retain_mut(|pred| match *pred { WherePredicate::BoundPredicate { @@ -1431,33 +1439,6 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( } None => bounds.push(GenericBound::maybe_sized(cx)), } - // Move bounds that are (likely) directly attached to the parameters of the - // (generic) associated type from the where clause to the respective parameter. - // There is no guarantee that this is what the user actually wrote but we have - // no way of knowing. - let mut where_predicates = ThinVec::new(); - for mut pred in generics.where_predicates { - if let WherePredicate::BoundPredicate { ty: Generic(arg), bounds, .. } = &mut pred - && let Some(GenericParamDef { - kind: GenericParamDefKind::Type { bounds: param_bounds, .. }, - .. - }) = generics.params.iter_mut().find(|param| ¶m.name == arg) - { - param_bounds.append(bounds); - } else if let WherePredicate::RegionPredicate { lifetime: Lifetime(arg), bounds } = &mut pred - && let Some(GenericParamDef { - kind: GenericParamDefKind::Lifetime { outlives: param_bounds }, - .. - }) = generics.params.iter_mut().find(|param| ¶m.name == arg) { - param_bounds.extend(bounds.drain(..).map(|bound| match bound { - GenericBound::Outlives(lifetime) => lifetime, - _ => unreachable!(), - })); - } else { - where_predicates.push(pred); - } - } - generics.where_predicates = where_predicates; if tcx.defaultness(assoc_item.def_id).has_value() { AssocTypeItem( @@ -1469,7 +1450,6 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( None, ), generics, - // FIXME: should we obtain the Type from HIR and pass it on here? item_type: None, }), bounds, @@ -1478,7 +1458,6 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( TyAssocTypeItem(generics, bounds) } } else { - // FIXME: when could this happen? Associated items in inherent impls? AssocTypeItem( Box::new(Typedef { type_: clean_middle_ty( @@ -1487,12 +1466,11 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( Some(assoc_item.def_id), None, ), - generics: Generics { - params: ThinVec::new(), - where_predicates: ThinVec::new(), - }, + generics, item_type: None, }), + // Associated types inside trait or inherent impls are not allowed to have + // item bounds. Thus we don't attempt to move any bounds there. Vec::new(), ) } @@ -2377,7 +2355,7 @@ fn filter_tokens_from_list( tokens } -/// When inlining items, we merge its attributes (and all the reexports attributes too) with the +/// When inlining items, we merge their attributes (and all the reexports attributes too) with the /// final reexport. For example: /// /// ```ignore (just an example) diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs index a8221cc9449..65b1b72adc1 100644 --- a/src/librustdoc/clean/simplify.rs +++ b/src/librustdoc/clean/simplify.rs @@ -128,9 +128,7 @@ fn trait_is_same_or_supertrait(cx: &DocContext<'_>, child: DefId, trait_: DefId) .predicates .iter() .filter_map(|(pred, _)| { - if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) = - pred.kind().skip_binder() - { + if let ty::ClauseKind::Trait(pred) = pred.kind().skip_binder() { if pred.trait_ref.self_ty() == self_ty { Some(pred.def_id()) } else { None } } else { None diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 5f5cade67a2..26139d52769 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -956,6 +956,8 @@ pub(crate) trait AttributesExt { .filter_map(|attr| Cfg::parse(attr.meta_item()?).ok()) .fold(Cfg::True, |cfg, new_cfg| cfg & new_cfg) } else if doc_auto_cfg_active { + // If there is no `doc(cfg())`, then we retrieve the `cfg()` attributes (because + // `doc(cfg())` overrides `cfg()`). self.iter() .filter(|attr| attr.has_name(sym::cfg)) .filter_map(|attr| single(attr.meta_item_list()?)) @@ -2387,6 +2389,7 @@ impl ImplKind { #[derive(Clone, Debug)] pub(crate) struct Import { pub(crate) kind: ImportKind, + /// The item being re-exported. pub(crate) source: ImportSource, pub(crate) should_be_displayed: bool, } diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 9f08609a6d1..217f1a6ee6b 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -15,6 +15,7 @@ use rustc_session::config::{ use rustc_session::getopts; use rustc_session::lint::Level; use rustc_session::search_paths::SearchPath; +use rustc_session::EarlyErrorHandler; use rustc_span::edition::Edition; use rustc_target::spec::TargetTriple; @@ -311,32 +312,33 @@ impl Options { /// Parses the given command-line for options. If an error message or other early-return has /// been printed, returns `Err` with the exit code. pub(crate) fn from_matches( + handler: &mut EarlyErrorHandler, matches: &getopts::Matches, args: Vec<String>, ) -> Result<(Options, RenderOptions), i32> { // Check for unstable options. - nightly_options::check_nightly_options(matches, &opts()); + nightly_options::check_nightly_options(handler, matches, &opts()); if args.is_empty() || matches.opt_present("h") || matches.opt_present("help") { crate::usage("rustdoc"); return Err(0); } else if matches.opt_present("version") { - rustc_driver::version!("rustdoc", matches); + rustc_driver::version!(&handler, "rustdoc", matches); return Err(0); } - if rustc_driver::describe_flag_categories(&matches) { + if rustc_driver::describe_flag_categories(handler, &matches) { return Err(0); } - let color = config::parse_color(matches); + let color = config::parse_color(handler, matches); let config::JsonConfig { json_rendered, json_unused_externs, .. } = - config::parse_json(matches); - let error_format = config::parse_error_format(matches, color, json_rendered); + config::parse_json(handler, matches); + let error_format = config::parse_error_format(handler, matches, color, json_rendered); let diagnostic_width = matches.opt_get("diagnostic-width").unwrap_or_default(); - let codegen_options = CodegenOptions::build(matches, error_format); - let unstable_opts = UnstableOptions::build(matches, error_format); + let codegen_options = CodegenOptions::build(handler, matches); + let unstable_opts = UnstableOptions::build(handler, matches); let diag = new_handler(error_format, None, diagnostic_width, &unstable_opts); @@ -393,8 +395,7 @@ impl Options { && !matches.opt_present("show-coverage") && !nightly_options::is_unstable_enabled(matches) { - rustc_session::early_error( - error_format, + handler.early_error( "the -Z unstable-options flag must be passed to enable --output-format for documentation generation (see https://github.com/rust-lang/rust/issues/76578)", ); } @@ -432,7 +433,7 @@ impl Options { return Err(0); } - let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format); + let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(handler, matches); let input = PathBuf::from(if describe_lints { "" // dummy, this won't be used @@ -446,12 +447,9 @@ impl Options { &matches.free[0] }); - let libs = matches - .opt_strs("L") - .iter() - .map(|s| SearchPath::from_cli_opt(s, error_format)) - .collect(); - let externs = parse_externs(matches, &unstable_opts, error_format); + let libs = + matches.opt_strs("L").iter().map(|s| SearchPath::from_cli_opt(handler, s)).collect(); + let externs = parse_externs(handler, matches, &unstable_opts); let extern_html_root_urls = match parse_extern_html_roots(matches) { Ok(ex) => ex, Err(err) => { @@ -589,7 +587,7 @@ impl Options { } } - let edition = config::parse_crate_edition(matches); + let edition = config::parse_crate_edition(handler, matches); let mut id_map = html::markdown::IdMap::new(); let Some(external_html) = ExternalHtml::load( @@ -623,7 +621,7 @@ impl Options { } } - let target = parse_target_triple(matches, error_format); + let target = parse_target_triple(handler, matches); let show_coverage = matches.opt_present("show-coverage"); diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index e10a6297775..9687b8b1887 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -13,8 +13,8 @@ use rustc_interface::interface; use rustc_middle::hir::nested_filter; use rustc_middle::ty::{ParamEnv, Ty, TyCtxt}; use rustc_session::config::{self, CrateType, ErrorOutputType, ResolveDocLinks}; -use rustc_session::lint; use rustc_session::Session; +use rustc_session::{lint, EarlyErrorHandler}; use rustc_span::symbol::sym; use rustc_span::{source_map, Span}; @@ -181,6 +181,7 @@ pub(crate) fn new_handler( /// Parse, resolve, and typecheck the given crate. pub(crate) fn create_config( + handler: &EarlyErrorHandler, RustdocOptions { input, crate_name, @@ -258,8 +259,8 @@ pub(crate) fn create_config( interface::Config { opts: sessopts, - crate_cfg: interface::parse_cfgspecs(cfgs), - crate_check_cfg: interface::parse_check_cfg(check_cfgs), + crate_cfg: interface::parse_cfgspecs(handler, cfgs), + crate_check_cfg: interface::parse_check_cfg(handler, check_cfgs), input, output_file: None, output_dir: None, diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index f6631b66f5b..217257316c8 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -12,7 +12,7 @@ use rustc_parse::maybe_new_parser_from_source_str; use rustc_parse::parser::attr::InnerAttrPolicy; use rustc_session::config::{self, CrateType, ErrorOutputType}; use rustc_session::parse::ParseSess; -use rustc_session::{lint, Session}; +use rustc_session::{lint, EarlyErrorHandler, Session}; use rustc_span::edition::Edition; use rustc_span::source_map::SourceMap; use rustc_span::symbol::sym; @@ -85,13 +85,18 @@ pub(crate) fn run(options: RustdocOptions) -> Result<(), ErrorGuaranteed> { ..config::Options::default() }; + let early_error_handler = EarlyErrorHandler::new(ErrorOutputType::default()); + let mut cfgs = options.cfgs.clone(); cfgs.push("doc".to_owned()); cfgs.push("doctest".to_owned()); let config = interface::Config { opts: sessopts, - crate_cfg: interface::parse_cfgspecs(cfgs), - crate_check_cfg: interface::parse_check_cfg(options.check_cfgs.clone()), + crate_cfg: interface::parse_cfgspecs(&early_error_handler, cfgs), + crate_check_cfg: interface::parse_check_cfg( + &early_error_handler, + options.check_cfgs.clone(), + ), input, output_file: None, output_dir: None, diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index b710311c858..b4aba2993c7 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -1408,7 +1408,7 @@ impl clean::FnDecl { let amp = if f.alternate() { "&" } else { "&" }; write!(f, "(")?; - if let Some(n) = line_wrapping_indent { + if let Some(n) = line_wrapping_indent && !self.inputs.values.is_empty() { write!(f, "\n{}", Indent(n + 4))?; } for (i, input) in self.inputs.values.iter().enumerate() { diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 21c1eb631e0..b6d90091bba 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -891,8 +891,10 @@ so that we can apply CSS-filters to change the arrow color in themes */ color: var(--search-results-grey-color); } .search-results .result-name .typename { + display: inline-block; color: var(--search-results-grey-color); font-size: 0.875rem; + width: 6.25rem; } .popover { diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 452348dc865..b8cc0a6db71 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -52,9 +52,9 @@ const longItemTypes = [ "enum variant", "macro", "primitive type", - "associated type", + "assoc type", "constant", - "associated constant", + "assoc const", "union", "foreign type", "keyword", diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index a8cd0ec453e..f28deae791a 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -79,8 +79,7 @@ use rustc_errors::ErrorGuaranteed; use rustc_interface::interface; use rustc_middle::ty::TyCtxt; use rustc_session::config::{make_crate_type_option, ErrorOutputType, RustcOptGroup}; -use rustc_session::getopts; -use rustc_session::{early_error, early_warn}; +use rustc_session::{getopts, EarlyErrorHandler}; use crate::clean::utils::DOC_RUST_LANG_ORG_CHANNEL; @@ -155,6 +154,8 @@ pub fn main() { } } + let mut handler = EarlyErrorHandler::new(ErrorOutputType::default()); + rustc_driver::install_ice_hook( "https://github.com/rust-lang/rust/issues/new\ ?labels=C-bug%2C+I-ICE%2C+T-rustdoc&template=ice.md", @@ -170,11 +171,12 @@ pub fn main() { // NOTE: The reason this doesn't show double logging when `download-rustc = false` and // `debug_logging = true` is because all rustc logging goes to its version of tracing (the one // in the sysroot), and all of rustdoc's logging goes to its version (the one in Cargo.toml). - init_logging(); - rustc_driver::init_env_logger("RUSTDOC_LOG"); - let exit_code = rustc_driver::catch_with_exit_code(|| match get_args() { - Some(args) => main_args(&args), + init_logging(&handler); + rustc_driver::init_env_logger(&handler, "RUSTDOC_LOG"); + + let exit_code = rustc_driver::catch_with_exit_code(|| match get_args(&handler) { + Some(args) => main_args(&mut handler, &args), _ => { #[allow(deprecated)] @@ -184,22 +186,19 @@ pub fn main() { process::exit(exit_code); } -fn init_logging() { +fn init_logging(handler: &EarlyErrorHandler) { let color_logs = match std::env::var("RUSTDOC_LOG_COLOR").as_deref() { Ok("always") => true, Ok("never") => false, Ok("auto") | Err(VarError::NotPresent) => io::stdout().is_terminal(), - Ok(value) => early_error( - ErrorOutputType::default(), - format!("invalid log color value '{}': expected one of always, never, or auto", value), - ), - Err(VarError::NotUnicode(value)) => early_error( - ErrorOutputType::default(), - format!( - "invalid log color value '{}': expected one of always, never, or auto", - value.to_string_lossy() - ), - ), + Ok(value) => handler.early_error(format!( + "invalid log color value '{}': expected one of always, never, or auto", + value + )), + Err(VarError::NotUnicode(value)) => handler.early_error(format!( + "invalid log color value '{}': expected one of always, never, or auto", + value.to_string_lossy() + )), }; let filter = tracing_subscriber::EnvFilter::from_env("RUSTDOC_LOG"); let layer = tracing_tree::HierarchicalLayer::default() @@ -219,16 +218,13 @@ fn init_logging() { tracing::subscriber::set_global_default(subscriber).unwrap(); } -fn get_args() -> Option<Vec<String>> { +fn get_args(handler: &EarlyErrorHandler) -> Option<Vec<String>> { env::args_os() .enumerate() .map(|(i, arg)| { arg.into_string() .map_err(|arg| { - early_warn( - ErrorOutputType::default(), - format!("Argument {} is not valid Unicode: {:?}", i, arg), - ); + handler.early_warn(format!("Argument {} is not valid Unicode: {:?}", i, arg)); }) .ok() }) @@ -710,7 +706,7 @@ fn run_renderer<'tcx, T: formats::FormatRenderer<'tcx>>( } } -fn main_args(at_args: &[String]) -> MainResult { +fn main_args(handler: &mut EarlyErrorHandler, at_args: &[String]) -> MainResult { // Throw away the first argument, the name of the binary. // In case of at_args being empty, as might be the case by // passing empty argument array to execve under some platforms, @@ -721,7 +717,7 @@ fn main_args(at_args: &[String]) -> MainResult { // the compiler with @empty_file as argv[0] and no more arguments. let at_args = at_args.get(1..).unwrap_or_default(); - let args = rustc_driver::args::arg_expand_all(at_args); + let args = rustc_driver::args::arg_expand_all(handler, at_args); let mut options = getopts::Options::new(); for option in opts() { @@ -730,13 +726,13 @@ fn main_args(at_args: &[String]) -> MainResult { let matches = match options.parse(&args) { Ok(m) => m, Err(err) => { - early_error(ErrorOutputType::default(), err.to_string()); + handler.early_error(err.to_string()); } }; // Note that we discard any distinction between different non-zero exit // codes from `from_matches` here. - let (options, render_options) = match config::Options::from_matches(&matches, args) { + let (options, render_options) = match config::Options::from_matches(handler, &matches, args) { Ok(opts) => opts, Err(code) => { return if code == 0 { @@ -764,7 +760,7 @@ fn main_args(at_args: &[String]) -> MainResult { (false, true) => { let input = options.input.clone(); let edition = options.edition; - let config = core::create_config(options, &render_options); + let config = core::create_config(handler, options, &render_options); // `markdown::render` can invoke `doctest::make_test`, which // requires session globals and a thread pool, so we use @@ -797,7 +793,7 @@ fn main_args(at_args: &[String]) -> MainResult { let scrape_examples_options = options.scrape_examples_options.clone(); let bin_crate = options.bin_crate; - let config = core::create_config(options, &render_options); + let config = core::create_config(handler, options, &render_options); interface::run_compiler(config, |compiler| { let sess = compiler.session(); diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs index ee6aef71980..1ecaa1a123c 100644 --- a/src/tools/clippy/clippy_lints/src/dereference.rs +++ b/src/tools/clippy/clippy_lints/src/dereference.rs @@ -27,7 +27,7 @@ use rustc_middle::mir::{Rvalue, StatementKind}; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability}; use rustc_middle::ty::{ self, Binder, BoundVariableKind, ClauseKind, EarlyBinder, FnSig, GenericArgKind, List, ParamEnv, ParamTy, - PredicateKind, ProjectionPredicate, Ty, TyCtxt, TypeVisitableExt, TypeckResults, + ProjectionPredicate, Ty, TyCtxt, TypeVisitableExt, TypeckResults, }; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::{symbol::sym, Span, Symbol}; @@ -1133,7 +1133,7 @@ fn needless_borrow_impl_arg_position<'tcx>( let projection_predicates = predicates .iter() .filter_map(|predicate| { - if let PredicateKind::Clause(ClauseKind::Projection(projection_predicate)) = predicate.kind().skip_binder() { + if let ClauseKind::Projection(projection_predicate) = predicate.kind().skip_binder() { Some(projection_predicate) } else { None @@ -1147,7 +1147,7 @@ fn needless_borrow_impl_arg_position<'tcx>( if predicates .iter() .filter_map(|predicate| { - if let PredicateKind::Clause(ClauseKind::Trait(trait_predicate)) = predicate.kind().skip_binder() + if let ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder() && trait_predicate.trait_ref.self_ty() == param_ty.to_ty(cx.tcx) { Some(trait_predicate.trait_ref.def_id) @@ -1209,7 +1209,7 @@ fn needless_borrow_impl_arg_position<'tcx>( } predicates.iter().all(|predicate| { - if let PredicateKind::Clause(ClauseKind::Trait(trait_predicate)) = predicate.kind().skip_binder() + if let ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder() && cx.tcx.is_diagnostic_item(sym::IntoIterator, trait_predicate.trait_ref.def_id) && let ty::Param(param_ty) = trait_predicate.self_ty().kind() && let GenericArgKind::Type(ty) = substs_with_referent_ty[param_ty.index as usize].unpack() diff --git a/src/tools/clippy/clippy_lints/src/derive.rs b/src/tools/clippy/clippy_lints/src/derive.rs index 8d84e756ff8..10a2f0cb1e7 100644 --- a/src/tools/clippy/clippy_lints/src/derive.rs +++ b/src/tools/clippy/clippy_lints/src/derive.rs @@ -14,8 +14,8 @@ use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::nested_filter; use rustc_middle::traits::Reveal; use rustc_middle::ty::{ - self, Binder, BoundConstness, ClauseKind, GenericArgKind, GenericParamDefKind, ImplPolarity, ParamEnv, PredicateKind, - TraitPredicate, Ty, TyCtxt, + self, BoundConstness, ClauseKind, GenericArgKind, GenericParamDefKind, ImplPolarity, ParamEnv, + ToPredicate, TraitPredicate, Ty, TyCtxt, }; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::def_id::LocalDefId; @@ -503,7 +503,7 @@ fn param_env_for_derived_eq(tcx: TyCtxt<'_>, did: DefId, eq_trait_id: DefId) -> let ty_predicates = tcx.predicates_of(did).predicates; for (p, _) in ty_predicates { - if let PredicateKind::Clause(ClauseKind::Trait(p)) = p.kind().skip_binder() + if let ClauseKind::Trait(p) = p.kind().skip_binder() && p.trait_ref.def_id == eq_trait_id && let ty::Param(self_ty) = p.trait_ref.self_ty().kind() && p.constness == BoundConstness::NotConst @@ -514,13 +514,13 @@ fn param_env_for_derived_eq(tcx: TyCtxt<'_>, did: DefId, eq_trait_id: DefId) -> } ParamEnv::new( - tcx.mk_predicates_from_iter(ty_predicates.iter().map(|&(p, _)| p).chain( + tcx.mk_clauses_from_iter(ty_predicates.iter().map(|&(p, _)| p).chain( params.iter().filter(|&&(_, needs_eq)| needs_eq).map(|&(param, _)| { - tcx.mk_predicate(Binder::dummy(PredicateKind::Clause(ClauseKind::Trait(TraitPredicate { + ClauseKind::Trait(TraitPredicate { trait_ref: ty::TraitRef::new(tcx, eq_trait_id, [tcx.mk_param_from_def(param)]), constness: BoundConstness::NotConst, polarity: ImplPolarity::Positive, - })))) + }).to_predicate(tcx) }), )), Reveal::UserFacing, diff --git a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs index 5f1fdf00be8..10b5e1edf92 100644 --- a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs @@ -206,6 +206,12 @@ fn never_loop_expr(expr: &Expr<'_>, ignore_ids: &mut Vec<HirId>, main_loop_id: H NeverLoopResult::AlwaysBreak, ) }), + ExprKind::Become(e) => { + combine_seq( + never_loop_expr(e, ignore_ids, main_loop_id), + NeverLoopResult::AlwaysBreak, + ) + } ExprKind::InlineAsm(asm) => asm .operands .iter() diff --git a/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs b/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs index 7945275393c..93ef07d36ae 100644 --- a/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs +++ b/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs @@ -329,6 +329,7 @@ impl<'a, 'tcx> Visitor<'tcx> for SigDropHelper<'a, 'tcx> { ExprKind::Field(..) | ExprKind::Index(..) | ExprKind::Ret(..) | + ExprKind::Become(..) | ExprKind::Repeat(..) | ExprKind::Yield(..) => walk_expr(self, ex), ExprKind::AddrOf(_, _, _) | diff --git a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs index cf85d3174db..0699997d0d2 100644 --- a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs +++ b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs @@ -16,7 +16,7 @@ use rustc_hir::{ }; use rustc_lint::LateContext; use rustc_middle::hir::nested_filter; -use rustc_middle::ty::{self, AssocKind, ClauseKind, EarlyBinder, GenericArg, GenericArgKind, PredicateKind, Ty}; +use rustc_middle::ty::{self, AssocKind, ClauseKind, EarlyBinder, GenericArg, GenericArgKind, Ty}; use rustc_span::symbol::Ident; use rustc_span::{sym, Span, Symbol}; @@ -175,7 +175,7 @@ fn check_collect_into_intoiterator<'tcx>( .caller_bounds() .into_iter() .filter_map(|p| { - if let PredicateKind::Clause(ClauseKind::Trait(t)) = p.kind().skip_binder() + if let ClauseKind::Trait(t) = p.kind().skip_binder() && cx.tcx.is_diagnostic_item(sym::IntoIterator,t.trait_ref.def_id) { Some(t.self_ty()) } else { diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs index 06fa95cd657..80eb00a1b42 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs @@ -14,7 +14,7 @@ use rustc_lint::LateContext; use rustc_middle::mir::Mutability; use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref}; use rustc_middle::ty::subst::{GenericArg, GenericArgKind, SubstsRef}; -use rustc_middle::ty::{self, ClauseKind, EarlyBinder, ParamTy, PredicateKind, ProjectionPredicate, TraitPredicate, Ty}; +use rustc_middle::ty::{self, ClauseKind, EarlyBinder, ParamTy, ProjectionPredicate, TraitPredicate, Ty}; use rustc_span::{sym, Symbol}; use rustc_trait_selection::traits::{query::evaluate_obligation::InferCtxtExt as _, Obligation, ObligationCause}; @@ -345,12 +345,12 @@ fn get_input_traits_and_projections<'tcx>( let mut projection_predicates = Vec::new(); for predicate in cx.tcx.param_env(callee_def_id).caller_bounds() { match predicate.kind().skip_binder() { - PredicateKind::Clause(ClauseKind::Trait(trait_predicate)) => { + ClauseKind::Trait(trait_predicate) => { if trait_predicate.trait_ref.self_ty() == input { trait_predicates.push(trait_predicate); } }, - PredicateKind::Clause(ClauseKind::Projection(projection_predicate)) => { + ClauseKind::Projection(projection_predicate) => { if projection_predicate.projection_ty.self_ty() == input { projection_predicates.push(projection_predicate); } @@ -407,7 +407,7 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty< let mut trait_predicates = cx.tcx.param_env(callee_def_id) .caller_bounds().iter().filter(|predicate| { - if let PredicateKind::Clause(ClauseKind::Trait(trait_predicate)) + if let ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder() && trait_predicate.trait_ref.self_ty() == *param_ty { diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs index 3773975e955..c0970048cdf 100644 --- a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs +++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs @@ -126,7 +126,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { .filter_map(|pred| { // Note that we do not want to deal with qualified predicates here. match pred.kind().no_bound_vars() { - Some(ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred))) if pred.def_id() != sized_trait => { + Some(ty::ClauseKind::Trait(pred)) if pred.def_id() != sized_trait => { Some(pred) }, _ => None, diff --git a/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs b/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs index a375e5d5b4c..99a1d197678 100644 --- a/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs +++ b/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs @@ -4,7 +4,7 @@ use rustc_hir::def_id::DefId; use rustc_hir::{Closure, Expr, ExprKind, StmtKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; -use rustc_middle::ty::{ClauseKind, GenericPredicates, PredicateKind, ProjectionPredicate, TraitPredicate}; +use rustc_middle::ty::{ClauseKind, GenericPredicates, ProjectionPredicate, TraitPredicate}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::{sym, BytePos, Span}; @@ -45,7 +45,7 @@ fn get_trait_predicates_for_trait_id<'tcx>( let mut preds = Vec::new(); for (pred, _) in generics.predicates { if_chain! { - if let PredicateKind::Clause(ClauseKind::Trait(poly_trait_pred)) = pred.kind().skip_binder(); + if let ClauseKind::Trait(poly_trait_pred) = pred.kind().skip_binder(); let trait_pred = cx.tcx.erase_late_bound_regions(pred.kind().rebind(poly_trait_pred)); if let Some(trait_def_id) = trait_id; if trait_def_id == trait_pred.trait_ref.def_id; @@ -63,7 +63,7 @@ fn get_projection_pred<'tcx>( trait_pred: TraitPredicate<'tcx>, ) -> Option<ProjectionPredicate<'tcx>> { generics.predicates.iter().find_map(|(proj_pred, _)| { - if let ty::PredicateKind::Clause(ClauseKind::Projection(pred)) = proj_pred.kind().skip_binder() { + if let ClauseKind::Projection(pred) = proj_pred.kind().skip_binder() { let projection_pred = cx.tcx.erase_late_bound_regions(proj_pred.kind().rebind(pred)); if projection_pred.projection_ty.substs == trait_pred.trait_ref.substs { return Some(projection_pred); diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs index 3c2bf5abab2..6b51974d739 100644 --- a/src/tools/clippy/clippy_lints/src/utils/author.rs +++ b/src/tools/clippy/clippy_lints/src/utils/author.rs @@ -559,6 +559,11 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { kind!("Ret({value})"); value.if_some(|e| self.expr(e)); }, + ExprKind::Become(value) => { + bind!(self, value); + kind!("Become({value})"); + self.expr(value); + }, ExprKind::InlineAsm(_) => { kind!("InlineAsm(_)"); out!("// unimplemented: `ExprKind::InlineAsm` is not further destructured at the moment"); diff --git a/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs b/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs index 941df3318ae..659c693f87a 100644 --- a/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs +++ b/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs @@ -15,7 +15,7 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::{walk_expr, Visitor}; use rustc_hir::{def_id::DefId, Block, Expr, ExprKind, QPath, UnOp}; use rustc_lint::LateContext; -use rustc_middle::ty::{self, PredicateKind}; +use rustc_middle::ty; use rustc_span::{sym, Symbol}; use std::cmp; use std::ops; @@ -73,7 +73,7 @@ fn fn_eagerness(cx: &LateContext<'_>, fn_id: DefId, name: Symbol, have_one_arg: .flat_map(|v| v.fields.iter()) .any(|x| matches!(cx.tcx.type_of(x.did).subst_identity().peel_refs().kind(), ty::Param(_))) && all_predicates_of(cx.tcx, fn_id).all(|(pred, _)| match pred.kind().skip_binder() { - PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => cx.tcx.trait_def(pred.trait_ref.def_id).is_marker, + ty::ClauseKind::Trait(pred) => cx.tcx.trait_def(pred.trait_ref.def_id).is_marker, _ => true, }) && subs.types().all(|x| matches!(x.peel_refs().kind(), ty::Param(_))) @@ -191,6 +191,7 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS ExprKind::Break(..) | ExprKind::Continue(_) | ExprKind::Ret(_) + | ExprKind::Become(_) | ExprKind::InlineAsm(_) | ExprKind::Yield(..) | ExprKind::Err(_) => { diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index a49246a7832..3e1d7356414 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -845,6 +845,9 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { self.hash_expr(e); } }, + ExprKind::Become(f) => { + self.hash_expr(f); + }, ExprKind::Path(ref qpath) => { self.hash_qpath(qpath); }, diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index a10eb8646af..b7e83ce6caa 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -21,35 +21,6 @@ type McfResult = Result<(), (Span, Cow<'static, str>)>; pub fn is_min_const_fn<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, msrv: &Msrv) -> McfResult { let def_id = body.source.def_id(); - let mut current = def_id; - loop { - let predicates = tcx.predicates_of(current); - for (predicate, _) in predicates.predicates { - match predicate.kind().skip_binder() { - ty::PredicateKind::Clause( - ty::ClauseKind::RegionOutlives(_) - | ty::ClauseKind::TypeOutlives(_) - | ty::ClauseKind::Projection(_) - | ty::ClauseKind::Trait(..) - | ty::ClauseKind::ConstArgHasType(..), - ) - | ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_)) - | ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..)) - | ty::PredicateKind::ConstEquate(..) - | ty::PredicateKind::TypeWellFormedFromEnv(..) => continue, - ty::PredicateKind::AliasRelate(..) => panic!("alias relate predicate on function: {predicate:#?}"), - ty::PredicateKind::ObjectSafe(_) => panic!("object safe predicate on function: {predicate:#?}"), - ty::PredicateKind::ClosureKind(..) => panic!("closure kind predicate on function: {predicate:#?}"), - ty::PredicateKind::Subtype(_) => panic!("subtype predicate on function: {predicate:#?}"), - ty::PredicateKind::Coerce(_) => panic!("coerce predicate on function: {predicate:#?}"), - ty::PredicateKind::Ambiguous => panic!("ambiguous predicate on function: {predicate:#?}"), - } - } - match predicates.parent { - Some(parent) => current = parent, - None => break, - } - } for local in &body.local_decls { check_ty(tcx, local.ty, local.source_info.span)?; diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs index a87d58110b0..b38b9553558 100644 --- a/src/tools/clippy/clippy_utils/src/sugg.rs +++ b/src/tools/clippy/clippy_utils/src/sugg.rs @@ -147,6 +147,7 @@ impl<'a> Sugg<'a> { | hir::ExprKind::Path(..) | hir::ExprKind::Repeat(..) | hir::ExprKind::Ret(..) + | hir::ExprKind::Become(..) | hir::ExprKind::Struct(..) | hir::ExprKind::Tup(..) | hir::ExprKind::Err(_) => Sugg::NonParen(get_snippet(expr.span)), diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index 2b185943c59..8d3aecd4785 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -17,7 +17,7 @@ use rustc_lint::LateContext; use rustc_middle::mir::interpret::{ConstValue, Scalar}; use rustc_middle::ty::{ self, layout::ValidityRequirement, AdtDef, AliasTy, AssocKind, Binder, BoundRegion, FnSig, IntTy, List, ParamEnv, - Predicate, PredicateKind, Region, RegionKind, SubstsRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, + Region, RegionKind, SubstsRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, UintTy, VariantDef, VariantDiscr, }; use rustc_middle::ty::{GenericArg, GenericArgKind}; @@ -563,7 +563,7 @@ fn is_uninit_value_valid_for_ty_fallback<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'t } /// Gets an iterator over all predicates which apply to the given item. -pub fn all_predicates_of(tcx: TyCtxt<'_>, id: DefId) -> impl Iterator<Item = &(Predicate<'_>, Span)> { +pub fn all_predicates_of(tcx: TyCtxt<'_>, id: DefId) -> impl Iterator<Item = &(ty::Clause<'_>, Span)> { let mut next_id = Some(id); iter::from_fn(move || { next_id.take().map(|id| { @@ -665,7 +665,7 @@ pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<ExprFnSig<'t ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => sig_from_bounds( cx, ty, - cx.tcx.item_bounds(def_id).subst_iter(cx.tcx, substs).map(|c| c.as_predicate()), + cx.tcx.item_bounds(def_id).subst_iter(cx.tcx, substs), cx.tcx.opt_parent(def_id), ), ty::FnPtr(sig) => Some(ExprFnSig::Sig(sig, None)), @@ -698,7 +698,7 @@ pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<ExprFnSig<'t fn sig_from_bounds<'tcx>( cx: &LateContext<'tcx>, ty: Ty<'tcx>, - predicates: impl IntoIterator<Item = Predicate<'tcx>>, + predicates: impl IntoIterator<Item = ty::Clause<'tcx>>, predicates_id: Option<DefId>, ) -> Option<ExprFnSig<'tcx>> { let mut inputs = None; @@ -707,7 +707,7 @@ fn sig_from_bounds<'tcx>( for pred in predicates { match pred.kind().skip_binder() { - PredicateKind::Clause(ty::ClauseKind::Trait(p)) + ty::ClauseKind::Trait(p) if (lang_items.fn_trait() == Some(p.def_id()) || lang_items.fn_mut_trait() == Some(p.def_id()) || lang_items.fn_once_trait() == Some(p.def_id())) @@ -720,7 +720,7 @@ fn sig_from_bounds<'tcx>( } inputs = Some(i); }, - PredicateKind::Clause(ty::ClauseKind::Projection(p)) + ty::ClauseKind::Projection(p) if Some(p.projection_ty.def_id) == lang_items.fn_once_output() && p.projection_ty.self_ty() == ty => { if output.is_some() { @@ -937,7 +937,7 @@ pub fn adt_and_variant_of_res<'tcx>(cx: &LateContext<'tcx>, res: Res) -> Option< } /// Checks if the type is a type parameter implementing `FnOnce`, but not `FnMut`. -pub fn ty_is_fn_once_param<'tcx>(tcx: TyCtxt<'_>, ty: Ty<'tcx>, predicates: &'tcx [Predicate<'_>]) -> bool { +pub fn ty_is_fn_once_param<'tcx>(tcx: TyCtxt<'_>, ty: Ty<'tcx>, predicates: &'tcx [ty::Clause<'_>]) -> bool { let ty::Param(ty) = *ty.kind() else { return false; }; @@ -950,7 +950,7 @@ pub fn ty_is_fn_once_param<'tcx>(tcx: TyCtxt<'_>, ty: Ty<'tcx>, predicates: &'tc predicates .iter() .try_fold(false, |found, p| { - if let PredicateKind::Clause(ty::ClauseKind::Trait(p)) = p.kind().skip_binder() + if let ty::ClauseKind::Trait(p) = p.kind().skip_binder() && let ty::Param(self_ty) = p.trait_ref.self_ty().kind() && ty.index == self_ty.index { diff --git a/src/tools/clippy/clippy_utils/src/visitors.rs b/src/tools/clippy/clippy_utils/src/visitors.rs index 5dcd71cef12..8dafa723afa 100644 --- a/src/tools/clippy/clippy_utils/src/visitors.rs +++ b/src/tools/clippy/clippy_utils/src/visitors.rs @@ -651,6 +651,7 @@ pub fn for_each_unconsumed_temporary<'tcx, B>( // Either drops temporaries, jumps out of the current expression, or has no sub expression. ExprKind::DropTemps(_) | ExprKind::Ret(_) + | ExprKind::Become(_) | ExprKind::Break(..) | ExprKind::Yield(..) | ExprKind::Block(..) diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs index 3c5b6e12b96..f3cc94aeff0 100644 --- a/src/tools/clippy/src/driver.rs +++ b/src/tools/clippy/src/driver.rs @@ -16,6 +16,8 @@ extern crate rustc_session; extern crate rustc_span; use rustc_interface::interface; +use rustc_session::EarlyErrorHandler; +use rustc_session::config::ErrorOutputType; use rustc_session::parse::ParseSess; use rustc_span::symbol::Symbol; @@ -187,7 +189,9 @@ const BUG_REPORT_URL: &str = "https://github.com/rust-lang/rust-clippy/issues/ne #[allow(clippy::too_many_lines)] pub fn main() { - rustc_driver::init_rustc_env_logger(); + let handler = EarlyErrorHandler::new(ErrorOutputType::default()); + + rustc_driver::init_rustc_env_logger(&handler); rustc_driver::install_ice_hook(BUG_REPORT_URL, |handler| { // FIXME: this macro calls unwrap internally but is called in a panicking context! It's not diff --git a/src/tools/clippy/tests/ui/crashes/ice-6250.stderr b/src/tools/clippy/tests/ui/crashes/ice-6250.stderr index 4506d1550bd..db34e6bfa7b 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-6250.stderr +++ b/src/tools/clippy/tests/ui/crashes/ice-6250.stderr @@ -12,11 +12,6 @@ LL | for reference in vec![1, 2, 3] { ... LL | Some(reference) = cache.data.get(key) { | ^^^^^^^^^ expected integer, found `&i32` - | -help: consider dereferencing the borrow - | -LL | Some(*reference) = cache.data.get(key) { - | + error[E0308]: mismatched types --> $DIR/ice-6250.rs:12:9 diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 1b46c42fa4c..85a8fbcffbe 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -453,7 +453,7 @@ impl TargetCfgs { let mut all_families = HashSet::new(); let mut all_pointer_widths = HashSet::new(); - for (target, cfg) in targets.into_iter() { + for (target, cfg) in targets.iter() { all_archs.insert(cfg.arch.clone()); all_oses.insert(cfg.os.clone()); all_oses_and_envs.insert(cfg.os_and_env()); @@ -464,11 +464,11 @@ impl TargetCfgs { } all_pointer_widths.insert(format!("{}bit", cfg.pointer_width)); - all_targets.insert(target.into()); + all_targets.insert(target.clone()); } Self { - current: Self::get_current_target_config(config), + current: Self::get_current_target_config(config, &targets), all_targets, all_archs, all_oses, @@ -480,16 +480,20 @@ impl TargetCfgs { } } - fn get_current_target_config(config: &Config) -> TargetCfg { - let mut arch = None; - let mut os = None; - let mut env = None; - let mut abi = None; - let mut families = Vec::new(); - let mut pointer_width = None; - let mut endian = None; - let mut panic = None; - + fn get_current_target_config( + config: &Config, + targets: &HashMap<String, TargetCfg>, + ) -> TargetCfg { + let mut cfg = targets[&config.target].clone(); + + // To get the target information for the current target, we take the target spec obtained + // from `--print=all-target-specs-json`, and then we enrich it with the information + // gathered from `--print=cfg --target=$target`. + // + // This is done because some parts of the target spec can be overridden with `-C` flags, + // which are respected for `--print=cfg` but not for `--print=all-target-specs-json`. The + // code below extracts them from `--print=cfg`: make sure to only override fields that can + // actually be changed with `-C` flags. for config in rustc_output(config, &["--print=cfg", "--target", &config.target]).trim().lines() { @@ -507,60 +511,16 @@ impl TargetCfgs { }) .unwrap_or_else(|| (config, None)); - match name { - "target_arch" => { - arch = Some(value.expect("target_arch should be a key-value pair").to_string()); - } - "target_os" => { - os = Some(value.expect("target_os sould be a key-value pair").to_string()); - } - "target_env" => { - env = Some(value.expect("target_env should be a key-value pair").to_string()); - } - "target_abi" => { - abi = Some(value.expect("target_abi should be a key-value pair").to_string()); - } - "target_family" => { - families - .push(value.expect("target_family should be a key-value pair").to_string()); - } - "target_pointer_width" => { - pointer_width = Some( - value - .expect("target_pointer_width should be a key-value pair") - .parse::<u32>() - .expect("target_pointer_width should be a valid u32"), - ); - } - "target_endian" => { - endian = Some(match value.expect("target_endian should be a key-value pair") { - "big" => Endian::Big, - "little" => Endian::Little, - _ => panic!("target_endian should be either 'big' or 'little'"), - }); - } - "panic" => { - panic = Some(match value.expect("panic should be a key-value pair") { - "abort" => PanicStrategy::Abort, - "unwind" => PanicStrategy::Unwind, - _ => panic!("panic should be either 'abort' or 'unwind'"), - }); - } - _ => (), + match (name, value) { + // Can be overridden with `-C panic=$strategy`. + ("panic", Some("abort")) => cfg.panic = PanicStrategy::Abort, + ("panic", Some("unwind")) => cfg.panic = PanicStrategy::Unwind, + ("panic", other) => panic!("unexpected value for panic cfg: {other:?}"), + _ => {} } } - TargetCfg { - arch: arch.expect("target configuration should specify target_arch"), - os: os.expect("target configuration should specify target_os"), - env: env.expect("target configuration should specify target_env"), - abi: abi.expect("target configuration should specify target_abi"), - families, - pointer_width: pointer_width - .expect("target configuration should specify target_pointer_width"), - endian: endian.expect("target configuration should specify target_endian"), - panic: panic.expect("target configuration should specify panic"), - } + cfg } } @@ -582,6 +542,8 @@ pub struct TargetCfg { endian: Endian, #[serde(rename = "panic-strategy", default)] pub(crate) panic: PanicStrategy, + #[serde(default)] + pub(crate) dynamic_linking: bool, } impl TargetCfg { diff --git a/src/tools/compiletest/src/header/needs.rs b/src/tools/compiletest/src/header/needs.rs index 18b3b913a68..0e306696a90 100644 --- a/src/tools/compiletest/src/header/needs.rs +++ b/src/tools/compiletest/src/header/needs.rs @@ -130,6 +130,11 @@ pub(super) fn handle_needs( condition: config.git_hash, ignore_reason: "ignored when git hashes have been omitted for building", }, + Need { + name: "needs-dynamic-linking", + condition: config.target_cfg().dynamic_linking, + ignore_reason: "ignored on targets without dynamic linking", + }, ]; let (name, comment) = match ln.split_once([':', ' ']) { diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 25b16e38e53..5c8ee7895d3 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1810,8 +1810,8 @@ impl<'test> TestCx<'test> { || self.config.target.contains("wasm32") || self.config.target.contains("nvptx") || self.is_vxworks_pure_static() - || self.config.target.contains("sgx") || self.config.target.contains("bpf") + || !self.config.target_cfg().dynamic_linking { // We primarily compile all auxiliary libraries as dynamic libraries // to avoid code size bloat and large binaries as much as possible diff --git a/src/tools/error_index_generator/main.rs b/src/tools/error_index_generator/main.rs index f984275b164..62a58576da5 100644 --- a/src/tools/error_index_generator/main.rs +++ b/src/tools/error_index_generator/main.rs @@ -1,6 +1,7 @@ #![feature(rustc_private)] extern crate rustc_driver; +extern crate rustc_session; use std::env; use std::error::Error; @@ -170,7 +171,9 @@ fn parse_args() -> (OutputFormat, PathBuf) { } fn main() { - rustc_driver::init_env_logger("RUST_LOG"); + let handler = + rustc_session::EarlyErrorHandler::new(rustc_session::config::ErrorOutputType::default()); + rustc_driver::init_env_logger(&handler, "RUST_LOG"); let (format, dst) = parse_args(); let result = main_with_result(format, &dst); if let Err(e) = result { diff --git a/src/tools/generate-windows-sys/src/arm_shim.rs b/src/tools/generate-windows-sys/src/arm_shim.rs deleted file mode 100644 index 17c2ccb223c..00000000000 --- a/src/tools/generate-windows-sys/src/arm_shim.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Begin of ARM32 shim -// The raw content of this file should be processed by `generate-windows-sys` -// to be merged with the generated binding. It is not supposed to be used as -// a normal Rust module. -cfg_if::cfg_if! { -if #[cfg(target_arch = "arm")] { -#[repr(C)] -pub struct WSADATA { - pub wVersion: u16, - pub wHighVersion: u16, - pub szDescription: [u8; 257], - pub szSystemStatus: [u8; 129], - pub iMaxSockets: u16, - pub iMaxUdpDg: u16, - pub lpVendorInfo: PSTR, -} -pub enum CONTEXT {} -} -} -// End of ARM32 shim diff --git a/src/tools/generate-windows-sys/src/main.rs b/src/tools/generate-windows-sys/src/main.rs index 65e480715ee..91d981462e8 100644 --- a/src/tools/generate-windows-sys/src/main.rs +++ b/src/tools/generate-windows-sys/src/main.rs @@ -11,9 +11,6 @@ const PRELUDE: &str = r#"// This file is autogenerated. // ignore-tidy-filelength "#; -/// This is a shim for the ARM (32-bit) architecture, which is no longer supported by windows-rs. -const ARM_SHIM: &str = include_str!("arm_shim.rs"); - fn main() -> io::Result<()> { let mut path: PathBuf = std::env::args_os().nth(1).expect("a path to the rust repository is required").into(); @@ -35,7 +32,6 @@ fn main() -> io::Result<()> { let mut f = std::fs::File::create(&path)?; f.write_all(PRELUDE.as_bytes())?; f.write_all(bindings.as_bytes())?; - f.write_all(ARM_SHIM.as_bytes())?; Ok(()) } diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 0ac1e277eb7..3e024086a6b 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -0928a1f7574f5ca019b5443b3a90008588d18c8c +08fd6f719ee764cf62659ddf481e22dbfe4b8894 diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs index 083dd4800d9..cc14cfecea4 100644 --- a/src/tools/miri/src/bin/miri.rs +++ b/src/tools/miri/src/bin/miri.rs @@ -31,9 +31,9 @@ use rustc_middle::{ query::{ExternProviders, LocalCrate}, ty::TyCtxt, }; -use rustc_session::config::OptLevel; - -use rustc_session::{config::CrateType, search_paths::PathKind, CtfeBacktrace}; +use rustc_session::config::{CrateType, ErrorOutputType, OptLevel}; +use rustc_session::search_paths::PathKind; +use rustc_session::{CtfeBacktrace, EarlyErrorHandler}; use miri::{BacktraceStyle, BorrowTrackerMethod, ProvenanceMode, RetagFields}; @@ -59,6 +59,7 @@ impl rustc_driver::Callbacks for MiriCompilerCalls { fn after_analysis<'tcx>( &mut self, + handler: &EarlyErrorHandler, _: &rustc_interface::interface::Compiler, queries: &'tcx rustc_interface::Queries<'tcx>, ) -> Compilation { @@ -66,8 +67,8 @@ impl rustc_driver::Callbacks for MiriCompilerCalls { if tcx.sess.compile_status().is_err() { tcx.sess.fatal("miri cannot be run on programs that fail compilation"); } - - init_late_loggers(tcx); +; + init_late_loggers(handler, tcx); if !tcx.sess.crate_types().contains(&CrateType::Executable) { tcx.sess.fatal("miri only makes sense on bin crates"); } @@ -181,7 +182,7 @@ macro_rules! show_error { ($($tt:tt)*) => { show_error(&format_args!($($tt)*)) }; } -fn init_early_loggers() { +fn init_early_loggers(handler: &EarlyErrorHandler) { // Note that our `extern crate log` is *not* the same as rustc's; as a result, we have to // initialize them both, and we always initialize `miri`'s first. let env = env_logger::Env::new().filter("MIRI_LOG").write_style("MIRI_LOG_STYLE"); @@ -195,11 +196,11 @@ fn init_early_loggers() { // later with our custom settings, and *not* log anything for what happens before // `miri` gets started. if env::var_os("RUSTC_LOG").is_some() { - rustc_driver::init_rustc_env_logger(); + rustc_driver::init_rustc_env_logger(handler); } } -fn init_late_loggers(tcx: TyCtxt<'_>) { +fn init_late_loggers(handler: &EarlyErrorHandler, tcx: TyCtxt<'_>) { // We initialize loggers right before we start evaluation. We overwrite the `RUSTC_LOG` // env var if it is not set, control it based on `MIRI_LOG`. // (FIXME: use `var_os`, but then we need to manually concatenate instead of `format!`.) @@ -218,7 +219,7 @@ fn init_late_loggers(tcx: TyCtxt<'_>) { } else { env::set_var("RUSTC_LOG", &var); } - rustc_driver::init_rustc_env_logger(); + rustc_driver::init_rustc_env_logger(handler); } } @@ -284,6 +285,8 @@ fn parse_comma_list<T: FromStr>(input: &str) -> Result<Vec<T>, T::Err> { } fn main() { + let handler = EarlyErrorHandler::new(ErrorOutputType::default()); + // Snapshot a copy of the environment before `rustc` starts messing with it. // (`install_ice_hook` might change `RUST_BACKTRACE`.) let env_snapshot = env::vars_os().collect::<Vec<_>>(); @@ -292,7 +295,7 @@ fn main() { if let Some(crate_kind) = env::var_os("MIRI_BE_RUSTC") { // Earliest rustc setup. rustc_driver::install_ice_hook(rustc_driver::DEFAULT_BUG_REPORT_URL, |_| ()); - rustc_driver::init_rustc_env_logger(); + rustc_driver::init_rustc_env_logger(&handler); let target_crate = if crate_kind == "target" { true @@ -314,7 +317,7 @@ fn main() { rustc_driver::install_ice_hook("https://github.com/rust-lang/miri/issues/new", |_| ()); // Init loggers the Miri way. - init_early_loggers(); + init_early_loggers(&handler); // Parse our arguments and split them across `rustc` and `miri`. let mut miri_config = miri::MiriConfig::default(); diff --git a/src/tools/rust-installer/Cargo.toml b/src/tools/rust-installer/Cargo.toml index 85e979f07bf..471f2b5ac73 100644 --- a/src/tools/rust-installer/Cargo.toml +++ b/src/tools/rust-installer/Cargo.toml @@ -2,7 +2,7 @@ authors = ["The Rust Project Developers"] name = "installer" version = "0.0.0" -edition = "2018" +edition = "2021" [[bin]] doc = false @@ -20,4 +20,4 @@ num_cpus = "1" [dependencies.clap] features = ["derive"] -version = "3.1" +version = "4.2" diff --git a/src/tools/rust-installer/src/combiner.rs b/src/tools/rust-installer/src/combiner.rs index abcf59cfe36..19466f63fed 100644 --- a/src/tools/rust-installer/src/combiner.rs +++ b/src/tools/rust-installer/src/combiner.rs @@ -13,47 +13,47 @@ actor! { #[derive(Debug)] pub struct Combiner { /// The name of the product, for display. - #[clap(value_name = "NAME")] + #[arg(value_name = "NAME")] product_name: String = "Product", /// The name of the package tarball. - #[clap(value_name = "NAME")] + #[arg(value_name = "NAME")] package_name: String = "package", /// The directory under lib/ where the manifest lives. - #[clap(value_name = "DIR")] + #[arg(value_name = "DIR")] rel_manifest_dir: String = "packagelib", /// The string to print after successful installation. - #[clap(value_name = "MESSAGE")] + #[arg(value_name = "MESSAGE")] success_message: String = "Installed.", /// Places to look for legacy manifests to uninstall. - #[clap(value_name = "DIRS")] + #[arg(value_name = "DIRS")] legacy_manifest_dirs: String = "", /// Installers to combine. - #[clap(value_name = "FILE,FILE")] + #[arg(value_name = "FILE,FILE")] input_tarballs: String = "", /// Directory containing files that should not be installed. - #[clap(value_name = "DIR")] + #[arg(value_name = "DIR")] non_installed_overlay: String = "", /// The directory to do temporary work. - #[clap(value_name = "DIR")] + #[arg(value_name = "DIR")] work_dir: String = "./workdir", /// The location to put the final image and tarball. - #[clap(value_name = "DIR")] + #[arg(value_name = "DIR")] output_dir: String = "./dist", /// The profile used to compress the tarball. - #[clap(value_name = "FORMAT", default_value_t)] + #[arg(value_name = "FORMAT", default_value_t)] compression_profile: CompressionProfile, /// The formats used to compress the tarball - #[clap(value_name = "FORMAT", default_value_t)] + #[arg(value_name = "FORMAT", default_value_t)] compression_formats: CompressionFormats, } } @@ -94,7 +94,7 @@ impl Combiner { let pkg_name = input_tarball.trim_end_matches(&format!(".tar.{}", compression.extension())); let pkg_name = Path::new(pkg_name).file_name().unwrap(); - let pkg_dir = Path::new(&self.work_dir).join(&pkg_name); + let pkg_dir = Path::new(&self.work_dir).join(pkg_name); // Verify the version number. let mut version = String::new(); @@ -114,9 +114,9 @@ impl Combiner { // All we need to do is copy the component directory. We could // move it, but rustbuild wants to reuse the unpacked package // dir for OS-specific installers on macOS and Windows. - let component_dir = package_dir.join(&component); + let component_dir = package_dir.join(component); create_dir(&component_dir)?; - copy_recursive(&pkg_dir.join(&component), &component_dir)?; + copy_recursive(&pkg_dir.join(component), &component_dir)?; // Merge the component name. writeln!(&components, "{}", component).context("failed to write new components")?; @@ -158,7 +158,7 @@ impl Combiner { .input(self.package_name) .output(path_to_str(&output)?.into()) .compression_profile(self.compression_profile) - .compression_formats(self.compression_formats.clone()); + .compression_formats(self.compression_formats); tarballer.run()?; Ok(()) diff --git a/src/tools/rust-installer/src/compression.rs b/src/tools/rust-installer/src/compression.rs index 7c9c946e0b5..902b2ec6907 100644 --- a/src/tools/rust-installer/src/compression.rs +++ b/src/tools/rust-installer/src/compression.rs @@ -166,7 +166,7 @@ impl Default for CompressionFormats { impl CompressionFormats { pub(crate) fn iter(&self) -> impl Iterator<Item = CompressionFormat> + '_ { - self.0.iter().map(|i| *i) + self.0.iter().copied() } } diff --git a/src/tools/rust-installer/src/generator.rs b/src/tools/rust-installer/src/generator.rs index ddd1052599d..45f8c49d03e 100644 --- a/src/tools/rust-installer/src/generator.rs +++ b/src/tools/rust-installer/src/generator.rs @@ -11,55 +11,55 @@ actor! { #[derive(Debug)] pub struct Generator { /// The name of the product, for display - #[clap(value_name = "NAME")] + #[arg(value_name = "NAME")] product_name: String = "Product", /// The name of the component, distinct from other installed components - #[clap(value_name = "NAME")] + #[arg(value_name = "NAME")] component_name: String = "component", /// The name of the package, tarball - #[clap(value_name = "NAME")] + #[arg(value_name = "NAME")] package_name: String = "package", /// The directory under lib/ where the manifest lives - #[clap(value_name = "DIR")] + #[arg(value_name = "DIR")] rel_manifest_dir: String = "packagelib", /// The string to print after successful installation - #[clap(value_name = "MESSAGE")] + #[arg(value_name = "MESSAGE")] success_message: String = "Installed.", /// Places to look for legacy manifests to uninstall - #[clap(value_name = "DIRS")] + #[arg(value_name = "DIRS")] legacy_manifest_dirs: String = "", /// Directory containing files that should not be installed - #[clap(value_name = "DIR")] + #[arg(value_name = "DIR")] non_installed_overlay: String = "", /// Path prefixes of directories that should be installed/uninstalled in bulk - #[clap(value_name = "DIRS")] + #[arg(value_name = "DIRS")] bulk_dirs: String = "", /// The directory containing the installation medium - #[clap(value_name = "DIR")] + #[arg(value_name = "DIR")] image_dir: String = "./install_image", /// The directory to do temporary work - #[clap(value_name = "DIR")] + #[arg(value_name = "DIR")] work_dir: String = "./workdir", /// The location to put the final image and tarball - #[clap(value_name = "DIR")] + #[arg(value_name = "DIR")] output_dir: String = "./dist", /// The profile used to compress the tarball. - #[clap(value_name = "FORMAT", default_value_t)] + #[arg(value_name = "FORMAT", default_value_t)] compression_profile: CompressionProfile, /// The formats used to compress the tarball - #[clap(value_name = "FORMAT", default_value_t)] + #[arg(value_name = "FORMAT", default_value_t)] compression_formats: CompressionFormats, } } @@ -118,7 +118,7 @@ impl Generator { .input(self.package_name) .output(path_to_str(&output)?.into()) .compression_profile(self.compression_profile) - .compression_formats(self.compression_formats.clone()); + .compression_formats(self.compression_formats); tarballer.run()?; Ok(()) diff --git a/src/tools/rust-installer/src/scripter.rs b/src/tools/rust-installer/src/scripter.rs index 06affc029fd..8180f925cb0 100644 --- a/src/tools/rust-installer/src/scripter.rs +++ b/src/tools/rust-installer/src/scripter.rs @@ -2,29 +2,29 @@ use crate::util::*; use anyhow::{Context, Result}; use std::io::Write; -const TEMPLATE: &'static str = include_str!("../install-template.sh"); +const TEMPLATE: &str = include_str!("../install-template.sh"); actor! { #[derive(Debug)] pub struct Scripter { /// The name of the product, for display - #[clap(value_name = "NAME")] + #[arg(value_name = "NAME")] product_name: String = "Product", /// The directory under lib/ where the manifest lives - #[clap(value_name = "DIR")] + #[arg(value_name = "DIR")] rel_manifest_dir: String = "manifestlib", /// The string to print after successful installation - #[clap(value_name = "MESSAGE")] + #[arg(value_name = "MESSAGE")] success_message: String = "Installed.", /// Places to look for legacy manifests to uninstall - #[clap(value_name = "DIRS")] + #[arg(value_name = "DIRS")] legacy_manifest_dirs: String = "", /// The name of the output script - #[clap(value_name = "FILE")] + #[arg(value_name = "FILE")] output_script: String = "install.sh", } } diff --git a/src/tools/rust-installer/src/tarballer.rs b/src/tools/rust-installer/src/tarballer.rs index 7353a49fe03..c60d5f648ff 100644 --- a/src/tools/rust-installer/src/tarballer.rs +++ b/src/tools/rust-installer/src/tarballer.rs @@ -14,23 +14,23 @@ actor! { #[derive(Debug)] pub struct Tarballer { /// The input folder to be compressed. - #[clap(value_name = "NAME")] + #[arg(value_name = "NAME")] input: String = "package", /// The prefix of the tarballs. - #[clap(value_name = "PATH")] + #[arg(value_name = "PATH")] output: String = "./dist", /// The folder in which the input is to be found. - #[clap(value_name = "DIR")] + #[arg(value_name = "DIR")] work_dir: String = "./workdir", /// The profile used to compress the tarball. - #[clap(value_name = "FORMAT", default_value_t)] + #[arg(value_name = "FORMAT", default_value_t)] compression_profile: CompressionProfile, /// The formats used to compress the tarball. - #[clap(value_name = "FORMAT", default_value_t)] + #[arg(value_name = "FORMAT", default_value_t)] compression_formats: CompressionFormats, } } @@ -98,7 +98,7 @@ fn append_path<W: Write>(builder: &mut Builder<W>, src: &Path, path: &String) -> if cfg!(windows) { // Windows doesn't really have a mode, so `tar` never marks files executable. // Use an extension whitelist to update files that usually should be so. - const EXECUTABLES: [&'static str; 4] = ["exe", "dll", "py", "sh"]; + const EXECUTABLES: [&str; 4] = ["exe", "dll", "py", "sh"]; if let Some(ext) = src.extension().and_then(|s| s.to_str()) { if EXECUTABLES.contains(&ext) { let mode = header.mode()?; @@ -134,7 +134,7 @@ where for entry in WalkDir::new(root.join(name)) { let entry = entry?; let path = entry.path().strip_prefix(root)?; - let path = path_to_str(&path)?; + let path = path_to_str(path)?; if entry.file_type().is_dir() { dirs.push(path.to_owned()); diff --git a/src/tools/rust-installer/src/util.rs b/src/tools/rust-installer/src/util.rs index 6cac314b68d..4eb2e75fd7e 100644 --- a/src/tools/rust-installer/src/util.rs +++ b/src/tools/rust-installer/src/util.rs @@ -117,7 +117,7 @@ where } else { copy(entry.path(), dst)?; } - callback(&path, file_type)?; + callback(path, file_type)?; } Ok(()) } @@ -135,7 +135,7 @@ macro_rules! actor { $( #[ $attr ] )+ #[derive(clap::Args)] pub struct $name { - $( $( #[ $field_attr ] )+ #[clap(long, $(default_value = $default)*)] $field : $type, )* + $( $( #[ $field_attr ] )+ #[arg(long, $(default_value = $default)*)] $field : $type, )* } impl Default for $name { diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs index 2fd4c797b43..7ad8f5c5c05 100644 --- a/src/tools/tidy/src/features.rs +++ b/src/tools/tidy/src/features.rs @@ -160,10 +160,10 @@ pub fn check( for &(name, _) in gate_untested.iter() { println!("Expected a gate test for the feature '{name}'."); println!( - "Hint: create a failing test file named 'feature-gate-{}.rs'\ - \n in the 'ui' test suite, with its failures due to\ - \n missing usage of `#![feature({})]`.", - name, name + "Hint: create a failing test file named 'tests/ui/feature-gates/feature-gate-{}.rs',\ + \n with its failures due to missing usage of `#![feature({})]`.", + name.replace("_", "-"), + name ); println!( "Hint: If you already have such a test and don't want to rename it,\ diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index 55bf38110a6..3ed587caadc 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -11,7 +11,7 @@ use std::path::{Path, PathBuf}; const ENTRY_LIMIT: usize = 900; // FIXME: The following limits should be reduced eventually. const ISSUES_ENTRY_LIMIT: usize = 1896; -const ROOT_ENTRY_LIMIT: usize = 870; +const ROOT_ENTRY_LIMIT: usize = 871; const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[ "rs", // test source files |
