From 70639c8a6a45f52cd875d90bf847f6a81f680b83 Mon Sep 17 00:00:00 2001 From: Raoul Strackx Date: Tue, 27 Feb 2024 16:29:10 +0100 Subject: [PATCH 01/16] Fixing shellcheck comments on lvi test script --- .../x86_64-fortanix-unknown-sgx-lvi/script.sh | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/script.sh b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/script.sh index 04a34724518e8..aacd0a67682b9 100644 --- a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/script.sh +++ b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/script.sh @@ -1,20 +1,20 @@ -#!/bin/sh +#!/bin/bash set -exuo pipefail function build { CRATE=enclave - mkdir -p $WORK_DIR - pushd $WORK_DIR - rm -rf $CRATE - cp -a $TEST_DIR/enclave . + mkdir -p "${WORK_DIR}" + pushd "${WORK_DIR}" + rm -rf "${CRATE}" + cp -a "${TEST_DIR}"/enclave . pushd $CRATE - echo ${WORK_DIR} + echo "${WORK_DIR}" # HACK(eddyb) sets `RUSTC_BOOTSTRAP=1` so Cargo can accept nightly features. # These come from the top-level Rust workspace, that this crate is not a # member of, but Cargo tries to load the workspace `Cargo.toml` anyway. env RUSTC_BOOTSTRAP=1 - cargo -v run --target $TARGET + cargo -v run --target "${TARGET}" popd popd } @@ -22,17 +22,18 @@ function build { function check { local func_re="$1" local checks="${TEST_DIR}/$2" - local asm=$(mktemp) + local asm="" local objdump="${LLVM_BIN_DIR}/llvm-objdump" local filecheck="${LLVM_BIN_DIR}/FileCheck" local enclave=${WORK_DIR}/enclave/target/x86_64-fortanix-unknown-sgx/debug/enclave - func="$(${objdump} --syms --demangle ${enclave} | \ + asm=$(mktemp) + func="$(${objdump} --syms --demangle "${enclave}" | \ grep --only-matching -E "[[:blank:]]+${func_re}\$" | \ sed -e 's/^[[:space:]]*//' )" ${objdump} --disassemble-symbols="${func}" --demangle \ - ${enclave} > ${asm} - ${filecheck} --input-file ${asm} ${checks} + "${enclave}" > "${asm}" + ${filecheck} --input-file "${asm}" "${checks}" if [ "${func_re}" != "rust_plus_one_global_asm" && "${func_re}" != "cmake_plus_one_c_global_asm" ]; then @@ -40,7 +41,7 @@ function check { # of `shlq $0x0, (%rsp); lfence; retq` are used instead. # https://www.intel.com/content/www/us/en/developer/articles/technical/ # software-security-guidance/technical-documentation/load-value-injection.html - ${filecheck} --implicit-check-not ret --input-file ${asm} ${checks} + ${filecheck} --implicit-check-not ret --input-file "${asm}" "${checks}" fi } From c3954b358f9e2be96d0dd553a8efaefc49f0bba7 Mon Sep 17 00:00:00 2001 From: r0cky Date: Sun, 3 Mar 2024 00:57:37 +0800 Subject: [PATCH 02/16] Add a tidy check that checks whether the fluent slugs only appear once --- src/tools/tidy/src/fluent_alphabetical.rs | 58 ++++++++++++++++++++--- src/tools/tidy/src/fluent_used.rs | 43 +++++++++++++++++ src/tools/tidy/src/lib.rs | 1 + 3 files changed, 96 insertions(+), 6 deletions(-) create mode 100644 src/tools/tidy/src/fluent_used.rs diff --git a/src/tools/tidy/src/fluent_alphabetical.rs b/src/tools/tidy/src/fluent_alphabetical.rs index 67b745373f019..9803b6eab2db5 100644 --- a/src/tools/tidy/src/fluent_alphabetical.rs +++ b/src/tools/tidy/src/fluent_alphabetical.rs @@ -1,6 +1,7 @@ //! Checks that all Flunt files have messages in alphabetical order use crate::walk::{filter_dirs, walk}; +use std::collections::HashMap; use std::{fs::OpenOptions, io::Write, path::Path}; use regex::Regex; @@ -13,11 +14,27 @@ fn filter_fluent(path: &Path) -> bool { if let Some(ext) = path.extension() { ext.to_str() != Some("ftl") } else { true } } -fn check_alphabetic(filename: &str, fluent: &str, bad: &mut bool) { +fn check_alphabetic( + filename: &str, + fluent: &str, + bad: &mut bool, + all_defined_msgs: &mut HashMap, +) { let mut matches = MESSAGE.captures_iter(fluent).peekable(); while let Some(m) = matches.next() { + let name = m.get(1).unwrap(); + if let Some(defined_filename) = all_defined_msgs.get(name.as_str()) { + tidy_error!( + bad, + "{filename}: message `{}` is already defined in {}", + name.as_str(), + defined_filename, + ); + } + + all_defined_msgs.insert(name.as_str().to_owned(), filename.to_owned()); + if let Some(next) = matches.peek() { - let name = m.get(1).unwrap(); let next = next.get(1).unwrap(); if name.as_str() > next.as_str() { tidy_error!( @@ -34,13 +51,29 @@ run `./x.py test tidy --bless` to sort the file correctly", } } -fn sort_messages(fluent: &str) -> String { +fn sort_messages( + filename: &str, + fluent: &str, + bad: &mut bool, + all_defined_msgs: &mut HashMap, +) -> String { let mut chunks = vec![]; let mut cur = String::new(); for line in fluent.lines() { - if MESSAGE.is_match(line) { + if let Some(name) = MESSAGE.find(line) { + if let Some(defined_filename) = all_defined_msgs.get(name.as_str()) { + tidy_error!( + bad, + "{filename}: message `{}` is already defined in {}", + name.as_str(), + defined_filename, + ); + } + + all_defined_msgs.insert(name.as_str().to_owned(), filename.to_owned()); chunks.push(std::mem::take(&mut cur)); } + cur += line; cur.push('\n'); } @@ -53,20 +86,33 @@ fn sort_messages(fluent: &str) -> String { } pub fn check(path: &Path, bless: bool, bad: &mut bool) { + let mut all_defined_msgs = HashMap::new(); walk( path, |path, is_dir| filter_dirs(path) || (!is_dir && filter_fluent(path)), &mut |ent, contents| { if bless { - let sorted = sort_messages(contents); + let sorted = sort_messages( + ent.path().to_str().unwrap(), + contents, + bad, + &mut all_defined_msgs, + ); if sorted != contents { let mut f = OpenOptions::new().write(true).truncate(true).open(ent.path()).unwrap(); f.write(sorted.as_bytes()).unwrap(); } } else { - check_alphabetic(ent.path().to_str().unwrap(), contents, bad); + check_alphabetic( + ent.path().to_str().unwrap(), + contents, + bad, + &mut all_defined_msgs, + ); } }, ); + + crate::fluent_used::check(path, all_defined_msgs, bad); } diff --git a/src/tools/tidy/src/fluent_used.rs b/src/tools/tidy/src/fluent_used.rs new file mode 100644 index 0000000000000..b73e79cb38d94 --- /dev/null +++ b/src/tools/tidy/src/fluent_used.rs @@ -0,0 +1,43 @@ +//! Checks that all Fluent messages appear at least twice + +use crate::walk::{filter_dirs, walk}; +use regex::Regex; +use std::collections::HashMap; +use std::path::Path; + +lazy_static::lazy_static! { + static ref WORD: Regex = Regex::new(r"\w+").unwrap(); +} + +fn filter_used_messages( + contents: &str, + msgs_not_appeared_yet: &mut HashMap, + msgs_appeared_only_once: &mut HashMap, +) { + // we don't just check messages never appear in Rust files, + // because messages can be used as parts of other fluent messages in Fluent files, + // so we do checking messages appear only once in all Rust and Fluent files. + let mut matches = WORD.find_iter(contents); + while let Some(name) = matches.next() { + if let Some((name, filename)) = msgs_not_appeared_yet.remove_entry(name.as_str()) { + // if one msg appears for the first time, + // remove it from `msgs_not_appeared_yet` and insert it into `msgs_appeared_only_once`. + msgs_appeared_only_once.insert(name, filename); + } else { + // if one msg appears for the second time, + // remove it from `msgs_appeared_only_once`. + msgs_appeared_only_once.remove(name.as_str()); + } + } +} + +pub fn check(path: &Path, mut all_defined_msgs: HashMap, bad: &mut bool) { + let mut msgs_appear_only_once = HashMap::new(); + walk(path, |path, _| filter_dirs(path), &mut |_, contents| { + filter_used_messages(contents, &mut all_defined_msgs, &mut msgs_appear_only_once); + }); + + for (name, filename) in msgs_appear_only_once { + tidy_error!(bad, "{filename}: message `{}` is not used", name,); + } +} diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs index 6f3ade0ab58c7..670b7eb2be995 100644 --- a/src/tools/tidy/src/lib.rs +++ b/src/tools/tidy/src/lib.rs @@ -65,6 +65,7 @@ pub mod ext_tool_checks; pub mod extdeps; pub mod features; pub mod fluent_alphabetical; +mod fluent_used; pub(crate) mod iter_header; pub mod mir_opt_tests; pub mod pal; From d88c7ffc62d0f1ee15abf3e9e65af3eeedc7d003 Mon Sep 17 00:00:00 2001 From: r0cky Date: Sun, 3 Mar 2024 00:57:45 +0800 Subject: [PATCH 03/16] Remove unused fluent messages --- compiler/rustc_const_eval/messages.ftl | 3 --- compiler/rustc_infer/messages.ftl | 8 -------- compiler/rustc_lint/messages.ftl | 2 -- compiler/rustc_parse/messages.ftl | 4 ---- compiler/rustc_passes/messages.ftl | 5 ----- 5 files changed, 22 deletions(-) diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl index 2805ca360ad3d..1bad62c4103a3 100644 --- a/compiler/rustc_const_eval/messages.ftl +++ b/compiler/rustc_const_eval/messages.ftl @@ -146,9 +146,6 @@ const_eval_intern_kind = {$kind -> *[other] {""} } -const_eval_invalid_align = - align has to be a power of 2 - const_eval_invalid_align_details = invalid align passed to `{$name}`: {$align} is {$err_kind -> [not_power_of_two] not a power of 2 diff --git a/compiler/rustc_infer/messages.ftl b/compiler/rustc_infer/messages.ftl index 2de87cbe631ac..e44a6ae3b3f2e 100644 --- a/compiler/rustc_infer/messages.ftl +++ b/compiler/rustc_infer/messages.ftl @@ -181,14 +181,6 @@ infer_more_targeted = {$has_param_name -> infer_msl_introduces_static = introduces a `'static` lifetime requirement infer_msl_unmet_req = because this has an unmet lifetime requirement -infer_need_type_info_in_coroutine = - type inside {$coroutine_kind -> - [async_block] `async` block - [async_closure] `async` closure - [async_fn] `async fn` body - *[coroutine] coroutine - } must be known in this context - infer_nothing = {""} diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 63e2fe47659db..8bf9d0b9d4aac 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -562,8 +562,6 @@ lint_suspicious_double_ref_clone = lint_suspicious_double_ref_deref = using `.deref()` on a double reference, which returns `{$ty}` instead of dereferencing the inner type -lint_trivial_untranslatable_diag = diagnostic with static strings only - lint_ty_qualified = usage of qualified `ty::{$ty}` .suggestion = try importing it and using it unqualified diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index 60cc138fd7bc2..a100e2d47bbbb 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -392,9 +392,6 @@ parse_invalid_identifier_with_leading_number = identifiers cannot start with a n parse_invalid_interpolated_expression = invalid interpolated expression -parse_invalid_literal_suffix = suffixes on {$kind} literals are invalid - .label = invalid suffix `{$suffix}` - parse_invalid_literal_suffix_on_tuple_index = suffixes on a tuple index are invalid .label = invalid suffix `{$suffix}` .tuple_exception_line_1 = `{$suffix}` is *temporarily* accepted on tuple index fields as it was incorrectly accepted on stable for a few releases @@ -609,7 +606,6 @@ parse_nonterminal_expected_item_keyword = expected an item keyword parse_nonterminal_expected_lifetime = expected a lifetime, found `{$token}` parse_nonterminal_expected_statement = expected a statement -parse_not_supported = not supported parse_note_edition_guide = for more on editions, read https://doc.rust-lang.org/edition-guide diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index c223b8475288b..7fc523ffe0dea 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -302,9 +302,6 @@ passes_export_name = attribute should be applied to a free function, impl method or static .label = not a free function, impl method or static -passes_expr_not_allowed_in_context = - {$expr} is not allowed in a `{$context}` - passes_extern_main = the `main` function cannot be declared in an `extern` block @@ -405,8 +402,6 @@ passes_lang_item_on_incorrect_target = `{$name}` language item must be applied to a {$expected_target} .label = attribute should be applied to a {$expected_target}, not a {$actual_target} -passes_layout = - layout error: {$layout_error} passes_layout_abi = abi: {$abi} passes_layout_align = From 489dcf216d62d6114b76fd7d0c6ed79a9d9b4e37 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Sat, 2 Mar 2024 20:34:38 +0300 Subject: [PATCH 04/16] skip sanity check for non-host targets in `check` builds For `check` builds, since we only need to perform a sanity check on the host target, this patch skips target sanity checks on non-host targets. Signed-off-by: onur-ozkan --- src/bootstrap/src/core/sanity.rs | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs index 1dce8d8ac7184..81acd65d85142 100644 --- a/src/bootstrap/src/core/sanity.rs +++ b/src/bootstrap/src/core/sanity.rs @@ -15,6 +15,7 @@ use std::fs; use std::path::PathBuf; use std::process::Command; +use crate::builder::Kind; use crate::core::config::Target; use crate::utils::helpers::output; use crate::Build; @@ -64,6 +65,8 @@ pub fn check(build: &mut Build) { let mut skip_target_sanity = env::var_os("BOOTSTRAP_SKIP_TARGET_SANITY").is_some_and(|s| s == "1" || s == "true"); + skip_target_sanity |= build.config.cmd.kind() == Kind::Check; + // Skip target sanity checks when we are doing anything with mir-opt tests or Miri let skipped_paths = [OsStr::new("mir-opt"), OsStr::new("miri")]; skip_target_sanity |= build.config.paths.iter().any(|path| { @@ -169,11 +172,7 @@ than building it. continue; } - // Some environments don't want or need these tools, such as when testing Miri. - // FIXME: it would be better to refactor this code to split necessary setup from pure sanity - // checks, and have a regular flag for skipping the latter. Also see - // . - if skip_target_sanity { + if skip_target_sanity && target != &build.build { continue; } @@ -215,11 +214,7 @@ than building it. panic!("All the *-none-* and nvptx* targets are no-std targets") } - // Some environments don't want or need these tools, such as when testing Miri. - // FIXME: it would be better to refactor this code to split necessary setup from pure sanity - // checks, and have a regular flag for skipping the latter. Also see - // . - if skip_target_sanity { + if skip_target_sanity && target != &build.build { continue; } From fbb97ed52b62248a44aed926c774212bf100c38e Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sat, 24 Feb 2024 21:35:19 +0100 Subject: [PATCH 05/16] Avoid some interning in bootstrap This interning is pointless and only makes the code more complex. The only remaining use of interning is `TargetSelection`, for which I left a comment. --- src/bootstrap/src/core/build_steps/check.rs | 24 ++++----- src/bootstrap/src/core/build_steps/clean.rs | 5 +- src/bootstrap/src/core/build_steps/compile.rs | 45 ++++++++--------- src/bootstrap/src/core/build_steps/dist.rs | 21 ++++---- src/bootstrap/src/core/build_steps/doc.rs | 41 ++++++++------- src/bootstrap/src/core/build_steps/install.rs | 3 +- src/bootstrap/src/core/build_steps/test.rs | 50 +++++++++++-------- src/bootstrap/src/core/builder.rs | 20 ++++---- src/bootstrap/src/core/builder/tests.rs | 2 +- src/bootstrap/src/core/config/config.rs | 18 ++++--- src/bootstrap/src/core/metadata.rs | 9 ++-- src/bootstrap/src/lib.rs | 19 ++++--- src/bootstrap/src/utils/cache.rs | 11 ---- 13 files changed, 128 insertions(+), 140 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/check.rs b/src/bootstrap/src/core/build_steps/check.rs index f6f4253a36435..a90139a070ac2 100644 --- a/src/bootstrap/src/core/build_steps/check.rs +++ b/src/bootstrap/src/core/build_steps/check.rs @@ -8,12 +8,10 @@ use crate::core::builder::{ self, crate_description, Alias, Builder, Kind, RunConfig, ShouldRun, Step, }; use crate::core::config::TargetSelection; -use crate::utils::cache::Interned; -use crate::INTERNER; use crate::{Compiler, Mode, Subcommand}; use std::path::{Path, PathBuf}; -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Std { pub target: TargetSelection, /// Whether to build only a subset of crates. @@ -21,7 +19,7 @@ pub struct Std { /// This shouldn't be used from other steps; see the comment on [`compile::Rustc`]. /// /// [`compile::Rustc`]: crate::core::build_steps::compile::Rustc - crates: Interned>, + crates: Vec, } /// Returns args for the subcommand itself (not for cargo) @@ -89,7 +87,7 @@ fn cargo_subcommand(kind: Kind) -> &'static str { impl Std { pub fn new(target: TargetSelection) -> Self { - Self { target, crates: INTERNER.intern_list(vec![]) } + Self { target, crates: vec![] } } } @@ -204,7 +202,7 @@ impl Step for Std { } } -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Rustc { pub target: TargetSelection, /// Whether to build only a subset of crates. @@ -212,7 +210,7 @@ pub struct Rustc { /// This shouldn't be used from other steps; see the comment on [`compile::Rustc`]. /// /// [`compile::Rustc`]: crate::core::build_steps::compile::Rustc - crates: Interned>, + crates: Vec, } impl Rustc { @@ -222,7 +220,7 @@ impl Rustc { .into_iter() .map(|krate| krate.name.to_string()) .collect(); - Self { target, crates: INTERNER.intern_list(crates) } + Self { target, crates } } } @@ -305,10 +303,10 @@ impl Step for Rustc { } } -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct CodegenBackend { pub target: TargetSelection, - pub backend: Interned, + pub backend: &'static str, } impl Step for CodegenBackend { @@ -321,14 +319,14 @@ impl Step for CodegenBackend { } fn make_run(run: RunConfig<'_>) { - for &backend in &[INTERNER.intern_str("cranelift"), INTERNER.intern_str("gcc")] { + for &backend in &["cranelift", "gcc"] { run.builder.ensure(CodegenBackend { target: run.target, backend }); } } fn run(self, builder: &Builder<'_>) { // FIXME: remove once https://github.com/rust-lang/rust/issues/112393 is resolved - if builder.build.config.vendor && &self.backend == "gcc" { + if builder.build.config.vendor && self.backend == "gcc" { println!("Skipping checking of `rustc_codegen_gcc` with vendoring enabled."); return; } @@ -552,7 +550,7 @@ fn codegen_backend_stamp( builder: &Builder<'_>, compiler: Compiler, target: TargetSelection, - backend: Interned, + backend: &str, ) -> PathBuf { builder .cargo_out(compiler, Mode::Codegen, target) diff --git a/src/bootstrap/src/core/build_steps/clean.rs b/src/bootstrap/src/core/build_steps/clean.rs index 17ca92f25a928..9e103a350e654 100644 --- a/src/bootstrap/src/core/build_steps/clean.rs +++ b/src/bootstrap/src/core/build_steps/clean.rs @@ -10,7 +10,6 @@ use std::io::{self, ErrorKind}; use std::path::Path; use crate::core::builder::{crate_description, Builder, RunConfig, ShouldRun, Step}; -use crate::utils::cache::Interned; use crate::utils::helpers::t; use crate::{Build, Compiler, Mode, Subcommand}; @@ -44,10 +43,10 @@ impl Step for CleanAll { macro_rules! clean_crate_tree { ( $( $name:ident, $mode:path, $root_crate:literal);+ $(;)? ) => { $( - #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] + #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct $name { compiler: Compiler, - crates: Interned>, + crates: Vec, } impl Step for $name { diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 43ac71b112c0b..e0dca129a30f9 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -27,7 +27,6 @@ use crate::core::builder::crate_description; use crate::core::builder::Cargo; use crate::core::builder::{Builder, Kind, PathSet, RunConfig, ShouldRun, Step, TaskPath}; use crate::core::config::{DebuginfoLevel, LlvmLibunwind, RustcLto, TargetSelection}; -use crate::utils::cache::{Interned, INTERNER}; use crate::utils::helpers::{ exe, get_clang_cl_resource_dir, is_debug_info, is_dylib, output, symlink_dir, t, up_to_date, }; @@ -35,14 +34,14 @@ use crate::LLVM_TOOLS; use crate::{CLang, Compiler, DependencyType, GitRepo, Mode}; use filetime::FileTime; -#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Std { pub target: TargetSelection, pub compiler: Compiler, /// Whether to build only a subset of crates in the standard library. /// /// This shouldn't be used from other steps; see the comment on [`Rustc`]. - crates: Interned>, + crates: Vec, /// When using download-rustc, we need to use a new build of `std` for running unit tests of Std itself, /// but we need to use the downloaded copy of std for linking to rustdoc. Allow this to be overriden by `builder.ensure` from other steps. force_recompile: bool, @@ -559,13 +558,13 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, car cargo.rustdocflag("-Zcrate-attr=warn(rust_2018_idioms)"); } -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Hash)] struct StdLink { pub compiler: Compiler, pub target_compiler: Compiler, pub target: TargetSelection, /// Not actually used; only present to make sure the cache invalidation is correct. - crates: Interned>, + crates: Vec, /// See [`Std::force_recompile`]. force_recompile: bool, } @@ -612,7 +611,7 @@ impl Step for StdLink { }); let libdir = sysroot.join(lib).join("rustlib").join(target.triple).join("lib"); let hostdir = sysroot.join(lib).join("rustlib").join(compiler.host.triple).join("lib"); - (INTERNER.intern_path(libdir), INTERNER.intern_path(hostdir)) + (libdir, hostdir) } else { let libdir = builder.sysroot_libdir(target_compiler, target); let hostdir = builder.sysroot_libdir(target_compiler, compiler.host); @@ -818,7 +817,7 @@ fn cp_rustc_component_to_ci_sysroot( } } -#[derive(Debug, PartialOrd, Ord, Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, PartialOrd, Ord, Clone, PartialEq, Eq, Hash)] pub struct Rustc { pub target: TargetSelection, pub compiler: Compiler, @@ -827,7 +826,7 @@ pub struct Rustc { /// This should only be requested by the user, not used within rustbuild itself. /// Using it within rustbuild can lead to confusing situation where lints are replayed /// in two different steps. - crates: Interned>, + crates: Vec, } impl Rustc { @@ -1220,13 +1219,13 @@ fn rustc_llvm_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelect } } -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Hash)] struct RustcLink { pub compiler: Compiler, pub target_compiler: Compiler, pub target: TargetSelection, /// Not actually used; only present to make sure the cache invalidation is correct. - crates: Interned>, + crates: Vec, } impl RustcLink { @@ -1261,11 +1260,11 @@ impl Step for RustcLink { } } -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct CodegenBackend { pub target: TargetSelection, pub compiler: Compiler, - pub backend: Interned, + pub backend: String, } fn needs_codegen_config(run: &RunConfig<'_>) -> bool { @@ -1284,7 +1283,7 @@ pub(crate) const CODEGEN_BACKEND_PREFIX: &str = "rustc_codegen_"; fn is_codegen_cfg_needed(path: &TaskPath, run: &RunConfig<'_>) -> bool { if path.path.to_str().unwrap().contains(CODEGEN_BACKEND_PREFIX) { let mut needs_codegen_backend_config = true; - for &backend in run.builder.config.codegen_backends(run.target) { + for backend in run.builder.config.codegen_backends(run.target) { if path .path .to_str() @@ -1321,7 +1320,7 @@ impl Step for CodegenBackend { return; } - for &backend in run.builder.config.codegen_backends(run.target) { + for backend in run.builder.config.codegen_backends(run.target) { if backend == "llvm" { continue; // Already built as part of rustc } @@ -1329,7 +1328,7 @@ impl Step for CodegenBackend { run.builder.ensure(CodegenBackend { target: run.target, compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()), - backend, + backend: backend.clone(), }); } } @@ -1394,7 +1393,7 @@ impl Step for CodegenBackend { f.display() ); } - let stamp = codegen_backend_stamp(builder, compiler, target, backend); + let stamp = codegen_backend_stamp(builder, compiler, target, &backend); let codegen_backend = codegen_backend.to_str().unwrap(); t!(fs::write(stamp, codegen_backend)); } @@ -1433,7 +1432,7 @@ fn copy_codegen_backends_to_sysroot( continue; // Already built as part of rustc } - let stamp = codegen_backend_stamp(builder, compiler, target, *backend); + let stamp = codegen_backend_stamp(builder, compiler, target, backend); let dylib = t!(fs::read_to_string(&stamp)); let file = Path::new(&dylib); let filename = file.file_name().unwrap().to_str().unwrap(); @@ -1470,7 +1469,7 @@ fn codegen_backend_stamp( builder: &Builder<'_>, compiler: Compiler, target: TargetSelection, - backend: Interned, + backend: &str, ) -> PathBuf { builder .cargo_out(compiler, Mode::Codegen, target) @@ -1508,7 +1507,7 @@ impl Sysroot { } impl Step for Sysroot { - type Output = Interned; + type Output = PathBuf; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.never() @@ -1520,7 +1519,7 @@ impl Step for Sysroot { /// That is, the sysroot for the stage0 compiler is not what the compiler /// thinks it is by default, but it's the same as the default for stages /// 1-3. - fn run(self, builder: &Builder<'_>) -> Interned { + fn run(self, builder: &Builder<'_>) -> PathBuf { let compiler = self.compiler; let host_dir = builder.out.join(compiler.host.triple); @@ -1652,7 +1651,7 @@ impl Step for Sysroot { ); } - INTERNER.intern_path(sysroot) + sysroot } } @@ -1735,7 +1734,7 @@ impl Step for Assemble { // to not fail while linking the artifacts. build_compiler.stage = actual_stage; - for &backend in builder.config.codegen_backends(target_compiler.host) { + for backend in builder.config.codegen_backends(target_compiler.host) { if backend == "llvm" { continue; // Already built as part of rustc } @@ -1743,7 +1742,7 @@ impl Step for Assemble { builder.ensure(CodegenBackend { compiler: build_compiler, target: target_compiler.host, - backend, + backend: backend.clone(), }); } diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index 067dede904f12..655495161fa35 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -25,7 +25,6 @@ use crate::core::build_steps::llvm; use crate::core::build_steps::tool::{self, Tool}; use crate::core::builder::{Builder, Kind, RunConfig, ShouldRun, Step}; use crate::core::config::TargetSelection; -use crate::utils::cache::{Interned, INTERNER}; use crate::utils::channel; use crate::utils::helpers::{exe, is_dylib, output, t, target_supports_cranelift_backend, timeit}; use crate::utils::tarball::{GeneratedTarball, OverlayKind, Tarball}; @@ -488,8 +487,7 @@ impl Step for Rustc { } // Debugger scripts - builder - .ensure(DebuggerScripts { sysroot: INTERNER.intern_path(image.to_owned()), host }); + builder.ensure(DebuggerScripts { sysroot: image.to_owned(), host }); // Misc license info let cp = |file: &str| { @@ -503,9 +501,9 @@ impl Step for Rustc { } } -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +#[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct DebuggerScripts { - pub sysroot: Interned, + pub sysroot: PathBuf, pub host: TargetSelection, } @@ -1263,10 +1261,10 @@ impl Step for Miri { } } -#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)] +#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)] pub struct CodegenBackend { pub compiler: Compiler, - pub backend: Interned, + pub backend: String, } impl Step for CodegenBackend { @@ -1279,14 +1277,14 @@ impl Step for CodegenBackend { } fn make_run(run: RunConfig<'_>) { - for &backend in run.builder.config.codegen_backends(run.target) { + for backend in run.builder.config.codegen_backends(run.target) { if backend == "llvm" { continue; // Already built as part of rustc } run.builder.ensure(CodegenBackend { compiler: run.builder.compiler(run.builder.top_stage, run.target), - backend, + backend: backend.clone(), }); } } @@ -1303,7 +1301,8 @@ impl Step for CodegenBackend { return None; } - if !builder.config.codegen_backends(self.compiler.host).contains(&self.backend) { + if !builder.config.codegen_backends(self.compiler.host).contains(&self.backend.to_string()) + { return None; } @@ -1528,7 +1527,7 @@ impl Step for Extended { add_component!("analysis" => Analysis { compiler, target }); add_component!("rustc-codegen-cranelift" => CodegenBackend { compiler: builder.compiler(stage, target), - backend: INTERNER.intern_str("cranelift"), + backend: "cranelift".to_string(), }); let etc = builder.src.join("src/etc/installer"); diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs index a4903ce235365..2ca77b79c5ed2 100644 --- a/src/bootstrap/src/core/build_steps/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -16,7 +16,6 @@ use crate::core::build_steps::tool::{self, prepare_tool_cargo, SourceType, Tool} use crate::core::builder::{self, crate_description}; use crate::core::builder::{Alias, Builder, Compiler, Kind, RunConfig, ShouldRun, Step}; use crate::core::config::{Config, TargetSelection}; -use crate::utils::cache::{Interned, INTERNER}; use crate::utils::helpers::{dir_is_empty, symlink_dir, t, up_to_date}; use crate::Mode; @@ -59,8 +58,8 @@ macro_rules! book { )? builder.ensure(RustbookSrc { target: self.target, - name: INTERNER.intern_str($book_name), - src: INTERNER.intern_path(builder.src.join($path)), + name: $book_name.to_owned(), + src: builder.src.join($path), parent: Some(self), }) } @@ -108,18 +107,18 @@ impl Step for UnstableBook { builder.ensure(UnstableBookGen { target: self.target }); builder.ensure(RustbookSrc { target: self.target, - name: INTERNER.intern_str("unstable-book"), - src: INTERNER.intern_path(builder.md_doc_out(self.target).join("unstable-book")), + name: "unstable-book".to_owned(), + src: builder.md_doc_out(self.target).join("unstable-book"), parent: Some(self), }) } } -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +#[derive(Debug, Clone, Hash, PartialEq, Eq)] struct RustbookSrc { target: TargetSelection, - name: Interned, - src: Interned, + name: String, + src: PathBuf, parent: Option

, } @@ -141,7 +140,7 @@ impl Step for RustbookSrc

{ let out = builder.doc_out(target); t!(fs::create_dir_all(&out)); - let out = out.join(name); + let out = out.join(&name); let index = out.join("index.html"); let rustbook = builder.tool_exe(Tool::Rustbook); let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook); @@ -211,8 +210,8 @@ impl Step for TheBook { // build book builder.ensure(RustbookSrc { target, - name: INTERNER.intern_str("book"), - src: INTERNER.intern_path(absolute_path.clone()), + name: "book".to_owned(), + src: absolute_path.clone(), parent: Some(self), }); @@ -220,8 +219,8 @@ impl Step for TheBook { for edition in &["first-edition", "second-edition", "2018-edition"] { builder.ensure(RustbookSrc { target, - name: INTERNER.intern_string(format!("book/{edition}")), - src: INTERNER.intern_path(absolute_path.join(edition)), + name: format!("book/{edition}"), + src: absolute_path.join(edition), // There should only be one book that is marked as the parent for each target, so // treat the other editions as not having a parent. parent: Option::::None, @@ -526,12 +525,12 @@ impl Step for SharedAssets { } } -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Std { pub stage: u32, pub target: TargetSelection, pub format: DocumentationFormat, - crates: Interned>, + crates: Vec, } impl Std { @@ -546,7 +545,7 @@ impl Std { .into_iter() .map(|krate| krate.name.to_string()) .collect(); - Std { stage, target, format, crates: INTERNER.intern_list(crates) } + Std { stage, target, format, crates } } } @@ -721,11 +720,11 @@ fn doc_std( builder.cp_r(&out_dir, out); } -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +#[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct Rustc { pub stage: u32, pub target: TargetSelection, - crates: Interned>, + crates: Vec, } impl Rustc { @@ -735,7 +734,7 @@ impl Rustc { .into_iter() .map(|krate| krate.name.to_string()) .collect(); - Self { stage, target, crates: INTERNER.intern_list(crates) } + Self { stage, target, crates } } } @@ -1189,8 +1188,8 @@ impl Step for RustcBook { // Run rustbook/mdbook to generate the HTML pages. builder.ensure(RustbookSrc { target: self.target, - name: INTERNER.intern_str("rustc"), - src: INTERNER.intern_path(out_base), + name: "rustc".to_owned(), + src: out_base, parent: Some(self), }); } diff --git a/src/bootstrap/src/core/build_steps/install.rs b/src/bootstrap/src/core/build_steps/install.rs index 6726671ddd9b3..41920fabaa974 100644 --- a/src/bootstrap/src/core/build_steps/install.rs +++ b/src/bootstrap/src/core/build_steps/install.rs @@ -13,7 +13,6 @@ use crate::core::builder::{Builder, RunConfig, ShouldRun, Step}; use crate::core::config::{Config, TargetSelection}; use crate::utils::helpers::t; use crate::utils::tarball::GeneratedTarball; -use crate::INTERNER; use crate::{Compiler, Kind}; #[cfg(target_os = "illumos")] @@ -291,7 +290,7 @@ install!((self, builder, _config), RustcCodegenCranelift, alias = "rustc-codegen-cranelift", Self::should_build(_config), only_hosts: true, { if let Some(tarball) = builder.ensure(dist::CodegenBackend { compiler: self.compiler, - backend: INTERNER.intern_str("cranelift"), + backend: "cranelift".to_string(), }) { install_sh(builder, "rustc-codegen-cranelift", self.compiler.stage, Some(self.target), &tarball); } else { diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 4a4497e57db14..659c992d59705 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -26,7 +26,6 @@ use crate::core::builder::{Builder, Compiler, Kind, RunConfig, ShouldRun, Step}; use crate::core::config::flags::get_completion; use crate::core::config::flags::Subcommand; use crate::core::config::TargetSelection; -use crate::utils::cache::{Interned, INTERNER}; use crate::utils::exec::BootstrapCommand; use crate::utils::helpers::{ self, add_link_lib_path, add_rustdoc_cargo_linker_args, dylib_path, dylib_path_var, @@ -38,9 +37,9 @@ use crate::{envify, CLang, DocTests, GitRepo, Mode}; const ADB_TEST_DIR: &str = "/data/local/tmp/work"; -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct CrateBootstrap { - path: Interned, + path: PathBuf, host: TargetSelection, } @@ -58,7 +57,7 @@ impl Step for CrateBootstrap { fn make_run(run: RunConfig<'_>) { for path in run.paths { - let path = INTERNER.intern_path(path.assert_single_path().path.clone()); + let path = path.assert_single_path().path.clone(); run.builder.ensure(CrateBootstrap { host: run.target, path }); } } @@ -623,7 +622,7 @@ impl Step for Miri { // miri tests need to know about the stage sysroot cargo.env("MIRI_SYSROOT", &miri_sysroot); - cargo.env("MIRI_HOST_SYSROOT", sysroot); + cargo.env("MIRI_HOST_SYSROOT", &sysroot); cargo.env("MIRI", &miri); if builder.config.locked_deps { // enforce lockfiles @@ -1646,8 +1645,10 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the } if suite == "debuginfo" { - builder - .ensure(dist::DebuggerScripts { sysroot: builder.sysroot(compiler), host: target }); + builder.ensure(dist::DebuggerScripts { + sysroot: builder.sysroot(compiler).to_path_buf(), + host: target, + }); } // Also provide `rust_test_helpers` for the host. @@ -2378,7 +2379,7 @@ impl Step for RustcGuide { pub struct CrateLibrustc { compiler: Compiler, target: TargetSelection, - crates: Vec>, + crates: Vec, } impl Step for CrateLibrustc { @@ -2394,8 +2395,11 @@ impl Step for CrateLibrustc { let builder = run.builder; let host = run.build_triple(); let compiler = builder.compiler_for(builder.top_stage, host, host); - let crates = - run.paths.iter().map(|p| builder.crate_paths[&p.assert_single_path().path]).collect(); + let crates = run + .paths + .iter() + .map(|p| builder.crate_paths[&p.assert_single_path().path].clone()) + .collect(); builder.ensure(CrateLibrustc { compiler, target: run.target, crates }); } @@ -2418,7 +2422,7 @@ impl Step for CrateLibrustc { fn run_cargo_test<'a>( cargo: impl Into, libtest_args: &[&str], - crates: &[Interned], + crates: &[String], primary_crate: &str, description: impl Into>, compiler: Compiler, @@ -2449,7 +2453,7 @@ fn run_cargo_test<'a>( fn prepare_cargo_test( cargo: impl Into, libtest_args: &[&str], - crates: &[Interned], + crates: &[String], primary_crate: &str, compiler: Compiler, target: TargetSelection, @@ -2477,7 +2481,7 @@ fn prepare_cargo_test( DocTests::No => { let krate = &builder .crates - .get(&INTERNER.intern_str(primary_crate)) + .get(primary_crate) .unwrap_or_else(|| panic!("missing crate {primary_crate}")); if krate.has_lib { cargo.arg("--lib"); @@ -2487,7 +2491,7 @@ fn prepare_cargo_test( DocTests::Yes => {} } - for &krate in crates { + for krate in crates { cargo.arg("-p").arg(krate); } @@ -2529,7 +2533,7 @@ pub struct Crate { pub compiler: Compiler, pub target: TargetSelection, pub mode: Mode, - pub crates: Vec>, + pub crates: Vec, } impl Step for Crate { @@ -2544,8 +2548,11 @@ impl Step for Crate { let builder = run.builder; let host = run.build_triple(); let compiler = builder.compiler_for(builder.top_stage, host, host); - let crates = - run.paths.iter().map(|p| builder.crate_paths[&p.assert_single_path().path]).collect(); + let crates = run + .paths + .iter() + .map(|p| builder.crate_paths[&p.assert_single_path().path].clone()) + .collect(); builder.ensure(Crate { compiler, target: run.target, mode: Mode::Std, crates }); } @@ -2707,7 +2714,7 @@ impl Step for CrateRustdoc { run_cargo_test( cargo, &[], - &[INTERNER.intern_str("rustdoc:0.0.0")], + &["rustdoc:0.0.0".to_string()], "rustdoc", "rustdoc", compiler, @@ -2768,7 +2775,7 @@ impl Step for CrateRustdocJsonTypes { run_cargo_test( cargo, libtest_args, - &[INTERNER.intern_str("rustdoc-json-types")], + &["rustdoc-json-types".to_string()], "rustdoc-json-types", "rustdoc-json-types", compiler, @@ -3194,8 +3201,7 @@ impl Step for CodegenCranelift { return; } - if !builder.config.codegen_backends(run.target).contains(&INTERNER.intern_str("cranelift")) - { + if !builder.config.codegen_backends(run.target).contains(&"cranelift".to_owned()) { builder.info("cranelift not in rust.codegen-backends. skipping"); return; } @@ -3319,7 +3325,7 @@ impl Step for CodegenGCC { return; } - if !builder.config.codegen_backends(run.target).contains(&INTERNER.intern_str("gcc")) { + if !builder.config.codegen_backends(run.target).contains(&"gcc".to_owned()) { builder.info("gcc not in rust.codegen-backends. skipping"); return; } diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs index 8223a80c93107..4927c83760808 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -19,7 +19,7 @@ use crate::core::build_steps::{check, clean, compile, dist, doc, install, run, s use crate::core::config::flags::{Color, Subcommand}; use crate::core::config::{DryRun, SplitDebuginfo, TargetSelection}; use crate::prepare_behaviour_dump_dir; -use crate::utils::cache::{Cache, Interned, INTERNER}; +use crate::utils::cache::Cache; use crate::utils::helpers::{self, add_dylib_path, add_link_lib_path, exe, linker_args}; use crate::utils::helpers::{check_cfg_arg, libdir, linker_flags, output, t, LldThreads}; use crate::EXTRA_CHECK_CFGS; @@ -102,7 +102,7 @@ impl RunConfig<'_> { /// Return a list of crate names selected by `run.paths`. #[track_caller] - pub fn cargo_crates_in_set(&self) -> Interned> { + pub fn cargo_crates_in_set(&self) -> Vec { let mut crates = Vec::new(); for krate in &self.paths { let path = krate.assert_single_path(); @@ -111,7 +111,7 @@ impl RunConfig<'_> { }; crates.push(crate_name.to_string()); } - INTERNER.intern_list(crates) + crates } /// Given an `alias` selected by the `Step` and the paths passed on the command line, @@ -120,7 +120,7 @@ impl RunConfig<'_> { /// Normally, people will pass *just* `library` if they pass it. /// But it's possible (although strange) to pass something like `library std core`. /// Build all crates anyway, as if they hadn't passed the other args. - pub fn make_run_crates(&self, alias: Alias) -> Interned> { + pub fn make_run_crates(&self, alias: Alias) -> Vec { let has_alias = self.paths.iter().any(|set| set.assert_single_path().path.ends_with(alias.as_str())); if !has_alias { @@ -133,7 +133,7 @@ impl RunConfig<'_> { }; let crate_names = crates.into_iter().map(|krate| krate.name.to_string()).collect(); - INTERNER.intern_list(crate_names) + crate_names } } @@ -1062,26 +1062,26 @@ impl<'a> Builder<'a> { } } - pub fn sysroot(&self, compiler: Compiler) -> Interned { + pub fn sysroot(&self, compiler: Compiler) -> PathBuf { self.ensure(compile::Sysroot::new(compiler)) } /// Returns the libdir where the standard library and other artifacts are /// found for a compiler's sysroot. - pub fn sysroot_libdir(&self, compiler: Compiler, target: TargetSelection) -> Interned { + pub fn sysroot_libdir(&self, compiler: Compiler, target: TargetSelection) -> PathBuf { #[derive(Debug, Clone, Hash, PartialEq, Eq)] struct Libdir { compiler: Compiler, target: TargetSelection, } impl Step for Libdir { - type Output = Interned; + type Output = PathBuf; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.never() } - fn run(self, builder: &Builder<'_>) -> Interned { + fn run(self, builder: &Builder<'_>) -> PathBuf { let lib = builder.sysroot_libdir_relative(self.compiler); let sysroot = builder .sysroot(self.compiler) @@ -1110,7 +1110,7 @@ impl<'a> Builder<'a> { ); } - INTERNER.intern_path(sysroot) + sysroot } } self.ensure(Libdir { compiler, target }) diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index 2cbebbcf4e2af..6a1dde51603be 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -608,7 +608,7 @@ mod dist { compiler: Compiler { host, stage: 0 }, target: host, mode: Mode::Std, - crates: vec![INTERNER.intern_str("std")], + crates: vec!["std".to_owned()], },] ); } diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 875a4efae02fc..b8301bdbdbc35 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -263,7 +263,7 @@ pub struct Config { pub rustc_default_linker: Option, pub rust_optimize_tests: bool, pub rust_dist_src: bool, - pub rust_codegen_backends: Vec>, + pub rust_codegen_backends: Vec, pub rust_verify_llvm_ir: bool, pub rust_thin_lto_import_instr_limit: Option, pub rust_remap_debuginfo: bool, @@ -457,6 +457,8 @@ impl std::str::FromStr for RustcLto { } #[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] +// N.B.: This type is used everywhere, and the entire codebase relies on it being Copy. +// Making !Copy is highly nontrivial! pub struct TargetSelection { pub triple: Interned, file: Option>, @@ -579,7 +581,7 @@ pub struct Target { pub wasi_root: Option, pub qemu_rootfs: Option, pub no_std: bool, - pub codegen_backends: Option>>, + pub codegen_backends: Option>, } impl Target { @@ -1161,7 +1163,7 @@ impl Config { channel: "dev".to_string(), codegen_tests: true, rust_dist_src: true, - rust_codegen_backends: vec![INTERNER.intern_str("llvm")], + rust_codegen_backends: vec!["llvm".to_owned()], deny_warnings: true, bindir: "bin".into(), dist_include_mingw_linker: true, @@ -1689,7 +1691,7 @@ impl Config { } } - INTERNER.intern_str(s) + s.clone() }).collect(); } @@ -1876,7 +1878,7 @@ impl Config { } } - INTERNER.intern_str(s) + s.clone() }).collect()); } @@ -2263,7 +2265,7 @@ impl Config { } pub fn llvm_enabled(&self, target: TargetSelection) -> bool { - self.codegen_backends(target).contains(&INTERNER.intern_str("llvm")) + self.codegen_backends(target).contains(&"llvm".to_owned()) } pub fn llvm_libunwind(&self, target: TargetSelection) -> LlvmLibunwind { @@ -2282,14 +2284,14 @@ impl Config { self.submodules.unwrap_or(rust_info.is_managed_git_subrepository()) } - pub fn codegen_backends(&self, target: TargetSelection) -> &[Interned] { + pub fn codegen_backends(&self, target: TargetSelection) -> &[String] { self.target_config .get(&target) .and_then(|cfg| cfg.codegen_backends.as_deref()) .unwrap_or(&self.rust_codegen_backends) } - pub fn default_codegen_backend(&self, target: TargetSelection) -> Option> { + pub fn default_codegen_backend(&self, target: TargetSelection) -> Option { self.codegen_backends(target).first().cloned() } diff --git a/src/bootstrap/src/core/metadata.rs b/src/bootstrap/src/core/metadata.rs index 5802082326a88..08a96407a6917 100644 --- a/src/bootstrap/src/core/metadata.rs +++ b/src/bootstrap/src/core/metadata.rs @@ -3,7 +3,6 @@ use std::process::Command; use serde_derive::Deserialize; -use crate::utils::cache::INTERNER; use crate::utils::helpers::output; use crate::{t, Build, Crate}; @@ -43,19 +42,19 @@ struct Target { pub fn build(build: &mut Build) { for package in workspace_members(build) { if package.source.is_none() { - let name = INTERNER.intern_string(package.name); + let name = package.name; let mut path = PathBuf::from(package.manifest_path); path.pop(); let deps = package .dependencies .into_iter() .filter(|dep| dep.source.is_none()) - .map(|dep| INTERNER.intern_string(dep.name)) + .map(|dep| dep.name) .collect(); let has_lib = package.targets.iter().any(|t| t.kind.iter().any(|k| k == "lib")); - let krate = Crate { name, deps, path, has_lib }; + let krate = Crate { name: name.clone(), deps, path, has_lib }; let relative_path = krate.local_path(build); - build.crates.insert(name, krate); + build.crates.insert(name.clone(), krate); let existing_path = build.crate_paths.insert(relative_path, name); assert!( existing_path.is_none(), diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index f7748621d93ba..a90f19475aa0f 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -41,7 +41,6 @@ use crate::core::builder::Kind; use crate::core::config::{flags, LldMode}; use crate::core::config::{DryRun, Target}; use crate::core::config::{LlvmLibunwind, TargetSelection}; -use crate::utils::cache::{Interned, INTERNER}; use crate::utils::exec::{BehaviorOnFailure, BootstrapCommand, OutputMode}; use crate::utils::helpers::{self, dir_is_empty, exe, libdir, mtime, output, symlink_dir}; @@ -191,8 +190,8 @@ pub struct Build { ranlib: RefCell>, // Miscellaneous // allow bidirectional lookups: both name -> path and path -> name - crates: HashMap, Crate>, - crate_paths: HashMap>, + crates: HashMap, + crate_paths: HashMap, is_sudo: bool, ci_env: CiEnv, delayed_failures: RefCell>, @@ -204,8 +203,8 @@ pub struct Build { #[derive(Debug, Clone)] struct Crate { - name: Interned, - deps: HashSet>, + name: String, + deps: HashSet, path: PathBuf, has_lib: bool, } @@ -829,8 +828,8 @@ impl Build { } /// Output directory for some generated md crate documentation for a target (temporary) - fn md_doc_out(&self, target: TargetSelection) -> Interned { - INTERNER.intern_path(self.out.join(&*target.triple).join("md-doc")) + fn md_doc_out(&self, target: TargetSelection) -> PathBuf { + self.out.join(&*target.triple).join("md-doc") } /// Returns `true` if this is an external version of LLVM not managed by bootstrap. @@ -1538,7 +1537,7 @@ impl Build { /// "local" crates (those in the local source tree, not from a registry). fn in_tree_crates(&self, root: &str, target: Option) -> Vec<&Crate> { let mut ret = Vec::new(); - let mut list = vec![INTERNER.intern_str(root)]; + let mut list = vec![root.to_owned()]; let mut visited = HashSet::new(); while let Some(krate) = list.pop() { let krate = self @@ -1564,11 +1563,11 @@ impl Build { && (dep != "rustc_codegen_llvm" || self.config.hosts.iter().any(|host| self.config.llvm_enabled(*host))) { - list.push(*dep); + list.push(dep.clone()); } } } - ret.sort_unstable_by_key(|krate| krate.name); // reproducible order needed for tests + ret.sort_unstable_by_key(|krate| krate.name.clone()); // reproducible order needed for tests ret } diff --git a/src/bootstrap/src/utils/cache.rs b/src/bootstrap/src/utils/cache.rs index 2b86585a9d3c0..e18dcbb47bea0 100644 --- a/src/bootstrap/src/utils/cache.rs +++ b/src/bootstrap/src/utils/cache.rs @@ -194,17 +194,6 @@ impl Interner { pub fn intern_str(&self, s: &str) -> Interned { self.strs.lock().unwrap().intern_borrow(s) } - pub fn intern_string(&self, s: String) -> Interned { - self.strs.lock().unwrap().intern(s) - } - - pub fn intern_path(&self, s: PathBuf) -> Interned { - self.paths.lock().unwrap().intern(s) - } - - pub fn intern_list(&self, v: Vec) -> Interned> { - self.lists.lock().unwrap().intern(v) - } } pub static INTERNER: Lazy = Lazy::new(Interner::default); From 1195518a5e59e6d37c78db24c637780d2c662f3b Mon Sep 17 00:00:00 2001 From: Kornel Date: Fri, 1 Mar 2024 13:37:08 +0000 Subject: [PATCH 06/16] Helper function for resolve_path --- compiler/rustc_expand/src/base.rs | 25 +++++++++++-------------- compiler/rustc_span/src/lib.rs | 11 +++++++++++ 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 69dfb48919cdb..a5f54b6b113e7 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -1233,21 +1233,18 @@ pub fn resolve_path(sess: &Session, path: impl Into, span: Span) -> PRe // after macro expansion (that is, they are unhygienic). if !path.is_absolute() { let callsite = span.source_callsite(); - let mut result = match sess.source_map().span_to_filename(callsite) { - FileName::Real(name) => name - .into_local_path() - .expect("attempting to resolve a file path in an external file"), - FileName::DocTest(path, _) => path, - other => { - return Err(sess.dcx().create_err(errors::ResolveRelativePath { - span, - path: sess.source_map().filename_for_diagnostics(&other).to_string(), - })); - } + let source_map = sess.source_map(); + let Some(mut base_path) = source_map.span_to_filename(callsite).into_local_path() else { + return Err(sess.dcx().create_err(errors::ResolveRelativePath { + span, + path: source_map + .filename_for_diagnostics(&source_map.span_to_filename(callsite)) + .to_string(), + })); }; - result.pop(); - result.push(path); - Ok(result) + base_path.pop(); + base_path.push(path); + Ok(base_path) } else { Ok(path) } diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 616a7ccc7c64f..0c974ef4ca3eb 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -427,6 +427,17 @@ impl FileName { src.hash(&mut hasher); FileName::InlineAsm(hasher.finish()) } + + /// Returns the path suitable for reading from the file system on the local host, + /// if this information exists. + /// Avoid embedding this in build artifacts; see `remapped_path_if_available()` for that. + pub fn into_local_path(self) -> Option { + match self { + FileName::Real(path) => path.into_local_path(), + FileName::DocTest(path, _) => Some(path), + _ => None, + } + } } /// Represents a span. From 25ab1c70734f101596e8703d8c3a4e65da55ec01 Mon Sep 17 00:00:00 2001 From: Kornel Date: Fri, 1 Mar 2024 02:49:02 +0000 Subject: [PATCH 07/16] Suggest correct path in include_bytes! --- .../rustc_builtin_macros/src/source_util.rs | 150 ++++++++++++++---- compiler/rustc_expand/src/base.rs | 16 +- tests/ui/include-macros/parent_dir.rs | 12 ++ tests/ui/include-macros/parent_dir.stderr | 50 ++++++ tests/ui/macros/macros-nonfatal-errors.rs | 2 +- tests/ui/macros/macros-nonfatal-errors.stderr | 4 +- 6 files changed, 200 insertions(+), 34 deletions(-) create mode 100644 tests/ui/include-macros/parent_dir.rs create mode 100644 tests/ui/include-macros/parent_dir.stderr diff --git a/compiler/rustc_builtin_macros/src/source_util.rs b/compiler/rustc_builtin_macros/src/source_util.rs index 2da9bda19e034..134a6baea6e8b 100644 --- a/compiler/rustc_builtin_macros/src/source_util.rs +++ b/compiler/rustc_builtin_macros/src/source_util.rs @@ -3,18 +3,20 @@ use rustc_ast::ptr::P; use rustc_ast::token; use rustc_ast::tokenstream::TokenStream; use rustc_ast_pretty::pprust; +use rustc_data_structures::sync::Lrc; use rustc_expand::base::{ - check_zero_tts, get_single_str_from_tts, parse_expr, resolve_path, DummyResult, ExtCtxt, - MacEager, MacResult, + check_zero_tts, get_single_str_from_tts, get_single_str_spanned_from_tts, parse_expr, + resolve_path, DummyResult, ExtCtxt, MacEager, MacResult, }; use rustc_expand::module::DirOwnership; use rustc_parse::new_parser_from_file; use rustc_parse::parser::{ForceCollect, Parser}; use rustc_session::lint::builtin::INCOMPLETE_INCLUDE; +use rustc_span::source_map::SourceMap; use rustc_span::symbol::Symbol; use rustc_span::{Pos, Span}; - use smallvec::SmallVec; +use std::path::{Path, PathBuf}; use std::rc::Rc; // These macros all relate to the file system; they either return @@ -180,32 +182,22 @@ pub fn expand_include_str( tts: TokenStream, ) -> Box { let sp = cx.with_def_site_ctxt(sp); - let file = match get_single_str_from_tts(cx, sp, tts, "include_str!") { - Ok(file) => file, + let (path, path_span) = match get_single_str_spanned_from_tts(cx, sp, tts, "include_str!") { + Ok(res) => res, Err(guar) => return DummyResult::any(sp, guar), }; - let file = match resolve_path(&cx.sess, file.as_str(), sp) { - Ok(f) => f, - Err(err) => { - let guar = err.emit(); - return DummyResult::any(sp, guar); - } - }; - match cx.source_map().load_binary_file(&file) { + match load_binary_file(cx, path.as_str().as_ref(), sp, path_span) { Ok(bytes) => match std::str::from_utf8(&bytes) { Ok(src) => { let interned_src = Symbol::intern(src); MacEager::expr(cx.expr_str(sp, interned_src)) } Err(_) => { - let guar = cx.dcx().span_err(sp, format!("{} wasn't a utf-8 file", file.display())); + let guar = cx.dcx().span_err(sp, format!("`{path}` wasn't a utf-8 file")); DummyResult::any(sp, guar) } }, - Err(e) => { - let guar = cx.dcx().span_err(sp, format!("couldn't read {}: {}", file.display(), e)); - DummyResult::any(sp, guar) - } + Err(dummy) => dummy, } } @@ -215,25 +207,123 @@ pub fn expand_include_bytes( tts: TokenStream, ) -> Box { let sp = cx.with_def_site_ctxt(sp); - let file = match get_single_str_from_tts(cx, sp, tts, "include_bytes!") { - Ok(file) => file, + let (path, path_span) = match get_single_str_spanned_from_tts(cx, sp, tts, "include_bytes!") { + Ok(res) => res, Err(guar) => return DummyResult::any(sp, guar), }; - let file = match resolve_path(&cx.sess, file.as_str(), sp) { - Ok(f) => f, + match load_binary_file(cx, path.as_str().as_ref(), sp, path_span) { + Ok(bytes) => { + let expr = cx.expr(sp, ast::ExprKind::IncludedBytes(bytes)); + MacEager::expr(expr) + } + Err(dummy) => dummy, + } +} + +fn load_binary_file( + cx: &mut ExtCtxt<'_>, + original_path: &Path, + macro_span: Span, + path_span: Span, +) -> Result, Box> { + let resolved_path = match resolve_path(&cx.sess, original_path, macro_span) { + Ok(path) => path, Err(err) => { let guar = err.emit(); - return DummyResult::any(sp, guar); + return Err(DummyResult::any(macro_span, guar)); } }; - match cx.source_map().load_binary_file(&file) { - Ok(bytes) => { - let expr = cx.expr(sp, ast::ExprKind::IncludedBytes(bytes)); - MacEager::expr(expr) + match cx.source_map().load_binary_file(&resolved_path) { + Ok(data) => Ok(data), + Err(io_err) => { + let mut err = cx.dcx().struct_span_err( + macro_span, + format!("couldn't read `{}`: {io_err}", resolved_path.display()), + ); + + if original_path.is_relative() { + let source_map = cx.sess.source_map(); + let new_path = source_map + .span_to_filename(macro_span.source_callsite()) + .into_local_path() + .and_then(|src| find_path_suggestion(source_map, src.parent()?, original_path)) + .and_then(|path| path.into_os_string().into_string().ok()); + + if let Some(new_path) = new_path { + err.span_suggestion( + path_span, + "there is a file with the same name in a different directory", + format!("\"{}\"", new_path.escape_debug()), + rustc_lint_defs::Applicability::MachineApplicable, + ); + } + } + let guar = err.emit(); + Err(DummyResult::any(macro_span, guar)) } - Err(e) => { - let guar = cx.dcx().span_err(sp, format!("couldn't read {}: {}", file.display(), e)); - DummyResult::any(sp, guar) + } +} + +fn find_path_suggestion( + source_map: &SourceMap, + base_dir: &Path, + wanted_path: &Path, +) -> Option { + // Fix paths that assume they're relative to cargo manifest dir + let mut base_c = base_dir.components(); + let mut wanted_c = wanted_path.components(); + let mut without_base = None; + while let Some(wanted_next) = wanted_c.next() { + if wanted_c.as_path().file_name().is_none() { + break; + } + // base_dir may be absolute + while let Some(base_next) = base_c.next() { + if base_next == wanted_next { + without_base = Some(wanted_c.as_path()); + break; + } + } + } + let root_absolute = without_base.into_iter().map(PathBuf::from); + + let base_dir_components = base_dir.components().count(); + // Avoid going all the way to the root dir + let max_parent_components = if base_dir.is_relative() { + base_dir_components + 1 + } else { + base_dir_components.saturating_sub(1) + }; + + // Try with additional leading ../ + let mut prefix = PathBuf::new(); + let add = std::iter::from_fn(|| { + prefix.push(".."); + Some(prefix.join(wanted_path)) + }) + .take(max_parent_components.min(3)); + + // Try without leading directories + let mut trimmed_path = wanted_path; + let remove = std::iter::from_fn(|| { + let mut components = trimmed_path.components(); + let removed = components.next()?; + trimmed_path = components.as_path(); + let _ = trimmed_path.file_name()?; // ensure there is a file name left + Some([ + Some(trimmed_path.to_path_buf()), + (removed != std::path::Component::ParentDir) + .then(|| Path::new("..").join(trimmed_path)), + ]) + }) + .flatten() + .flatten() + .take(4); + + for new_path in root_absolute.chain(add).chain(remove) { + if source_map.file_exists(&base_dir.join(&new_path)) { + return Some(new_path); } } + None } diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index a5f54b6b113e7..58589ebdca675 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -1341,6 +1341,15 @@ pub fn get_single_str_from_tts( tts: TokenStream, name: &str, ) -> Result { + get_single_str_spanned_from_tts(cx, span, tts, name).map(|(s, _)| s) +} + +pub fn get_single_str_spanned_from_tts( + cx: &mut ExtCtxt<'_>, + span: Span, + tts: TokenStream, + name: &str, +) -> Result<(Symbol, Span), ErrorGuaranteed> { let mut p = cx.new_parser_from_tts(tts); if p.token == token::Eof { let guar = cx.dcx().emit_err(errors::OnlyOneArgument { span, name }); @@ -1352,7 +1361,12 @@ pub fn get_single_str_from_tts( if p.token != token::Eof { cx.dcx().emit_err(errors::OnlyOneArgument { span, name }); } - expr_to_string(cx, ret, "argument must be a string literal").map(|(s, _)| s) + expr_to_spanned_string(cx, ret, "argument must be a string literal") + .map_err(|err| match err { + Ok((err, _)) => err.emit(), + Err(guar) => guar, + }) + .map(|(symbol, _style, span)| (symbol, span)) } /// Extracts comma-separated expressions from `tts`. diff --git a/tests/ui/include-macros/parent_dir.rs b/tests/ui/include-macros/parent_dir.rs new file mode 100644 index 0000000000000..321baf77025d2 --- /dev/null +++ b/tests/ui/include-macros/parent_dir.rs @@ -0,0 +1,12 @@ +//@ normalize-stderr-test: "`: .*\(os error" -> "`: $$FILE_NOT_FOUND_MSG (os error" + +fn main() { + let _ = include_str!("include-macros/file.txt"); //~ ERROR couldn't read + //~^HELP different directory + let _ = include_str!("hello.rs"); //~ ERROR couldn't read + //~^HELP different directory + let _ = include_bytes!("../../data.bin"); //~ ERROR couldn't read + //~^HELP different directory + let _ = include_str!("tests/ui/include-macros/file.txt"); //~ ERROR couldn't read + //~^HELP different directory +} diff --git a/tests/ui/include-macros/parent_dir.stderr b/tests/ui/include-macros/parent_dir.stderr new file mode 100644 index 0000000000000..7610360815b7a --- /dev/null +++ b/tests/ui/include-macros/parent_dir.stderr @@ -0,0 +1,50 @@ +error: couldn't read `$DIR/include-macros/file.txt`: $FILE_NOT_FOUND_MSG (os error 2) + --> $DIR/parent_dir.rs:4:13 + | +LL | let _ = include_str!("include-macros/file.txt"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the macro `include_str` (in Nightly builds, run with -Z macro-backtrace for more info) +help: there is a file with the same name in a different directory + | +LL | let _ = include_str!("file.txt"); + | ~~~~~~~~~~ + +error: couldn't read `$DIR/hello.rs`: $FILE_NOT_FOUND_MSG (os error 2) + --> $DIR/parent_dir.rs:6:13 + | +LL | let _ = include_str!("hello.rs"); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the macro `include_str` (in Nightly builds, run with -Z macro-backtrace for more info) +help: there is a file with the same name in a different directory + | +LL | let _ = include_str!("../hello.rs"); + | ~~~~~~~~~~~~~ + +error: couldn't read `$DIR/../../data.bin`: $FILE_NOT_FOUND_MSG (os error 2) + --> $DIR/parent_dir.rs:8:13 + | +LL | let _ = include_bytes!("../../data.bin"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the macro `include_bytes` (in Nightly builds, run with -Z macro-backtrace for more info) +help: there is a file with the same name in a different directory + | +LL | let _ = include_bytes!("data.bin"); + | ~~~~~~~~~~ + +error: couldn't read `$DIR/tests/ui/include-macros/file.txt`: $FILE_NOT_FOUND_MSG (os error 2) + --> $DIR/parent_dir.rs:10:13 + | +LL | let _ = include_str!("tests/ui/include-macros/file.txt"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the macro `include_str` (in Nightly builds, run with -Z macro-backtrace for more info) +help: there is a file with the same name in a different directory + | +LL | let _ = include_str!("file.txt"); + | ~~~~~~~~~~ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/macros/macros-nonfatal-errors.rs b/tests/ui/macros/macros-nonfatal-errors.rs index 20e6d70500358..65cb899e0941b 100644 --- a/tests/ui/macros/macros-nonfatal-errors.rs +++ b/tests/ui/macros/macros-nonfatal-errors.rs @@ -1,4 +1,4 @@ -//@ normalize-stderr-test: "existed:.*\(" -> "existed: $$FILE_NOT_FOUND_MSG (" +//@ normalize-stderr-test: "`: .*\(" -> "`: $$FILE_NOT_FOUND_MSG (" // test that errors in a (selection) of macros don't kill compilation // immediately, so that we get more errors listed at a time. diff --git a/tests/ui/macros/macros-nonfatal-errors.stderr b/tests/ui/macros/macros-nonfatal-errors.stderr index ca373ea6cd9e4..d02d2399bbadb 100644 --- a/tests/ui/macros/macros-nonfatal-errors.stderr +++ b/tests/ui/macros/macros-nonfatal-errors.stderr @@ -200,7 +200,7 @@ error: argument must be a string literal LL | include_str!(invalid); | ^^^^^^^ -error: couldn't read $DIR/i'd be quite surprised if a file with this name existed: $FILE_NOT_FOUND_MSG (os error 2) +error: couldn't read `$DIR/i'd be quite surprised if a file with this name existed`: $FILE_NOT_FOUND_MSG (os error 2) --> $DIR/macros-nonfatal-errors.rs:113:5 | LL | include_str!("i'd be quite surprised if a file with this name existed"); @@ -214,7 +214,7 @@ error: argument must be a string literal LL | include_bytes!(invalid); | ^^^^^^^ -error: couldn't read $DIR/i'd be quite surprised if a file with this name existed: $FILE_NOT_FOUND_MSG (os error 2) +error: couldn't read `$DIR/i'd be quite surprised if a file with this name existed`: $FILE_NOT_FOUND_MSG (os error 2) --> $DIR/macros-nonfatal-errors.rs:115:5 | LL | include_bytes!("i'd be quite surprised if a file with this name existed"); From fbb2129e93bcb0b143df7bbc94c93fd83feeb853 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 3 Mar 2024 19:18:25 +0000 Subject: [PATCH 08/16] Fix test for multiline span ui display The compiler output changed in such a way that this test was no longer testing what it was meant to. --- .../codemap_tests/huge_multispan_highlight.rs | 30 +++++++++++++++-- .../huge_multispan_highlight.stderr | 33 +++++++++++++------ 2 files changed, 51 insertions(+), 12 deletions(-) diff --git a/tests/ui/codemap_tests/huge_multispan_highlight.rs b/tests/ui/codemap_tests/huge_multispan_highlight.rs index 623c59081d0fe..9e445f73ec742 100644 --- a/tests/ui/codemap_tests/huge_multispan_highlight.rs +++ b/tests/ui/codemap_tests/huge_multispan_highlight.rs @@ -1,5 +1,6 @@ fn main() { - let x = "foo"; + let _ = match true { + true => ( @@ -87,5 +88,30 @@ fn main() { - let y = &mut x; //~ ERROR cannot borrow + + ), + false => " + + + + + + + + + + + + + + + + + + + + + + ", //~^^^^^^^^^^^^^^^^^^^^^^ ERROR `match` arms have incompatible types + }; } diff --git a/tests/ui/codemap_tests/huge_multispan_highlight.stderr b/tests/ui/codemap_tests/huge_multispan_highlight.stderr index d2923875c94cf..6c5f965099dd7 100644 --- a/tests/ui/codemap_tests/huge_multispan_highlight.stderr +++ b/tests/ui/codemap_tests/huge_multispan_highlight.stderr @@ -1,14 +1,27 @@ -error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable - --> $DIR/huge_multispan_highlight.rs:90:13 +error[E0308]: `match` arms have incompatible types + --> $DIR/huge_multispan_highlight.rs:93:18 | -LL | let y = &mut x; - | ^^^^^^ cannot borrow as mutable - | -help: consider changing this to be mutable - | -LL | let mut x = "foo"; - | +++ +LL | let _ = match true { + | ---------- `match` arms have incompatible types +LL | true => ( + | _________________- +LL | | +LL | | +LL | | +... | +LL | | +LL | | ), + | |_________- this is found to be of type `()` +LL | false => " + | __________________^ +LL | | +LL | | +LL | | +... | +LL | | +LL | | ", + | |_________^ expected `()`, found `&str` error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0596`. +For more information about this error, try `rustc --explain E0308`. From 9693a46c9ae5728a00c07ac7d3ec4c8706a3edae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 3 Mar 2024 19:21:44 +0000 Subject: [PATCH 09/16] Move multispan test to svg output --- .../codemap_tests/huge_multispan_highlight.rs | 6 +- .../huge_multispan_highlight.stderr | 27 ------- .../huge_multispan_highlight.svg | 80 +++++++++++++++++++ 3 files changed, 85 insertions(+), 28 deletions(-) delete mode 100644 tests/ui/codemap_tests/huge_multispan_highlight.stderr create mode 100644 tests/ui/codemap_tests/huge_multispan_highlight.svg diff --git a/tests/ui/codemap_tests/huge_multispan_highlight.rs b/tests/ui/codemap_tests/huge_multispan_highlight.rs index 9e445f73ec742..6bf4afb8ebd97 100644 --- a/tests/ui/codemap_tests/huge_multispan_highlight.rs +++ b/tests/ui/codemap_tests/huge_multispan_highlight.rs @@ -1,3 +1,7 @@ +//@ compile-flags: --error-format=human --color=always +//@ ignore-windows +// Temporary until next release: +//@ ignore-stage2 fn main() { let _ = match true { true => ( @@ -112,6 +116,6 @@ fn main() { - ", //~^^^^^^^^^^^^^^^^^^^^^^ ERROR `match` arms have incompatible types + ", }; } diff --git a/tests/ui/codemap_tests/huge_multispan_highlight.stderr b/tests/ui/codemap_tests/huge_multispan_highlight.stderr deleted file mode 100644 index 6c5f965099dd7..0000000000000 --- a/tests/ui/codemap_tests/huge_multispan_highlight.stderr +++ /dev/null @@ -1,27 +0,0 @@ -error[E0308]: `match` arms have incompatible types - --> $DIR/huge_multispan_highlight.rs:93:18 - | -LL | let _ = match true { - | ---------- `match` arms have incompatible types -LL | true => ( - | _________________- -LL | | -LL | | -LL | | -... | -LL | | -LL | | ), - | |_________- this is found to be of type `()` -LL | false => " - | __________________^ -LL | | -LL | | -LL | | -... | -LL | | -LL | | ", - | |_________^ expected `()`, found `&str` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/codemap_tests/huge_multispan_highlight.svg b/tests/ui/codemap_tests/huge_multispan_highlight.svg new file mode 100644 index 0000000000000..cc3449f936890 --- /dev/null +++ b/tests/ui/codemap_tests/huge_multispan_highlight.svg @@ -0,0 +1,80 @@ + + + + + + + error[E0308]: `match` arms have incompatible types + + --> $DIR/huge_multispan_highlight.rs:97:18 + + | + + LL | let _ = match true { + + | ---------- `match` arms have incompatible types + + LL | true => ( + + | _________________- + + LL | | + + LL | | + + LL | | + + ... | + + LL | | + + LL | | ), + + | |_________- this is found to be of type `()` + + LL | false => " + + | __________________^ + + LL | | + + LL | | + + LL | | + + ... | + + LL | | + + LL | | ", + + | |_________^ expected `()`, found `&str` + + + + error: aborting due to 1 previous error + + + + For more information about this error, try `rustc --explain E0308`. + + + + + + From e119b3265337f5f022e394eeba62f54ac84965c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 5 Mar 2024 16:24:30 +0000 Subject: [PATCH 10/16] When displaying multispans, ignore empty lines adjacent to `...` ``` error[E0308]: `match` arms have incompatible types --> tests/ui/codemap_tests/huge_multispan_highlight.rs:98:18 | 6 | let _ = match true { | ---------- `match` arms have incompatible types 7 | true => ( | _________________- 8 | | // last line shown in multispan header ... | 96 | | 97 | | ), | |_________- this is found to be of type `()` 98 | false => " | __________________^ ... | 119 | | 120 | | ", | |_________^ expected `()`, found `&str` error[E0308]: `match` arms have incompatible types --> tests/ui/codemap_tests/huge_multispan_highlight.rs:215:18 | 122 | let _ = match true { | ---------- `match` arms have incompatible types 123 | true => ( | _________________- 124 | | 125 | | 1 // last line shown in multispan header ... | 213 | | 214 | | ), | |_________- this is found to be of type `{integer}` 215 | false => " | __________________^ 216 | | 217 | | 218 | | 1 last line shown in multispan ... | 237 | | 238 | | ", | |_________^ expected integer, found `&str` ``` --- compiler/rustc_errors/src/emitter.rs | 49 +++++- compiler/rustc_expand/src/tests.rs | 3 +- .../clippy/tests/ui/async_yields_async.stderr | 3 +- .../empty_line_after_outer_attribute.stderr | 3 +- tests/rustdoc-ui/lints/check.stderr | 2 - ...issue-109271-pass-self-into-closure.stderr | 3 +- .../codemap_tests/huge_multispan_highlight.rs | 161 +++++++++++++++--- .../huge_multispan_highlight.svg | 80 ++++++--- .../derive-in-eager-expansion-hang.stderr | 3 +- tests/ui/offset-of/offset-of-tuple.stderr | 1 - .../effective_visibilities_invariants.stderr | 1 - ...-match-prior-arm-bool-expected-unit.stderr | 3 +- 12 files changed, 252 insertions(+), 60 deletions(-) diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 57b8df52f4b79..a01677e4b3158 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -1638,6 +1638,27 @@ impl HumanEmitter { *style, ); } + if let Some(line) = annotated_file.lines.get(line_idx) { + for ann in &line.annotations { + if let AnnotationType::MultilineStart(pos) = ann.annotation_type + { + // In the case where we have elided the entire start of the + // multispan because those lines were empty, we still need + // to draw the `|`s across the `...`. + draw_multiline_line( + &mut buffer, + last_buffer_line_num, + width_offset, + pos, + if ann.is_primary { + Style::UnderlinePrimary + } else { + Style::UnderlineSecondary + }, + ); + } + } + } } else if line_idx_delta == 2 { let unannotated_line = annotated_file .file @@ -1665,6 +1686,24 @@ impl HumanEmitter { *style, ); } + if let Some(line) = annotated_file.lines.get(line_idx) { + for ann in &line.annotations { + if let AnnotationType::MultilineStart(pos) = ann.annotation_type + { + draw_multiline_line( + &mut buffer, + last_buffer_line_num, + width_offset, + pos, + if ann.is_primary { + Style::UnderlinePrimary + } else { + Style::UnderlineSecondary + }, + ); + } + } + } } } @@ -2417,7 +2456,15 @@ impl FileWithAnnotatedLines { // the beginning doesn't have an underline, but the current logic seems to be // working correctly. let middle = min(ann.line_start + 4, ann.line_end); - for line in ann.line_start + 1..middle { + // We'll show up to 4 lines past the beginning of the multispan start. + // We will *not* include the tail of lines that are only whitespace. + let until = (ann.line_start..middle) + .rev() + .filter_map(|line| file.get_line(line - 1).map(|s| (line + 1, s))) + .find(|(_, s)| !s.trim().is_empty()) + .map(|(line, _)| line) + .unwrap_or(ann.line_start); + for line in ann.line_start + 1..until { // Every `|` that joins the beginning of the span (`___^`) to the end (`|__^`). add_annotation_to_file(&mut output, file.clone(), line, ann.as_line()); } diff --git a/compiler/rustc_expand/src/tests.rs b/compiler/rustc_expand/src/tests.rs index a3510dc9bff4d..2b0b58eb1d924 100644 --- a/compiler/rustc_expand/src/tests.rs +++ b/compiler/rustc_expand/src/tests.rs @@ -276,8 +276,7 @@ error: foo | 2 | fn foo() { | __________^ -3 | | -4 | | +... | 5 | | } | |___^ test diff --git a/src/tools/clippy/tests/ui/async_yields_async.stderr b/src/tools/clippy/tests/ui/async_yields_async.stderr index f1fae6549de4c..991ad7ae0ae2f 100644 --- a/src/tools/clippy/tests/ui/async_yields_async.stderr +++ b/src/tools/clippy/tests/ui/async_yields_async.stderr @@ -81,8 +81,7 @@ LL | let _m = async || { | _______________________- LL | | println!("I'm bored"); LL | | // Some more stuff -LL | | -LL | | // Finally something to await +... | LL | | CustomFutureType | | ^^^^^^^^^^^^^^^^ | | | diff --git a/src/tools/clippy/tests/ui/empty_line_after_outer_attribute.stderr b/src/tools/clippy/tests/ui/empty_line_after_outer_attribute.stderr index 1b5b00a4a83bb..b43e6e30da220 100644 --- a/src/tools/clippy/tests/ui/empty_line_after_outer_attribute.stderr +++ b/src/tools/clippy/tests/ui/empty_line_after_outer_attribute.stderr @@ -22,8 +22,7 @@ error: found an empty line after an outer attribute. Perhaps you forgot to add a --> tests/ui/empty_line_after_outer_attribute.rs:28:1 | LL | / #[crate_type = "lib"] -LL | | -LL | | +... | LL | | fn with_two_newlines() { assert!(true) } | |_ diff --git a/tests/rustdoc-ui/lints/check.stderr b/tests/rustdoc-ui/lints/check.stderr index c5ed5d0c3efbe..acdb8128443fd 100644 --- a/tests/rustdoc-ui/lints/check.stderr +++ b/tests/rustdoc-ui/lints/check.stderr @@ -4,7 +4,6 @@ warning: missing documentation for the crate LL | / #![feature(rustdoc_missing_doc_code_examples)] LL | | LL | | -LL | | ... | LL | | LL | | pub fn foo() {} @@ -39,7 +38,6 @@ warning: missing code example in this documentation LL | / #![feature(rustdoc_missing_doc_code_examples)] LL | | LL | | -LL | | ... | LL | | LL | | pub fn foo() {} diff --git a/tests/ui/borrowck/issue-109271-pass-self-into-closure.stderr b/tests/ui/borrowck/issue-109271-pass-self-into-closure.stderr index 4e3bf1d70429d..a66281a188d72 100644 --- a/tests/ui/borrowck/issue-109271-pass-self-into-closure.stderr +++ b/tests/ui/borrowck/issue-109271-pass-self-into-closure.stderr @@ -42,8 +42,7 @@ LL | v.call(|(), this: &mut S| { | | LL | | LL | | -LL | | -LL | | _ = v; +... | LL | | v.set(); | | - first borrow occurs due to use of `v` in closure ... | diff --git a/tests/ui/codemap_tests/huge_multispan_highlight.rs b/tests/ui/codemap_tests/huge_multispan_highlight.rs index 6bf4afb8ebd97..c2bd393589e01 100644 --- a/tests/ui/codemap_tests/huge_multispan_highlight.rs +++ b/tests/ui/codemap_tests/huge_multispan_highlight.rs @@ -5,6 +5,7 @@ fn main() { let _ = match true { true => ( + // last line shown in multispan header @@ -95,27 +96,145 @@ fn main() { ), false => " - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + ", + }; + let _ = match true { + true => ( + + 1 // last line shown in multispan header + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ), + false => " + + + 1 last line shown in multispan + + + + + + + + + + + + + + + + + + + ", }; } diff --git a/tests/ui/codemap_tests/huge_multispan_highlight.svg b/tests/ui/codemap_tests/huge_multispan_highlight.svg index cc3449f936890..403e9961102d5 100644 --- a/tests/ui/codemap_tests/huge_multispan_highlight.svg +++ b/tests/ui/codemap_tests/huge_multispan_highlight.svg @@ -1,4 +1,4 @@ - +