From c43210f67be938e14f8193cc87309a5469ef3705 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Mon, 24 Oct 2022 02:34:48 +0100 Subject: [PATCH 001/115] Pass on null handle values to child process --- library/std/src/sys/windows/process.rs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/library/std/src/sys/windows/process.rs b/library/std/src/sys/windows/process.rs index 9cbb4ef19e9b..32be07aee8f4 100644 --- a/library/std/src/sys/windows/process.rs +++ b/library/std/src/sys/windows/process.rs @@ -513,9 +513,6 @@ fn program_exists(path: &Path) -> Option> { impl Stdio { fn to_handle(&self, stdio_id: c::DWORD, pipe: &mut Option) -> io::Result { match *self { - // If no stdio handle is available, then inherit means that it - // should still be unavailable so propagate the - // INVALID_HANDLE_VALUE. Stdio::Inherit => match stdio::get_handle(stdio_id) { Ok(io) => unsafe { let io = Handle::from_raw_handle(io); @@ -523,7 +520,8 @@ impl Stdio { io.into_raw_handle(); ret }, - Err(..) => unsafe { Ok(Handle::from_raw_handle(c::INVALID_HANDLE_VALUE)) }, + // If no stdio handle is available, then propagate the null value. + Err(..) => unsafe { Ok(Handle::from_raw_handle(ptr::null_mut())) }, }, Stdio::MakePipe => { @@ -730,9 +728,9 @@ fn zeroed_startupinfo() -> c::STARTUPINFO { wShowWindow: 0, cbReserved2: 0, lpReserved2: ptr::null_mut(), - hStdInput: c::INVALID_HANDLE_VALUE, - hStdOutput: c::INVALID_HANDLE_VALUE, - hStdError: c::INVALID_HANDLE_VALUE, + hStdInput: ptr::null_mut(), + hStdOutput: ptr::null_mut(), + hStdError: ptr::null_mut(), } } From 17ee25d77550b771200d73533e3bcb2a9959122d Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Tue, 8 Nov 2022 12:27:49 +0100 Subject: [PATCH 002/115] add the build.reuse config option to choose the reuse binary --- config.toml.example | 7 +++++++ src/bootstrap/config.rs | 3 +++ src/bootstrap/sanity.rs | 7 +++++++ 3 files changed, 17 insertions(+) diff --git a/config.toml.example b/config.toml.example index c94a27b12a3a..ffc6a330b9f6 100644 --- a/config.toml.example +++ b/config.toml.example @@ -255,6 +255,13 @@ changelog-seen = 2 # Defaults to the Python interpreter used to execute x.py #python = "python" +# The path to the REUSE executable to use. REUSE will be used to gather +# the licensing information of the codebase. +# +# If this is omitted, the cached licensing information present in the source +# tarball will have to be present. +#reuse = "reuse" + # Force Cargo to check that Cargo.lock describes the precise dependency # set that all the Cargo.toml files create, instead of updating it. #locked-deps = false diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index af004aa50985..34b631c2bcac 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -212,6 +212,7 @@ pub struct Config { pub npm: Option, pub gdb: Option, pub python: Option, + pub reuse: Option, pub cargo_native_static: bool, pub configure_args: Vec, @@ -610,6 +611,7 @@ define_config! { nodejs: Option = "nodejs", npm: Option = "npm", python: Option = "python", + reuse: Option = "reuse", locked_deps: Option = "locked-deps", vendor: Option = "vendor", full_bootstrap: Option = "full-bootstrap", @@ -1003,6 +1005,7 @@ impl Config { config.npm = build.npm.map(PathBuf::from); config.gdb = build.gdb.map(PathBuf::from); config.python = build.python.map(PathBuf::from); + config.reuse = build.reuse.map(PathBuf::from); config.submodules = build.submodules; set(&mut config.low_priority, build.low_priority); set(&mut config.compiler_docs, build.compiler_docs); diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs index 631d42acb93f..8a40b0f64f4b 100644 --- a/src/bootstrap/sanity.rs +++ b/src/bootstrap/sanity.rs @@ -140,6 +140,13 @@ than building it. .map(|p| cmd_finder.must_have(p)) .or_else(|| cmd_finder.maybe_have("gdb")); + build.config.reuse = build + .config + .reuse + .take() + .map(|p| cmd_finder.must_have(p)) + .or_else(|| cmd_finder.maybe_have("reuse")); + // We're gonna build some custom C code here and there, host triples // also build some C++ shims for LLVM so we need a C++ compiler. for target in &build.targets { From 13efb20846dc3b3916e44c67ebd4141a39c54d9b Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Tue, 15 Nov 2022 10:19:17 +0100 Subject: [PATCH 003/115] add tool to collect license metadata from REUSE --- Cargo.lock | 68 ++++ Cargo.toml | 1 + src/bootstrap/builder.rs | 1 + src/bootstrap/run.rs | 33 ++ src/bootstrap/tool.rs | 1 + src/tools/collect-license-metadata/Cargo.toml | 10 + .../collect-license-metadata/src/licenses.rs | 37 +++ .../collect-license-metadata/src/main.rs | 30 ++ .../collect-license-metadata/src/path_tree.rs | 292 ++++++++++++++++++ .../collect-license-metadata/src/reuse.rs | 49 +++ 10 files changed, 522 insertions(+) create mode 100644 src/tools/collect-license-metadata/Cargo.toml create mode 100644 src/tools/collect-license-metadata/src/licenses.rs create mode 100644 src/tools/collect-license-metadata/src/main.rs create mode 100644 src/tools/collect-license-metadata/src/path_tree.rs create mode 100644 src/tools/collect-license-metadata/src/reuse.rs diff --git a/Cargo.lock b/Cargo.lock index 9f64aa44314d..eadaf721f021 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -563,6 +563,7 @@ dependencies = [ "libc", "num-integer", "num-traits", + "serde", "time", "winapi", ] @@ -712,6 +713,16 @@ dependencies = [ "rustc-semver", ] +[[package]] +name = "collect-license-metadata" +version = "0.1.0" +dependencies = [ + "anyhow", + "serde", + "serde_json", + "spdx-rs", +] + [[package]] name = "color-eyre" version = "0.6.2" @@ -4628,6 +4639,35 @@ dependencies = [ "winapi", ] +[[package]] +name = "spdx-expression" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d7ac03c67c572d85049d6db815e20a4a19b41b3d5cca732ac582342021ad77" +dependencies = [ + "nom", + "serde", + "thiserror", + "tracing", +] + +[[package]] +name = "spdx-rs" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3c02f6eb7e7b4100c272f685a9ccaccaab302324e8c7ec3e2ee72340fb29ff3" +dependencies = [ + "chrono", + "log", + "nom", + "serde", + "spdx-expression", + "strum", + "strum_macros", + "thiserror", + "uuid", +] + [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -4731,6 +4771,25 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +[[package]] +name = "strum" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" + +[[package]] +name = "strum_macros" +version = "0.24.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn", +] + [[package]] name = "syn" version = "1.0.102" @@ -5357,6 +5416,15 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8772a4ccbb4e89959023bc5b7cb8623a795caa7092d99f3aa9501b9484d4557d" +[[package]] +name = "uuid" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" +dependencies = [ + "getrandom 0.2.0", +] + [[package]] name = "valuable" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 13a98eedde86..ddaf9b41f860 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,6 +39,7 @@ members = [ "src/tools/bump-stage0", "src/tools/replace-version-placeholder", "src/tools/lld-wrapper", + "src/tools/collect-license-metadata", ] exclude = [ diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 8d999302a6d7..803b1c266f3c 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -753,6 +753,7 @@ impl<'a> Builder<'a> { run::BumpStage0, run::ReplaceVersionPlaceholder, run::Miri, + run::CollectLicenseMetadata, ), // These commands either don't use paths, or they're special-cased in Build::build() Kind::Clean | Kind::Format | Kind::Setup => vec![], diff --git a/src/bootstrap/run.rs b/src/bootstrap/run.rs index d49b41c51327..8cbfe3ebab55 100644 --- a/src/bootstrap/run.rs +++ b/src/bootstrap/run.rs @@ -1,3 +1,4 @@ +use std::path::PathBuf; use std::process::Command; use crate::builder::{Builder, RunConfig, ShouldRun, Step}; @@ -189,3 +190,35 @@ impl Step for Miri { builder.run(&mut miri); } } + +#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)] +pub struct CollectLicenseMetadata; + +impl Step for CollectLicenseMetadata { + type Output = PathBuf; + const ONLY_HOSTS: bool = true; + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + run.path("src/tools/collect-license-metadata") + } + + fn make_run(run: RunConfig<'_>) { + run.builder.ensure(CollectLicenseMetadata); + } + + fn run(self, builder: &Builder<'_>) -> Self::Output { + let Some(reuse) = &builder.config.reuse else { + panic!("REUSE is required to collect the license metadata"); + }; + + // Temporary location, it will be moved to src/etc once it's accurate. + let dest = builder.out.join("license-metadata.json"); + + let mut cmd = builder.tool_cmd(Tool::CollectLicenseMetadata); + cmd.env("REUSE_EXE", reuse); + cmd.env("DEST", &dest); + builder.run(&mut cmd); + + dest + } +} diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index ba329ea6c759..4dd9a40dcb3c 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -380,6 +380,7 @@ bootstrap_tool!( HtmlChecker, "src/tools/html-checker", "html-checker"; BumpStage0, "src/tools/bump-stage0", "bump-stage0"; ReplaceVersionPlaceholder, "src/tools/replace-version-placeholder", "replace-version-placeholder"; + CollectLicenseMetadata, "src/tools/collect-license-metadata", "collect-license-metadata"; ); #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Ord, PartialOrd)] diff --git a/src/tools/collect-license-metadata/Cargo.toml b/src/tools/collect-license-metadata/Cargo.toml new file mode 100644 index 000000000000..d0820cfc2a0e --- /dev/null +++ b/src/tools/collect-license-metadata/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "collect-license-metadata" +version = "0.1.0" +edition = "2021" + +[dependencies] +anyhow = "1.0.65" +serde = { version = "1.0.147", features = ["derive"] } +serde_json = "1.0.85" +spdx-rs = "0.5.1" diff --git a/src/tools/collect-license-metadata/src/licenses.rs b/src/tools/collect-license-metadata/src/licenses.rs new file mode 100644 index 000000000000..34aabc873014 --- /dev/null +++ b/src/tools/collect-license-metadata/src/licenses.rs @@ -0,0 +1,37 @@ +use std::collections::HashMap; + +pub(crate) struct LicensesInterner { + by_id: Vec, + by_struct: HashMap, +} + +impl LicensesInterner { + pub(crate) fn new() -> Self { + LicensesInterner { by_id: Vec::new(), by_struct: HashMap::new() } + } + + pub(crate) fn intern(&mut self, license: License) -> LicenseId { + if let Some(id) = self.by_struct.get(&license) { + LicenseId(*id) + } else { + let id = self.by_id.len(); + self.by_id.push(license.clone()); + self.by_struct.insert(license, id); + LicenseId(id) + } + } + + pub(crate) fn resolve(&self, id: LicenseId) -> &License { + &self.by_id[id.0] + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, serde::Serialize)] +#[serde(transparent)] +pub(crate) struct LicenseId(usize); + +#[derive(Clone, Hash, PartialEq, Eq, serde::Serialize)] +pub(crate) struct License { + pub(crate) spdx: String, + pub(crate) copyright: Vec, +} diff --git a/src/tools/collect-license-metadata/src/main.rs b/src/tools/collect-license-metadata/src/main.rs new file mode 100644 index 000000000000..0864408fd534 --- /dev/null +++ b/src/tools/collect-license-metadata/src/main.rs @@ -0,0 +1,30 @@ +mod licenses; +mod path_tree; +mod reuse; + +use crate::licenses::LicensesInterner; +use anyhow::Error; +use std::path::PathBuf; + +fn main() -> Result<(), Error> { + let reuse_exe: PathBuf = std::env::var_os("REUSE_EXE").expect("Missing REUSE_EXE").into(); + let dest: PathBuf = std::env::var_os("DEST").expect("Missing DEST").into(); + + let mut interner = LicensesInterner::new(); + let paths = crate::reuse::collect(&reuse_exe, &mut interner)?; + + let mut tree = crate::path_tree::build(paths); + tree.simplify(); + + if let Some(parent) = dest.parent() { + std::fs::create_dir_all(parent)?; + } + std::fs::write( + &dest, + &serde_json::to_vec_pretty(&serde_json::json!({ + "files": crate::path_tree::strip_interning(tree, &interner), + }))?, + )?; + + Ok(()) +} diff --git a/src/tools/collect-license-metadata/src/path_tree.rs b/src/tools/collect-license-metadata/src/path_tree.rs new file mode 100644 index 000000000000..6278970d8136 --- /dev/null +++ b/src/tools/collect-license-metadata/src/path_tree.rs @@ -0,0 +1,292 @@ +//! Tools like REUSE output per-file licensing information, but we need to condense it in the +//! minimum amount of data that still represents the same licensing metadata. This module is +//! responsible for that, by turning the list of paths into a tree and executing simplification +//! passes over the tree to remove redundant information. + +use crate::licenses::{License, LicenseId, LicensesInterner}; +use std::collections::BTreeMap; +use std::path::{Path, PathBuf}; + +#[derive(serde::Serialize)] +#[serde(rename_all = "kebab-case", tag = "type")] +pub(crate) enum Node { + Root { childs: Vec> }, + Directory { name: PathBuf, childs: Vec>, license: Option }, + File { name: PathBuf, license: L }, + FileGroup { names: Vec, license: L }, + Empty, +} + +impl Node { + pub(crate) fn simplify(&mut self) { + self.merge_directories(); + self.collapse_in_licensed_directories(); + self.merge_directory_licenses(); + self.merge_file_groups(); + self.remove_empty(); + } + + /// Initially, trees are built by the build() function with each file practically having a + /// separate directory tree, like so: + /// + /// ```text + /// ┌─► ./ ──► compiler/ ──► rustc/ ──► src/ ──► main.rs + /// │ + /// ─┼─► ./ ──► compiler/ ──► rustc/ ──► Cargo.toml + /// │ + /// └─► ./ ──► library/ ───► std/ ──► Cargo.toml + /// ``` + /// + /// This pass is responsible for turning that into a proper directory tree: + /// + /// ```text + /// ┌─► compiler/ ──► rustc/ ──┬─► src/ ──► main.rs + /// │ │ + /// ──► ./ ──┤ └─► Cargo.toml + /// │ + /// └─► library/ ───► std/ ──► Cargo.toml + /// ``` + fn merge_directories(&mut self) { + match self { + Node::Root { childs } | Node::Directory { childs, license: None, .. } => { + let mut directories = BTreeMap::new(); + let mut files = Vec::new(); + + for child in childs.drain(..) { + match child { + Node::Directory { name, mut childs, license: None } => { + directories.entry(name).or_insert_with(Vec::new).append(&mut childs); + } + file @ Node::File { .. } => { + files.push(file); + } + Node::Empty => {} + Node::Root { .. } => { + panic!("can't have a root inside another element"); + } + Node::FileGroup { .. } => { + panic!("FileGroup should not be present at this stage"); + } + Node::Directory { license: Some(_), .. } => { + panic!("license should not be set at this stage"); + } + } + } + + childs.extend(directories.into_iter().map(|(name, childs)| Node::Directory { + name, + childs, + license: None, + })); + childs.append(&mut files); + + for child in &mut *childs { + child.merge_directories(); + } + } + Node::Empty => {} + Node::File { .. } => {} + Node::FileGroup { .. } => { + panic!("FileGroup should not be present at this stage"); + } + Node::Directory { license: Some(_), .. } => { + panic!("license should not be set at this stage"); + } + } + } + + /// In our codebase, most files in a directory have the same license as the other files in that + /// same directory, so it's redundant to store licensing metadata for all the files. Instead, + /// we can add a license for a whole directory, and only record the exceptions to a directory + /// licensing metadata. + /// + /// We cannot instead record only the difference to Rust's standard licensing, as the majority + /// of the files in our repository are *not* licensed under Rust's standard licensing due to + /// our inclusion of LLVM. + fn collapse_in_licensed_directories(&mut self) { + match self { + Node::Directory { childs, license, .. } => { + for child in &mut *childs { + child.collapse_in_licensed_directories(); + } + + let mut licenses_count = BTreeMap::new(); + for child in &*childs { + let Some(license) = child.license() else { continue }; + *licenses_count.entry(license).or_insert(0) += 1; + } + + let most_popular_license = licenses_count + .into_iter() + .max_by_key(|(_, count)| *count) + .map(|(license, _)| license); + + if let Some(most_popular_license) = most_popular_license { + childs.retain(|child| child.license() != Some(most_popular_license)); + *license = Some(most_popular_license); + } + } + Node::Root { childs } => { + for child in &mut *childs { + child.collapse_in_licensed_directories(); + } + } + Node::File { .. } => {} + Node::FileGroup { .. } => {} + Node::Empty => {} + } + } + + /// Reduce the depth of the tree by merging subdirectories with the same license as their + /// parent directory into their parent, and adjusting the paths of the childs accordingly. + fn merge_directory_licenses(&mut self) { + match self { + Node::Root { childs } => { + for child in &mut *childs { + child.merge_directory_licenses(); + } + } + Node::Directory { childs, license, .. } => { + let mut to_add = Vec::new(); + for child in &mut *childs { + child.merge_directory_licenses(); + + let Node::Directory { + name: child_name, + childs: child_childs, + license: child_license, + } = child else { continue }; + + if child_license != license { + continue; + } + for mut child_child in child_childs.drain(..) { + match &mut child_child { + Node::Root { .. } => { + panic!("can't have a root inside another element"); + } + Node::FileGroup { .. } => { + panic!("FileGroup should not be present at this stage"); + } + Node::Directory { name: child_child_name, .. } => { + *child_child_name = child_name.join(&child_child_name); + } + Node::File { name: child_child_name, .. } => { + *child_child_name = child_name.join(&child_child_name); + } + Node::Empty => {} + } + to_add.push(child_child); + } + + *child = Node::Empty; + } + childs.append(&mut to_add); + } + Node::Empty => {} + Node::File { .. } => {} + Node::FileGroup { .. } => {} + } + } + + /// This pass groups multiple files in a directory with the same license into a single + /// "FileGroup", so that the license of all those files can be reported as a group. + /// + /// Crucially this pass runs after collapse_in_licensed_directories, so the most common license + /// will already be marked as the directory's license and won't be turned into a group. + fn merge_file_groups(&mut self) { + match self { + Node::Root { childs } | Node::Directory { childs, .. } => { + let mut grouped = BTreeMap::new(); + + for child in &mut *childs { + child.merge_file_groups(); + if let Node::File { name, license } = child { + grouped.entry(*license).or_insert_with(Vec::new).push(name.clone()); + *child = Node::Empty; + } + } + + for (license, mut names) in grouped.into_iter() { + if names.len() == 1 { + childs.push(Node::File { license, name: names.pop().unwrap() }); + } else { + childs.push(Node::FileGroup { license, names }); + } + } + } + Node::File { .. } => {} + Node::FileGroup { .. } => panic!("FileGroup should not be present at this stage"), + Node::Empty => {} + } + } + + /// Some nodes were replaced with Node::Empty to mark them for deletion. As the last step, make + /// sure to remove them from the tree. + fn remove_empty(&mut self) { + match self { + Node::Root { childs } | Node::Directory { childs, .. } => { + for child in &mut *childs { + child.remove_empty(); + } + childs.retain(|child| !matches!(child, Node::Empty)); + } + Node::FileGroup { .. } => {} + Node::File { .. } => {} + Node::Empty => {} + } + } + + fn license(&self) -> Option { + match self { + Node::Directory { childs, license: Some(license), .. } if childs.is_empty() => { + Some(*license) + } + Node::File { license, .. } => Some(*license), + _ => None, + } + } +} + +pub(crate) fn build(mut input: Vec<(PathBuf, LicenseId)>) -> Node { + let mut childs = Vec::new(); + + // Ensure reproducibility of all future steps. + input.sort(); + + for (path, license) in input { + let mut node = Node::File { name: path.file_name().unwrap().into(), license }; + for component in path.parent().unwrap_or_else(|| Path::new(".")).components().rev() { + node = Node::Directory { + name: component.as_os_str().into(), + childs: vec![node], + license: None, + }; + } + + childs.push(node); + } + + Node::Root { childs } +} + +pub(crate) fn strip_interning( + node: Node, + interner: &LicensesInterner, +) -> Node<&License> { + match node { + Node::Root { childs } => Node::Root { + childs: childs.into_iter().map(|child| strip_interning(child, interner)).collect(), + }, + Node::Directory { name, childs, license } => Node::Directory { + childs: childs.into_iter().map(|child| strip_interning(child, interner)).collect(), + license: license.map(|license| interner.resolve(license)), + name, + }, + Node::File { name, license } => Node::File { name, license: interner.resolve(license) }, + Node::FileGroup { names, license } => { + Node::FileGroup { names, license: interner.resolve(license) } + } + Node::Empty => Node::Empty, + } +} diff --git a/src/tools/collect-license-metadata/src/reuse.rs b/src/tools/collect-license-metadata/src/reuse.rs new file mode 100644 index 000000000000..d6b3772ba515 --- /dev/null +++ b/src/tools/collect-license-metadata/src/reuse.rs @@ -0,0 +1,49 @@ +use crate::licenses::{License, LicenseId, LicensesInterner}; +use anyhow::Error; +use std::path::{Path, PathBuf}; +use std::process::{Command, Stdio}; +use std::time::Instant; + +pub(crate) fn collect( + reuse_exe: &Path, + interner: &mut LicensesInterner, +) -> Result, Error> { + eprintln!("gathering license information from REUSE"); + let start = Instant::now(); + let raw = &obtain_spdx_document(reuse_exe)?; + eprintln!("finished gathering the license information from REUSE in {:.2?}", start.elapsed()); + + let document = spdx_rs::parsers::spdx_from_tag_value(&raw)?; + + let mut result = Vec::new(); + for file in document.file_information { + let license = interner.intern(License { + spdx: file.concluded_license.to_string(), + copyright: file.copyright_text.split('\n').map(|s| s.into()).collect(), + }); + + result.push((file.file_name.into(), license)); + } + + Ok(result) +} + +fn obtain_spdx_document(reuse_exe: &Path) -> Result { + let output = Command::new(reuse_exe) + .args(&["spdx", "--add-license-concluded", "--creator-person=bors"]) + .stdout(Stdio::piped()) + .spawn()? + .wait_with_output()?; + + if !output.status.success() { + eprintln!(); + eprintln!("Note that Rust requires some REUSE features that might not be present in the"); + eprintln!("release you're using. Make sure your REUSE release includes these PRs:"); + eprintln!(); + eprintln!(" - https://github.com/fsfe/reuse-tool/pull/623"); + eprintln!(); + anyhow::bail!("collecting licensing information with REUSE failed"); + } + + Ok(String::from_utf8(output.stdout)?) +} From 4af7de13d26aabe9bc459771bd5641c140407954 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Tue, 15 Nov 2022 11:27:19 +0100 Subject: [PATCH 004/115] initial prototype of the tool to generate copyright notices --- Cargo.lock | 9 +++ Cargo.toml | 1 + src/bootstrap/builder.rs | 1 + src/bootstrap/run.rs | 30 ++++++++ src/bootstrap/tool.rs | 1 + src/tools/generate-copyright/Cargo.toml | 11 +++ src/tools/generate-copyright/src/main.rs | 94 ++++++++++++++++++++++++ 7 files changed, 147 insertions(+) create mode 100644 src/tools/generate-copyright/Cargo.toml create mode 100644 src/tools/generate-copyright/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index eadaf721f021..8cde96b519f7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1498,6 +1498,15 @@ dependencies = [ "termcolor", ] +[[package]] +name = "generate-copyright" +version = "0.1.0" +dependencies = [ + "anyhow", + "serde", + "serde_json", +] + [[package]] name = "generic-array" version = "0.14.4" diff --git a/Cargo.toml b/Cargo.toml index ddaf9b41f860..000c10a1f906 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,6 +40,7 @@ members = [ "src/tools/replace-version-placeholder", "src/tools/lld-wrapper", "src/tools/collect-license-metadata", + "src/tools/generate-copyright", ] exclude = [ diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 803b1c266f3c..0a311529bcae 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -754,6 +754,7 @@ impl<'a> Builder<'a> { run::ReplaceVersionPlaceholder, run::Miri, run::CollectLicenseMetadata, + run::GenerateCopyright, ), // These commands either don't use paths, or they're special-cased in Build::build() Kind::Clean | Kind::Format | Kind::Setup => vec![], diff --git a/src/bootstrap/run.rs b/src/bootstrap/run.rs index 8cbfe3ebab55..05de51f8cc57 100644 --- a/src/bootstrap/run.rs +++ b/src/bootstrap/run.rs @@ -222,3 +222,33 @@ impl Step for CollectLicenseMetadata { dest } } + +#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)] +pub struct GenerateCopyright; + +impl Step for GenerateCopyright { + type Output = PathBuf; + const ONLY_HOSTS: bool = true; + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + run.path("src/tools/generate-copyright") + } + + fn make_run(run: RunConfig<'_>) { + run.builder.ensure(GenerateCopyright); + } + + fn run(self, builder: &Builder<'_>) -> Self::Output { + let license_metadata = builder.ensure(CollectLicenseMetadata); + + // Temporary location, it will be moved to the proper one once it's accurate. + let dest = builder.out.join("COPYRIGHT.md"); + + let mut cmd = builder.tool_cmd(Tool::GenerateCopyright); + cmd.env("LICENSE_METADATA", &license_metadata); + cmd.env("DEST", &dest); + builder.run(&mut cmd); + + dest + } +} diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 4dd9a40dcb3c..e0be4c432f16 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -381,6 +381,7 @@ bootstrap_tool!( BumpStage0, "src/tools/bump-stage0", "bump-stage0"; ReplaceVersionPlaceholder, "src/tools/replace-version-placeholder", "replace-version-placeholder"; CollectLicenseMetadata, "src/tools/collect-license-metadata", "collect-license-metadata"; + GenerateCopyright, "src/tools/generate-copyright", "generate-copyright"; ); #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Ord, PartialOrd)] diff --git a/src/tools/generate-copyright/Cargo.toml b/src/tools/generate-copyright/Cargo.toml new file mode 100644 index 000000000000..899ef0f8a6c2 --- /dev/null +++ b/src/tools/generate-copyright/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "generate-copyright" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +anyhow = "1.0.65" +serde = { version = "1.0.147", features = ["derive"] } +serde_json = "1.0.85" diff --git a/src/tools/generate-copyright/src/main.rs b/src/tools/generate-copyright/src/main.rs new file mode 100644 index 000000000000..d172c9e157bc --- /dev/null +++ b/src/tools/generate-copyright/src/main.rs @@ -0,0 +1,94 @@ +use anyhow::Error; +use std::io::Write; +use std::path::PathBuf; + +fn main() -> Result<(), Error> { + let dest = env_path("DEST")?; + let license_metadata = env_path("LICENSE_METADATA")?; + + let metadata: Metadata = serde_json::from_slice(&std::fs::read(&license_metadata)?)?; + + let mut buffer = Vec::new(); + render_recursive(&metadata.files, &mut buffer, 0)?; + + std::fs::write(&dest, &buffer)?; + + Ok(()) +} + +fn render_recursive(node: &Node, buffer: &mut Vec, depth: usize) -> Result<(), Error> { + let prefix = std::iter::repeat("> ").take(depth + 1).collect::(); + + match node { + Node::Root { childs } => { + for child in childs { + render_recursive(child, buffer, depth)?; + } + } + Node::Directory { name, childs, license } => { + render_license(&prefix, std::iter::once(name), license, buffer)?; + if !childs.is_empty() { + writeln!(buffer, "{prefix}")?; + writeln!(buffer, "{prefix}*Exceptions:*")?; + for child in childs { + writeln!(buffer, "{prefix}")?; + render_recursive(child, buffer, depth + 1)?; + } + } + } + Node::FileGroup { names, license } => { + render_license(&prefix, names.iter(), license, buffer)?; + } + Node::File { name, license } => { + render_license(&prefix, std::iter::once(name), license, buffer)?; + } + } + + Ok(()) +} + +fn render_license<'a>( + prefix: &str, + names: impl Iterator, + license: &License, + buffer: &mut Vec, +) -> Result<(), Error> { + for name in names { + writeln!(buffer, "{prefix}**`{name}`** ")?; + } + writeln!(buffer, "{prefix}License: `{}` ", license.spdx)?; + for (i, copyright) in license.copyright.iter().enumerate() { + let suffix = if i == license.copyright.len() - 1 { "" } else { " " }; + writeln!(buffer, "{prefix}Copyright: {copyright}{suffix}")?; + } + + Ok(()) +} + +#[derive(serde::Deserialize)] +struct Metadata { + files: Node, +} + +#[derive(serde::Deserialize)] +#[serde(rename_all = "kebab-case", tag = "type")] +pub(crate) enum Node { + Root { childs: Vec }, + Directory { name: String, childs: Vec, license: License }, + File { name: String, license: License }, + FileGroup { names: Vec, license: License }, +} + +#[derive(serde::Deserialize)] +struct License { + spdx: String, + copyright: Vec, +} + +fn env_path(var: &str) -> Result { + if let Some(var) = std::env::var_os(var) { + Ok(var.into()) + } else { + anyhow::bail!("missing environment variable {var}") + } +} From 51d5ae63d0845322cd274a67a504513df929b310 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Thu, 17 Nov 2022 11:05:27 +0100 Subject: [PATCH 005/115] merge together similar copyright statements --- .../collect-license-metadata/src/licenses.rs | 30 ++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/src/tools/collect-license-metadata/src/licenses.rs b/src/tools/collect-license-metadata/src/licenses.rs index 34aabc873014..1c95b1bc8e96 100644 --- a/src/tools/collect-license-metadata/src/licenses.rs +++ b/src/tools/collect-license-metadata/src/licenses.rs @@ -1,5 +1,7 @@ use std::collections::HashMap; +const COPYRIGHT_PREFIXES: &[&str] = &["SPDX-FileCopyrightText:", "Copyright", "(c)", "(C)", "©"]; + pub(crate) struct LicensesInterner { by_id: Vec, by_struct: HashMap, @@ -10,7 +12,8 @@ impl LicensesInterner { LicensesInterner { by_id: Vec::new(), by_struct: HashMap::new() } } - pub(crate) fn intern(&mut self, license: License) -> LicenseId { + pub(crate) fn intern(&mut self, mut license: License) -> LicenseId { + license.simplify(); if let Some(id) = self.by_struct.get(&license) { LicenseId(*id) } else { @@ -35,3 +38,28 @@ pub(crate) struct License { pub(crate) spdx: String, pub(crate) copyright: Vec, } + +impl License { + fn simplify(&mut self) { + self.remove_copyright_prefixes(); + self.copyright.sort(); + self.copyright.dedup(); + } + + fn remove_copyright_prefixes(&mut self) { + for copyright in &mut self.copyright { + let mut stripped = copyright.trim(); + let mut previous_stripped; + loop { + previous_stripped = stripped; + for pattern in COPYRIGHT_PREFIXES { + stripped = stripped.trim_start_matches(pattern).trim_start(); + } + if stripped == previous_stripped { + break; + } + } + *copyright = stripped.into(); + } + } +} From f78e6468ba40b5d328cf282c92fc94521988000e Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Thu, 24 Nov 2022 16:02:55 +0100 Subject: [PATCH 006/115] make comment more clear Co-authored-by: Felix S Klock II --- src/tools/collect-license-metadata/src/path_tree.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/collect-license-metadata/src/path_tree.rs b/src/tools/collect-license-metadata/src/path_tree.rs index 6278970d8136..fa4ae87bdad0 100644 --- a/src/tools/collect-license-metadata/src/path_tree.rs +++ b/src/tools/collect-license-metadata/src/path_tree.rs @@ -26,8 +26,8 @@ impl Node { self.remove_empty(); } - /// Initially, trees are built by the build() function with each file practically having a - /// separate directory tree, like so: + /// Initially, the build() function constructs a list of separate paths from the file + /// system root down to each file, like so: /// /// ```text /// ┌─► ./ ──► compiler/ ──► rustc/ ──► src/ ──► main.rs From f8a7123b276ed18e6cdd488818a8f4e5e3e1cf94 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Thu, 24 Nov 2022 17:25:35 +0100 Subject: [PATCH 007/115] address review feedback --- config.toml.example | 11 +++++++---- src/tools/collect-license-metadata/src/main.rs | 2 +- src/tools/collect-license-metadata/src/path_tree.rs | 4 +++- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/config.toml.example b/config.toml.example index ffc6a330b9f6..ca54cbd2d68d 100644 --- a/config.toml.example +++ b/config.toml.example @@ -255,11 +255,14 @@ changelog-seen = 2 # Defaults to the Python interpreter used to execute x.py #python = "python" -# The path to the REUSE executable to use. REUSE will be used to gather -# the licensing information of the codebase. +# The path to the REUSE executable to use. Note that REUSE is not required in +# most cases, as our tooling relies on a cached (and shrinked) copy of the +# REUSE output present in the git repository and in our source tarballs. # -# If this is omitted, the cached licensing information present in the source -# tarball will have to be present. +# REUSE is only needed if your changes caused the overral licensing of the +# repository to change, and the cached copy has to be regenerated. +# +# Defaults to the "reuse" command in the system path. #reuse = "reuse" # Force Cargo to check that Cargo.lock describes the precise dependency diff --git a/src/tools/collect-license-metadata/src/main.rs b/src/tools/collect-license-metadata/src/main.rs index 0864408fd534..ca2a6f4b8c8a 100644 --- a/src/tools/collect-license-metadata/src/main.rs +++ b/src/tools/collect-license-metadata/src/main.rs @@ -22,7 +22,7 @@ fn main() -> Result<(), Error> { std::fs::write( &dest, &serde_json::to_vec_pretty(&serde_json::json!({ - "files": crate::path_tree::strip_interning(tree, &interner), + "files": crate::path_tree::expand_interned_licenses(tree, &interner), }))?, )?; diff --git a/src/tools/collect-license-metadata/src/path_tree.rs b/src/tools/collect-license-metadata/src/path_tree.rs index fa4ae87bdad0..133ff6837378 100644 --- a/src/tools/collect-license-metadata/src/path_tree.rs +++ b/src/tools/collect-license-metadata/src/path_tree.rs @@ -270,7 +270,9 @@ pub(crate) fn build(mut input: Vec<(PathBuf, LicenseId)>) -> Node { Node::Root { childs } } -pub(crate) fn strip_interning( +/// Convert a `Node` into a `Node<&License>`, expanding all interned license IDs with a +/// reference to the actual license metadata. +pub(crate) fn expand_interned_licenses( node: Node, interner: &LicensesInterner, ) -> Node<&License> { From 34de2573f5a66f6f000d71f6933aa190dcfb17a1 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 25 Nov 2022 20:48:53 +0100 Subject: [PATCH 008/115] PERs are homogeneous --- library/core/src/cmp.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index 5db5cbfc3dfd..949896e57480 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -29,8 +29,7 @@ use crate::marker::StructuralPartialEq; use self::Ordering::*; -/// Trait for equality comparisons which are [partial equivalence -/// relations](https://en.wikipedia.org/wiki/Partial_equivalence_relation). +/// Trait for equality comparisons. /// /// `x.eq(y)` can also be written `x == y`, and `x.ne(y)` can be written `x != y`. /// We use the easier-to-read infix notation in the remainder of this documentation. @@ -38,6 +37,8 @@ use self::Ordering::*; /// This trait allows for partial equality, for types that do not have a full /// equivalence relation. For example, in floating point numbers `NaN != NaN`, /// so floating point types implement `PartialEq` but not [`trait@Eq`]. +/// Formally speaking, when `Rhs == Self`, this trait corresponds to a [partial equivalence +/// relation](https://en.wikipedia.org/wiki/Partial_equivalence_relation). /// /// Implementations must ensure that `eq` and `ne` are consistent with each other: /// From 71fd3abc73471bf1b68666c980d73c4385e5e9a7 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sat, 26 Nov 2022 15:00:39 -0500 Subject: [PATCH 009/115] Don't update submodules for `x setup` Before, the submodule handling was very jank and would update *between two interactive prompts*: ``` ; x setup Building rustbuild Finished dev [unoptimized] target(s) in 0.05s Welcome to the Rust project! What do you want to do with x.py? a) library: Contribute to the standard library Please choose one (a/b/c/d/e): a Updating submodule library/backtrace Submodule 'library/backtrace' (https://github.com/rust-lang/backtrace-rs.git) registered for path 'library/backtrace' error: you asked `x.py` to setup a new config file, but one already exists at `config.toml` Build completed unsuccessfully in 0:00:02 ``` That's not a great user experience because you need to wait a long time between prompts. It would be possible to move the submodule handling either before or after the prompt, but it seems better to just not require submodules to be checked out at all, to minimize the time spend waiting just to create a new configuration. --- src/bootstrap/flags.rs | 9 +++++---- src/bootstrap/lib.rs | 44 ++++++++++++++++++++++++------------------ src/bootstrap/setup.rs | 3 ++- 3 files changed, 32 insertions(+), 24 deletions(-) diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index 2001e29bd2ea..37a8eb884efb 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -143,7 +143,7 @@ pub enum Subcommand { args: Vec, }, Setup { - profile: Profile, + profile: Option, }, } @@ -628,14 +628,15 @@ Arguments: |path| format!("{} is not a valid UTF8 string", path.to_string_lossy()) )); - profile_string.parse().unwrap_or_else(|err| { + let profile = profile_string.parse().unwrap_or_else(|err| { eprintln!("error: {}", err); eprintln!("help: the available profiles are:"); eprint!("{}", Profile::all_for_help("- ")); crate::detail_exit(1); - }) + }); + Some(profile) } else { - t!(crate::setup::interactive_path()) + None }; Subcommand::Setup { profile } } diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index f4fa556b9745..60ce431cb0c3 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -542,16 +542,6 @@ impl Build { metrics: metrics::BuildMetrics::init(), }; - build.verbose("finding compilers"); - cc_detect::find(&mut build); - // When running `setup`, the profile is about to change, so any requirements we have now may - // be different on the next invocation. Don't check for them until the next time x.py is - // run. This is ok because `setup` never runs any build commands, so it won't fail if commands are missing. - if !matches!(build.config.cmd, Subcommand::Setup { .. }) { - build.verbose("running sanity check"); - sanity::check(&mut build); - } - // If local-rust is the same major.minor as the current version, then force a // local-rebuild let local_version_verbose = @@ -567,16 +557,32 @@ impl Build { build.local_rebuild = true; } - // Make sure we update these before gathering metadata so we don't get an error about missing - // Cargo.toml files. - let rust_submodules = - ["src/tools/rust-installer", "src/tools/cargo", "library/backtrace", "library/stdarch"]; - for s in rust_submodules { - build.update_submodule(Path::new(s)); - } + build.verbose("finding compilers"); + cc_detect::find(&mut build); + // When running `setup`, the profile is about to change, so any requirements we have now may + // be different on the next invocation. Don't check for them until the next time x.py is + // run. This is ok because `setup` never runs any build commands, so it won't fail if commands are missing. + // + // Similarly, for `setup` we don't actually need submodules or cargo metadata. + if !matches!(build.config.cmd, Subcommand::Setup { .. }) { + build.verbose("running sanity check"); + sanity::check(&mut build); - build.verbose("learning about cargo"); - metadata::build(&mut build); + // Make sure we update these before gathering metadata so we don't get an error about missing + // Cargo.toml files. + let rust_submodules = [ + "src/tools/rust-installer", + "src/tools/cargo", + "library/backtrace", + "library/stdarch", + ]; + for s in rust_submodules { + build.update_submodule(Path::new(s)); + } + + build.verbose("learning about cargo"); + metadata::build(&mut build); + } build } diff --git a/src/bootstrap/setup.rs b/src/bootstrap/setup.rs index 04480277fe04..2507b7a29b06 100644 --- a/src/bootstrap/setup.rs +++ b/src/bootstrap/setup.rs @@ -81,8 +81,9 @@ impl fmt::Display for Profile { } } -pub fn setup(config: &Config, profile: Profile) { +pub fn setup(config: &Config, profile: Option) { let path = &config.config.clone().unwrap_or(PathBuf::from("config.toml")); + let profile = profile.unwrap_or_else(|| t!(interactive_path())); if path.exists() { eprintln!( From 86251dabac6252ebd3c2a90bd4695563d202b919 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sat, 26 Nov 2022 15:08:41 -0500 Subject: [PATCH 010/115] Refactor `setup_config_toml` into a function --- src/bootstrap/setup.rs | 62 +++++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/src/bootstrap/setup.rs b/src/bootstrap/setup.rs index 2507b7a29b06..bad6accc7847 100644 --- a/src/bootstrap/setup.rs +++ b/src/bootstrap/setup.rs @@ -1,15 +1,13 @@ +use crate::Config; use crate::{t, VERSION}; -use crate::{Config, TargetSelection}; use std::env::consts::EXE_SUFFIX; use std::fmt::Write as _; use std::fs::File; +use std::io::Write; use std::path::{Path, PathBuf, MAIN_SEPARATOR}; use std::process::Command; use std::str::FromStr; -use std::{ - env, fmt, fs, - io::{self, Write}, -}; +use std::{fmt, fs, io}; #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum Profile { @@ -84,34 +82,10 @@ impl fmt::Display for Profile { pub fn setup(config: &Config, profile: Option) { let path = &config.config.clone().unwrap_or(PathBuf::from("config.toml")); let profile = profile.unwrap_or_else(|| t!(interactive_path())); + setup_config_toml(path, profile, config); - if path.exists() { - eprintln!( - "error: you asked `x.py` to setup a new config file, but one already exists at `{}`", - path.display() - ); - eprintln!("help: try adding `profile = \"{}\"` at the top of {}", profile, path.display()); - eprintln!( - "note: this will use the configuration in {}", - profile.include_path(&config.src).display() - ); - crate::detail_exit(1); - } - - let settings = format!( - "# Includes one of the default files in src/bootstrap/defaults\n\ - profile = \"{}\"\n\ - changelog-seen = {}\n", - profile, VERSION - ); - t!(fs::write(path, settings)); - - let include_path = profile.include_path(&config.src); - println!("`x.py` will now use the configuration at {}", include_path.display()); - - let build = TargetSelection::from_user(&env!("BUILD_TRIPLE")); let stage_path = - ["build", build.rustc_target_arg(), "stage1"].join(&MAIN_SEPARATOR.to_string()); + ["build", config.build.rustc_target_arg(), "stage1"].join(&MAIN_SEPARATOR.to_string()); println!(); @@ -153,6 +127,32 @@ pub fn setup(config: &Config, profile: Option) { } } +fn setup_config_toml(path: &PathBuf, profile: Profile, config: &Config) { + if path.exists() { + eprintln!( + "error: you asked `x.py` to setup a new config file, but one already exists at `{}`", + path.display() + ); + eprintln!("help: try adding `profile = \"{}\"` at the top of {}", profile, path.display()); + eprintln!( + "note: this will use the configuration in {}", + profile.include_path(&config.src).display() + ); + crate::detail_exit(1); + } + + let settings = format!( + "# Includes one of the default files in src/bootstrap/defaults\n\ + profile = \"{}\"\n\ + changelog-seen = {}\n", + profile, VERSION + ); + t!(fs::write(path, settings)); + + let include_path = profile.include_path(&config.src); + println!("`x.py` will now use the configuration at {}", include_path.display()); +} + fn rustup_installed() -> bool { Command::new("rustup") .arg("--version") From b771d901f735aa6d4078aed92b03e30eba35bf5a Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sat, 26 Nov 2022 15:43:10 -0500 Subject: [PATCH 011/115] Revamp the order `setup` executes - Create `config.toml` last. It's the most likely to error, and used to stop later steps from executing - Don't print an error message + exit if the git hook already exists; that's expected --- src/bootstrap/setup.rs | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/bootstrap/setup.rs b/src/bootstrap/setup.rs index bad6accc7847..c7f98a7d0d14 100644 --- a/src/bootstrap/setup.rs +++ b/src/bootstrap/setup.rs @@ -80,15 +80,10 @@ impl fmt::Display for Profile { } pub fn setup(config: &Config, profile: Option) { - let path = &config.config.clone().unwrap_or(PathBuf::from("config.toml")); let profile = profile.unwrap_or_else(|| t!(interactive_path())); - setup_config_toml(path, profile, config); - let stage_path = ["build", config.build.rustc_target_arg(), "stage1"].join(&MAIN_SEPARATOR.to_string()); - println!(); - if !rustup_installed() && profile != Profile::User { eprintln!("`rustup` is not installed; cannot link `stage1` toolchain"); } else if stage_dir_exists(&stage_path[..]) { @@ -109,8 +104,6 @@ pub fn setup(config: &Config, profile: Option) { Profile::User => &["dist", "build"], }; - println!(); - t!(install_git_hook_maybe(&config)); println!(); @@ -125,10 +118,14 @@ pub fn setup(config: &Config, profile: Option) { "For more suggestions, see https://rustc-dev-guide.rust-lang.org/building/suggested.html" ); } + + let path = &config.config.clone().unwrap_or(PathBuf::from("config.toml")); + setup_config_toml(path, profile, config); } fn setup_config_toml(path: &PathBuf, profile: Profile, config: &Config) { if path.exists() { + eprintln!(); eprintln!( "error: you asked `x.py` to setup a new config file, but one already exists at `{}`", path.display() @@ -304,7 +301,18 @@ pub fn interactive_path() -> io::Result { // install a git hook to automatically run tidy --bless, if they want fn install_git_hook_maybe(config: &Config) -> io::Result<()> { + let git = t!(config.git().args(&["rev-parse", "--git-common-dir"]).output().map(|output| { + assert!(output.status.success(), "failed to run `git`"); + PathBuf::from(t!(String::from_utf8(output.stdout)).trim()) + })); + let dst = git.join("hooks").join("pre-push"); + if dst.exists() { + // The git hook has already been set up, or the user already has a custom hook. + return Ok(()); + } + let mut input = String::new(); + println!(); println!( "Rust's CI will automatically fail if it doesn't pass `tidy`, the internal tool for ensuring code quality. If you'd like, x.py can install a git hook for you that will automatically run `tidy --bless` before @@ -330,12 +338,6 @@ undesirable, simply delete the `pre-push` file from .git/hooks." if should_install { let src = config.src.join("src").join("etc").join("pre-push.sh"); - let git = - t!(config.git().args(&["rev-parse", "--git-common-dir"]).output().map(|output| { - assert!(output.status.success(), "failed to run `git`"); - PathBuf::from(t!(String::from_utf8(output.stdout)).trim()) - })); - let dst = git.join("hooks").join("pre-push"); match fs::hard_link(src, &dst) { Err(e) => eprintln!( "error: could not create hook {}: do you already have the git hook installed?\n{}", From ab89c171bdb29194baca274decf86acfecd2bb9d Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sat, 26 Nov 2022 16:11:07 -0500 Subject: [PATCH 012/115] Ensure required submodules at the same time as updating existing submodules In practice, this would always happen at the same time, but putting them next to each other makes that more obvious and ensures it doesn't change in the future. It also avoids the difference avoiding `cargo metadata` somehow. --- src/bootstrap/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 60ce431cb0c3..86b195fb89e0 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -579,6 +579,8 @@ impl Build { for s in rust_submodules { build.update_submodule(Path::new(s)); } + // Now, update all existing submodules. + build.update_existing_submodules(); build.verbose("learning about cargo"); metadata::build(&mut build); @@ -660,7 +662,7 @@ impl Build { /// If any submodule has been initialized already, sync it unconditionally. /// This avoids contributors checking in a submodule change by accident. - pub fn maybe_update_submodules(&self) { + pub fn update_existing_submodules(&self) { // Avoid running git when there isn't a git checkout. if !self.config.submodules(&self.rust_info()) { return; @@ -689,8 +691,6 @@ impl Build { job::setup(self); } - self.maybe_update_submodules(); - if let Subcommand::Format { check, paths } = &self.config.cmd { return format::format(&builder::Builder::new(&self), *check, &paths); } From 83ba42526fd859ab5605ada767f14c77b1dc2560 Mon Sep 17 00:00:00 2001 From: Will Crichton Date: Sat, 26 Nov 2022 21:39:39 -0600 Subject: [PATCH 013/115] Fix UI issues with Rustdoc scrape-examples feature. * Help file was being loaded from the wrong place. * CSS selector in JS has a typo. * Line numbers are overflowing, change to display: grid to fix. --- src/librustdoc/html/static/css/rustdoc.css | 4 +++- src/librustdoc/html/static/js/scrape-examples.js | 2 +- src/librustdoc/html/static_files.rs | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 586462c0ef08..ad943a06a6e2 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -2015,7 +2015,9 @@ in storage.js } .scraped-example .code-wrapper .example-wrap { - flex: 1; + display: grid; + grid-template-columns: max-content auto; + width: 100%; overflow-x: auto; overflow-y: hidden; margin-bottom: 0; diff --git a/src/librustdoc/html/static/js/scrape-examples.js b/src/librustdoc/html/static/js/scrape-examples.js index d0fd115fd15c..e328e656edda 100644 --- a/src/librustdoc/html/static/js/scrape-examples.js +++ b/src/librustdoc/html/static/js/scrape-examples.js @@ -57,7 +57,7 @@ }); }); - example.querySelector("next") + example.querySelector(".next") .addEventListener("click", () => { onChangeLoc(() => { locIndex = (locIndex + 1) % locs.length; diff --git a/src/librustdoc/html/static_files.rs b/src/librustdoc/html/static_files.rs index 1f87f95563ad..b48b82307ebc 100644 --- a/src/librustdoc/html/static_files.rs +++ b/src/librustdoc/html/static_files.rs @@ -130,4 +130,4 @@ static_files! { nanum_barun_gothic_license => "static/fonts/NanumBarunGothic-LICENSE.txt", } -pub(crate) static SCRAPE_EXAMPLES_HELP_MD: &str = include_str!("static/js/scrape-examples.js"); +pub(crate) static SCRAPE_EXAMPLES_HELP_MD: &str = include_str!("static/scrape-examples-help.md"); From 5a9fffc593046abaa3522cfe0a1a59c7decdc61d Mon Sep 17 00:00:00 2001 From: Will Crichton Date: Sat, 26 Nov 2022 23:27:10 -0600 Subject: [PATCH 014/115] Add test for scrape-examples next/prev buttons --- .../rustdoc-gui/scrape-examples-button-focus.goml | 15 ++++++++++++++- .../src/scrape_examples/examples/check.rs | 1 + 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/test/rustdoc-gui/scrape-examples-button-focus.goml b/src/test/rustdoc-gui/scrape-examples-button-focus.goml index 2a263a87a475..1eb04eb92d12 100644 --- a/src/test/rustdoc-gui/scrape-examples-button-focus.goml +++ b/src/test/rustdoc-gui/scrape-examples-button-focus.goml @@ -1,4 +1,17 @@ goto: "file://" + |DOC_PATH| + "/scrape_examples/fn.test.html" + +store-property: (initialScrollTop, ".scraped-example-list > .scraped-example pre", "scrollTop") +focus: ".scraped-example-list > .scraped-example .next" +press-key: "Enter" +assert-property-false: (".scraped-example-list > .scraped-example pre", { + "scrollTop": |initialScrollTop| +}) +focus: ".scraped-example-list > .scraped-example .prev" +press-key: "Enter" +assert-property: (".scraped-example-list > .scraped-example pre", { + "scrollTop": |initialScrollTop| +}) + store-property: (smallOffsetHeight, ".scraped-example-list > .scraped-example pre", "offsetHeight") assert-property-false: (".scraped-example-list > .scraped-example pre", { "scrollHeight": |smallOffsetHeight| @@ -11,4 +24,4 @@ assert-property-false: (".scraped-example-list > .scraped-example pre", { store-property: (fullOffsetHeight, ".scraped-example-list > .scraped-example pre", "offsetHeight") assert-property: (".scraped-example-list > .scraped-example pre", { "scrollHeight": |fullOffsetHeight| -}) +}) \ No newline at end of file diff --git a/src/test/rustdoc-gui/src/scrape_examples/examples/check.rs b/src/test/rustdoc-gui/src/scrape_examples/examples/check.rs index 3e69c6086ae2..b3f682fe4973 100644 --- a/src/test/rustdoc-gui/src/scrape_examples/examples/check.rs +++ b/src/test/rustdoc-gui/src/scrape_examples/examples/check.rs @@ -22,4 +22,5 @@ fn main() { println!("hello world!"); println!("hello world!"); } + scrape_examples::test(); } From 7674edeebac02ce9b3ee6434e5a4ab6a085005f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 25 Nov 2022 17:14:25 -0800 Subject: [PATCH 015/115] Detect long types in E0308 and write them to disk On type error with long types, print an abridged type and write the full type to disk. Print the widest possible short type while still fitting in the terminal. --- Cargo.lock | 1 + .../src/infer/error_reporting/mod.rs | 178 ++++++++++-------- .../src/infer/error_reporting/note.rs | 2 +- compiler/rustc_middle/src/ty/error.rs | 28 ++- compiler/rustc_session/Cargo.toml | 1 + compiler/rustc_session/src/session.rs | 11 ++ src/test/ui/diagnostic-width/long-E0308.rs | 86 +++++++++ .../ui/diagnostic-width/long-E0308.stderr | 80 ++++++++ src/test/ui/error-codes/E0275.stderr | 2 +- src/test/ui/issues/issue-20413.stderr | 10 +- src/test/ui/recursion/issue-83150.stderr | 2 +- src/test/ui/regions/issue-102374.rs | 1 + src/test/ui/regions/issue-102374.stderr | 5 +- .../issue-91949-hangs-on-recursion.stderr | 2 +- .../typeck/return_type_containing_closure.rs | 1 + .../return_type_containing_closure.stderr | 5 +- 16 files changed, 314 insertions(+), 101 deletions(-) create mode 100644 src/test/ui/diagnostic-width/long-E0308.rs create mode 100644 src/test/ui/diagnostic-width/long-E0308.stderr diff --git a/Cargo.lock b/Cargo.lock index dbf1e06ee6e9..550c5c69949b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4298,6 +4298,7 @@ dependencies = [ "rustc_span", "rustc_target", "smallvec", + "termize", "tracing", "winapi", ] diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index e2be8fb12d0d..1750282712a4 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -80,6 +80,7 @@ use rustc_middle::ty::{ use rustc_span::{sym, symbol::kw, BytePos, DesugaringKind, Pos, Span}; use rustc_target::spec::abi; use std::ops::{ControlFlow, Deref}; +use std::path::PathBuf; use std::{cmp, fmt, iter}; mod note; @@ -1351,10 +1352,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { .map(|(mod_str, _)| mod_str.len() + separator_len) .sum(); - debug!( - "cmp: separator_len={}, split_idx={}, min_len={}", - separator_len, split_idx, min_len - ); + debug!(?separator_len, ?split_idx, ?min_len, "cmp"); if split_idx >= min_len { // paths are identical, highlight everything @@ -1365,7 +1363,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } else { let (common, uniq1) = t1_str.split_at(split_idx); let (_, uniq2) = t2_str.split_at(split_idx); - debug!("cmp: common={}, uniq1={}, uniq2={}", common, uniq1, uniq2); + debug!(?common, ?uniq1, ?uniq2, "cmp"); values.0.push_normal(common); values.0.push_highlighted(uniq1); @@ -1658,17 +1656,14 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } ValuePairs::Regions(_) => (false, Mismatch::Fixed("lifetime")), }; - let vals = match self.values_str(values) { - Some((expected, found)) => Some((expected, found)), - None => { - // Derived error. Cancel the emitter. - // NOTE(eddyb) this was `.cancel()`, but `diag` - // is borrowed, so we can't fully defuse it. - diag.downgrade_to_delayed_bug(); - return; - } + let Some(vals) = self.values_str(values) else { + // Derived error. Cancel the emitter. + // NOTE(eddyb) this was `.cancel()`, but `diag` + // is borrowed, so we can't fully defuse it. + diag.downgrade_to_delayed_bug(); + return; }; - (vals, exp_found, is_simple_error, Some(values)) + (Some(vals), exp_found, is_simple_error, Some(values)) } }; @@ -1700,7 +1695,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { label_or_note(span, &terr.to_string()); } - if let Some((expected, found)) = expected_found { + if let Some((expected, found, exp_p, found_p)) = expected_found { let (expected_label, found_label, exp_found) = match exp_found { Mismatch::Variable(ef) => ( ef.expected.prefix_string(self.tcx), @@ -1817,32 +1812,41 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } TypeError::Sorts(values) => { let extra = expected == found; - let sort_string = |ty: Ty<'tcx>| match (extra, ty.kind()) { - (true, ty::Opaque(def_id, _)) => { - let sm = self.tcx.sess.source_map(); - let pos = sm.lookup_char_pos(self.tcx.def_span(*def_id).lo()); - format!( - " (opaque type at <{}:{}:{}>)", - sm.filename_for_diagnostics(&pos.file.name), - pos.line, - pos.col.to_usize() + 1, - ) + let sort_string = |ty: Ty<'tcx>, path: Option| { + let mut s = match (extra, ty.kind()) { + (true, ty::Opaque(def_id, _)) => { + let sm = self.tcx.sess.source_map(); + let pos = sm.lookup_char_pos(self.tcx.def_span(*def_id).lo()); + format!( + " (opaque type at <{}:{}:{}>)", + sm.filename_for_diagnostics(&pos.file.name), + pos.line, + pos.col.to_usize() + 1, + ) + } + (true, ty::Projection(proj)) + if self.tcx.def_kind(proj.item_def_id) + == DefKind::ImplTraitPlaceholder => + { + let sm = self.tcx.sess.source_map(); + let pos = sm.lookup_char_pos(self.tcx.def_span(proj.item_def_id).lo()); + format!( + " (trait associated opaque type at <{}:{}:{}>)", + sm.filename_for_diagnostics(&pos.file.name), + pos.line, + pos.col.to_usize() + 1, + ) + } + (true, _) => format!(" ({})", ty.sort_string(self.tcx)), + (false, _) => "".to_string(), + }; + if let Some(path) = path { + s.push_str(&format!( + "\nthe full type name has been written to '{}'", + path.display(), + )); } - (true, ty::Projection(proj)) - if self.tcx.def_kind(proj.item_def_id) - == DefKind::ImplTraitPlaceholder => - { - let sm = self.tcx.sess.source_map(); - let pos = sm.lookup_char_pos(self.tcx.def_span(proj.item_def_id).lo()); - format!( - " (trait associated opaque type at <{}:{}:{}>)", - sm.filename_for_diagnostics(&pos.file.name), - pos.line, - pos.col.to_usize() + 1, - ) - } - (true, _) => format!(" ({})", ty.sort_string(self.tcx)), - (false, _) => "".to_string(), + s }; if !(values.expected.is_simple_text() && values.found.is_simple_text()) || (exp_found.map_or(false, |ef| { @@ -1864,8 +1868,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { expected, &found_label, found, - &sort_string(values.expected), - &sort_string(values.found), + &sort_string(values.expected, exp_p), + &sort_string(values.found, found_p), ); } } @@ -2338,7 +2342,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { let code = trace.cause.code(); if let &MatchExpressionArm(box MatchExpressionArmCause { source, .. }) = code && let hir::MatchSource::TryDesugar = source - && let Some((expected_ty, found_ty)) = self.values_str(trace.values) + && let Some((expected_ty, found_ty, _, _)) = self.values_str(trace.values) { err.note(&format!( "`?` operator cannot convert from `{}` to `{}`", @@ -2454,7 +2458,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { fn values_str( &self, values: ValuePairs<'tcx>, - ) -> Option<(DiagnosticStyledString, DiagnosticStyledString)> { + ) -> Option<(DiagnosticStyledString, DiagnosticStyledString, Option, Option)> + { match values { infer::Regions(exp_found) => self.expected_found_str(exp_found), infer::Terms(exp_found) => self.expected_found_str_term(exp_found), @@ -2464,7 +2469,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { found: exp_found.found.print_only_trait_path(), }; match self.expected_found_str(pretty_exp_found) { - Some((expected, found)) if expected == found => { + Some((expected, found, _, _)) if expected == found => { self.expected_found_str(exp_found) } ret => ret, @@ -2476,7 +2481,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { found: exp_found.found.print_only_trait_path(), }; match self.expected_found_str(pretty_exp_found) { - Some((expected, found)) if expected == found => { + Some((expected, found, _, _)) if expected == found => { self.expected_found_str(exp_found) } ret => ret, @@ -2488,17 +2493,38 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { fn expected_found_str_term( &self, exp_found: ty::error::ExpectedFound>, - ) -> Option<(DiagnosticStyledString, DiagnosticStyledString)> { + ) -> Option<(DiagnosticStyledString, DiagnosticStyledString, Option, Option)> + { let exp_found = self.resolve_vars_if_possible(exp_found); if exp_found.references_error() { return None; } Some(match (exp_found.expected.unpack(), exp_found.found.unpack()) { - (ty::TermKind::Ty(expected), ty::TermKind::Ty(found)) => self.cmp(expected, found), + (ty::TermKind::Ty(expected), ty::TermKind::Ty(found)) => { + let (mut exp, mut fnd) = self.cmp(expected, found); + let len = self.tcx.sess().diagnostic_width().saturating_sub(20); + let exp_s = exp.content(); + let fnd_s = fnd.content(); + let mut exp_p = None; + let mut fnd_p = None; + if exp_s.len() > len { + let (exp_s, exp_path) = self.tcx.short_ty_string(expected); + exp = DiagnosticStyledString::highlighted(exp_s); + exp_p = exp_path; + } + if fnd_s.len() > len { + let (fnd_s, fnd_path) = self.tcx.short_ty_string(found); + fnd = DiagnosticStyledString::highlighted(fnd_s); + fnd_p = fnd_path; + } + (exp, fnd, exp_p, fnd_p) + } _ => ( DiagnosticStyledString::highlighted(exp_found.expected.to_string()), DiagnosticStyledString::highlighted(exp_found.found.to_string()), + None, + None, ), }) } @@ -2507,7 +2533,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { fn expected_found_str>( &self, exp_found: ty::error::ExpectedFound, - ) -> Option<(DiagnosticStyledString, DiagnosticStyledString)> { + ) -> Option<(DiagnosticStyledString, DiagnosticStyledString, Option, Option)> + { let exp_found = self.resolve_vars_if_possible(exp_found); if exp_found.references_error() { return None; @@ -2516,6 +2543,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { Some(( DiagnosticStyledString::highlighted(exp_found.expected.to_string()), DiagnosticStyledString::highlighted(exp_found.found.to_string()), + None, + None, )) } @@ -2849,36 +2878,29 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { debug!("report_sub_sup_conflict: sup_region={:?}", sup_region); debug!("report_sub_sup_conflict: sup_origin={:?}", sup_origin); - if let (&infer::Subtype(ref sup_trace), &infer::Subtype(ref sub_trace)) = - (&sup_origin, &sub_origin) + if let infer::Subtype(ref sup_trace) = sup_origin + && let infer::Subtype(ref sub_trace) = sub_origin + && let Some((sup_expected, sup_found, _, _)) = self.values_str(sup_trace.values) + && let Some((sub_expected, sub_found, _, _)) = self.values_str(sub_trace.values) + && sub_expected == sup_expected + && sub_found == sup_found { - debug!("report_sub_sup_conflict: sup_trace={:?}", sup_trace); - debug!("report_sub_sup_conflict: sub_trace={:?}", sub_trace); - debug!("report_sub_sup_conflict: sup_trace.values={:?}", sup_trace.values); - debug!("report_sub_sup_conflict: sub_trace.values={:?}", sub_trace.values); + note_and_explain_region( + self.tcx, + &mut err, + "...but the lifetime must also be valid for ", + sub_region, + "...", + None, + ); + err.span_note( + sup_trace.cause.span, + &format!("...so that the {}", sup_trace.cause.as_requirement_str()), + ); - if let (Some((sup_expected, sup_found)), Some((sub_expected, sub_found))) = - (self.values_str(sup_trace.values), self.values_str(sub_trace.values)) - { - if sub_expected == sup_expected && sub_found == sup_found { - note_and_explain_region( - self.tcx, - &mut err, - "...but the lifetime must also be valid for ", - sub_region, - "...", - None, - ); - err.span_note( - sup_trace.cause.span, - &format!("...so that the {}", sup_trace.cause.as_requirement_str()), - ); - - err.note_expected_found(&"", sup_expected, &"", sup_found); - err.emit(); - return; - } - } + err.note_expected_found(&"", sup_expected, &"", sup_found); + err.emit(); + return; } self.note_region_origin(&mut err, &sup_origin); diff --git a/compiler/rustc_infer/src/infer/error_reporting/note.rs b/compiler/rustc_infer/src/infer/error_reporting/note.rs index 41b115f3377a..d2dffa4a0b78 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs @@ -16,7 +16,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { infer::Subtype(ref trace) => RegionOriginNote::WithRequirement { span: trace.cause.span, requirement: ObligationCauseAsDiagArg(trace.cause.clone()), - expected_found: self.values_str(trace.values), + expected_found: self.values_str(trace.values).map(|(e, f, _, _)| (e, f)), } .add_to_diagnostic(err), infer::Reborrow(span) => { diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index d83e17574a09..cc3101bc83bb 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -986,8 +986,8 @@ fn foo(&self) -> Self::T { String::new() } } pub fn short_ty_string(self, ty: Ty<'tcx>) -> (String, Option) { - let length_limit = 50; - let type_limit = 4; + let length_limit = self.sess.diagnostic_width().saturating_sub(20); + let mut type_limit = 50; let regular = FmtPrinter::new(self, hir::def::Namespace::TypeNS) .pretty_print_type(ty) .expect("could not write to `String`") @@ -995,14 +995,22 @@ fn foo(&self) -> Self::T { String::new() } if regular.len() <= length_limit { return (regular, None); } - let short = FmtPrinter::new_with_limit( - self, - hir::def::Namespace::TypeNS, - rustc_session::Limit(type_limit), - ) - .pretty_print_type(ty) - .expect("could not write to `String`") - .into_buffer(); + let mut short; + loop { + // Look for the longest properly trimmed path that still fits in lenght_limit. + short = FmtPrinter::new_with_limit( + self, + hir::def::Namespace::TypeNS, + rustc_session::Limit(type_limit), + ) + .pretty_print_type(ty) + .expect("could not write to `String`") + .into_buffer(); + if short.len() <= length_limit || type_limit == 0 { + break; + } + type_limit -= 1; + } if regular == short { return (regular, None); } diff --git a/compiler/rustc_session/Cargo.toml b/compiler/rustc_session/Cargo.toml index a052f2933416..cbbba2252bf6 100644 --- a/compiler/rustc_session/Cargo.toml +++ b/compiler/rustc_session/Cargo.toml @@ -18,6 +18,7 @@ rustc_fs_util = { path = "../rustc_fs_util" } rustc_ast = { path = "../rustc_ast" } rustc_lint_defs = { path = "../rustc_lint_defs" } smallvec = "1.8.1" +termize = "0.1.1" [target.'cfg(unix)'.dependencies] libc = "0.2" diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index e99e460913ef..4c049a8d628e 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -952,6 +952,17 @@ impl Session { ) -> Option { attrs.iter().find(|at| at.has_name(name)).and_then(|at| at.value_str()) } + + pub fn diagnostic_width(&self) -> usize { + let default_column_width = 140; + if let Some(width) = self.opts.diagnostic_width { + width + } else if self.opts.unstable_opts.ui_testing { + default_column_width + } else { + termize::dimensions().map_or(default_column_width, |(w, _)| w) + } + } } // JUSTIFICATION: defn of the suggested wrapper fns diff --git a/src/test/ui/diagnostic-width/long-E0308.rs b/src/test/ui/diagnostic-width/long-E0308.rs new file mode 100644 index 000000000000..22ee1cd8d55b --- /dev/null +++ b/src/test/ui/diagnostic-width/long-E0308.rs @@ -0,0 +1,86 @@ +// compile-flags: --diagnostic-width=100 +// normalize-stderr-test: "long-type-\d+" -> "long-type-hash" + +struct Atype(T, K); +struct Btype(T, K); +struct Ctype(T, K); + +fn main() { + let x: Atype< + Btype< + Ctype< + Atype< + Btype< + Ctype< + Atype< + Btype< + Ctype, + i32 + >, + i32 + >, + i32 + >, + i32 + >, + i32 + >, + i32 + >, + i32 + >, + i32 + > = Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok( + Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok( + Ok("") + )))))))))))))))))))))))))))))) + )))))))))))))))))))))))))))))); + //~^^^^^ ERROR E0308 + + let _ = Some(Ok(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some( + Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some( + Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some( + Some(Some(Some(Some(Some(Some(Some(Some(Some(""))))))))) + ))))))))))))))))) + )))))))))))))))))) + ))))))))))))))))) == Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok( + Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok( + Ok(Ok(Ok(Ok(Ok(Ok(Ok(""))))))) + )))))))))))))))))))))))))))))) + )))))))))))))))))))))))); + //~^^^^^ ERROR E0308 + + let x: Atype< + Btype< + Ctype< + Atype< + Btype< + Ctype< + Atype< + Btype< + Ctype, + i32 + >, + i32 + >, + i32 + >, + i32 + >, + i32 + >, + i32 + >, + i32 + >, + i32 + > = (); + //~^ ERROR E0308 + + let _: () = Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok( + Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok( + Ok(Ok(Ok(Ok(Ok(Ok(Ok(""))))))) + )))))))))))))))))))))))))))))) + )))))))))))))))))))))))); + //~^^^^^ ERROR E0308 +} diff --git a/src/test/ui/diagnostic-width/long-E0308.stderr b/src/test/ui/diagnostic-width/long-E0308.stderr new file mode 100644 index 000000000000..142e34f7687f --- /dev/null +++ b/src/test/ui/diagnostic-width/long-E0308.stderr @@ -0,0 +1,80 @@ +error[E0308]: mismatched types + --> $DIR/long-E0308.rs:33:9 + | +LL | let x: Atype< + | ____________- +LL | | Btype< +LL | | Ctype< +LL | | Atype< +... | +LL | | i32 +LL | | > = Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(... + | |_____-___^ + | ||_____| + | | expected due to this +LL | | Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(... +LL | | Ok("") +LL | | )))))))))))))))))))))))))))))) +LL | | )))))))))))))))))))))))))))))); + | |___________________________________^ expected struct `Atype`, found enum `Result` + | + = note: expected struct `Atype, ...>, ...>, ...>, ...>, ...>` + the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt' + found enum `Result, ...>, ...>, ...>, ...>` + the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt' + +error[E0308]: mismatched types + --> $DIR/long-E0308.rs:46:26 + | +LL | ))))))))))))))))) == Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok... + | __________________________^ +LL | | Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(O... +LL | | Ok(Ok(Ok(Ok(Ok(Ok(Ok(""))))))) +LL | | )))))))))))))))))))))))))))))) +LL | | )))))))))))))))))))))))); + | |____________________________^ expected enum `Option`, found enum `Result` + | + = note: expected enum `Option>>>>>>, ...>>` + the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt' + found enum `Result, ...>, ...>, ...>, ...>` + the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt' + +error[E0308]: mismatched types + --> $DIR/long-E0308.rs:77:9 + | +LL | let x: Atype< + | ____________- +LL | | Btype< +LL | | Ctype< +LL | | Atype< +... | +LL | | i32 +LL | | > = (); + | | - ^^ expected struct `Atype`, found `()` + | |_____| + | expected due to this + | + = note: expected struct `Atype, ...>, ...>, ...>, ...>, ...>` + the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt' + found unit type `()` + +error[E0308]: mismatched types + --> $DIR/long-E0308.rs:80:17 + | +LL | let _: () = Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok( + | ____________--___^ + | | | + | | expected due to this +LL | | Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(O... +LL | | Ok(Ok(Ok(Ok(Ok(Ok(Ok(""))))))) +LL | | )))))))))))))))))))))))))))))) +LL | | )))))))))))))))))))))))); + | |____________________________^ expected `()`, found enum `Result` + | + = note: expected unit type `()` + found enum `Result, ...>, ...>, ...>, ...>` + the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt' + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/error-codes/E0275.stderr b/src/test/ui/error-codes/E0275.stderr index 49a4d984af9e..8d4f44218bc8 100644 --- a/src/test/ui/error-codes/E0275.stderr +++ b/src/test/ui/error-codes/E0275.stderr @@ -5,7 +5,7 @@ LL | impl Foo for T where Bar: Foo {} | ^^^ | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`E0275`) -note: required for `Bar>>>>>` to implement `Foo` +note: required for `Bar>>>>>>>>>>>>>>>>>>>>>>` to implement `Foo` --> $DIR/E0275.rs:6:9 | LL | impl Foo for T where Bar: Foo {} diff --git a/src/test/ui/issues/issue-20413.stderr b/src/test/ui/issues/issue-20413.stderr index 91509ceace8c..0a5867429e24 100644 --- a/src/test/ui/issues/issue-20413.stderr +++ b/src/test/ui/issues/issue-20413.stderr @@ -14,7 +14,7 @@ LL | impl Foo for T where NoData: Foo { | ^^^ | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_20413`) -note: required for `NoData>>>>>` to implement `Foo` +note: required for `NoData>>>>>>>>>>>>>` to implement `Foo` --> $DIR/issue-20413.rs:9:9 | LL | impl Foo for T where NoData: Foo { @@ -30,13 +30,13 @@ LL | impl Bar for T where EvenLessData: Baz { | ^^^ | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_20413`) -note: required for `AlmostNoData>>>>>` to implement `Bar` +note: required for `AlmostNoData>>>>>>>` to implement `Bar` --> $DIR/issue-20413.rs:28:9 | LL | impl Bar for T where EvenLessData: Baz { | ^^^ ^ = note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-20413/issue-20413.long-type-hash.txt' -note: required for `EvenLessData>>>>>` to implement `Baz` +note: required for `EvenLessData>>>>>>>` to implement `Baz` --> $DIR/issue-20413.rs:35:9 | LL | impl Baz for T where AlmostNoData: Bar { @@ -52,13 +52,13 @@ LL | impl Baz for T where AlmostNoData: Bar { | ^^^ | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_20413`) -note: required for `EvenLessData>>>>>` to implement `Baz` +note: required for `EvenLessData>>>>>>>` to implement `Baz` --> $DIR/issue-20413.rs:35:9 | LL | impl Baz for T where AlmostNoData: Bar { | ^^^ ^ = note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-20413/issue-20413.long-type-hash.txt' -note: required for `AlmostNoData>>>>>` to implement `Bar` +note: required for `AlmostNoData>>>>>>>` to implement `Bar` --> $DIR/issue-20413.rs:28:9 | LL | impl Bar for T where EvenLessData: Baz { diff --git a/src/test/ui/recursion/issue-83150.stderr b/src/test/ui/recursion/issue-83150.stderr index 4d00a7083137..fc43efff2eac 100644 --- a/src/test/ui/recursion/issue-83150.stderr +++ b/src/test/ui/recursion/issue-83150.stderr @@ -12,7 +12,7 @@ LL | func(&mut iter.map(|x| x + 1)) error[E0275]: overflow evaluating the requirement `Map<&mut Map<&mut Map<&mut Map<..., ...>, ...>, ...>, ...>: Iterator` | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_83150`) - = note: required for `&mut Map<&mut Map<&mut Map<..., ...>, ...>, ...>` to implement `Iterator` + = note: required for `&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut ..., ...>, ...>, ...>, ...>, ...>, ...>, ...>` to implement `Iterator` = note: the full type name has been written to '$TEST_BUILD_DIR/recursion/issue-83150/issue-83150.long-type-hash.txt' error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/regions/issue-102374.rs b/src/test/ui/regions/issue-102374.rs index e0a1164211a2..fd71248d9cb4 100644 --- a/src/test/ui/regions/issue-102374.rs +++ b/src/test/ui/regions/issue-102374.rs @@ -1,3 +1,4 @@ +// normalize-stderr-test: "long-type-\d+" -> "long-type-hash" use std::cell::Cell; #[rustfmt::skip] diff --git a/src/test/ui/regions/issue-102374.stderr b/src/test/ui/regions/issue-102374.stderr index 31b855c36bea..157850693ab5 100644 --- a/src/test/ui/regions/issue-102374.stderr +++ b/src/test/ui/regions/issue-102374.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/issue-102374.rs:16:5 + --> $DIR/issue-102374.rs:17:5 | LL | ) -> i32 { | --- expected `i32` because of return type @@ -7,7 +7,8 @@ LL | f | ^ expected `i32`, found fn pointer | = note: expected type `i32` - found fn pointer `for<'z1, 'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i, 'j, 'k, 'l, 'm, 'n, 'o, 'p, 'q, 'r, 's, 't, 'u, 'v, 'w, 'x, 'y, 'z, 'z0> fn(Cell<(&'z1 i32, &'a i32, &'b i32, &'c i32, &'d i32, &'e i32, &'f i32, &'g i32, &'h i32, &'i i32, &'j i32, &'k i32, &'l i32, &'m i32, &'n i32, &'o i32, &'p i32, &'q i32, &'r i32, &'s i32, &'t i32, &'u i32, &'v i32, &'w i32, &'x i32, &'y i32, &'z i32, &'z0 i32)>)` + found fn pointer `for<'z1, 'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i, 'j, 'k, 'l, 'm, 'n, 'o, 'p, 'q, 'r, 's, 't, 'u, 'v, 'w, 'x, 'y, 'z, 'z0> fn(Cell<...>)` + the full type name has been written to '$TEST_BUILD_DIR/regions/issue-102374/issue-102374.long-type-hash.txt' error: aborting due to previous error diff --git a/src/test/ui/traits/issue-91949-hangs-on-recursion.stderr b/src/test/ui/traits/issue-91949-hangs-on-recursion.stderr index a74d2524996a..1f18c5daf66e 100644 --- a/src/test/ui/traits/issue-91949-hangs-on-recursion.stderr +++ b/src/test/ui/traits/issue-91949-hangs-on-recursion.stderr @@ -17,7 +17,7 @@ error[E0275]: overflow evaluating the requirement `(): Sized` = help: consider increasing the recursion limit by adding a `#![recursion_limit = "512"]` attribute to your crate (`issue_91949_hangs_on_recursion`) = note: required for `std::iter::Empty<()>` to implement `Iterator` = note: 171 redundant requirements hidden - = note: required for `IteratorOfWrapped<(), Map>, ...>>` to implement `Iterator` + = note: required for `IteratorOfWrapped<(), Map>, ...>>, ...>>` to implement `Iterator` = note: the full type name has been written to '$TEST_BUILD_DIR/traits/issue-91949-hangs-on-recursion/issue-91949-hangs-on-recursion.long-type-hash.txt' error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/typeck/return_type_containing_closure.rs b/src/test/ui/typeck/return_type_containing_closure.rs index 29624e08a2e8..ea7b47a5a380 100644 --- a/src/test/ui/typeck/return_type_containing_closure.rs +++ b/src/test/ui/typeck/return_type_containing_closure.rs @@ -1,3 +1,4 @@ +// normalize-stderr-test: "long-type-\d+" -> "long-type-hash" #[allow(unused)] fn foo() { //~ HELP a return type might be missing here vec!['a'].iter().map(|c| c) diff --git a/src/test/ui/typeck/return_type_containing_closure.stderr b/src/test/ui/typeck/return_type_containing_closure.stderr index 101aee39559c..d6c103de3dc1 100644 --- a/src/test/ui/typeck/return_type_containing_closure.stderr +++ b/src/test/ui/typeck/return_type_containing_closure.stderr @@ -1,11 +1,12 @@ error[E0308]: mismatched types - --> $DIR/return_type_containing_closure.rs:3:5 + --> $DIR/return_type_containing_closure.rs:4:5 | LL | vec!['a'].iter().map(|c| c) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found struct `Map` | = note: expected unit type `()` - found struct `Map, [closure@$DIR/return_type_containing_closure.rs:3:26: 3:29]>` + found struct `Map, ...>` + the full type name has been written to '$TEST_BUILD_DIR/typeck/return_type_containing_closure/return_type_containing_closure.long-type-hash.txt' help: consider using a semicolon here | LL | vec!['a'].iter().map(|c| c); From 360c0a7a3e787aea059d9a100907dfb5841b3dee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 25 Nov 2022 18:20:08 -0800 Subject: [PATCH 016/115] Tweak shortening logic to be less trigger happy --- .../src/infer/error_reporting/mod.rs | 5 +++- src/test/ui/diagnostic-width/long-E0308.rs | 2 +- .../ui/diagnostic-width/long-E0308.stderr | 24 +++++++++---------- .../return_type_containing_closure.stderr | 3 +-- 4 files changed, 18 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 1750282712a4..7b936c7693b1 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -2503,7 +2503,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { Some(match (exp_found.expected.unpack(), exp_found.found.unpack()) { (ty::TermKind::Ty(expected), ty::TermKind::Ty(found)) => { let (mut exp, mut fnd) = self.cmp(expected, found); - let len = self.tcx.sess().diagnostic_width().saturating_sub(20); + // Use the terminal width as the basis to determine when to compress the printed + // out type, but give ourselves some leeway to avoid ending up creating a file for + // a type that is somewhat shorter than the path we'd write to. + let len = self.tcx.sess().diagnostic_width() + 40; let exp_s = exp.content(); let fnd_s = fnd.content(); let mut exp_p = None; diff --git a/src/test/ui/diagnostic-width/long-E0308.rs b/src/test/ui/diagnostic-width/long-E0308.rs index 22ee1cd8d55b..3fd7a7110fd9 100644 --- a/src/test/ui/diagnostic-width/long-E0308.rs +++ b/src/test/ui/diagnostic-width/long-E0308.rs @@ -1,4 +1,4 @@ -// compile-flags: --diagnostic-width=100 +// compile-flags: --diagnostic-width=60 // normalize-stderr-test: "long-type-\d+" -> "long-type-hash" struct Atype(T, K); diff --git a/src/test/ui/diagnostic-width/long-E0308.stderr b/src/test/ui/diagnostic-width/long-E0308.stderr index 142e34f7687f..c784995b0e86 100644 --- a/src/test/ui/diagnostic-width/long-E0308.stderr +++ b/src/test/ui/diagnostic-width/long-E0308.stderr @@ -8,35 +8,35 @@ LL | | Ctype< LL | | Atype< ... | LL | | i32 -LL | | > = Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(... +LL | | > = Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok... | |_____-___^ | ||_____| | | expected due to this -LL | | Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(... +LL | | Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok... LL | | Ok("") LL | | )))))))))))))))))))))))))))))) LL | | )))))))))))))))))))))))))))))); | |___________________________________^ expected struct `Atype`, found enum `Result` | - = note: expected struct `Atype, ...>, ...>, ...>, ...>, ...>` + = note: expected struct `Atype, ...>, ...>` the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt' - found enum `Result, ...>, ...>, ...>, ...>` + found enum `Result, ...>` the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt' error[E0308]: mismatched types --> $DIR/long-E0308.rs:46:26 | -LL | ))))))))))))))))) == Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok... +LL | ))))))))))))))))) == Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(O... | __________________________^ -LL | | Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(O... +LL | | Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(... LL | | Ok(Ok(Ok(Ok(Ok(Ok(Ok(""))))))) LL | | )))))))))))))))))))))))))))))) LL | | )))))))))))))))))))))))); | |____________________________^ expected enum `Option`, found enum `Result` | - = note: expected enum `Option>>>>>>, ...>>` + = note: expected enum `Option>, ...>>` the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt' - found enum `Result, ...>, ...>, ...>, ...>` + found enum `Result, ...>` the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt' error[E0308]: mismatched types @@ -54,25 +54,25 @@ LL | | > = (); | |_____| | expected due to this | - = note: expected struct `Atype, ...>, ...>, ...>, ...>, ...>` + = note: expected struct `Atype, ...>, ...>` the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt' found unit type `()` error[E0308]: mismatched types --> $DIR/long-E0308.rs:80:17 | -LL | let _: () = Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok( +LL | let _: () = Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(O... | ____________--___^ | | | | | expected due to this -LL | | Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(O... +LL | | Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(... LL | | Ok(Ok(Ok(Ok(Ok(Ok(Ok(""))))))) LL | | )))))))))))))))))))))))))))))) LL | | )))))))))))))))))))))))); | |____________________________^ expected `()`, found enum `Result` | = note: expected unit type `()` - found enum `Result, ...>, ...>, ...>, ...>` + found enum `Result, ...>` the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt' error: aborting due to 4 previous errors diff --git a/src/test/ui/typeck/return_type_containing_closure.stderr b/src/test/ui/typeck/return_type_containing_closure.stderr index d6c103de3dc1..90b552a62839 100644 --- a/src/test/ui/typeck/return_type_containing_closure.stderr +++ b/src/test/ui/typeck/return_type_containing_closure.stderr @@ -5,8 +5,7 @@ LL | vec!['a'].iter().map(|c| c) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found struct `Map` | = note: expected unit type `()` - found struct `Map, ...>` - the full type name has been written to '$TEST_BUILD_DIR/typeck/return_type_containing_closure/return_type_containing_closure.long-type-hash.txt' + found struct `Map, [closure@$DIR/return_type_containing_closure.rs:4:26: 4:29]>` help: consider using a semicolon here | LL | vec!['a'].iter().map(|c| c); From 73b371a16c54e610617070c85a2572ce04475a2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 25 Nov 2022 19:08:46 -0800 Subject: [PATCH 017/115] Further tweak the type shortening logic --- compiler/rustc_middle/src/ty/error.rs | 5 +++-- src/test/ui/diagnostic-width/long-E0308.stderr | 6 +++--- src/test/ui/error-codes/E0275.stderr | 2 +- src/test/ui/issues/issue-20413.stderr | 10 +++++----- src/test/ui/recursion/issue-83150.stderr | 2 +- 5 files changed, 13 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index cc3101bc83bb..aa61c39b8d81 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -986,13 +986,14 @@ fn foo(&self) -> Self::T { String::new() } } pub fn short_ty_string(self, ty: Ty<'tcx>) -> (String, Option) { - let length_limit = self.sess.diagnostic_width().saturating_sub(20); + let width = self.sess.diagnostic_width(); + let length_limit = width.saturating_sub(30); let mut type_limit = 50; let regular = FmtPrinter::new(self, hir::def::Namespace::TypeNS) .pretty_print_type(ty) .expect("could not write to `String`") .into_buffer(); - if regular.len() <= length_limit { + if regular.len() <= width { return (regular, None); } let mut short; diff --git a/src/test/ui/diagnostic-width/long-E0308.stderr b/src/test/ui/diagnostic-width/long-E0308.stderr index c784995b0e86..99270a4696cb 100644 --- a/src/test/ui/diagnostic-width/long-E0308.stderr +++ b/src/test/ui/diagnostic-width/long-E0308.stderr @@ -18,7 +18,7 @@ LL | | )))))))))))))))))))))))))))))) LL | | )))))))))))))))))))))))))))))); | |___________________________________^ expected struct `Atype`, found enum `Result` | - = note: expected struct `Atype, ...>, ...>` + = note: expected struct `Atype, ...>` the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt' found enum `Result, ...>` the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt' @@ -34,7 +34,7 @@ LL | | )))))))))))))))))))))))))))))) LL | | )))))))))))))))))))))))); | |____________________________^ expected enum `Option`, found enum `Result` | - = note: expected enum `Option>, ...>>` + = note: expected enum `Option>` the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt' found enum `Result, ...>` the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt' @@ -54,7 +54,7 @@ LL | | > = (); | |_____| | expected due to this | - = note: expected struct `Atype, ...>, ...>` + = note: expected struct `Atype, ...>` the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt' found unit type `()` diff --git a/src/test/ui/error-codes/E0275.stderr b/src/test/ui/error-codes/E0275.stderr index 8d4f44218bc8..451a683ac8a6 100644 --- a/src/test/ui/error-codes/E0275.stderr +++ b/src/test/ui/error-codes/E0275.stderr @@ -5,7 +5,7 @@ LL | impl Foo for T where Bar: Foo {} | ^^^ | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`E0275`) -note: required for `Bar>>>>>>>>>>>>>>>>>>>>>>` to implement `Foo` +note: required for `Bar>>>>>>>>>>>>>>>>>>>>` to implement `Foo` --> $DIR/E0275.rs:6:9 | LL | impl Foo for T where Bar: Foo {} diff --git a/src/test/ui/issues/issue-20413.stderr b/src/test/ui/issues/issue-20413.stderr index 0a5867429e24..78df445972c9 100644 --- a/src/test/ui/issues/issue-20413.stderr +++ b/src/test/ui/issues/issue-20413.stderr @@ -14,7 +14,7 @@ LL | impl Foo for T where NoData: Foo { | ^^^ | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_20413`) -note: required for `NoData>>>>>>>>>>>>>` to implement `Foo` +note: required for `NoData>>>>>>>>>>>>` to implement `Foo` --> $DIR/issue-20413.rs:9:9 | LL | impl Foo for T where NoData: Foo { @@ -30,13 +30,13 @@ LL | impl Bar for T where EvenLessData: Baz { | ^^^ | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_20413`) -note: required for `AlmostNoData>>>>>>>` to implement `Bar` +note: required for `AlmostNoData>>>>>>` to implement `Bar` --> $DIR/issue-20413.rs:28:9 | LL | impl Bar for T where EvenLessData: Baz { | ^^^ ^ = note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-20413/issue-20413.long-type-hash.txt' -note: required for `EvenLessData>>>>>>>` to implement `Baz` +note: required for `EvenLessData>>>>>>` to implement `Baz` --> $DIR/issue-20413.rs:35:9 | LL | impl Baz for T where AlmostNoData: Bar { @@ -52,13 +52,13 @@ LL | impl Baz for T where AlmostNoData: Bar { | ^^^ | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_20413`) -note: required for `EvenLessData>>>>>>>` to implement `Baz` +note: required for `EvenLessData>>>>>>` to implement `Baz` --> $DIR/issue-20413.rs:35:9 | LL | impl Baz for T where AlmostNoData: Bar { | ^^^ ^ = note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-20413/issue-20413.long-type-hash.txt' -note: required for `AlmostNoData>>>>>>>` to implement `Bar` +note: required for `AlmostNoData>>>>>>` to implement `Bar` --> $DIR/issue-20413.rs:28:9 | LL | impl Bar for T where EvenLessData: Baz { diff --git a/src/test/ui/recursion/issue-83150.stderr b/src/test/ui/recursion/issue-83150.stderr index fc43efff2eac..dde8ad1b6b32 100644 --- a/src/test/ui/recursion/issue-83150.stderr +++ b/src/test/ui/recursion/issue-83150.stderr @@ -12,7 +12,7 @@ LL | func(&mut iter.map(|x| x + 1)) error[E0275]: overflow evaluating the requirement `Map<&mut Map<&mut Map<&mut Map<..., ...>, ...>, ...>, ...>: Iterator` | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_83150`) - = note: required for `&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut ..., ...>, ...>, ...>, ...>, ...>, ...>, ...>` to implement `Iterator` + = note: required for `&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<..., ...>, ...>, ...>, ...>, ...>, ...>, ...>` to implement `Iterator` = note: the full type name has been written to '$TEST_BUILD_DIR/recursion/issue-83150/issue-83150.long-type-hash.txt' error: aborting due to previous error; 1 warning emitted From be02bd9ac1483c67b7764eb81bfc3396f9f18473 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 25 Nov 2022 19:54:02 -0800 Subject: [PATCH 018/115] Remove unneeded test change --- src/test/ui/typeck/return_type_containing_closure.rs | 1 - src/test/ui/typeck/return_type_containing_closure.stderr | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/test/ui/typeck/return_type_containing_closure.rs b/src/test/ui/typeck/return_type_containing_closure.rs index ea7b47a5a380..29624e08a2e8 100644 --- a/src/test/ui/typeck/return_type_containing_closure.rs +++ b/src/test/ui/typeck/return_type_containing_closure.rs @@ -1,4 +1,3 @@ -// normalize-stderr-test: "long-type-\d+" -> "long-type-hash" #[allow(unused)] fn foo() { //~ HELP a return type might be missing here vec!['a'].iter().map(|c| c) diff --git a/src/test/ui/typeck/return_type_containing_closure.stderr b/src/test/ui/typeck/return_type_containing_closure.stderr index 90b552a62839..101aee39559c 100644 --- a/src/test/ui/typeck/return_type_containing_closure.stderr +++ b/src/test/ui/typeck/return_type_containing_closure.stderr @@ -1,11 +1,11 @@ error[E0308]: mismatched types - --> $DIR/return_type_containing_closure.rs:4:5 + --> $DIR/return_type_containing_closure.rs:3:5 | LL | vec!['a'].iter().map(|c| c) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found struct `Map` | = note: expected unit type `()` - found struct `Map, [closure@$DIR/return_type_containing_closure.rs:4:26: 4:29]>` + found struct `Map, [closure@$DIR/return_type_containing_closure.rs:3:26: 3:29]>` help: consider using a semicolon here | LL | vec!['a'].iter().map(|c| c); From 360bcb6fc6fb09e4a20e6b6de4f8db86807cb9a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 26 Nov 2022 12:24:58 -0800 Subject: [PATCH 019/115] fix test --- src/test/ui/issues/issue-23122-2.stderr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/issues/issue-23122-2.stderr b/src/test/ui/issues/issue-23122-2.stderr index 5828e027b590..1f50b06a0e4c 100644 --- a/src/test/ui/issues/issue-23122-2.stderr +++ b/src/test/ui/issues/issue-23122-2.stderr @@ -5,7 +5,7 @@ LL | type Next = as Next>::Next; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_23122_2`) -note: required for `GetNext<<<<<<... as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next>` to implement `Next` +note: required for `GetNext<<<<<<<... as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next>` to implement `Next` --> $DIR/issue-23122-2.rs:10:15 | LL | impl Next for GetNext { From 34b3c49d72b4199b7a804e8893fc585dbd00d5d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 28 Nov 2022 14:41:42 -0800 Subject: [PATCH 020/115] fix rebase --- .../ui/diagnostic-width/long-E0308.stderr | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/test/ui/diagnostic-width/long-E0308.stderr b/src/test/ui/diagnostic-width/long-E0308.stderr index 99270a4696cb..487ab23a1c10 100644 --- a/src/test/ui/diagnostic-width/long-E0308.stderr +++ b/src/test/ui/diagnostic-width/long-E0308.stderr @@ -2,21 +2,21 @@ error[E0308]: mismatched types --> $DIR/long-E0308.rs:33:9 | LL | let x: Atype< - | ____________- -LL | | Btype< -LL | | Ctype< -LL | | Atype< -... | -LL | | i32 -LL | | > = Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok... - | |_____-___^ + | _____________- +LL | | Btype< +LL | | Ctype< +LL | | Atype< +... | +LL | | i32 +LL | | > = Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok... + | | _____-___^ | ||_____| - | | expected due to this -LL | | Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok... -LL | | Ok("") -LL | | )))))))))))))))))))))))))))))) -LL | | )))))))))))))))))))))))))))))); - | |___________________________________^ expected struct `Atype`, found enum `Result` + | | expected due to this +LL | | Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok... +LL | | Ok("") +LL | | )))))))))))))))))))))))))))))) +LL | | )))))))))))))))))))))))))))))); + | |__________________________________^ expected struct `Atype`, found enum `Result` | = note: expected struct `Atype, ...>` the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt' From 3d31e5c9810227ceb56d6d3a5228ca28b1aca890 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 25 Nov 2022 16:30:23 +0000 Subject: [PATCH 021/115] s/WithStableHash/WithCachedTypeInfo/ --- compiler/rustc_data_structures/src/intern.rs | 20 ++++++------- compiler/rustc_middle/src/arena.rs | 4 +-- compiler/rustc_middle/src/ty/context.rs | 30 ++++++++++---------- compiler/rustc_middle/src/ty/mod.rs | 29 ++++++++++--------- compiler/rustc_middle/src/ty/subst.rs | 6 ++-- 5 files changed, 45 insertions(+), 44 deletions(-) diff --git a/compiler/rustc_data_structures/src/intern.rs b/compiler/rustc_data_structures/src/intern.rs index 11cbff8ea6a8..9985aeaab57d 100644 --- a/compiler/rustc_data_structures/src/intern.rs +++ b/compiler/rustc_data_structures/src/intern.rs @@ -118,33 +118,33 @@ where /// This is useful if you have values that you intern but never (can?) use for stable /// hashing. #[derive(Copy, Clone)] -pub struct WithStableHash { +pub struct WithCachedTypeInfo { pub internee: T, pub stable_hash: Fingerprint, } -impl PartialEq for WithStableHash { +impl PartialEq for WithCachedTypeInfo { #[inline] fn eq(&self, other: &Self) -> bool { self.internee.eq(&other.internee) } } -impl Eq for WithStableHash {} +impl Eq for WithCachedTypeInfo {} -impl PartialOrd for WithStableHash { - fn partial_cmp(&self, other: &WithStableHash) -> Option { +impl PartialOrd for WithCachedTypeInfo { + fn partial_cmp(&self, other: &WithCachedTypeInfo) -> Option { Some(self.internee.cmp(&other.internee)) } } -impl Ord for WithStableHash { - fn cmp(&self, other: &WithStableHash) -> Ordering { +impl Ord for WithCachedTypeInfo { + fn cmp(&self, other: &WithCachedTypeInfo) -> Ordering { self.internee.cmp(&other.internee) } } -impl Deref for WithStableHash { +impl Deref for WithCachedTypeInfo { type Target = T; #[inline] @@ -153,7 +153,7 @@ impl Deref for WithStableHash { } } -impl Hash for WithStableHash { +impl Hash for WithCachedTypeInfo { #[inline] fn hash(&self, s: &mut H) { if self.stable_hash != Fingerprint::ZERO { @@ -164,7 +164,7 @@ impl Hash for WithStableHash { } } -impl, CTX> HashStable for WithStableHash { +impl, CTX> HashStable for WithCachedTypeInfo { fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { if self.stable_hash == Fingerprint::ZERO || cfg!(debug_assertions) { // No cached hash available. This can only mean that incremental is disabled. diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index e83106b1ee51..3f3d92d68e33 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -88,8 +88,8 @@ macro_rules! arena_types { [] hir_id_set: rustc_hir::HirIdSet, // Interned types - [] tys: rustc_data_structures::intern::WithStableHash>, - [] predicates: rustc_data_structures::intern::WithStableHash>, + [] tys: rustc_data_structures::intern::WithCachedTypeInfo>, + [] predicates: rustc_data_structures::intern::WithCachedTypeInfo>, [] consts: rustc_middle::ty::ConstS<'tcx>, // Note that this deliberately duplicates items in the `rustc_hir::arena`, diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index a1acca3097d8..3af3444b86c3 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -27,7 +27,7 @@ use crate::ty::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef, UserSubst use rustc_ast as ast; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_data_structures::intern::{Interned, WithStableHash}; +use rustc_data_structures::intern::{Interned, WithCachedTypeInfo}; use rustc_data_structures::memmap::Mmap; use rustc_data_structures::profiling::SelfProfilerRef; use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap}; @@ -136,13 +136,13 @@ pub struct CtxtInterners<'tcx> { // Specifically use a speedy hash algorithm for these hash sets, since // they're accessed quite often. - type_: InternedSet<'tcx, WithStableHash>>, + type_: InternedSet<'tcx, WithCachedTypeInfo>>, const_lists: InternedSet<'tcx, List>>, substs: InternedSet<'tcx, InternalSubsts<'tcx>>, canonical_var_infos: InternedSet<'tcx, List>>, region: InternedSet<'tcx, RegionKind<'tcx>>, poly_existential_predicates: InternedSet<'tcx, List>>, - predicate: InternedSet<'tcx, WithStableHash>>, + predicate: InternedSet<'tcx, WithCachedTypeInfo>>, predicates: InternedSet<'tcx, List>>, projs: InternedSet<'tcx, List>, place_elems: InternedSet<'tcx, List>>, @@ -200,7 +200,7 @@ impl<'tcx> CtxtInterners<'tcx> { }; InternedInSet( - self.arena.alloc(WithStableHash { internee: ty_struct, stable_hash }), + self.arena.alloc(WithCachedTypeInfo { internee: ty_struct, stable_hash }), ) }) .0, @@ -253,7 +253,7 @@ impl<'tcx> CtxtInterners<'tcx> { InternedInSet( self.arena - .alloc(WithStableHash { internee: predicate_struct, stable_hash }), + .alloc(WithCachedTypeInfo { internee: predicate_struct, stable_hash }), ) }) .0, @@ -2167,23 +2167,23 @@ impl<'tcx, T: 'tcx + ?Sized> IntoPointer for InternedInSet<'tcx, T> { } #[allow(rustc::usage_of_ty_tykind)] -impl<'tcx> Borrow> for InternedInSet<'tcx, WithStableHash>> { +impl<'tcx> Borrow> for InternedInSet<'tcx, WithCachedTypeInfo>> { fn borrow<'a>(&'a self) -> &'a TyKind<'tcx> { &self.0.kind } } -impl<'tcx> PartialEq for InternedInSet<'tcx, WithStableHash>> { - fn eq(&self, other: &InternedInSet<'tcx, WithStableHash>>) -> bool { +impl<'tcx> PartialEq for InternedInSet<'tcx, WithCachedTypeInfo>> { + fn eq(&self, other: &InternedInSet<'tcx, WithCachedTypeInfo>>) -> bool { // The `Borrow` trait requires that `x.borrow() == y.borrow()` equals // `x == y`. self.0.kind == other.0.kind } } -impl<'tcx> Eq for InternedInSet<'tcx, WithStableHash>> {} +impl<'tcx> Eq for InternedInSet<'tcx, WithCachedTypeInfo>> {} -impl<'tcx> Hash for InternedInSet<'tcx, WithStableHash>> { +impl<'tcx> Hash for InternedInSet<'tcx, WithCachedTypeInfo>> { fn hash(&self, s: &mut H) { // The `Borrow` trait requires that `x.borrow().hash(s) == x.hash(s)`. self.0.kind.hash(s) @@ -2191,24 +2191,24 @@ impl<'tcx> Hash for InternedInSet<'tcx, WithStableHash>> { } impl<'tcx> Borrow>> - for InternedInSet<'tcx, WithStableHash>> + for InternedInSet<'tcx, WithCachedTypeInfo>> { fn borrow<'a>(&'a self) -> &'a Binder<'tcx, PredicateKind<'tcx>> { &self.0.kind } } -impl<'tcx> PartialEq for InternedInSet<'tcx, WithStableHash>> { - fn eq(&self, other: &InternedInSet<'tcx, WithStableHash>>) -> bool { +impl<'tcx> PartialEq for InternedInSet<'tcx, WithCachedTypeInfo>> { + fn eq(&self, other: &InternedInSet<'tcx, WithCachedTypeInfo>>) -> bool { // The `Borrow` trait requires that `x.borrow() == y.borrow()` equals // `x == y`. self.0.kind == other.0.kind } } -impl<'tcx> Eq for InternedInSet<'tcx, WithStableHash>> {} +impl<'tcx> Eq for InternedInSet<'tcx, WithCachedTypeInfo>> {} -impl<'tcx> Hash for InternedInSet<'tcx, WithStableHash>> { +impl<'tcx> Hash for InternedInSet<'tcx, WithCachedTypeInfo>> { fn hash(&self, s: &mut H) { // The `Borrow` trait requires that `x.borrow().hash(s) == x.hash(s)`. self.0.kind.hash(s) diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index dd4ab3e8d30b..d3cbd2e03cfb 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -32,7 +32,7 @@ use rustc_ast::node_id::NodeMap; use rustc_attr as attr; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet}; -use rustc_data_structures::intern::{Interned, WithStableHash}; +use rustc_data_structures::intern::{Interned, WithCachedTypeInfo}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::tagged_ptr::CopyTaggedPtr; use rustc_hir as hir; @@ -495,19 +495,20 @@ pub(crate) struct TyS<'tcx> { #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)] #[rustc_diagnostic_item = "Ty"] #[rustc_pass_by_value] -pub struct Ty<'tcx>(Interned<'tcx, WithStableHash>>); +pub struct Ty<'tcx>(Interned<'tcx, WithCachedTypeInfo>>); impl<'tcx> TyCtxt<'tcx> { /// A "bool" type used in rustc_mir_transform unit tests when we /// have not spun up a TyCtxt. - pub const BOOL_TY_FOR_UNIT_TESTING: Ty<'tcx> = Ty(Interned::new_unchecked(&WithStableHash { - internee: TyS { - kind: ty::Bool, - flags: TypeFlags::empty(), - outer_exclusive_binder: DebruijnIndex::from_usize(0), - }, - stable_hash: Fingerprint::ZERO, - })); + pub const BOOL_TY_FOR_UNIT_TESTING: Ty<'tcx> = + Ty(Interned::new_unchecked(&WithCachedTypeInfo { + internee: TyS { + kind: ty::Bool, + flags: TypeFlags::empty(), + outer_exclusive_binder: DebruijnIndex::from_usize(0), + }, + stable_hash: Fingerprint::ZERO, + })); } impl<'a, 'tcx> HashStable> for TyS<'tcx> { @@ -550,7 +551,7 @@ pub(crate) struct PredicateS<'tcx> { /// Use this rather than `PredicateS`, whenever possible. #[derive(Clone, Copy, PartialEq, Eq, Hash, HashStable)] #[rustc_pass_by_value] -pub struct Predicate<'tcx>(Interned<'tcx, WithStableHash>>); +pub struct Predicate<'tcx>(Interned<'tcx, WithCachedTypeInfo>>); impl<'tcx> Predicate<'tcx> { /// Gets the inner `Binder<'tcx, PredicateKind<'tcx>>`. @@ -1028,7 +1029,7 @@ impl<'tcx> Term<'tcx> { unsafe { match ptr & TAG_MASK { TYPE_TAG => TermKind::Ty(Ty(Interned::new_unchecked( - &*((ptr & !TAG_MASK) as *const WithStableHash>), + &*((ptr & !TAG_MASK) as *const WithCachedTypeInfo>), ))), CONST_TAG => TermKind::Const(ty::Const(Interned::new_unchecked( &*((ptr & !TAG_MASK) as *const ty::ConstS<'tcx>), @@ -1072,7 +1073,7 @@ impl<'tcx> TermKind<'tcx> { TermKind::Ty(ty) => { // Ensure we can use the tag bits. assert_eq!(mem::align_of_val(&*ty.0.0) & TAG_MASK, 0); - (TYPE_TAG, ty.0.0 as *const WithStableHash> as usize) + (TYPE_TAG, ty.0.0 as *const WithCachedTypeInfo> as usize) } TermKind::Const(ct) => { // Ensure we can use the tag bits. @@ -2694,6 +2695,6 @@ mod size_asserts { // tidy-alphabetical-start static_assert_size!(PredicateS<'_>, 48); static_assert_size!(TyS<'_>, 40); - static_assert_size!(WithStableHash>, 56); + static_assert_size!(WithCachedTypeInfo>, 56); // tidy-alphabetical-end } diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs index 141c8354c183..f69035f619ff 100644 --- a/compiler/rustc_middle/src/ty/subst.rs +++ b/compiler/rustc_middle/src/ty/subst.rs @@ -6,7 +6,7 @@ use crate::ty::sty::{ClosureSubsts, GeneratorSubsts, InlineConstSubsts}; use crate::ty::visit::{TypeVisitable, TypeVisitor}; use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt}; -use rustc_data_structures::intern::{Interned, WithStableHash}; +use rustc_data_structures::intern::{Interned, WithCachedTypeInfo}; use rustc_hir::def_id::DefId; use rustc_macros::HashStable; use rustc_serialize::{self, Decodable, Encodable}; @@ -84,7 +84,7 @@ impl<'tcx> GenericArgKind<'tcx> { GenericArgKind::Type(ty) => { // Ensure we can use the tag bits. assert_eq!(mem::align_of_val(&*ty.0.0) & TAG_MASK, 0); - (TYPE_TAG, ty.0.0 as *const WithStableHash> as usize) + (TYPE_TAG, ty.0.0 as *const WithCachedTypeInfo> as usize) } GenericArgKind::Const(ct) => { // Ensure we can use the tag bits. @@ -162,7 +162,7 @@ impl<'tcx> GenericArg<'tcx> { &*((ptr & !TAG_MASK) as *const ty::RegionKind<'tcx>), ))), TYPE_TAG => GenericArgKind::Type(Ty(Interned::new_unchecked( - &*((ptr & !TAG_MASK) as *const WithStableHash>), + &*((ptr & !TAG_MASK) as *const WithCachedTypeInfo>), ))), CONST_TAG => GenericArgKind::Const(ty::Const(Interned::new_unchecked( &*((ptr & !TAG_MASK) as *const ty::ConstS<'tcx>), From 87a04f51ba4ccf9f6b44897713edaa7c68dc580a Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 25 Nov 2022 16:38:16 +0000 Subject: [PATCH 022/115] move WithCachedTypeInfo to rustc_type_ir --- compiler/rustc_data_structures/src/intern.rs | 83 ------------------ compiler/rustc_middle/src/arena.rs | 4 +- compiler/rustc_middle/src/ty/context.rs | 3 +- compiler/rustc_middle/src/ty/mod.rs | 3 +- compiler/rustc_middle/src/ty/subst.rs | 3 +- compiler/rustc_type_ir/src/lib.rs | 2 + compiler/rustc_type_ir/src/ty_info.rs | 91 ++++++++++++++++++++ 7 files changed, 101 insertions(+), 88 deletions(-) create mode 100644 compiler/rustc_type_ir/src/ty_info.rs diff --git a/compiler/rustc_data_structures/src/intern.rs b/compiler/rustc_data_structures/src/intern.rs index 9985aeaab57d..7a320b10b603 100644 --- a/compiler/rustc_data_structures/src/intern.rs +++ b/compiler/rustc_data_structures/src/intern.rs @@ -4,8 +4,6 @@ use std::hash::{Hash, Hasher}; use std::ops::Deref; use std::ptr; -use crate::fingerprint::Fingerprint; - mod private { #[derive(Clone, Copy, Debug)] pub struct PrivateZst; @@ -110,86 +108,5 @@ where } } -/// A helper type that you can wrap round your own type in order to automatically -/// cache the stable hash on creation and not recompute it whenever the stable hash -/// of the type is computed. -/// This is only done in incremental mode. You can also opt out of caching by using -/// StableHash::ZERO for the hash, in which case the hash gets computed each time. -/// This is useful if you have values that you intern but never (can?) use for stable -/// hashing. -#[derive(Copy, Clone)] -pub struct WithCachedTypeInfo { - pub internee: T, - pub stable_hash: Fingerprint, -} - -impl PartialEq for WithCachedTypeInfo { - #[inline] - fn eq(&self, other: &Self) -> bool { - self.internee.eq(&other.internee) - } -} - -impl Eq for WithCachedTypeInfo {} - -impl PartialOrd for WithCachedTypeInfo { - fn partial_cmp(&self, other: &WithCachedTypeInfo) -> Option { - Some(self.internee.cmp(&other.internee)) - } -} - -impl Ord for WithCachedTypeInfo { - fn cmp(&self, other: &WithCachedTypeInfo) -> Ordering { - self.internee.cmp(&other.internee) - } -} - -impl Deref for WithCachedTypeInfo { - type Target = T; - - #[inline] - fn deref(&self) -> &T { - &self.internee - } -} - -impl Hash for WithCachedTypeInfo { - #[inline] - fn hash(&self, s: &mut H) { - if self.stable_hash != Fingerprint::ZERO { - self.stable_hash.hash(s) - } else { - self.internee.hash(s) - } - } -} - -impl, CTX> HashStable for WithCachedTypeInfo { - fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { - if self.stable_hash == Fingerprint::ZERO || cfg!(debug_assertions) { - // No cached hash available. This can only mean that incremental is disabled. - // We don't cache stable hashes in non-incremental mode, because they are used - // so rarely that the performance actually suffers. - - // We need to build the hash as if we cached it and then hash that hash, as - // otherwise the hashes will differ between cached and non-cached mode. - let stable_hash: Fingerprint = { - let mut hasher = StableHasher::new(); - self.internee.hash_stable(hcx, &mut hasher); - hasher.finish() - }; - if cfg!(debug_assertions) && self.stable_hash != Fingerprint::ZERO { - assert_eq!( - stable_hash, self.stable_hash, - "cached stable hash does not match freshly computed stable hash" - ); - } - stable_hash.hash_stable(hcx, hasher); - } else { - self.stable_hash.hash_stable(hcx, hasher); - } - } -} - #[cfg(test)] mod tests; diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index 3f3d92d68e33..2cbc381a11a7 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -88,8 +88,8 @@ macro_rules! arena_types { [] hir_id_set: rustc_hir::HirIdSet, // Interned types - [] tys: rustc_data_structures::intern::WithCachedTypeInfo>, - [] predicates: rustc_data_structures::intern::WithCachedTypeInfo>, + [] tys: rustc_type_ir::WithCachedTypeInfo>, + [] predicates: rustc_type_ir::WithCachedTypeInfo>, [] consts: rustc_middle::ty::ConstS<'tcx>, // Note that this deliberately duplicates items in the `rustc_hir::arena`, diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 3af3444b86c3..e1834f1f57af 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -27,7 +27,7 @@ use crate::ty::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef, UserSubst use rustc_ast as ast; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_data_structures::intern::{Interned, WithCachedTypeInfo}; +use rustc_data_structures::intern::Interned; use rustc_data_structures::memmap::Mmap; use rustc_data_structures::profiling::SelfProfilerRef; use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap}; @@ -67,6 +67,7 @@ use rustc_span::{Span, DUMMY_SP}; use rustc_target::abi::{Layout, LayoutS, TargetDataLayout, VariantIdx}; use rustc_target::spec::abi; use rustc_type_ir::sty::TyKind::*; +use rustc_type_ir::WithCachedTypeInfo; use rustc_type_ir::{DynKind, InternAs, InternIteratorElement, Interner, TypeFlags}; use std::any::Any; diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index d3cbd2e03cfb..c56e1b6e5a0f 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -32,7 +32,7 @@ use rustc_ast::node_id::NodeMap; use rustc_attr as attr; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet}; -use rustc_data_structures::intern::{Interned, WithCachedTypeInfo}; +use rustc_data_structures::intern::Interned; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::tagged_ptr::CopyTaggedPtr; use rustc_hir as hir; @@ -50,6 +50,7 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{ExpnId, Span}; use rustc_target::abi::{Align, Integer, IntegerType, VariantIdx}; pub use rustc_target::abi::{ReprFlags, ReprOptions}; +use rustc_type_ir::WithCachedTypeInfo; pub use subst::*; pub use vtable::*; diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs index f69035f619ff..13fab0068d6a 100644 --- a/compiler/rustc_middle/src/ty/subst.rs +++ b/compiler/rustc_middle/src/ty/subst.rs @@ -6,10 +6,11 @@ use crate::ty::sty::{ClosureSubsts, GeneratorSubsts, InlineConstSubsts}; use crate::ty::visit::{TypeVisitable, TypeVisitor}; use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt}; -use rustc_data_structures::intern::{Interned, WithCachedTypeInfo}; +use rustc_data_structures::intern::Interned; use rustc_hir::def_id::DefId; use rustc_macros::HashStable; use rustc_serialize::{self, Decodable, Encodable}; +use rustc_type_ir::WithCachedTypeInfo; use smallvec::SmallVec; use core::intrinsics; diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index 581993ba7d86..e3f7a1bd033c 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -19,9 +19,11 @@ use std::mem::discriminant; pub mod codec; pub mod sty; +pub mod ty_info; pub use codec::*; pub use sty::*; +pub use ty_info::*; /// Needed so we can use #[derive(HashStable_Generic)] pub trait HashStableContext {} diff --git a/compiler/rustc_type_ir/src/ty_info.rs b/compiler/rustc_type_ir/src/ty_info.rs new file mode 100644 index 000000000000..815237a06c06 --- /dev/null +++ b/compiler/rustc_type_ir/src/ty_info.rs @@ -0,0 +1,91 @@ +use std::{ + cmp::Ordering, + hash::{Hash, Hasher}, + ops::Deref, +}; + +use rustc_data_structures::{ + fingerprint::Fingerprint, + stable_hasher::{HashStable, StableHasher}, +}; + +/// A helper type that you can wrap round your own type in order to automatically +/// cache the stable hash on creation and not recompute it whenever the stable hash +/// of the type is computed. +/// This is only done in incremental mode. You can also opt out of caching by using +/// StableHash::ZERO for the hash, in which case the hash gets computed each time. +/// This is useful if you have values that you intern but never (can?) use for stable +/// hashing. +#[derive(Copy, Clone)] +pub struct WithCachedTypeInfo { + pub internee: T, + pub stable_hash: Fingerprint, +} + +impl PartialEq for WithCachedTypeInfo { + #[inline] + fn eq(&self, other: &Self) -> bool { + self.internee.eq(&other.internee) + } +} + +impl Eq for WithCachedTypeInfo {} + +impl PartialOrd for WithCachedTypeInfo { + fn partial_cmp(&self, other: &WithCachedTypeInfo) -> Option { + Some(self.internee.cmp(&other.internee)) + } +} + +impl Ord for WithCachedTypeInfo { + fn cmp(&self, other: &WithCachedTypeInfo) -> Ordering { + self.internee.cmp(&other.internee) + } +} + +impl Deref for WithCachedTypeInfo { + type Target = T; + + #[inline] + fn deref(&self) -> &T { + &self.internee + } +} + +impl Hash for WithCachedTypeInfo { + #[inline] + fn hash(&self, s: &mut H) { + if self.stable_hash != Fingerprint::ZERO { + self.stable_hash.hash(s) + } else { + self.internee.hash(s) + } + } +} + +impl, CTX> HashStable for WithCachedTypeInfo { + fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { + if self.stable_hash == Fingerprint::ZERO || cfg!(debug_assertions) { + // No cached hash available. This can only mean that incremental is disabled. + // We don't cache stable hashes in non-incremental mode, because they are used + // so rarely that the performance actually suffers. + + // We need to build the hash as if we cached it and then hash that hash, as + // otherwise the hashes will differ between cached and non-cached mode. + let stable_hash: Fingerprint = { + let mut hasher = StableHasher::new(); + self.internee.hash_stable(hcx, &mut hasher); + hasher.finish() + }; + if cfg!(debug_assertions) && self.stable_hash != Fingerprint::ZERO { + assert_eq!( + stable_hash, self.stable_hash, + "cached stable hash does not match freshly computed stable hash" + ); + } + stable_hash.hash_stable(hcx, hasher); + } else { + self.stable_hash.hash_stable(hcx, hasher); + } + } +} From 147b854dede7b0dda933e24f6ee6c8dd30323a7e Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 25 Nov 2022 16:55:25 +0000 Subject: [PATCH 023/115] Remove TyS --- compiler/rustc_middle/src/arena.rs | 4 +- compiler/rustc_middle/src/ty/context.rs | 35 +++++------ compiler/rustc_middle/src/ty/mod.rs | 82 +++---------------------- compiler/rustc_middle/src/ty/sty.rs | 2 +- compiler/rustc_middle/src/ty/subst.rs | 4 +- compiler/rustc_type_ir/src/ty_info.rs | 35 ++++++++++- 6 files changed, 65 insertions(+), 97 deletions(-) diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index 2cbc381a11a7..3a0ddae1c63f 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -1,3 +1,5 @@ +#![allow(rustc::usage_of_ty_tykind)] + /// This higher-order macro declares a list of types which can be allocated by `Arena`. /// /// Specifying the `decode` modifier will add decode impls for `&T` and `&[T]` where `T` is the type @@ -88,7 +90,7 @@ macro_rules! arena_types { [] hir_id_set: rustc_hir::HirIdSet, // Interned types - [] tys: rustc_type_ir::WithCachedTypeInfo>, + [] tys: rustc_type_ir::WithCachedTypeInfo>, [] predicates: rustc_type_ir::WithCachedTypeInfo>, [] consts: rustc_middle::ty::ConstS<'tcx>, diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index e1834f1f57af..f798c0a4e229 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1,5 +1,7 @@ //! Type context book-keeping. +#![allow(rustc::usage_of_ty_tykind)] + use crate::arena::Arena; use crate::dep_graph::{DepGraph, DepKindStruct}; use crate::hir::place::Place as HirPlace; @@ -20,7 +22,7 @@ use crate::ty::{ ClosureSizeProfileData, Const, ConstS, DefIdTree, FloatTy, FloatVar, FloatVid, GenericParamDefKind, InferTy, IntTy, IntVar, IntVid, List, ParamConst, ParamTy, PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, PredicateS, ProjectionTy, - Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyS, TyVar, TyVid, TypeAndMut, + Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVar, TyVid, TypeAndMut, UintTy, Visibility, }; use crate::ty::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef, UserSubsts}; @@ -137,7 +139,7 @@ pub struct CtxtInterners<'tcx> { // Specifically use a speedy hash algorithm for these hash sets, since // they're accessed quite often. - type_: InternedSet<'tcx, WithCachedTypeInfo>>, + type_: InternedSet<'tcx, WithCachedTypeInfo>>, const_lists: InternedSet<'tcx, List>>, substs: InternedSet<'tcx, InternalSubsts<'tcx>>, canonical_var_infos: InternedSet<'tcx, List>>, @@ -194,15 +196,12 @@ impl<'tcx> CtxtInterners<'tcx> { let stable_hash = self.stable_hash(&flags, sess, definitions, cstore, source_span, &kind); - let ty_struct = TyS { - kind, + InternedInSet(self.arena.alloc(WithCachedTypeInfo { + internee: kind, + stable_hash, flags: flags.flags, outer_exclusive_binder: flags.outer_exclusive_binder, - }; - - InternedInSet( - self.arena.alloc(WithCachedTypeInfo { internee: ty_struct, stable_hash }), - ) + })) }) .0, )) @@ -2058,7 +2057,7 @@ macro_rules! sty_debug_print { let shards = tcx.interners.type_.lock_shards(); let types = shards.iter().flat_map(|shard| shard.keys()); for &InternedInSet(t) in types { - let variant = match t.kind { + let variant = match t.internee { ty::Bool | ty::Char | ty::Int(..) | ty::Uint(..) | ty::Float(..) | ty::Str | ty::Never => continue, ty::Error(_) => /* unimportant */ continue, @@ -2168,26 +2167,26 @@ impl<'tcx, T: 'tcx + ?Sized> IntoPointer for InternedInSet<'tcx, T> { } #[allow(rustc::usage_of_ty_tykind)] -impl<'tcx> Borrow> for InternedInSet<'tcx, WithCachedTypeInfo>> { +impl<'tcx> Borrow> for InternedInSet<'tcx, WithCachedTypeInfo>> { fn borrow<'a>(&'a self) -> &'a TyKind<'tcx> { - &self.0.kind + &self.0.internee } } -impl<'tcx> PartialEq for InternedInSet<'tcx, WithCachedTypeInfo>> { - fn eq(&self, other: &InternedInSet<'tcx, WithCachedTypeInfo>>) -> bool { +impl<'tcx> PartialEq for InternedInSet<'tcx, WithCachedTypeInfo>> { + fn eq(&self, other: &InternedInSet<'tcx, WithCachedTypeInfo>>) -> bool { // The `Borrow` trait requires that `x.borrow() == y.borrow()` equals // `x == y`. - self.0.kind == other.0.kind + self.0.internee == other.0.internee } } -impl<'tcx> Eq for InternedInSet<'tcx, WithCachedTypeInfo>> {} +impl<'tcx> Eq for InternedInSet<'tcx, WithCachedTypeInfo>> {} -impl<'tcx> Hash for InternedInSet<'tcx, WithCachedTypeInfo>> { +impl<'tcx> Hash for InternedInSet<'tcx, WithCachedTypeInfo>> { fn hash(&self, s: &mut H) { // The `Borrow` trait requires that `x.borrow().hash(s) == x.hash(s)`. - self.0.kind.hash(s) + self.0.internee.hash(s) } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index c56e1b6e5a0f..667b55088ccf 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -9,6 +9,8 @@ //! //! ["The `ty` module: representing types"]: https://rustc-dev-guide.rust-lang.org/ty.html +#![allow(rustc::usage_of_ty_tykind)] + pub use self::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable}; pub use self::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}; pub use self::AssocItemContainer::*; @@ -446,89 +448,24 @@ pub struct CReaderCacheKey { pub pos: usize, } -/// Represents a type. -/// -/// IMPORTANT: -/// - This is a very "dumb" struct (with no derives and no `impls`). -/// - Values of this type are always interned and thus unique, and are stored -/// as an `Interned`. -/// - `Ty` (which contains a reference to a `Interned`) or `Interned` -/// should be used everywhere instead of `TyS`. In particular, `Ty` has most -/// of the relevant methods. -#[derive(PartialEq, Eq, PartialOrd, Ord)] -#[allow(rustc::usage_of_ty_tykind)] -pub(crate) struct TyS<'tcx> { - /// This field shouldn't be used directly and may be removed in the future. - /// Use `Ty::kind()` instead. - kind: TyKind<'tcx>, - - /// This field provides fast access to information that is also contained - /// in `kind`. - /// - /// This field shouldn't be used directly and may be removed in the future. - /// Use `Ty::flags()` instead. - flags: TypeFlags, - - /// This field provides fast access to information that is also contained - /// in `kind`. - /// - /// This is a kind of confusing thing: it stores the smallest - /// binder such that - /// - /// (a) the binder itself captures nothing but - /// (b) all the late-bound things within the type are captured - /// by some sub-binder. - /// - /// So, for a type without any late-bound things, like `u32`, this - /// will be *innermost*, because that is the innermost binder that - /// captures nothing. But for a type `&'D u32`, where `'D` is a - /// late-bound region with De Bruijn index `D`, this would be `D + 1` - /// -- the binder itself does not capture `D`, but `D` is captured - /// by an inner binder. - /// - /// We call this concept an "exclusive" binder `D` because all - /// De Bruijn indices within the type are contained within `0..D` - /// (exclusive). - outer_exclusive_binder: ty::DebruijnIndex, -} - /// Use this rather than `TyS`, whenever possible. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)] #[rustc_diagnostic_item = "Ty"] #[rustc_pass_by_value] -pub struct Ty<'tcx>(Interned<'tcx, WithCachedTypeInfo>>); +pub struct Ty<'tcx>(Interned<'tcx, WithCachedTypeInfo>>); impl<'tcx> TyCtxt<'tcx> { /// A "bool" type used in rustc_mir_transform unit tests when we /// have not spun up a TyCtxt. pub const BOOL_TY_FOR_UNIT_TESTING: Ty<'tcx> = Ty(Interned::new_unchecked(&WithCachedTypeInfo { - internee: TyS { - kind: ty::Bool, - flags: TypeFlags::empty(), - outer_exclusive_binder: DebruijnIndex::from_usize(0), - }, + internee: ty::Bool, stable_hash: Fingerprint::ZERO, + flags: TypeFlags::empty(), + outer_exclusive_binder: DebruijnIndex::from_usize(0), })); } -impl<'a, 'tcx> HashStable> for TyS<'tcx> { - #[inline] - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - let TyS { - kind, - - // The other fields just provide fast access to information that is - // also contained in `kind`, so no need to hash them. - flags: _, - - outer_exclusive_binder: _, - } = self; - - kind.hash_stable(hcx, hasher) - } -} - impl ty::EarlyBoundRegion { /// Does this early bound region have a name? Early bound regions normally /// always have names except when using anonymous lifetimes (`'_`). @@ -1030,7 +967,7 @@ impl<'tcx> Term<'tcx> { unsafe { match ptr & TAG_MASK { TYPE_TAG => TermKind::Ty(Ty(Interned::new_unchecked( - &*((ptr & !TAG_MASK) as *const WithCachedTypeInfo>), + &*((ptr & !TAG_MASK) as *const WithCachedTypeInfo>), ))), CONST_TAG => TermKind::Const(ty::Const(Interned::new_unchecked( &*((ptr & !TAG_MASK) as *const ty::ConstS<'tcx>), @@ -1074,7 +1011,7 @@ impl<'tcx> TermKind<'tcx> { TermKind::Ty(ty) => { // Ensure we can use the tag bits. assert_eq!(mem::align_of_val(&*ty.0.0) & TAG_MASK, 0); - (TYPE_TAG, ty.0.0 as *const WithCachedTypeInfo> as usize) + (TYPE_TAG, ty.0.0 as *const WithCachedTypeInfo> as usize) } TermKind::Const(ct) => { // Ensure we can use the tag bits. @@ -2695,7 +2632,6 @@ mod size_asserts { use rustc_data_structures::static_assert_size; // tidy-alphabetical-start static_assert_size!(PredicateS<'_>, 48); - static_assert_size!(TyS<'_>, 40); - static_assert_size!(WithCachedTypeInfo>, 56); + static_assert_size!(WithCachedTypeInfo>, 56); // tidy-alphabetical-end } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 5984686044b7..a90f4f91377f 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1602,7 +1602,7 @@ impl<'tcx> Region<'tcx> { impl<'tcx> Ty<'tcx> { #[inline(always)] pub fn kind(self) -> &'tcx TyKind<'tcx> { - &self.0.0.kind + &self.0.0 } #[inline(always)] diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs index 13fab0068d6a..89901d1575ae 100644 --- a/compiler/rustc_middle/src/ty/subst.rs +++ b/compiler/rustc_middle/src/ty/subst.rs @@ -85,7 +85,7 @@ impl<'tcx> GenericArgKind<'tcx> { GenericArgKind::Type(ty) => { // Ensure we can use the tag bits. assert_eq!(mem::align_of_val(&*ty.0.0) & TAG_MASK, 0); - (TYPE_TAG, ty.0.0 as *const WithCachedTypeInfo> as usize) + (TYPE_TAG, ty.0.0 as *const WithCachedTypeInfo> as usize) } GenericArgKind::Const(ct) => { // Ensure we can use the tag bits. @@ -163,7 +163,7 @@ impl<'tcx> GenericArg<'tcx> { &*((ptr & !TAG_MASK) as *const ty::RegionKind<'tcx>), ))), TYPE_TAG => GenericArgKind::Type(Ty(Interned::new_unchecked( - &*((ptr & !TAG_MASK) as *const WithCachedTypeInfo>), + &*((ptr & !TAG_MASK) as *const WithCachedTypeInfo>), ))), CONST_TAG => GenericArgKind::Const(ty::Const(Interned::new_unchecked( &*((ptr & !TAG_MASK) as *const ty::ConstS<'tcx>), diff --git a/compiler/rustc_type_ir/src/ty_info.rs b/compiler/rustc_type_ir/src/ty_info.rs index 815237a06c06..4e5d424886ad 100644 --- a/compiler/rustc_type_ir/src/ty_info.rs +++ b/compiler/rustc_type_ir/src/ty_info.rs @@ -9,9 +9,11 @@ use rustc_data_structures::{ stable_hasher::{HashStable, StableHasher}, }; +use crate::{DebruijnIndex, TypeFlags}; + /// A helper type that you can wrap round your own type in order to automatically -/// cache the stable hash on creation and not recompute it whenever the stable hash -/// of the type is computed. +/// cache the stable hash, type flags and debruijn index on creation and +/// not recompute it whenever the information is needed. /// This is only done in incremental mode. You can also opt out of caching by using /// StableHash::ZERO for the hash, in which case the hash gets computed each time. /// This is useful if you have values that you intern but never (can?) use for stable @@ -20,6 +22,35 @@ use rustc_data_structures::{ pub struct WithCachedTypeInfo { pub internee: T, pub stable_hash: Fingerprint, + + /// This field provides fast access to information that is also contained + /// in `kind`. + /// + /// This field shouldn't be used directly and may be removed in the future. + /// Use `Ty::flags()` instead. + pub flags: TypeFlags, + + /// This field provides fast access to information that is also contained + /// in `kind`. + /// + /// This is a kind of confusing thing: it stores the smallest + /// binder such that + /// + /// (a) the binder itself captures nothing but + /// (b) all the late-bound things within the type are captured + /// by some sub-binder. + /// + /// So, for a type without any late-bound things, like `u32`, this + /// will be *innermost*, because that is the innermost binder that + /// captures nothing. But for a type `&'D u32`, where `'D` is a + /// late-bound region with De Bruijn index `D`, this would be `D + 1` + /// -- the binder itself does not capture `D`, but `D` is captured + /// by an inner binder. + /// + /// We call this concept an "exclusive" binder `D` because all + /// De Bruijn indices within the type are contained within `0..D` + /// (exclusive). + pub outer_exclusive_binder: DebruijnIndex, } impl PartialEq for WithCachedTypeInfo { From 46ba1545b89020486fb9da460e9f3b7b60e83c40 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 28 Nov 2022 14:23:49 +0000 Subject: [PATCH 024/115] Update documentation --- compiler/rustc_lint/src/pass_by_value.rs | 2 +- compiler/rustc_middle/src/mir/interpret/allocation.rs | 2 +- compiler/rustc_middle/src/ty/mod.rs | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_lint/src/pass_by_value.rs b/compiler/rustc_lint/src/pass_by_value.rs index cf1d82f4c06e..0fa81b7e4e0b 100644 --- a/compiler/rustc_lint/src/pass_by_value.rs +++ b/compiler/rustc_lint/src/pass_by_value.rs @@ -10,7 +10,7 @@ declare_tool_lint! { /// The `rustc_pass_by_value` lint marks a type with `#[rustc_pass_by_value]` requiring it to /// always be passed by value. This is usually used for types that are thin wrappers around /// references, so there is no benefit to an extra layer of indirection. (Example: `Ty` which - /// is a reference to an `Interned`) + /// is a reference to an `Interned`) pub rustc::PASS_BY_VALUE, Warn, "pass by reference of a type flagged as `#[rustc_pass_by_value]`", diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index 5f911d5884a3..221105ac48f7 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -103,7 +103,7 @@ impl hash::Hash for Allocation { /// Interned types generally have an `Outer` type and an `Inner` type, where /// `Outer` is a newtype around `Interned`, and all the operations are /// done on `Outer`, because all occurrences are interned. E.g. `Ty` is an -/// outer type and `TyS` is its inner type. +/// outer type and `TyKind` is its inner type. /// /// Here things are different because only const allocations are interned. This /// means that both the inner type (`Allocation`) and the outer type diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 667b55088ccf..756c0c583adc 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -448,7 +448,7 @@ pub struct CReaderCacheKey { pub pos: usize, } -/// Use this rather than `TyS`, whenever possible. +/// Use this rather than `TyKind`, whenever possible. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)] #[rustc_diagnostic_item = "Ty"] #[rustc_pass_by_value] @@ -476,13 +476,13 @@ impl ty::EarlyBoundRegion { /// Represents a predicate. /// -/// See comments on `TyS`, which apply here too (albeit for -/// `PredicateS`/`Predicate` rather than `TyS`/`Ty`). +/// See comments on `WithCachedTypeInfo`, which apply here too (albeit for +/// `PredicateS`/`Predicate` rather than `TyKind`/`Ty`). #[derive(Debug)] pub(crate) struct PredicateS<'tcx> { kind: Binder<'tcx, PredicateKind<'tcx>>, flags: TypeFlags, - /// See the comment for the corresponding field of [TyS]. + /// See the comment for the corresponding field of [WithCachedTypeInfo]. outer_exclusive_binder: ty::DebruijnIndex, } From 907ef227ef22bed182100641564a223a23dcba62 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 30 Nov 2022 14:47:40 +0000 Subject: [PATCH 025/115] Remove PredicateS type --- compiler/rustc_middle/src/arena.rs | 2 +- compiler/rustc_middle/src/ty/context.rs | 41 +++++++++++++------------ compiler/rustc_middle/src/ty/mod.rs | 37 ++++------------------ 3 files changed, 28 insertions(+), 52 deletions(-) diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index 3a0ddae1c63f..f8063dd238b2 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -91,7 +91,7 @@ macro_rules! arena_types { // Interned types [] tys: rustc_type_ir::WithCachedTypeInfo>, - [] predicates: rustc_type_ir::WithCachedTypeInfo>, + [] predicates: rustc_type_ir::WithCachedTypeInfo>, [] consts: rustc_middle::ty::ConstS<'tcx>, // Note that this deliberately duplicates items in the `rustc_hir::arena`, diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index f798c0a4e229..850b25473d64 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -21,9 +21,9 @@ use crate::ty::{ self, AdtDef, AdtDefData, AdtKind, Binder, BindingMode, BoundVar, CanonicalPolyFnSig, ClosureSizeProfileData, Const, ConstS, DefIdTree, FloatTy, FloatVar, FloatVid, GenericParamDefKind, InferTy, IntTy, IntVar, IntVid, List, ParamConst, ParamTy, - PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, PredicateS, ProjectionTy, - Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVar, TyVid, TypeAndMut, - UintTy, Visibility, + PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, ProjectionTy, Region, + RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVar, TyVid, TypeAndMut, UintTy, + Visibility, }; use crate::ty::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef, UserSubsts}; use rustc_ast as ast; @@ -145,7 +145,7 @@ pub struct CtxtInterners<'tcx> { canonical_var_infos: InternedSet<'tcx, List>>, region: InternedSet<'tcx, RegionKind<'tcx>>, poly_existential_predicates: InternedSet<'tcx, List>>, - predicate: InternedSet<'tcx, WithCachedTypeInfo>>, + predicate: InternedSet<'tcx, WithCachedTypeInfo>>>, predicates: InternedSet<'tcx, List>>, projs: InternedSet<'tcx, List>, place_elems: InternedSet<'tcx, List>>, @@ -245,16 +245,12 @@ impl<'tcx> CtxtInterners<'tcx> { let stable_hash = self.stable_hash(&flags, sess, definitions, cstore, source_span, &kind); - let predicate_struct = PredicateS { - kind, + InternedInSet(self.arena.alloc(WithCachedTypeInfo { + internee: kind, + stable_hash, flags: flags.flags, outer_exclusive_binder: flags.outer_exclusive_binder, - }; - - InternedInSet( - self.arena - .alloc(WithCachedTypeInfo { internee: predicate_struct, stable_hash }), - ) + })) }) .0, )) @@ -2191,27 +2187,32 @@ impl<'tcx> Hash for InternedInSet<'tcx, WithCachedTypeInfo>> { } impl<'tcx> Borrow>> - for InternedInSet<'tcx, WithCachedTypeInfo>> + for InternedInSet<'tcx, WithCachedTypeInfo>>> { fn borrow<'a>(&'a self) -> &'a Binder<'tcx, PredicateKind<'tcx>> { - &self.0.kind + &self.0.internee } } -impl<'tcx> PartialEq for InternedInSet<'tcx, WithCachedTypeInfo>> { - fn eq(&self, other: &InternedInSet<'tcx, WithCachedTypeInfo>>) -> bool { +impl<'tcx> PartialEq + for InternedInSet<'tcx, WithCachedTypeInfo>>> +{ + fn eq( + &self, + other: &InternedInSet<'tcx, WithCachedTypeInfo>>>, + ) -> bool { // The `Borrow` trait requires that `x.borrow() == y.borrow()` equals // `x == y`. - self.0.kind == other.0.kind + self.0.internee == other.0.internee } } -impl<'tcx> Eq for InternedInSet<'tcx, WithCachedTypeInfo>> {} +impl<'tcx> Eq for InternedInSet<'tcx, WithCachedTypeInfo>>> {} -impl<'tcx> Hash for InternedInSet<'tcx, WithCachedTypeInfo>> { +impl<'tcx> Hash for InternedInSet<'tcx, WithCachedTypeInfo>>> { fn hash(&self, s: &mut H) { // The `Borrow` trait requires that `x.borrow().hash(s) == x.hash(s)`. - self.0.kind.hash(s) + self.0.internee.hash(s) } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 756c0c583adc..4b4b5126719e 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -474,28 +474,18 @@ impl ty::EarlyBoundRegion { } } -/// Represents a predicate. -/// -/// See comments on `WithCachedTypeInfo`, which apply here too (albeit for -/// `PredicateS`/`Predicate` rather than `TyKind`/`Ty`). -#[derive(Debug)] -pub(crate) struct PredicateS<'tcx> { - kind: Binder<'tcx, PredicateKind<'tcx>>, - flags: TypeFlags, - /// See the comment for the corresponding field of [WithCachedTypeInfo]. - outer_exclusive_binder: ty::DebruijnIndex, -} - -/// Use this rather than `PredicateS`, whenever possible. +/// Use this rather than `PredicateKind`, whenever possible. #[derive(Clone, Copy, PartialEq, Eq, Hash, HashStable)] #[rustc_pass_by_value] -pub struct Predicate<'tcx>(Interned<'tcx, WithCachedTypeInfo>>); +pub struct Predicate<'tcx>( + Interned<'tcx, WithCachedTypeInfo>>>, +); impl<'tcx> Predicate<'tcx> { /// Gets the inner `Binder<'tcx, PredicateKind<'tcx>>`. #[inline] pub fn kind(self) -> Binder<'tcx, PredicateKind<'tcx>> { - self.0.kind + self.0.internee } #[inline(always)] @@ -570,21 +560,6 @@ impl<'tcx> Predicate<'tcx> { } } -impl<'a, 'tcx> HashStable> for PredicateS<'tcx> { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - let PredicateS { - ref kind, - - // The other fields just provide fast access to information that is - // also contained in `kind`, so no need to hash them. - flags: _, - outer_exclusive_binder: _, - } = self; - - kind.hash_stable(hcx, hasher); - } -} - impl rustc_errors::IntoDiagnosticArg for Predicate<'_> { fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { rustc_errors::DiagnosticArgValue::Str(std::borrow::Cow::Owned(self.to_string())) @@ -2631,7 +2606,7 @@ mod size_asserts { use super::*; use rustc_data_structures::static_assert_size; // tidy-alphabetical-start - static_assert_size!(PredicateS<'_>, 48); + static_assert_size!(PredicateKind<'_>, 32); static_assert_size!(WithCachedTypeInfo>, 56); // tidy-alphabetical-end } From 14a9cf2ba2178f6f776ca22bd45a83bdf27b39cd Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 30 Nov 2022 14:52:05 +0000 Subject: [PATCH 026/115] Generalize some InternedInSet impls --- compiler/rustc_middle/src/ty/context.rs | 42 ++++--------------------- 1 file changed, 6 insertions(+), 36 deletions(-) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 850b25473d64..89d4ad31d1ec 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -2163,53 +2163,23 @@ impl<'tcx, T: 'tcx + ?Sized> IntoPointer for InternedInSet<'tcx, T> { } #[allow(rustc::usage_of_ty_tykind)] -impl<'tcx> Borrow> for InternedInSet<'tcx, WithCachedTypeInfo>> { - fn borrow<'a>(&'a self) -> &'a TyKind<'tcx> { +impl<'tcx, T> Borrow for InternedInSet<'tcx, WithCachedTypeInfo> { + fn borrow<'a>(&'a self) -> &'a T { &self.0.internee } } -impl<'tcx> PartialEq for InternedInSet<'tcx, WithCachedTypeInfo>> { - fn eq(&self, other: &InternedInSet<'tcx, WithCachedTypeInfo>>) -> bool { +impl<'tcx, T: PartialEq> PartialEq for InternedInSet<'tcx, WithCachedTypeInfo> { + fn eq(&self, other: &InternedInSet<'tcx, WithCachedTypeInfo>) -> bool { // The `Borrow` trait requires that `x.borrow() == y.borrow()` equals // `x == y`. self.0.internee == other.0.internee } } -impl<'tcx> Eq for InternedInSet<'tcx, WithCachedTypeInfo>> {} +impl<'tcx, T: Eq> Eq for InternedInSet<'tcx, WithCachedTypeInfo> {} -impl<'tcx> Hash for InternedInSet<'tcx, WithCachedTypeInfo>> { - fn hash(&self, s: &mut H) { - // The `Borrow` trait requires that `x.borrow().hash(s) == x.hash(s)`. - self.0.internee.hash(s) - } -} - -impl<'tcx> Borrow>> - for InternedInSet<'tcx, WithCachedTypeInfo>>> -{ - fn borrow<'a>(&'a self) -> &'a Binder<'tcx, PredicateKind<'tcx>> { - &self.0.internee - } -} - -impl<'tcx> PartialEq - for InternedInSet<'tcx, WithCachedTypeInfo>>> -{ - fn eq( - &self, - other: &InternedInSet<'tcx, WithCachedTypeInfo>>>, - ) -> bool { - // The `Borrow` trait requires that `x.borrow() == y.borrow()` equals - // `x == y`. - self.0.internee == other.0.internee - } -} - -impl<'tcx> Eq for InternedInSet<'tcx, WithCachedTypeInfo>>> {} - -impl<'tcx> Hash for InternedInSet<'tcx, WithCachedTypeInfo>>> { +impl<'tcx, T: Hash> Hash for InternedInSet<'tcx, WithCachedTypeInfo> { fn hash(&self, s: &mut H) { // The `Borrow` trait requires that `x.borrow().hash(s) == x.hash(s)`. self.0.internee.hash(s) From 0e24cee063e7e37d31929faaefaf5ded1732e6e1 Mon Sep 17 00:00:00 2001 From: yukang Date: Thu, 1 Dec 2022 02:21:48 +0800 Subject: [PATCH 027/115] fix #105028, Only suggest removing struct field from destructive binding in shorthand scenario --- compiler/rustc_passes/src/liveness.rs | 8 +++++++- .../ui/suggestions/try-removing-the-field.rs | 15 +++++++++++++++ .../ui/suggestions/try-removing-the-field.stderr | 16 +++++++++++++++- 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index 2234837050bd..1f65cc8b6096 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -1548,7 +1548,13 @@ impl<'tcx> Liveness<'_, 'tcx> { .or_insert_with(|| (ln, var, vec![id_and_sp])); }); - let can_remove = matches!(&pat.kind, hir::PatKind::Struct(_, _, true)); + let can_remove = match pat.kind { + hir::PatKind::Struct(_, fields, true) => { + // if all fields are shorthand, remove the struct field, otherwise, mark with _ as prefix + fields.iter().all(|f| f.is_shorthand) + } + _ => false, + }; for (_, (ln, var, hir_ids_and_spans)) in vars { if self.used_on_entry(ln, var) { diff --git a/src/test/ui/suggestions/try-removing-the-field.rs b/src/test/ui/suggestions/try-removing-the-field.rs index 9d0573ca2554..1b7289b229b5 100644 --- a/src/test/ui/suggestions/try-removing-the-field.rs +++ b/src/test/ui/suggestions/try-removing-the-field.rs @@ -14,4 +14,19 @@ fn use_foo(x: Foo) -> i32 { return foo; } +// issue #105028, suggest removing the field only for shorthand +fn use_match(x: Foo) { + match x { + Foo { foo: unused, .. } => { //~ WARNING unused variable + //~| help: if this is intentional, prefix it with an underscore + } + } + + match x { + Foo { foo, .. } => { //~ WARNING unused variable + //~| help: try removing the field + } + } +} + fn main() {} diff --git a/src/test/ui/suggestions/try-removing-the-field.stderr b/src/test/ui/suggestions/try-removing-the-field.stderr index 448a2c3d2ec2..7a6013d4a6ea 100644 --- a/src/test/ui/suggestions/try-removing-the-field.stderr +++ b/src/test/ui/suggestions/try-removing-the-field.stderr @@ -8,5 +8,19 @@ LL | let Foo { foo, bar, .. } = x; | = note: `#[warn(unused_variables)]` on by default -warning: 1 warning emitted +warning: unused variable: `unused` + --> $DIR/try-removing-the-field.rs:20:20 + | +LL | Foo { foo: unused, .. } => { + | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused` + +warning: unused variable: `foo` + --> $DIR/try-removing-the-field.rs:26:15 + | +LL | Foo { foo, .. } => { + | ^^^- + | | + | help: try removing the field + +warning: 3 warnings emitted From 427a079d318e68686cc7512838a23ed71315d8de Mon Sep 17 00:00:00 2001 From: Tomoaki Kawada Date: Thu, 1 Dec 2022 10:40:15 +0900 Subject: [PATCH 028/115] kmc-solid: Use `expose_addr` and `from_exposed_addr` for pointer-integer casts Pointer-integer casts are required for conversion between `EXINF` (ITRON task entry point parameter) and `*const ThreadInner`. Addresses the deny-level lint `fuzzy_provenance_casts`. --- library/std/src/sys/itron/thread.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/std/src/sys/itron/thread.rs b/library/std/src/sys/itron/thread.rs index d28f57f33be2..573a50b42de3 100644 --- a/library/std/src/sys/itron/thread.rs +++ b/library/std/src/sys/itron/thread.rs @@ -91,7 +91,7 @@ impl Thread { unsafe extern "C" fn trampoline(exinf: isize) { // Safety: `ThreadInner` is alive at this point - let inner = unsafe { &*(exinf as *const ThreadInner) }; + let inner: &ThreadInner = unsafe { &*crate::ptr::from_exposed_addr(exinf as usize) }; // Safety: Since `trampoline` is called only once for each // `ThreadInner` and only `trampoline` touches `start`, @@ -168,7 +168,7 @@ impl Thread { abi::acre_tsk(&abi::T_CTSK { // Activate this task immediately tskatr: abi::TA_ACT, - exinf: inner_ptr as abi::EXINF, + exinf: inner_ptr.expose_addr() as abi::EXINF, // The entry point task: Some(trampoline), // Inherit the calling task's base priority From 47f2f6d615a70b29a4ef76ebf480703655a0ea05 Mon Sep 17 00:00:00 2001 From: Tomoaki Kawada Date: Thu, 1 Dec 2022 10:57:33 +0900 Subject: [PATCH 029/115] kmc-solid: Add a stub implementation of `is_terminal` Copied from `unsupported/io.rs`. Fixes build failure. --- library/std/src/sys/solid/io.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/library/std/src/sys/solid/io.rs b/library/std/src/sys/solid/io.rs index 9eb17a10daa2..a862bb787026 100644 --- a/library/std/src/sys/solid/io.rs +++ b/library/std/src/sys/solid/io.rs @@ -75,3 +75,7 @@ impl<'a> IoSliceMut<'a> { unsafe { slice::from_raw_parts_mut(self.vec.iov_base as *mut u8, self.vec.iov_len) } } } + +pub fn is_terminal(_: &T) -> bool { + false +} From f482e55adf3fb76860d304c9b7f5c7f3f9a40717 Mon Sep 17 00:00:00 2001 From: Tomoaki Kawada Date: Thu, 1 Dec 2022 11:03:43 +0900 Subject: [PATCH 030/115] kmc-solid: Address compiler warnings Addresses the warn-by-default lints `unused_imports` and `unused_unsafe`. --- library/std/src/sys/itron/condvar.rs | 4 ++-- library/std/src/sys/itron/mutex.rs | 2 +- library/std/src/sys/solid/os.rs | 3 +-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/library/std/src/sys/itron/condvar.rs b/library/std/src/sys/itron/condvar.rs index f70aa434e483..7a47cc6696a3 100644 --- a/library/std/src/sys/itron/condvar.rs +++ b/library/std/src/sys/itron/condvar.rs @@ -71,7 +71,7 @@ impl Condvar { } } - unsafe { mutex.lock() }; + mutex.lock(); } pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool { @@ -109,7 +109,7 @@ impl Condvar { // we woke up because of `notify_*`. let success = self.waiters.with_locked(|waiters| unsafe { !waiters.remove(waiter) }); - unsafe { mutex.lock() }; + mutex.lock(); success } } diff --git a/library/std/src/sys/itron/mutex.rs b/library/std/src/sys/itron/mutex.rs index f2eed8e771c4..1f6cc4194760 100644 --- a/library/std/src/sys/itron/mutex.rs +++ b/library/std/src/sys/itron/mutex.rs @@ -72,7 +72,7 @@ pub(super) struct MutexGuard<'a>(&'a Mutex); impl<'a> MutexGuard<'a> { #[inline] pub(super) fn lock(x: &'a Mutex) -> Self { - unsafe { x.lock() }; + x.lock(); Self(x) } } diff --git a/library/std/src/sys/solid/os.rs b/library/std/src/sys/solid/os.rs index 4906c62689d4..6135921f0b5a 100644 --- a/library/std/src/sys/solid/os.rs +++ b/library/std/src/sys/solid/os.rs @@ -1,7 +1,6 @@ use super::unsupported; -use crate::convert::TryFrom; use crate::error::Error as StdError; -use crate::ffi::{CStr, CString, OsStr, OsString}; +use crate::ffi::{CStr, OsStr, OsString}; use crate::fmt; use crate::io; use crate::os::{ From f4f777772e751066b0ca75f942d403111595c45c Mon Sep 17 00:00:00 2001 From: Jakob Degen Date: Mon, 28 Nov 2022 03:01:11 -0800 Subject: [PATCH 031/115] Disable top-down inlining --- compiler/rustc_mir_transform/src/inline.rs | 28 ++---- src/test/mir-opt/inline/cycle.g.Inline.diff | 25 +++--- .../mir-opt/inline/cycle.main.Inline.diff | 42 +++------ .../exponential_runtime.main.Inline.diff | 50 +++++++++++ .../mir-opt/inline/exponential_runtime.rs | 87 +++++++++++++++++++ .../inline/inline_cycle.one.Inline.diff | 11 +-- .../inline/inline_cycle.two.Inline.diff | 23 ++--- .../inline_cycle_generic.main.Inline.diff | 9 +- .../inline/inline_diverging.h.Inline.diff | 52 ++++++++--- ...t_switch.identity.SeparateConstSwitch.diff | 35 ++++---- 10 files changed, 245 insertions(+), 117 deletions(-) create mode 100644 src/test/mir-opt/inline/exponential_runtime.main.Inline.diff create mode 100644 src/test/mir-opt/inline/exponential_runtime.rs diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 9174f04887e4..744a48c6bb82 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -8,7 +8,6 @@ use rustc_middle::mir::visit::*; use rustc_middle::mir::*; use rustc_middle::ty::{self, Instance, InstanceDef, ParamEnv, Ty, TyCtxt}; use rustc_session::config::OptLevel; -use rustc_span::def_id::DefId; use rustc_span::{hygiene::ExpnKind, ExpnData, LocalExpnId, Span}; use rustc_target::abi::VariantIdx; use rustc_target::spec::abi::Abi; @@ -87,13 +86,8 @@ fn inline<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool { let param_env = tcx.param_env_reveal_all_normalized(def_id); - let mut this = Inliner { - tcx, - param_env, - codegen_fn_attrs: tcx.codegen_fn_attrs(def_id), - history: Vec::new(), - changed: false, - }; + let mut this = + Inliner { tcx, param_env, codegen_fn_attrs: tcx.codegen_fn_attrs(def_id), changed: false }; let blocks = BasicBlock::new(0)..body.basic_blocks.next_index(); this.process_blocks(body, blocks); this.changed @@ -104,12 +98,6 @@ struct Inliner<'tcx> { param_env: ParamEnv<'tcx>, /// Caller codegen attributes. codegen_fn_attrs: &'tcx CodegenFnAttrs, - /// Stack of inlined instances. - /// We only check the `DefId` and not the substs because we want to - /// avoid inlining cases of polymorphic recursion. - /// The number of `DefId`s is finite, so checking history is enough - /// to ensure that we do not loop endlessly while inlining. - history: Vec, /// Indicates that the caller body has been modified. changed: bool, } @@ -134,12 +122,12 @@ impl<'tcx> Inliner<'tcx> { debug!("not-inlined {} [{}]", callsite.callee, reason); continue; } - Ok(new_blocks) => { + Ok(_) => { debug!("inlined {}", callsite.callee); self.changed = true; - self.history.push(callsite.callee.def_id()); - self.process_blocks(caller_body, new_blocks); - self.history.pop(); + // We could process the blocks returned by `try_inlining` here. However, that + // leads to exponential compile times due to the top-down nature of this kind + // of inlining. } } } @@ -313,10 +301,6 @@ impl<'tcx> Inliner<'tcx> { return None; } - if self.history.contains(&callee.def_id()) { - return None; - } - let fn_sig = self.tcx.bound_fn_sig(def_id).subst(self.tcx, substs); return Some(CallSite { diff --git a/src/test/mir-opt/inline/cycle.g.Inline.diff b/src/test/mir-opt/inline/cycle.g.Inline.diff index 5f3ee467c88c..afe157ccd7fa 100644 --- a/src/test/mir-opt/inline/cycle.g.Inline.diff +++ b/src/test/mir-opt/inline/cycle.g.Inline.diff @@ -10,8 +10,6 @@ + let _3: (); // in scope 1 at $DIR/cycle.rs:6:5: 6:8 + let mut _4: &fn() {main}; // in scope 1 at $DIR/cycle.rs:6:5: 6:6 + let mut _5: (); // in scope 1 at $DIR/cycle.rs:6:5: 6:8 -+ scope 2 (inlined >::call - shim(fn() {main})) { // at $DIR/cycle.rs:6:5: 6:8 -+ } + } bb0: { @@ -29,7 +27,10 @@ + StorageLive(_4); // scope 1 at $DIR/cycle.rs:6:5: 6:6 + _4 = &_2; // scope 1 at $DIR/cycle.rs:6:5: 6:6 + StorageLive(_5); // scope 1 at $DIR/cycle.rs:6:5: 6:8 -+ _3 = move (*_4)() -> [return: bb4, unwind: bb2]; // scope 2 at $SRC_DIR/core/src/ops/function.rs:LL:COL ++ _3 = >::call(move _4, move _5) -> [return: bb2, unwind: bb3]; // scope 1 at $DIR/cycle.rs:6:5: 6:8 ++ // mir::Constant ++ // + span: $DIR/cycle.rs:6:5: 6:6 ++ // + literal: Const { ty: for<'a> extern "rust-call" fn(&'a fn() {main}, ()) -> >::Output {>::call}, val: Value() } } bb1: { @@ -39,19 +40,19 @@ return; // scope 0 at $DIR/cycle.rs:+2:2: +2:2 + } + -+ bb2 (cleanup): { -+ drop(_2) -> bb3; // scope 1 at $DIR/cycle.rs:7:1: 7:2 -+ } -+ -+ bb3 (cleanup): { -+ resume; // scope 1 at $DIR/cycle.rs:5:1: 7:2 -+ } -+ -+ bb4: { ++ bb2: { + StorageDead(_5); // scope 1 at $DIR/cycle.rs:6:7: 6:8 + StorageDead(_4); // scope 1 at $DIR/cycle.rs:6:7: 6:8 + StorageDead(_3); // scope 1 at $DIR/cycle.rs:6:8: 6:9 + drop(_2) -> bb1; // scope 1 at $DIR/cycle.rs:7:1: 7:2 ++ } ++ ++ bb3 (cleanup): { ++ drop(_2) -> bb4; // scope 1 at $DIR/cycle.rs:7:1: 7:2 ++ } ++ ++ bb4 (cleanup): { ++ resume; // scope 1 at $DIR/cycle.rs:5:1: 7:2 } } diff --git a/src/test/mir-opt/inline/cycle.main.Inline.diff b/src/test/mir-opt/inline/cycle.main.Inline.diff index 8b4099b9d9f7..bd89e09ecd14 100644 --- a/src/test/mir-opt/inline/cycle.main.Inline.diff +++ b/src/test/mir-opt/inline/cycle.main.Inline.diff @@ -10,18 +10,6 @@ + let _3: (); // in scope 1 at $DIR/cycle.rs:6:5: 6:8 + let mut _4: &fn() {g}; // in scope 1 at $DIR/cycle.rs:6:5: 6:6 + let mut _5: (); // in scope 1 at $DIR/cycle.rs:6:5: 6:8 -+ scope 2 (inlined >::call - shim(fn() {g})) { // at $DIR/cycle.rs:6:5: 6:8 -+ scope 3 (inlined g) { // at $SRC_DIR/core/src/ops/function.rs:LL:COL -+ let mut _6: fn() {main}; // in scope 3 at $DIR/cycle.rs:12:5: 12:12 -+ scope 4 (inlined f::) { // at $DIR/cycle.rs:12:5: 12:12 -+ debug g => _6; // in scope 4 at $DIR/cycle.rs:5:6: 5:7 -+ let _7: (); // in scope 4 at $DIR/cycle.rs:6:5: 6:8 -+ let mut _8: &fn() {main}; // in scope 4 at $DIR/cycle.rs:6:5: 6:6 -+ scope 5 (inlined >::call - shim(fn() {main})) { // at $DIR/cycle.rs:6:5: 6:8 -+ } -+ } -+ } -+ } + } bb0: { @@ -39,11 +27,10 @@ + StorageLive(_4); // scope 1 at $DIR/cycle.rs:6:5: 6:6 + _4 = &_2; // scope 1 at $DIR/cycle.rs:6:5: 6:6 + StorageLive(_5); // scope 1 at $DIR/cycle.rs:6:5: 6:8 -+ StorageLive(_6); // scope 3 at $DIR/cycle.rs:12:5: 12:12 -+ StorageLive(_7); // scope 4 at $DIR/cycle.rs:6:5: 6:8 -+ StorageLive(_8); // scope 4 at $DIR/cycle.rs:6:5: 6:6 -+ _8 = &_6; // scope 4 at $DIR/cycle.rs:6:5: 6:6 -+ _7 = move (*_8)() -> [return: bb4, unwind: bb2]; // scope 5 at $SRC_DIR/core/src/ops/function.rs:LL:COL ++ _3 = >::call(move _4, move _5) -> [return: bb2, unwind: bb3]; // scope 1 at $DIR/cycle.rs:6:5: 6:8 ++ // mir::Constant ++ // + span: $DIR/cycle.rs:6:5: 6:6 ++ // + literal: Const { ty: for<'a> extern "rust-call" fn(&'a fn() {g}, ()) -> >::Output {>::call}, val: Value() } } bb1: { @@ -53,22 +40,19 @@ return; // scope 0 at $DIR/cycle.rs:+2:2: +2:2 + } + -+ bb2 (cleanup): { -+ drop(_2) -> bb3; // scope 1 at $DIR/cycle.rs:7:1: 7:2 -+ } -+ -+ bb3 (cleanup): { -+ resume; // scope 1 at $DIR/cycle.rs:5:1: 7:2 -+ } -+ -+ bb4: { -+ StorageDead(_8); // scope 4 at $DIR/cycle.rs:6:7: 6:8 -+ StorageDead(_7); // scope 4 at $DIR/cycle.rs:6:8: 6:9 -+ StorageDead(_6); // scope 3 at $DIR/cycle.rs:12:5: 12:12 ++ bb2: { + StorageDead(_5); // scope 1 at $DIR/cycle.rs:6:7: 6:8 + StorageDead(_4); // scope 1 at $DIR/cycle.rs:6:7: 6:8 + StorageDead(_3); // scope 1 at $DIR/cycle.rs:6:8: 6:9 + drop(_2) -> bb1; // scope 1 at $DIR/cycle.rs:7:1: 7:2 ++ } ++ ++ bb3 (cleanup): { ++ drop(_2) -> bb4; // scope 1 at $DIR/cycle.rs:7:1: 7:2 ++ } ++ ++ bb4 (cleanup): { ++ resume; // scope 1 at $DIR/cycle.rs:5:1: 7:2 } } diff --git a/src/test/mir-opt/inline/exponential_runtime.main.Inline.diff b/src/test/mir-opt/inline/exponential_runtime.main.Inline.diff new file mode 100644 index 000000000000..d9fd7b324c76 --- /dev/null +++ b/src/test/mir-opt/inline/exponential_runtime.main.Inline.diff @@ -0,0 +1,50 @@ +- // MIR for `main` before Inline ++ // MIR for `main` after Inline + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/exponential_runtime.rs:+0:11: +0:11 + let _1: (); // in scope 0 at $DIR/exponential_runtime.rs:+1:5: +1:22 ++ scope 1 (inlined <() as G>::call) { // at $DIR/exponential_runtime.rs:86:5: 86:22 ++ let _2: (); // in scope 1 at $DIR/exponential_runtime.rs:73:9: 73:25 ++ let _3: (); // in scope 1 at $DIR/exponential_runtime.rs:74:9: 74:25 ++ let _4: (); // in scope 1 at $DIR/exponential_runtime.rs:75:9: 75:25 ++ } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/exponential_runtime.rs:+1:5: +1:22 +- _1 = <() as G>::call() -> bb1; // scope 0 at $DIR/exponential_runtime.rs:+1:5: +1:22 ++ StorageLive(_2); // scope 1 at $DIR/exponential_runtime.rs:73:9: 73:25 ++ _2 = <() as F>::call() -> bb1; // scope 1 at $DIR/exponential_runtime.rs:73:9: 73:25 + // mir::Constant +- // + span: $DIR/exponential_runtime.rs:86:5: 86:20 +- // + literal: Const { ty: fn() {<() as G>::call}, val: Value() } ++ // + span: $DIR/exponential_runtime.rs:73:9: 73:23 ++ // + literal: Const { ty: fn() {<() as F>::call}, val: Value() } + } + + bb1: { ++ StorageDead(_2); // scope 1 at $DIR/exponential_runtime.rs:73:25: 73:26 ++ StorageLive(_3); // scope 1 at $DIR/exponential_runtime.rs:74:9: 74:25 ++ _3 = <() as F>::call() -> bb2; // scope 1 at $DIR/exponential_runtime.rs:74:9: 74:25 ++ // mir::Constant ++ // + span: $DIR/exponential_runtime.rs:74:9: 74:23 ++ // + literal: Const { ty: fn() {<() as F>::call}, val: Value() } ++ } ++ ++ bb2: { ++ StorageDead(_3); // scope 1 at $DIR/exponential_runtime.rs:74:25: 74:26 ++ StorageLive(_4); // scope 1 at $DIR/exponential_runtime.rs:75:9: 75:25 ++ _4 = <() as F>::call() -> bb3; // scope 1 at $DIR/exponential_runtime.rs:75:9: 75:25 ++ // mir::Constant ++ // + span: $DIR/exponential_runtime.rs:75:9: 75:23 ++ // + literal: Const { ty: fn() {<() as F>::call}, val: Value() } ++ } ++ ++ bb3: { ++ StorageDead(_4); // scope 1 at $DIR/exponential_runtime.rs:75:25: 75:26 + StorageDead(_1); // scope 0 at $DIR/exponential_runtime.rs:+1:22: +1:23 + _0 = const (); // scope 0 at $DIR/exponential_runtime.rs:+0:11: +2:2 + return; // scope 0 at $DIR/exponential_runtime.rs:+2:2: +2:2 + } + } + diff --git a/src/test/mir-opt/inline/exponential_runtime.rs b/src/test/mir-opt/inline/exponential_runtime.rs new file mode 100644 index 000000000000..d9219d76a98b --- /dev/null +++ b/src/test/mir-opt/inline/exponential_runtime.rs @@ -0,0 +1,87 @@ +// Checks that code with exponential runtime does not have exponential behavior in inlining. + +trait A { + fn call(); +} + +trait B { + fn call(); +} +impl B for T { + #[inline] + fn call() { + ::call(); + ::call(); + ::call(); + } +} + +trait C { + fn call(); +} +impl C for T { + #[inline] + fn call() { + ::call(); + ::call(); + ::call(); + } +} + +trait D { + fn call(); +} +impl D for T { + #[inline] + fn call() { + ::call(); + ::call(); + ::call(); + } +} + +trait E { + fn call(); +} +impl E for T { + #[inline] + fn call() { + ::call(); + ::call(); + ::call(); + } +} + +trait F { + fn call(); +} +impl F for T { + #[inline] + fn call() { + ::call(); + ::call(); + ::call(); + } +} + +trait G { + fn call(); +} +impl G for T { + #[inline] + fn call() { + ::call(); + ::call(); + ::call(); + } +} + +impl A for () { + #[inline(never)] + fn call() {} +} + +// EMIT_MIR exponential_runtime.main.Inline.diff +fn main() { + <() as G>::call(); +} diff --git a/src/test/mir-opt/inline/inline_cycle.one.Inline.diff b/src/test/mir-opt/inline/inline_cycle.one.Inline.diff index 5510cd7bc8ce..f54a1a747d47 100644 --- a/src/test/mir-opt/inline/inline_cycle.one.Inline.diff +++ b/src/test/mir-opt/inline/inline_cycle.one.Inline.diff @@ -5,20 +5,17 @@ let mut _0: (); // return place in scope 0 at $DIR/inline_cycle.rs:+0:10: +0:10 let _1: (); // in scope 0 at $DIR/inline_cycle.rs:+1:5: +1:24 + scope 1 (inlined ::call) { // at $DIR/inline_cycle.rs:14:5: 14:24 -+ scope 2 (inlined as Call>::call) { // at $DIR/inline_cycle.rs:43:9: 43:23 -+ scope 3 (inlined as Call>::call) { // at $DIR/inline_cycle.rs:28:9: 28:31 -+ } -+ } + } bb0: { StorageLive(_1); // scope 0 at $DIR/inline_cycle.rs:+1:5: +1:24 - _1 = ::call() -> bb1; // scope 0 at $DIR/inline_cycle.rs:+1:5: +1:24 -+ _1 = ::call() -> bb1; // scope 3 at $DIR/inline_cycle.rs:36:9: 36:28 ++ _1 = as Call>::call() -> bb1; // scope 1 at $DIR/inline_cycle.rs:43:9: 43:23 // mir::Constant - // + span: $DIR/inline_cycle.rs:14:5: 14:22 -+ // + span: $DIR/inline_cycle.rs:36:9: 36:26 - // + literal: Const { ty: fn() {::call}, val: Value() } +- // + literal: Const { ty: fn() {::call}, val: Value() } ++ // + span: $DIR/inline_cycle.rs:43:9: 43:21 ++ // + literal: Const { ty: fn() { as Call>::call}, val: Value() } } bb1: { diff --git a/src/test/mir-opt/inline/inline_cycle.two.Inline.diff b/src/test/mir-opt/inline/inline_cycle.two.Inline.diff index ab1ea0e3b2c2..a940848c269c 100644 --- a/src/test/mir-opt/inline/inline_cycle.two.Inline.diff +++ b/src/test/mir-opt/inline/inline_cycle.two.Inline.diff @@ -9,11 +9,6 @@ + debug f => _2; // in scope 1 at $DIR/inline_cycle.rs:53:22: 53:23 + let _3: (); // in scope 1 at $DIR/inline_cycle.rs:54:5: 54:8 + let mut _4: (); // in scope 1 at $DIR/inline_cycle.rs:54:5: 54:8 -+ scope 2 (inlined >::call_once - shim(fn() {f})) { // at $DIR/inline_cycle.rs:54:5: 54:8 -+ scope 3 (inlined f) { // at $SRC_DIR/core/src/ops/function.rs:LL:COL -+ let _5: (); // in scope 3 at $DIR/inline_cycle.rs:59:5: 59:12 -+ } -+ } + } bb0: { @@ -23,23 +18,19 @@ + _2 = f; // scope 0 at $DIR/inline_cycle.rs:+1:5: +1:12 // mir::Constant - // + span: $DIR/inline_cycle.rs:49:5: 49:9 -+ // + span: $DIR/inline_cycle.rs:49:10: 49:11 -+ // + literal: Const { ty: fn() {f}, val: Value() } +- // + literal: Const { ty: fn(fn() {f}) {call::}, val: Value() } +- // mir::Constant + // + span: $DIR/inline_cycle.rs:49:10: 49:11 + // + literal: Const { ty: fn() {f}, val: Value() } + StorageLive(_3); // scope 1 at $DIR/inline_cycle.rs:54:5: 54:8 + StorageLive(_4); // scope 1 at $DIR/inline_cycle.rs:54:5: 54:8 -+ StorageLive(_5); // scope 3 at $DIR/inline_cycle.rs:59:5: 59:12 -+ _5 = call::(f) -> bb1; // scope 3 at $DIR/inline_cycle.rs:59:5: 59:12 ++ _3 = >::call_once(move _2, move _4) -> bb1; // scope 1 at $DIR/inline_cycle.rs:54:5: 54:8 + // mir::Constant -+ // + span: $DIR/inline_cycle.rs:59:5: 59:9 - // + literal: Const { ty: fn(fn() {f}) {call::}, val: Value() } - // mir::Constant -- // + span: $DIR/inline_cycle.rs:49:10: 49:11 -+ // + span: $DIR/inline_cycle.rs:59:10: 59:11 - // + literal: Const { ty: fn() {f}, val: Value() } ++ // + span: $DIR/inline_cycle.rs:54:5: 54:6 ++ // + literal: Const { ty: extern "rust-call" fn(fn() {f}, ()) -> >::Output {>::call_once}, val: Value() } } bb1: { -+ StorageDead(_5); // scope 3 at $DIR/inline_cycle.rs:59:12: 59:13 + StorageDead(_4); // scope 1 at $DIR/inline_cycle.rs:54:7: 54:8 + StorageDead(_3); // scope 1 at $DIR/inline_cycle.rs:54:8: 54:9 + StorageDead(_2); // scope 0 at $DIR/inline_cycle.rs:+1:5: +1:12 diff --git a/src/test/mir-opt/inline/inline_cycle_generic.main.Inline.diff b/src/test/mir-opt/inline/inline_cycle_generic.main.Inline.diff index 52debab4dd1c..04de3e61e5ff 100644 --- a/src/test/mir-opt/inline/inline_cycle_generic.main.Inline.diff +++ b/src/test/mir-opt/inline/inline_cycle_generic.main.Inline.diff @@ -6,21 +6,18 @@ let _1: (); // in scope 0 at $DIR/inline_cycle_generic.rs:+1:5: +1:24 + scope 1 (inlined ::call) { // at $DIR/inline_cycle_generic.rs:9:5: 9:24 + scope 2 (inlined as Call>::call) { // at $DIR/inline_cycle_generic.rs:38:9: 38:31 -+ scope 3 (inlined ::call) { // at $DIR/inline_cycle_generic.rs:31:9: 31:28 -+ scope 4 (inlined as Call>::call) { // at $DIR/inline_cycle_generic.rs:23:9: 23:31 -+ } -+ } + } + } bb0: { StorageLive(_1); // scope 0 at $DIR/inline_cycle_generic.rs:+1:5: +1:24 - _1 = ::call() -> bb1; // scope 0 at $DIR/inline_cycle_generic.rs:+1:5: +1:24 -+ _1 = ::call() -> bb1; // scope 4 at $DIR/inline_cycle_generic.rs:31:9: 31:28 ++ _1 = ::call() -> bb1; // scope 2 at $DIR/inline_cycle_generic.rs:31:9: 31:28 // mir::Constant - // + span: $DIR/inline_cycle_generic.rs:9:5: 9:22 +- // + literal: Const { ty: fn() {::call}, val: Value() } + // + span: $DIR/inline_cycle_generic.rs:31:9: 31:26 - // + literal: Const { ty: fn() {::call}, val: Value() } ++ // + literal: Const { ty: fn() {::call}, val: Value() } } bb1: { diff --git a/src/test/mir-opt/inline/inline_diverging.h.Inline.diff b/src/test/mir-opt/inline/inline_diverging.h.Inline.diff index 75a6ab370089..a01bcf1645b0 100644 --- a/src/test/mir-opt/inline/inline_diverging.h.Inline.diff +++ b/src/test/mir-opt/inline/inline_diverging.h.Inline.diff @@ -19,14 +19,6 @@ + scope 3 { + debug b => _9; // in scope 3 at $DIR/inline_diverging.rs:28:9: 28:10 + } -+ scope 6 (inlined ! {sleep} as Fn<()>>::call - shim(fn() -> ! {sleep})) { // at $DIR/inline_diverging.rs:28:13: 28:16 -+ scope 7 (inlined sleep) { // at $SRC_DIR/core/src/ops/function.rs:LL:COL -+ } -+ } -+ } -+ scope 4 (inlined ! {sleep} as Fn<()>>::call - shim(fn() -> ! {sleep})) { // at $DIR/inline_diverging.rs:27:13: 27:16 -+ scope 5 (inlined sleep) { // at $SRC_DIR/core/src/ops/function.rs:LL:COL -+ } + } + } @@ -46,11 +38,51 @@ + StorageLive(_4); // scope 1 at $DIR/inline_diverging.rs:27:13: 27:14 + _4 = &_2; // scope 1 at $DIR/inline_diverging.rs:27:13: 27:14 + StorageLive(_5); // scope 1 at $DIR/inline_diverging.rs:27:13: 27:16 -+ goto -> bb1; // scope 5 at $DIR/inline_diverging.rs:39:5: 39:12 ++ _3 = ! {sleep} as Fn<()>>::call(move _4, move _5) -> [return: bb1, unwind: bb5]; // scope 1 at $DIR/inline_diverging.rs:27:13: 27:16 ++ // mir::Constant ++ // + span: $DIR/inline_diverging.rs:27:13: 27:14 ++ // + literal: Const { ty: for<'a> extern "rust-call" fn(&'a fn() -> ! {sleep}, ()) -> ! {sleep} as FnOnce<()>>::Output { ! {sleep} as Fn<()>>::call}, val: Value() } + } + + bb1: { -+ goto -> bb1; // scope 5 at $DIR/inline_diverging.rs:39:5: 39:12 ++ StorageDead(_5); // scope 1 at $DIR/inline_diverging.rs:27:15: 27:16 ++ StorageDead(_4); // scope 1 at $DIR/inline_diverging.rs:27:15: 27:16 ++ StorageLive(_6); // scope 2 at $DIR/inline_diverging.rs:28:13: 28:14 ++ _6 = &_2; // scope 2 at $DIR/inline_diverging.rs:28:13: 28:14 ++ StorageLive(_7); // scope 2 at $DIR/inline_diverging.rs:28:13: 28:16 ++ _9 = ! {sleep} as Fn<()>>::call(move _6, move _7) -> [return: bb2, unwind: bb4]; // scope 2 at $DIR/inline_diverging.rs:28:13: 28:16 ++ // mir::Constant ++ // + span: $DIR/inline_diverging.rs:28:13: 28:14 ++ // + literal: Const { ty: for<'a> extern "rust-call" fn(&'a fn() -> ! {sleep}, ()) -> ! {sleep} as FnOnce<()>>::Output { ! {sleep} as Fn<()>>::call}, val: Value() } ++ } ++ ++ bb2: { ++ StorageDead(_7); // scope 2 at $DIR/inline_diverging.rs:28:15: 28:16 ++ StorageDead(_6); // scope 2 at $DIR/inline_diverging.rs:28:15: 28:16 ++ StorageLive(_8); // scope 3 at $DIR/inline_diverging.rs:29:6: 29:7 ++ _8 = move _3; // scope 3 at $DIR/inline_diverging.rs:29:6: 29:7 ++ Deinit(_1); // scope 3 at $DIR/inline_diverging.rs:29:5: 29:11 ++ (_1.0: !) = move _8; // scope 3 at $DIR/inline_diverging.rs:29:5: 29:11 ++ (_1.1: !) = move _9; // scope 3 at $DIR/inline_diverging.rs:29:5: 29:11 ++ StorageDead(_8); // scope 3 at $DIR/inline_diverging.rs:29:10: 29:11 ++ StorageDead(_3); // scope 1 at $DIR/inline_diverging.rs:30:1: 30:2 ++ drop(_2) -> bb3; // scope 1 at $DIR/inline_diverging.rs:30:1: 30:2 ++ } ++ ++ bb3: { ++ unreachable; // scope 0 at $DIR/inline_diverging.rs:30:2: 30:2 ++ } ++ ++ bb4 (cleanup): { ++ drop(_3) -> bb5; // scope 1 at $DIR/inline_diverging.rs:30:1: 30:2 ++ } ++ ++ bb5 (cleanup): { ++ drop(_2) -> bb6; // scope 1 at $DIR/inline_diverging.rs:30:1: 30:2 ++ } ++ ++ bb6 (cleanup): { ++ resume; // scope 1 at $DIR/inline_diverging.rs:26:1: 30:2 } } diff --git a/src/test/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff b/src/test/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff index f25b3ce724be..b28c6f687f70 100644 --- a/src/test/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff +++ b/src/test/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff @@ -22,9 +22,6 @@ let mut _18: i32; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL scope 9 { debug e => _16; // in scope 9 at $SRC_DIR/core/src/result.rs:LL:COL - scope 10 (inlined >::from) { // at $SRC_DIR/core/src/result.rs:LL:COL - debug t => _18; // in scope 10 at $SRC_DIR/core/src/convert/mod.rs:LL:COL - } } } } @@ -95,18 +92,11 @@ StorageLive(_17); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL StorageLive(_18); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL _18 = move _16; // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL - _17 = move _18; // scope 10 at $SRC_DIR/core/src/convert/mod.rs:LL:COL - StorageDead(_18); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL - Deinit(_0); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL - ((_0 as Err).0: i32) = move _17; // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL - discriminant(_0) = 1; // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL - StorageDead(_17); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL - StorageDead(_16); // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL - StorageDead(_8); // scope 2 at $DIR/separate_const_switch.rs:+1:9: +1:10 - StorageDead(_6); // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10 - StorageDead(_2); // scope 0 at $DIR/separate_const_switch.rs:+1:10: +1:11 - StorageDead(_3); // scope 0 at $DIR/separate_const_switch.rs:+2:1: +2:2 - return; // scope 0 at $DIR/separate_const_switch.rs:+2:2: +2:2 +- _17 = >::from(move _18) -> bb8; // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL ++ _17 = >::from(move _18) -> bb7; // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL + // mir::Constant + // + span: $SRC_DIR/core/src/result.rs:LL:COL + // + literal: Const { ty: fn(i32) -> i32 {>::from}, val: Value() } } - bb5: { @@ -152,5 +142,20 @@ + _5 = discriminant(_3); // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10 + switchInt(move _5) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10 } + +- bb8: { ++ bb7: { + StorageDead(_18); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL + Deinit(_0); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL + ((_0 as Err).0: i32) = move _17; // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL + discriminant(_0) = 1; // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL + StorageDead(_17); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL + StorageDead(_16); // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL + StorageDead(_8); // scope 2 at $DIR/separate_const_switch.rs:+1:9: +1:10 + StorageDead(_6); // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10 + StorageDead(_2); // scope 0 at $DIR/separate_const_switch.rs:+1:10: +1:11 + StorageDead(_3); // scope 0 at $DIR/separate_const_switch.rs:+2:1: +2:2 + return; // scope 0 at $DIR/separate_const_switch.rs:+2:2: +2:2 + } } From 0e19fb92e1eb7f91aa5570b2ac782c9a42a6e329 Mon Sep 17 00:00:00 2001 From: Yiming Lei Date: Wed, 30 Nov 2022 12:01:00 -0800 Subject: [PATCH 032/115] While parsing enum variant, the error message always disappear Because the error message that emit out is from main error of parser The information of enum variant disappears while parsing enum variant with error We only check the syntax of expecting token, i.e, in case #103869 It will error it without telling the message that this error is from pasring enum variant. Propagate the sub-error from parsing enum variant to the main error of parser by chaining it with map_err Check the sub-error before emitting the main error of parser and attach it. Fix #103869 --- compiler/rustc_parse/src/parser/item.rs | 5 ++++- compiler/rustc_parse/src/parser/mod.rs | 4 ++++ src/test/ui/macros/syntax-error-recovery.stderr | 1 + src/test/ui/parser/issue-101477-enum.stderr | 2 ++ src/test/ui/parser/issue-103869.rs | 9 +++++++++ src/test/ui/parser/issue-103869.stderr | 16 ++++++++++++++++ src/test/ui/parser/macro/issue-37113.stderr | 1 + src/test/ui/structs/struct-fn-in-definition.rs | 1 + .../ui/structs/struct-fn-in-definition.stderr | 1 + 9 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/parser/issue-103869.rs create mode 100644 src/test/ui/parser/issue-103869.stderr diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 767fb9378bef..7ce89b5c3597 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1414,7 +1414,10 @@ impl<'a> Parser<'a> { Ok((Some(vr), TrailingToken::MaybeComma)) }, - ) + ).map_err(|mut err|{ + err.help("enum variants can be `Variant`, `Variant = `, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }`"); + err + }) } /// Parses `struct Foo { ... }`. diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 4d8bff28b05a..bebb012660a1 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -943,6 +943,10 @@ impl<'a> Parser<'a> { Err(e) => { // Parsing failed, therefore it must be something more serious // than just a missing separator. + for xx in &e.children { + // propagate the help message from sub error 'e' to main error 'expect_err; + expect_err.children.push(xx.clone()); + } expect_err.emit(); e.cancel(); diff --git a/src/test/ui/macros/syntax-error-recovery.stderr b/src/test/ui/macros/syntax-error-recovery.stderr index c153b3b910bb..c42ee9b295e1 100644 --- a/src/test/ui/macros/syntax-error-recovery.stderr +++ b/src/test/ui/macros/syntax-error-recovery.stderr @@ -7,6 +7,7 @@ LL | $token $($inner)? = $value, LL | values!(STRING(1) as (String) => cfg(test),); | -------------------------------------------- in this macro invocation | + = help: enum variants can be `Variant`, `Variant = `, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }` = note: this error originates in the macro `values` (in Nightly builds, run with -Z macro-backtrace for more info) error: macro expansion ignores token `(String)` and any following diff --git a/src/test/ui/parser/issue-101477-enum.stderr b/src/test/ui/parser/issue-101477-enum.stderr index bffc881bdc84..1edca391e8fd 100644 --- a/src/test/ui/parser/issue-101477-enum.stderr +++ b/src/test/ui/parser/issue-101477-enum.stderr @@ -3,6 +3,8 @@ error: unexpected `==` | LL | B == 2 | ^^ help: try using `=` instead + | + = help: enum variants can be `Variant`, `Variant = `, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }` error: expected item, found `==` --> $DIR/issue-101477-enum.rs:6:7 diff --git a/src/test/ui/parser/issue-103869.rs b/src/test/ui/parser/issue-103869.rs new file mode 100644 index 000000000000..28c442bdd632 --- /dev/null +++ b/src/test/ui/parser/issue-103869.rs @@ -0,0 +1,9 @@ +enum VecOrMap{ + vec: Vec, + //~^ ERROR expected one of `(`, `,`, `=`, `{`, or `}`, found `:` + //~| HELP: enum variants can be `Variant`, `Variant = `, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }` + //~| ERROR expected item, found `:` + map: HashMap +} + +fn main() {} diff --git a/src/test/ui/parser/issue-103869.stderr b/src/test/ui/parser/issue-103869.stderr new file mode 100644 index 000000000000..0b8cd919a9de --- /dev/null +++ b/src/test/ui/parser/issue-103869.stderr @@ -0,0 +1,16 @@ +error: expected one of `(`, `,`, `=`, `{`, or `}`, found `:` + --> $DIR/issue-103869.rs:2:8 + | +LL | vec: Vec, + | ^ expected one of `(`, `,`, `=`, `{`, or `}` + | + = help: enum variants can be `Variant`, `Variant = `, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }` + +error: expected item, found `:` + --> $DIR/issue-103869.rs:2:8 + | +LL | vec: Vec, + | ^ expected item + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/parser/macro/issue-37113.stderr b/src/test/ui/parser/macro/issue-37113.stderr index b1f8674fbdf3..da9e743a0b44 100644 --- a/src/test/ui/parser/macro/issue-37113.stderr +++ b/src/test/ui/parser/macro/issue-37113.stderr @@ -9,6 +9,7 @@ LL | $( $t, )* LL | test_macro!(String,); | -------------------- in this macro invocation | + = help: enum variants can be `Variant`, `Variant = `, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }` = note: this error originates in the macro `test_macro` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/structs/struct-fn-in-definition.rs b/src/test/ui/structs/struct-fn-in-definition.rs index 5ae1b727dc77..7f48f55fec93 100644 --- a/src/test/ui/structs/struct-fn-in-definition.rs +++ b/src/test/ui/structs/struct-fn-in-definition.rs @@ -28,6 +28,7 @@ enum E { //~^ ERROR functions are not allowed in enum definitions //~| HELP unlike in C++, Java, and C#, functions are declared in `impl` blocks //~| HELP see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information + //~| HELP enum variants can be `Variant`, `Variant = `, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }` } fn main() {} diff --git a/src/test/ui/structs/struct-fn-in-definition.stderr b/src/test/ui/structs/struct-fn-in-definition.stderr index 472365c6ed73..439c86ec22b0 100644 --- a/src/test/ui/structs/struct-fn-in-definition.stderr +++ b/src/test/ui/structs/struct-fn-in-definition.stderr @@ -33,6 +33,7 @@ LL | fn foo() {} | = help: unlike in C++, Java, and C#, functions are declared in `impl` blocks = help: see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information + = help: enum variants can be `Variant`, `Variant = `, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }` error: aborting due to 3 previous errors From ae7633f434011fe1829b9b235a20d91634479eb5 Mon Sep 17 00:00:00 2001 From: Tomoaki Kawada Date: Thu, 1 Dec 2022 11:56:31 +0900 Subject: [PATCH 033/115] kmc-solid: Don't do `Box::from_raw(&*(x: Box) as *const T as *mut T)` This pattern seems to be considered illegal by Miri. --- library/std/src/sys/itron/thread.rs | 48 ++++++++++++++++++----------- 1 file changed, 30 insertions(+), 18 deletions(-) diff --git a/library/std/src/sys/itron/thread.rs b/library/std/src/sys/itron/thread.rs index 573a50b42de3..c2b366808722 100644 --- a/library/std/src/sys/itron/thread.rs +++ b/library/std/src/sys/itron/thread.rs @@ -11,18 +11,25 @@ use crate::{ ffi::CStr, hint, io, mem::ManuallyDrop, + ptr::NonNull, sync::atomic::{AtomicUsize, Ordering}, sys::thread_local_dtor::run_dtors, time::Duration, }; pub struct Thread { - inner: ManuallyDrop>, + p_inner: NonNull, /// The ID of the underlying task. task: abi::ID, } +// Safety: There's nothing in `Thread` that ties it to the original creator. It +// can be dropped by any threads. +unsafe impl Send for Thread {} +// Safety: `Thread` provides no methods that take `&self`. +unsafe impl Sync for Thread {} + /// State data shared between a parent thread and child thread. It's dropped on /// a transition to one of the final states. struct ThreadInner { @@ -90,8 +97,9 @@ impl Thread { }); unsafe extern "C" fn trampoline(exinf: isize) { + let p_inner: *mut ThreadInner = crate::ptr::from_exposed_addr_mut(exinf as usize); // Safety: `ThreadInner` is alive at this point - let inner: &ThreadInner = unsafe { &*crate::ptr::from_exposed_addr(exinf as usize) }; + let inner = unsafe { &*p_inner }; // Safety: Since `trampoline` is called only once for each // `ThreadInner` and only `trampoline` touches `start`, @@ -119,13 +127,13 @@ impl Thread { // No one will ever join, so we'll ask the collector task to // delete the task. - // In this case, `inner`'s ownership has been moved to us, - // And we are responsible for dropping it. The acquire + // In this case, `*p_inner`'s ownership has been moved to + // us, and we are responsible for dropping it. The acquire // ordering is not necessary because the parent thread made // no memory access needing synchronization since the call // to `acre_tsk`. // Safety: See above. - let _ = unsafe { Box::from_raw(inner as *const _ as *mut ThreadInner) }; + let _ = unsafe { Box::from_raw(p_inner) }; // Safety: There are no pinned references to the stack unsafe { terminate_and_delete_current_task() }; @@ -162,13 +170,14 @@ impl Thread { } } - let inner_ptr = (&*inner) as *const ThreadInner; + // Safety: `Box::into_raw` returns a non-null pointer + let p_inner = unsafe { NonNull::new_unchecked(Box::into_raw(inner)) }; let new_task = ItronError::err_if_negative(unsafe { abi::acre_tsk(&abi::T_CTSK { // Activate this task immediately tskatr: abi::TA_ACT, - exinf: inner_ptr.expose_addr() as abi::EXINF, + exinf: p_inner.as_ptr().expose_addr() as abi::EXINF, // The entry point task: Some(trampoline), // Inherit the calling task's base priority @@ -180,7 +189,7 @@ impl Thread { }) .map_err(|e| e.as_io_error())?; - Ok(Self { inner: ManuallyDrop::new(inner), task: new_task }) + Ok(Self { p_inner, task: new_task }) } pub fn yield_now() { @@ -197,8 +206,9 @@ impl Thread { } } - pub fn join(mut self) { - let inner = &*self.inner; + pub fn join(self) { + // Safety: `ThreadInner` is alive at this point + let inner = unsafe { self.p_inner.as_ref() }; // Get the current task ID. Panicking here would cause a resource leak, // so just abort on failure. let current_task = task::current_task_id_aborting(); @@ -243,8 +253,8 @@ impl Thread { unsafe { terminate_and_delete_task(self.task) }; // In either case, we are responsible for dropping `inner`. - // Safety: The contents of `self.inner` will not be accessed hereafter - let _inner = unsafe { ManuallyDrop::take(&mut self.inner) }; + // Safety: The contents of `*p_inner` will not be accessed hereafter + let _inner = unsafe { Box::from_raw(self.p_inner.as_ptr()) }; // Skip the destructor (because it would attempt to detach the thread) crate::mem::forget(self); @@ -253,13 +263,16 @@ impl Thread { impl Drop for Thread { fn drop(&mut self) { + // Safety: `ThreadInner` is alive at this point + let inner = unsafe { self.p_inner.as_ref() }; + // Detach the thread. - match self.inner.lifecycle.swap(LIFECYCLE_DETACHED_OR_JOINED, Ordering::Acquire) { + match inner.lifecycle.swap(LIFECYCLE_DETACHED_OR_JOINED, Ordering::Acquire) { LIFECYCLE_INIT => { // [INIT → DETACHED] // When the time comes, the child will figure out that no // one will ever join it. - // The ownership of `self.inner` is moved to the child thread. + // The ownership of `*p_inner` is moved to the child thread. // However, the release ordering is not necessary because we // made no memory access needing synchronization since the call // to `acre_tsk`. @@ -278,10 +291,9 @@ impl Drop for Thread { // delete by entering the `FINISHED` state. unsafe { terminate_and_delete_task(self.task) }; - // Wwe are responsible for dropping `inner`. - // Safety: The contents of `self.inner` will not be accessed - // hereafter - unsafe { ManuallyDrop::drop(&mut self.inner) }; + // Wwe are responsible for dropping `*p_inner`. + // Safety: The contents of `*p_inner` will not be accessed hereafter + let _ = unsafe { Box::from_raw(self.p_inner.as_ptr()) }; } _ => unsafe { hint::unreachable_unchecked() }, } From 5c7278a36412c1a0a06bab4f1364cf5719ab8287 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Mon, 28 Nov 2022 16:14:20 +0900 Subject: [PATCH 034/115] return when expr has error fmt add a comment --- compiler/rustc_lint/src/unused.rs | 31 ++++++++++++++++---- src/test/ui/lint/issue-104897.rs | 6 ++++ src/test/ui/lint/issue-104897.stderr | 43 ++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+), 5 deletions(-) create mode 100644 src/test/ui/lint/issue-104897.rs create mode 100644 src/test/ui/lint/issue-104897.stderr diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 43864ed45fae..372b6d7a2b8c 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -636,13 +636,34 @@ trait UnusedDelimLint { left_pos: Option, right_pos: Option, ) { + // If `value` has `ExprKind::Err`, unused delim lint can be broken. + // For example, the following code caused ICE. + // This is because the `ExprKind::Call` in `value` has `ExprKind::Err` as its argument + // and this leads to wrong spans. #104897 + // + // ``` + // fn f(){(print!(á + // ``` + use rustc_ast::visit::{walk_expr, Visitor}; + struct ErrExprVisitor { + has_error: bool, + } + impl<'ast> Visitor<'ast> for ErrExprVisitor { + fn visit_expr(&mut self, expr: &'ast ast::Expr) { + if let ExprKind::Err = expr.kind { + self.has_error = true; + return; + } + walk_expr(self, expr) + } + } + let mut visitor = ErrExprVisitor { has_error: false }; + visitor.visit_expr(value); + if visitor.has_error { + return; + } let spans = match value.kind { ast::ExprKind::Block(ref block, None) if block.stmts.len() == 1 => { - if let StmtKind::Expr(expr) = &block.stmts[0].kind - && let ExprKind::Err = expr.kind - { - return - } if let Some(span) = block.stmts[0].span.find_ancestor_inside(value.span) { Some((value.span.with_hi(span.lo()), value.span.with_lo(span.hi()))) } else { diff --git a/src/test/ui/lint/issue-104897.rs b/src/test/ui/lint/issue-104897.rs new file mode 100644 index 000000000000..5fbc658f1557 --- /dev/null +++ b/src/test/ui/lint/issue-104897.rs @@ -0,0 +1,6 @@ +// error-pattern: this file contains an unclosed delimiter +// error-pattern: this file contains an unclosed delimiter +// error-pattern: this file contains an unclosed delimiter +// error-pattern: format argument must be a string literal + +fn f(){(print!(á diff --git a/src/test/ui/lint/issue-104897.stderr b/src/test/ui/lint/issue-104897.stderr new file mode 100644 index 000000000000..817a93c2f3bb --- /dev/null +++ b/src/test/ui/lint/issue-104897.stderr @@ -0,0 +1,43 @@ +error: this file contains an unclosed delimiter + --> $DIR/issue-104897.rs:6:18 + | +LL | fn f(){(print!(á + | -- - ^ + | || | + | || unclosed delimiter + | |unclosed delimiter + | unclosed delimiter + +error: this file contains an unclosed delimiter + --> $DIR/issue-104897.rs:6:18 + | +LL | fn f(){(print!(á + | -- - ^ + | || | + | || unclosed delimiter + | |unclosed delimiter + | unclosed delimiter + +error: this file contains an unclosed delimiter + --> $DIR/issue-104897.rs:6:18 + | +LL | fn f(){(print!(á + | -- - ^ + | || | + | || unclosed delimiter + | |unclosed delimiter + | unclosed delimiter + +error: format argument must be a string literal + --> $DIR/issue-104897.rs:6:16 + | +LL | fn f(){(print!(á + | ^ + | +help: you might be missing a string literal to format with + | +LL | fn f(){(print!("{}", á + | +++++ + +error: aborting due to 4 previous errors + From eadf69a6c6edfe220fc5b1b659e46e271d75a3a1 Mon Sep 17 00:00:00 2001 From: klensy Date: Fri, 2 Dec 2022 17:17:36 +0300 Subject: [PATCH 035/115] reduce docker image sizes by cleaning cache/squashing steps --- src/ci/docker/host-aarch64/aarch64-gnu/Dockerfile | 3 ++- src/ci/docker/host-x86_64/dist-i686-linux/Dockerfile | 3 ++- src/ci/docker/host-x86_64/dist-x86_64-freebsd/Dockerfile | 3 ++- src/ci/docker/host-x86_64/dist-x86_64-illumos/Dockerfile | 3 ++- src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile | 3 ++- src/ci/docker/host-x86_64/dist-x86_64-musl/Dockerfile | 3 ++- src/ci/docker/host-x86_64/i686-gnu-nopt/Dockerfile | 3 ++- src/ci/docker/host-x86_64/i686-gnu/Dockerfile | 3 ++- src/ci/docker/host-x86_64/mingw-check/Dockerfile | 8 ++++---- src/ci/docker/host-x86_64/test-various/Dockerfile | 3 ++- src/ci/docker/host-x86_64/wasm32/Dockerfile | 3 ++- src/ci/docker/host-x86_64/x86_64-gnu-aux/Dockerfile | 3 ++- src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile | 3 ++- src/ci/docker/host-x86_64/x86_64-gnu-distcheck/Dockerfile | 3 ++- .../host-x86_64/x86_64-gnu-llvm-13-stage1/Dockerfile | 3 ++- src/ci/docker/host-x86_64/x86_64-gnu-llvm-13/Dockerfile | 8 ++++---- src/ci/docker/host-x86_64/x86_64-gnu-nopt/Dockerfile | 3 ++- src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile | 6 +++--- src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile | 3 ++- 19 files changed, 43 insertions(+), 27 deletions(-) diff --git a/src/ci/docker/host-aarch64/aarch64-gnu/Dockerfile b/src/ci/docker/host-aarch64/aarch64-gnu/Dockerfile index e54d0eafb400..699938c37184 100644 --- a/src/ci/docker/host-aarch64/aarch64-gnu/Dockerfile +++ b/src/ci/docker/host-aarch64/aarch64-gnu/Dockerfile @@ -14,7 +14,8 @@ RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-ins gdb \ libssl-dev \ pkg-config \ - xz-utils + xz-utils \ + && rm -rf /var/lib/apt/lists/* COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh diff --git a/src/ci/docker/host-x86_64/dist-i686-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-i686-linux/Dockerfile index cd86d9fb584f..ea4a2a2427db 100644 --- a/src/ci/docker/host-x86_64/dist-i686-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-i686-linux/Dockerfile @@ -32,7 +32,8 @@ RUN yum upgrade -y && \ wget \ xz \ zlib-devel.i686 \ - zlib-devel.x86_64 + zlib-devel.x86_64 \ + && yum clean all RUN mkdir -p /rustroot/bin && ln -s /usr/bin/cmake3 /rustroot/bin/cmake diff --git a/src/ci/docker/host-x86_64/dist-x86_64-freebsd/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-freebsd/Dockerfile index f9b1fa8951ad..377d4a9ce5eb 100644 --- a/src/ci/docker/host-x86_64/dist-x86_64-freebsd/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-x86_64-freebsd/Dockerfile @@ -15,7 +15,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ xz-utils \ wget \ libssl-dev \ - pkg-config + pkg-config \ + && rm -rf /var/lib/apt/lists/* COPY scripts/freebsd-toolchain.sh /tmp/ RUN /tmp/freebsd-toolchain.sh x86_64 diff --git a/src/ci/docker/host-x86_64/dist-x86_64-illumos/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-illumos/Dockerfile index c2e44ead51ee..4e46bdee5acb 100644 --- a/src/ci/docker/host-x86_64/dist-x86_64-illumos/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-x86_64-illumos/Dockerfile @@ -11,7 +11,8 @@ RUN apt-get update && \ apt-get install -y --no-install-recommends \ libgmp-dev \ libmpfr-dev \ - libmpc-dev + libmpc-dev \ + && rm -rf /var/lib/apt/lists/* COPY scripts/illumos-toolchain.sh /tmp/ diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile index 423aba06ccaf..6bdc88e18f53 100644 --- a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile @@ -32,7 +32,8 @@ RUN yum upgrade -y && \ wget \ xz \ zlib-devel.i686 \ - zlib-devel.x86_64 + zlib-devel.x86_64 \ + && yum clean all RUN mkdir -p /rustroot/bin && ln -s /usr/bin/cmake3 /rustroot/bin/cmake diff --git a/src/ci/docker/host-x86_64/dist-x86_64-musl/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-musl/Dockerfile index 51645a81853f..13eaf7fce8cd 100644 --- a/src/ci/docker/host-x86_64/dist-x86_64-musl/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-x86_64-musl/Dockerfile @@ -16,7 +16,8 @@ RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-ins gdb \ patch \ libssl-dev \ - pkg-config + pkg-config \ + && rm -rf /var/lib/apt/lists/* WORKDIR /build/ diff --git a/src/ci/docker/host-x86_64/i686-gnu-nopt/Dockerfile b/src/ci/docker/host-x86_64/i686-gnu-nopt/Dockerfile index dd74726f8569..e2b66c2cff1d 100644 --- a/src/ci/docker/host-x86_64/i686-gnu-nopt/Dockerfile +++ b/src/ci/docker/host-x86_64/i686-gnu-nopt/Dockerfile @@ -15,7 +15,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ gdb \ zlib1g-dev \ lib32z1-dev \ - xz-utils + xz-utils \ + && rm -rf /var/lib/apt/lists/* COPY scripts/sccache.sh /scripts/ diff --git a/src/ci/docker/host-x86_64/i686-gnu/Dockerfile b/src/ci/docker/host-x86_64/i686-gnu/Dockerfile index 0c36cfd66bde..cb6559707d96 100644 --- a/src/ci/docker/host-x86_64/i686-gnu/Dockerfile +++ b/src/ci/docker/host-x86_64/i686-gnu/Dockerfile @@ -15,7 +15,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ gdb \ zlib1g-dev \ lib32z1-dev \ - xz-utils + xz-utils \ + && rm -rf /var/lib/apt/lists/* COPY scripts/sccache.sh /scripts/ diff --git a/src/ci/docker/host-x86_64/mingw-check/Dockerfile b/src/ci/docker/host-x86_64/mingw-check/Dockerfile index 52a7776153da..40caa7c50135 100644 --- a/src/ci/docker/host-x86_64/mingw-check/Dockerfile +++ b/src/ci/docker/host-x86_64/mingw-check/Dockerfile @@ -20,20 +20,20 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ xz-utils \ libssl-dev \ pkg-config \ - mingw-w64 + mingw-w64 \ + && rm -rf /var/lib/apt/lists/* RUN curl -sL https://nodejs.org/dist/v16.9.0/node-v16.9.0-linux-x64.tar.xz | tar -xJ ENV PATH="/node-v16.9.0-linux-x64/bin:${PATH}" # Install es-check # Pin its version to prevent unrelated CI failures due to future es-check versions. -RUN npm install es-check@6.1.1 -g -RUN npm install eslint@8.6.0 -g +RUN npm install es-check@6.1.1 eslint@8.6.0 -g COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh COPY host-x86_64/mingw-check/reuse-requirements.txt /tmp/ -RUN pip3 install --no-deps --require-hashes -r /tmp/reuse-requirements.txt +RUN pip3 install --no-deps --no-cache-dir --require-hashes -r /tmp/reuse-requirements.txt COPY host-x86_64/mingw-check/validate-toolstate.sh /scripts/ COPY host-x86_64/mingw-check/validate-error-codes.sh /scripts/ diff --git a/src/ci/docker/host-x86_64/test-various/Dockerfile b/src/ci/docker/host-x86_64/test-various/Dockerfile index 7c09e3a582fd..cf4451f8b33b 100644 --- a/src/ci/docker/host-x86_64/test-various/Dockerfile +++ b/src/ci/docker/host-x86_64/test-various/Dockerfile @@ -21,7 +21,8 @@ RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-ins ovmf \ qemu-efi-aarch64 \ qemu-system-arm \ - qemu-system-x86 + qemu-system-x86 \ + && rm -rf /var/lib/apt/lists/* RUN curl -sL https://nodejs.org/dist/v15.14.0/node-v15.14.0-linux-x64.tar.xz | \ tar -xJ diff --git a/src/ci/docker/host-x86_64/wasm32/Dockerfile b/src/ci/docker/host-x86_64/wasm32/Dockerfile index 9e37c2822e8b..ef1fde1c3b92 100644 --- a/src/ci/docker/host-x86_64/wasm32/Dockerfile +++ b/src/ci/docker/host-x86_64/wasm32/Dockerfile @@ -13,7 +13,8 @@ RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-ins sudo \ gdb \ xz-utils \ - bzip2 + bzip2 \ + && rm -rf /var/lib/apt/lists/* COPY scripts/emscripten.sh /scripts/ RUN bash /scripts/emscripten.sh diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-aux/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-aux/Dockerfile index d55d5b56ad3f..e08c4e1e8b7d 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-aux/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-aux/Dockerfile @@ -19,7 +19,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ llvm-dev \ libfreetype6-dev \ libexpat1-dev \ - tidy + tidy \ + && rm -rf /var/lib/apt/lists/* COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile index 739045248fea..c2b002055a8f 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile @@ -23,7 +23,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ pkg-config \ xz-utils \ lld \ - clang + clang \ + && rm -rf /var/lib/apt/lists/* COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-distcheck/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-distcheck/Dockerfile index 80a004501a81..7e640c49f015 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-distcheck/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-distcheck/Dockerfile @@ -15,7 +15,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ gdb \ xz-utils \ libssl-dev \ - pkg-config + pkg-config \ + && rm -rf /var/lib/apt/lists/* COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-13-stage1/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-13-stage1/Dockerfile index 23f2215c2d93..16976a9428ef 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-13-stage1/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-13-stage1/Dockerfile @@ -21,7 +21,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ pkg-config \ zlib1g-dev \ xz-utils \ - nodejs + nodejs \ + && rm -rf /var/lib/apt/lists/* COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-13/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-13/Dockerfile index 8f6831bc54e6..c3b47c3510d4 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-13/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-13/Dockerfile @@ -24,15 +24,15 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ pkg-config \ zlib1g-dev \ xz-utils \ - nodejs + nodejs \ # Install powershell so we can test x.ps1 on Linux -RUN apt-get update && \ - apt-get install -y apt-transport-https software-properties-common && \ + apt-transport-https software-properties-common && \ curl -s "https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/packages-microsoft-prod.deb" > packages-microsoft-prod.deb && \ dpkg -i packages-microsoft-prod.deb && \ apt-get update && \ - apt-get install -y powershell + apt-get install -y powershell \ + && rm -rf /var/lib/apt/lists/* COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-nopt/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-nopt/Dockerfile index 77510d7ac62d..9fdc78406fbd 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-nopt/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-nopt/Dockerfile @@ -15,7 +15,8 @@ RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-ins gdb \ libssl-dev \ pkg-config \ - xz-utils + xz-utils \ + && rm -rf /var/lib/apt/lists/* COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile index 4350ca205862..501d27816462 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile @@ -14,10 +14,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ libssl-dev \ sudo \ xz-utils \ - tidy + tidy \ # Install dependencies for chromium browser -RUN apt-get install -y \ gconf-service \ libasound2 \ libatk1.0-0 \ @@ -56,7 +55,8 @@ RUN apt-get install -y \ libnss3 \ lsb-release \ xdg-utils \ - wget + wget \ + && rm -rf /var/lib/apt/lists/* COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh diff --git a/src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile index 88c182a4d431..5b9581f72a64 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile @@ -15,7 +15,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ gdb \ libssl-dev \ pkg-config \ - xz-utils + xz-utils \ + && rm -rf /var/lib/apt/lists/* COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh From 3a58309798e39ab48e4cb85c1013ad7e7410ace8 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Fri, 2 Dec 2022 15:14:49 +0100 Subject: [PATCH 036/115] Add StableOrd trait as proposed in MCP 533. The StableOrd trait can be used to mark types as having a stable sort order across compilation sessions. Collections that sort their items in a stable way can safely implement HashStable by hashing items in sort order. --- compiler/rustc_abi/src/lib.rs | 7 ++ .../rustc_data_structures/src/fingerprint.rs | 2 +- .../rustc_data_structures/src/sorted_map.rs | 4 +- .../src/sorted_map/index_map.rs | 9 +- .../src/stable_hasher.rs | 99 +++++++++++++------ compiler/rustc_hir/src/hir_id.rs | 6 +- compiler/rustc_session/src/config.rs | 5 +- 7 files changed, 96 insertions(+), 36 deletions(-) diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 85693259cd01..e14c9ea9a5d1 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -9,6 +9,8 @@ use std::ops::{Add, AddAssign, Mul, RangeInclusive, Sub}; use std::str::FromStr; use bitflags::bitflags; +#[cfg(feature = "nightly")] +use rustc_data_structures::stable_hasher::StableOrd; use rustc_index::vec::{Idx, IndexVec}; #[cfg(feature = "nightly")] use rustc_macros::HashStable_Generic; @@ -403,6 +405,11 @@ pub struct Size { raw: u64, } +// Safety: Ord is implement as just comparing numerical values and numerical values +// are not changed by (de-)serialization. +#[cfg(feature = "nightly")] +unsafe impl StableOrd for Size {} + // This is debug-printed a lot in larger structs, don't waste too much space there impl fmt::Debug for Size { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { diff --git a/compiler/rustc_data_structures/src/fingerprint.rs b/compiler/rustc_data_structures/src/fingerprint.rs index a39178016ce2..6f0b9bff90a7 100644 --- a/compiler/rustc_data_structures/src/fingerprint.rs +++ b/compiler/rustc_data_structures/src/fingerprint.rs @@ -140,7 +140,7 @@ impl stable_hasher::StableHasherResult for Fingerprint { } } -impl_stable_hash_via_hash!(Fingerprint); +impl_stable_ord_and_stable_hash_via_hash!(Fingerprint); impl Encodable for Fingerprint { #[inline] diff --git a/compiler/rustc_data_structures/src/sorted_map.rs b/compiler/rustc_data_structures/src/sorted_map.rs index d607a5c8314e..d13313dfd0eb 100644 --- a/compiler/rustc_data_structures/src/sorted_map.rs +++ b/compiler/rustc_data_structures/src/sorted_map.rs @@ -1,4 +1,4 @@ -use crate::stable_hasher::{HashStable, StableHasher}; +use crate::stable_hasher::{HashStable, StableHasher, StableOrd}; use std::borrow::Borrow; use std::cmp::Ordering; use std::iter::FromIterator; @@ -308,7 +308,7 @@ impl FromIterator<(K, V)> for SortedMap { } } -impl, V: HashStable, CTX> HashStable for SortedMap { +impl + StableOrd, V: HashStable, CTX> HashStable for SortedMap { #[inline] fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { self.data.hash_stable(ctx, hasher); diff --git a/compiler/rustc_data_structures/src/sorted_map/index_map.rs b/compiler/rustc_data_structures/src/sorted_map/index_map.rs index 0ec32dc43070..c2f0ae328962 100644 --- a/compiler/rustc_data_structures/src/sorted_map/index_map.rs +++ b/compiler/rustc_data_structures/src/sorted_map/index_map.rs @@ -120,13 +120,20 @@ where self.items.hash(hasher) } } + impl HashStable for SortedIndexMultiMap where K: HashStable, V: HashStable, { fn hash_stable(&self, ctx: &mut C, hasher: &mut StableHasher) { - self.items.hash_stable(ctx, hasher) + let SortedIndexMultiMap { + items, + // We can ignore this field because it is not observable from the outside. + idx_sorted_by_item_key: _, + } = self; + + items.hash_stable(ctx, hasher) } } diff --git a/compiler/rustc_data_structures/src/stable_hasher.rs b/compiler/rustc_data_structures/src/stable_hasher.rs index e2c33e7e0626..d43b74c2740c 100644 --- a/compiler/rustc_data_structures/src/stable_hasher.rs +++ b/compiler/rustc_data_structures/src/stable_hasher.rs @@ -219,7 +219,35 @@ pub trait ToStableHashKey { fn to_stable_hash_key(&self, hcx: &HCX) -> Self::KeyType; } -/// Implement HashStable by just calling `Hash::hash()`. +/// Trait for marking a type as having a sort order that is +/// stable across compilation session boundaries. More formally: +/// +/// ```txt +/// Ord::cmp(a1, b1) == Ord:cmp(a2, b2) +/// where a2 = decode(encode(a1, context1), context2) +/// b2 = decode(encode(b1, context1), context2) +/// ``` +/// +/// i.e. the result of `Ord::cmp` is not influenced by encoding +/// the values in one session and then decoding them in another +/// session. +/// +/// This is trivially true for types where encoding and decoding +/// don't change the bytes of the values that are used during +/// comparison and comparison only depends on these bytes (as +/// opposed to some non-local state). Examples are u32, String, +/// Path, etc. +/// +/// But it is not true for: +/// - `*const T` and `*mut T` because the values of these pointers +/// will change between sessions. +/// - `DefIndex`, `CrateNum`, `LocalDefId`, because their concrete +/// values depend on state that might be different between +/// compilation sessions. +pub unsafe trait StableOrd: Ord {} + +/// Implement HashStable by just calling `Hash::hash()`. Also implement `StableOrd` for the type since +/// that has the same requirements. /// /// **WARNING** This is only valid for types that *really* don't need any context for fingerprinting. /// But it is easy to misuse this macro (see [#96013](https://github.com/rust-lang/rust/issues/96013) @@ -227,7 +255,7 @@ pub trait ToStableHashKey { /// here in this module. /// /// Use `#[derive(HashStable_Generic)]` instead. -macro_rules! impl_stable_hash_via_hash { +macro_rules! impl_stable_ord_and_stable_hash_via_hash { ($t:ty) => { impl $crate::stable_hasher::HashStable for $t { #[inline] @@ -235,26 +263,28 @@ macro_rules! impl_stable_hash_via_hash { ::std::hash::Hash::hash(self, hasher); } } + + unsafe impl $crate::stable_hasher::StableOrd for $t {} }; } -impl_stable_hash_via_hash!(i8); -impl_stable_hash_via_hash!(i16); -impl_stable_hash_via_hash!(i32); -impl_stable_hash_via_hash!(i64); -impl_stable_hash_via_hash!(isize); +impl_stable_ord_and_stable_hash_via_hash!(i8); +impl_stable_ord_and_stable_hash_via_hash!(i16); +impl_stable_ord_and_stable_hash_via_hash!(i32); +impl_stable_ord_and_stable_hash_via_hash!(i64); +impl_stable_ord_and_stable_hash_via_hash!(isize); -impl_stable_hash_via_hash!(u8); -impl_stable_hash_via_hash!(u16); -impl_stable_hash_via_hash!(u32); -impl_stable_hash_via_hash!(u64); -impl_stable_hash_via_hash!(usize); +impl_stable_ord_and_stable_hash_via_hash!(u8); +impl_stable_ord_and_stable_hash_via_hash!(u16); +impl_stable_ord_and_stable_hash_via_hash!(u32); +impl_stable_ord_and_stable_hash_via_hash!(u64); +impl_stable_ord_and_stable_hash_via_hash!(usize); -impl_stable_hash_via_hash!(u128); -impl_stable_hash_via_hash!(i128); +impl_stable_ord_and_stable_hash_via_hash!(u128); +impl_stable_ord_and_stable_hash_via_hash!(i128); -impl_stable_hash_via_hash!(char); -impl_stable_hash_via_hash!(()); +impl_stable_ord_and_stable_hash_via_hash!(char); +impl_stable_ord_and_stable_hash_via_hash!(()); impl HashStable for ! { fn hash_stable(&self, _ctx: &mut CTX, _hasher: &mut StableHasher) { @@ -444,6 +474,10 @@ impl HashStable for String { } } +// Safety: String comparison only depends on their contents and the +// contents are not changed by (de-)serialization. +unsafe impl StableOrd for String {} + impl ToStableHashKey for String { type KeyType = String; #[inline] @@ -459,6 +493,9 @@ impl HashStable for bool { } } +// Safety: sort order of bools is not changed by (de-)serialization. +unsafe impl StableOrd for bool {} + impl HashStable for Option where T: HashStable, @@ -474,6 +511,9 @@ where } } +// Safety: the Option wrapper does not add instability to comparison. +unsafe impl StableOrd for Option {} + impl HashStable for Result where T1: HashStable, @@ -550,8 +590,8 @@ where } } -impl_stable_hash_via_hash!(::std::path::Path); -impl_stable_hash_via_hash!(::std::path::PathBuf); +impl_stable_ord_and_stable_hash_via_hash!(::std::path::Path); +impl_stable_ord_and_stable_hash_via_hash!(::std::path::PathBuf); impl HashStable for ::std::collections::HashMap where @@ -584,27 +624,26 @@ where impl HashStable for ::std::collections::BTreeMap where - K: ToStableHashKey, + K: HashStable + StableOrd, V: HashStable, { fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) { - stable_hash_reduce(hcx, hasher, self.iter(), self.len(), |hasher, hcx, (key, value)| { - let key = key.to_stable_hash_key(hcx); - key.hash_stable(hcx, hasher); - value.hash_stable(hcx, hasher); - }); + self.len().hash_stable(hcx, hasher); + for entry in self.iter() { + entry.hash_stable(hcx, hasher); + } } } -impl HashStable for ::std::collections::BTreeSet +impl HashStable for ::std::collections::BTreeSet where - K: ToStableHashKey, + K: HashStable + StableOrd, { fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) { - stable_hash_reduce(hcx, hasher, self.iter(), self.len(), |hasher, hcx, key| { - let key = key.to_stable_hash_key(hcx); - key.hash_stable(hcx, hasher); - }); + self.len().hash_stable(hcx, hasher); + for entry in self.iter() { + entry.hash_stable(hcx, hasher); + } } } diff --git a/compiler/rustc_hir/src/hir_id.rs b/compiler/rustc_hir/src/hir_id.rs index 33f02a115ef3..9f7e79596e94 100644 --- a/compiler/rustc_hir/src/hir_id.rs +++ b/compiler/rustc_hir/src/hir_id.rs @@ -1,5 +1,5 @@ use crate::def_id::{DefId, DefIndex, LocalDefId, CRATE_DEF_ID}; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey}; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableOrd, ToStableHashKey}; use rustc_span::{def_id::DefPathHash, HashStableContext}; use std::fmt; @@ -146,6 +146,10 @@ impl ItemLocalId { pub const INVALID: ItemLocalId = ItemLocalId::MAX; } +// Safety: Ord is implement as just comparing the LocalItemId's numerical +// values and these are not changed by (de-)serialization. +unsafe impl StableOrd for ItemLocalId {} + /// The `HirId` corresponding to `CRATE_NODE_ID` and `CRATE_DEF_ID`. pub const CRATE_HIR_ID: HirId = HirId { owner: OwnerId { def_id: CRATE_DEF_ID }, local_id: ItemLocalId::from_u32(0) }; diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 927810351e95..5dcd53e8e516 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -10,7 +10,7 @@ use crate::{lint, HashStableContext}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_data_structures::stable_hasher::ToStableHashKey; +use rustc_data_structures::stable_hasher::{StableOrd, ToStableHashKey}; use rustc_target::abi::Align; use rustc_target::spec::{PanicStrategy, SanitizerSet, SplitDebuginfo}; use rustc_target::spec::{Target, TargetTriple, TargetWarnings, TARGETS}; @@ -288,6 +288,9 @@ pub enum OutputType { DepInfo, } +// Safety: Trivial C-Style enums have a stable sort order across compilation sessions. +unsafe impl StableOrd for OutputType {} + impl ToStableHashKey for OutputType { type KeyType = Self; From 4c73b646328d4adeb66fe67bae57c8206803eef8 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Fri, 2 Dec 2022 16:40:57 +0000 Subject: [PATCH 037/115] Use proper HirId for async track_caller attribute check --- compiler/rustc_ast_lowering/src/expr.rs | 30 ++++++++++--------- compiler/rustc_ast_lowering/src/item.rs | 24 +++++++++++---- .../async-await/track-caller/issue-105134.rs | 11 +++++++ 3 files changed, 45 insertions(+), 20 deletions(-) create mode 100644 src/test/ui/async-await/track-caller/issue-105134.rs diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 82912a733d55..2d7cd067e08a 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -147,6 +147,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ), ExprKind::Async(capture_clause, closure_node_id, block) => self.make_async_expr( *capture_clause, + None, *closure_node_id, None, e.span, @@ -581,6 +582,7 @@ impl<'hir> LoweringContext<'_, 'hir> { pub(super) fn make_async_expr( &mut self, capture_clause: CaptureBy, + outer_hir_id: Option, closure_node_id: NodeId, ret_ty: Option>, span: Span, @@ -647,18 +649,20 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::ExprKind::Closure(c) }; - let parent_has_track_caller = self - .attrs - .values() - .find(|attrs| attrs.into_iter().find(|attr| attr.has_name(sym::track_caller)).is_some()) - .is_some(); - let unstable_span = - self.mark_span_with_reason(DesugaringKind::Async, span, self.allow_gen_future.clone()); - let hir_id = if parent_has_track_caller { - let generator_hir_id = self.lower_node_id(closure_node_id); + let track_caller = outer_hir_id + .and_then(|id| self.attrs.get(&id.local_id)) + .map_or(false, |attrs| attrs.into_iter().any(|attr| attr.has_name(sym::track_caller))); + + let hir_id = self.lower_node_id(closure_node_id); + if track_caller { + let unstable_span = self.mark_span_with_reason( + DesugaringKind::Async, + span, + self.allow_gen_future.clone(), + ); self.lower_attrs( - generator_hir_id, + hir_id, &[Attribute { kind: AttrKind::Normal(ptr::P(NormalAttr { item: AttrItem { @@ -673,10 +677,7 @@ impl<'hir> LoweringContext<'_, 'hir> { span: unstable_span, }], ); - generator_hir_id - } else { - self.lower_node_id(closure_node_id) - }; + } let generator = hir::Expr { hir_id, kind: generator_kind, span: self.lower_span(span) }; @@ -1012,6 +1013,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let async_body = this.make_async_expr( capture_clause, + None, inner_closure_id, async_ret_ty, body.span, diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 2b47e9089129..b66923a91f68 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -268,8 +268,13 @@ impl<'hir> LoweringContext<'_, 'hir> { // only cares about the input argument patterns in the function // declaration (decl), not the return types. let asyncness = header.asyncness; - let body_id = - this.lower_maybe_async_body(span, &decl, asyncness, body.as_deref()); + let body_id = this.lower_maybe_async_body( + span, + hir_id, + &decl, + asyncness, + body.as_deref(), + ); let mut itctx = ImplTraitContext::Universal; let (generics, decl) = this.lower_generics(generics, id, &mut itctx, |this| { @@ -789,7 +794,7 @@ impl<'hir> LoweringContext<'_, 'hir> { AssocItemKind::Fn(box Fn { sig, generics, body: Some(body), .. }) => { let asyncness = sig.header.asyncness; let body_id = - self.lower_maybe_async_body(i.span, &sig.decl, asyncness, Some(&body)); + self.lower_maybe_async_body(i.span, hir_id, &sig.decl, asyncness, Some(&body)); let (generics, sig) = self.lower_method_sig( generics, sig, @@ -863,6 +868,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // Since `default impl` is not yet implemented, this is always true in impls. let has_value = true; let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value); + let hir_id = self.lower_node_id(i.id); let (generics, kind) = match &i.kind { AssocItemKind::Const(_, ty, expr) => { @@ -875,8 +881,13 @@ impl<'hir> LoweringContext<'_, 'hir> { AssocItemKind::Fn(box Fn { sig, generics, body, .. }) => { self.current_item = Some(i.span); let asyncness = sig.header.asyncness; - let body_id = - self.lower_maybe_async_body(i.span, &sig.decl, asyncness, body.as_deref()); + let body_id = self.lower_maybe_async_body( + i.span, + hir_id, + &sig.decl, + asyncness, + body.as_deref(), + ); let (generics, sig) = self.lower_method_sig( generics, sig, @@ -909,7 +920,6 @@ impl<'hir> LoweringContext<'_, 'hir> { AssocItemKind::MacCall(..) => panic!("`TyMac` should have been expanded by now"), }; - let hir_id = self.lower_node_id(i.id); self.lower_attrs(hir_id, &i.attrs); let item = hir::ImplItem { owner_id: hir_id.expect_owner(), @@ -1043,6 +1053,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_maybe_async_body( &mut self, span: Span, + fn_id: hir::HirId, decl: &FnDecl, asyncness: Async, body: Option<&Block>, @@ -1193,6 +1204,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let async_expr = this.make_async_expr( CaptureBy::Value, + Some(fn_id), closure_id, None, body.span, diff --git a/src/test/ui/async-await/track-caller/issue-105134.rs b/src/test/ui/async-await/track-caller/issue-105134.rs new file mode 100644 index 000000000000..4e52b8e250b9 --- /dev/null +++ b/src/test/ui/async-await/track-caller/issue-105134.rs @@ -0,0 +1,11 @@ +// check-pass +// edition:2021 + +#[track_caller] +fn f() { + let _ = async {}; +} + +fn main() { + f(); +} From ec4080b23699d096561e2e6163f3f74f6f9e8b4d Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Fri, 2 Dec 2022 16:41:25 +0000 Subject: [PATCH 038/115] Fix async track caller for assoc fn and trait impl fn --- compiler/rustc_ast_lowering/src/item.rs | 4 ++-- .../async-await/track-caller/panic-track-caller.rs | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index b66923a91f68..7ad6ba6ed735 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -771,6 +771,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> { let hir_id = self.lower_node_id(i.id); + self.lower_attrs(hir_id, &i.attrs); let trait_item_def_id = hir_id.expect_owner(); let (generics, kind, has_default) = match &i.kind { @@ -829,7 +830,6 @@ impl<'hir> LoweringContext<'_, 'hir> { AssocItemKind::MacCall(..) => panic!("macro item shouldn't exist at this point"), }; - self.lower_attrs(hir_id, &i.attrs); let item = hir::TraitItem { owner_id: trait_item_def_id, ident: self.lower_ident(i.ident), @@ -869,6 +869,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let has_value = true; let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value); let hir_id = self.lower_node_id(i.id); + self.lower_attrs(hir_id, &i.attrs); let (generics, kind) = match &i.kind { AssocItemKind::Const(_, ty, expr) => { @@ -920,7 +921,6 @@ impl<'hir> LoweringContext<'_, 'hir> { AssocItemKind::MacCall(..) => panic!("`TyMac` should have been expanded by now"), }; - self.lower_attrs(hir_id, &i.attrs); let item = hir::ImplItem { owner_id: hir_id.expect_owner(), ident: self.lower_ident(i.ident), diff --git a/src/test/ui/async-await/track-caller/panic-track-caller.rs b/src/test/ui/async-await/track-caller/panic-track-caller.rs index b113c56412ff..5ebfeb3f36ac 100644 --- a/src/test/ui/async-await/track-caller/panic-track-caller.rs +++ b/src/test/ui/async-await/track-caller/panic-track-caller.rs @@ -54,6 +54,19 @@ async fn foo_track_caller() { bar_track_caller().await } +struct Foo; + +impl Foo { + #[track_caller] + async fn bar_assoc() { + panic!(); + } +} + +async fn foo_assoc() { + Foo::bar_assoc().await +} + fn panicked_at(f: impl FnOnce() + panic::UnwindSafe) -> u32 { let loc = Arc::new(Mutex::new(None)); @@ -73,4 +86,5 @@ fn panicked_at(f: impl FnOnce() + panic::UnwindSafe) -> u32 { fn main() { assert_eq!(panicked_at(|| block_on(foo())), 41); assert_eq!(panicked_at(|| block_on(foo_track_caller())), 54); + assert_eq!(panicked_at(|| block_on(foo_assoc())), 67); } From c38ff3b3853dabcd524ba0e3faf2521e2172af38 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Sat, 3 Dec 2022 12:28:01 +0000 Subject: [PATCH 039/115] Remove all but one call site of `prepare_outputs` and fetch the value from the TyCtxt instead --- compiler/rustc_interface/src/passes.rs | 6 ++---- compiler/rustc_interface/src/queries.rs | 14 ++++++++------ compiler/rustc_metadata/src/fs.rs | 10 ++++------ compiler/rustc_mir_transform/src/dump_mir.rs | 6 +++--- 4 files changed, 17 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 7f1d21bf1d8b..77c3270fe6a0 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -968,12 +968,10 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { pub fn start_codegen<'tcx>( codegen_backend: &dyn CodegenBackend, tcx: TyCtxt<'tcx>, - outputs: &OutputFilenames, ) -> Box { info!("Pre-codegen\n{:?}", tcx.debug_stats()); - let (metadata, need_metadata_module) = - rustc_metadata::fs::encode_and_write_metadata(tcx, outputs); + let (metadata, need_metadata_module) = rustc_metadata::fs::encode_and_write_metadata(tcx); let codegen = tcx.sess.time("codegen_crate", move || { codegen_backend.codegen_crate(tcx, metadata, need_metadata_module) @@ -989,7 +987,7 @@ pub fn start_codegen<'tcx>( info!("Post-codegen\n{:?}", tcx.debug_stats()); if tcx.sess.opts.output_types.contains_key(&OutputType::Mir) { - if let Err(error) = rustc_mir_transform::dump_mir::emit_mir(tcx, outputs) { + if let Err(error) = rustc_mir_transform::dump_mir::emit_mir(tcx) { tcx.sess.emit_err(CantEmitMIR { error }); tcx.sess.abort_if_errors(); } diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index fc0b11183f7b..f5ddd647b243 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -20,6 +20,7 @@ use rustc_span::symbol::sym; use std::any::Any; use std::cell::{Ref, RefCell, RefMut}; use std::rc::Rc; +use std::sync::Arc; /// Represent the result of a query. /// @@ -214,7 +215,7 @@ impl<'tcx> Queries<'tcx> { pub fn global_ctxt(&'tcx self) -> Result<&Query>> { self.global_ctxt.compute(|| { let crate_name = self.crate_name()?.peek().clone(); - let outputs = self.prepare_outputs()?.peek().clone(); + let outputs = self.prepare_outputs()?.take(); let dep_graph = self.dep_graph()?.peek().clone(); let (krate, resolver, lint_store) = self.expansion()?.take(); Ok(passes::create_global_ctxt( @@ -235,7 +236,6 @@ impl<'tcx> Queries<'tcx> { pub fn ongoing_codegen(&'tcx self) -> Result<&Query>> { self.ongoing_codegen.compute(|| { - let outputs = self.prepare_outputs()?; self.global_ctxt()?.peek_mut().enter(|tcx| { tcx.analysis(()).ok(); @@ -249,7 +249,7 @@ impl<'tcx> Queries<'tcx> { // Hook for UI tests. Self::check_for_rustc_errors_attr(tcx); - Ok(passes::start_codegen(&***self.codegen_backend(), tcx, &*outputs.peek())) + Ok(passes::start_codegen(&***self.codegen_backend(), tcx)) }) }) } @@ -293,8 +293,10 @@ impl<'tcx> Queries<'tcx> { let codegen_backend = self.codegen_backend().clone(); let dep_graph = self.dep_graph()?.peek().clone(); - let prepare_outputs = self.prepare_outputs()?.take(); - let crate_hash = self.global_ctxt()?.peek_mut().enter(|tcx| tcx.crate_hash(LOCAL_CRATE)); + let (crate_hash, prepare_outputs) = self + .global_ctxt()? + .peek_mut() + .enter(|tcx| (tcx.crate_hash(LOCAL_CRATE), tcx.output_filenames(()).clone())); let ongoing_codegen = self.ongoing_codegen()?.take(); Ok(Linker { @@ -316,7 +318,7 @@ pub struct Linker { // compilation outputs dep_graph: DepGraph, - prepare_outputs: OutputFilenames, + prepare_outputs: Arc, crate_hash: Svh, ongoing_codegen: Box, } diff --git a/compiler/rustc_metadata/src/fs.rs b/compiler/rustc_metadata/src/fs.rs index c41ae8d55cda..4fa440c7ca69 100644 --- a/compiler/rustc_metadata/src/fs.rs +++ b/compiler/rustc_metadata/src/fs.rs @@ -6,7 +6,7 @@ use crate::{encode_metadata, EncodedMetadata}; use rustc_data_structures::temp_dir::MaybeTempDir; use rustc_hir::def_id::LOCAL_CRATE; use rustc_middle::ty::TyCtxt; -use rustc_session::config::{CrateType, OutputFilenames, OutputType}; +use rustc_session::config::{CrateType, OutputType}; use rustc_session::output::filename_for_metadata; use rustc_session::Session; use tempfile::Builder as TempFileBuilder; @@ -38,10 +38,7 @@ pub fn emit_wrapper_file( out_filename } -pub fn encode_and_write_metadata( - tcx: TyCtxt<'_>, - outputs: &OutputFilenames, -) -> (EncodedMetadata, bool) { +pub fn encode_and_write_metadata(tcx: TyCtxt<'_>) -> (EncodedMetadata, bool) { #[derive(PartialEq, Eq, PartialOrd, Ord)] enum MetadataKind { None, @@ -64,7 +61,8 @@ pub fn encode_and_write_metadata( .unwrap_or(MetadataKind::None); let crate_name = tcx.crate_name(LOCAL_CRATE); - let out_filename = filename_for_metadata(tcx.sess, crate_name.as_str(), outputs); + let out_filename = + filename_for_metadata(tcx.sess, crate_name.as_str(), tcx.output_filenames(())); // To avoid races with another rustc process scanning the output directory, // we need to write the file somewhere else and atomically move it to its // final destination, with an `fs::rename` call. In order for the rename to diff --git a/compiler/rustc_mir_transform/src/dump_mir.rs b/compiler/rustc_mir_transform/src/dump_mir.rs index 6b995141a2be..7b5cf39a02c4 100644 --- a/compiler/rustc_mir_transform/src/dump_mir.rs +++ b/compiler/rustc_mir_transform/src/dump_mir.rs @@ -8,7 +8,7 @@ use crate::MirPass; use rustc_middle::mir::write_mir_pretty; use rustc_middle::mir::Body; use rustc_middle::ty::TyCtxt; -use rustc_session::config::{OutputFilenames, OutputType}; +use rustc_session::config::OutputType; pub struct Marker(pub &'static str); @@ -20,8 +20,8 @@ impl<'tcx> MirPass<'tcx> for Marker { fn run_pass(&self, _tcx: TyCtxt<'tcx>, _body: &mut Body<'tcx>) {} } -pub fn emit_mir(tcx: TyCtxt<'_>, outputs: &OutputFilenames) -> io::Result<()> { - let path = outputs.path(OutputType::Mir); +pub fn emit_mir(tcx: TyCtxt<'_>) -> io::Result<()> { + let path = tcx.output_filenames(()).path(OutputType::Mir); let mut f = io::BufWriter::new(File::create(&path)?); write_mir_pretty(tcx, None, &mut f)?; Ok(()) From 51ac2af99ffd46cf83760ceef2404dad0ce238a9 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 3 Dec 2022 13:33:00 +0100 Subject: [PATCH 040/115] interpret: clobber return place when calling function --- compiler/rustc_const_eval/src/interpret/eval_context.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index 79450fccfc4d..e17d3e516a64 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -676,6 +676,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { return_to_block: StackPopCleanup, ) -> InterpResult<'tcx> { trace!("body: {:#?}", body); + // Clobber previous return place contents, nobody is supposed to be able to see them any more + // This also checks dereferenceable, but not align. We rely on all constructed places being + // sufficiently aligned (in particular we rely on `deref_operand` checking alignment). + self.write_uninit(return_place)?; // first push a stack frame so we have access to the local substs let pre_frame = Frame { body, From 71cf89223501223eb038421867f6afaa83d063e1 Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Sat, 3 Dec 2022 19:01:55 +0000 Subject: [PATCH 041/115] std update libc version and freebsd image build dependencies --- Cargo.lock | 4 ++-- library/std/Cargo.toml | 2 +- src/ci/docker/scripts/freebsd-toolchain.sh | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d56ac132b6f6..295c13d2b3bc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2085,9 +2085,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.135" +version = "0.2.138" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68783febc7782c6c5cb401fbda4de5a9898be1762314da0bb2c10ced61f18b0c" +checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8" dependencies = [ "rustc-std-workspace-core", ] diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index c10bfde4ddf7..a7aefc26b97c 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -15,7 +15,7 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] } panic_unwind = { path = "../panic_unwind", optional = true } panic_abort = { path = "../panic_abort" } core = { path = "../core" } -libc = { version = "0.2.135", default-features = false, features = ['rustc-dep-of-std'] } +libc = { version = "0.2.138", default-features = false, features = ['rustc-dep-of-std'] } compiler_builtins = { version = "0.1.82" } profiler_builtins = { path = "../profiler_builtins", optional = true } unwind = { path = "../unwind" } diff --git a/src/ci/docker/scripts/freebsd-toolchain.sh b/src/ci/docker/scripts/freebsd-toolchain.sh index 4a4cac1b723c..17cd456b995a 100755 --- a/src/ci/docker/scripts/freebsd-toolchain.sh +++ b/src/ci/docker/scripts/freebsd-toolchain.sh @@ -53,7 +53,7 @@ files_to_extract=( for lib in c cxxrt gcc_s m thr util; do files_to_extract=("${files_to_extract[@]}" "./lib/lib${lib}.*" "./usr/lib/lib${lib}.*") done -for lib in c++ c_nonshared compiler_rt execinfo gcc pthread rt ssp_nonshared procstat devstat kvm; do +for lib in c++ c_nonshared compiler_rt execinfo gcc pthread rt ssp_nonshared procstat devstat kvm memstat; do files_to_extract=("${files_to_extract[@]}" "./usr/lib/lib${lib}.*") done From 35c00a9731809292959e98b1e7da3c6e2673f3cc Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Sat, 3 Dec 2022 20:02:39 +0100 Subject: [PATCH 042/115] suggest parenthesis around ExprWithBlock BinOp ExprWithBlock --- .../src/fn_ctxt/suggestions.rs | 4 +- compiler/rustc_parse/src/parser/expr.rs | 14 +----- src/test/ui/parser/expr-as-stmt.fixed | 12 ++++++ src/test/ui/parser/expr-as-stmt.rs | 12 ++++++ src/test/ui/parser/expr-as-stmt.stderr | 43 ++++++++++++++++++- 5 files changed, 71 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index b9a8d16311c9..56b889fdcdda 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -32,11 +32,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } pub(in super::super) fn suggest_semicolon_at_end(&self, span: Span, err: &mut Diagnostic) { + // This suggestion is incorrect for + // fn foo() -> bool { match () { () => true } || match () { () => true } } err.span_suggestion_short( span.shrink_to_hi(), "consider using a semicolon here", ";", - Applicability::MachineApplicable, + Applicability::MaybeIncorrect, ); } diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index e0443a697b50..377638ab9687 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -390,20 +390,10 @@ impl<'a> Parser<'a> { // want to keep their span info to improve diagnostics in these cases in a later stage. (true, Some(AssocOp::Multiply)) | // `{ 42 } *foo = bar;` or `{ 42 } * 3` (true, Some(AssocOp::Subtract)) | // `{ 42 } -5` - (true, Some(AssocOp::Add)) // `{ 42 } + 42 - // If the next token is a keyword, then the tokens above *are* unambiguously incorrect: - // `if x { a } else { b } && if y { c } else { d }` - if !self.look_ahead(1, |t| t.is_used_keyword()) => { - // These cases are ambiguous and can't be identified in the parser alone. - let sp = self.sess.source_map().start_point(self.token.span); - self.sess.ambiguous_block_expr_parse.borrow_mut().insert(sp, lhs.span); - false - } - (true, Some(AssocOp::LAnd)) | + (true, Some(AssocOp::Add)) | // `{ 42 } + 42 + (true, Some(AssocOp::LAnd)) | // `{ 42 } &&x` (#61475) or `{ 42 } && if x { 1 } else { 0 }` (true, Some(AssocOp::LOr)) | (true, Some(AssocOp::BitOr)) => { - // `{ 42 } &&x` (#61475) or `{ 42 } && if x { 1 } else { 0 }`. Separated from the - // above due to #74233. // These cases are ambiguous and can't be identified in the parser alone. // // Bitwise AND is left out because guessing intent is hard. We can make diff --git a/src/test/ui/parser/expr-as-stmt.fixed b/src/test/ui/parser/expr-as-stmt.fixed index 36709eea17c2..b06f62794c4e 100644 --- a/src/test/ui/parser/expr-as-stmt.fixed +++ b/src/test/ui/parser/expr-as-stmt.fixed @@ -64,4 +64,16 @@ fn asteroids() -> impl FnOnce() -> bool { { foo(); } || { true } //~ ERROR E0308 } +// https://github.com/rust-lang/rust/issues/105179 +fn r#match() -> i32 { + (match () { () => 1 }) + match () { () => 1 } //~ ERROR expected expression, found `+` + //~^ ERROR mismatched types +} + +// https://github.com/rust-lang/rust/issues/102171 +fn r#unsafe() -> i32 { + (unsafe { 1 }) + unsafe { 1 } //~ ERROR expected expression, found `+` + //~^ ERROR mismatched types +} + fn main() {} diff --git a/src/test/ui/parser/expr-as-stmt.rs b/src/test/ui/parser/expr-as-stmt.rs index 92bb972b2402..b39d2b88647c 100644 --- a/src/test/ui/parser/expr-as-stmt.rs +++ b/src/test/ui/parser/expr-as-stmt.rs @@ -64,4 +64,16 @@ fn asteroids() -> impl FnOnce() -> bool { { foo() } || { true } //~ ERROR E0308 } +// https://github.com/rust-lang/rust/issues/105179 +fn r#match() -> i32 { + match () { () => 1 } + match () { () => 1 } //~ ERROR expected expression, found `+` + //~^ ERROR mismatched types +} + +// https://github.com/rust-lang/rust/issues/102171 +fn r#unsafe() -> i32 { + unsafe { 1 } + unsafe { 1 } //~ ERROR expected expression, found `+` + //~^ ERROR mismatched types +} + fn main() {} diff --git a/src/test/ui/parser/expr-as-stmt.stderr b/src/test/ui/parser/expr-as-stmt.stderr index 6da4ac34067e..18c8b0b7c506 100644 --- a/src/test/ui/parser/expr-as-stmt.stderr +++ b/src/test/ui/parser/expr-as-stmt.stderr @@ -55,6 +55,28 @@ help: parentheses are required to parse this as an expression LL | ({ true }) | { true } | + + +error: expected expression, found `+` + --> $DIR/expr-as-stmt.rs:69:26 + | +LL | match () { () => 1 } + match () { () => 1 } + | ^ expected expression + | +help: parentheses are required to parse this as an expression + | +LL | (match () { () => 1 }) + match () { () => 1 } + | + + + +error: expected expression, found `+` + --> $DIR/expr-as-stmt.rs:75:18 + | +LL | unsafe { 1 } + unsafe { 1 } + | ^ expected expression + | +help: parentheses are required to parse this as an expression + | +LL | (unsafe { 1 }) + unsafe { 1 } + | + + + error[E0308]: mismatched types --> $DIR/expr-as-stmt.rs:64:7 | @@ -201,7 +223,26 @@ help: parentheses are required to parse this as an expression LL | ({ true }) || { true } | + + -error: aborting due to 18 previous errors +error[E0308]: mismatched types + --> $DIR/expr-as-stmt.rs:69:5 + | +LL | match () { () => 1 } + match () { () => 1 } + | ^^^^^^^^^^^^^^^^^^^^- help: consider using a semicolon here + | | + | expected `()`, found integer + +error[E0308]: mismatched types + --> $DIR/expr-as-stmt.rs:75:14 + | +LL | unsafe { 1 } + unsafe { 1 } + | ^ expected `()`, found integer + | +help: you might have meant to return this value + | +LL | unsafe { return 1; } + unsafe { 1 } + | ++++++ + + +error: aborting due to 22 previous errors Some errors have detailed explanations: E0308, E0600, E0614. For more information about an error, try `rustc --explain E0308`. From b1514108e270e198e13b1f9abb8af16960afc1bc Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 3 Dec 2022 22:40:30 +0000 Subject: [PATCH 043/115] Skip recording resolution for duplicated generic params. --- compiler/rustc_resolve/src/late.rs | 2 +- .../ui/const-generics/defaults/self-referential.rs | 4 ++++ .../const-generics/defaults/self-referential.stderr | 11 +++++++++++ src/test/ui/duplicate/duplicate-type-parameter.stderr | 4 ++-- 4 files changed, 18 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/const-generics/defaults/self-referential.rs create mode 100644 src/test/ui/const-generics/defaults/self-referential.stderr diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 2d2408c061ee..08dd1825f824 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -2360,8 +2360,8 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { if let GenericParamKind::Lifetime = param.kind { // Record lifetime res, so lowering knows there is something fishy. self.record_lifetime_param(param.id, LifetimeRes::Error); - continue; } + continue; } Entry::Vacant(entry) => { entry.insert(param.ident.span); diff --git a/src/test/ui/const-generics/defaults/self-referential.rs b/src/test/ui/const-generics/defaults/self-referential.rs new file mode 100644 index 000000000000..14a870dc39bf --- /dev/null +++ b/src/test/ui/const-generics/defaults/self-referential.rs @@ -0,0 +1,4 @@ +trait Foo {} +//~^ ERROR the name `M` is already used for a generic parameter in this item's generic parameters +impl Foo<2> for () {} +fn main() {} diff --git a/src/test/ui/const-generics/defaults/self-referential.stderr b/src/test/ui/const-generics/defaults/self-referential.stderr new file mode 100644 index 000000000000..170c1f7f7b2a --- /dev/null +++ b/src/test/ui/const-generics/defaults/self-referential.stderr @@ -0,0 +1,11 @@ +error[E0403]: the name `M` is already used for a generic parameter in this item's generic parameters + --> $DIR/self-referential.rs:1:30 + | +LL | trait Foo {} + | - ^ already used + | | + | first use of `M` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0403`. diff --git a/src/test/ui/duplicate/duplicate-type-parameter.stderr b/src/test/ui/duplicate/duplicate-type-parameter.stderr index 6754574f0b95..628f898d5c87 100644 --- a/src/test/ui/duplicate/duplicate-type-parameter.stderr +++ b/src/test/ui/duplicate/duplicate-type-parameter.stderr @@ -55,10 +55,10 @@ LL | impl Qux for Option {} | first use of `T` error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates - --> $DIR/duplicate-type-parameter.rs:24:6 + --> $DIR/duplicate-type-parameter.rs:24:8 | LL | impl Qux for Option {} - | ^ unconstrained type parameter + | ^ unconstrained type parameter error: aborting due to 8 previous errors From c808d0b289c1f8e0f26885bf44cb2ba1873ba10e Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Sat, 3 Dec 2022 23:54:06 +0100 Subject: [PATCH 044/115] more comments --- compiler/rustc_parse/src/parser/expr.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 377638ab9687..0a948a2810a4 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -390,10 +390,11 @@ impl<'a> Parser<'a> { // want to keep their span info to improve diagnostics in these cases in a later stage. (true, Some(AssocOp::Multiply)) | // `{ 42 } *foo = bar;` or `{ 42 } * 3` (true, Some(AssocOp::Subtract)) | // `{ 42 } -5` - (true, Some(AssocOp::Add)) | // `{ 42 } + 42 + (true, Some(AssocOp::Add)) | // `{ 42 } + 42` (unary plus) (true, Some(AssocOp::LAnd)) | // `{ 42 } &&x` (#61475) or `{ 42 } && if x { 1 } else { 0 }` - (true, Some(AssocOp::LOr)) | - (true, Some(AssocOp::BitOr)) => { + (true, Some(AssocOp::LOr)) | // `{ 42 } || 42` ("logical or" or closure) + (true, Some(AssocOp::BitOr)) // `{ 42 } | 42` or `{ 42 } |x| 42` + => { // These cases are ambiguous and can't be identified in the parser alone. // // Bitwise AND is left out because guessing intent is hard. We can make From 74a270ac93710ef4ef2315cce3840486f92698b5 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Sat, 3 Dec 2022 17:00:05 -0500 Subject: [PATCH 045/115] Re-enable removal of ZST writes to unions --- .../rustc_mir_transform/src/remove_zsts.rs | 27 +------------------ ...remove_zsts.get_union.PreCodegen.after.mir | 10 +++++++ .../remove_zsts.get_union.RemoveZsts.diff | 19 +++++++++++++ src/test/mir-opt/remove_zsts.rs | 14 ++++++++++ ...ouch_unions.get_union.RemoveZsts.after.mir | 15 ----------- .../mir-opt/remove_zsts_dont_touch_unions.rs | 19 ------------- 6 files changed, 44 insertions(+), 60 deletions(-) create mode 100644 src/test/mir-opt/remove_zsts.get_union.PreCodegen.after.mir create mode 100644 src/test/mir-opt/remove_zsts.get_union.RemoveZsts.diff create mode 100644 src/test/mir-opt/remove_zsts.rs delete mode 100644 src/test/mir-opt/remove_zsts_dont_touch_unions.get_union.RemoveZsts.after.mir delete mode 100644 src/test/mir-opt/remove_zsts_dont_touch_unions.rs diff --git a/compiler/rustc_mir_transform/src/remove_zsts.rs b/compiler/rustc_mir_transform/src/remove_zsts.rs index 40be4f146db9..569e783fee84 100644 --- a/compiler/rustc_mir_transform/src/remove_zsts.rs +++ b/compiler/rustc_mir_transform/src/remove_zsts.rs @@ -1,8 +1,7 @@ //! Removes assignments to ZST places. use crate::MirPass; -use rustc_middle::mir::tcx::PlaceTy; -use rustc_middle::mir::{Body, LocalDecls, Place, StatementKind}; +use rustc_middle::mir::{Body, StatementKind}; use rustc_middle::ty::{self, Ty, TyCtxt}; pub struct RemoveZsts; @@ -35,9 +34,6 @@ impl<'tcx> MirPass<'tcx> for RemoveZsts { if !layout.is_zst() { continue; } - if involves_a_union(place, local_decls, tcx) { - continue; - } if tcx.consider_optimizing(|| { format!( "RemoveZsts - Place: {:?} SourceInfo: {:?}", @@ -63,24 +59,3 @@ fn maybe_zst(ty: Ty<'_>) -> bool { _ => false, } } - -/// Miri lazily allocates memory for locals on assignment, -/// so we must preserve writes to unions and union fields, -/// or it will ICE on reads of those fields. -fn involves_a_union<'tcx>( - place: Place<'tcx>, - local_decls: &LocalDecls<'tcx>, - tcx: TyCtxt<'tcx>, -) -> bool { - let mut place_ty = PlaceTy::from_ty(local_decls[place.local].ty); - if place_ty.ty.is_union() { - return true; - } - for elem in place.projection { - place_ty = place_ty.projection_ty(tcx, elem); - if place_ty.ty.is_union() { - return true; - } - } - return false; -} diff --git a/src/test/mir-opt/remove_zsts.get_union.PreCodegen.after.mir b/src/test/mir-opt/remove_zsts.get_union.PreCodegen.after.mir new file mode 100644 index 000000000000..12e914e25e0c --- /dev/null +++ b/src/test/mir-opt/remove_zsts.get_union.PreCodegen.after.mir @@ -0,0 +1,10 @@ +// MIR for `get_union` after PreCodegen + +fn get_union() -> Foo { + let mut _0: Foo; // return place in scope 0 at $DIR/remove_zsts.rs:+0:19: +0:22 + + bb0: { + Deinit(_0); // scope 0 at $DIR/remove_zsts.rs:+1:5: +1:18 + return; // scope 0 at $DIR/remove_zsts.rs:+2:2: +2:2 + } +} diff --git a/src/test/mir-opt/remove_zsts.get_union.RemoveZsts.diff b/src/test/mir-opt/remove_zsts.get_union.RemoveZsts.diff new file mode 100644 index 000000000000..169b7b1054b4 --- /dev/null +++ b/src/test/mir-opt/remove_zsts.get_union.RemoveZsts.diff @@ -0,0 +1,19 @@ +- // MIR for `get_union` before RemoveZsts ++ // MIR for `get_union` after RemoveZsts + + fn get_union() -> Foo { + let mut _0: Foo; // return place in scope 0 at $DIR/remove_zsts.rs:+0:19: +0:22 + let mut _1: (); // in scope 0 at $DIR/remove_zsts.rs:+1:14: +1:16 + + bb0: { + StorageLive(_1); // scope 0 at $DIR/remove_zsts.rs:+1:14: +1:16 +- Deinit(_1); // scope 0 at $DIR/remove_zsts.rs:+1:14: +1:16 ++ nop; // scope 0 at $DIR/remove_zsts.rs:+1:14: +1:16 + Deinit(_0); // scope 0 at $DIR/remove_zsts.rs:+1:5: +1:18 +- (_0.0: ()) = move _1; // scope 0 at $DIR/remove_zsts.rs:+1:5: +1:18 ++ nop; // scope 0 at $DIR/remove_zsts.rs:+1:5: +1:18 + StorageDead(_1); // scope 0 at $DIR/remove_zsts.rs:+1:17: +1:18 + return; // scope 0 at $DIR/remove_zsts.rs:+2:2: +2:2 + } + } + diff --git a/src/test/mir-opt/remove_zsts.rs b/src/test/mir-opt/remove_zsts.rs new file mode 100644 index 000000000000..1cf7ad6e3667 --- /dev/null +++ b/src/test/mir-opt/remove_zsts.rs @@ -0,0 +1,14 @@ +union Foo { + x: (), + y: u64, +} + +// EMIT_MIR remove_zsts.get_union.RemoveZsts.diff +// EMIT_MIR remove_zsts.get_union.PreCodegen.after.mir +fn get_union() -> Foo { + Foo { x: () } +} + +fn main() { + get_union(); +} diff --git a/src/test/mir-opt/remove_zsts_dont_touch_unions.get_union.RemoveZsts.after.mir b/src/test/mir-opt/remove_zsts_dont_touch_unions.get_union.RemoveZsts.after.mir deleted file mode 100644 index 7d9e6046202c..000000000000 --- a/src/test/mir-opt/remove_zsts_dont_touch_unions.get_union.RemoveZsts.after.mir +++ /dev/null @@ -1,15 +0,0 @@ -// MIR for `get_union` after RemoveZsts - -fn get_union() -> Foo { - let mut _0: Foo; // return place in scope 0 at $DIR/remove_zsts_dont_touch_unions.rs:+0:19: +0:22 - let mut _1: (); // in scope 0 at $DIR/remove_zsts_dont_touch_unions.rs:+1:14: +1:16 - - bb0: { - StorageLive(_1); // scope 0 at $DIR/remove_zsts_dont_touch_unions.rs:+1:14: +1:16 - nop; // scope 0 at $DIR/remove_zsts_dont_touch_unions.rs:+1:14: +1:16 - Deinit(_0); // scope 0 at $DIR/remove_zsts_dont_touch_unions.rs:+1:5: +1:18 - (_0.0: ()) = move _1; // scope 0 at $DIR/remove_zsts_dont_touch_unions.rs:+1:5: +1:18 - StorageDead(_1); // scope 0 at $DIR/remove_zsts_dont_touch_unions.rs:+1:17: +1:18 - return; // scope 0 at $DIR/remove_zsts_dont_touch_unions.rs:+2:2: +2:2 - } -} diff --git a/src/test/mir-opt/remove_zsts_dont_touch_unions.rs b/src/test/mir-opt/remove_zsts_dont_touch_unions.rs deleted file mode 100644 index 8b9de9b4d65a..000000000000 --- a/src/test/mir-opt/remove_zsts_dont_touch_unions.rs +++ /dev/null @@ -1,19 +0,0 @@ -// unit-test: RemoveZsts - -// Ensure RemoveZsts doesn't remove ZST assignments to union fields, -// which causes problems in Miri. - -union Foo { - x: (), - y: u64, -} - -// EMIT_MIR remove_zsts_dont_touch_unions.get_union.RemoveZsts.after.mir -fn get_union() -> Foo { - Foo { x: () } -} - - -fn main() { - get_union(); -} From c823dfa8b2f1b0cfb82d253e6d55efd6927bcb6d Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 4 Dec 2022 10:32:00 +0100 Subject: [PATCH 046/115] remove no-op 'let _ = ' --- library/std/src/sync/mpsc/mod.rs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/library/std/src/sync/mpsc/mod.rs b/library/std/src/sync/mpsc/mod.rs index 27fba761ada1..adb488d4378f 100644 --- a/library/std/src/sync/mpsc/mod.rs +++ b/library/std/src/sync/mpsc/mod.rs @@ -629,9 +629,7 @@ impl Clone for Sender { #[stable(feature = "rust1", since = "1.0.0")] impl Drop for Sender { - fn drop(&mut self) { - let _ = self.inner; - } + fn drop(&mut self) {} } #[stable(feature = "mpsc_debug", since = "1.8.0")] @@ -751,9 +749,7 @@ impl Clone for SyncSender { #[stable(feature = "rust1", since = "1.0.0")] impl Drop for SyncSender { - fn drop(&mut self) { - let _ = self.inner; - } + fn drop(&mut self) {} } #[stable(feature = "mpsc_debug", since = "1.8.0")] @@ -1094,9 +1090,7 @@ impl IntoIterator for Receiver { #[stable(feature = "rust1", since = "1.0.0")] impl Drop for Receiver { - fn drop(&mut self) { - let _ = self.inner; - } + fn drop(&mut self) {} } #[stable(feature = "mpsc_debug", since = "1.8.0")] From 01a48982106fbcf4be448ad560d51fd91ace2b92 Mon Sep 17 00:00:00 2001 From: Jakob Degen Date: Sun, 4 Dec 2022 02:23:21 -0800 Subject: [PATCH 047/115] Fix --pass in compiletest --- src/tools/compiletest/src/header.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 0d9a629e179b..64d97e914423 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -260,9 +260,9 @@ impl TestProps { props.load_from(testfile, cfg, config); match (props.pass_mode, props.fail_mode) { - (None, None) => props.fail_mode = Some(FailMode::Check), - (Some(_), None) | (None, Some(_)) => {} + (None, None) if config.mode == Mode::Ui => props.fail_mode = Some(FailMode::Check), (Some(_), Some(_)) => panic!("cannot use a *-fail and *-pass mode together"), + _ => {} } props @@ -522,8 +522,8 @@ impl TestProps { } pub fn pass_mode(&self, config: &Config) -> Option { - if !self.ignore_pass && self.fail_mode.is_none() && config.mode == Mode::Ui { - if let (mode @ Some(_), Some(_)) = (config.force_pass_mode, self.pass_mode) { + if !self.ignore_pass && self.fail_mode.is_none() { + if let mode @ Some(_) = config.force_pass_mode { return mode; } } From 44948d1fdc97a4fd24594be77df673a2c3b40544 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 4 Dec 2022 13:54:41 +0000 Subject: [PATCH 048/115] Recurse into nested impl-trait when computing variance. --- .../rustc_hir_analysis/src/variance/mod.rs | 42 +++++++++++++++++-- src/test/ui/impl-trait/nested-return-type4.rs | 8 ++++ .../ui/impl-trait/nested-return-type4.stderr | 20 +++++++++ 3 files changed, 66 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/impl-trait/nested-return-type4.rs create mode 100644 src/test/ui/impl-trait/nested-return-type4.stderr diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs index 9db05eedbde7..8b2719c2f8aa 100644 --- a/compiler/rustc_hir_analysis/src/variance/mod.rs +++ b/compiler/rustc_hir_analysis/src/variance/mod.rs @@ -7,7 +7,8 @@ use rustc_arena::DroplessArena; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::ty::query::Providers; -use rustc_middle::ty::{self, CrateVariancesMap, TyCtxt, TypeSuperVisitable, TypeVisitable}; +use rustc_middle::ty::{self, CrateVariancesMap, SubstsRef, Ty, TyCtxt}; +use rustc_middle::ty::{DefIdTree, TypeSuperVisitable, TypeVisitable}; use std::ops::ControlFlow; /// Defines the `TermsContext` basically houses an arena where we can @@ -75,11 +76,30 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc // type Foo<'a, 'b, 'c> = impl Trait<'a> + 'b; // ``` // we may not use `'c` in the hidden type. - struct OpaqueTypeLifetimeCollector { + struct OpaqueTypeLifetimeCollector<'tcx> { + tcx: TyCtxt<'tcx>, + root_def_id: DefId, variances: Vec, } - impl<'tcx> ty::TypeVisitor<'tcx> for OpaqueTypeLifetimeCollector { + impl<'tcx> OpaqueTypeLifetimeCollector<'tcx> { + #[instrument(level = "trace", skip(self), ret)] + fn visit_opaque(&mut self, def_id: DefId, substs: SubstsRef<'tcx>) -> ControlFlow { + if def_id != self.root_def_id && self.tcx.is_descendant_of(def_id, self.root_def_id) { + let child_variances = self.tcx.variances_of(def_id); + for (a, v) in substs.iter().zip(child_variances) { + if *v != ty::Bivariant { + a.visit_with(self)?; + } + } + ControlFlow::CONTINUE + } else { + substs.visit_with(self) + } + } + } + + impl<'tcx> ty::TypeVisitor<'tcx> for OpaqueTypeLifetimeCollector<'tcx> { #[instrument(level = "trace", skip(self), ret)] fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { if let ty::RegionKind::ReEarlyBound(ebr) = r.kind() { @@ -87,6 +107,19 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc } r.super_visit_with(self) } + + #[instrument(level = "trace", skip(self), ret)] + fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + match t.kind() { + ty::Opaque(def_id, substs) => self.visit_opaque(*def_id, substs), + ty::Projection(proj) + if self.tcx.def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder => + { + self.visit_opaque(proj.item_def_id, proj.substs) + } + _ => t.super_visit_with(self), + } + } } // By default, RPIT are invariant wrt type and const generics, but they are bivariant wrt @@ -111,7 +144,8 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc } } - let mut collector = OpaqueTypeLifetimeCollector { variances }; + let mut collector = + OpaqueTypeLifetimeCollector { tcx, root_def_id: item_def_id.to_def_id(), variances }; let id_substs = ty::InternalSubsts::identity_for_item(tcx, item_def_id.to_def_id()); for pred in tcx.bound_explicit_item_bounds(item_def_id.to_def_id()).transpose_iter() { let pred = pred.map_bound(|(pred, _)| *pred).subst(tcx, id_substs); diff --git a/src/test/ui/impl-trait/nested-return-type4.rs b/src/test/ui/impl-trait/nested-return-type4.rs new file mode 100644 index 000000000000..cec70bb1a0d9 --- /dev/null +++ b/src/test/ui/impl-trait/nested-return-type4.rs @@ -0,0 +1,8 @@ +// edition: 2021 + +fn test<'s: 's>(s: &'s str) -> impl std::future::Future { + async move { let _s = s; } + //~^ ERROR hidden type for `impl Future` captures lifetime that does not appear in bounds +} + +fn main() {} diff --git a/src/test/ui/impl-trait/nested-return-type4.stderr b/src/test/ui/impl-trait/nested-return-type4.stderr new file mode 100644 index 000000000000..e761a60e79c2 --- /dev/null +++ b/src/test/ui/impl-trait/nested-return-type4.stderr @@ -0,0 +1,20 @@ +error[E0700]: hidden type for `impl Future` captures lifetime that does not appear in bounds + --> $DIR/nested-return-type4.rs:4:5 + | +LL | fn test<'s: 's>(s: &'s str) -> impl std::future::Future { + | -- hidden type `[async block@$DIR/nested-return-type4.rs:4:5: 4:31]` captures the lifetime `'s` as defined here +LL | async move { let _s = s; } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: to declare that `impl Future` captures `'s`, you can add an explicit `'s` lifetime bound + | +LL | fn test<'s: 's>(s: &'s str) -> impl std::future::Future + 's { + | ++++ +help: to declare that `impl Sized` captures `'s`, you can add an explicit `'s` lifetime bound + | +LL | fn test<'s: 's>(s: &'s str) -> impl std::future::Future { + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0700`. From 6cc86db06957194191028c9c7582d920f6aeb6d0 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 4 Dec 2022 15:21:05 +0100 Subject: [PATCH 049/115] Add small comment explaining what `method-margins.goml` test is about --- src/test/rustdoc-gui/method-margins.goml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/rustdoc-gui/method-margins.goml b/src/test/rustdoc-gui/method-margins.goml index 397bcd40b36c..ed36bcdec17d 100644 --- a/src/test/rustdoc-gui/method-margins.goml +++ b/src/test/rustdoc-gui/method-margins.goml @@ -1,3 +1,4 @@ +// This test ensures that the margins on methods are coherent inside an impl block. goto: "file://" + |DOC_PATH| + "/test_docs/trait_members/struct.HasTrait.html#impl-TraitMembers-for-HasTrait" assert-count: ("#trait-implementations-list > .rustdoc-toggle", 1) From e2d41f4c974f0cc09e5aafb02883f222487610f9 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 4 Dec 2022 14:18:52 +0000 Subject: [PATCH 050/115] Make nested RPITIT inherit the parent opaque's generics. --- .../src/collect/generics_of.rs | 16 +--------------- src/test/ui/async-await/in-trait/nested-rpit.rs | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 15 deletions(-) create mode 100644 src/test/ui/async-await/in-trait/nested-rpit.rs diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index 639f81f20bfb..0a7e25300cba 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -4,7 +4,6 @@ use hir::{ GenericParamKind, HirId, Node, }; use rustc_hir as hir; -use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_middle::ty::{self, TyCtxt}; use rustc_session::lint; @@ -143,20 +142,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { Some(tcx.typeck_root_def_id(def_id)) } Node::Item(item) => match item.kind { - ItemKind::OpaqueTy(hir::OpaqueTy { - origin: - hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id), - in_trait, - .. - }) => { - if in_trait { - assert!(matches!(tcx.def_kind(fn_def_id), DefKind::AssocFn)) - } else { - assert!(matches!(tcx.def_kind(fn_def_id), DefKind::AssocFn | DefKind::Fn)) - } - Some(fn_def_id.to_def_id()) - } - ItemKind::OpaqueTy(hir::OpaqueTy { origin: hir::OpaqueTyOrigin::TyAlias, .. }) => { + ItemKind::OpaqueTy(hir::OpaqueTy { .. }) => { let parent_id = tcx.hir().get_parent_item(hir_id); assert_ne!(parent_id, hir::CRATE_OWNER_ID); debug!("generics_of: parent of opaque ty {:?} is {:?}", def_id, parent_id); diff --git a/src/test/ui/async-await/in-trait/nested-rpit.rs b/src/test/ui/async-await/in-trait/nested-rpit.rs new file mode 100644 index 000000000000..ae8e0aed0cc5 --- /dev/null +++ b/src/test/ui/async-await/in-trait/nested-rpit.rs @@ -0,0 +1,17 @@ +// check-pass +// edition: 2021 + +#![feature(async_fn_in_trait)] +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +use std::future::Future; +use std::marker::PhantomData; + +trait Lockable { + async fn lock_all_entries(&self) -> impl Future>; +} + +struct Guard<'a>(PhantomData<&'a ()>); + +fn main() {} From 26b24cd7558c02c433ef9f621894cb6a2f31898d Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 4 Dec 2022 17:59:21 +0000 Subject: [PATCH 051/115] drive-by: move field_index to typeck results --- compiler/rustc_hir_typeck/src/expr_use_visitor.rs | 6 +++--- compiler/rustc_lint/src/builtin.rs | 2 +- compiler/rustc_middle/src/ty/context.rs | 8 ++++++++ compiler/rustc_middle/src/ty/mod.rs | 4 ---- compiler/rustc_mir_build/src/thir/cx/expr.rs | 4 ++-- compiler/rustc_mir_build/src/thir/pattern/mod.rs | 2 +- compiler/rustc_passes/src/dead.rs | 6 +++--- compiler/rustc_privacy/src/lib.rs | 10 +++++----- 8 files changed, 23 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index e5e798f4b933..4f06ad8a0182 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -540,9 +540,9 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { ty::Adt(adt, substs) if adt.is_struct() => { // Consume those fields of the with expression that are needed. for (f_index, with_field) in adt.non_enum_variant().fields.iter().enumerate() { - let is_mentioned = fields.iter().any(|f| { - self.tcx().field_index(f.hir_id, self.mc.typeck_results) == f_index - }); + let is_mentioned = fields + .iter() + .any(|f| self.mc.typeck_results.field_index(f.hir_id) == f_index); if !is_mentioned { let field_place = self.mc.cat_projection( &*with_expr, diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 825093384fba..d0d34d8d2b40 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -259,7 +259,7 @@ impl<'tcx> LateLintPass<'tcx> for NonShorthandFieldPatterns { } if let PatKind::Binding(binding_annot, _, ident, None) = fieldpat.pat.kind { if cx.tcx.find_field_index(ident, &variant) - == Some(cx.tcx.field_index(fieldpat.hir_id, cx.typeck_results())) + == Some(cx.typeck_results().field_index(fieldpat.hir_id)) { cx.struct_span_lint( NON_SHORTHAND_FIELD_PATTERNS, diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index c5683a9db947..11811de8e7af 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -671,6 +671,14 @@ impl<'tcx> TypeckResults<'tcx> { LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.field_indices } } + pub fn field_index(&self, id: hir::HirId) -> usize { + self.field_indices().get(id).cloned().expect("no index for a field") + } + + pub fn opt_field_index(&self, id: hir::HirId) -> Option { + self.field_indices().get(id).cloned() + } + pub fn user_provided_types(&self) -> LocalTableInContext<'_, CanonicalUserType<'tcx>> { LocalTableInContext { hir_owner: self.hir_owner, data: &self.user_provided_types } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index dd4ab3e8d30b..d869f17e3ac5 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2228,10 +2228,6 @@ impl<'tcx> TyCtxt<'tcx> { } } - pub fn field_index(self, hir_id: hir::HirId, typeck_results: &TypeckResults<'_>) -> usize { - typeck_results.field_indices().get(hir_id).cloned().expect("no index for a field") - } - pub fn find_field_index(self, ident: Ident, variant: &VariantDef) -> Option { variant .fields diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 5fa41ebeb6e5..261b95ba95b0 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -704,7 +704,7 @@ impl<'tcx> Cx<'tcx> { hir::ExprKind::Field(ref source, ..) => ExprKind::Field { lhs: self.mirror_expr(source), variant_index: VariantIdx::new(0), - name: Field::new(tcx.field_index(expr.hir_id, self.typeck_results)), + name: Field::new(self.typeck_results.field_index(expr.hir_id)), }, hir::ExprKind::Cast(ref source, ref cast_ty) => { // Check for a user-given type annotation on this `cast` @@ -1079,7 +1079,7 @@ impl<'tcx> Cx<'tcx> { fields .iter() .map(|field| FieldExpr { - name: Field::new(self.tcx.field_index(field.hir_id, self.typeck_results)), + name: Field::new(self.typeck_results.field_index(field.hir_id)), expr: self.mirror_expr(field.expr), }) .collect() diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 4c2a80e523f3..48a231a6cd6b 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -321,7 +321,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { let subpatterns = fields .iter() .map(|field| FieldPat { - field: Field::new(self.tcx.field_index(field.hir_id, self.typeck_results)), + field: Field::new(self.typeck_results.field_index(field.hir_id)), pattern: self.lower_pattern(&field.pat), }) .collect(); diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index da023fcf4c3b..a71ae717a508 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -124,7 +124,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { fn handle_field_access(&mut self, lhs: &hir::Expr<'_>, hir_id: hir::HirId) { match self.typeck_results().expr_ty_adjusted(lhs).kind() { ty::Adt(def, _) => { - let index = self.tcx.field_index(hir_id, self.typeck_results()); + let index = self.typeck_results().field_index(hir_id); self.insert_def_id(def.non_enum_variant().fields[index].did); } ty::Tuple(..) => {} @@ -208,7 +208,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { if let PatKind::Wild = pat.pat.kind { continue; } - let index = self.tcx.field_index(pat.hir_id, self.typeck_results()); + let index = self.typeck_results().field_index(pat.hir_id); self.insert_def_id(variant.fields[index].did); } } @@ -341,7 +341,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { fn mark_as_used_if_union(&mut self, adt: ty::AdtDef<'tcx>, fields: &[hir::ExprField<'_>]) { if adt.is_union() && adt.non_enum_variant().fields.len() > 1 && adt.did().is_local() { for field in fields { - let index = self.tcx.field_index(field.hir_id, self.typeck_results()); + let index = self.typeck_results().field_index(field.hir_id); self.insert_def_id(adt.non_enum_variant().fields[index].did); } } diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index f2177a7c2833..a254c892478c 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -1065,9 +1065,9 @@ impl<'tcx> Visitor<'tcx> for NamePrivacyVisitor<'tcx> { // are checked for privacy (RFC 736). Rather than computing the set of // unmentioned fields, just check them all. for (vf_index, variant_field) in variant.fields.iter().enumerate() { - let field = fields.iter().find(|f| { - self.tcx.field_index(f.hir_id, self.typeck_results()) == vf_index - }); + let field = fields + .iter() + .find(|f| self.typeck_results().field_index(f.hir_id) == vf_index); let (use_ctxt, span) = match field { Some(field) => (field.ident.span, field.span), None => (base.span, base.span), @@ -1077,7 +1077,7 @@ impl<'tcx> Visitor<'tcx> for NamePrivacyVisitor<'tcx> { } else { for field in fields { let use_ctxt = field.ident.span; - let index = self.tcx.field_index(field.hir_id, self.typeck_results()); + let index = self.typeck_results().field_index(field.hir_id); self.check_field(use_ctxt, field.span, adt, &variant.fields[index], false); } } @@ -1093,7 +1093,7 @@ impl<'tcx> Visitor<'tcx> for NamePrivacyVisitor<'tcx> { let variant = adt.variant_of_res(res); for field in fields { let use_ctxt = field.ident.span; - let index = self.tcx.field_index(field.hir_id, self.typeck_results()); + let index = self.typeck_results().field_index(field.hir_id); self.check_field(use_ctxt, field.span, adt, &variant.fields[index], false); } } From d442c015d6d688460a182947e797f4bf69876044 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 4 Dec 2022 18:53:50 +0000 Subject: [PATCH 052/115] Don't ICE in ExprUseVisitor on FRU for non-existent struct --- compiler/rustc_hir_typeck/src/expr_use_visitor.rs | 7 ++++++- src/test/ui/structs/unresolved-struct-with-fru.rs | 12 ++++++++++++ .../ui/structs/unresolved-struct-with-fru.stderr | 9 +++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/structs/unresolved-struct-with-fru.rs create mode 100644 src/test/ui/structs/unresolved-struct-with-fru.stderr diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index 4f06ad8a0182..03b174c77955 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -523,6 +523,11 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { // Consume the expressions supplying values for each field. for field in fields { self.consume_expr(field.expr); + + // The struct path probably didn't resolve + if self.mc.typeck_results.opt_field_index(field.hir_id).is_none() { + self.tcx().sess.delay_span_bug(field.span, "couldn't resolve index for field"); + } } let with_expr = match *opt_with { @@ -542,7 +547,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { for (f_index, with_field) in adt.non_enum_variant().fields.iter().enumerate() { let is_mentioned = fields .iter() - .any(|f| self.mc.typeck_results.field_index(f.hir_id) == f_index); + .any(|f| self.mc.typeck_results.opt_field_index(f.hir_id) == Some(f_index)); if !is_mentioned { let field_place = self.mc.cat_projection( &*with_expr, diff --git a/src/test/ui/structs/unresolved-struct-with-fru.rs b/src/test/ui/structs/unresolved-struct-with-fru.rs new file mode 100644 index 000000000000..c9fdca457727 --- /dev/null +++ b/src/test/ui/structs/unresolved-struct-with-fru.rs @@ -0,0 +1,12 @@ +struct S { + a: u32, +} + +fn main() { + let s1 = S { a: 1 }; + + let _ = || { + let s2 = Oops { a: 2, ..s1 }; + //~^ ERROR cannot find struct, variant or union type `Oops` in this scope + }; +} diff --git a/src/test/ui/structs/unresolved-struct-with-fru.stderr b/src/test/ui/structs/unresolved-struct-with-fru.stderr new file mode 100644 index 000000000000..a5796a222256 --- /dev/null +++ b/src/test/ui/structs/unresolved-struct-with-fru.stderr @@ -0,0 +1,9 @@ +error[E0422]: cannot find struct, variant or union type `Oops` in this scope + --> $DIR/unresolved-struct-with-fru.rs:9:18 + | +LL | let s2 = Oops { a: 2, ..s1 }; + | ^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0422`. From 2e51122647d5c4c21309b6f6287cd63e6a9dcf8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20S=C3=A1nchez=20Mu=C3=B1oz?= Date: Sun, 4 Dec 2022 22:55:18 +0100 Subject: [PATCH 053/115] Make integer-to-integer `From` impls `#[inline(always)]` --- library/core/src/convert/num.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/convert/num.rs b/library/core/src/convert/num.rs index 4fa5d129bc6a..9c0d7e9a1e89 100644 --- a/library/core/src/convert/num.rs +++ b/library/core/src/convert/num.rs @@ -49,7 +49,7 @@ macro_rules! impl_from { // Rustdocs on the impl block show a "[+] show undocumented items" toggle. // Rustdocs on functions do not. #[doc = $doc] - #[inline] + #[inline(always)] fn from(small: $Small) -> Self { small as Self } From 1c81540206b10a2b5b709540ba5ac138eaaa5261 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 4 Dec 2022 21:02:51 +0000 Subject: [PATCH 054/115] Unconditional check FRU expression, even if there are errors present --- compiler/rustc_hir_typeck/src/expr.rs | 3 +++ .../drop-track-bad-field-in-fru.rs | 10 ++++++++ .../drop-track-bad-field-in-fru.stderr | 23 +++++++++++++++++++ 3 files changed, 36 insertions(+) create mode 100644 src/test/ui/async-await/drop-track-bad-field-in-fru.rs create mode 100644 src/test/ui/async-await/drop-track-bad-field-in-fru.stderr diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 0c5bbb3e20be..2ca5b980fc83 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1646,6 +1646,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // the fields with the base_expr. This could cause us to hit errors later // when certain fields are assumed to exist that in fact do not. if error_happened { + if let Some(base_expr) = base_expr { + self.check_expr(base_expr); + } return; } diff --git a/src/test/ui/async-await/drop-track-bad-field-in-fru.rs b/src/test/ui/async-await/drop-track-bad-field-in-fru.rs new file mode 100644 index 000000000000..28ad7767583c --- /dev/null +++ b/src/test/ui/async-await/drop-track-bad-field-in-fru.rs @@ -0,0 +1,10 @@ +// compile-flags: -Zdrop-tracking +// edition: 2021 + +fn main() {} + +async fn foo() { + None { value: (), ..Default::default() }.await; + //~^ ERROR `Option<_>` is not a future + //~| ERROR variant `Option<_>::None` has no field named `value` +} diff --git a/src/test/ui/async-await/drop-track-bad-field-in-fru.stderr b/src/test/ui/async-await/drop-track-bad-field-in-fru.stderr new file mode 100644 index 000000000000..819b64ad77f5 --- /dev/null +++ b/src/test/ui/async-await/drop-track-bad-field-in-fru.stderr @@ -0,0 +1,23 @@ +error[E0559]: variant `Option<_>::None` has no field named `value` + --> $DIR/drop-track-bad-field-in-fru.rs:7:12 + | +LL | None { value: (), ..Default::default() }.await; + | ^^^^^ `Option<_>::None` does not have this field + +error[E0277]: `Option<_>` is not a future + --> $DIR/drop-track-bad-field-in-fru.rs:7:45 + | +LL | None { value: (), ..Default::default() }.await; + | ^^^^^^ + | | + | `Option<_>` is not a future + | help: remove the `.await` + | + = help: the trait `Future` is not implemented for `Option<_>` + = note: Option<_> must be a future or must implement `IntoFuture` to be awaited + = note: required for `Option<_>` to implement `IntoFuture` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0277, E0559. +For more information about an error, try `rustc --explain E0277`. From 34c377335bc6b855722eb1f4a0866de29af0f2c9 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Mon, 5 Dec 2022 03:18:26 +0000 Subject: [PATCH 055/115] Add fixme note --- compiler/rustc_ast_lowering/src/expr.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 2d7cd067e08a..c7a322ffa942 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -1013,6 +1013,8 @@ impl<'hir> LoweringContext<'_, 'hir> { let async_body = this.make_async_expr( capture_clause, + // FIXME(nbdd0121): This should also use a proper HIR id so `#[track_caller]` + // can be applied on async closures as well. None, inner_closure_id, async_ret_ty, From 19175e9b75234647963c84247db653f53c8c936a Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 5 Dec 2022 05:44:24 +0000 Subject: [PATCH 056/115] Synthesize generics for bad auto traits in dyn types --- compiler/rustc_middle/src/ty/sty.rs | 24 +++++++++++++++++-- .../ui/auto-traits/bad-generics-on-dyn.rs | 11 +++++++++ .../ui/auto-traits/bad-generics-on-dyn.stderr | 11 +++++++++ 3 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/auto-traits/bad-generics-on-dyn.rs create mode 100644 src/test/ui/auto-traits/bad-generics-on-dyn.stderr diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 5984686044b7..8e69824e6c79 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -722,8 +722,28 @@ impl<'tcx> PolyExistentialPredicate<'tcx> { self.rebind(p.with_self_ty(tcx, self_ty)).to_predicate(tcx) } ExistentialPredicate::AutoTrait(did) => { - let trait_ref = self.rebind(tcx.mk_trait_ref(did, [self_ty])); - trait_ref.without_const().to_predicate(tcx) + let generics = tcx.generics_of(did); + let trait_ref = if generics.params.len() == 1 { + tcx.mk_trait_ref(did, [self_ty]) + } else { + // If this is an ill-formed auto trait, then synthesize + // new error substs for the missing generics. + let err_substs = ty::InternalSubsts::for_item(tcx, did, |def, substs| { + if def.index == 0 { + self_ty.into() + } else { + match &def.kind { + ty::GenericParamDefKind::Lifetime => tcx.lifetimes.re_static.into(), + ty::GenericParamDefKind::Type { .. } => tcx.ty_error().into(), + ty::GenericParamDefKind::Const { .. } => tcx + .const_error(tcx.bound_type_of(def.def_id).subst(tcx, substs)) + .into(), + } + } + }); + tcx.mk_trait_ref(did, err_substs) + }; + self.rebind(trait_ref).without_const().to_predicate(tcx) } } } diff --git a/src/test/ui/auto-traits/bad-generics-on-dyn.rs b/src/test/ui/auto-traits/bad-generics-on-dyn.rs new file mode 100644 index 000000000000..3f8ac14c72d9 --- /dev/null +++ b/src/test/ui/auto-traits/bad-generics-on-dyn.rs @@ -0,0 +1,11 @@ +#![feature(auto_traits)] + +auto trait Trait1<'a> {} +//~^ ERROR auto traits cannot have generic parameters + +fn f<'a>(x: &dyn Trait1<'a>) +{} + +fn main() { + f(&1); +} diff --git a/src/test/ui/auto-traits/bad-generics-on-dyn.stderr b/src/test/ui/auto-traits/bad-generics-on-dyn.stderr new file mode 100644 index 000000000000..ade69ced6060 --- /dev/null +++ b/src/test/ui/auto-traits/bad-generics-on-dyn.stderr @@ -0,0 +1,11 @@ +error[E0567]: auto traits cannot have generic parameters + --> $DIR/bad-generics-on-dyn.rs:3:18 + | +LL | auto trait Trait1<'a> {} + | ------^^^^ help: remove the parameters + | | + | auto trait cannot have generic parameters + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0567`. From 3bf7d88ef138957c998bb71e048c3e03a71661b5 Mon Sep 17 00:00:00 2001 From: Will Crichton Date: Sun, 4 Dec 2022 21:07:55 -0800 Subject: [PATCH 057/115] Add -Z maximal-hir-to-mir-coverage flag --- compiler/rustc_interface/src/tests.rs | 1 + compiler/rustc_middle/src/lint.rs | 10 ++++++++++ compiler/rustc_session/src/options.rs | 3 +++ src/test/rustdoc-ui/z-help.stdout | 1 + src/test/ui/maximal_mir_to_hir_coverage.rs | 10 ++++++++++ 5 files changed, 25 insertions(+) create mode 100644 src/test/ui/maximal_mir_to_hir_coverage.rs diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index a6205f4d3a53..2b8f6557c829 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -747,6 +747,7 @@ fn test_unstable_options_tracking_hash() { tracked!(link_only, true); tracked!(llvm_plugins, vec![String::from("plugin_name")]); tracked!(location_detail, LocationDetail { file: true, line: false, column: false }); + tracked!(maximal_hir_to_mir_coverage, true); tracked!(merge_functions, Some(MergeFunctions::Disabled)); tracked!(mir_emit_retag, true); tracked!(mir_enable_passes, vec![("DestProp".to_string(), false)]); diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index 51df42f6d14e..bde3e28c1345 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -173,6 +173,16 @@ impl TyCtxt<'_> { /// Walks upwards from `id` to find a node which might change lint levels with attributes. /// It stops at `bound` and just returns it if reached. pub fn maybe_lint_level_root_bounded(self, mut id: HirId, bound: HirId) -> HirId { + // Some consumers of rustc need to map MIR locations back to HIR nodes. Currently the + // the only part of rustc that tracks MIR -> HIR is the `SourceScopeLocalData::lint_root` + // field that tracks lint levels for MIR locations. Normally the number of source scopes + // is limited to the set of nodes with lint annotations. The -Zmaximal-hir-to-mir-coverage + // flag changes this behavior to maximize the number of source scopes, increasing the + // granularity of the MIR->HIR mapping. + if self.sess.opts.unstable_opts.maximal_hir_to_mir_coverage { + return id; + } + let hir = self.hir(); loop { if id == bound { diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 01a9361e7867..8e9198b79dff 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1382,6 +1382,9 @@ options! { "list the symbols defined by a library crate (default: no)"), macro_backtrace: bool = (false, parse_bool, [UNTRACKED], "show macro backtraces (default: no)"), + maximal_hir_to_mir_coverage: bool = (false, parse_bool, [TRACKED], + "save as much information as possible about the correspondence between MIR and HIR \ + as source scopes (default: no)"), merge_functions: Option = (None, parse_merge_functions, [TRACKED], "control the operation of the MergeFunctions LLVM pass, taking \ the same values as the target option of the same name"), diff --git a/src/test/rustdoc-ui/z-help.stdout b/src/test/rustdoc-ui/z-help.stdout index 551548030986..94cf7b94241d 100644 --- a/src/test/rustdoc-ui/z-help.stdout +++ b/src/test/rustdoc-ui/z-help.stdout @@ -77,6 +77,7 @@ -Z location-detail=val -- what location details should be tracked when using caller_location, either `none`, or a comma separated list of location details, for which valid options are `file`, `line`, and `column` (default: `file,line,column`) -Z ls=val -- list the symbols defined by a library crate (default: no) -Z macro-backtrace=val -- show macro backtraces (default: no) + -Z maximal-hir-to-mir-coverage=val -- save as much information as possible about the correspondence between MIR and HIR as source scopes (default: no) -Z merge-functions=val -- control the operation of the MergeFunctions LLVM pass, taking the same values as the target option of the same name -Z meta-stats=val -- gather metadata statistics (default: no) -Z mir-emit-retag=val -- emit Retagging MIR statements, interpreted e.g., by miri; implies -Zmir-opt-level=0 (default: no) diff --git a/src/test/ui/maximal_mir_to_hir_coverage.rs b/src/test/ui/maximal_mir_to_hir_coverage.rs new file mode 100644 index 000000000000..5ca54633f219 --- /dev/null +++ b/src/test/ui/maximal_mir_to_hir_coverage.rs @@ -0,0 +1,10 @@ +// compile-flags: -Zmaximal-hir-to-mir-coverage +// run-pass + +// Just making sure this flag is accepted and doesn't crash the compiler + +fn main() { + let x = 1; + let y = x + 1; + println!("{y}"); +} From 58110572fb23e0ad1944bdf3d8cdb3f84cb91aa2 Mon Sep 17 00:00:00 2001 From: Rageking8 Date: Mon, 5 Dec 2022 16:42:36 +0800 Subject: [PATCH 058/115] fix dupe word typos --- compiler/rustc_const_eval/src/const_eval/machine.rs | 2 +- compiler/rustc_mir_dataflow/src/value_analysis.rs | 2 +- compiler/rustc_resolve/src/late.rs | 2 +- library/core/src/iter/sources/repeat_n.rs | 2 +- library/core/src/str/pattern.rs | 2 +- library/std/src/sync/mpmc/array.rs | 2 +- library/std/src/thread/scoped.rs | 2 +- .../match-requires-both-partialeq-and-eq.rs | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 04e68b964552..3dfded2d930a 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -240,7 +240,7 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> { let align = ImmTy::from_uint(target_align, args[1].layout).into(); let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty())?; - // We replace the entire entire function call with a "tail call". + // We replace the entire function call with a "tail call". // Note that this happens before the frame of the original function // is pushed on the stack. self.eval_fn_call( diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index cc69a1bb02db..7df011422641 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -406,7 +406,7 @@ impl Clone for StateData { /// The dataflow state for an instance of [`ValueAnalysis`]. /// /// Every instance specifies a lattice that represents the possible values of a single tracked -/// place. If we call this lattice `V` and set set of tracked places `P`, then a [`State`] is an +/// place. If we call this lattice `V` and set of tracked places `P`, then a [`State`] is an /// element of `{unreachable} ∪ (P -> V)`. This again forms a lattice, where the bottom element is /// `unreachable` and the top element is the mapping `p ↦ ⊤`. Note that the mapping `p ↦ ⊥` is not /// the bottom element (because joining an unreachable and any other reachable state yields a diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 51a53f7b37cc..cf241b8922d6 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1927,7 +1927,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { // We have a single lifetime => success. elision_lifetime = Elision::Param(res) } else { - // We have have multiple lifetimes => error. + // We have multiple lifetimes => error. elision_lifetime = Elision::Err; } } diff --git a/library/core/src/iter/sources/repeat_n.rs b/library/core/src/iter/sources/repeat_n.rs index dc69bf4df595..fd8d25ce1a55 100644 --- a/library/core/src/iter/sources/repeat_n.rs +++ b/library/core/src/iter/sources/repeat_n.rs @@ -20,7 +20,7 @@ use crate::mem::ManuallyDrop; /// #![feature(iter_repeat_n)] /// use std::iter; /// -/// // four of the the number four: +/// // four of the number four: /// let mut four_fours = iter::repeat_n(4, 4); /// /// assert_eq!(Some(4), four_fours.next()); diff --git a/library/core/src/str/pattern.rs b/library/core/src/str/pattern.rs index d76d6f8b2a2d..19da6d2fbecb 100644 --- a/library/core/src/str/pattern.rs +++ b/library/core/src/str/pattern.rs @@ -1894,7 +1894,7 @@ unsafe fn small_slice_eq(x: &[u8], y: &[u8]) -> bool { // Thus, derefencing both `px` and `py` in the loop below is safe. // // Moreover, we set `pxend` and `pyend` to be 4 bytes before the actual - // end of of `px` and `py`. Thus, the final dereference outside of the + // end of `px` and `py`. Thus, the final dereference outside of the // loop is guaranteed to be valid. (The final comparison will overlap with // the last comparison done in the loop for lengths that aren't multiples // of four.) diff --git a/library/std/src/sync/mpmc/array.rs b/library/std/src/sync/mpmc/array.rs index 4db7b4990b97..f71edc6c525a 100644 --- a/library/std/src/sync/mpmc/array.rs +++ b/library/std/src/sync/mpmc/array.rs @@ -225,7 +225,7 @@ impl Channel { let slot = unsafe { self.buffer.get_unchecked(index) }; let stamp = slot.stamp.load(Ordering::Acquire); - // If the the stamp is ahead of the head by 1, we may attempt to pop. + // If the stamp is ahead of the head by 1, we may attempt to pop. if head + 1 == stamp { let new = if index + 1 < self.cap { // Same lap, incremented index. diff --git a/library/std/src/thread/scoped.rs b/library/std/src/thread/scoped.rs index e6dbf35bd028..ada69aa8269f 100644 --- a/library/std/src/thread/scoped.rs +++ b/library/std/src/thread/scoped.rs @@ -46,7 +46,7 @@ impl ScopeData { // We check for 'overflow' with usize::MAX / 2, to make sure there's no // chance it overflows to 0, which would result in unsoundness. if self.num_running_threads.fetch_add(1, Ordering::Relaxed) > usize::MAX / 2 { - // This can only reasonably happen by mem::forget()'ing many many ScopedJoinHandles. + // This can only reasonably happen by mem::forget()'ing a lot of ScopedJoinHandles. self.decrement_num_running_threads(false); panic!("too many running threads in thread scope"); } diff --git a/src/test/ui/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.rs b/src/test/ui/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.rs index 6b7d94603b56..a8deb8a7550b 100644 --- a/src/test/ui/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.rs +++ b/src/test/ui/rfc-1445-restrict-constants-in-patterns/match-requires-both-partialeq-and-eq.rs @@ -5,7 +5,7 @@ struct Foo { impl PartialEq for Foo { fn eq(&self, _: &Foo) -> bool { - false // ha ha sucker! + false // ha ha! } } From 8980d9a76d68f1b75f104c955aaafb0b0d0d58bc Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 5 Dec 2022 19:31:36 +1100 Subject: [PATCH 059/115] Remove `{Early,Late}LintPassObjects`. `EarlyContextAndPass` wraps a single early lint pass. We aggregate multiple passes into that single pass by using `EarlyLintPassObjects`. This commit removes `EarlyLintPassObjects` by changing `EarlyContextAndPass` into `EarlyContextAndPasses`. I.e. it just removes a level of indirection. This makes the code simpler and slightly faster. The commit does likewise for late lints. --- compiler/rustc_lint/src/early.rs | 107 ++++++++++++------------------- compiler/rustc_lint/src/late.rs | 44 +++---------- 2 files changed, 51 insertions(+), 100 deletions(-) diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs index 215df567e0e0..52363b0be2db 100644 --- a/compiler/rustc_lint/src/early.rs +++ b/compiler/rustc_lint/src/early.rs @@ -20,21 +20,23 @@ use rustc_ast::ptr::P; use rustc_ast::visit::{self as ast_visit, Visitor}; use rustc_ast::{self as ast, walk_list, HasAttrs}; use rustc_middle::ty::RegisteredTools; -use rustc_session::lint::{BufferedEarlyLint, LintBuffer, LintPass}; +use rustc_session::lint::{BufferedEarlyLint, LintBuffer}; use rustc_session::Session; use rustc_span::symbol::Ident; use rustc_span::Span; -macro_rules! run_early_pass { ($cx:expr, $f:ident, $($args:expr),*) => ({ - $cx.pass.$f(&$cx.context, $($args),*); +macro_rules! run_early_passes { ($cx:expr, $f:ident, $($args:expr),*) => ({ + for pass in $cx.passes.iter_mut() { + pass.$f(&$cx.context, $($args),*); + } }) } -pub struct EarlyContextAndPass<'a, T: EarlyLintPass> { +pub struct EarlyContextAndPasses<'a> { context: EarlyContext<'a>, - pass: T, + passes: Vec, } -impl<'a, T: EarlyLintPass> EarlyContextAndPass<'a, T> { +impl<'a> EarlyContextAndPasses<'a> { fn check_id(&mut self, id: ast::NodeId) { for early_lint in self.context.buffered.take(id) { let BufferedEarlyLint { span, msg, node_id: _, lint_id, diagnostic } = early_lint; @@ -61,27 +63,27 @@ impl<'a, T: EarlyLintPass> EarlyContextAndPass<'a, T> { self.check_id(id); debug!("early context: enter_attrs({:?})", attrs); - run_early_pass!(self, enter_lint_attrs, attrs); + run_early_passes!(self, enter_lint_attrs, attrs); f(self); debug!("early context: exit_attrs({:?})", attrs); - run_early_pass!(self, exit_lint_attrs, attrs); + run_early_passes!(self, exit_lint_attrs, attrs); self.context.builder.pop(push); } } -impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> { +impl<'a> ast_visit::Visitor<'a> for EarlyContextAndPasses<'a> { fn visit_param(&mut self, param: &'a ast::Param) { self.with_lint_attrs(param.id, ¶m.attrs, |cx| { - run_early_pass!(cx, check_param, param); + run_early_passes!(cx, check_param, param); ast_visit::walk_param(cx, param); }); } fn visit_item(&mut self, it: &'a ast::Item) { self.with_lint_attrs(it.id, &it.attrs, |cx| { - run_early_pass!(cx, check_item, it); + run_early_passes!(cx, check_item, it); ast_visit::walk_item(cx, it); - run_early_pass!(cx, check_item_post, it); + run_early_passes!(cx, check_item_post, it); }) } @@ -92,10 +94,10 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> } fn visit_pat(&mut self, p: &'a ast::Pat) { - run_early_pass!(self, check_pat, p); + run_early_passes!(self, check_pat, p); self.check_id(p.id); ast_visit::walk_pat(self, p); - run_early_pass!(self, check_pat_post, p); + run_early_passes!(self, check_pat_post, p); } fn visit_pat_field(&mut self, field: &'a ast::PatField) { @@ -111,7 +113,7 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> fn visit_expr(&mut self, e: &'a ast::Expr) { self.with_lint_attrs(e.id, &e.attrs, |cx| { - run_early_pass!(cx, check_expr, e); + run_early_passes!(cx, check_expr, e); ast_visit::walk_expr(cx, e); }) } @@ -132,7 +134,7 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> // Note that statements get their attributes from // the AST struct that they wrap (e.g. an item) self.with_lint_attrs(s.id, s.attrs(), |cx| { - run_early_pass!(cx, check_stmt, s); + run_early_passes!(cx, check_stmt, s); cx.check_id(s.id); }); // The visitor for the AST struct wrapped @@ -143,7 +145,7 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> } fn visit_fn(&mut self, fk: ast_visit::FnKind<'a>, span: Span, id: ast::NodeId) { - run_early_pass!(self, check_fn, fk, span, id); + run_early_passes!(self, check_fn, fk, span, id); self.check_id(id); ast_visit::walk_fn(self, fk); @@ -171,37 +173,37 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> fn visit_variant(&mut self, v: &'a ast::Variant) { self.with_lint_attrs(v.id, &v.attrs, |cx| { - run_early_pass!(cx, check_variant, v); + run_early_passes!(cx, check_variant, v); ast_visit::walk_variant(cx, v); }) } fn visit_ty(&mut self, t: &'a ast::Ty) { - run_early_pass!(self, check_ty, t); + run_early_passes!(self, check_ty, t); self.check_id(t.id); ast_visit::walk_ty(self, t); } fn visit_ident(&mut self, ident: Ident) { - run_early_pass!(self, check_ident, ident); + run_early_passes!(self, check_ident, ident); } fn visit_local(&mut self, l: &'a ast::Local) { self.with_lint_attrs(l.id, &l.attrs, |cx| { - run_early_pass!(cx, check_local, l); + run_early_passes!(cx, check_local, l); ast_visit::walk_local(cx, l); }) } fn visit_block(&mut self, b: &'a ast::Block) { - run_early_pass!(self, check_block, b); + run_early_passes!(self, check_block, b); self.check_id(b.id); ast_visit::walk_block(self, b); } fn visit_arm(&mut self, a: &'a ast::Arm) { self.with_lint_attrs(a.id, &a.attrs, |cx| { - run_early_pass!(cx, check_arm, a); + run_early_passes!(cx, check_arm, a); ast_visit::walk_arm(cx, a); }) } @@ -220,19 +222,19 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> } fn visit_generic_arg(&mut self, arg: &'a ast::GenericArg) { - run_early_pass!(self, check_generic_arg, arg); + run_early_passes!(self, check_generic_arg, arg); ast_visit::walk_generic_arg(self, arg); } fn visit_generic_param(&mut self, param: &'a ast::GenericParam) { self.with_lint_attrs(param.id, ¶m.attrs, |cx| { - run_early_pass!(cx, check_generic_param, param); + run_early_passes!(cx, check_generic_param, param); ast_visit::walk_generic_param(cx, param); }); } fn visit_generics(&mut self, g: &'a ast::Generics) { - run_early_pass!(self, check_generics, g); + run_early_passes!(self, check_generics, g); ast_visit::walk_generics(self, g); } @@ -241,18 +243,18 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> } fn visit_poly_trait_ref(&mut self, t: &'a ast::PolyTraitRef) { - run_early_pass!(self, check_poly_trait_ref, t); + run_early_passes!(self, check_poly_trait_ref, t); ast_visit::walk_poly_trait_ref(self, t); } fn visit_assoc_item(&mut self, item: &'a ast::AssocItem, ctxt: ast_visit::AssocCtxt) { self.with_lint_attrs(item.id, &item.attrs, |cx| match ctxt { ast_visit::AssocCtxt::Trait => { - run_early_pass!(cx, check_trait_item, item); + run_early_passes!(cx, check_trait_item, item); ast_visit::walk_assoc_item(cx, item, ctxt); } ast_visit::AssocCtxt::Impl => { - run_early_pass!(cx, check_impl_item, item); + run_early_passes!(cx, check_impl_item, item); ast_visit::walk_assoc_item(cx, item, ctxt); } }); @@ -273,45 +275,20 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> } fn visit_attribute(&mut self, attr: &'a ast::Attribute) { - run_early_pass!(self, check_attribute, attr); + run_early_passes!(self, check_attribute, attr); } fn visit_mac_def(&mut self, mac: &'a ast::MacroDef, id: ast::NodeId) { - run_early_pass!(self, check_mac_def, mac); + run_early_passes!(self, check_mac_def, mac); self.check_id(id); } fn visit_mac_call(&mut self, mac: &'a ast::MacCall) { - run_early_pass!(self, check_mac, mac); + run_early_passes!(self, check_mac, mac); ast_visit::walk_mac(self, mac); } } -struct EarlyLintPassObjects<'a> { - lints: &'a mut [EarlyLintPassObject], -} - -#[allow(rustc::lint_pass_impl_without_macro)] -impl LintPass for EarlyLintPassObjects<'_> { - fn name(&self) -> &'static str { - panic!() - } -} - -macro_rules! early_lint_pass_impl { - ([], [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => ( - impl EarlyLintPass for EarlyLintPassObjects<'_> { - $(fn $name(&mut self, context: &EarlyContext<'_>, $($param: $arg),*) { - for obj in self.lints.iter_mut() { - obj.$name(context, $($param),*); - } - })* - } - ) -} - -crate::early_lint_methods!(early_lint_pass_impl, []); - /// Early lints work on different nodes - either on the crate root, or on freshly loaded modules. /// This trait generalizes over those nodes. pub trait EarlyCheckNode<'a>: Copy { @@ -319,7 +296,7 @@ pub trait EarlyCheckNode<'a>: Copy { fn attrs<'b>(self) -> &'b [ast::Attribute] where 'a: 'b; - fn check<'b>(self, cx: &mut EarlyContextAndPass<'b, impl EarlyLintPass>) + fn check<'b>(self, cx: &mut EarlyContextAndPasses<'b>) where 'a: 'b; } @@ -334,13 +311,13 @@ impl<'a> EarlyCheckNode<'a> for &'a ast::Crate { { &self.attrs } - fn check<'b>(self, cx: &mut EarlyContextAndPass<'b, impl EarlyLintPass>) + fn check<'b>(self, cx: &mut EarlyContextAndPasses<'b>) where 'a: 'b, { - run_early_pass!(cx, check_crate, self); + run_early_passes!(cx, check_crate, self); ast_visit::walk_crate(cx, self); - run_early_pass!(cx, check_crate_post, self); + run_early_passes!(cx, check_crate_post, self); } } @@ -354,7 +331,7 @@ impl<'a> EarlyCheckNode<'a> for (ast::NodeId, &'a [ast::Attribute], &'a [P(self, cx: &mut EarlyContextAndPass<'b, impl EarlyLintPass>) + fn check<'b>(self, cx: &mut EarlyContextAndPasses<'b>) where 'a: 'b, { @@ -374,10 +351,10 @@ pub fn check_ast_node<'a>( ) { let passes = if pre_expansion { &lint_store.pre_expansion_passes } else { &lint_store.early_passes }; - let mut passes: Vec<_> = passes.iter().map(|p| (p)()).collect(); + let mut passes: Vec = passes.iter().map(|p| (p)()).collect(); passes.push(Box::new(builtin_lints)); - let mut cx = EarlyContextAndPass { + let mut cx = EarlyContextAndPasses { context: EarlyContext::new( sess, !pre_expansion, @@ -385,7 +362,7 @@ pub fn check_ast_node<'a>( registered_tools, lint_buffer.unwrap_or_default(), ), - pass: EarlyLintPassObjects { lints: &mut passes[..] }, + passes, }; cx.with_lint_attrs(check_node.id(), check_node.attrs(), |cx| check_node.check(cx)); diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs index e1aedc26d1b0..8a50cb1f19ef 100644 --- a/compiler/rustc_lint/src/late.rs +++ b/compiler/rustc_lint/src/late.rs @@ -23,7 +23,6 @@ use rustc_hir::intravisit as hir_visit; use rustc_hir::intravisit::Visitor; use rustc_middle::hir::nested_filter; use rustc_middle::ty::{self, TyCtxt}; -use rustc_session::lint::LintPass; use rustc_span::Span; use std::any::Any; @@ -37,15 +36,17 @@ pub fn unerased_lint_store(tcx: TyCtxt<'_>) -> &LintStore { } macro_rules! lint_callback { ($cx:expr, $f:ident, $($args:expr),*) => ({ - $cx.pass.$f(&$cx.context, $($args),*); + for pass in $cx.passes.iter_mut() { + pass.$f(&$cx.context, $($args),*); + } }) } -struct LateContextAndPass<'tcx, T: LateLintPass<'tcx>> { +struct LateContextAndPasses<'tcx> { context: LateContext<'tcx>, - pass: T, + passes: Vec>, } -impl<'tcx, T: LateLintPass<'tcx>> LateContextAndPass<'tcx, T> { +impl<'tcx> LateContextAndPasses<'tcx> { /// Merge the lints specified by any lint attributes into the /// current lint context, call the provided function, then reset the /// lints in effect to their previous state. @@ -81,7 +82,7 @@ impl<'tcx, T: LateLintPass<'tcx>> LateContextAndPass<'tcx, T> { } } -impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPass<'tcx, T> { +impl<'tcx> hir_visit::Visitor<'tcx> for LateContextAndPasses<'tcx> { type NestedFilter = nested_filter::All; /// Because lints are scoped lexically, we want to walk nested @@ -301,31 +302,6 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas } } -struct LateLintPassObjects<'a, 'tcx> { - lints: &'a mut [LateLintPassObject<'tcx>], -} - -#[allow(rustc::lint_pass_impl_without_macro)] -impl LintPass for LateLintPassObjects<'_, '_> { - fn name(&self) -> &'static str { - panic!() - } -} - -macro_rules! late_lint_pass_impl { - ([], [$hir:tt], [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => { - impl<$hir> LateLintPass<$hir> for LateLintPassObjects<'_, $hir> { - $(fn $name(&mut self, context: &LateContext<$hir>, $($param: $arg),*) { - for obj in self.lints.iter_mut() { - obj.$name(context, $($param),*); - } - })* - } - }; -} - -crate::late_lint_methods!(late_lint_pass_impl, [], ['tcx]); - pub(super) fn late_lint_mod<'tcx, T: LateLintPass<'tcx> + 'tcx>( tcx: TyCtxt<'tcx>, module_def_id: LocalDefId, @@ -346,9 +322,8 @@ pub(super) fn late_lint_mod<'tcx, T: LateLintPass<'tcx> + 'tcx>( let mut passes: Vec<_> = unerased_lint_store(tcx).late_module_passes.iter().map(|pass| (pass)(tcx)).collect(); passes.push(Box::new(builtin_lints)); - let pass = LateLintPassObjects { lints: &mut passes[..] }; - let mut cx = LateContextAndPass { context, pass }; + let mut cx = LateContextAndPasses { context, passes }; let (module, _span, hir_id) = tcx.hir().get_module(module_def_id); cx.process_mod(module, hir_id); @@ -377,9 +352,8 @@ fn late_lint_crate<'tcx, T: LateLintPass<'tcx> + 'tcx>(tcx: TyCtxt<'tcx>, builti let mut passes = unerased_lint_store(tcx).late_passes.iter().map(|p| (p)(tcx)).collect::>(); passes.push(Box::new(builtin_lints)); - let pass = LateLintPassObjects { lints: &mut passes[..] }; - let mut cx = LateContextAndPass { context, pass }; + let mut cx = LateContextAndPasses { context, passes }; // Visit the whole crate. cx.with_lint_attrs(hir::CRATE_HIR_ID, |cx| { From 56aacb245ce484994ac2e0ecab72b477ad6dc362 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Mon, 5 Dec 2022 10:45:31 +0100 Subject: [PATCH 060/115] StableOrd: Address review comments. --- .../rustc_data_structures/src/fingerprint.rs | 2 +- .../src/stable_hasher.rs | 36 +++++++++---------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_data_structures/src/fingerprint.rs b/compiler/rustc_data_structures/src/fingerprint.rs index 6f0b9bff90a7..d98f4e43fe88 100644 --- a/compiler/rustc_data_structures/src/fingerprint.rs +++ b/compiler/rustc_data_structures/src/fingerprint.rs @@ -140,7 +140,7 @@ impl stable_hasher::StableHasherResult for Fingerprint { } } -impl_stable_ord_and_stable_hash_via_hash!(Fingerprint); +impl_stable_traits_for_trivial_type!(Fingerprint); impl Encodable for Fingerprint { #[inline] diff --git a/compiler/rustc_data_structures/src/stable_hasher.rs b/compiler/rustc_data_structures/src/stable_hasher.rs index d43b74c2740c..be70d30eeaf0 100644 --- a/compiler/rustc_data_structures/src/stable_hasher.rs +++ b/compiler/rustc_data_structures/src/stable_hasher.rs @@ -255,7 +255,7 @@ pub unsafe trait StableOrd: Ord {} /// here in this module. /// /// Use `#[derive(HashStable_Generic)]` instead. -macro_rules! impl_stable_ord_and_stable_hash_via_hash { +macro_rules! impl_stable_traits_for_trivial_type { ($t:ty) => { impl $crate::stable_hasher::HashStable for $t { #[inline] @@ -268,23 +268,23 @@ macro_rules! impl_stable_ord_and_stable_hash_via_hash { }; } -impl_stable_ord_and_stable_hash_via_hash!(i8); -impl_stable_ord_and_stable_hash_via_hash!(i16); -impl_stable_ord_and_stable_hash_via_hash!(i32); -impl_stable_ord_and_stable_hash_via_hash!(i64); -impl_stable_ord_and_stable_hash_via_hash!(isize); +impl_stable_traits_for_trivial_type!(i8); +impl_stable_traits_for_trivial_type!(i16); +impl_stable_traits_for_trivial_type!(i32); +impl_stable_traits_for_trivial_type!(i64); +impl_stable_traits_for_trivial_type!(isize); -impl_stable_ord_and_stable_hash_via_hash!(u8); -impl_stable_ord_and_stable_hash_via_hash!(u16); -impl_stable_ord_and_stable_hash_via_hash!(u32); -impl_stable_ord_and_stable_hash_via_hash!(u64); -impl_stable_ord_and_stable_hash_via_hash!(usize); +impl_stable_traits_for_trivial_type!(u8); +impl_stable_traits_for_trivial_type!(u16); +impl_stable_traits_for_trivial_type!(u32); +impl_stable_traits_for_trivial_type!(u64); +impl_stable_traits_for_trivial_type!(usize); -impl_stable_ord_and_stable_hash_via_hash!(u128); -impl_stable_ord_and_stable_hash_via_hash!(i128); +impl_stable_traits_for_trivial_type!(u128); +impl_stable_traits_for_trivial_type!(i128); -impl_stable_ord_and_stable_hash_via_hash!(char); -impl_stable_ord_and_stable_hash_via_hash!(()); +impl_stable_traits_for_trivial_type!(char); +impl_stable_traits_for_trivial_type!(()); impl HashStable for ! { fn hash_stable(&self, _ctx: &mut CTX, _hasher: &mut StableHasher) { @@ -590,8 +590,8 @@ where } } -impl_stable_ord_and_stable_hash_via_hash!(::std::path::Path); -impl_stable_ord_and_stable_hash_via_hash!(::std::path::PathBuf); +impl_stable_traits_for_trivial_type!(::std::path::Path); +impl_stable_traits_for_trivial_type!(::std::path::PathBuf); impl HashStable for ::std::collections::HashMap where @@ -635,7 +635,7 @@ where } } -impl HashStable for ::std::collections::BTreeSet +impl HashStable for ::std::collections::BTreeSet where K: HashStable + StableOrd, { From 125b729dddda053d022ae8db32d42fdf3d1ea48d Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Sat, 3 Dec 2022 13:36:39 +0000 Subject: [PATCH 061/115] Allow arbitrary keys in feeding API --- compiler/rustc_middle/src/ty/context.rs | 21 ++++++++++++++------- compiler/rustc_middle/src/ty/query.rs | 10 +++++----- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index c5683a9db947..40207c335a46 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1034,16 +1034,23 @@ pub struct FreeRegionInfo { /// This struct should only be created by `create_def`. #[derive(Copy, Clone)] -pub struct TyCtxtFeed<'tcx> { +pub struct TyCtxtFeed<'tcx, KEY: Copy> { pub tcx: TyCtxt<'tcx>, // Do not allow direct access, as downstream code must not mutate this field. - def_id: LocalDefId, + key: KEY, } -impl<'tcx> TyCtxtFeed<'tcx> { +impl<'tcx, KEY: Copy> TyCtxtFeed<'tcx, KEY> { + #[inline(always)] + pub fn key(&self) -> KEY { + self.key + } +} + +impl<'tcx> TyCtxtFeed<'tcx, LocalDefId> { #[inline(always)] pub fn def_id(&self) -> LocalDefId { - self.def_id + self.key } } @@ -1515,7 +1522,7 @@ impl<'tcx> TyCtxtAt<'tcx> { self, parent: LocalDefId, data: hir::definitions::DefPathData, - ) -> TyCtxtFeed<'tcx> { + ) -> TyCtxtFeed<'tcx, LocalDefId> { // This function modifies `self.definitions` using a side-effect. // We need to ensure that these side effects are re-run by the incr. comp. engine. // Depending on the forever-red node will tell the graph that the calling query @@ -1536,9 +1543,9 @@ impl<'tcx> TyCtxtAt<'tcx> { // This is fine because: // - those queries are `eval_always` so we won't miss their result changing; // - this write will have happened before these queries are called. - let def_id = self.definitions.write().create_def(parent, data); + let key = self.definitions.write().create_def(parent, data); - let feed = TyCtxtFeed { tcx: self.tcx, def_id }; + let feed = TyCtxtFeed { tcx: self.tcx, key }; feed.def_span(self.span); feed } diff --git a/compiler/rustc_middle/src/ty/query.rs b/compiler/rustc_middle/src/ty/query.rs index a7fd1754960a..e073fca92e78 100644 --- a/compiler/rustc_middle/src/ty/query.rs +++ b/compiler/rustc_middle/src/ty/query.rs @@ -330,11 +330,11 @@ macro_rules! define_callbacks { macro_rules! define_feedable { ($($(#[$attr:meta])* [$($modifiers:tt)*] fn $name:ident($($K:tt)*) -> $V:ty,)*) => { - impl<'tcx> TyCtxtFeed<'tcx> { - $($(#[$attr])* + $(impl<'tcx, K: IntoQueryParam<$($K)*> + Copy> TyCtxtFeed<'tcx, K> { + $(#[$attr])* #[inline(always)] pub fn $name(self, value: $V) -> query_stored::$name<'tcx> { - let key = self.def_id().into_query_param(); + let key = self.key().into_query_param(); opt_remap_env_constness!([$($modifiers)*][key]); let tcx = self.tcx; @@ -361,8 +361,8 @@ macro_rules! define_feedable { dep_graph::hash_result, ); cache.complete(key, value, dep_node_index) - })* - } + } + })* } } From f693b7848ea5b24ef3a503aa59e616492a9b0b22 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Sat, 3 Dec 2022 18:06:39 +0000 Subject: [PATCH 062/115] feed resolver_for_lowering instead of storing it in a field --- compiler/rustc_interface/src/passes.rs | 17 +++++++++++++++-- compiler/rustc_macros/src/query.rs | 4 ---- compiler/rustc_middle/src/arena.rs | 1 + compiler/rustc_middle/src/query/mod.rs | 2 +- compiler/rustc_middle/src/ty/context.rs | 19 +++++++++---------- compiler/rustc_middle/src/ty/mod.rs | 4 ++-- compiler/rustc_middle/src/ty/query.rs | 14 +++++++++++++- .../rustc_query_system/src/dep_graph/graph.rs | 15 +++++++++------ 8 files changed, 50 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 77c3270fe6a0..3e2ea77c07e5 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -12,6 +12,7 @@ use rustc_ast::{self as ast, visit}; use rustc_borrowck as mir_borrowck; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_data_structures::parallel; +use rustc_data_structures::steal::Steal; use rustc_data_structures::sync::{Lrc, OnceCell, WorkerLocal}; use rustc_errors::{ErrorGuaranteed, PResult}; use rustc_expand::base::{ExtCtxt, LintStoreExpand, ResolverExpand}; @@ -804,6 +805,12 @@ pub fn create_global_ctxt<'tcx>( TcxQueries::new(local_providers, extern_providers, query_result_on_disk_cache) }); + let ty::ResolverOutputs { + definitions, + global_ctxt: untracked_resolutions, + ast_lowering: untracked_resolver_for_lowering, + } = resolver_outputs; + let gcx = sess.time("setup_global_ctxt", || { global_ctxt.get_or_init(move || { TyCtxt::create_global_ctxt( @@ -811,7 +818,8 @@ pub fn create_global_ctxt<'tcx>( lint_store, arena, hir_arena, - resolver_outputs, + definitions, + untracked_resolutions, krate, dep_graph, queries.on_disk_cache.as_ref().map(OnDiskCache::as_dyn), @@ -823,7 +831,12 @@ pub fn create_global_ctxt<'tcx>( }) }); - QueryContext { gcx } + let mut qcx = QueryContext { gcx }; + qcx.enter(|tcx| { + tcx.feed_unit_query() + .resolver_for_lowering(tcx.arena.alloc(Steal::new(untracked_resolver_for_lowering))) + }); + qcx } /// Runs the resolution, type-checking, region checking and other diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs index 4047969724aa..789d83a0dd00 100644 --- a/compiler/rustc_macros/src/query.rs +++ b/compiler/rustc_macros/src/query.rs @@ -364,10 +364,6 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream { modifiers.eval_always.is_none(), "Query {name} cannot be both `feedable` and `eval_always`." ); - assert!( - modifiers.no_hash.is_none(), - "Query {name} cannot be both `feedable` and `no_hash`." - ); feedable_queries.extend(quote! { #(#doc_comments)* [#attribute_stream] fn #name(#arg) #result, diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index e83106b1ee51..9aed75931bfc 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -28,6 +28,7 @@ macro_rules! arena_types { [decode] typeck_results: rustc_middle::ty::TypeckResults<'tcx>, [decode] borrowck_result: rustc_middle::mir::BorrowCheckResult<'tcx>, + [] resolver: rustc_data_structures::steal::Steal, [decode] unsafety_check_result: rustc_middle::mir::UnsafetyCheckResult, [decode] code_region: rustc_middle::mir::coverage::CodeRegion, [] const_allocs: rustc_middle::mir::interpret::Allocation, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index d6dea0e9f30f..f2f2b22f52a3 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -33,7 +33,7 @@ rustc_queries! { } query resolver_for_lowering(_: ()) -> &'tcx Steal { - eval_always + feedable no_hash desc { "getting the resolver for lowering" } } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 40207c335a46..c39d04d38193 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -81,7 +81,7 @@ use std::mem; use std::ops::{Bound, Deref}; use std::sync::Arc; -use super::{ImplPolarity, ResolverOutputs, RvalueScopes}; +use super::{ImplPolarity, RvalueScopes}; pub trait OnDiskCache<'tcx>: rustc_data_structures::sync::Sync { /// Creates a new `OnDiskCache` instance from the serialized data in `data`. @@ -1040,6 +1040,12 @@ pub struct TyCtxtFeed<'tcx, KEY: Copy> { key: KEY, } +impl<'tcx> TyCtxt<'tcx> { + pub fn feed_unit_query(self) -> TyCtxtFeed<'tcx, ()> { + TyCtxtFeed { tcx: self, key: () } + } +} + impl<'tcx, KEY: Copy> TyCtxtFeed<'tcx, KEY> { #[inline(always)] pub fn key(&self) -> KEY { @@ -1106,7 +1112,6 @@ pub struct GlobalCtxt<'tcx> { /// Output of the resolver. pub(crate) untracked_resolutions: ty::ResolverGlobalCtxt, - untracked_resolver_for_lowering: Steal, /// The entire crate as AST. This field serves as the input for the hir_crate query, /// which lowers it from AST to HIR. It must not be read or used by anything else. pub untracked_crate: Steal>, @@ -1269,7 +1274,8 @@ impl<'tcx> TyCtxt<'tcx> { lint_store: Lrc, arena: &'tcx WorkerLocal>, hir_arena: &'tcx WorkerLocal>, - resolver_outputs: ResolverOutputs, + definitions: Definitions, + untracked_resolutions: ty::ResolverGlobalCtxt, krate: Lrc, dep_graph: DepGraph, on_disk_cache: Option<&'tcx dyn OnDiskCache<'tcx>>, @@ -1278,11 +1284,6 @@ impl<'tcx> TyCtxt<'tcx> { crate_name: &str, output_filenames: OutputFilenames, ) -> GlobalCtxt<'tcx> { - let ResolverOutputs { - definitions, - global_ctxt: untracked_resolutions, - ast_lowering: untracked_resolver_for_lowering, - } = resolver_outputs; let data_layout = s.target.parse_data_layout().unwrap_or_else(|err| { s.emit_fatal(err); }); @@ -1311,7 +1312,6 @@ impl<'tcx> TyCtxt<'tcx> { lifetimes: common_lifetimes, consts: common_consts, untracked_resolutions, - untracked_resolver_for_lowering: Steal::new(untracked_resolver_for_lowering), untracked_crate: Steal::new(krate), on_disk_cache, queries, @@ -3114,7 +3114,6 @@ fn ptr_eq(t: *const T, u: *const U) -> bool { pub fn provide(providers: &mut ty::query::Providers) { providers.resolutions = |tcx, ()| &tcx.untracked_resolutions; - providers.resolver_for_lowering = |tcx, ()| &tcx.untracked_resolver_for_lowering; providers.module_reexports = |tcx, id| tcx.resolutions(()).reexport_map.get(&id).map(|v| &v[..]); providers.crate_name = |tcx, id| { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index dd4ab3e8d30b..9e73236f8d59 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -82,8 +82,8 @@ pub use self::consts::{ pub use self::context::{ tls, CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, CtxtInterners, DeducedParamAttrs, FreeRegionInfo, GeneratorDiagnosticData, - GeneratorInteriorTypeCause, GlobalCtxt, Lift, OnDiskCache, TyCtxt, TypeckResults, UserType, - UserTypeAnnotationIndex, + GeneratorInteriorTypeCause, GlobalCtxt, Lift, OnDiskCache, TyCtxt, TyCtxtFeed, TypeckResults, + UserType, UserTypeAnnotationIndex, }; pub use self::instance::{Instance, InstanceDef, ShortInstance}; pub use self::list::List; diff --git a/compiler/rustc_middle/src/ty/query.rs b/compiler/rustc_middle/src/ty/query.rs index e073fca92e78..642900d3ab42 100644 --- a/compiler/rustc_middle/src/ty/query.rs +++ b/compiler/rustc_middle/src/ty/query.rs @@ -328,6 +328,18 @@ macro_rules! define_callbacks { }; } +macro_rules! hash_result { + ([]) => {{ + Some(dep_graph::hash_result) + }}; + ([(no_hash) $($rest:tt)*]) => {{ + None + }}; + ([$other:tt $($modifiers:tt)*]) => { + hash_result!([$($modifiers)*]) + }; +} + macro_rules! define_feedable { ($($(#[$attr:meta])* [$($modifiers:tt)*] fn $name:ident($($K:tt)*) -> $V:ty,)*) => { $(impl<'tcx, K: IntoQueryParam<$($K)*> + Copy> TyCtxtFeed<'tcx, K> { @@ -358,7 +370,7 @@ macro_rules! define_feedable { tcx, key, &value, - dep_graph::hash_result, + hash_result!([$($modifiers)*]), ); cache.complete(key, value, dep_node_index) } diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index 30d28ff34550..38c7c6cce676 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -510,7 +510,7 @@ impl DepGraph { cx: Ctxt, key: A, result: &R, - hash_result: fn(&mut StableHashingContext<'_>, &R) -> Fingerprint, + hash_result: Option, &R) -> Fingerprint>, ) -> DepNodeIndex { if let Some(data) = self.data.as_ref() { // The caller query has more dependencies than the node we are creating. We may @@ -521,10 +521,12 @@ impl DepGraph { // For sanity, we still check that the loaded stable hash and the new one match. if let Some(dep_node_index) = self.dep_node_index_of_opt(&node) { let _current_fingerprint = - crate::query::incremental_verify_ich(cx, result, &node, Some(hash_result)); + crate::query::incremental_verify_ich(cx, result, &node, hash_result); #[cfg(debug_assertions)] - data.current.record_edge(dep_node_index, node, _current_fingerprint); + if hash_result.is_some() { + data.current.record_edge(dep_node_index, node, _current_fingerprint); + } return dep_node_index; } @@ -539,8 +541,9 @@ impl DepGraph { }); let hashing_timer = cx.profiler().incr_result_hashing(); - let current_fingerprint = - cx.with_stable_hashing_context(|mut hcx| hash_result(&mut hcx, result)); + let current_fingerprint = hash_result.map(|hash_result| { + cx.with_stable_hashing_context(|mut hcx| hash_result(&mut hcx, result)) + }); let print_status = cfg!(debug_assertions) && cx.sess().opts.unstable_opts.dep_tasks; @@ -550,7 +553,7 @@ impl DepGraph { &data.previous, node, edges, - Some(current_fingerprint), + current_fingerprint, print_status, ); From f4c76b193d54eeb88b2c966612679d733536efaf Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 5 Dec 2022 08:15:30 -0800 Subject: [PATCH 063/115] Be more careful about unresolved exprs in suggestion --- .../rustc_hir_typeck/src/method/suggest.rs | 23 +++++++++++-------- .../path-to-method-sugg-unresolved-expr.rs | 4 ++++ ...path-to-method-sugg-unresolved-expr.stderr | 9 ++++++++ 3 files changed, 26 insertions(+), 10 deletions(-) create mode 100644 src/test/ui/typeck/path-to-method-sugg-unresolved-expr.rs create mode 100644 src/test/ui/typeck/path-to-method-sugg-unresolved-expr.stderr diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 9ba4ddfd5cf7..db93cfab2c0d 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -1482,15 +1482,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ident_name: Symbol, } + // FIXME: This really should be taking scoping, etc into account. impl<'v> Visitor<'v> for LetVisitor<'v> { fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) { - if let hir::StmtKind::Local(hir::Local { pat, init, .. }) = &ex.kind { - if let Binding(_, _, ident, ..) = pat.kind && - ident.name == self.ident_name { - self.result = *init; - } + if let hir::StmtKind::Local(hir::Local { pat, init, .. }) = &ex.kind + && let Binding(_, _, ident, ..) = pat.kind + && ident.name == self.ident_name + { + self.result = *init; + } else { + hir::intravisit::walk_stmt(self, ex); } - hir::intravisit::walk_stmt(self, ex); } } @@ -1498,9 +1500,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { visitor.visit_body(&body); let parent = self.tcx.hir().get_parent_node(seg1.hir_id); - if let Some(Node::Expr(call_expr)) = self.tcx.hir().find(parent) && - let Some(expr) = visitor.result { - let self_ty = self.node_ty(expr.hir_id); + if let Some(Node::Expr(call_expr)) = self.tcx.hir().find(parent) + && let Some(expr) = visitor.result + && let Some(self_ty) = self.node_ty_opt(expr.hir_id) + { let probe = self.lookup_probe( seg2.ident, self_ty, @@ -1513,7 +1516,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { sm.span_extend_while(seg1.ident.span.shrink_to_hi(), |c| c == ':').unwrap(), "you may have meant to call an instance method", ".".to_string(), - Applicability::MaybeIncorrect + Applicability::MaybeIncorrect, ); } } diff --git a/src/test/ui/typeck/path-to-method-sugg-unresolved-expr.rs b/src/test/ui/typeck/path-to-method-sugg-unresolved-expr.rs new file mode 100644 index 000000000000..fb56b394493d --- /dev/null +++ b/src/test/ui/typeck/path-to-method-sugg-unresolved-expr.rs @@ -0,0 +1,4 @@ +fn main() { + let page_size = page_size::get(); + //~^ ERROR failed to resolve: use of undeclared crate or module `page_size` +} diff --git a/src/test/ui/typeck/path-to-method-sugg-unresolved-expr.stderr b/src/test/ui/typeck/path-to-method-sugg-unresolved-expr.stderr new file mode 100644 index 000000000000..b01e30be54de --- /dev/null +++ b/src/test/ui/typeck/path-to-method-sugg-unresolved-expr.stderr @@ -0,0 +1,9 @@ +error[E0433]: failed to resolve: use of undeclared crate or module `page_size` + --> $DIR/path-to-method-sugg-unresolved-expr.rs:2:21 + | +LL | let page_size = page_size::get(); + | ^^^^^^^^^ use of undeclared crate or module `page_size` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0433`. From 65072ee775e681d40876580d6e551d4ee046b3c1 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 5 Dec 2022 09:15:43 -0700 Subject: [PATCH 064/115] rustdoc: remove no-op mobile CSS `.sidebar { margin: 0; padding: 0 }` This isn't overriding anything, because the sidebar never has a margin or padding on it. --- src/librustdoc/html/static/css/rustdoc.css | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index f44797fe55f1..c1c1241ba543 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -1660,8 +1660,6 @@ in storage.js /* Hide the sidebar offscreen while not in use. Doing this instead of display: none means the sidebar stays visible for screen readers, which is useful for navigation. */ left: -1000px; - margin: 0; - padding: 0; z-index: 11; /* Reduce height slightly to account for mobile topbar. */ height: calc(100vh - 45px); From a192284a94b18800b8b4255b9d3c886b2cd38596 Mon Sep 17 00:00:00 2001 From: rustbot <47979223+rustbot@users.noreply.github.com> Date: Mon, 5 Dec 2022 12:01:18 -0500 Subject: [PATCH 065/115] Update books --- src/doc/book | 2 +- src/doc/embedded-book | 2 +- src/doc/nomicon | 2 +- src/doc/reference | 2 +- src/doc/rust-by-example | 2 +- src/doc/rustc-dev-guide | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/doc/book b/src/doc/book index 3f64052c048c..a60f4316ec92 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit 3f64052c048c6def93b94a2b514ee88bba918744 +Subproject commit a60f4316ec923a5ac2ed6a2eba6960edb832d855 diff --git a/src/doc/embedded-book b/src/doc/embedded-book index c533348edd69..19f798d44883 160000 --- a/src/doc/embedded-book +++ b/src/doc/embedded-book @@ -1 +1 @@ -Subproject commit c533348edd69f11a8f4225d633a05d7093fddbf3 +Subproject commit 19f798d448835a4888e3b3eae7fe69f1d61d8681 diff --git a/src/doc/nomicon b/src/doc/nomicon index 05532356e7a4..ae406aa5287a 160000 --- a/src/doc/nomicon +++ b/src/doc/nomicon @@ -1 +1 @@ -Subproject commit 05532356e7a4dbea2330aabb77611f5179493bb8 +Subproject commit ae406aa5287a9e025abb72343aaceec98458c117 diff --git a/src/doc/reference b/src/doc/reference index 9f0cc13ffcd2..3ae62681ff23 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 9f0cc13ffcd27c1fbe1ab766a9491e15ddcf4d19 +Subproject commit 3ae62681ff236d5528ef7c8c28ba7c6b2ecc6731 diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index 2b15c0abf2ba..a9869b4a3c4c 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit 2b15c0abf2bada6e00553814336bc3e2d8399097 +Subproject commit a9869b4a3c4cac3bc6099b41f088679e268400b8 diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide index d0dc6c97a648..e269950a57fa 160000 --- a/src/doc/rustc-dev-guide +++ b/src/doc/rustc-dev-guide @@ -1 +1 @@ -Subproject commit d0dc6c97a6486f68bac782fff135086eae6d77ec +Subproject commit e269950a57fa6fcda356426545fb5aa3691a7ced From d5cb5fb1853952c0e5377e86a09c0fcf5bf2a829 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Mon, 5 Dec 2022 18:02:47 +0100 Subject: [PATCH 066/115] normalize inherent associated types after substitution --- .../rustc_hir_analysis/src/astconv/mod.rs | 1 + .../normalize-projection-0.rs | 22 +++++++++++++++++++ .../normalize-projection-1.rs | 22 +++++++++++++++++++ 3 files changed, 45 insertions(+) create mode 100644 src/test/ui/associated-inherent-types/normalize-projection-0.rs create mode 100644 src/test/ui/associated-inherent-types/normalize-projection-1.rs diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index f204d59d0055..66906b331da2 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -1930,6 +1930,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { adt_substs, ); let ty = tcx.bound_type_of(assoc_ty_did).subst(tcx, item_substs); + let ty = self.normalize_ty(span, ty); return Ok((ty, DefKind::AssocTy, assoc_ty_did)); } } diff --git a/src/test/ui/associated-inherent-types/normalize-projection-0.rs b/src/test/ui/associated-inherent-types/normalize-projection-0.rs new file mode 100644 index 000000000000..50763ecddf99 --- /dev/null +++ b/src/test/ui/associated-inherent-types/normalize-projection-0.rs @@ -0,0 +1,22 @@ +// check-pass + +#![feature(inherent_associated_types)] +#![allow(incomplete_features)] + +struct S(T); + +impl S { + type P = ::P; +} + +trait O { + type P; +} + +impl O for i32 { + type P = String; +} + +fn main() { + let _: S::P = String::new(); +} diff --git a/src/test/ui/associated-inherent-types/normalize-projection-1.rs b/src/test/ui/associated-inherent-types/normalize-projection-1.rs new file mode 100644 index 000000000000..2f7b2551a03e --- /dev/null +++ b/src/test/ui/associated-inherent-types/normalize-projection-1.rs @@ -0,0 +1,22 @@ +// check-pass + +#![feature(inherent_associated_types)] +#![allow(incomplete_features)] + +struct S; + +impl S { + type P = ::P; +} + +trait O { + type P; +} + +impl O for i32 { + type P = String; +} + +fn main() { + let _: S::P = String::new(); +} From da929fa63c7a9687de708587f170cbe7f874a495 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 5 Dec 2022 17:34:17 +0000 Subject: [PATCH 067/115] Make get_impl_future_output_ty work with AFIT --- .../src/infer/error_reporting/mod.rs | 10 +++++++- .../in-trait/return-type-suggestion.rs | 14 +++++++++++ .../in-trait/return-type-suggestion.stderr | 23 +++++++++++++++++++ 3 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/async-await/in-trait/return-type-suggestion.rs create mode 100644 src/test/ui/async-await/in-trait/return-type-suggestion.stderr diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 662136ca18df..3256ca1fb20f 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -341,7 +341,15 @@ pub fn unexpected_hidden_region_diagnostic<'tcx>( impl<'tcx> InferCtxt<'tcx> { pub fn get_impl_future_output_ty(&self, ty: Ty<'tcx>) -> Option> { - let ty::Opaque(def_id, substs) = *ty.kind() else { return None; }; + let (def_id, substs) = match *ty.kind() { + ty::Opaque(def_id, substs) => (def_id, substs), + ty::Projection(data) + if self.tcx.def_kind(data.item_def_id) == DefKind::ImplTraitPlaceholder => + { + (data.item_def_id, data.substs) + } + _ => return None, + }; let future_trait = self.tcx.require_lang_item(LangItem::Future, None); let item_def_id = self.tcx.associated_item_def_ids(future_trait)[0]; diff --git a/src/test/ui/async-await/in-trait/return-type-suggestion.rs b/src/test/ui/async-await/in-trait/return-type-suggestion.rs new file mode 100644 index 000000000000..3446761d119d --- /dev/null +++ b/src/test/ui/async-await/in-trait/return-type-suggestion.rs @@ -0,0 +1,14 @@ +// edition: 2021 + +#![feature(async_fn_in_trait)] +//~^ WARN the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes + +trait A { + async fn e() { + Ok(()) + //~^ ERROR mismatched types + //~| HELP consider using a semicolon here + } +} + +fn main() {} diff --git a/src/test/ui/async-await/in-trait/return-type-suggestion.stderr b/src/test/ui/async-await/in-trait/return-type-suggestion.stderr new file mode 100644 index 000000000000..5a9b15e54a00 --- /dev/null +++ b/src/test/ui/async-await/in-trait/return-type-suggestion.stderr @@ -0,0 +1,23 @@ +warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/return-type-suggestion.rs:3:12 + | +LL | #![feature(async_fn_in_trait)] + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #91611 for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0308]: mismatched types + --> $DIR/return-type-suggestion.rs:8:9 + | +LL | Ok(()) + | ^^^^^^- help: consider using a semicolon here: `;` + | | + | expected `()`, found enum `Result` + | + = note: expected unit type `()` + found enum `Result<(), _>` + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0308`. From a1fbc143729b140f51c4a93dfc5a9a54a9a20486 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 5 Dec 2022 19:06:32 +0000 Subject: [PATCH 068/115] Point at GAT where clause when unsatisfied --- .../src/traits/project.rs | 30 +++++++++++++++---- .../own-bound-span.rs | 17 +++++++++++ .../own-bound-span.stderr | 15 ++++++++++ ...ject-safety-supertrait-mentions-GAT.stderr | 6 ++-- 4 files changed, 60 insertions(+), 8 deletions(-) create mode 100644 src/test/ui/generic-associated-types/own-bound-span.rs create mode 100644 src/test/ui/generic-associated-types/own-bound-span.stderr diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 051660be9c47..71f6eae45aa5 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -2321,11 +2321,10 @@ fn assoc_ty_own_obligations<'cx, 'tcx>( nested: &mut Vec>, ) { let tcx = selcx.tcx(); - for predicate in tcx + let own = tcx .predicates_of(obligation.predicate.item_def_id) - .instantiate_own(tcx, obligation.predicate.substs) - .predicates - { + .instantiate_own(tcx, obligation.predicate.substs); + for (predicate, span) in std::iter::zip(own.predicates, own.spans) { let normalized = normalize_with_depth_to( selcx, obligation.param_env, @@ -2334,9 +2333,30 @@ fn assoc_ty_own_obligations<'cx, 'tcx>( predicate, nested, ); + + let nested_cause = if matches!( + obligation.cause.code(), + super::CompareImplItemObligation { .. } + | super::CheckAssociatedTypeBounds { .. } + | super::AscribeUserTypeProvePredicate(..) + ) { + obligation.cause.clone() + } else if span.is_dummy() { + ObligationCause::new( + obligation.cause.span, + obligation.cause.body_id, + super::ItemObligation(obligation.predicate.item_def_id), + ) + } else { + ObligationCause::new( + obligation.cause.span, + obligation.cause.body_id, + super::BindingObligation(obligation.predicate.item_def_id, span), + ) + }; nested.push(Obligation::with_depth( tcx, - obligation.cause.clone(), + nested_cause, obligation.recursion_depth + 1, obligation.param_env, normalized, diff --git a/src/test/ui/generic-associated-types/own-bound-span.rs b/src/test/ui/generic-associated-types/own-bound-span.rs new file mode 100644 index 000000000000..3699f7296f5d --- /dev/null +++ b/src/test/ui/generic-associated-types/own-bound-span.rs @@ -0,0 +1,17 @@ +struct S; + +trait D { + type P; + //~^ NOTE required by this bound in `D::P` + //~| NOTE required by a bound in `D::P` +} + +impl D for S { + type P = (); +} + +fn main() { + let _: ::P; + //~^ ERROR the trait bound `String: Copy` is not satisfied + //~| NOTE the trait `Copy` is not implemented for `String` +} diff --git a/src/test/ui/generic-associated-types/own-bound-span.stderr b/src/test/ui/generic-associated-types/own-bound-span.stderr new file mode 100644 index 000000000000..8ab8ea623b2c --- /dev/null +++ b/src/test/ui/generic-associated-types/own-bound-span.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `String: Copy` is not satisfied + --> $DIR/own-bound-span.rs:14:12 + | +LL | let _: ::P; + | ^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String` + | +note: required by a bound in `D::P` + --> $DIR/own-bound-span.rs:4:15 + | +LL | type P; + | ^^^^ required by this bound in `D::P` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/object-safety/object-safety-supertrait-mentions-GAT.stderr b/src/test/ui/object-safety/object-safety-supertrait-mentions-GAT.stderr index c1aaad31e812..f05b0cd65381 100644 --- a/src/test/ui/object-safety/object-safety-supertrait-mentions-GAT.stderr +++ b/src/test/ui/object-safety/object-safety-supertrait-mentions-GAT.stderr @@ -3,10 +3,10 @@ error[E0311]: the parameter type `Self` may not live long enough = help: consider adding an explicit lifetime bound `Self: 'a`... = note: ...so that the type `Self` will meet its required lifetime bounds... note: ...that is required by this bound - --> $DIR/object-safety-supertrait-mentions-GAT.rs:9:39 + --> $DIR/object-safety-supertrait-mentions-GAT.rs:6:15 | -LL | trait SuperTrait: for<'a> GatTrait = T> { - | ^^^^^^^^^^^ +LL | Self: 'a; + | ^^ error: associated item referring to unboxed trait object for its own trait --> $DIR/object-safety-supertrait-mentions-GAT.rs:10:20 From 32765fbe101f748ca33d190b0f37b79c23d61241 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 5 Dec 2022 11:15:09 -0700 Subject: [PATCH 069/115] rustdoc: simplify CSS selectors on top-doc and non-exhaustive toggles This code uses a special `hideme` class anyway, so just style that. --- src/librustdoc/html/static/css/rustdoc.css | 11 ++--------- src/test/rustdoc-gui/enum-variants.goml | 5 +++++ src/test/rustdoc-gui/src/test_docs/lib.rs | 1 + src/test/rustdoc-gui/toggle-docs.goml | 4 ++++ 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index f44797fe55f1..d9edaf97670b 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -195,8 +195,7 @@ h1, h2, h3, h4, h5, h6, span.since, a.srclink, #help-button > a, -details.rustdoc-toggle.top-doc > summary, -details.rustdoc-toggle.non-exhaustive > summary, +summary.hideme, .scraped-example-list, /* This selector is for the items listed in the "all items" page. */ ul.all-items { @@ -1484,6 +1483,7 @@ details.rustdoc-toggle { "Expand description" or "Show methods". */ details.rustdoc-toggle > summary.hideme { cursor: pointer; + font-size: 1rem; } details.rustdoc-toggle > summary { @@ -1546,13 +1546,6 @@ details.rustdoc-toggle > summary:focus-visible::before { outline-offset: 1px; } -details.rustdoc-toggle.top-doc > summary, -details.rustdoc-toggle.top-doc > summary::before, -details.rustdoc-toggle.non-exhaustive > summary, -details.rustdoc-toggle.non-exhaustive > summary::before { - font-size: 1rem; -} - details.non-exhaustive { margin-bottom: 8px; } diff --git a/src/test/rustdoc-gui/enum-variants.goml b/src/test/rustdoc-gui/enum-variants.goml index 230abb236bd6..8dfc49285f2e 100644 --- a/src/test/rustdoc-gui/enum-variants.goml +++ b/src/test/rustdoc-gui/enum-variants.goml @@ -3,3 +3,8 @@ goto: "file://" + |DOC_PATH| + "/test_docs/enum.WhoLetTheDogOut.html" assert-css: (".variants > .variant", {"margin": "0px 0px 12px"}) assert-css: (".variants > .docblock", {"margin": "0px 0px 32px 24px"}) + +assert-css: ( + "details.non-exhaustive > summary", + {"font-family": '"Fira Sans", Arial, NanumBarunGothic, sans-serif'}, +) diff --git a/src/test/rustdoc-gui/src/test_docs/lib.rs b/src/test/rustdoc-gui/src/test_docs/lib.rs index dea154c93193..1340511d4726 100644 --- a/src/test/rustdoc-gui/src/test_docs/lib.rs +++ b/src/test/rustdoc-gui/src/test_docs/lib.rs @@ -76,6 +76,7 @@ impl AsRef for Foo { /// /// # title! #[doc(alias = "ThisIsAnAlias")] +#[non_exhaustive] pub enum WhoLetTheDogOut { /// Woof! Woof, diff --git a/src/test/rustdoc-gui/toggle-docs.goml b/src/test/rustdoc-gui/toggle-docs.goml index b7d107237675..45bb8daf1f20 100644 --- a/src/test/rustdoc-gui/toggle-docs.goml +++ b/src/test/rustdoc-gui/toggle-docs.goml @@ -7,6 +7,10 @@ wait-for: 50 // This is now collapsed so there shouldn't be the "open" attribute on details. assert-attribute-false: ("#main-content > details.top-doc", {"open": ""}) assert-text: ("#toggle-all-docs", "[+]") +assert-css: ( + "#main-content > details.top-doc > summary", + {"font-family": '"Fira Sans", Arial, NanumBarunGothic, sans-serif'}, +) click: "#toggle-all-docs" // Not collapsed anymore so the "open" attribute should be back. wait-for-attribute: ("#main-content > details.top-doc", {"open": ""}) From d595884302240f07576239288c771b0e9717fc19 Mon Sep 17 00:00:00 2001 From: Will Crichton Date: Mon, 5 Dec 2022 11:22:35 -0800 Subject: [PATCH 070/115] Move -Z maximal-hir-to-mir-coverage implementation to new `maybe_new_source_scope` method --- compiler/rustc_middle/src/lint.rs | 10 ---- compiler/rustc_mir_build/src/build/mod.rs | 20 +++----- compiler/rustc_mir_build/src/build/scope.rs | 56 ++++++++++++++------- 3 files changed, 44 insertions(+), 42 deletions(-) diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index bde3e28c1345..51df42f6d14e 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -173,16 +173,6 @@ impl TyCtxt<'_> { /// Walks upwards from `id` to find a node which might change lint levels with attributes. /// It stops at `bound` and just returns it if reached. pub fn maybe_lint_level_root_bounded(self, mut id: HirId, bound: HirId) -> HirId { - // Some consumers of rustc need to map MIR locations back to HIR nodes. Currently the - // the only part of rustc that tracks MIR -> HIR is the `SourceScopeLocalData::lint_root` - // field that tracks lint levels for MIR locations. Normally the number of source scopes - // is limited to the set of nodes with lint annotations. The -Zmaximal-hir-to-mir-coverage - // flag changes this behavior to maximize the number of source scopes, increasing the - // granularity of the MIR->HIR mapping. - if self.sess.opts.unstable_opts.maximal_hir_to_mir_coverage { - return id; - } - let hir = self.hir(); loop { if id == bound { diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index b456e2aa37a2..007f3b55ec8b 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -948,20 +948,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { original_source_scope: SourceScope, pattern_span: Span, ) { - let tcx = self.tcx; - let current_root = tcx.maybe_lint_level_root_bounded(arg_hir_id, self.hir_id); - let parent_root = tcx.maybe_lint_level_root_bounded( - self.source_scopes[original_source_scope] - .local_data - .as_ref() - .assert_crate_local() - .lint_root, - self.hir_id, - ); - if current_root != parent_root { - self.source_scope = - self.new_source_scope(pattern_span, LintLevel::Explicit(current_root), None); - } + let parent_id = self.source_scopes[original_source_scope] + .local_data + .as_ref() + .assert_crate_local() + .lint_root; + self.maybe_new_source_scope(pattern_span, None, arg_hir_id, parent_id); } fn get_unit_temp(&mut self) -> Place<'tcx> { diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs index 5ddae5f5300f..33f49ffdaf64 100644 --- a/compiler/rustc_mir_build/src/build/scope.rs +++ b/compiler/rustc_mir_build/src/build/scope.rs @@ -85,6 +85,7 @@ use std::mem; use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder, CFG}; use rustc_data_structures::fx::FxHashMap; +use rustc_hir::HirId; use rustc_index::vec::IndexVec; use rustc_middle::middle::region; use rustc_middle::mir::*; @@ -567,25 +568,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { F: FnOnce(&mut Builder<'a, 'tcx>) -> BlockAnd, { let source_scope = self.source_scope; - let tcx = self.tcx; if let LintLevel::Explicit(current_hir_id) = lint_level { - // Use `maybe_lint_level_root_bounded` with `root_lint_level` as a bound - // to avoid adding Hir dependencies on our parents. - // We estimate the true lint roots here to avoid creating a lot of source scopes. - - let parent_root = tcx.maybe_lint_level_root_bounded( - self.source_scopes[source_scope].local_data.as_ref().assert_crate_local().lint_root, - self.hir_id, - ); - let current_root = tcx.maybe_lint_level_root_bounded(current_hir_id, self.hir_id); - - if parent_root != current_root { - self.source_scope = self.new_source_scope( - region_scope.1.span, - LintLevel::Explicit(current_root), - None, - ); - } + let parent_id = + self.source_scopes[source_scope].local_data.as_ref().assert_crate_local().lint_root; + self.maybe_new_source_scope(region_scope.1.span, None, current_hir_id, parent_id); } self.push_scope(region_scope); let mut block; @@ -758,6 +744,40 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { )) } + /// Possibly creates a new source scope if `current_root` and `parent_root` + /// are different, or if -Zmaximal-hir-to-mir-coverage is enabled. + pub(crate) fn maybe_new_source_scope( + &mut self, + span: Span, + safety: Option, + current_id: HirId, + parent_id: HirId, + ) { + let (current_root, parent_root) = + if self.tcx.sess.opts.unstable_opts.maximal_hir_to_mir_coverage { + // Some consumers of rustc need to map MIR locations back to HIR nodes. Currently the + // the only part of rustc that tracks MIR -> HIR is the `SourceScopeLocalData::lint_root` + // field that tracks lint levels for MIR locations. Normally the number of source scopes + // is limited to the set of nodes with lint annotations. The -Zmaximal-hir-to-mir-coverage + // flag changes this behavior to maximize the number of source scopes, increasing the + // granularity of the MIR->HIR mapping. + (current_id, parent_id) + } else { + // Use `maybe_lint_level_root_bounded` with `self.hir_id` as a bound + // to avoid adding Hir dependencies on our parents. + // We estimate the true lint roots here to avoid creating a lot of source scopes. + ( + self.tcx.maybe_lint_level_root_bounded(current_id, self.hir_id), + self.tcx.maybe_lint_level_root_bounded(parent_id, self.hir_id), + ) + }; + + if current_root != parent_root { + let lint_level = LintLevel::Explicit(current_root); + self.source_scope = self.new_source_scope(span, lint_level, safety); + } + } + /// Creates a new source scope, nested in the current one. pub(crate) fn new_source_scope( &mut self, From f7a705929aa3f40ff5c3b1e569858a7030b2e3bd Mon Sep 17 00:00:00 2001 From: Will Crichton Date: Mon, 5 Dec 2022 14:04:57 -0800 Subject: [PATCH 071/115] Restore missing newline --- src/test/rustdoc-gui/scrape-examples-button-focus.goml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/rustdoc-gui/scrape-examples-button-focus.goml b/src/test/rustdoc-gui/scrape-examples-button-focus.goml index 1eb04eb92d12..a222139f1dc4 100644 --- a/src/test/rustdoc-gui/scrape-examples-button-focus.goml +++ b/src/test/rustdoc-gui/scrape-examples-button-focus.goml @@ -24,4 +24,4 @@ assert-property-false: (".scraped-example-list > .scraped-example pre", { store-property: (fullOffsetHeight, ".scraped-example-list > .scraped-example pre", "offsetHeight") assert-property: (".scraped-example-list > .scraped-example pre", { "scrollHeight": |fullOffsetHeight| -}) \ No newline at end of file +}) From e1649c442f47a8b9d071b5bcca20684b70b393d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 5 Dec 2022 14:24:48 -0800 Subject: [PATCH 072/115] Tweak "the following other types implement trait" When *any* of the suggested impls is an exact match, *only* show the exact matches. This is particularly relevant for integer types. fix fmt --- .../src/traits/error_reporting/mod.rs | 12 +- src/test/ui/binop/binop-mul-i32-f32.stderr | 11 +- .../defaults/rp_impl_trait_fail.stderr | 8 +- .../const-eval/const-eval-overflow-3b.stderr | 11 +- .../const-eval/const-eval-overflow-4b.stderr | 11 +- .../issue-39802-show-5-trait-impls.stderr | 9 -- src/test/ui/impl-trait/equality.stderr | 13 +- src/test/ui/issues/issue-24352.stderr | 11 +- src/test/ui/kindck/kindck-copy.stderr | 22 +-- .../ui/lexer/lex-bad-char-literals-6.stderr | 18 +-- src/test/ui/mismatched_types/binops.stderr | 13 +- src/test/ui/never_type/issue-13352.stderr | 13 +- .../not-suggest-float-literal.stderr | 141 +++++------------- .../suggest-float-literal.stderr | 88 +++-------- src/test/ui/span/multiline-span-simple.stderr | 13 +- src/test/ui/traits/issue-79458.stderr | 5 +- .../ui/try-trait/bad-interconversion.stderr | 11 +- .../self-referential-2.stderr | 11 +- .../self-referential-4.stderr | 33 +--- .../self-referential.stderr | 33 +--- src/test/ui/type/type-check-defaults.stderr | 11 +- src/test/ui/typeck/issue-81293.stderr | 13 +- .../ui/ufcs/ufcs-qpath-self-mismatch.stderr | 22 +-- 23 files changed, 138 insertions(+), 395 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 3379279dd154..12cc72d30c87 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1810,7 +1810,8 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { &self, trait_pred: ty::PolyTraitPredicate<'tcx>, ) -> Vec> { - self.tcx + let mut candidates: Vec<_> = self + .tcx .all_impls(trait_pred.def_id()) .filter_map(|def_id| { if self.tcx.impl_polarity(def_id) == ty::ImplPolarity::Negative @@ -1826,7 +1827,14 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { self.fuzzy_match_tys(trait_pred.skip_binder().self_ty(), imp.self_ty(), false) .map(|similarity| ImplCandidate { trait_ref: imp, similarity }) }) - .collect() + .collect(); + if candidates.iter().any(|c| matches!(c.similarity, CandidateSimilarity::Exact { .. })) { + // If any of the candidates is a perfect match, we don't want to show all of them. + // This is particularly relevant for the case of numeric types (as they all have the + // same cathegory). + candidates.retain(|c| matches!(c.similarity, CandidateSimilarity::Exact { .. })); + } + candidates } fn report_similar_impl_candidates( diff --git a/src/test/ui/binop/binop-mul-i32-f32.stderr b/src/test/ui/binop/binop-mul-i32-f32.stderr index 21c490965b14..c986bc3fd1e3 100644 --- a/src/test/ui/binop/binop-mul-i32-f32.stderr +++ b/src/test/ui/binop/binop-mul-i32-f32.stderr @@ -6,15 +6,10 @@ LL | x * y | = help: the trait `Mul` is not implemented for `i32` = help: the following other types implement trait `Mul`: - <&'a f32 as Mul> - <&'a f64 as Mul> - <&'a i128 as Mul> - <&'a i16 as Mul> <&'a i32 as Mul> - <&'a i64 as Mul> - <&'a i8 as Mul> - <&'a isize as Mul> - and 49 others + <&i32 as Mul<&i32>> + > + error: aborting due to previous error diff --git a/src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr b/src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr index f2e7777ce681..a46bd53520b5 100644 --- a/src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr +++ b/src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr @@ -18,9 +18,7 @@ LL | LL | 1_u32 | ----- return type was inferred to be `u32` here | - = help: the following other types implement trait `Traitor`: - > - > + = help: the trait `Traitor` is implemented for `u32` error[E0277]: the trait bound `u64: Traitor` is not satisfied --> $DIR/rp_impl_trait_fail.rs:21:13 @@ -31,9 +29,7 @@ LL | LL | 1_u64 | ----- return type was inferred to be `u64` here | - = help: the following other types implement trait `Traitor`: - > - > + = help: the trait `Traitor<1, 2>` is implemented for `u64` error: aborting due to 3 previous errors diff --git a/src/test/ui/consts/const-eval/const-eval-overflow-3b.stderr b/src/test/ui/consts/const-eval/const-eval-overflow-3b.stderr index c685922c456b..f199170018f2 100644 --- a/src/test/ui/consts/const-eval/const-eval-overflow-3b.stderr +++ b/src/test/ui/consts/const-eval/const-eval-overflow-3b.stderr @@ -12,15 +12,10 @@ LL | = [0; (i8::MAX + 1u8) as usize]; | = help: the trait `~const Add` is not implemented for `i8` = help: the following other types implement trait `Add`: - <&'a f32 as Add> - <&'a f64 as Add> - <&'a i128 as Add> - <&'a i16 as Add> - <&'a i32 as Add> - <&'a i64 as Add> <&'a i8 as Add> - <&'a isize as Add> - and 48 others + <&i8 as Add<&i8>> + > + error: aborting due to 2 previous errors diff --git a/src/test/ui/consts/const-eval/const-eval-overflow-4b.stderr b/src/test/ui/consts/const-eval/const-eval-overflow-4b.stderr index b396079240a9..1f8e402317aa 100644 --- a/src/test/ui/consts/const-eval/const-eval-overflow-4b.stderr +++ b/src/test/ui/consts/const-eval/const-eval-overflow-4b.stderr @@ -12,15 +12,10 @@ LL | : [u32; (i8::MAX as i8 + 1u8) as usize] | = help: the trait `~const Add` is not implemented for `i8` = help: the following other types implement trait `Add`: - <&'a f32 as Add> - <&'a f64 as Add> - <&'a i128 as Add> - <&'a i16 as Add> - <&'a i32 as Add> - <&'a i64 as Add> <&'a i8 as Add> - <&'a isize as Add> - and 48 others + <&i8 as Add<&i8>> + > + error[E0604]: only `u8` can be cast as `char`, not `i8` --> $DIR/const-eval-overflow-4b.rs:22:13 diff --git a/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr b/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr index d27b05fe7f7d..7229b9ac986a 100644 --- a/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr +++ b/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr @@ -12,10 +12,6 @@ LL | Foo::::bar(&1i8); > > > - > - > - > - > error[E0277]: the trait bound `u8: Foo` is not satisfied --> $DIR/issue-39802-show-5-trait-impls.rs:25:21 @@ -26,11 +22,6 @@ LL | Foo::::bar(&1u8); | required by a bound introduced by this call | = help: the following other types implement trait `Foo`: - > - > - > - > - > > > > diff --git a/src/test/ui/impl-trait/equality.stderr b/src/test/ui/impl-trait/equality.stderr index 1841b8e5dcd0..69f4cbbbf429 100644 --- a/src/test/ui/impl-trait/equality.stderr +++ b/src/test/ui/impl-trait/equality.stderr @@ -30,15 +30,10 @@ LL | n + sum_to(n - 1) | = help: the trait `Add` is not implemented for `u32` = help: the following other types implement trait `Add`: - <&'a f32 as Add> - <&'a f64 as Add> - <&'a i128 as Add> - <&'a i16 as Add> - <&'a i32 as Add> - <&'a i64 as Add> - <&'a i8 as Add> - <&'a isize as Add> - and 48 others + <&'a u32 as Add> + <&u32 as Add<&u32>> + > + error: aborting due to 2 previous errors; 1 warning emitted diff --git a/src/test/ui/issues/issue-24352.stderr b/src/test/ui/issues/issue-24352.stderr index 118f37f6971e..1f51b6e29050 100644 --- a/src/test/ui/issues/issue-24352.stderr +++ b/src/test/ui/issues/issue-24352.stderr @@ -6,15 +6,10 @@ LL | 1.0f64 - 1 | = help: the trait `Sub<{integer}>` is not implemented for `f64` = help: the following other types implement trait `Sub`: - <&'a f32 as Sub> <&'a f64 as Sub> - <&'a i128 as Sub> - <&'a i16 as Sub> - <&'a i32 as Sub> - <&'a i64 as Sub> - <&'a i8 as Sub> - <&'a isize as Sub> - and 48 others + <&f64 as Sub<&f64>> + > + help: consider using a floating-point literal by writing it with `.0` | LL | 1.0f64 - 1.0 diff --git a/src/test/ui/kindck/kindck-copy.stderr b/src/test/ui/kindck/kindck-copy.stderr index 025a5008d0f1..9af89159a8cf 100644 --- a/src/test/ui/kindck/kindck-copy.stderr +++ b/src/test/ui/kindck/kindck-copy.stderr @@ -4,16 +4,7 @@ error[E0277]: the trait bound `&'static mut isize: Copy` is not satisfied LL | assert_copy::<&'static mut isize>(); | ^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `&'static mut isize` | - = help: the following other types implement trait `Copy`: - f32 - f64 - i128 - i16 - i32 - i64 - i8 - isize - and 6 others + = help: the trait `Copy` is implemented for `isize` note: required by a bound in `assert_copy` --> $DIR/kindck-copy.rs:5:18 | @@ -26,16 +17,7 @@ error[E0277]: the trait bound `&'a mut isize: Copy` is not satisfied LL | assert_copy::<&'a mut isize>(); | ^^^^^^^^^^^^^ the trait `Copy` is not implemented for `&'a mut isize` | - = help: the following other types implement trait `Copy`: - f32 - f64 - i128 - i16 - i32 - i64 - i8 - isize - and 6 others + = help: the trait `Copy` is implemented for `isize` note: required by a bound in `assert_copy` --> $DIR/kindck-copy.rs:5:18 | diff --git a/src/test/ui/lexer/lex-bad-char-literals-6.stderr b/src/test/ui/lexer/lex-bad-char-literals-6.stderr index afef0cb60348..ce41942467ce 100644 --- a/src/test/ui/lexer/lex-bad-char-literals-6.stderr +++ b/src/test/ui/lexer/lex-bad-char-literals-6.stderr @@ -42,12 +42,11 @@ LL | if x == y {} <&'a str as PartialEq> <&'a str as PartialEq> <&'b str as PartialEq>> - > - >> - > - >> - and 4 others + > + > + > + error[E0308]: mismatched types --> $DIR/lex-bad-char-literals-6.rs:15:20 @@ -68,12 +67,11 @@ LL | if x == z {} <&'a str as PartialEq> <&'a str as PartialEq> <&'b str as PartialEq>> - > - >> - > - >> - and 4 others + > + > + > + error: aborting due to 6 previous errors diff --git a/src/test/ui/mismatched_types/binops.stderr b/src/test/ui/mismatched_types/binops.stderr index 3de652d87ec5..3585587ed4c0 100644 --- a/src/test/ui/mismatched_types/binops.stderr +++ b/src/test/ui/mismatched_types/binops.stderr @@ -24,15 +24,10 @@ LL | 2 as usize - Some(1); | = help: the trait `Sub>` is not implemented for `usize` = help: the following other types implement trait `Sub`: - <&'a f32 as Sub> - <&'a f64 as Sub> - <&'a i128 as Sub> - <&'a i16 as Sub> - <&'a i32 as Sub> - <&'a i64 as Sub> - <&'a i8 as Sub> - <&'a isize as Sub> - and 48 others + <&'a usize as Sub> + <&usize as Sub<&usize>> + > + error[E0277]: cannot multiply `{integer}` by `()` --> $DIR/binops.rs:4:7 diff --git a/src/test/ui/never_type/issue-13352.stderr b/src/test/ui/never_type/issue-13352.stderr index fed780e68957..2d22da0b420e 100644 --- a/src/test/ui/never_type/issue-13352.stderr +++ b/src/test/ui/never_type/issue-13352.stderr @@ -6,15 +6,10 @@ LL | 2_usize + (loop {}); | = help: the trait `Add<()>` is not implemented for `usize` = help: the following other types implement trait `Add`: - <&'a f32 as Add> - <&'a f64 as Add> - <&'a i128 as Add> - <&'a i16 as Add> - <&'a i32 as Add> - <&'a i64 as Add> - <&'a i8 as Add> - <&'a isize as Add> - and 48 others + <&'a usize as Add> + <&usize as Add<&usize>> + > + error: aborting due to previous error diff --git a/src/test/ui/numbers-arithmetic/not-suggest-float-literal.stderr b/src/test/ui/numbers-arithmetic/not-suggest-float-literal.stderr index 6aa1ad8dd899..8f0eef237cfe 100644 --- a/src/test/ui/numbers-arithmetic/not-suggest-float-literal.stderr +++ b/src/test/ui/numbers-arithmetic/not-suggest-float-literal.stderr @@ -6,15 +6,10 @@ LL | x + 100.0 | = help: the trait `Add<{float}>` is not implemented for `u8` = help: the following other types implement trait `Add`: - <&'a f32 as Add> - <&'a f64 as Add> - <&'a i128 as Add> - <&'a i16 as Add> - <&'a i32 as Add> - <&'a i64 as Add> - <&'a i8 as Add> - <&'a isize as Add> - and 48 others + <&'a u8 as Add> + <&u8 as Add<&u8>> + > + error[E0277]: cannot add `&str` to `f64` --> $DIR/not-suggest-float-literal.rs:6:7 @@ -24,15 +19,10 @@ LL | x + "foo" | = help: the trait `Add<&str>` is not implemented for `f64` = help: the following other types implement trait `Add`: - <&'a f32 as Add> <&'a f64 as Add> - <&'a i128 as Add> - <&'a i16 as Add> - <&'a i32 as Add> - <&'a i64 as Add> - <&'a i8 as Add> - <&'a isize as Add> - and 48 others + <&f64 as Add<&f64>> + > + error[E0277]: cannot add `{integer}` to `f64` --> $DIR/not-suggest-float-literal.rs:11:7 @@ -42,15 +32,10 @@ LL | x + y | = help: the trait `Add<{integer}>` is not implemented for `f64` = help: the following other types implement trait `Add`: - <&'a f32 as Add> <&'a f64 as Add> - <&'a i128 as Add> - <&'a i16 as Add> - <&'a i32 as Add> - <&'a i64 as Add> - <&'a i8 as Add> - <&'a isize as Add> - and 48 others + <&f64 as Add<&f64>> + > + error[E0277]: cannot subtract `{float}` from `u8` --> $DIR/not-suggest-float-literal.rs:15:7 @@ -60,15 +45,10 @@ LL | x - 100.0 | = help: the trait `Sub<{float}>` is not implemented for `u8` = help: the following other types implement trait `Sub`: - <&'a f32 as Sub> - <&'a f64 as Sub> - <&'a i128 as Sub> - <&'a i16 as Sub> - <&'a i32 as Sub> - <&'a i64 as Sub> - <&'a i8 as Sub> - <&'a isize as Sub> - and 48 others + <&'a u8 as Sub> + <&u8 as Sub<&u8>> + > + error[E0277]: cannot subtract `&str` from `f64` --> $DIR/not-suggest-float-literal.rs:19:7 @@ -78,15 +58,10 @@ LL | x - "foo" | = help: the trait `Sub<&str>` is not implemented for `f64` = help: the following other types implement trait `Sub`: - <&'a f32 as Sub> <&'a f64 as Sub> - <&'a i128 as Sub> - <&'a i16 as Sub> - <&'a i32 as Sub> - <&'a i64 as Sub> - <&'a i8 as Sub> - <&'a isize as Sub> - and 48 others + <&f64 as Sub<&f64>> + > + error[E0277]: cannot subtract `{integer}` from `f64` --> $DIR/not-suggest-float-literal.rs:24:7 @@ -96,15 +71,10 @@ LL | x - y | = help: the trait `Sub<{integer}>` is not implemented for `f64` = help: the following other types implement trait `Sub`: - <&'a f32 as Sub> <&'a f64 as Sub> - <&'a i128 as Sub> - <&'a i16 as Sub> - <&'a i32 as Sub> - <&'a i64 as Sub> - <&'a i8 as Sub> - <&'a isize as Sub> - and 48 others + <&f64 as Sub<&f64>> + > + error[E0277]: cannot multiply `u8` by `{float}` --> $DIR/not-suggest-float-literal.rs:28:7 @@ -114,15 +84,10 @@ LL | x * 100.0 | = help: the trait `Mul<{float}>` is not implemented for `u8` = help: the following other types implement trait `Mul`: - <&'a f32 as Mul> - <&'a f64 as Mul> - <&'a i128 as Mul> - <&'a i16 as Mul> - <&'a i32 as Mul> - <&'a i64 as Mul> - <&'a i8 as Mul> - <&'a isize as Mul> - and 49 others + <&'a u8 as Mul> + <&u8 as Mul<&u8>> + > + error[E0277]: cannot multiply `f64` by `&str` --> $DIR/not-suggest-float-literal.rs:32:7 @@ -132,15 +97,10 @@ LL | x * "foo" | = help: the trait `Mul<&str>` is not implemented for `f64` = help: the following other types implement trait `Mul`: - <&'a f32 as Mul> <&'a f64 as Mul> - <&'a i128 as Mul> - <&'a i16 as Mul> - <&'a i32 as Mul> - <&'a i64 as Mul> - <&'a i8 as Mul> - <&'a isize as Mul> - and 49 others + <&f64 as Mul<&f64>> + > + error[E0277]: cannot multiply `f64` by `{integer}` --> $DIR/not-suggest-float-literal.rs:37:7 @@ -150,15 +110,10 @@ LL | x * y | = help: the trait `Mul<{integer}>` is not implemented for `f64` = help: the following other types implement trait `Mul`: - <&'a f32 as Mul> <&'a f64 as Mul> - <&'a i128 as Mul> - <&'a i16 as Mul> - <&'a i32 as Mul> - <&'a i64 as Mul> - <&'a i8 as Mul> - <&'a isize as Mul> - and 49 others + <&f64 as Mul<&f64>> + > + error[E0277]: cannot divide `u8` by `{float}` --> $DIR/not-suggest-float-literal.rs:41:7 @@ -168,15 +123,11 @@ LL | x / 100.0 | = help: the trait `Div<{float}>` is not implemented for `u8` = help: the following other types implement trait `Div`: - <&'a f32 as Div> - <&'a f64 as Div> - <&'a i128 as Div> - <&'a i16 as Div> - <&'a i32 as Div> - <&'a i64 as Div> - <&'a i8 as Div> - <&'a isize as Div> - and 54 others + <&'a u8 as Div> + <&u8 as Div<&u8>> + > + > + error[E0277]: cannot divide `f64` by `&str` --> $DIR/not-suggest-float-literal.rs:45:7 @@ -186,15 +137,10 @@ LL | x / "foo" | = help: the trait `Div<&str>` is not implemented for `f64` = help: the following other types implement trait `Div`: - <&'a f32 as Div> <&'a f64 as Div> - <&'a i128 as Div> - <&'a i16 as Div> - <&'a i32 as Div> - <&'a i64 as Div> - <&'a i8 as Div> - <&'a isize as Div> - and 54 others + <&f64 as Div<&f64>> + > + error[E0277]: cannot divide `f64` by `{integer}` --> $DIR/not-suggest-float-literal.rs:50:7 @@ -204,15 +150,10 @@ LL | x / y | = help: the trait `Div<{integer}>` is not implemented for `f64` = help: the following other types implement trait `Div`: - <&'a f32 as Div> <&'a f64 as Div> - <&'a i128 as Div> - <&'a i16 as Div> - <&'a i32 as Div> - <&'a i64 as Div> - <&'a i8 as Div> - <&'a isize as Div> - and 54 others + <&f64 as Div<&f64>> + > + error: aborting due to 12 previous errors diff --git a/src/test/ui/numbers-arithmetic/suggest-float-literal.stderr b/src/test/ui/numbers-arithmetic/suggest-float-literal.stderr index 988379e582a3..03779d356371 100644 --- a/src/test/ui/numbers-arithmetic/suggest-float-literal.stderr +++ b/src/test/ui/numbers-arithmetic/suggest-float-literal.stderr @@ -7,14 +7,9 @@ LL | x + 100 = help: the trait `Add<{integer}>` is not implemented for `f32` = help: the following other types implement trait `Add`: <&'a f32 as Add> - <&'a f64 as Add> - <&'a i128 as Add> - <&'a i16 as Add> - <&'a i32 as Add> - <&'a i64 as Add> - <&'a i8 as Add> - <&'a isize as Add> - and 48 others + <&f32 as Add<&f32>> + > + help: consider using a floating-point literal by writing it with `.0` | LL | x + 100.0 @@ -28,15 +23,10 @@ LL | x + 100 | = help: the trait `Add<{integer}>` is not implemented for `f64` = help: the following other types implement trait `Add`: - <&'a f32 as Add> <&'a f64 as Add> - <&'a i128 as Add> - <&'a i16 as Add> - <&'a i32 as Add> - <&'a i64 as Add> - <&'a i8 as Add> - <&'a isize as Add> - and 48 others + <&f64 as Add<&f64>> + > + help: consider using a floating-point literal by writing it with `.0` | LL | x + 100.0 @@ -51,14 +41,9 @@ LL | x - 100 = help: the trait `Sub<{integer}>` is not implemented for `f32` = help: the following other types implement trait `Sub`: <&'a f32 as Sub> - <&'a f64 as Sub> - <&'a i128 as Sub> - <&'a i16 as Sub> - <&'a i32 as Sub> - <&'a i64 as Sub> - <&'a i8 as Sub> - <&'a isize as Sub> - and 48 others + <&f32 as Sub<&f32>> + > + help: consider using a floating-point literal by writing it with `.0` | LL | x - 100.0 @@ -72,15 +57,10 @@ LL | x - 100 | = help: the trait `Sub<{integer}>` is not implemented for `f64` = help: the following other types implement trait `Sub`: - <&'a f32 as Sub> <&'a f64 as Sub> - <&'a i128 as Sub> - <&'a i16 as Sub> - <&'a i32 as Sub> - <&'a i64 as Sub> - <&'a i8 as Sub> - <&'a isize as Sub> - and 48 others + <&f64 as Sub<&f64>> + > + help: consider using a floating-point literal by writing it with `.0` | LL | x - 100.0 @@ -95,14 +75,9 @@ LL | x * 100 = help: the trait `Mul<{integer}>` is not implemented for `f32` = help: the following other types implement trait `Mul`: <&'a f32 as Mul> - <&'a f64 as Mul> - <&'a i128 as Mul> - <&'a i16 as Mul> - <&'a i32 as Mul> - <&'a i64 as Mul> - <&'a i8 as Mul> - <&'a isize as Mul> - and 49 others + <&f32 as Mul<&f32>> + > + help: consider using a floating-point literal by writing it with `.0` | LL | x * 100.0 @@ -116,15 +91,10 @@ LL | x * 100 | = help: the trait `Mul<{integer}>` is not implemented for `f64` = help: the following other types implement trait `Mul`: - <&'a f32 as Mul> <&'a f64 as Mul> - <&'a i128 as Mul> - <&'a i16 as Mul> - <&'a i32 as Mul> - <&'a i64 as Mul> - <&'a i8 as Mul> - <&'a isize as Mul> - and 49 others + <&f64 as Mul<&f64>> + > + help: consider using a floating-point literal by writing it with `.0` | LL | x * 100.0 @@ -139,14 +109,9 @@ LL | x / 100 = help: the trait `Div<{integer}>` is not implemented for `f32` = help: the following other types implement trait `Div`: <&'a f32 as Div> - <&'a f64 as Div> - <&'a i128 as Div> - <&'a i16 as Div> - <&'a i32 as Div> - <&'a i64 as Div> - <&'a i8 as Div> - <&'a isize as Div> - and 54 others + <&f32 as Div<&f32>> + > + help: consider using a floating-point literal by writing it with `.0` | LL | x / 100.0 @@ -160,15 +125,10 @@ LL | x / 100 | = help: the trait `Div<{integer}>` is not implemented for `f64` = help: the following other types implement trait `Div`: - <&'a f32 as Div> <&'a f64 as Div> - <&'a i128 as Div> - <&'a i16 as Div> - <&'a i32 as Div> - <&'a i64 as Div> - <&'a i8 as Div> - <&'a isize as Div> - and 54 others + <&f64 as Div<&f64>> + > + help: consider using a floating-point literal by writing it with `.0` | LL | x / 100.0 diff --git a/src/test/ui/span/multiline-span-simple.stderr b/src/test/ui/span/multiline-span-simple.stderr index c0d9a8634e48..b44df962a9ba 100644 --- a/src/test/ui/span/multiline-span-simple.stderr +++ b/src/test/ui/span/multiline-span-simple.stderr @@ -6,15 +6,10 @@ LL | foo(1 as u32 + | = help: the trait `Add<()>` is not implemented for `u32` = help: the following other types implement trait `Add`: - <&'a f32 as Add> - <&'a f64 as Add> - <&'a i128 as Add> - <&'a i16 as Add> - <&'a i32 as Add> - <&'a i64 as Add> - <&'a i8 as Add> - <&'a isize as Add> - and 48 others + <&'a u32 as Add> + <&u32 as Add<&u32>> + > + error: aborting due to previous error diff --git a/src/test/ui/traits/issue-79458.stderr b/src/test/ui/traits/issue-79458.stderr index cf2e4edf9f0a..08f7bbbf0eaf 100644 --- a/src/test/ui/traits/issue-79458.stderr +++ b/src/test/ui/traits/issue-79458.stderr @@ -7,10 +7,7 @@ LL | struct Foo<'a, T> { LL | bar: &'a mut T | ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `&mut T` | - = help: the following other types implement trait `Clone`: - &T - *const T - *mut T + = help: the trait `Clone` is implemented for `&T` = note: `Clone` is implemented for `&T`, but not for `&mut T` = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/try-trait/bad-interconversion.stderr b/src/test/ui/try-trait/bad-interconversion.stderr index 419a86bf33bb..a49630adb953 100644 --- a/src/test/ui/try-trait/bad-interconversion.stderr +++ b/src/test/ui/try-trait/bad-interconversion.stderr @@ -8,15 +8,8 @@ LL | Ok(Err(123_i32)?) | = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait = help: the following other types implement trait `From`: - > - > - > - > - > - > - > - > - and 68 others + > + > = note: required for `Result` to implement `FromResidual>` error[E0277]: the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result` diff --git a/src/test/ui/type-alias-impl-trait/self-referential-2.stderr b/src/test/ui/type-alias-impl-trait/self-referential-2.stderr index 2b505d30730a..c2cf70687fd2 100644 --- a/src/test/ui/type-alias-impl-trait/self-referential-2.stderr +++ b/src/test/ui/type-alias-impl-trait/self-referential-2.stderr @@ -7,16 +7,7 @@ LL | 42_i32 | ------ return type was inferred to be `i32` here | = help: the trait `PartialEq` is not implemented for `i32` - = help: the following other types implement trait `PartialEq`: - f32 - f64 - i128 - i16 - i32 - i64 - i8 - isize - and 6 others + = help: the trait `PartialEq` is implemented for `i32` error: aborting due to previous error diff --git a/src/test/ui/type-alias-impl-trait/self-referential-4.stderr b/src/test/ui/type-alias-impl-trait/self-referential-4.stderr index 27880f792f46..98c762e3d382 100644 --- a/src/test/ui/type-alias-impl-trait/self-referential-4.stderr +++ b/src/test/ui/type-alias-impl-trait/self-referential-4.stderr @@ -7,16 +7,7 @@ LL | i | - return type was inferred to be `&i32` here | = help: the trait `PartialEq>` is not implemented for `&i32` - = help: the following other types implement trait `PartialEq`: - f32 - f64 - i128 - i16 - i32 - i64 - i8 - isize - and 6 others + = help: the trait `PartialEq` is implemented for `i32` error[E0277]: can't compare `&i32` with `Foo<'static, 'b>` --> $DIR/self-referential-4.rs:11:31 @@ -27,16 +18,7 @@ LL | i | - return type was inferred to be `&i32` here | = help: the trait `PartialEq>` is not implemented for `&i32` - = help: the following other types implement trait `PartialEq`: - f32 - f64 - i128 - i16 - i32 - i64 - i8 - isize - and 6 others + = help: the trait `PartialEq` is implemented for `i32` error[E0277]: can't compare `&i32` with `Moo<'static, 'a>` --> $DIR/self-referential-4.rs:17:31 @@ -47,16 +29,7 @@ LL | i | - return type was inferred to be `&i32` here | = help: the trait `PartialEq>` is not implemented for `&i32` - = help: the following other types implement trait `PartialEq`: - f32 - f64 - i128 - i16 - i32 - i64 - i8 - isize - and 6 others + = help: the trait `PartialEq` is implemented for `i32` error: aborting due to 3 previous errors diff --git a/src/test/ui/type-alias-impl-trait/self-referential.stderr b/src/test/ui/type-alias-impl-trait/self-referential.stderr index 97d510f6830a..aff489d70e38 100644 --- a/src/test/ui/type-alias-impl-trait/self-referential.stderr +++ b/src/test/ui/type-alias-impl-trait/self-referential.stderr @@ -8,16 +8,7 @@ LL | i | - return type was inferred to be `&i32` here | = help: the trait `PartialEq>` is not implemented for `&i32` - = help: the following other types implement trait `PartialEq`: - f32 - f64 - i128 - i16 - i32 - i64 - i8 - isize - and 6 others + = help: the trait `PartialEq` is implemented for `i32` error[E0277]: can't compare `&i32` with `(i32, &i32)` --> $DIR/self-referential.rs:12:31 @@ -29,16 +20,7 @@ LL | (42, i) | ------- return type was inferred to be `(i32, &i32)` here | = help: the trait `PartialEq<(i32, &i32)>` is not implemented for `&i32` - = help: the following other types implement trait `PartialEq`: - f32 - f64 - i128 - i16 - i32 - i64 - i8 - isize - and 6 others + = help: the trait `PartialEq` is implemented for `i32` error[E0277]: can't compare `&i32` with `(i32, Moo<'b, 'a>::{opaque#0})` --> $DIR/self-referential.rs:19:31 @@ -50,16 +32,7 @@ LL | (42, i) | ------- return type was inferred to be `(i32, &i32)` here | = help: the trait `PartialEq<(i32, Moo<'b, 'a>::{opaque#0})>` is not implemented for `&i32` - = help: the following other types implement trait `PartialEq`: - f32 - f64 - i128 - i16 - i32 - i64 - i8 - isize - and 6 others + = help: the trait `PartialEq` is implemented for `i32` error: aborting due to 3 previous errors diff --git a/src/test/ui/type/type-check-defaults.stderr b/src/test/ui/type/type-check-defaults.stderr index cf77c057d46d..9ba63ffe9c93 100644 --- a/src/test/ui/type/type-check-defaults.stderr +++ b/src/test/ui/type/type-check-defaults.stderr @@ -66,15 +66,10 @@ LL | trait ProjectionPred> where T::Item : Add {} | = help: the trait `Add` is not implemented for `i32` = help: the following other types implement trait `Add`: - <&'a f32 as Add> - <&'a f64 as Add> - <&'a i128 as Add> - <&'a i16 as Add> <&'a i32 as Add> - <&'a i64 as Add> - <&'a i8 as Add> - <&'a isize as Add> - and 48 others + <&i32 as Add<&i32>> + > + error: aborting due to 7 previous errors diff --git a/src/test/ui/typeck/issue-81293.stderr b/src/test/ui/typeck/issue-81293.stderr index 9658288ac8b2..6976be71135c 100644 --- a/src/test/ui/typeck/issue-81293.stderr +++ b/src/test/ui/typeck/issue-81293.stderr @@ -21,15 +21,10 @@ LL | a = c + b * 5; | = help: the trait `Add` is not implemented for `usize` = help: the following other types implement trait `Add`: - <&'a f32 as Add> - <&'a f64 as Add> - <&'a i128 as Add> - <&'a i16 as Add> - <&'a i32 as Add> - <&'a i64 as Add> - <&'a i8 as Add> - <&'a isize as Add> - and 48 others + <&'a usize as Add> + <&usize as Add<&usize>> + > + error: aborting due to 3 previous errors diff --git a/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr b/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr index eaab6ff3d9a0..ed56e1cf957f 100644 --- a/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr +++ b/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr @@ -8,15 +8,10 @@ LL | >::add(1, 2); | = help: the trait `Add` is not implemented for `i32` = help: the following other types implement trait `Add`: - <&'a f32 as Add> - <&'a f64 as Add> - <&'a i128 as Add> - <&'a i16 as Add> <&'a i32 as Add> - <&'a i64 as Add> - <&'a i8 as Add> - <&'a isize as Add> - and 48 others + <&i32 as Add<&i32>> + > + error[E0308]: mismatched types --> $DIR/ufcs-qpath-self-mismatch.rs:7:28 @@ -62,15 +57,10 @@ LL | >::add(1, 2); | = help: the trait `Add` is not implemented for `i32` = help: the following other types implement trait `Add`: - <&'a f32 as Add> - <&'a f64 as Add> - <&'a i128 as Add> - <&'a i16 as Add> <&'a i32 as Add> - <&'a i64 as Add> - <&'a i8 as Add> - <&'a isize as Add> - and 48 others + <&i32 as Add<&i32>> + > + error: aborting due to 4 previous errors From 5873ebeef3a4497c14b4199abba705fe7b530935 Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Wed, 23 Nov 2022 18:13:30 -0800 Subject: [PATCH 073/115] Move linkage type check to HIR analysis and fix semantics issues. This ensures that the error is printed even for unused variables, as well as unifying the handling between the LLVM and GCC backends. This also fixes unusual behavior around exported Rust-defined variables with linkage attributes. With the previous behavior, it appears to be impossible to define such a variable such that it can actually be imported and used by another crate. This is because on the importing side, the variable is required to be a pointer, but on the exporting side, the type checker rejects static variables of pointer type because they do not implement `Sync`. Even if it were possible to import such a type, it appears that code generation on the importing side would add an unexpected additional level of pointer indirection, which would break type safety. This highlighted that the semantics of linkage on Rust-defined variables is different to linkage on foreign items. As such, we now model the difference with two different codegen attributes: linkage for Rust-defined variables, and import_linkage for foreign items. This change gives semantics to the test src/test/ui/linkage-attr/auxiliary/def_illtyped_external.rs which was previously expected to fail to compile. Therefore, convert it into a test that is expected to successfully compile. The update to the GCC backend is speculative and untested. --- compiler/rustc_codegen_gcc/src/consts.rs | 27 +++++-------------- compiler/rustc_codegen_gcc/src/errors.rs | 7 ----- compiler/rustc_codegen_llvm/src/consts.rs | 18 +++---------- compiler/rustc_codegen_llvm/src/errors.rs | 7 ----- .../locales/en-US/codegen_gcc.ftl | 3 --- .../locales/en-US/codegen_llvm.ftl | 3 --- .../locales/en-US/hir_analysis.ftl | 3 +++ .../rustc_hir_analysis/src/check/check.rs | 14 ++++++++++ compiler/rustc_hir_analysis/src/collect.rs | 7 ++++- compiler/rustc_hir_analysis/src/errors.rs | 7 +++++ .../src/middle/codegen_fn_attrs.rs | 5 +++- .../ui/feature-gates/feature-gate-linkage.rs | 2 +- .../feature-gates/feature-gate-linkage.stderr | 2 +- ...f_illtyped_external.rs => def_external.rs} | 0 src/test/ui/linkage-attr/linkage-import.rs | 8 ++++++ .../linkage-attr/linkage-requires-raw-ptr.rs | 11 -------- .../linkage-requires-raw-ptr.stderr | 8 ------ src/test/ui/linkage-attr/linkage2.rs | 7 +---- src/test/ui/linkage-attr/linkage2.stderr | 2 +- 19 files changed, 56 insertions(+), 85 deletions(-) rename src/test/ui/linkage-attr/auxiliary/{def_illtyped_external.rs => def_external.rs} (100%) create mode 100644 src/test/ui/linkage-attr/linkage-import.rs delete mode 100644 src/test/ui/linkage-attr/linkage-requires-raw-ptr.rs delete mode 100644 src/test/ui/linkage-attr/linkage-requires-raw-ptr.stderr diff --git a/compiler/rustc_codegen_gcc/src/consts.rs b/compiler/rustc_codegen_gcc/src/consts.rs index 111bfeb13220..ea8ab7611460 100644 --- a/compiler/rustc_codegen_gcc/src/consts.rs +++ b/compiler/rustc_codegen_gcc/src/consts.rs @@ -8,13 +8,11 @@ use rustc_middle::mir::mono::MonoItem; use rustc_middle::ty::{self, Instance, Ty}; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::mir::interpret::{self, ConstAllocation, ErrorHandled, Scalar as InterpScalar, read_target_uint}; -use rustc_span::Span; use rustc_span::def_id::DefId; use rustc_target::abi::{self, Align, HasDataLayout, Primitive, Size, WrappingRange}; use crate::base; use crate::context::CodegenCx; -use crate::errors::LinkageConstOrMutType; use crate::type_of::LayoutGccExt; impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { @@ -239,12 +237,12 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { } Node::ForeignItem(&hir::ForeignItem { - span, + span: _, kind: hir::ForeignItemKind::Static(..), .. }) => { let fn_attrs = self.tcx.codegen_fn_attrs(def_id); - check_and_apply_linkage(&self, &fn_attrs, ty, sym, span) + check_and_apply_linkage(&self, &fn_attrs, ty, sym) } item => bug!("get_static: expected static, found {:?}", item), @@ -257,8 +255,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { //debug!("get_static: sym={} item_attr={:?}", sym, self.tcx.item_attrs(def_id)); let attrs = self.tcx.codegen_fn_attrs(def_id); - let span = self.tcx.def_span(def_id); - let global = check_and_apply_linkage(&self, &attrs, ty, sym, span); + let global = check_and_apply_linkage(&self, &attrs, ty, sym); let needs_dll_storage_attr = false; // TODO(antoyo) @@ -355,24 +352,12 @@ pub fn codegen_static_initializer<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, def_id Ok((const_alloc_to_gcc(cx, alloc), alloc)) } -fn check_and_apply_linkage<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, attrs: &CodegenFnAttrs, ty: Ty<'tcx>, sym: &str, span: Span) -> LValue<'gcc> { +fn check_and_apply_linkage<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, attrs: &CodegenFnAttrs, ty: Ty<'tcx>, sym: &str) -> LValue<'gcc> { let is_tls = attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL); let llty = cx.layout_of(ty).gcc_type(cx, true); - if let Some(linkage) = attrs.linkage { - // If this is a static with a linkage specified, then we need to handle - // it a little specially. The typesystem prevents things like &T and - // extern "C" fn() from being non-null, so we can't just declare a - // static and call it a day. Some linkages (like weak) will make it such - // that the static actually has a null value. - let llty2 = - if let ty::RawPtr(ref mt) = ty.kind() { - cx.layout_of(mt.ty).gcc_type(cx, true) - } - else { - cx.sess().emit_fatal(LinkageConstOrMutType { span: span }) - }; + if let Some(linkage) = attrs.import_linkage { // Declare a symbol `foo` with the desired linkage. - let global1 = cx.declare_global_with_linkage(&sym, llty2, base::global_linkage_to_gcc(linkage)); + let global1 = cx.declare_global_with_linkage(&sym, cx.type_i8(), base::global_linkage_to_gcc(linkage)); // Declare an internal global `extern_with_linkage_foo` which // is initialized with the address of `foo`. If `foo` is diff --git a/compiler/rustc_codegen_gcc/src/errors.rs b/compiler/rustc_codegen_gcc/src/errors.rs index 89fed7be1315..d0ba7e247911 100644 --- a/compiler/rustc_codegen_gcc/src/errors.rs +++ b/compiler/rustc_codegen_gcc/src/errors.rs @@ -211,13 +211,6 @@ pub(crate) struct InvalidMonomorphizationUnsupportedOperation<'a> { pub in_elem: Ty<'a>, } -#[derive(Diagnostic)] -#[diag(codegen_gcc_linkage_const_or_mut_type)] -pub(crate) struct LinkageConstOrMutType { - #[primary_span] - pub span: Span, -} - #[derive(Diagnostic)] #[diag(codegen_gcc_lto_not_supported)] pub(crate) struct LTONotSupported; diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index 3c324359565c..3626aa901c0e 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -1,7 +1,7 @@ use crate::base; use crate::common::{self, CodegenCx}; use crate::debuginfo; -use crate::errors::{InvalidMinimumAlignment, LinkageConstOrMutType, SymbolAlreadyDefined}; +use crate::errors::{InvalidMinimumAlignment, SymbolAlreadyDefined}; use crate::llvm::{self, True}; use crate::llvm_util; use crate::type_::Type; @@ -162,22 +162,12 @@ fn check_and_apply_linkage<'ll, 'tcx>( def_id: DefId, ) -> &'ll Value { let llty = cx.layout_of(ty).llvm_type(cx); - if let Some(linkage) = attrs.linkage { + if let Some(linkage) = attrs.import_linkage { debug!("get_static: sym={} linkage={:?}", sym, linkage); - // If this is a static with a linkage specified, then we need to handle - // it a little specially. The typesystem prevents things like &T and - // extern "C" fn() from being non-null, so we can't just declare a - // static and call it a day. Some linkages (like weak) will make it such - // that the static actually has a null value. - let llty2 = if let ty::RawPtr(ref mt) = ty.kind() { - cx.layout_of(mt.ty).llvm_type(cx) - } else { - cx.sess().emit_fatal(LinkageConstOrMutType { span: cx.tcx.def_span(def_id) }) - }; unsafe { // Declare a symbol `foo` with the desired linkage. - let g1 = cx.declare_global(sym, llty2); + let g1 = cx.declare_global(sym, cx.type_i8()); llvm::LLVMRustSetLinkage(g1, base::linkage_to_llvm(linkage)); // Declare an internal global `extern_with_linkage_foo` which @@ -195,7 +185,7 @@ fn check_and_apply_linkage<'ll, 'tcx>( }) }); llvm::LLVMRustSetLinkage(g2, llvm::Linkage::InternalLinkage); - llvm::LLVMSetInitializer(g2, g1); + llvm::LLVMSetInitializer(g2, cx.const_ptrcast(g1, llty)); g2 } } else if cx.tcx.sess.target.arch == "x86" && diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index fddfbb23c67d..af9f31fc3249 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -61,13 +61,6 @@ pub(crate) struct InvalidMinimumAlignment { pub err: String, } -#[derive(Diagnostic)] -#[diag(codegen_llvm_linkage_const_or_mut_type)] -pub(crate) struct LinkageConstOrMutType { - #[primary_span] - pub span: Span, -} - #[derive(Diagnostic)] #[diag(codegen_llvm_sanitizer_memtag_requires_mte)] pub(crate) struct SanitizerMemtagRequiresMte; diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl index a1b7afeb7099..08ce5172574a 100644 --- a/compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl +++ b/compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl @@ -1,6 +1,3 @@ -codegen_gcc_linkage_const_or_mut_type = - must have type `*const T` or `*mut T` due to `#[linkage]` attribute - codegen_gcc_unwinding_inline_asm = GCC backend does not support unwinding from inline asm diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl index e273476b60bb..97198cb4be2c 100644 --- a/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl +++ b/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl @@ -23,9 +23,6 @@ codegen_llvm_branch_protection_requires_aarch64 = codegen_llvm_invalid_minimum_alignment = invalid minimum global alignment: {$err} -codegen_llvm_linkage_const_or_mut_type = - must have type `*const T` or `*mut T` due to `#[linkage]` attribute - codegen_llvm_sanitizer_memtag_requires_mte = `-Zsanitizer=memtag` requires `-Ctarget-feature=+mte` diff --git a/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl b/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl index 0894bbcaad47..86a51b2d3107 100644 --- a/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl +++ b/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl @@ -113,3 +113,6 @@ hir_analysis_const_bound_for_non_const_trait = hir_analysis_self_in_impl_self = `Self` is not valid in the self type of an impl block .note = replace `Self` with a different type + +hir_analysis_linkage_type = + must have type `*const T` or `*mut T` due to `#[linkage]` attribute diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 069b405423c4..7345e604d0b5 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -1,4 +1,5 @@ use crate::check::intrinsicck::InlineAsmCtxt; +use crate::errors::LinkageType; use super::compare_method::check_type_bounds; use super::compare_method::{compare_impl_method, compare_ty_impl}; @@ -478,6 +479,17 @@ fn check_opaque_meets_bounds<'tcx>( let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types(); } +fn check_static_linkage<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) { + if tcx.codegen_fn_attrs(def_id).import_linkage.is_some() { + if match tcx.type_of(def_id).kind() { + ty::RawPtr(_) => false, + _ => true, + } { + tcx.sess.emit_err(LinkageType { span: tcx.def_span(def_id) }); + } + } +} + fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) { debug!( "check_item_type(it.def_id={:?}, it.name={})", @@ -490,6 +502,7 @@ fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) { tcx.ensure().typeck(id.owner_id.def_id); maybe_check_static_with_link_section(tcx, id.owner_id.def_id); check_static_inhabited(tcx, id.owner_id.def_id); + check_static_linkage(tcx, id.owner_id.def_id); } DefKind::Const => { tcx.ensure().typeck(id.owner_id.def_id); @@ -627,6 +640,7 @@ fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) { } hir::ForeignItemKind::Static(..) => { check_static_inhabited(tcx, def_id); + check_static_linkage(tcx, def_id); } _ => {} } diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index b7084303aafb..945361ef43a4 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1814,7 +1814,12 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs { ); } else if attr.has_name(sym::linkage) { if let Some(val) = attr.value_str() { - codegen_fn_attrs.linkage = Some(linkage_by_name(tcx, did, val.as_str())); + let linkage = Some(linkage_by_name(tcx, did, val.as_str())); + if tcx.is_foreign_item(did) { + codegen_fn_attrs.import_linkage = linkage; + } else { + codegen_fn_attrs.linkage = linkage; + } } } else if attr.has_name(sym::link_section) { if let Some(val) = attr.value_str() { diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index afbb27155a2f..02943e7b887d 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -285,3 +285,10 @@ pub struct SelfInImplSelf { #[note] pub note: (), } + +#[derive(Diagnostic)] +#[diag(hir_analysis_linkage_type)] +pub(crate) struct LinkageType { + #[primary_span] + pub span: Span, +} diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs index 45d33a1659ff..bea884c856a9 100644 --- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs +++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs @@ -26,8 +26,10 @@ pub struct CodegenFnAttrs { /// The `#[target_feature(enable = "...")]` attribute and the enabled /// features (only enabled features are supported right now). pub target_features: Vec, - /// The `#[linkage = "..."]` attribute and the value we found. + /// The `#[linkage = "..."]` attribute on Rust-defined items and the value we found. pub linkage: Option, + /// The `#[linkage = "..."]` attribute on foreign items and the value we found. + pub import_linkage: Option, /// The `#[link_section = "..."]` attribute, or what executable section this /// should be placed in. pub link_section: Option, @@ -113,6 +115,7 @@ impl CodegenFnAttrs { link_ordinal: None, target_features: vec![], linkage: None, + import_linkage: None, link_section: None, no_sanitize: SanitizerSet::empty(), instruction_set: None, diff --git a/src/test/ui/feature-gates/feature-gate-linkage.rs b/src/test/ui/feature-gates/feature-gate-linkage.rs index 15b8d442aeb9..505f31ec6388 100644 --- a/src/test/ui/feature-gates/feature-gate-linkage.rs +++ b/src/test/ui/feature-gates/feature-gate-linkage.rs @@ -1,5 +1,5 @@ extern "C" { - #[linkage = "extern_weak"] static foo: isize; + #[linkage = "extern_weak"] static foo: *mut isize; //~^ ERROR: the `linkage` attribute is experimental and not portable } diff --git a/src/test/ui/feature-gates/feature-gate-linkage.stderr b/src/test/ui/feature-gates/feature-gate-linkage.stderr index 3e5b79bfd417..a1c73e555ef7 100644 --- a/src/test/ui/feature-gates/feature-gate-linkage.stderr +++ b/src/test/ui/feature-gates/feature-gate-linkage.stderr @@ -1,7 +1,7 @@ error[E0658]: the `linkage` attribute is experimental and not portable across platforms --> $DIR/feature-gate-linkage.rs:2:5 | -LL | #[linkage = "extern_weak"] static foo: isize; +LL | #[linkage = "extern_weak"] static foo: *mut isize; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: see issue #29603 for more information diff --git a/src/test/ui/linkage-attr/auxiliary/def_illtyped_external.rs b/src/test/ui/linkage-attr/auxiliary/def_external.rs similarity index 100% rename from src/test/ui/linkage-attr/auxiliary/def_illtyped_external.rs rename to src/test/ui/linkage-attr/auxiliary/def_external.rs diff --git a/src/test/ui/linkage-attr/linkage-import.rs b/src/test/ui/linkage-attr/linkage-import.rs new file mode 100644 index 000000000000..f754ddc6e08f --- /dev/null +++ b/src/test/ui/linkage-attr/linkage-import.rs @@ -0,0 +1,8 @@ +// build-pass +// aux-build:def_external.rs + +extern crate def_external as dep; + +fn main() { + println!("{:p}", &dep::EXTERN); +} diff --git a/src/test/ui/linkage-attr/linkage-requires-raw-ptr.rs b/src/test/ui/linkage-attr/linkage-requires-raw-ptr.rs deleted file mode 100644 index 93afc537f7c6..000000000000 --- a/src/test/ui/linkage-attr/linkage-requires-raw-ptr.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rust-lang/rust#59548: We used to ICE when trying to use a static -// with a type that violated its own `#[linkage]`. - -// build-fail -// aux-build:def_illtyped_external.rs - -extern crate def_illtyped_external as dep; - -fn main() { - println!("{:p}", &dep::EXTERN); -} diff --git a/src/test/ui/linkage-attr/linkage-requires-raw-ptr.stderr b/src/test/ui/linkage-attr/linkage-requires-raw-ptr.stderr deleted file mode 100644 index 5abbe745c6a2..000000000000 --- a/src/test/ui/linkage-attr/linkage-requires-raw-ptr.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: must have type `*const T` or `*mut T` due to `#[linkage]` attribute - --> $DIR/auxiliary/def_illtyped_external.rs:5:1 - | -LL | pub static EXTERN: u32 = 0; - | ^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to previous error - diff --git a/src/test/ui/linkage-attr/linkage2.rs b/src/test/ui/linkage-attr/linkage2.rs index a7be1985286a..3bc6634f18a0 100644 --- a/src/test/ui/linkage-attr/linkage2.rs +++ b/src/test/ui/linkage-attr/linkage2.rs @@ -1,9 +1,4 @@ -// FIXME https://github.com/rust-lang/rust/issues/59774 - -// build-fail -// normalize-stderr-test "thread.*panicked.*Metadata module not compiled.*\n" -> "" -// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> "" -// ignore-sgx no weak linkages permitted +// check-fail #![feature(linkage)] diff --git a/src/test/ui/linkage-attr/linkage2.stderr b/src/test/ui/linkage-attr/linkage2.stderr index a6ac0aad0778..44e8eaaef51e 100644 --- a/src/test/ui/linkage-attr/linkage2.stderr +++ b/src/test/ui/linkage-attr/linkage2.stderr @@ -1,5 +1,5 @@ error: must have type `*const T` or `*mut T` due to `#[linkage]` attribute - --> $DIR/linkage2.rs:12:5 + --> $DIR/linkage2.rs:7:5 | LL | static foo: i32; | ^^^^^^^^^^^^^^^ From f44a0153bc4efbb93933c9859168315883d6edc2 Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Wed, 23 Nov 2022 18:15:50 -0800 Subject: [PATCH 074/115] Support Option and similar enums as type of static variable with linkage attribute. Compiler MCP: https://github.com/rust-lang/compiler-team/issues/565 --- compiler/rustc_error_codes/src/error_codes.rs | 1 + .../src/error_codes/E0791.md | 41 +++++++++++++++++++ .../locales/en-US/hir_analysis.ftl | 2 +- .../rustc_hir_analysis/src/check/check.rs | 21 +++++++++- compiler/rustc_hir_analysis/src/errors.rs | 2 +- src/test/ui/linkage-attr/linkage2.rs | 2 +- src/test/ui/linkage-attr/linkage2.stderr | 3 +- 7 files changed, 67 insertions(+), 5 deletions(-) create mode 100644 compiler/rustc_error_codes/src/error_codes/E0791.md diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs index 1e86d159668f..31a709c36d4b 100644 --- a/compiler/rustc_error_codes/src/error_codes.rs +++ b/compiler/rustc_error_codes/src/error_codes.rs @@ -494,6 +494,7 @@ E0786: include_str!("./error_codes/E0786.md"), E0787: include_str!("./error_codes/E0787.md"), E0788: include_str!("./error_codes/E0788.md"), E0790: include_str!("./error_codes/E0790.md"), +E0791: include_str!("./error_codes/E0791.md"), ; // E0006, // merged with E0005 // E0008, // cannot bind by-move into a pattern guard diff --git a/compiler/rustc_error_codes/src/error_codes/E0791.md b/compiler/rustc_error_codes/src/error_codes/E0791.md new file mode 100644 index 000000000000..61d2f511a348 --- /dev/null +++ b/compiler/rustc_error_codes/src/error_codes/E0791.md @@ -0,0 +1,41 @@ +Static variables with the `#[linkage]` attribute within external blocks +must have one of the following types, which are equivalent to a nullable +pointer in C: + +* `*mut T` or `*const T`, where `T` may be any type. + +* An enumerator type with no `#[repr]` attribute and with two variants, where + one of the variants has no fields, and the other has a single field of one of + the following non-nullable types: + * Reference type + * Function pointer type + + The variants can appear in either order. + +For example, the following declaration is invalid: + +```compile_fail,E0791 +#![feature(linkage)] + +extern "C" { + #[linkage = "extern_weak"] + static foo: i8; +} +``` + +The following declarations are valid: + +``` +#![feature(linkage)] + +extern "C" { + #[linkage = "extern_weak"] + static foo: Option; + + #[linkage = "extern_weak"] + static bar: Option<&'static i8>; + + #[linkage = "extern_weak"] + static baz: *mut i8; +} +``` diff --git a/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl b/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl index 86a51b2d3107..a4910dacd5ff 100644 --- a/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl +++ b/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl @@ -115,4 +115,4 @@ hir_analysis_self_in_impl_self = .note = replace `Self` with a different type hir_analysis_linkage_type = - must have type `*const T` or `*mut T` due to `#[linkage]` attribute + invalid type for variable with `#[linkage]` attribute diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 7345e604d0b5..fc0ca62090d1 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -21,7 +21,7 @@ use rustc_middle::middle::stability::EvalResult; use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES}; use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::util::{Discr, IntTypeExt}; -use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable}; +use rustc_middle::ty::{self, AdtDef, ParamEnv, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable}; use rustc_session::lint::builtin::{UNINHABITED_STATIC, UNSUPPORTED_CALLING_CONVENTIONS}; use rustc_span::symbol::sym; use rustc_span::{self, Span}; @@ -479,10 +479,29 @@ fn check_opaque_meets_bounds<'tcx>( let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types(); } +fn is_enum_of_nonnullable_ptr<'tcx>( + tcx: TyCtxt<'tcx>, + adt_def: AdtDef<'tcx>, + substs: SubstsRef<'tcx>, +) -> bool { + if adt_def.repr().inhibit_enum_layout_opt() { + return false; + } + + let [var_one, var_two] = &adt_def.variants().raw[..] else { + return false; + }; + let (([], [field]) | ([field], [])) = (&var_one.fields[..], &var_two.fields[..]) else { + return false; + }; + matches!(field.ty(tcx, substs).kind(), ty::FnPtr(..) | ty::Ref(..)) +} + fn check_static_linkage<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) { if tcx.codegen_fn_attrs(def_id).import_linkage.is_some() { if match tcx.type_of(def_id).kind() { ty::RawPtr(_) => false, + ty::Adt(adt_def, substs) => !is_enum_of_nonnullable_ptr(tcx, *adt_def, *substs), _ => true, } { tcx.sess.emit_err(LinkageType { span: tcx.def_span(def_id) }); diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 02943e7b887d..1ac53fb6ddf2 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -287,7 +287,7 @@ pub struct SelfInImplSelf { } #[derive(Diagnostic)] -#[diag(hir_analysis_linkage_type)] +#[diag(hir_analysis_linkage_type, code = "E0791")] pub(crate) struct LinkageType { #[primary_span] pub span: Span, diff --git a/src/test/ui/linkage-attr/linkage2.rs b/src/test/ui/linkage-attr/linkage2.rs index 3bc6634f18a0..aa42874f7ba8 100644 --- a/src/test/ui/linkage-attr/linkage2.rs +++ b/src/test/ui/linkage-attr/linkage2.rs @@ -5,7 +5,7 @@ extern "C" { #[linkage = "extern_weak"] static foo: i32; -//~^ ERROR: must have type `*const T` or `*mut T` due to `#[linkage]` attribute +//~^ ERROR: invalid type for variable with `#[linkage]` attribute } fn main() { diff --git a/src/test/ui/linkage-attr/linkage2.stderr b/src/test/ui/linkage-attr/linkage2.stderr index 44e8eaaef51e..7265f711fd01 100644 --- a/src/test/ui/linkage-attr/linkage2.stderr +++ b/src/test/ui/linkage-attr/linkage2.stderr @@ -1,4 +1,4 @@ -error: must have type `*const T` or `*mut T` due to `#[linkage]` attribute +error[E0791]: invalid type for variable with `#[linkage]` attribute --> $DIR/linkage2.rs:7:5 | LL | static foo: i32; @@ -6,3 +6,4 @@ LL | static foo: i32; error: aborting due to previous error +For more information about this error, try `rustc --explain E0791`. From b4278b02a7e6ad814c09bbc6c066c1713171fe82 Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Wed, 23 Nov 2022 18:16:28 -0800 Subject: [PATCH 075/115] Reimplement weak! using Option. --- library/std/src/sys/unix/weak.rs | 37 +++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/library/std/src/sys/unix/weak.rs b/library/std/src/sys/unix/weak.rs index e4ff21b25bd9..f5a4ce929b2a 100644 --- a/library/std/src/sys/unix/weak.rs +++ b/library/std/src/sys/unix/weak.rs @@ -29,7 +29,21 @@ use crate::ptr; use crate::sync::atomic::{self, AtomicPtr, Ordering}; // We can use true weak linkage on ELF targets. -#[cfg(not(any(target_os = "macos", target_os = "ios")))] +#[cfg(all(not(any(target_os = "macos", target_os = "ios")), not(bootstrap)))] +pub(crate) macro weak { + (fn $name:ident($($t:ty),*) -> $ret:ty) => ( + let ref $name: ExternWeak $ret> = { + extern "C" { + #[linkage = "extern_weak"] + static $name: Option $ret>; + } + #[allow(unused_unsafe)] + ExternWeak::new(unsafe { $name }) + }; + ) +} + +#[cfg(all(not(any(target_os = "macos", target_os = "ios")), bootstrap))] pub(crate) macro weak { (fn $name:ident($($t:ty),*) -> $ret:ty) => ( let ref $name: ExternWeak $ret> = { @@ -47,11 +61,31 @@ pub(crate) macro weak { #[cfg(any(target_os = "macos", target_os = "ios"))] pub(crate) use self::dlsym as weak; +#[cfg(not(bootstrap))] +pub(crate) struct ExternWeak { + weak_ptr: Option, +} + +#[cfg(not(bootstrap))] +impl ExternWeak { + #[inline] + pub(crate) fn new(weak_ptr: Option) -> Self { + ExternWeak { weak_ptr } + } + + #[inline] + pub(crate) fn get(&self) -> Option { + self.weak_ptr + } +} + +#[cfg(bootstrap)] pub(crate) struct ExternWeak { weak_ptr: *const libc::c_void, _marker: PhantomData, } +#[cfg(bootstrap)] impl ExternWeak { #[inline] pub(crate) fn new(weak_ptr: *const libc::c_void) -> Self { @@ -59,6 +93,7 @@ impl ExternWeak { } } +#[cfg(bootstrap)] impl ExternWeak { #[inline] pub(crate) fn get(&self) -> Option { From c9bab74fb2cb494b99edba2f8b999dfe9281c548 Mon Sep 17 00:00:00 2001 From: Boxy Date: Mon, 5 Dec 2022 23:17:55 +0000 Subject: [PATCH 076/115] support `Expr` in `is_const_evaluatable` and `compute` --- .../src/traits/const_evaluatable.rs | 58 +++++++++++++------ .../rustc_trait_selection/src/traits/wf.rs | 19 +++++- .../const_kind_expr/wf_obligation.rs | 22 +++++++ .../const_kind_expr/wf_obligation.stderr | 20 +++++++ 4 files changed, 99 insertions(+), 20 deletions(-) create mode 100644 src/test/ui/const-generics/generic_const_exprs/const_kind_expr/wf_obligation.rs create mode 100644 src/test/ui/const-generics/generic_const_exprs/const_kind_expr/wf_obligation.stderr diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index e9e65336299e..d01c6bac2963 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -25,15 +25,13 @@ use crate::traits::ObligationCtxt; #[instrument(skip(infcx), level = "debug")] pub fn is_const_evaluatable<'tcx>( infcx: &InferCtxt<'tcx>, - ct: ty::Const<'tcx>, + unexpanded_ct: ty::Const<'tcx>, param_env: ty::ParamEnv<'tcx>, span: Span, ) -> Result<(), NotConstEvaluatable> { let tcx = infcx.tcx; - let uv = match ct.kind() { - ty::ConstKind::Unevaluated(uv) => uv, - // FIXME(generic_const_exprs): this seems wrong but I couldn't find a way to get this to trigger - ty::ConstKind::Expr(_) => bug!("unexpected expr in `is_const_evaluatable: {ct:?}"), + match unexpanded_ct.kind() { + ty::ConstKind::Unevaluated(_) | ty::ConstKind::Expr(_) => (), ty::ConstKind::Param(_) | ty::ConstKind::Bound(_, _) | ty::ConstKind::Placeholder(_) @@ -43,7 +41,7 @@ pub fn is_const_evaluatable<'tcx>( }; if tcx.features().generic_const_exprs { - let ct = tcx.expand_abstract_consts(ct); + let ct = tcx.expand_abstract_consts(unexpanded_ct); let is_anon_ct = if let ty::ConstKind::Unevaluated(uv) = ct.kind() { tcx.def_kind(uv.def.did) == DefKind::AnonConst @@ -62,18 +60,40 @@ pub fn is_const_evaluatable<'tcx>( } } - let concrete = infcx.const_eval_resolve(param_env, uv, Some(span)); - match concrete { - Err(ErrorHandled::TooGeneric) => Err(NotConstEvaluatable::Error( - infcx - .tcx - .sess - .delay_span_bug(span, "Missing value for constant, but no error reported?"), - )), - Err(ErrorHandled::Reported(e)) => Err(NotConstEvaluatable::Error(e)), - Ok(_) => Ok(()), + match unexpanded_ct.kind() { + ty::ConstKind::Expr(_) => { + // FIXME(generic_const_exprs): we have a `ConstKind::Expr` which is fully concrete, but + // currently it is not possible to evaluate `ConstKind::Expr` so we are unable to tell if it + // is evaluatable or not. For now we just ICE until this is implemented this. + Err(NotConstEvaluatable::Error(tcx.sess.delay_span_bug( + span, + "evaluating `ConstKind::Expr` is not currently supported", + ))) + } + ty::ConstKind::Unevaluated(uv) => { + let concrete = infcx.const_eval_resolve(param_env, uv, Some(span)); + match concrete { + Err(ErrorHandled::TooGeneric) => { + Err(NotConstEvaluatable::Error(infcx.tcx.sess.delay_span_bug( + span, + "Missing value for constant, but no error reported?", + ))) + } + Err(ErrorHandled::Reported(e)) => Err(NotConstEvaluatable::Error(e)), + Ok(_) => Ok(()), + } + } + _ => bug!("unexpected constkind in `is_const_evalautable: {unexpanded_ct:?}`"), } } else { + let uv = match unexpanded_ct.kind() { + ty::ConstKind::Unevaluated(uv) => uv, + ty::ConstKind::Expr(_) => { + bug!("`ConstKind::Expr` without `feature(generic_const_exprs)` enabled") + } + _ => bug!("unexpected constkind in `is_const_evalautable: {unexpanded_ct:?}`"), + }; + // FIXME: We should only try to evaluate a given constant here if it is fully concrete // as we don't want to allow things like `[u8; std::mem::size_of::<*mut T>()]`. // @@ -92,7 +112,7 @@ pub fn is_const_evaluatable<'tcx>( && satisfied_from_param_env( tcx, infcx, - tcx.expand_abstract_consts(ct), + tcx.expand_abstract_consts(unexpanded_ct), param_env, ) => { @@ -152,6 +172,7 @@ fn satisfied_from_param_env<'tcx>( impl<'a, 'tcx> TypeVisitor<'tcx> for Visitor<'a, 'tcx> { type BreakTy = (); fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow { + debug!("is_const_evaluatable: candidate={:?}", c); if let Ok(()) = self.infcx.commit_if_ok(|_| { let ocx = ObligationCtxt::new_in_snapshot(self.infcx); if let Ok(()) = ocx.eq(&ObligationCause::dummy(), self.param_env, c.ty(), self.ct.ty()) @@ -187,7 +208,7 @@ fn satisfied_from_param_env<'tcx>( let result = b_ct.visit_with(&mut v); if let ControlFlow::Break(()) = result { - debug!("is_const_evaluatable: abstract_const ~~> ok"); + debug!("is_const_evaluatable: yes"); return true; } } @@ -195,5 +216,6 @@ fn satisfied_from_param_env<'tcx>( } } + debug!("is_const_evaluatable: no"); false } diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 0855d6d19736..e47ba64245f5 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -476,9 +476,24 @@ impl<'tcx> WfPredicates<'tcx> { ty::Binder::dummy(ty::PredicateKind::WellFormed(ct.into())), )); } - // FIXME(generic_const_exprs): This seems wrong but I could not find a way to get this to trigger ty::ConstKind::Expr(_) => { - bug!("checking wfness of `ConstKind::Expr` is unsupported") + // FIXME(generic_const_exprs): this doesnt verify that given `Expr(N + 1)` the + // trait bound `typeof(N): Add` holds. This is currently unnecessary + // as `ConstKind::Expr` is only produced via normalization of `ConstKind::Unevaluated` + // which means that the `DefId` would have been typeck'd elsewhere. However in + // the future we may allow directly lowering to `ConstKind::Expr` in which case + // we would not be proving bounds we should. + + let predicate = + ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(ct)); + let cause = self.cause(traits::WellFormed(None)); + self.out.push(traits::Obligation::with_depth( + self.tcx(), + cause, + self.recursion_depth, + self.param_env, + predicate, + )); } ty::ConstKind::Error(_) diff --git a/src/test/ui/const-generics/generic_const_exprs/const_kind_expr/wf_obligation.rs b/src/test/ui/const-generics/generic_const_exprs/const_kind_expr/wf_obligation.rs new file mode 100644 index 000000000000..6093fc70b169 --- /dev/null +++ b/src/test/ui/const-generics/generic_const_exprs/const_kind_expr/wf_obligation.rs @@ -0,0 +1,22 @@ +#![feature(generic_const_exprs, generic_arg_infer)] +#![allow(incomplete_features)] + +// minimized repro for #105205 +// +// the `foo::<_, L>` call results in a `WellFormed(_)` obligation and a +// `ConstEvaluatable(Unevaluated(_ + 1 + L))` obligation. Attempting to fulfill the latter +// unifies the `_` with `Expr(L - 1)` from the paramenv which turns the `WellFormed` +// obligation into `WellFormed(Expr(L - 1))` + +fn foo(_: [(); N + 1 + M]) {} + +fn ice() +where + [(); (L - 1) + 1 + L]:, +{ + foo::<_, L>([(); L + 1 + L]); + //~^ ERROR: mismatched types + //~^^ ERROR: unconstrained generic constant +} + +fn main() {} diff --git a/src/test/ui/const-generics/generic_const_exprs/const_kind_expr/wf_obligation.stderr b/src/test/ui/const-generics/generic_const_exprs/const_kind_expr/wf_obligation.stderr new file mode 100644 index 000000000000..da5194696e65 --- /dev/null +++ b/src/test/ui/const-generics/generic_const_exprs/const_kind_expr/wf_obligation.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/wf_obligation.rs:17:17 + | +LL | foo::<_, L>([(); L + 1 + L]); + | ^^^^^^^^^^^^^^^ expected `N + 1 + M`, found `L + 1 + L` + | + = note: expected constant `N + 1 + M` + found constant `L + 1 + L` + +error: unconstrained generic constant + --> $DIR/wf_obligation.rs:17:22 + | +LL | foo::<_, L>([(); L + 1 + L]); + | ^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); L + 1 + L]:` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. From e940f845be13ff37d4ba28df5f40d74e5b0895a0 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 6 Dec 2022 00:00:01 +0000 Subject: [PATCH 077/115] drive-by: Default param for ToPredicate --- .../rustc_borrowck/src/type_check/canonical.rs | 6 ++---- compiler/rustc_middle/src/ty/mod.rs | 18 +++++++++--------- .../rustc_trait_selection/src/traits/mod.rs | 2 +- 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs index 1aad6738bba7..3617bf58be9d 100644 --- a/compiler/rustc_borrowck/src/type_check/canonical.rs +++ b/compiler/rustc_borrowck/src/type_check/canonical.rs @@ -121,9 +121,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { pub(super) fn prove_predicates( &mut self, - predicates: impl IntoIterator< - Item = impl ToPredicate<'tcx, ty::Predicate<'tcx>> + std::fmt::Debug, - >, + predicates: impl IntoIterator + std::fmt::Debug>, locations: Locations, category: ConstraintCategory<'tcx>, ) { @@ -135,7 +133,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { #[instrument(skip(self), level = "debug")] pub(super) fn prove_predicate( &mut self, - predicate: impl ToPredicate<'tcx, ty::Predicate<'tcx>> + std::fmt::Debug, + predicate: impl ToPredicate<'tcx> + std::fmt::Debug, locations: Locations, category: ConstraintCategory<'tcx>, ) { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index dd4ab3e8d30b..81847e2e4cab 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1150,8 +1150,8 @@ impl<'tcx> ToPolyTraitRef<'tcx> for PolyTraitPredicate<'tcx> { } } -pub trait ToPredicate<'tcx, Predicate> { - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate; +pub trait ToPredicate<'tcx, P = Predicate<'tcx>> { + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> P; } impl<'tcx, T> ToPredicate<'tcx, T> for T { @@ -1160,21 +1160,21 @@ impl<'tcx, T> ToPredicate<'tcx, T> for T { } } -impl<'tcx> ToPredicate<'tcx, Predicate<'tcx>> for Binder<'tcx, PredicateKind<'tcx>> { +impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, PredicateKind<'tcx>> { #[inline(always)] fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { tcx.mk_predicate(self) } } -impl<'tcx> ToPredicate<'tcx, Predicate<'tcx>> for Clause<'tcx> { +impl<'tcx> ToPredicate<'tcx> for Clause<'tcx> { #[inline(always)] fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { tcx.mk_predicate(ty::Binder::dummy(ty::PredicateKind::Clause(self))) } } -impl<'tcx> ToPredicate<'tcx, Predicate<'tcx>> for Binder<'tcx, TraitRef<'tcx>> { +impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, TraitRef<'tcx>> { #[inline(always)] fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { let pred: PolyTraitPredicate<'tcx> = self.to_predicate(tcx); @@ -1193,25 +1193,25 @@ impl<'tcx> ToPredicate<'tcx, PolyTraitPredicate<'tcx>> for Binder<'tcx, TraitRef } } -impl<'tcx> ToPredicate<'tcx, Predicate<'tcx>> for PolyTraitPredicate<'tcx> { +impl<'tcx> ToPredicate<'tcx> for PolyTraitPredicate<'tcx> { fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { self.map_bound(|p| PredicateKind::Clause(Clause::Trait(p))).to_predicate(tcx) } } -impl<'tcx> ToPredicate<'tcx, Predicate<'tcx>> for PolyRegionOutlivesPredicate<'tcx> { +impl<'tcx> ToPredicate<'tcx> for PolyRegionOutlivesPredicate<'tcx> { fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { self.map_bound(|p| PredicateKind::Clause(Clause::RegionOutlives(p))).to_predicate(tcx) } } -impl<'tcx> ToPredicate<'tcx, Predicate<'tcx>> for PolyTypeOutlivesPredicate<'tcx> { +impl<'tcx> ToPredicate<'tcx> for PolyTypeOutlivesPredicate<'tcx> { fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { self.map_bound(|p| PredicateKind::Clause(Clause::TypeOutlives(p))).to_predicate(tcx) } } -impl<'tcx> ToPredicate<'tcx, Predicate<'tcx>> for PolyProjectionPredicate<'tcx> { +impl<'tcx> ToPredicate<'tcx> for PolyProjectionPredicate<'tcx> { fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { self.map_bound(|p| PredicateKind::Clause(Clause::Projection(p))).to_predicate(tcx) } diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index c6818a4e57d4..d3cfd61e1956 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -150,7 +150,7 @@ pub fn type_known_to_meet_bound_modulo_regions<'tcx>( fn pred_known_to_hold_modulo_regions<'tcx>( infcx: &InferCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, - pred: impl ToPredicate<'tcx, ty::Predicate<'tcx>> + TypeVisitable<'tcx>, + pred: impl ToPredicate<'tcx> + TypeVisitable<'tcx>, span: Span, ) -> bool { let has_non_region_infer = pred.has_non_region_infer(); From d2a80c157145d0c1e6fd6669862358de6cd89185 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 6 Dec 2022 00:19:42 +0000 Subject: [PATCH 078/115] Avoid noting cause code (which is usually misc, b/c codegen) for opaque type reveal overflow --- .../src/traits/codegen.rs | 2 +- .../src/traits/error_reporting/mod.rs | 88 ++++++++++++++----- .../src/traits/error_reporting/suggestions.rs | 4 +- .../src/traits/project.rs | 12 ++- .../src/traits/query/normalize.rs | 14 ++- .../src/traits/select/mod.rs | 13 +-- 6 files changed, 82 insertions(+), 51 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/codegen.rs b/compiler/rustc_trait_selection/src/traits/codegen.rs index 61743d78e9e8..0102d268b42e 100644 --- a/compiler/rustc_trait_selection/src/traits/codegen.rs +++ b/compiler/rustc_trait_selection/src/traits/codegen.rs @@ -70,7 +70,7 @@ pub fn codegen_select_candidate<'tcx>( // `rustc_ty_utils::resolve_associated_item` doesn't return `None` post-monomorphization. for err in errors { if let FulfillmentErrorCode::CodeCycle(cycle) = err.code { - infcx.err_ctxt().report_overflow_error_cycle(&cycle); + infcx.err_ctxt().report_overflow_obligation_cycle(&cycle); } } return Err(CodegenObligationError::FulfillmentError); diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 56dea916b305..80870d871d16 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -99,16 +99,12 @@ pub trait InferCtxtExt<'tcx> { } pub trait TypeErrCtxtExt<'tcx> { - fn report_fulfillment_errors( - &self, - errors: &[FulfillmentError<'tcx>], - body_id: Option, - ) -> ErrorGuaranteed; - fn report_overflow_error( &self, - obligation: &Obligation<'tcx, T>, + predicate: &T, + span: Span, suggest_increasing_limit: bool, + mutate: impl FnOnce(&mut Diagnostic), ) -> ! where T: fmt::Display @@ -116,9 +112,23 @@ pub trait TypeErrCtxtExt<'tcx> { + Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>, >>::Error: std::fmt::Debug; + fn report_fulfillment_errors( + &self, + errors: &[FulfillmentError<'tcx>], + body_id: Option, + ) -> ErrorGuaranteed; + + fn report_overflow_obligation( + &self, + obligation: &Obligation<'tcx, T>, + suggest_increasing_limit: bool, + ) -> ! + where + T: ToPredicate<'tcx> + Clone; + fn suggest_new_overflow_limit(&self, err: &mut Diagnostic); - fn report_overflow_error_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> !; + fn report_overflow_obligation_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> !; /// The `root_obligation` parameter should be the `root_obligation` field /// from a `FulfillmentError`. If no `FulfillmentError` is available, @@ -458,8 +468,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { /// occurrences in any case. fn report_overflow_error( &self, - obligation: &Obligation<'tcx, T>, + predicate: &T, + span: Span, suggest_increasing_limit: bool, + mutate: impl FnOnce(&mut Diagnostic), ) -> ! where T: fmt::Display @@ -467,8 +479,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { + Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>, >>::Error: std::fmt::Debug, { - let predicate = self.resolve_vars_if_possible(obligation.predicate.clone()); + let predicate = self.resolve_vars_if_possible(predicate.clone()); let mut pred_str = predicate.to_string(); + if pred_str.len() > 50 { // We don't need to save the type to a file, we will be talking about this type already // in a separate note when we explain the obligation, so it will be available that way. @@ -483,7 +496,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } let mut err = struct_span_err!( self.tcx.sess, - obligation.cause.span, + span, E0275, "overflow evaluating the requirement `{}`", pred_str, @@ -493,20 +506,46 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { self.suggest_new_overflow_limit(&mut err); } - self.note_obligation_cause_code( - &mut err, - &obligation.predicate, - obligation.param_env, - obligation.cause.code(), - &mut vec![], - &mut Default::default(), - ); + mutate(&mut err); err.emit(); self.tcx.sess.abort_if_errors(); bug!(); } + /// Reports that an overflow has occurred and halts compilation. We + /// halt compilation unconditionally because it is important that + /// overflows never be masked -- they basically represent computations + /// whose result could not be truly determined and thus we can't say + /// if the program type checks or not -- and they are unusual + /// occurrences in any case. + fn report_overflow_obligation( + &self, + obligation: &Obligation<'tcx, T>, + suggest_increasing_limit: bool, + ) -> ! + where + T: ToPredicate<'tcx> + Clone, + { + let predicate = obligation.predicate.clone().to_predicate(self.tcx); + let predicate = self.resolve_vars_if_possible(predicate); + self.report_overflow_error( + &predicate, + obligation.cause.span, + suggest_increasing_limit, + |err| { + self.note_obligation_cause_code( + err, + &predicate, + obligation.param_env, + obligation.cause.code(), + &mut vec![], + &mut Default::default(), + ); + }, + ); + } + fn suggest_new_overflow_limit(&self, err: &mut Diagnostic) { let suggested_limit = match self.tcx.recursion_limit() { Limit(0) => Limit(2), @@ -521,11 +560,11 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } /// Reports that a cycle was detected which led to overflow and halts - /// compilation. This is equivalent to `report_overflow_error` except + /// compilation. This is equivalent to `report_overflow_obligation` except /// that we can give a more helpful error message (and, in particular, /// we do not suggest increasing the overflow limit, which is not /// going to help). - fn report_overflow_error_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> ! { + fn report_overflow_obligation_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> ! { let cycle = self.resolve_vars_if_possible(cycle.to_owned()); assert!(!cycle.is_empty()); @@ -533,7 +572,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { // The 'deepest' obligation is most likely to have a useful // cause 'backtrace' - self.report_overflow_error(cycle.iter().max_by_key(|p| p.recursion_depth).unwrap(), false); + self.report_overflow_obligation( + cycle.iter().max_by_key(|p| p.recursion_depth).unwrap(), + false, + ); } fn report_selection_error( @@ -1554,7 +1596,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { diag.emit(); } FulfillmentErrorCode::CodeCycle(ref cycle) => { - self.report_overflow_error_cycle(cycle); + self.report_overflow_obligation_cycle(cycle); } } } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 1740128727a5..6ea54b625bbc 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -298,7 +298,7 @@ pub trait TypeErrCtxtExt<'tcx> { obligated_types: &mut Vec>, seen_requirements: &mut FxHashSet, ) where - T: fmt::Display + ToPredicate<'tcx, T>; + T: fmt::Display + ToPredicate<'tcx>; /// Suggest to await before try: future? => future.await? fn suggest_await_before_try( @@ -2353,7 +2353,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { obligated_types: &mut Vec>, seen_requirements: &mut FxHashSet, ) where - T: fmt::Display, + T: fmt::Display + ToPredicate<'tcx>, { let tcx = self.tcx; match *cause_code { diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 051660be9c47..1790ef5b4814 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -504,14 +504,12 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { Reveal::All => { let recursion_limit = self.tcx().recursion_limit(); if !recursion_limit.value_within_limit(self.depth) { - let obligation = Obligation::with_depth( - self.tcx(), - self.cause.clone(), - recursion_limit.0, - self.param_env, - ty, + self.selcx.infcx.err_ctxt().report_overflow_error( + &ty, + self.cause.span, + true, + |_| {}, ); - self.selcx.infcx.err_ctxt().report_overflow_error(&obligation, true); } let substs = substs.fold_with(self); diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index f899321fc01e..7ad532d8a346 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -7,7 +7,7 @@ use crate::infer::canonical::OriginalQueryValues; use crate::infer::{InferCtxt, InferOk}; use crate::traits::error_reporting::TypeErrCtxtExt; use crate::traits::project::{needs_normalization, BoundVarReplacer, PlaceholderReplacer}; -use crate::traits::{Obligation, ObligationCause, PredicateObligation, Reveal}; +use crate::traits::{ObligationCause, PredicateObligation, Reveal}; use rustc_data_structures::sso::SsoHashMap; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_infer::traits::Normalized; @@ -214,14 +214,12 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { let substs = substs.try_fold_with(self)?; let recursion_limit = self.tcx().recursion_limit(); if !recursion_limit.value_within_limit(self.anon_depth) { - let obligation = Obligation::with_depth( - self.tcx(), - self.cause.clone(), - recursion_limit.0, - self.param_env, - ty, + self.infcx.err_ctxt().report_overflow_error( + &ty, + self.cause.span, + true, + |_| {}, ); - self.infcx.err_ctxt().report_overflow_error(&obligation, true); } let generic_ty = self.tcx().bound_type_of(def_id); diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 8835f2cc1b97..035deb616398 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -43,7 +43,6 @@ use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::ty::abstract_const::NotConstEvaluatable; use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams}; use rustc_middle::ty::fold::BottomUpFolder; -use rustc_middle::ty::print::{FmtPrinter, Print}; use rustc_middle::ty::relate::TypeRelation; use rustc_middle::ty::SubstsRef; use rustc_middle::ty::{self, EarlyBinder, PolyProjectionPredicate, ToPolyTraitRef, ToPredicate}; @@ -1313,10 +1312,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { error_obligation: &Obligation<'tcx, T>, ) -> Result<(), OverflowError> where - T: fmt::Display - + TypeFoldable<'tcx> - + Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>, - >>::Error: std::fmt::Debug, + T: ToPredicate<'tcx> + Clone, { if !self.infcx.tcx.recursion_limit().value_within_limit(depth) { match self.query_mode { @@ -1324,7 +1320,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { if let Some(e) = self.infcx.tainted_by_errors() { return Err(OverflowError::Error(e)); } - self.infcx.err_ctxt().report_overflow_error(error_obligation, true); + self.infcx.err_ctxt().report_overflow_obligation(error_obligation, true); } TraitQueryMode::Canonical => { return Err(OverflowError::Canonical); @@ -1345,10 +1341,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { error_obligation: &Obligation<'tcx, V>, ) -> Result<(), OverflowError> where - V: fmt::Display - + TypeFoldable<'tcx> - + Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>, - >>::Error: std::fmt::Debug, + V: ToPredicate<'tcx> + Clone, { self.check_recursion_depth(obligation.recursion_depth, error_obligation) } From c559cf62c21f9e4f804fae633f6d0499be7fae1c Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Tue, 6 Dec 2022 01:01:42 +0000 Subject: [PATCH 079/115] Simplify attribute handling in rustc_ast_lowering Given that attributes is stored in a separate BTreeMap, it's not necessary to pass it in when constructing `hir::Expr`. We can just construct `hir::Expr` and then call `self.lower_attrs` later if it needs attributes. As most desugaring code don't use attributes, this allows some code cleanup. --- compiler/rustc_ast_lowering/src/expr.rs | 133 +++++++----------------- compiler/rustc_ast_lowering/src/item.rs | 16 +-- compiler/rustc_ast_lowering/src/lib.rs | 2 +- 3 files changed, 45 insertions(+), 106 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 695ccec0b1cb..77b7ee38bde0 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -436,18 +436,14 @@ impl<'hir> LoweringContext<'_, 'hir> { let lhs = self.lower_cond(lhs); let rhs = self.lower_cond(rhs); - self.arena.alloc(self.expr( - cond.span, - hir::ExprKind::Binary(op, lhs, rhs), - AttrVec::new(), - )) + self.arena.alloc(self.expr(cond.span, hir::ExprKind::Binary(op, lhs, rhs))) } ExprKind::Let(..) => self.lower_expr(cond), _ => { let cond = self.lower_expr(cond); let reason = DesugaringKind::CondTemporary; let span_block = self.mark_span_with_reason(reason, cond.span, None); - self.expr_drop_temps(span_block, cond, AttrVec::new()) + self.expr_drop_temps(span_block, cond) } } } @@ -477,12 +473,12 @@ impl<'hir> LoweringContext<'_, 'hir> { ) -> hir::ExprKind<'hir> { let lowered_cond = self.with_loop_condition_scope(|t| t.lower_cond(cond)); let then = self.lower_block_expr(body); - let expr_break = self.expr_break(span, AttrVec::new()); + let expr_break = self.expr_break(span); let stmt_break = self.stmt_expr(span, expr_break); let else_blk = self.block_all(span, arena_vec![self; stmt_break], None); - let else_expr = self.arena.alloc(self.expr_block(else_blk, AttrVec::new())); + let else_expr = self.arena.alloc(self.expr_block(else_blk)); let if_kind = hir::ExprKind::If(lowered_cond, self.arena.alloc(then), Some(else_expr)); - let if_expr = self.expr(span, if_kind, AttrVec::new()); + let if_expr = self.expr(span, if_kind); let block = self.block_expr(self.arena.alloc(if_expr)); let span = self.lower_span(span.with_hi(cond.span.hi())); let opt_label = self.lower_label(opt_label); @@ -538,12 +534,7 @@ impl<'hir> LoweringContext<'_, 'hir> { expr: &'hir hir::Expr<'hir>, overall_span: Span, ) -> &'hir hir::Expr<'hir> { - let constructor = self.arena.alloc(self.expr_lang_item_path( - method_span, - lang_item, - AttrVec::new(), - None, - )); + let constructor = self.arena.alloc(self.expr_lang_item_path(method_span, lang_item, None)); self.expr_call(overall_span, constructor, std::slice::from_ref(expr)) } @@ -694,12 +685,8 @@ impl<'hir> LoweringContext<'_, 'hir> { // E0700 in src/test/ui/self/self_lifetime-async.rs // `future::identity_future`: - let identity_future = self.expr_lang_item_path( - unstable_span, - hir::LangItem::IdentityFuture, - AttrVec::new(), - None, - ); + let identity_future = + self.expr_lang_item_path(unstable_span, hir::LangItem::IdentityFuture, None); // `future::identity_future(generator)`: hir::ExprKind::Call(self.arena.alloc(identity_future), arena_vec![self; generator]) @@ -802,7 +789,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let break_x = self.with_loop_scope(loop_node_id, move |this| { let expr_break = hir::ExprKind::Break(this.lower_loop_destination(None), Some(x_expr)); - this.arena.alloc(this.expr(gen_future_span, expr_break, AttrVec::new())) + this.arena.alloc(this.expr(gen_future_span, expr_break)) }); self.arm(ready_pat, break_x) }; @@ -835,17 +822,13 @@ impl<'hir> LoweringContext<'_, 'hir> { let yield_expr = self.expr( span, hir::ExprKind::Yield(unit, hir::YieldSource::Await { expr: Some(expr_hir_id) }), - AttrVec::new(), ); let yield_expr = self.arena.alloc(yield_expr); if let Some(task_context_hid) = self.task_context { let lhs = self.expr_ident(span, task_context_ident, task_context_hid); - let assign = self.expr( - span, - hir::ExprKind::Assign(lhs, yield_expr, self.lower_span(span)), - AttrVec::new(), - ); + let assign = + self.expr(span, hir::ExprKind::Assign(lhs, yield_expr, self.lower_span(span))); self.stmt_expr(span, assign) } else { // Use of `await` outside of an async context. Return `yield_expr` so that we can @@ -1029,7 +1012,7 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::AsyncGeneratorKind::Closure, |this| this.with_new_scopes(|this| this.lower_expr_mut(body)), ); - this.expr(fn_decl_span, async_body, AttrVec::new()) + this.expr(fn_decl_span, async_body) }); body_id }); @@ -1289,7 +1272,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let ident = self.expr_ident(lhs.span, ident, binding); let assign = hir::ExprKind::Assign(self.lower_expr(lhs), ident, self.lower_span(eq_sign_span)); - let expr = self.expr(lhs.span, assign, AttrVec::new()); + let expr = self.expr(lhs.span, assign); assignments.push(self.stmt_expr(lhs.span, expr)); pat } @@ -1330,8 +1313,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let e2 = self.lower_expr_mut(e2); let fn_path = hir::QPath::LangItem(hir::LangItem::RangeInclusiveNew, self.lower_span(span), None); - let fn_expr = - self.arena.alloc(self.expr(span, hir::ExprKind::Path(fn_path), AttrVec::new())); + let fn_expr = self.arena.alloc(self.expr(span, hir::ExprKind::Path(fn_path))); hir::ExprKind::Call(fn_expr, arena_vec![self; e1, e2]) } @@ -1503,8 +1485,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // `None => break` let none_arm = { - let break_expr = - self.with_loop_scope(e.id, |this| this.expr_break_alloc(for_span, AttrVec::new())); + let break_expr = self.with_loop_scope(e.id, |this| this.expr_break_alloc(for_span)); let pat = self.pat_none(for_span); self.arm(pat, break_expr) }; @@ -1513,7 +1494,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let some_arm = { let some_pat = self.pat_some(pat_span, pat); let body_block = self.with_loop_scope(e.id, |this| this.lower_block(body, false)); - let body_expr = self.arena.alloc(self.expr_block(body_block, AttrVec::new())); + let body_expr = self.arena.alloc(self.expr_block(body_block)); self.arm(some_pat, body_expr) }; @@ -1576,7 +1557,9 @@ impl<'hir> LoweringContext<'_, 'hir> { // surrounding scope of the `match` since the `match` is not a terminating scope. // // Also, add the attributes to the outer returned expr node. - self.expr_drop_temps_mut(for_span, match_expr, e.attrs.clone()) + let expr = self.expr_drop_temps_mut(for_span, match_expr); + self.lower_attrs(expr.hir_id, &e.attrs); + expr } /// Desugar `ExprKind::Try` from: `?` into: @@ -1631,12 +1614,8 @@ impl<'hir> LoweringContext<'_, 'hir> { let continue_arm = { let val_ident = Ident::with_dummy_span(sym::val); let (val_pat, val_pat_nid) = self.pat_ident(span, val_ident); - let val_expr = self.arena.alloc(self.expr_ident_with_attrs( - span, - val_ident, - val_pat_nid, - attrs.clone(), - )); + let val_expr = self.expr_ident(span, val_ident, val_pat_nid); + self.lower_attrs(val_expr.hir_id, &attrs); let continue_pat = self.pat_cf_continue(unstable_span, val_pat); self.arm(continue_pat, val_expr) }; @@ -1662,15 +1641,11 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::Destination { label: None, target_id }, Some(from_residual_expr), ), - attrs, )) } else { - self.arena.alloc(self.expr( - try_span, - hir::ExprKind::Ret(Some(from_residual_expr)), - attrs, - )) + self.arena.alloc(self.expr(try_span, hir::ExprKind::Ret(Some(from_residual_expr)))) }; + self.lower_attrs(ret_expr.hir_id, &attrs); let break_pat = self.pat_cf_break(try_span, residual_local); self.arm(break_pat, ret_expr) @@ -1735,18 +1710,16 @@ impl<'hir> LoweringContext<'_, 'hir> { &mut self, span: Span, expr: &'hir hir::Expr<'hir>, - attrs: AttrVec, ) -> &'hir hir::Expr<'hir> { - self.arena.alloc(self.expr_drop_temps_mut(span, expr, attrs)) + self.arena.alloc(self.expr_drop_temps_mut(span, expr)) } pub(super) fn expr_drop_temps_mut( &mut self, span: Span, expr: &'hir hir::Expr<'hir>, - attrs: AttrVec, ) -> hir::Expr<'hir> { - self.expr(span, hir::ExprKind::DropTemps(expr), attrs) + self.expr(span, hir::ExprKind::DropTemps(expr)) } fn expr_match( @@ -1756,29 +1729,25 @@ impl<'hir> LoweringContext<'_, 'hir> { arms: &'hir [hir::Arm<'hir>], source: hir::MatchSource, ) -> hir::Expr<'hir> { - self.expr(span, hir::ExprKind::Match(arg, arms, source), AttrVec::new()) + self.expr(span, hir::ExprKind::Match(arg, arms, source)) } - fn expr_break(&mut self, span: Span, attrs: AttrVec) -> hir::Expr<'hir> { + fn expr_break(&mut self, span: Span) -> hir::Expr<'hir> { let expr_break = hir::ExprKind::Break(self.lower_loop_destination(None), None); - self.expr(span, expr_break, attrs) + self.expr(span, expr_break) } - fn expr_break_alloc(&mut self, span: Span, attrs: AttrVec) -> &'hir hir::Expr<'hir> { - let expr_break = self.expr_break(span, attrs); + fn expr_break_alloc(&mut self, span: Span) -> &'hir hir::Expr<'hir> { + let expr_break = self.expr_break(span); self.arena.alloc(expr_break) } fn expr_mut_addr_of(&mut self, span: Span, e: &'hir hir::Expr<'hir>) -> hir::Expr<'hir> { - self.expr( - span, - hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Mut, e), - AttrVec::new(), - ) + self.expr(span, hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Mut, e)) } fn expr_unit(&mut self, sp: Span) -> &'hir hir::Expr<'hir> { - self.arena.alloc(self.expr(sp, hir::ExprKind::Tup(&[]), AttrVec::new())) + self.arena.alloc(self.expr(sp, hir::ExprKind::Tup(&[]))) } fn expr_call_mut( @@ -1787,7 +1756,7 @@ impl<'hir> LoweringContext<'_, 'hir> { e: &'hir hir::Expr<'hir>, args: &'hir [hir::Expr<'hir>], ) -> hir::Expr<'hir> { - self.expr(span, hir::ExprKind::Call(e, args), AttrVec::new()) + self.expr(span, hir::ExprKind::Call(e, args)) } fn expr_call( @@ -1806,8 +1775,7 @@ impl<'hir> LoweringContext<'_, 'hir> { args: &'hir [hir::Expr<'hir>], hir_id: Option, ) -> hir::Expr<'hir> { - let path = - self.arena.alloc(self.expr_lang_item_path(span, lang_item, AttrVec::new(), hir_id)); + let path = self.arena.alloc(self.expr_lang_item_path(span, lang_item, hir_id)); self.expr_call_mut(span, path, args) } @@ -1825,13 +1793,11 @@ impl<'hir> LoweringContext<'_, 'hir> { &mut self, span: Span, lang_item: hir::LangItem, - attrs: AttrVec, hir_id: Option, ) -> hir::Expr<'hir> { self.expr( span, hir::ExprKind::Path(hir::QPath::LangItem(lang_item, self.lower_span(span), hir_id)), - attrs, ) } @@ -1845,20 +1811,10 @@ impl<'hir> LoweringContext<'_, 'hir> { } pub(super) fn expr_ident_mut( - &mut self, - sp: Span, - ident: Ident, - binding: hir::HirId, - ) -> hir::Expr<'hir> { - self.expr_ident_with_attrs(sp, ident, binding, AttrVec::new()) - } - - fn expr_ident_with_attrs( &mut self, span: Span, ident: Ident, binding: hir::HirId, - attrs: AttrVec, ) -> hir::Expr<'hir> { let hir_id = self.next_id(); let res = Res::Local(binding); @@ -1871,7 +1827,7 @@ impl<'hir> LoweringContext<'_, 'hir> { }), )); - self.expr(span, expr_path, attrs) + self.expr(span, expr_path) } fn expr_unsafe(&mut self, expr: &'hir hir::Expr<'hir>) -> hir::Expr<'hir> { @@ -1890,32 +1846,21 @@ impl<'hir> LoweringContext<'_, 'hir> { }), None, ), - AttrVec::new(), ) } fn expr_block_empty(&mut self, span: Span) -> &'hir hir::Expr<'hir> { let blk = self.block_all(span, &[], None); - let expr = self.expr_block(blk, AttrVec::new()); + let expr = self.expr_block(blk); self.arena.alloc(expr) } - pub(super) fn expr_block( - &mut self, - b: &'hir hir::Block<'hir>, - attrs: AttrVec, - ) -> hir::Expr<'hir> { - self.expr(b.span, hir::ExprKind::Block(b, None), attrs) + pub(super) fn expr_block(&mut self, b: &'hir hir::Block<'hir>) -> hir::Expr<'hir> { + self.expr(b.span, hir::ExprKind::Block(b, None)) } - pub(super) fn expr( - &mut self, - span: Span, - kind: hir::ExprKind<'hir>, - attrs: AttrVec, - ) -> hir::Expr<'hir> { + pub(super) fn expr(&mut self, span: Span, kind: hir::ExprKind<'hir>) -> hir::Expr<'hir> { let hir_id = self.next_id(); - self.lower_attrs(hir_id, &attrs); hir::Expr { hir_id, kind, span: self.lower_span(span) } } diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 9eda48e93294..d73d6d3918ea 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -796,7 +796,7 @@ impl<'hir> LoweringContext<'_, 'hir> { /// Construct `ExprKind::Err` for the given `span`. pub(crate) fn expr_err(&mut self, span: Span) -> hir::Expr<'hir> { - self.expr(span, hir::ExprKind::Err, AttrVec::new()) + self.expr(span, hir::ExprKind::Err) } fn lower_impl_item(&mut self, i: &AssocItem) -> &'hir hir::ImplItem<'hir> { @@ -1151,11 +1151,8 @@ impl<'hir> LoweringContext<'_, 'hir> { // Transform into `drop-temps { }`, an expression: let desugared_span = this.mark_span_with_reason(DesugaringKind::Async, user_body.span, None); - let user_body = this.expr_drop_temps( - desugared_span, - this.arena.alloc(user_body), - AttrVec::new(), - ); + let user_body = + this.expr_drop_temps(desugared_span, this.arena.alloc(user_body)); // As noted above, create the final block like // @@ -1172,14 +1169,11 @@ impl<'hir> LoweringContext<'_, 'hir> { Some(user_body), ); - this.expr_block(body, AttrVec::new()) + this.expr_block(body) }, ); - ( - this.arena.alloc_from_iter(parameters), - this.expr(body.span, async_expr, AttrVec::new()), - ) + (this.arena.alloc_from_iter(parameters), this.expr(body.span, async_expr)) }) } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 0258f8fd2d9a..07558ca075d3 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -2291,7 +2291,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { /// has no attributes and is not targeted by a `break`. fn lower_block_expr(&mut self, b: &Block) -> hir::Expr<'hir> { let block = self.lower_block(b, false); - self.expr_block(block, AttrVec::new()) + self.expr_block(block) } fn lower_array_length(&mut self, c: &AnonConst) -> hir::ArrayLen { From 6dc2aa26759578f09974041f19767a75b8c6320e Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 6 Dec 2022 01:52:02 +0000 Subject: [PATCH 080/115] Add GenericParamDef::to_error and InternalSubsts::extend_with_error --- compiler/rustc_middle/src/ty/generics.rs | 14 ++++++++++++++ compiler/rustc_middle/src/ty/sty.rs | 15 ++------------- compiler/rustc_middle/src/ty/subst.rs | 16 ++++++++++++++++ 3 files changed, 32 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index a8da93e4c69b..48329da3e633 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -101,6 +101,20 @@ impl GenericParamDef { _ => None, } } + + pub fn to_error<'tcx>( + &self, + tcx: TyCtxt<'tcx>, + preceding_substs: &[ty::GenericArg<'tcx>], + ) -> ty::GenericArg<'tcx> { + match &self.kind { + ty::GenericParamDefKind::Lifetime => tcx.lifetimes.re_static.into(), + ty::GenericParamDefKind::Type { .. } => tcx.ty_error().into(), + ty::GenericParamDefKind::Const { .. } => { + tcx.const_error(tcx.bound_type_of(self.def_id).subst(tcx, preceding_substs)).into() + } + } + } } #[derive(Default)] diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 8e69824e6c79..1eec119616ea 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -728,19 +728,8 @@ impl<'tcx> PolyExistentialPredicate<'tcx> { } else { // If this is an ill-formed auto trait, then synthesize // new error substs for the missing generics. - let err_substs = ty::InternalSubsts::for_item(tcx, did, |def, substs| { - if def.index == 0 { - self_ty.into() - } else { - match &def.kind { - ty::GenericParamDefKind::Lifetime => tcx.lifetimes.re_static.into(), - ty::GenericParamDefKind::Type { .. } => tcx.ty_error().into(), - ty::GenericParamDefKind::Const { .. } => tcx - .const_error(tcx.bound_type_of(def.def_id).subst(tcx, substs)) - .into(), - } - } - }); + let err_substs = + ty::InternalSubsts::extend_with_error(tcx, did, &[self_ty.into()]); tcx.mk_trait_ref(did, err_substs) }; self.rebind(trait_ref).without_const().to_predicate(tcx) diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs index 141c8354c183..23507d280459 100644 --- a/compiler/rustc_middle/src/ty/subst.rs +++ b/compiler/rustc_middle/src/ty/subst.rs @@ -352,6 +352,22 @@ impl<'tcx> InternalSubsts<'tcx> { } } + // Extend an `original_substs` list to the full number of substs expected by `def_id`, + // filling in the missing parameters with error ty/ct or 'static regions. + pub fn extend_with_error( + tcx: TyCtxt<'tcx>, + def_id: DefId, + original_substs: &[GenericArg<'tcx>], + ) -> SubstsRef<'tcx> { + ty::InternalSubsts::for_item(tcx, def_id, |def, substs| { + if let Some(subst) = original_substs.get(def.index as usize) { + *subst + } else { + def.to_error(tcx, substs) + } + }) + } + #[inline] pub fn types(&'tcx self) -> impl DoubleEndedIterator> + 'tcx { self.iter() From 9c9c47677487af4f9a9810a0171b077789ddd63b Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 6 Dec 2022 03:50:48 +0000 Subject: [PATCH 081/115] Point at args in associated const fn pointers --- compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs | 10 +++------- src/test/ui/suggestions/assoc-const-as-fn.stderr | 6 ++++-- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 3078e0cbeda5..8a875e05b19b 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -1918,15 +1918,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { receiver: Option<&'tcx hir::Expr<'tcx>>, args: &'tcx [hir::Expr<'tcx>], ) -> bool { - // Do not call `fn_sig` on non-functions. - if !matches!( - self.tcx.def_kind(def_id), - DefKind::Fn | DefKind::AssocFn | DefKind::Variant | DefKind::Ctor(..) - ) { + let ty = self.tcx.type_of(def_id); + if !ty.is_fn() { return false; } - - let sig = self.tcx.fn_sig(def_id).skip_binder(); + let sig = ty.fn_sig(self.tcx).skip_binder(); let args_referencing_param: Vec<_> = sig .inputs() .iter() diff --git a/src/test/ui/suggestions/assoc-const-as-fn.stderr b/src/test/ui/suggestions/assoc-const-as-fn.stderr index fa7406878582..3b6e947c59f7 100644 --- a/src/test/ui/suggestions/assoc-const-as-fn.stderr +++ b/src/test/ui/suggestions/assoc-const-as-fn.stderr @@ -1,8 +1,10 @@ error[E0277]: the trait bound `T: GlUniformScalar` is not satisfied - --> $DIR/assoc-const-as-fn.rs:14:5 + --> $DIR/assoc-const-as-fn.rs:14:40 | LL | ::FACTORY(1, value); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `GlUniformScalar` is not implemented for `T` + | ------------------------------- ^^^^^ the trait `GlUniformScalar` is not implemented for `T` + | | + | required by a bound introduced by this call | help: consider further restricting this bound | From eff76455fd4061f268546a706d3dfb1cc34ecb48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 5 Dec 2022 16:13:32 -0800 Subject: [PATCH 082/115] Avoid ICE by accounting for missing type Fix #105330 --- .../src/traits/error_reporting/mod.rs | 2 +- src/test/ui/issues/issue-105330.rs | 21 ++++ src/test/ui/issues/issue-105330.stderr | 109 ++++++++++++++++++ 3 files changed, 131 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/issues/issue-105330.rs create mode 100644 src/test/ui/issues/issue-105330.stderr diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 3379279dd154..fcf0a94462e1 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1607,7 +1607,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { | ObligationCauseCode::ObjectCastObligation(..) | ObligationCauseCode::OpaqueType ); - let expected_ty = data.term.ty().unwrap(); + let expected_ty = data.term.ty().unwrap_or_else(|| self.tcx.ty_error()); // constrain inference variables a bit more to nested obligations from normalize so // we can have more helpful errors. diff --git a/src/test/ui/issues/issue-105330.rs b/src/test/ui/issues/issue-105330.rs new file mode 100644 index 000000000000..86e45f10b0e1 --- /dev/null +++ b/src/test/ui/issues/issue-105330.rs @@ -0,0 +1,21 @@ +pub trait TraitWAssocConst { + const A: usize; +} +pub struct Demo {} + +impl TraitWAssocConst for impl Demo { //~ ERROR E0404 + //~^ ERROR E0562 + pubconst A: str = 32; //~ ERROR expected one of +} + +fn foo>() { //~ ERROR E0658 + foo::()(); //~ ERROR E0271 + //~^ ERROR E0618 + //~| ERROR E0277 +} + +fn main>() { //~ ERROR E0131 + //~^ ERROR E0658 + foo::(); //~ ERROR E0277 + //~^ ERROR E0271 +} diff --git a/src/test/ui/issues/issue-105330.stderr b/src/test/ui/issues/issue-105330.stderr new file mode 100644 index 000000000000..92f2ccb6544b --- /dev/null +++ b/src/test/ui/issues/issue-105330.stderr @@ -0,0 +1,109 @@ +error: expected one of `!` or `::`, found `A` + --> $DIR/issue-105330.rs:8:14 + | +LL | impl TraitWAssocConst for impl Demo { + | - while parsing this item list starting here +LL | +LL | pubconst A: str = 32; + | ^ expected one of `!` or `::` +LL | } + | - the item list ends here + +error[E0404]: expected trait, found struct `Demo` + --> $DIR/issue-105330.rs:6:32 + | +LL | impl TraitWAssocConst for impl Demo { + | ^^^^ not a trait + +error[E0658]: associated const equality is incomplete + --> $DIR/issue-105330.rs:11:28 + | +LL | fn foo>() { + | ^^^^ + | + = note: see issue #92827 for more information + = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable + +error[E0658]: associated const equality is incomplete + --> $DIR/issue-105330.rs:17:29 + | +LL | fn main>() { + | ^^^^ + | + = note: see issue #92827 for more information + = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable + +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type + --> $DIR/issue-105330.rs:6:27 + | +LL | impl TraitWAssocConst for impl Demo { + | ^^^^^^^^^ + +error[E0277]: the trait bound `Demo: TraitWAssocConst` is not satisfied + --> $DIR/issue-105330.rs:12:11 + | +LL | foo::()(); + | ^^^^ the trait `TraitWAssocConst` is not implemented for `Demo` + | +note: required by a bound in `foo` + --> $DIR/issue-105330.rs:11:11 + | +LL | fn foo>() { + | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `foo` + +error[E0271]: type mismatch resolving `::A == 32` + --> $DIR/issue-105330.rs:12:11 + | +LL | foo::()(); + | ^^^^ types differ + | +note: required by a bound in `foo` + --> $DIR/issue-105330.rs:11:28 + | +LL | fn foo>() { + | ^^^^ required by this bound in `foo` + +error[E0618]: expected function, found `()` + --> $DIR/issue-105330.rs:12:5 + | +LL | fn foo>() { + | ----------------------------------- `foo::` defined here returns `()` +LL | foo::()(); + | ^^^^^^^^^^^^^-- + | | + | call expression requires function + +error[E0277]: the trait bound `Demo: TraitWAssocConst` is not satisfied + --> $DIR/issue-105330.rs:19:11 + | +LL | foo::(); + | ^^^^ the trait `TraitWAssocConst` is not implemented for `Demo` + | +note: required by a bound in `foo` + --> $DIR/issue-105330.rs:11:11 + | +LL | fn foo>() { + | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `foo` + +error[E0271]: type mismatch resolving `::A == 32` + --> $DIR/issue-105330.rs:19:11 + | +LL | foo::(); + | ^^^^ types differ + | +note: required by a bound in `foo` + --> $DIR/issue-105330.rs:11:28 + | +LL | fn foo>() { + | ^^^^ required by this bound in `foo` + +error[E0131]: `main` function is not allowed to have generic parameters + --> $DIR/issue-105330.rs:17:8 + | +LL | fn main>() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `main` cannot have generic parameters + +error: aborting due to 11 previous errors + +Some errors have detailed explanations: E0131, E0271, E0277, E0404, E0562, E0618, E0658. +For more information about an error, try `rustc --explain E0131`. From e802165dfe346e92a3ef9b0e49634943df862a67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 28 Nov 2022 00:03:57 -0800 Subject: [PATCH 083/115] On E0195 point at where clause lifetime bounds Fix #104733 --- .../locales/en-US/hir_analysis.ftl | 2 + .../src/check/compare_method.rs | 51 +++++++++++++++---- compiler/rustc_hir_analysis/src/errors.rs | 4 ++ ...ssing-where-clause-lifetimes-from-trait.rs | 30 +++++++++++ ...g-where-clause-lifetimes-from-trait.stderr | 27 ++++++++++ 5 files changed, 103 insertions(+), 11 deletions(-) create mode 100644 src/test/ui/trait-bounds/impl-missing-where-clause-lifetimes-from-trait.rs create mode 100644 src/test/ui/trait-bounds/impl-missing-where-clause-lifetimes-from-trait.stderr diff --git a/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl b/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl index 0894bbcaad47..a5cb8a88819d 100644 --- a/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl +++ b/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl @@ -17,6 +17,8 @@ hir_analysis_lifetimes_or_bounds_mismatch_on_trait = lifetime parameters or bounds on {$item_kind} `{$ident}` do not match the trait declaration .label = lifetimes do not match {$item_kind} in trait .generics_label = lifetimes in impl do not match this {$item_kind} in trait + .where_label = this `where` clause might not match the one in the trait + .bounds_label = this bound might be missing in the impl hir_analysis_drop_impl_on_wrong_item = the `Drop` trait may only be implemented for local structs, enums, and unions diff --git a/compiler/rustc_hir_analysis/src/check/compare_method.rs b/compiler/rustc_hir_analysis/src/check/compare_method.rs index 82a77416a190..1d6f9b291765 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_method.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_method.rs @@ -751,17 +751,45 @@ fn check_region_bounds_on_impl_item<'tcx>( .get_generics(impl_m.def_id.expect_local()) .expect("expected impl item to have generics or else we can't compare them") .span; - let generics_span = if let Some(local_def_id) = trait_m.def_id.as_local() { - Some( - tcx.hir() - .get_generics(local_def_id) - .expect("expected trait item to have generics or else we can't compare them") - .span, - ) - } else { - None - }; + let mut generics_span = None; + let mut bounds_span = vec![]; + let mut where_span = None; + if let Some(trait_node) = tcx.hir().get_if_local(trait_m.def_id) + && let Some(trait_generics) = trait_node.generics() + { + generics_span = Some(trait_generics.span); + // FIXME: we could potentially look at the impl's bounds to not point at bounds that + // *are* present in the impl. + for p in trait_generics.predicates { + if let hir::WherePredicate::BoundPredicate(pred) = p { + for b in pred.bounds { + if let hir::GenericBound::Outlives(lt) = b { + bounds_span.push(lt.ident.span); + } + } + } + } + if let Some(impl_node) = tcx.hir().get_if_local(impl_m.def_id) + && let Some(impl_generics) = impl_node.generics() + { + let mut impl_bounds = 0; + for p in impl_generics.predicates { + if let hir::WherePredicate::BoundPredicate(pred) = p { + for b in pred.bounds { + if let hir::GenericBound::Outlives(_) = b { + impl_bounds += 1; + } + } + } + } + if impl_bounds == bounds_span.len() { + bounds_span = vec![]; + } else if impl_generics.has_where_clause_predicates { + where_span = Some(impl_generics.where_clause_span); + } + } + } let reported = tcx .sess .create_err(LifetimesOrBoundsMismatchOnTrait { @@ -769,9 +797,10 @@ fn check_region_bounds_on_impl_item<'tcx>( item_kind: assoc_item_kind_str(impl_m), ident: impl_m.ident(tcx), generics_span, + bounds_span, + where_span, }) .emit_unless(delay); - return Err(reported); } diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index afbb27155a2f..5156d432b5b3 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -43,6 +43,10 @@ pub struct LifetimesOrBoundsMismatchOnTrait { pub span: Span, #[label(generics_label)] pub generics_span: Option, + #[label(where_label)] + pub where_span: Option, + #[label(bounds_label)] + pub bounds_span: Vec, pub item_kind: &'static str, pub ident: Ident, } diff --git a/src/test/ui/trait-bounds/impl-missing-where-clause-lifetimes-from-trait.rs b/src/test/ui/trait-bounds/impl-missing-where-clause-lifetimes-from-trait.rs new file mode 100644 index 000000000000..1994120ce146 --- /dev/null +++ b/src/test/ui/trait-bounds/impl-missing-where-clause-lifetimes-from-trait.rs @@ -0,0 +1,30 @@ +trait Trait { + fn foo<'a, K>(self, _: T, _: K) where T: 'a, K: 'a; +} + +impl Trait<()> for () { + fn foo<'a, K>(self, _: (), _: K) where { //~ ERROR E0195 + todo!(); + } +} + +struct State; + +trait Foo { + fn foo<'a>(&self, state: &'a State) -> &'a T + where + T: 'a; +} + +impl Foo for F +where + F: Fn(&State) -> &T, +{ + fn foo<'a>(&self, state: &'a State) -> &'a T { //~ ERROR E0195 + self(state) + } +} + +fn main() { + ().foo((), ()); +} diff --git a/src/test/ui/trait-bounds/impl-missing-where-clause-lifetimes-from-trait.stderr b/src/test/ui/trait-bounds/impl-missing-where-clause-lifetimes-from-trait.stderr new file mode 100644 index 000000000000..3a02369e2ee8 --- /dev/null +++ b/src/test/ui/trait-bounds/impl-missing-where-clause-lifetimes-from-trait.stderr @@ -0,0 +1,27 @@ +error[E0195]: lifetime parameters or bounds on method `foo` do not match the trait declaration + --> $DIR/impl-missing-where-clause-lifetimes-from-trait.rs:6:11 + | +LL | fn foo<'a, K>(self, _: T, _: K) where T: 'a, K: 'a; + | ------- -- -- this bound might be missing in the impl + | | | + | | this bound might be missing in the impl + | lifetimes in impl do not match this method in trait +... +LL | fn foo<'a, K>(self, _: (), _: K) where { + | ^^^^^^^ lifetimes do not match method in trait + +error[E0195]: lifetime parameters or bounds on method `foo` do not match the trait declaration + --> $DIR/impl-missing-where-clause-lifetimes-from-trait.rs:23:11 + | +LL | fn foo<'a>(&self, state: &'a State) -> &'a T + | ---- lifetimes in impl do not match this method in trait +LL | where +LL | T: 'a; + | -- this bound might be missing in the impl +... +LL | fn foo<'a>(&self, state: &'a State) -> &'a T { + | ^^^^ lifetimes do not match method in trait + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0195`. From 9ffd0868653ad5113962c6f2a42d5061afbcf493 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 28 Nov 2022 14:04:46 -0800 Subject: [PATCH 084/115] review comment: add test case --- .../impl-missing-where-clause-lifetimes-from-trait.rs | 8 ++++++++ ...l-missing-where-clause-lifetimes-from-trait.stderr | 11 ++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/test/ui/trait-bounds/impl-missing-where-clause-lifetimes-from-trait.rs b/src/test/ui/trait-bounds/impl-missing-where-clause-lifetimes-from-trait.rs index 1994120ce146..dcdbd0228737 100644 --- a/src/test/ui/trait-bounds/impl-missing-where-clause-lifetimes-from-trait.rs +++ b/src/test/ui/trait-bounds/impl-missing-where-clause-lifetimes-from-trait.rs @@ -25,6 +25,14 @@ where } } +trait Bar { + fn foo<'a>(&'a self) {} +} + +impl Bar for () { + fn foo<'a: 'a>(&'a self) {} //~ ERROR E0195 +} + fn main() { ().foo((), ()); } diff --git a/src/test/ui/trait-bounds/impl-missing-where-clause-lifetimes-from-trait.stderr b/src/test/ui/trait-bounds/impl-missing-where-clause-lifetimes-from-trait.stderr index 3a02369e2ee8..e26cb22163f1 100644 --- a/src/test/ui/trait-bounds/impl-missing-where-clause-lifetimes-from-trait.stderr +++ b/src/test/ui/trait-bounds/impl-missing-where-clause-lifetimes-from-trait.stderr @@ -22,6 +22,15 @@ LL | T: 'a; LL | fn foo<'a>(&self, state: &'a State) -> &'a T { | ^^^^ lifetimes do not match method in trait -error: aborting due to 2 previous errors +error[E0195]: lifetime parameters or bounds on method `foo` do not match the trait declaration + --> $DIR/impl-missing-where-clause-lifetimes-from-trait.rs:33:11 + | +LL | fn foo<'a>(&'a self) {} + | ---- lifetimes in impl do not match this method in trait +... +LL | fn foo<'a: 'a>(&'a self) {} + | ^^^^^^^^ lifetimes do not match method in trait + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0195`. From d15ca0974ed716ae6c701add8757183d7550d766 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Tue, 6 Dec 2022 17:49:24 +0900 Subject: [PATCH 085/115] add a test for #104260 --- .../ui/associated-inherent-types/issue-104260.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 src/test/ui/associated-inherent-types/issue-104260.rs diff --git a/src/test/ui/associated-inherent-types/issue-104260.rs b/src/test/ui/associated-inherent-types/issue-104260.rs new file mode 100644 index 000000000000..a73cd1775b46 --- /dev/null +++ b/src/test/ui/associated-inherent-types/issue-104260.rs @@ -0,0 +1,14 @@ +// check-pass + +#![feature(inherent_associated_types)] +#![allow(incomplete_features)] + +struct Foo; + +impl Foo { + type Bar = u8; +} + +fn main() { + let a: Foo::Bar<()>; +} From cf031a3355f677ed1a44e31cbc2b2d84f3cb13b6 Mon Sep 17 00:00:00 2001 From: Arpad Borsos Date: Sun, 4 Dec 2022 12:32:15 +0100 Subject: [PATCH 086/115] Replace usage of `ResumeTy` in async lowering with `Context` Replaces using `ResumeTy` / `get_context` in favor of using `&'static mut Context<'_>`. Usage of the `'static` lifetime here is technically "cheating", and replaces the raw pointer in `ResumeTy` and the `get_context` fn that pulls the correct lifetimes out of thin air. --- compiler/rustc_ast_lowering/src/expr.rs | 57 ++++++++++++------- compiler/rustc_hir/src/lang_items.rs | 3 +- compiler/rustc_span/src/symbol.rs | 3 +- library/core/src/future/mod.rs | 10 +++- library/core/src/task/wake.rs | 1 + .../async-await-let-else.drop-tracking.stderr | 2 +- .../issue-68112.drop_tracking.stderr | 2 +- .../issue-68112.no_drop_tracking.stderr | 2 +- .../issue-69446-fnmut-capture.stderr | 3 + ...e-70935-complex-spans.drop_tracking.stderr | 2 +- ...l-drop-partial-reinit.drop_tracking.stderr | 2 +- ...rop-partial-reinit.no_drop_tracking.stderr | 2 +- .../closure-in-projection-issue-97405.rs | 4 +- .../closure-in-projection-issue-97405.stderr | 20 ++++--- 14 files changed, 70 insertions(+), 43 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 695ccec0b1cb..9974ebff311f 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -16,7 +16,7 @@ use rustc_hir::def::Res; use rustc_hir::definitions::DefPathData; use rustc_session::errors::report_lit_error; use rustc_span::source_map::{respan, DesugaringKind, Span, Spanned}; -use rustc_span::symbol::{sym, Ident}; +use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::DUMMY_SP; use thin_vec::thin_vec; @@ -594,14 +594,38 @@ impl<'hir> LoweringContext<'_, 'hir> { ) -> hir::ExprKind<'hir> { let output = ret_ty.unwrap_or_else(|| hir::FnRetTy::DefaultReturn(self.lower_span(span))); - // Resume argument type: `ResumeTy` - let unstable_span = - self.mark_span_with_reason(DesugaringKind::Async, span, self.allow_gen_future.clone()); - let resume_ty = hir::QPath::LangItem(hir::LangItem::ResumeTy, unstable_span, None); + // Resume argument type, which should be `&mut Context<'_>`. + // NOTE: Using the `'static` lifetime here is technically cheating. + // The `Future::poll` argument really is `&'a mut Context<'b>`, but we cannot + // express the fact that we are not storing it across yield-points yet, + // and we would thus run into lifetime errors. + // See . + // Our lowering makes sure we are not mis-using the `_task_context` input type + // in the sense that we are indeed not using it across yield points. We + // get a fresh `&mut Context` for each resume / call of `Future::poll`. + // This "cheating" was previously done with a `ResumeTy` that contained a raw + // pointer, and a `get_context` accessor that pulled the `Context` lifetimes + // out of thin air. + let context_lifetime_ident = Ident::with_dummy_span(kw::StaticLifetime); + let context_lifetime = self.arena.alloc(hir::Lifetime { + hir_id: self.next_id(), + ident: context_lifetime_ident, + res: hir::LifetimeName::Static, + }); + let context_path = + hir::QPath::LangItem(hir::LangItem::Context, self.lower_span(span), None); + let context_ty = hir::MutTy { + ty: self.arena.alloc(hir::Ty { + hir_id: self.next_id(), + kind: hir::TyKind::Path(context_path), + span: self.lower_span(span), + }), + mutbl: hir::Mutability::Mut, + }; let input_ty = hir::Ty { hir_id: self.next_id(), - kind: hir::TyKind::Path(resume_ty), - span: unstable_span, + kind: hir::TyKind::Rptr(context_lifetime, context_ty), + span: self.lower_span(span), }; // The closure/generator `FnDecl` takes a single (resume) argument of type `input_ty`. @@ -659,12 +683,9 @@ impl<'hir> LoweringContext<'_, 'hir> { .map_or(false, |attrs| attrs.into_iter().any(|attr| attr.has_name(sym::track_caller))); let hir_id = self.lower_node_id(closure_node_id); + let unstable_span = + self.mark_span_with_reason(DesugaringKind::Async, span, self.allow_gen_future.clone()); if track_caller { - let unstable_span = self.mark_span_with_reason( - DesugaringKind::Async, - span, - self.allow_gen_future.clone(), - ); self.lower_attrs( hir_id, &[Attribute { @@ -711,7 +732,7 @@ impl<'hir> LoweringContext<'_, 'hir> { /// mut __awaitee => loop { /// match unsafe { ::std::future::Future::poll( /// <::std::pin::Pin>::new_unchecked(&mut __awaitee), - /// ::std::future::get_context(task_context), + /// task_context, /// ) } { /// ::std::task::Poll::Ready(result) => break result, /// ::std::task::Poll::Pending => {} @@ -752,7 +773,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // unsafe { // ::std::future::Future::poll( // ::std::pin::Pin::new_unchecked(&mut __awaitee), - // ::std::future::get_context(task_context), + // task_context, // ) // } let poll_expr = { @@ -770,16 +791,10 @@ impl<'hir> LoweringContext<'_, 'hir> { arena_vec![self; ref_mut_awaitee], Some(expr_hir_id), ); - let get_context = self.expr_call_lang_item_fn_mut( - gen_future_span, - hir::LangItem::GetContext, - arena_vec![self; task_context], - Some(expr_hir_id), - ); let call = self.expr_call_lang_item_fn( span, hir::LangItem::FuturePoll, - arena_vec![self; new_unchecked, get_context], + arena_vec![self; new_unchecked, task_context], Some(expr_hir_id), ); self.arena.alloc(self.expr_unsafe(call)) diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index 038509031b18..b51257df713e 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -286,10 +286,9 @@ language_item_table! { // FIXME(swatinem): the following lang items are used for async lowering and // should become obsolete eventually. - ResumeTy, sym::ResumeTy, resume_ty, Target::Struct, GenericRequirement::None; IdentityFuture, sym::identity_future, identity_future_fn, Target::Fn, GenericRequirement::None; - GetContext, sym::get_context, get_context_fn, Target::Fn, GenericRequirement::None; + Context, sym::Context, context, Target::Struct, GenericRequirement::None; FuturePoll, sym::poll, future_poll_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None; FromFrom, sym::from, from_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None; diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 9e446c96db31..612538454972 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -165,6 +165,7 @@ symbols! { Capture, Center, Clone, + Context, Continue, Copy, Count, @@ -264,7 +265,6 @@ symbols! { Relaxed, Release, Result, - ResumeTy, Return, Right, Rust, @@ -754,7 +754,6 @@ symbols! { generic_associated_types_extended, generic_const_exprs, generic_param_attrs, - get_context, global_allocator, global_asm, globs, diff --git a/library/core/src/future/mod.rs b/library/core/src/future/mod.rs index f2b961d62e00..2a8e12fd4cf6 100644 --- a/library/core/src/future/mod.rs +++ b/library/core/src/future/mod.rs @@ -44,7 +44,7 @@ pub use poll_fn::{poll_fn, PollFn}; /// non-Send/Sync as well, and we don't want that. /// /// It also simplifies the HIR lowering of `.await`. -#[cfg_attr(not(bootstrap), lang = "ResumeTy")] +// FIXME(swatinem): This type can be removed when bumping the bootstrap compiler #[doc(hidden)] #[unstable(feature = "gen_future", issue = "50547")] #[derive(Debug, Copy, Clone)] @@ -61,6 +61,7 @@ unsafe impl Sync for ResumeTy {} /// This function returns a `GenFuture` underneath, but hides it in `impl Trait` to give /// better error messages (`impl Future` rather than `GenFuture<[closure.....]>`). // This is `const` to avoid extra errors after we recover from `const async fn` +// FIXME(swatinem): This fn can be removed when bumping the bootstrap compiler #[cfg_attr(bootstrap, lang = "from_generator")] #[doc(hidden)] #[unstable(feature = "gen_future", issue = "50547")] @@ -102,7 +103,8 @@ where GenFuture(gen) } -#[lang = "get_context"] +// FIXME(swatinem): This fn can be removed when bumping the bootstrap compiler +#[cfg_attr(bootstrap, lang = "get_context")] #[doc(hidden)] #[unstable(feature = "gen_future", issue = "50547")] #[must_use] @@ -113,6 +115,10 @@ pub unsafe fn get_context<'a, 'b>(cx: ResumeTy) -> &'a mut Context<'b> { unsafe { &mut *cx.0.as_ptr().cast() } } +// FIXME(swatinem): This fn is currently needed to work around shortcomings +// in type and lifetime inference. +// See the comment at the bottom of `LoweringContext::make_async_expr` and +// . #[cfg_attr(not(bootstrap), lang = "identity_future")] #[doc(hidden)] #[unstable(feature = "gen_future", issue = "50547")] diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index 0cff972df3a5..9ab9b0ba1c79 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -174,6 +174,7 @@ impl RawWakerVTable { /// Currently, `Context` only serves to provide access to a [`&Waker`](Waker) /// which can be used to wake the current task. #[stable(feature = "futures_api", since = "1.36.0")] +#[cfg_attr(not(bootstrap), lang = "Context")] pub struct Context<'a> { waker: &'a Waker, // Ensure we future-proof against variance changes by forcing diff --git a/src/test/ui/async-await/async-await-let-else.drop-tracking.stderr b/src/test/ui/async-await/async-await-let-else.drop-tracking.stderr index 3be7f370da3f..616623ee0775 100644 --- a/src/test/ui/async-await/async-await-let-else.drop-tracking.stderr +++ b/src/test/ui/async-await/async-await-let-else.drop-tracking.stderr @@ -40,7 +40,7 @@ LL | async fn bar2(_: T) -> ! { LL | | panic!() LL | | } | |_^ - = note: required because it captures the following types: `ResumeTy`, `Option`, `impl Future`, `()` + = note: required because it captures the following types: `&mut Context<'_>`, `Option`, `impl Future`, `()` note: required because it's used within this `async fn` body --> $DIR/async-await-let-else.rs:21:32 | diff --git a/src/test/ui/async-await/issue-68112.drop_tracking.stderr b/src/test/ui/async-await/issue-68112.drop_tracking.stderr index f2802698fd5b..1c90bedae790 100644 --- a/src/test/ui/async-await/issue-68112.drop_tracking.stderr +++ b/src/test/ui/async-await/issue-68112.drop_tracking.stderr @@ -57,7 +57,7 @@ note: required because it appears within the type `impl Future impl Future>> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: required because it captures the following types: `ResumeTy`, `impl Future>>`, `()`, `Ready` + = note: required because it captures the following types: `&mut Context<'_>`, `impl Future>>`, `()`, `Ready` note: required because it's used within this `async` block --> $DIR/issue-68112.rs:60:20 | diff --git a/src/test/ui/async-await/issue-68112.no_drop_tracking.stderr b/src/test/ui/async-await/issue-68112.no_drop_tracking.stderr index 38eb85b302fd..e09ae7fedd80 100644 --- a/src/test/ui/async-await/issue-68112.no_drop_tracking.stderr +++ b/src/test/ui/async-await/issue-68112.no_drop_tracking.stderr @@ -57,7 +57,7 @@ note: required because it appears within the type `impl Future impl Future>> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: required because it captures the following types: `ResumeTy`, `impl Future>>`, `()`, `i32`, `Ready` + = note: required because it captures the following types: `&mut Context<'_>`, `impl Future>>`, `()`, `i32`, `Ready` note: required because it's used within this `async` block --> $DIR/issue-68112.rs:60:20 | diff --git a/src/test/ui/async-await/issue-69446-fnmut-capture.stderr b/src/test/ui/async-await/issue-69446-fnmut-capture.stderr index 3d2b0402bc52..e6ad2f0d444b 100644 --- a/src/test/ui/async-await/issue-69446-fnmut-capture.stderr +++ b/src/test/ui/async-await/issue-69446-fnmut-capture.stderr @@ -14,6 +14,9 @@ LL | | }); | = note: `FnMut` closures only have access to their captured variables while they are executing... = note: ...therefore, they cannot allow references to captured variables to escape + = note: requirement occurs because of a mutable reference to `Context<'_>` + = note: mutable references are invariant over their type parameter + = help: see for more information about variance error: aborting due to previous error diff --git a/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr b/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr index 721234aa4a78..a8fd97cde8f7 100644 --- a/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr +++ b/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr @@ -18,7 +18,7 @@ LL | async fn baz(_c: impl FnMut() -> T) where T: Future { | ___________________________________________________________________^ LL | | } | |_^ - = note: required because it captures the following types: `ResumeTy`, `impl Future`, `()` + = note: required because it captures the following types: `&mut Context<'_>`, `impl Future`, `()` note: required because it's used within this `async` block --> $DIR/issue-70935-complex-spans.rs:16:5 | diff --git a/src/test/ui/async-await/partial-drop-partial-reinit.drop_tracking.stderr b/src/test/ui/async-await/partial-drop-partial-reinit.drop_tracking.stderr index 17b4ef7bdc67..25876d508401 100644 --- a/src/test/ui/async-await/partial-drop-partial-reinit.drop_tracking.stderr +++ b/src/test/ui/async-await/partial-drop-partial-reinit.drop_tracking.stderr @@ -11,7 +11,7 @@ LL | async fn foo() { | = help: within `impl Future`, the trait `Send` is not implemented for `NotSend` = note: required because it appears within the type `(NotSend,)` - = note: required because it captures the following types: `ResumeTy`, `(NotSend,)`, `()`, `impl Future` + = note: required because it captures the following types: `&mut Context<'_>`, `(NotSend,)`, `()`, `impl Future` note: required because it's used within this `async fn` body --> $DIR/partial-drop-partial-reinit.rs:31:16 | diff --git a/src/test/ui/async-await/partial-drop-partial-reinit.no_drop_tracking.stderr b/src/test/ui/async-await/partial-drop-partial-reinit.no_drop_tracking.stderr index 34d8a159f106..dba2a620779f 100644 --- a/src/test/ui/async-await/partial-drop-partial-reinit.no_drop_tracking.stderr +++ b/src/test/ui/async-await/partial-drop-partial-reinit.no_drop_tracking.stderr @@ -11,7 +11,7 @@ LL | async fn foo() { | = help: within `impl Future`, the trait `Send` is not implemented for `NotSend` = note: required because it appears within the type `(NotSend,)` - = note: required because it captures the following types: `ResumeTy`, `(NotSend,)`, `impl Future`, `()` + = note: required because it captures the following types: `&mut Context<'_>`, `(NotSend,)`, `impl Future`, `()` note: required because it's used within this `async fn` body --> $DIR/partial-drop-partial-reinit.rs:31:16 | diff --git a/src/test/ui/regions/closure-in-projection-issue-97405.rs b/src/test/ui/regions/closure-in-projection-issue-97405.rs index e567d5c2723f..88b1c1396516 100644 --- a/src/test/ui/regions/closure-in-projection-issue-97405.rs +++ b/src/test/ui/regions/closure-in-projection-issue-97405.rs @@ -22,11 +22,11 @@ fn good_generic_fn() { // This should fail because `T` ends up in the upvars of the closure. fn bad_generic_fn(t: T) { assert_static(opaque(async move { t; }).next()); - //~^ ERROR the associated type `::Item` may not live long enough + //~^ ERROR the parameter type `T` may not live long enough assert_static(opaque(move || { t; }).next()); //~^ ERROR the associated type `::Item` may not live long enough assert_static(opaque(opaque(async move { t; }).next()).next()); - //~^ ERROR the associated type `::Item` may not live long enough + //~^ ERROR the parameter type `T` may not live long enough } fn main() {} diff --git a/src/test/ui/regions/closure-in-projection-issue-97405.stderr b/src/test/ui/regions/closure-in-projection-issue-97405.stderr index c08f1059ebf5..907964aaf379 100644 --- a/src/test/ui/regions/closure-in-projection-issue-97405.stderr +++ b/src/test/ui/regions/closure-in-projection-issue-97405.stderr @@ -1,11 +1,13 @@ -error[E0310]: the associated type `::Item` may not live long enough +error[E0310]: the parameter type `T` may not live long enough --> $DIR/closure-in-projection-issue-97405.rs:24:5 | LL | assert_static(opaque(async move { t; }).next()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | - = help: consider adding an explicit lifetime bound `::Item: 'static`... - = note: ...so that the type `::Item` will meet its required lifetime bounds +help: consider adding an explicit lifetime bound... + | +LL | fn bad_generic_fn(t: T) { + | +++++++++ error[E0310]: the associated type `::Item` may not live long enough --> $DIR/closure-in-projection-issue-97405.rs:26:5 @@ -16,14 +18,16 @@ LL | assert_static(opaque(move || { t; }).next()); = help: consider adding an explicit lifetime bound `::Item: 'static`... = note: ...so that the type `::Item` will meet its required lifetime bounds -error[E0310]: the associated type `::Item` may not live long enough +error[E0310]: the parameter type `T` may not live long enough --> $DIR/closure-in-projection-issue-97405.rs:28:5 | LL | assert_static(opaque(opaque(async move { t; }).next()).next()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | - = help: consider adding an explicit lifetime bound `::Item: 'static`... - = note: ...so that the type `::Item` will meet its required lifetime bounds +help: consider adding an explicit lifetime bound... + | +LL | fn bad_generic_fn(t: T) { + | +++++++++ error: aborting due to 3 previous errors From 9397ea136851ebe5d03ba64a50f6ea3171dc210f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 5 Dec 2022 15:17:11 +0100 Subject: [PATCH 087/115] make retagging work even with 'unstable' places --- .../rustc_const_eval/src/interpret/machine.rs | 16 ++++- .../rustc_const_eval/src/interpret/step.rs | 39 +++++++++-- compiler/rustc_middle/src/mir/syntax.rs | 2 +- compiler/rustc_mir_transform/src/add_retag.rs | 53 ++++---------- compiler/rustc_mir_transform/src/generator.rs | 10 --- compiler/rustc_mir_transform/src/shim.rs | 10 --- .../inline/inline_retag.bar.Inline.after.mir | 4 -- ...asts.SimplifyCfg-elaborate-drops.after.mir | 10 --- ...place.Test.SimplifyCfg-make_shim.after.mir | 1 - ...e#0}.SimplifyCfg-elaborate-drops.after.mir | 1 - ...main.SimplifyCfg-elaborate-drops.after.mir | 11 --- ...-foo.SimplifyCfg-elaborate-drops.after.mir | 2 - src/tools/miri/src/borrow_tracker/mod.rs | 13 +++- .../src/borrow_tracker/stacked_borrows/mod.rs | 69 ++++++++++++------- src/tools/miri/src/machine.rs | 22 ++++-- 15 files changed, 135 insertions(+), 128 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index 88d25be6bd86..0604d5ee6fa4 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -373,9 +373,21 @@ pub trait Machine<'mir, 'tcx>: Sized { Ok(()) } - /// Executes a retagging operation. + /// Executes a retagging operation for a single pointer. + /// Returns the possibly adjusted pointer. #[inline] - fn retag( + fn retag_ptr_value( + _ecx: &mut InterpCx<'mir, 'tcx, Self>, + _kind: mir::RetagKind, + val: &ImmTy<'tcx, Self::Provenance>, + ) -> InterpResult<'tcx, ImmTy<'tcx, Self::Provenance>> { + Ok(val.clone()) + } + + /// Executes a retagging operation on a compound value. + /// Replaces all pointers stored in the given place. + #[inline] + fn retag_place_contents( _ecx: &mut InterpCx<'mir, 'tcx, Self>, _kind: mir::RetagKind, _place: &PlaceTy<'tcx, Self::Provenance>, diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index 60578246eedc..81b44a49484d 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -8,7 +8,7 @@ use rustc_middle::mir; use rustc_middle::mir::interpret::{InterpResult, Scalar}; use rustc_middle::ty::layout::LayoutOf; -use super::{InterpCx, Machine}; +use super::{ImmTy, InterpCx, Machine}; /// Classify whether an operator is "left-homogeneous", i.e., the LHS has the /// same type as the result. @@ -108,7 +108,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Stacked Borrows. Retag(kind, place) => { let dest = self.eval_place(**place)?; - M::retag(self, *kind, &dest)?; + M::retag_place_contents(self, *kind, &dest)?; } Intrinsic(box ref intrinsic) => self.emulate_nondiverging_intrinsic(intrinsic)?, @@ -247,10 +247,41 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.write_scalar(Scalar::from_machine_usize(len, self), &dest)?; } - AddressOf(_, place) | Ref(_, _, place) => { + Ref(_, borrow_kind, place) => { let src = self.eval_place(place)?; let place = self.force_allocation(&src)?; - self.write_immediate(place.to_ref(self), &dest)?; + let val = ImmTy::from_immediate(place.to_ref(self), dest.layout); + // A fresh reference was created, make sure it gets retagged. + let val = M::retag_ptr_value( + self, + if borrow_kind.allows_two_phase_borrow() { + mir::RetagKind::TwoPhase + } else { + mir::RetagKind::Default + }, + &val, + )?; + self.write_immediate(*val, &dest)?; + } + + AddressOf(_, place) => { + // Figure out whether this is an addr_of of an already raw place. + let place_base_raw = if place.has_deref() { + let ty = self.frame().body.local_decls[place.local].ty; + ty.is_unsafe_ptr() + } else { + // Not a deref, and thus not raw. + false + }; + + let src = self.eval_place(place)?; + let place = self.force_allocation(&src)?; + let mut val = ImmTy::from_immediate(place.to_ref(self), dest.layout); + if !place_base_raw { + // If this was not already raw, it needs retagging. + val = M::retag_ptr_value(self, mir::RetagKind::Raw, &val)?; + } + self.write_immediate(*val, &dest)?; } NullaryOp(null_op, ty) => { diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 7d2a6bda5692..614e0d012b35 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -400,7 +400,7 @@ impl std::fmt::Display for NonDivergingIntrinsic<'_> { #[derive(Copy, Clone, TyEncodable, TyDecodable, Debug, PartialEq, Eq, Hash, HashStable)] #[rustc_pass_by_value] pub enum RetagKind { - /// The initial retag when entering a function. + /// The initial retag of arguments when entering a function. FnEntry, /// Retag preparing for a two-phase borrow. TwoPhase, diff --git a/compiler/rustc_mir_transform/src/add_retag.rs b/compiler/rustc_mir_transform/src/add_retag.rs index 036b5589849a..3d22035f0785 100644 --- a/compiler/rustc_mir_transform/src/add_retag.rs +++ b/compiler/rustc_mir_transform/src/add_retag.rs @@ -10,16 +10,6 @@ use rustc_middle::ty::{self, Ty, TyCtxt}; pub struct AddRetag; -/// Determines whether this place is "stable": Whether, if we evaluate it again -/// after the assignment, we can be sure to obtain the same place value. -/// (Concurrent accesses by other threads are no problem as these are anyway non-atomic -/// copies. Data races are UB.) -fn is_stable(place: PlaceRef<'_>) -> bool { - // Which place this evaluates to can change with any memory write, - // so cannot assume deref to be stable. - !place.has_deref() -} - /// Determine whether this type may contain a reference (or box), and thus needs retagging. /// We will only recurse `depth` times into Tuples/ADTs to bound the cost of this. fn may_contain_reference<'tcx>(ty: Ty<'tcx>, depth: u32, tcx: TyCtxt<'tcx>) -> bool { @@ -69,22 +59,10 @@ impl<'tcx> MirPass<'tcx> for AddRetag { let basic_blocks = body.basic_blocks.as_mut(); let local_decls = &body.local_decls; let needs_retag = |place: &Place<'tcx>| { - // FIXME: Instead of giving up for unstable places, we should introduce - // a temporary and retag on that. - is_stable(place.as_ref()) + !place.has_deref() // we're not eally interested in stores to "outside" locations, they are hard to keep track of anyway && may_contain_reference(place.ty(&*local_decls, tcx).ty, /*depth*/ 3, tcx) && !local_decls[place.local].is_deref_temp() }; - let place_base_raw = |place: &Place<'tcx>| { - // If this is a `Deref`, get the type of what we are deref'ing. - if place.has_deref() { - let ty = &local_decls[place.local].ty; - ty.is_unsafe_ptr() - } else { - // Not a deref, and thus not raw. - false - } - }; // PART 1 // Retag arguments at the beginning of the start block. @@ -108,7 +86,7 @@ impl<'tcx> MirPass<'tcx> for AddRetag { } // PART 2 - // Retag return values of functions. Also escape-to-raw the argument of `drop`. + // Retag return values of functions. // We collect the return destinations because we cannot mutate while iterating. let returns = basic_blocks .iter_mut() @@ -140,30 +118,25 @@ impl<'tcx> MirPass<'tcx> for AddRetag { } // PART 3 - // Add retag after assignment. + // Add retag after assignments where data "enters" this function: the RHS is behind a deref and the LHS is not. for block_data in basic_blocks { // We want to insert statements as we iterate. To this end, we // iterate backwards using indices. for i in (0..block_data.statements.len()).rev() { let (retag_kind, place) = match block_data.statements[i].kind { - // Retag-as-raw after escaping to a raw pointer, if the referent - // is not already a raw pointer. - StatementKind::Assign(box (lplace, Rvalue::AddressOf(_, ref rplace))) - if !place_base_raw(rplace) => - { - (RetagKind::Raw, lplace) - } // Retag after assignments of reference type. StatementKind::Assign(box (ref place, ref rvalue)) if needs_retag(place) => { - let kind = match rvalue { - Rvalue::Ref(_, borrow_kind, _) - if borrow_kind.allows_two_phase_borrow() => - { - RetagKind::TwoPhase - } - _ => RetagKind::Default, + let add_retag = match rvalue { + // Ptr-creating operations already do their own internal retagging, no + // need to also add a retag statement. + Rvalue::Ref(..) | Rvalue::AddressOf(..) => false, + _ => true, }; - (kind, *place) + if add_retag { + (RetagKind::Default, *place) + } else { + continue; + } } // Do nothing for the rest _ => continue, diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs index 8922298ecafc..69f96fe48ea2 100644 --- a/compiler/rustc_mir_transform/src/generator.rs +++ b/compiler/rustc_mir_transform/src/generator.rs @@ -985,16 +985,6 @@ fn create_generator_drop_shim<'tcx>( tcx.mk_ptr(ty::TypeAndMut { ty: gen_ty, mutbl: hir::Mutability::Mut }), source_info, ); - if tcx.sess.opts.unstable_opts.mir_emit_retag { - // Alias tracking must know we changed the type - body.basic_blocks_mut()[START_BLOCK].statements.insert( - 0, - Statement { - source_info, - kind: StatementKind::Retag(RetagKind::Raw, Box::new(Place::from(SELF_ARG))), - }, - ) - } // Make sure we remove dead blocks to remove // unrelated code from the resume part of the function diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index a115bb2831a4..16b7dcad17e7 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -177,16 +177,6 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option>) if ty.is_some() { // The first argument (index 0), but add 1 for the return value. let dropee_ptr = Place::from(Local::new(1 + 0)); - if tcx.sess.opts.unstable_opts.mir_emit_retag { - // Function arguments should be retagged, and we make this one raw. - body.basic_blocks_mut()[START_BLOCK].statements.insert( - 0, - Statement { - source_info, - kind: StatementKind::Retag(RetagKind::Raw, Box::new(dropee_ptr)), - }, - ); - } let patch = { let param_env = tcx.param_env_reveal_all_normalized(def_id); let mut elaborator = diff --git a/src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir b/src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir index 75af20d482dd..60149ff36064 100644 --- a/src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir +++ b/src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir @@ -38,9 +38,7 @@ fn bar() -> bool { // + literal: Const { ty: &i32, val: Unevaluated(bar, [], Some(promoted[1])) } Retag(_10); // scope 1 at $DIR/inline_retag.rs:+2:7: +2:9 _4 = &(*_10); // scope 1 at $DIR/inline_retag.rs:+2:7: +2:9 - Retag(_4); // scope 1 at $DIR/inline_retag.rs:+2:7: +2:9 _3 = &(*_4); // scope 1 at $DIR/inline_retag.rs:+2:7: +2:9 - Retag(_3); // scope 1 at $DIR/inline_retag.rs:+2:7: +2:9 StorageLive(_6); // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14 StorageLive(_7); // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14 _9 = const _; // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14 @@ -49,9 +47,7 @@ fn bar() -> bool { // + literal: Const { ty: &i32, val: Unevaluated(bar, [], Some(promoted[0])) } Retag(_9); // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14 _7 = &(*_9); // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14 - Retag(_7); // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14 _6 = &(*_7); // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14 - Retag(_6); // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14 Retag(_3); // scope 2 at $DIR/inline_retag.rs:16:8: 16:9 Retag(_6); // scope 2 at $DIR/inline_retag.rs:16:17: 16:18 StorageLive(_11); // scope 2 at $DIR/inline_retag.rs:17:5: 17:7 diff --git a/src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir index fe57e32a7acc..7b69b3e07d6c 100644 --- a/src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir +++ b/src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir @@ -68,9 +68,7 @@ fn array_casts() -> () { StorageLive(_3); // scope 1 at $DIR/retag.rs:+2:13: +2:19 StorageLive(_4); // scope 1 at $DIR/retag.rs:+2:13: +2:19 _4 = &mut _1; // scope 1 at $DIR/retag.rs:+2:13: +2:19 - Retag(_4); // scope 1 at $DIR/retag.rs:+2:13: +2:19 _3 = &raw mut (*_4); // scope 1 at $DIR/retag.rs:+2:13: +2:19 - Retag([raw] _3); // scope 1 at $DIR/retag.rs:+2:13: +2:19 _2 = move _3 as *mut usize (Pointer(ArrayToPointer)); // scope 1 at $DIR/retag.rs:+2:13: +2:33 StorageDead(_3); // scope 1 at $DIR/retag.rs:+2:32: +2:33 StorageDead(_4); // scope 1 at $DIR/retag.rs:+2:33: +2:34 @@ -96,9 +94,7 @@ fn array_casts() -> () { StorageLive(_10); // scope 4 at $DIR/retag.rs:+6:13: +6:15 StorageLive(_11); // scope 4 at $DIR/retag.rs:+6:13: +6:15 _11 = &_8; // scope 4 at $DIR/retag.rs:+6:13: +6:15 - Retag(_11); // scope 4 at $DIR/retag.rs:+6:13: +6:15 _10 = &raw const (*_11); // scope 4 at $DIR/retag.rs:+6:13: +6:15 - Retag([raw] _10); // scope 4 at $DIR/retag.rs:+6:13: +6:15 _9 = move _10 as *const usize (Pointer(ArrayToPointer)); // scope 4 at $DIR/retag.rs:+6:13: +6:31 StorageDead(_10); // scope 4 at $DIR/retag.rs:+6:30: +6:31 StorageDead(_11); // scope 4 at $DIR/retag.rs:+6:31: +6:32 @@ -119,7 +115,6 @@ fn array_casts() -> () { StorageDead(_17); // scope 6 at $DIR/retag.rs:+7:33: +7:34 _15 = (*_16); // scope 6 at $DIR/retag.rs:+7:25: +7:34 _14 = &_15; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - Retag(_14); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_18); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _35 = const _; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL // mir::Constant @@ -127,7 +122,6 @@ fn array_casts() -> () { // + literal: Const { ty: &usize, val: Unevaluated(array_casts, [], Some(promoted[0])) } Retag(_35); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _18 = &(*_35); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - Retag(_18); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL Deinit(_13); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL (_13.0: &usize) = move _14; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL (_13.1: &usize) = move _18; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL @@ -164,15 +158,11 @@ fn array_casts() -> () { StorageLive(_30); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_31); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _31 = &(*_20); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - Retag(_31); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _30 = &(*_31); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - Retag(_30); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_32); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_33); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _33 = &(*_21); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - Retag(_33); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _32 = &(*_33); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - Retag(_32); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_34); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL Deinit(_34); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL discriminant(_34) = 0; // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL diff --git a/src/test/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir b/src/test/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir index cdc413c568f1..14f297e948be 100644 --- a/src/test/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir +++ b/src/test/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir @@ -6,7 +6,6 @@ fn std::ptr::drop_in_place(_1: *mut Test) -> () { let mut _3: (); // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 bb0: { - Retag([raw] _1); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 _2 = &mut (*_1); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 _3 = ::drop(move _2) -> bb1; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 // mir::Constant diff --git a/src/test/mir-opt/retag.main-{closure#0}.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/retag.main-{closure#0}.SimplifyCfg-elaborate-drops.after.mir index 96fc7e6493ab..9e5c119a2b24 100644 --- a/src/test/mir-opt/retag.main-{closure#0}.SimplifyCfg-elaborate-drops.after.mir +++ b/src/test/mir-opt/retag.main-{closure#0}.SimplifyCfg-elaborate-drops.after.mir @@ -15,7 +15,6 @@ fn main::{closure#0}(_1: &[closure@main::{closure#0}], _2: &i32) -> &i32 { _3 = _2; // scope 0 at $DIR/retag.rs:+1:18: +1:19 Retag(_3); // scope 0 at $DIR/retag.rs:+1:18: +1:19 _0 = &(*_2); // scope 1 at $DIR/retag.rs:+2:9: +2:10 - Retag(_0); // scope 1 at $DIR/retag.rs:+2:9: +2:10 StorageDead(_3); // scope 0 at $DIR/retag.rs:+3:5: +3:6 return; // scope 0 at $DIR/retag.rs:+3:6: +3:6 } diff --git a/src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir index 81225b44ebf9..b853e4505417 100644 --- a/src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir +++ b/src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir @@ -65,13 +65,10 @@ fn main() -> () { Deinit(_5); // scope 1 at $DIR/retag.rs:+3:17: +3:24 (_5.0: i32) = const 0_i32; // scope 1 at $DIR/retag.rs:+3:17: +3:24 _4 = &_5; // scope 1 at $DIR/retag.rs:+3:17: +3:36 - Retag(_4); // scope 1 at $DIR/retag.rs:+3:17: +3:36 StorageLive(_6); // scope 1 at $DIR/retag.rs:+3:29: +3:35 StorageLive(_7); // scope 1 at $DIR/retag.rs:+3:29: +3:35 _7 = &mut _1; // scope 1 at $DIR/retag.rs:+3:29: +3:35 - Retag(_7); // scope 1 at $DIR/retag.rs:+3:29: +3:35 _6 = &mut (*_7); // scope 1 at $DIR/retag.rs:+3:29: +3:35 - Retag([2phase] _6); // scope 1 at $DIR/retag.rs:+3:29: +3:35 _3 = Test::foo(move _4, move _6) -> [return: bb1, unwind: bb8]; // scope 1 at $DIR/retag.rs:+3:17: +3:36 // mir::Constant // + span: $DIR/retag.rs:33:25: 33:28 @@ -93,7 +90,6 @@ fn main() -> () { _9 = move _3; // scope 2 at $DIR/retag.rs:+4:19: +4:20 Retag(_9); // scope 2 at $DIR/retag.rs:+4:19: +4:20 _8 = &mut (*_9); // scope 2 at $DIR/retag.rs:+4:19: +4:20 - Retag(_8); // scope 2 at $DIR/retag.rs:+4:19: +4:20 StorageDead(_9); // scope 2 at $DIR/retag.rs:+4:22: +4:23 StorageLive(_10); // scope 3 at $DIR/retag.rs:+5:13: +5:14 _10 = move _8; // scope 3 at $DIR/retag.rs:+5:17: +5:18 @@ -101,7 +97,6 @@ fn main() -> () { StorageLive(_11); // scope 4 at $DIR/retag.rs:+7:13: +7:15 StorageLive(_12); // scope 4 at $DIR/retag.rs:+7:18: +7:29 _12 = &raw mut (*_10); // scope 4 at $DIR/retag.rs:+7:18: +7:19 - Retag([raw] _12); // scope 4 at $DIR/retag.rs:+7:18: +7:19 _11 = _12; // scope 4 at $DIR/retag.rs:+7:18: +7:29 StorageDead(_12); // scope 4 at $DIR/retag.rs:+7:29: +7:30 _2 = const (); // scope 1 at $DIR/retag.rs:+2:5: +8:6 @@ -122,9 +117,7 @@ fn main() -> () { StorageLive(_17); // scope 6 at $DIR/retag.rs:+15:16: +15:18 StorageLive(_18); // scope 6 at $DIR/retag.rs:+15:16: +15:18 _18 = &_1; // scope 6 at $DIR/retag.rs:+15:16: +15:18 - Retag(_18); // scope 6 at $DIR/retag.rs:+15:16: +15:18 _17 = &(*_18); // scope 6 at $DIR/retag.rs:+15:16: +15:18 - Retag(_17); // scope 6 at $DIR/retag.rs:+15:16: +15:18 _15 = move _16(move _17) -> bb3; // scope 6 at $DIR/retag.rs:+15:14: +15:19 } @@ -139,7 +132,6 @@ fn main() -> () { Deinit(_21); // scope 7 at $DIR/retag.rs:+18:5: +18:12 (_21.0: i32) = const 0_i32; // scope 7 at $DIR/retag.rs:+18:5: +18:12 _20 = &_21; // scope 7 at $DIR/retag.rs:+18:5: +18:24 - Retag(_20); // scope 7 at $DIR/retag.rs:+18:5: +18:24 StorageLive(_22); // scope 7 at $DIR/retag.rs:+18:21: +18:23 StorageLive(_23); // scope 7 at $DIR/retag.rs:+18:21: +18:23 _28 = const _; // scope 7 at $DIR/retag.rs:+18:21: +18:23 @@ -148,9 +140,7 @@ fn main() -> () { // + literal: Const { ty: &i32, val: Unevaluated(main, [], Some(promoted[0])) } Retag(_28); // scope 7 at $DIR/retag.rs:+18:21: +18:23 _23 = &(*_28); // scope 7 at $DIR/retag.rs:+18:21: +18:23 - Retag(_23); // scope 7 at $DIR/retag.rs:+18:21: +18:23 _22 = &(*_23); // scope 7 at $DIR/retag.rs:+18:21: +18:23 - Retag(_22); // scope 7 at $DIR/retag.rs:+18:21: +18:23 _19 = Test::foo_shr(move _20, move _22) -> [return: bb4, unwind: bb7]; // scope 7 at $DIR/retag.rs:+18:5: +18:24 // mir::Constant // + span: $DIR/retag.rs:48:13: 48:20 @@ -171,7 +161,6 @@ fn main() -> () { StorageLive(_25); // scope 7 at $DIR/retag.rs:+21:9: +21:11 StorageLive(_26); // scope 7 at $DIR/retag.rs:+21:14: +21:28 _26 = &raw const (*_15); // scope 7 at $DIR/retag.rs:+21:14: +21:16 - Retag([raw] _26); // scope 7 at $DIR/retag.rs:+21:14: +21:16 _25 = _26; // scope 7 at $DIR/retag.rs:+21:14: +21:28 StorageDead(_26); // scope 7 at $DIR/retag.rs:+21:28: +21:29 StorageLive(_27); // scope 8 at $DIR/retag.rs:+23:5: +23:18 diff --git a/src/test/mir-opt/retag.{impl#0}-foo.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/retag.{impl#0}-foo.SimplifyCfg-elaborate-drops.after.mir index 08fd655ae29b..4b50205fa808 100644 --- a/src/test/mir-opt/retag.{impl#0}-foo.SimplifyCfg-elaborate-drops.after.mir +++ b/src/test/mir-opt/retag.{impl#0}-foo.SimplifyCfg-elaborate-drops.after.mir @@ -11,9 +11,7 @@ fn ::foo(_1: &Test, _2: &mut i32) -> &mut i32 Retag([fn entry] _2); // scope 0 at $DIR/retag.rs:+0:23: +0:24 StorageLive(_3); // scope 0 at $DIR/retag.rs:+1:9: +1:10 _3 = &mut (*_2); // scope 0 at $DIR/retag.rs:+1:9: +1:10 - Retag(_3); // scope 0 at $DIR/retag.rs:+1:9: +1:10 _0 = &mut (*_3); // scope 0 at $DIR/retag.rs:+1:9: +1:10 - Retag(_0); // scope 0 at $DIR/retag.rs:+1:9: +1:10 StorageDead(_3); // scope 0 at $DIR/retag.rs:+2:5: +2:6 return; // scope 0 at $DIR/retag.rs:+2:6: +2:6 } diff --git a/src/tools/miri/src/borrow_tracker/mod.rs b/src/tools/miri/src/borrow_tracker/mod.rs index 10e6e252e94b..f896a337f42c 100644 --- a/src/tools/miri/src/borrow_tracker/mod.rs +++ b/src/tools/miri/src/borrow_tracker/mod.rs @@ -11,7 +11,6 @@ use rustc_target::abi::Size; use crate::*; pub mod stacked_borrows; -use stacked_borrows::diagnostics::RetagCause; pub type CallId = NonZeroU64; @@ -265,11 +264,19 @@ impl GlobalStateInner { impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { - fn retag(&mut self, kind: RetagKind, place: &PlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> { + fn retag_ptr_value(&mut self, kind: RetagKind, val: &ImmTy<'tcx, Provenance>) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> { let this = self.eval_context_mut(); let method = this.machine.borrow_tracker.as_ref().unwrap().borrow().borrow_tracker_method; match method { - BorrowTrackerMethod::StackedBorrows => this.sb_retag(kind, place), + BorrowTrackerMethod::StackedBorrows => this.sb_retag_ptr_value(kind, val), + } + } + + fn retag_place_contents(&mut self, kind: RetagKind, place: &PlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> { + let this = self.eval_context_mut(); + let method = this.machine.borrow_tracker.as_ref().unwrap().borrow().borrow_tracker_method; + match method { + BorrowTrackerMethod::StackedBorrows => this.sb_retag_place_contents(kind, place), } } diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs index bcac873251f5..04298d435b77 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs @@ -1,6 +1,10 @@ //! Implements "Stacked Borrows". See //! for further information. +mod item; +mod stack; +pub mod diagnostics; + use log::trace; use std::cmp; use std::fmt::{self, Write}; @@ -15,15 +19,13 @@ use rustc_target::abi::{Abi, Size}; use crate::borrow_tracker::{ stacked_borrows::diagnostics::{AllocHistory, DiagnosticCx, DiagnosticCxBuilder, TagHistory}, - AccessKind, GlobalStateInner, ProtectorKind, RetagCause, RetagFields, + AccessKind, GlobalStateInner, ProtectorKind, RetagFields, }; use crate::*; -mod item; pub use item::{Item, Permission}; -mod stack; pub use stack::Stack; -pub mod diagnostics; +use diagnostics::RetagCause; pub type AllocState = Stacks; @@ -807,7 +809,34 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<' impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { - fn sb_retag( + fn sb_retag_ptr_value( + &mut self, + kind: RetagKind, + val: &ImmTy<'tcx, Provenance>, + ) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> { + let this = self.eval_context_mut(); + let ref_kind = match val.layout.ty.kind() { + ty::Ref(_, _, mutbl) => { + match mutbl { + Mutability::Mut => + RefKind::Unique { two_phase: kind == RetagKind::TwoPhase }, + Mutability::Not => RefKind::Shared, + } + } + ty::RawPtr(tym) => { + RefKind::Raw { mutable: tym.mutbl == Mutability::Mut } + } + _ => unreachable!(), + }; + let retag_cause = match kind { + RetagKind::TwoPhase { .. } => RetagCause::TwoPhase, + RetagKind::FnEntry => unreachable!(), + RetagKind::Raw | RetagKind::Default => RetagCause::Normal, + }; + this.sb_retag_reference(&val, ref_kind, retag_cause, None) + } + + fn sb_retag_place_contents( &mut self, kind: RetagKind, place: &PlaceTy<'tcx, Provenance>, @@ -815,9 +844,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let this = self.eval_context_mut(); let retag_fields = this.machine.borrow_tracker.as_mut().unwrap().get_mut().retag_fields; let retag_cause = match kind { - RetagKind::TwoPhase { .. } => RetagCause::TwoPhase, + RetagKind::Raw | RetagKind::TwoPhase { .. } => unreachable!(), RetagKind::FnEntry => RetagCause::FnEntry, - RetagKind::Raw | RetagKind::Default => RetagCause::Normal, + RetagKind::Default => RetagCause::Normal, }; let mut visitor = RetagVisitor { ecx: this, kind, retag_cause, retag_fields }; return visitor.visit_value(place); @@ -831,7 +860,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } impl<'ecx, 'mir, 'tcx> RetagVisitor<'ecx, 'mir, 'tcx> { #[inline(always)] // yes this helps in our benchmarks - fn retag_place( + fn retag_ptr_inplace( &mut self, place: &PlaceTy<'tcx, Provenance>, ref_kind: RefKind, @@ -856,7 +885,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { fn visit_box(&mut self, place: &PlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> { // Boxes get a weak protectors, since they may be deallocated. - self.retag_place( + self.retag_ptr_inplace( place, RefKind::Box, self.retag_cause, @@ -879,10 +908,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { ty::Ref(_, _, mutbl) => { let ref_kind = match mutbl { Mutability::Mut => - RefKind::Unique { two_phase: self.kind == RetagKind::TwoPhase }, + RefKind::Unique { two_phase: false }, Mutability::Not => RefKind::Shared, }; - self.retag_place( + self.retag_ptr_inplace( place, ref_kind, self.retag_cause, @@ -891,21 +920,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { .then_some(ProtectorKind::StrongProtector), )?; } - ty::RawPtr(tym) => { - // We definitely do *not* want to recurse into raw pointers -- wide raw - // pointers have fields, and for dyn Trait pointees those can have reference - // type! - if self.kind == RetagKind::Raw { - // Raw pointers need to be enabled. - self.retag_place( - place, - RefKind::Raw { mutable: tym.mutbl == Mutability::Mut }, - self.retag_cause, - /*protector*/ None, - )?; - } + ty::RawPtr(..) => { + // We do *not* want to recurse into raw pointers -- wide raw pointers have + // fields, and for dyn Trait pointees those can have reference type! } - _ if place.layout.ty.ty_adt_def().is_some_and(|adt| adt.is_box()) => { + ty::Adt(adt, _) if adt.is_box() => { // Recurse for boxes, they require some tricky handling and will end up in `visit_box` above. // (Yes this means we technically also recursively retag the allocator itself // even if field retagging is not enabled. *shrug*) diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index c110229c985d..e5b1eb2e4870 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -967,8 +967,9 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { ptr: Pointer, ) -> InterpResult<'tcx> { match ptr.provenance { - Provenance::Concrete { alloc_id, tag } => - intptrcast::GlobalStateInner::expose_ptr(ecx, alloc_id, tag), + Provenance::Concrete { alloc_id, tag } => { + intptrcast::GlobalStateInner::expose_ptr(ecx, alloc_id, tag) + } Provenance::Wildcard => { // No need to do anything for wildcard pointers as // their provenances have already been previously exposed. @@ -1055,13 +1056,26 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { } #[inline(always)] - fn retag( + fn retag_ptr_value( + ecx: &mut InterpCx<'mir, 'tcx, Self>, + kind: mir::RetagKind, + val: &ImmTy<'tcx, Provenance>, + ) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> { + if ecx.machine.borrow_tracker.is_some() { + ecx.retag_ptr_value(kind, val) + } else { + Ok(val.clone()) + } + } + + #[inline(always)] + fn retag_place_contents( ecx: &mut InterpCx<'mir, 'tcx, Self>, kind: mir::RetagKind, place: &PlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx> { if ecx.machine.borrow_tracker.is_some() { - ecx.retag(kind, place)?; + ecx.retag_place_contents(kind, place)?; } Ok(()) } From 34c58e897fc6336e31da9c7d6301a1c3520a5cde Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 5 Dec 2022 18:19:18 +0100 Subject: [PATCH 088/115] Stacked Borrows: factor the logic determining the new permissions on retag into a separate function --- .../stacked_borrows/diagnostics.rs | 4 +- .../src/borrow_tracker/stacked_borrows/mod.rs | 340 +++++++++--------- src/tools/miri/src/diagnostics.rs | 10 +- 3 files changed, 187 insertions(+), 167 deletions(-) diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs index 9a7b38b13a3a..24b3489e0d1d 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs @@ -459,10 +459,10 @@ impl<'history, 'ecx, 'mir, 'tcx> DiagnosticCx<'history, 'ecx, 'mir, 'tcx> { Operation::Dealloc(_) => format!(" due to deallocation"), Operation::Access(AccessOp { kind, tag, .. }) => format!(" due to {kind:?} access for {tag:?}"), - Operation::Retag(RetagOp { orig_tag, permission, .. }) => { + Operation::Retag(RetagOp { orig_tag, permission, new_tag, .. }) => { let permission = permission .expect("start_grant should set the current permission before popping a tag"); - format!(" due to {permission:?} retag from {orig_tag:?}") + format!(" due to {permission:?} retag from {orig_tag:?} (that retag created {new_tag:?})") } }; diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs index 04298d435b77..ffbc00864022 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs @@ -1,13 +1,13 @@ //! Implements "Stacked Borrows". See //! for further information. +pub mod diagnostics; mod item; mod stack; -pub mod diagnostics; use log::trace; use std::cmp; -use std::fmt::{self, Write}; +use std::fmt::Write; use rustc_data_structures::fx::FxHashSet; use rustc_middle::mir::{Mutability, RetagKind}; @@ -23,9 +23,9 @@ use crate::borrow_tracker::{ }; use crate::*; +use diagnostics::RetagCause; pub use item::{Item, Permission}; pub use stack::Stack; -use diagnostics::RetagCause; pub type AllocState = Stacks; @@ -42,30 +42,104 @@ pub struct Stacks { modified_since_last_gc: bool, } -/// Indicates which kind of reference is being created. -/// Used by high-level `reborrow` to compute which permissions to grant to the -/// new pointer. -#[derive(Copy, Clone, Hash, PartialEq, Eq)] -enum RefKind { - /// `Box`. - Box, - /// `&mut`. - Unique { two_phase: bool }, - /// `&` with or without interior mutability. - Shared, - /// `*mut`/`*const` (raw pointers). - Raw { mutable: bool }, +/// Indicates which permissions to grant to the retagged pointer. +#[derive(Clone, Debug)] +enum NewPermission { + Uniform { + perm: Permission, + access: Option, + protector: Option, + }, + FreezeSensitive { + freeze_perm: Permission, + freeze_access: Option, + freeze_protector: Option, + nonfreeze_perm: Permission, + nonfreeze_access: Option, + // nonfreeze_protector must always be None + }, } -impl fmt::Display for RefKind { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +impl NewPermission { + /// A key function: determine the permissions to grant at a retag for the given kind of + /// reference/pointer. + fn from_ref_ty<'tcx>( + ty: ty::Ty<'tcx>, + kind: RetagKind, + cx: &crate::MiriInterpCx<'_, 'tcx>, + ) -> Self { + let protector = (kind == RetagKind::FnEntry).then_some(ProtectorKind::StrongProtector); + match ty.kind() { + ty::Ref(_, pointee, Mutability::Mut) => { + if kind == RetagKind::TwoPhase { + // We mostly just give up on 2phase-borrows, and treat these exactly like raw pointers. + assert!(protector.is_none()); // RetagKind can't be both FnEntry and TwoPhase. + NewPermission::Uniform { + perm: Permission::SharedReadWrite, + access: None, + protector: None, + } + } else if pointee.is_unpin(*cx.tcx, cx.param_env()) { + // A regular full mutable reference. + NewPermission::Uniform { + perm: Permission::Unique, + access: Some(AccessKind::Write), + protector, + } + } else { + NewPermission::Uniform { + perm: Permission::SharedReadWrite, + // FIXME: We emit `dereferenceable` for `!Unpin` mutable references, so we + // should do fake accesses here. But then we run into + // , so for now + // we don't do that. + access: None, + protector, + } + } + } + ty::RawPtr(ty::TypeAndMut { mutbl: Mutability::Mut, .. }) => { + assert!(protector.is_none()); // RetagKind can't be both FnEntry and Raw. + // Mutable raw pointer. No access, not protected. + NewPermission::Uniform { + perm: Permission::SharedReadWrite, + access: None, + protector: None, + } + } + ty::Ref(_, _pointee, Mutability::Not) => { + NewPermission::FreezeSensitive { + freeze_perm: Permission::SharedReadOnly, + freeze_access: Some(AccessKind::Read), + freeze_protector: protector, + nonfreeze_perm: Permission::SharedReadWrite, + // Inside UnsafeCell, this does *not* count as an access, as there + // might actually be mutable references further up the stack that + // we have to keep alive. + nonfreeze_access: None, + // We do not protect inside UnsafeCell. + // This fixes https://github.com/rust-lang/rust/issues/55005. + } + } + ty::RawPtr(ty::TypeAndMut { mutbl: Mutability::Not, .. }) => { + assert!(protector.is_none()); // RetagKind can't be both FnEntry and Raw. + // `*const T`, when freshly created, are read-only in the frozen part. + NewPermission::FreezeSensitive { + freeze_perm: Permission::SharedReadOnly, + freeze_access: Some(AccessKind::Read), + freeze_protector: None, + nonfreeze_perm: Permission::SharedReadWrite, + nonfreeze_access: None, + } + } + _ => unreachable!(), + } + } + + fn protector(&self) -> Option { match self { - RefKind::Box => write!(f, "Box"), - RefKind::Unique { two_phase: false } => write!(f, "unique reference"), - RefKind::Unique { two_phase: true } => write!(f, "unique reference (two-phase)"), - RefKind::Shared => write!(f, "shared reference"), - RefKind::Raw { mutable: true } => write!(f, "raw (mutable) pointer"), - RefKind::Raw { mutable: false } => write!(f, "raw (constant) pointer"), + NewPermission::Uniform { protector, .. } => *protector, + NewPermission::FreezeSensitive { freeze_protector, .. } => *freeze_protector, } } } @@ -520,10 +594,9 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<' &mut self, place: &MPlaceTy<'tcx, Provenance>, size: Size, - kind: RefKind, - retag_cause: RetagCause, // What caused this retag, for diagnostics only + new_perm: NewPermission, new_tag: BorTag, - protect: Option, + retag_cause: RetagCause, // What caused this retag, for diagnostics only ) -> InterpResult<'tcx, Option> { let this = self.eval_context_mut(); @@ -534,20 +607,16 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<' let global = this.machine.borrow_tracker.as_ref().unwrap().borrow(); let ty = place.layout.ty; if global.tracked_pointer_tags.contains(&new_tag) { - let mut kind_str = format!("{kind}"); - match kind { - RefKind::Unique { two_phase: false } - if !ty.is_unpin(*this.tcx, this.param_env()) => - { - write!(kind_str, " (!Unpin pointee type {ty})").unwrap() - }, - RefKind::Shared - if !ty.is_freeze(*this.tcx, this.param_env()) => - { - write!(kind_str, " (!Freeze pointee type {ty})").unwrap() - }, - _ => write!(kind_str, " (pointee type {ty})").unwrap(), - }; + let mut kind_str = String::new(); + match new_perm { + NewPermission::Uniform { perm, .. } => + write!(kind_str, "{perm:?} permission").unwrap(), + NewPermission::FreezeSensitive { freeze_perm, .. } if ty.is_freeze(*this.tcx, this.param_env()) => + write!(kind_str, "{freeze_perm:?} permission").unwrap(), + NewPermission::FreezeSensitive { freeze_perm, nonfreeze_perm, .. } => + write!(kind_str, "{freeze_perm:?}/{nonfreeze_perm:?} permission for frozen/non-frozen parts").unwrap(), + } + write!(kind_str, " (pointee type {ty})").unwrap(); this.emit_diagnostic(NonHaltingDiagnostic::CreatedPointerTag( new_tag.inner(), Some(kind_str), @@ -581,7 +650,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<' ); let mut dcx = dcx.build(&mut stacked_borrows.history, base_offset); dcx.log_creation(); - if protect.is_some() { + if new_perm.protector().is_some() { dcx.log_protector(); } }, @@ -594,8 +663,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<' if size == Size::ZERO { trace!( - "reborrow of size 0: {} reference {:?} derived from {:?} (pointee {})", - kind, + "reborrow of size 0: reference {:?} derived from {:?} (pointee {})", new_tag, place.ptr, place.layout.ty, @@ -632,8 +700,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<' } trace!( - "reborrow: {} reference {:?} derived from {:?} (pointee {}): {:?}, size {}", - kind, + "reborrow: reference {:?} derived from {:?} (pointee {}): {:?}, size {}", new_tag, orig_tag, place.layout.ty, @@ -641,7 +708,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<' size.bytes() ); - if let Some(protect) = protect { + if let Some(protect) = new_perm.protector() { // See comment in `Stack::item_invalidated` for why we store the tag twice. this.frame_mut().extra.borrow_tracker.as_mut().unwrap().protected_tags.push(new_tag); this.machine @@ -653,30 +720,45 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<' .insert(new_tag, protect); } - // Update the stacks. - // Make sure that raw pointers and mutable shared references are reborrowed "weak": - // There could be existing unique pointers reborrowed from them that should remain valid! - let (perm, access) = match kind { - RefKind::Unique { two_phase } => { - // Permission is Unique only if the type is `Unpin` and this is not twophase - if !two_phase && place.layout.ty.is_unpin(*this.tcx, this.param_env()) { - (Permission::Unique, Some(AccessKind::Write)) - } else { - // FIXME: We emit `dereferenceable` for `!Unpin` mutable references, so we - // should do fake accesses here. But then we run into - // , so for now - // we don't do that. - (Permission::SharedReadWrite, None) + // Update the stacks, according to the new permission information we are given. + match new_perm { + NewPermission::Uniform { perm, access, protector } => { + assert!(perm != Permission::SharedReadOnly); + // Here we can avoid `borrow()` calls because we have mutable references. + // Note that this asserts that the allocation is mutable -- but since we are creating a + // mutable pointer, that seems reasonable. + let (alloc_extra, machine) = this.get_alloc_extra_mut(alloc_id)?; + let stacked_borrows = alloc_extra.borrow_tracker_sb_mut().get_mut(); + let item = Item::new(new_tag, perm, protector.is_some()); + let range = alloc_range(base_offset, size); + let global = machine.borrow_tracker.as_ref().unwrap().borrow(); + let dcx = DiagnosticCxBuilder::retag( + machine, + retag_cause, + new_tag, + orig_tag, + alloc_range(base_offset, size), + ); + stacked_borrows.for_each(range, dcx, |stack, dcx, exposed_tags| { + stack.grant(orig_tag, item, access, &global, dcx, exposed_tags) + })?; + drop(global); + if let Some(access) = access { + assert_eq!(access, AccessKind::Write); + // Make sure the data race model also knows about this. + if let Some(data_race) = alloc_extra.data_race.as_mut() { + data_race.write(alloc_id, range, machine)?; + } } } - RefKind::Box => (Permission::Unique, Some(AccessKind::Write)), - RefKind::Raw { mutable: true } => { - // Creating a raw ptr does not count as an access - (Permission::SharedReadWrite, None) - } - RefKind::Shared | RefKind::Raw { mutable: false } => { - // Shared references and *const are a whole different kind of game, the - // permission is not uniform across the entire range! + NewPermission::FreezeSensitive { + freeze_perm, + freeze_access, + freeze_protector, + nonfreeze_perm, + nonfreeze_access, + } => { + // The permission is not uniform across the entire range! // We need a frozen-sensitive reborrow. // We have to use shared references to alloc/memory_extra here since // `visit_freeze_sensitive` needs to access the global state. @@ -686,22 +768,12 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<' // Adjust range. range.start += base_offset; // We are only ever `SharedReadOnly` inside the frozen bits. - let (perm, access) = if frozen { - (Permission::SharedReadOnly, Some(AccessKind::Read)) + let (perm, access, protector) = if frozen { + (freeze_perm, freeze_access, freeze_protector) } else { - // Inside UnsafeCell, this does *not* count as an access, as there - // might actually be mutable references further up the stack that - // we have to keep alive. - (Permission::SharedReadWrite, None) + (nonfreeze_perm, nonfreeze_access, None) }; - let protected = if frozen { - protect.is_some() - } else { - // We do not protect inside UnsafeCell. - // This fixes https://github.com/rust-lang/rust/issues/55005. - false - }; - let item = Item::new(new_tag, perm, protected); + let item = Item::new(new_tag, perm, protector.is_some()); let global = this.machine.borrow_tracker.as_ref().unwrap().borrow(); let dcx = DiagnosticCxBuilder::retag( &this.machine, @@ -723,34 +795,6 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<' } Ok(()) })?; - return Ok(Some(alloc_id)); - } - }; - - // Here we can avoid `borrow()` calls because we have mutable references. - // Note that this asserts that the allocation is mutable -- but since we are creating a - // mutable pointer, that seems reasonable. - let (alloc_extra, machine) = this.get_alloc_extra_mut(alloc_id)?; - let stacked_borrows = alloc_extra.borrow_tracker_sb_mut().get_mut(); - let item = Item::new(new_tag, perm, protect.is_some()); - let range = alloc_range(base_offset, size); - let global = machine.borrow_tracker.as_ref().unwrap().borrow(); - let dcx = DiagnosticCxBuilder::retag( - machine, - retag_cause, - new_tag, - orig_tag, - alloc_range(base_offset, size), - ); - stacked_borrows.for_each(range, dcx, |stack, dcx, exposed_tags| { - stack.grant(orig_tag, item, access, &global, dcx, exposed_tags) - })?; - drop(global); - if let Some(access) = access { - assert_eq!(access, AccessKind::Write); - // Make sure the data race model also knows about this. - if let Some(data_race) = alloc_extra.data_race.as_mut() { - data_race.write(alloc_id, range, machine)?; } } @@ -762,9 +806,8 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<' fn sb_retag_reference( &mut self, val: &ImmTy<'tcx, Provenance>, - kind: RefKind, - retag_cause: RetagCause, // What caused this retag, for diagnostics only - protect: Option, + new_perm: NewPermission, + cause: RetagCause, // What caused this retag, for diagnostics only ) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> { let this = self.eval_context_mut(); // We want a place for where the ptr *points to*, so we get one. @@ -782,7 +825,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<' let new_tag = this.machine.borrow_tracker.as_mut().unwrap().get_mut().new_ptr(); // Reborrow. - let alloc_id = this.sb_reborrow(&place, size, kind, retag_cause, new_tag, protect)?; + let alloc_id = this.sb_reborrow(&place, size, new_perm, new_tag, cause)?; // Adjust pointer. let new_place = place.map_provenance(|p| { @@ -815,25 +858,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { val: &ImmTy<'tcx, Provenance>, ) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> { let this = self.eval_context_mut(); - let ref_kind = match val.layout.ty.kind() { - ty::Ref(_, _, mutbl) => { - match mutbl { - Mutability::Mut => - RefKind::Unique { two_phase: kind == RetagKind::TwoPhase }, - Mutability::Not => RefKind::Shared, - } - } - ty::RawPtr(tym) => { - RefKind::Raw { mutable: tym.mutbl == Mutability::Mut } - } - _ => unreachable!(), - }; + let new_perm = NewPermission::from_ref_ty(val.layout.ty, kind, this); let retag_cause = match kind { RetagKind::TwoPhase { .. } => RetagCause::TwoPhase, RetagKind::FnEntry => unreachable!(), RetagKind::Raw | RetagKind::Default => RetagCause::Normal, }; - this.sb_retag_reference(&val, ref_kind, retag_cause, None) + this.sb_retag_reference(&val, new_perm, retag_cause) } fn sb_retag_place_contents( @@ -844,7 +875,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let this = self.eval_context_mut(); let retag_fields = this.machine.borrow_tracker.as_mut().unwrap().get_mut().retag_fields; let retag_cause = match kind { - RetagKind::Raw | RetagKind::TwoPhase { .. } => unreachable!(), + RetagKind::Raw | RetagKind::TwoPhase { .. } => unreachable!(), // these can only happen in `retag_ptr_value` RetagKind::FnEntry => RetagCause::FnEntry, RetagKind::Default => RetagCause::Normal, }; @@ -863,12 +894,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { fn retag_ptr_inplace( &mut self, place: &PlaceTy<'tcx, Provenance>, - ref_kind: RefKind, + new_perm: NewPermission, retag_cause: RetagCause, - protector: Option, ) -> InterpResult<'tcx> { let val = self.ecx.read_immediate(&self.ecx.place_to_op(place)?)?; - let val = self.ecx.sb_retag_reference(&val, ref_kind, retag_cause, protector)?; + let val = self.ecx.sb_retag_reference(&val, new_perm, retag_cause)?; self.ecx.write_immediate(*val, place)?; Ok(()) } @@ -885,13 +915,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { fn visit_box(&mut self, place: &PlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> { // Boxes get a weak protectors, since they may be deallocated. - self.retag_ptr_inplace( - place, - RefKind::Box, - self.retag_cause, - /*protector*/ - (self.kind == RetagKind::FnEntry).then_some(ProtectorKind::WeakProtector), - ) + let new_perm = NewPermission::Uniform { + perm: Permission::Unique, + access: Some(AccessKind::Write), + protector: (self.kind == RetagKind::FnEntry) + .then_some(ProtectorKind::WeakProtector), + }; + self.retag_ptr_inplace(place, new_perm, self.retag_cause) } fn visit_value(&mut self, place: &PlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> { @@ -905,20 +935,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // Check the type of this value to see what to do with it (retag, or recurse). match place.layout.ty.kind() { - ty::Ref(_, _, mutbl) => { - let ref_kind = match mutbl { - Mutability::Mut => - RefKind::Unique { two_phase: false }, - Mutability::Not => RefKind::Shared, - }; - self.retag_ptr_inplace( - place, - ref_kind, - self.retag_cause, - /*protector*/ - (self.kind == RetagKind::FnEntry) - .then_some(ProtectorKind::StrongProtector), - )?; + ty::Ref(..) => { + let new_perm = + NewPermission::from_ref_ty(place.layout.ty, self.kind, self.ecx); + self.retag_ptr_inplace(place, new_perm, self.retag_cause)?; } ty::RawPtr(..) => { // We do *not* want to recurse into raw pointers -- wide raw pointers have @@ -972,12 +992,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let ptr_layout = this.layout_of(this.tcx.mk_mut_ptr(return_place.layout.ty))?; let val = ImmTy::from_immediate(return_place.to_ref(this), ptr_layout); // Reborrow it. With protection! That is part of the point. - let val = this.sb_retag_reference( - &val, - RefKind::Unique { two_phase: false }, - RetagCause::FnReturn, - /*protector*/ Some(ProtectorKind::StrongProtector), - )?; + let new_perm = NewPermission::Uniform { + perm: Permission::Unique, + access: Some(AccessKind::Write), + protector: Some(ProtectorKind::StrongProtector), + }; + let val = this.sb_retag_reference(&val, new_perm, RetagCause::FnReturn)?; // And use reborrowed pointer for return place. let return_place = this.ref_to_mplace(&val)?; this.frame_mut().return_place = return_place.into(); diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs index 074fa032dcc4..d0fb9f9b0b5f 100644 --- a/src/tools/miri/src/diagnostics.rs +++ b/src/tools/miri/src/diagnostics.rs @@ -63,9 +63,9 @@ impl MachineStopType for TerminationInfo {} /// Miri specific diagnostics pub enum NonHaltingDiagnostic { - /// (new_tag, new_kind, (alloc_id, base_offset, orig_tag)) + /// (new_tag, new_perm, (alloc_id, base_offset, orig_tag)) /// - /// new_kind is `None` for base tags. + /// new_perm is `None` for base tags. CreatedPointerTag(NonZeroU64, Option, Option<(AllocId, AllocRange, ProvenanceExtra)>), /// This `Item` was popped from the borrow stack. The string explains the reason. PoppedPointerTag(Item, String), @@ -393,10 +393,10 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> { let msg = match &e { CreatedPointerTag(tag, None, _) => format!("created base tag {tag:?}"), - CreatedPointerTag(tag, Some(kind), None) => format!("created {tag:?} for {kind}"), - CreatedPointerTag(tag, Some(kind), Some((alloc_id, range, orig_tag))) => + CreatedPointerTag(tag, Some(perm), None) => format!("created {tag:?} with {perm} derived from unknown tag"), + CreatedPointerTag(tag, Some(perm), Some((alloc_id, range, orig_tag))) => format!( - "created tag {tag:?} for {kind} at {alloc_id:?}{range:?} derived from {orig_tag:?}" + "created tag {tag:?} with {perm} at {alloc_id:?}{range:?} derived from {orig_tag:?}" ), PoppedPointerTag(item, cause) => format!("popped tracked tag for item {item:?}{cause}"), CreatedCallId(id) => format!("function call with id {id}"), From 07fbb1b372435283716885fc2973808ff7da22ca Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Tue, 6 Dec 2022 11:17:49 +0000 Subject: [PATCH 089/115] Cleanup macro-expanded code in `rustc_type_ir` --- compiler/rustc_span/src/def_id.rs | 2 +- compiler/rustc_type_ir/src/sty.rs | 554 ++++++++++-------------------- 2 files changed, 189 insertions(+), 367 deletions(-) diff --git a/compiler/rustc_span/src/def_id.rs b/compiler/rustc_span/src/def_id.rs index f5555846d20a..0ad1f1a0da72 100644 --- a/compiler/rustc_span/src/def_id.rs +++ b/compiler/rustc_span/src/def_id.rs @@ -274,7 +274,7 @@ impl Ord for DefId { impl PartialOrd for DefId { #[inline] fn partial_cmp(&self, other: &DefId) -> Option { - Some(Ord::cmp(self, other)) + Some(self.cmp(other)) } } diff --git a/compiler/rustc_type_ir/src/sty.rs b/compiler/rustc_type_ir/src/sty.rs index 02cbb2e858f8..a6537f41d1e5 100644 --- a/compiler/rustc_type_ir/src/sty.rs +++ b/compiler/rustc_type_ir/src/sty.rs @@ -301,61 +301,37 @@ impl Clone for TyKind { impl PartialEq for TyKind { #[inline] fn eq(&self, other: &TyKind) -> bool { - let __self_vi = tykind_discriminant(self); - let __arg_1_vi = tykind_discriminant(other); - if __self_vi == __arg_1_vi { - match (&*self, &*other) { - (&Int(ref __self_0), &Int(ref __arg_1_0)) => __self_0 == __arg_1_0, - (&Uint(ref __self_0), &Uint(ref __arg_1_0)) => __self_0 == __arg_1_0, - (&Float(ref __self_0), &Float(ref __arg_1_0)) => __self_0 == __arg_1_0, - (&Adt(ref __self_0, ref __self_1), &Adt(ref __arg_1_0, ref __arg_1_1)) => { - __self_0 == __arg_1_0 && __self_1 == __arg_1_1 + tykind_discriminant(self) == tykind_discriminant(other) + && match (self, other) { + (Int(a_i), Int(b_i)) => a_i == b_i, + (Uint(a_u), Uint(b_u)) => a_u == b_u, + (Float(a_f), Float(b_f)) => a_f == b_f, + (Adt(a_d, a_s), Adt(b_d, b_s)) => a_d == b_d && a_s == b_s, + (Foreign(a_d), Foreign(b_d)) => a_d == b_d, + (Array(a_t, a_c), Array(b_t, b_c)) => a_t == b_t && a_c == b_c, + (Slice(a_t), Slice(b_t)) => a_t == b_t, + (RawPtr(a_t), RawPtr(b_t)) => a_t == b_t, + (Ref(a_r, a_t, a_m), Ref(b_r, b_t, b_m)) => a_r == b_r && a_t == b_t && a_m == b_m, + (FnDef(a_d, a_s), FnDef(b_d, b_s)) => a_d == b_d && a_s == b_s, + (FnPtr(a_s), FnPtr(b_s)) => a_s == b_s, + (Dynamic(a_p, a_r, a_repr), Dynamic(b_p, b_r, b_repr)) => { + a_p == b_p && a_r == b_r && a_repr == b_repr } - (&Foreign(ref __self_0), &Foreign(ref __arg_1_0)) => __self_0 == __arg_1_0, - (&Array(ref __self_0, ref __self_1), &Array(ref __arg_1_0, ref __arg_1_1)) => { - __self_0 == __arg_1_0 && __self_1 == __arg_1_1 + (Closure(a_d, a_s), Closure(b_d, b_s)) => a_d == b_d && a_s == b_s, + (Generator(a_d, a_s, a_m), Generator(b_d, b_s, b_m)) => { + a_d == b_d && a_s == b_s && a_m == b_m } - (&Slice(ref __self_0), &Slice(ref __arg_1_0)) => __self_0 == __arg_1_0, - (&RawPtr(ref __self_0), &RawPtr(ref __arg_1_0)) => __self_0 == __arg_1_0, - ( - &Ref(ref __self_0, ref __self_1, ref __self_2), - &Ref(ref __arg_1_0, ref __arg_1_1, ref __arg_1_2), - ) => __self_0 == __arg_1_0 && __self_1 == __arg_1_1 && __self_2 == __arg_1_2, - (&FnDef(ref __self_0, ref __self_1), &FnDef(ref __arg_1_0, ref __arg_1_1)) => { - __self_0 == __arg_1_0 && __self_1 == __arg_1_1 - } - (&FnPtr(ref __self_0), &FnPtr(ref __arg_1_0)) => __self_0 == __arg_1_0, - ( - &Dynamic(ref __self_0, ref __self_1, ref self_repr), - &Dynamic(ref __arg_1_0, ref __arg_1_1, ref arg_repr), - ) => __self_0 == __arg_1_0 && __self_1 == __arg_1_1 && self_repr == arg_repr, - (&Closure(ref __self_0, ref __self_1), &Closure(ref __arg_1_0, ref __arg_1_1)) => { - __self_0 == __arg_1_0 && __self_1 == __arg_1_1 - } - ( - &Generator(ref __self_0, ref __self_1, ref __self_2), - &Generator(ref __arg_1_0, ref __arg_1_1, ref __arg_1_2), - ) => __self_0 == __arg_1_0 && __self_1 == __arg_1_1 && __self_2 == __arg_1_2, - (&GeneratorWitness(ref __self_0), &GeneratorWitness(ref __arg_1_0)) => { - __self_0 == __arg_1_0 - } - (&Tuple(ref __self_0), &Tuple(ref __arg_1_0)) => __self_0 == __arg_1_0, - (&Projection(ref __self_0), &Projection(ref __arg_1_0)) => __self_0 == __arg_1_0, - (&Opaque(ref __self_0, ref __self_1), &Opaque(ref __arg_1_0, ref __arg_1_1)) => { - __self_0 == __arg_1_0 && __self_1 == __arg_1_1 - } - (&Param(ref __self_0), &Param(ref __arg_1_0)) => __self_0 == __arg_1_0, - (&Bound(ref __self_0, ref __self_1), &Bound(ref __arg_1_0, ref __arg_1_1)) => { - __self_0 == __arg_1_0 && __self_1 == __arg_1_1 - } - (&Placeholder(ref __self_0), &Placeholder(ref __arg_1_0)) => __self_0 == __arg_1_0, - (&Infer(ref __self_0), &Infer(ref __arg_1_0)) => __self_0 == __arg_1_0, - (&Error(ref __self_0), &Error(ref __arg_1_0)) => __self_0 == __arg_1_0, - _ => true, + (GeneratorWitness(a_g), GeneratorWitness(b_g)) => a_g == b_g, + (Tuple(a_t), Tuple(b_t)) => a_t == b_t, + (Projection(a_p), Projection(b_p)) => a_p == b_p, + (Opaque(a_d, a_s), Opaque(b_d, b_s)) => a_d == b_d && a_s == b_s, + (Param(a_p), Param(b_p)) => a_p == b_p, + (Bound(a_d, a_b), Bound(b_d, b_b)) => a_d == b_d && a_b == b_b, + (Placeholder(a_p), Placeholder(b_p)) => a_p == b_p, + (Infer(a_t), Infer(b_t)) => a_t == b_t, + (Error(a_e), Error(b_e)) => a_e == b_e, + _ => true, // unreachable } - } else { - false - } } } @@ -366,7 +342,7 @@ impl Eq for TyKind {} impl PartialOrd for TyKind { #[inline] fn partial_cmp(&self, other: &TyKind) -> Option { - Some(Ord::cmp(self, other)) + Some(self.cmp(other)) } } @@ -374,213 +350,102 @@ impl PartialOrd for TyKind { impl Ord for TyKind { #[inline] fn cmp(&self, other: &TyKind) -> Ordering { - let __self_vi = tykind_discriminant(self); - let __arg_1_vi = tykind_discriminant(other); - if __self_vi == __arg_1_vi { - match (&*self, &*other) { - (&Int(ref __self_0), &Int(ref __arg_1_0)) => Ord::cmp(__self_0, __arg_1_0), - (&Uint(ref __self_0), &Uint(ref __arg_1_0)) => Ord::cmp(__self_0, __arg_1_0), - (&Float(ref __self_0), &Float(ref __arg_1_0)) => Ord::cmp(__self_0, __arg_1_0), - (&Adt(ref __self_0, ref __self_1), &Adt(ref __arg_1_0, ref __arg_1_1)) => { - match Ord::cmp(__self_0, __arg_1_0) { - Ordering::Equal => Ord::cmp(__self_1, __arg_1_1), - cmp => cmp, - } + tykind_discriminant(self).cmp(&tykind_discriminant(other)).then_with(|| { + match (self, other) { + (Int(a_i), Int(b_i)) => a_i.cmp(b_i), + (Uint(a_u), Uint(b_u)) => a_u.cmp(b_u), + (Float(a_f), Float(b_f)) => a_f.cmp(b_f), + (Adt(a_d, a_s), Adt(b_d, b_s)) => a_d.cmp(b_d).then_with(|| a_s.cmp(b_s)), + (Foreign(a_d), Foreign(b_d)) => a_d.cmp(b_d), + (Array(a_t, a_c), Array(b_t, b_c)) => a_t.cmp(b_t).then_with(|| a_c.cmp(b_c)), + (Slice(a_t), Slice(b_t)) => a_t.cmp(b_t), + (RawPtr(a_t), RawPtr(b_t)) => a_t.cmp(b_t), + (Ref(a_r, a_t, a_m), Ref(b_r, b_t, b_m)) => { + a_r.cmp(b_r).then_with(|| a_t.cmp(b_t).then_with(|| a_m.cmp(b_m))) } - (&Foreign(ref __self_0), &Foreign(ref __arg_1_0)) => Ord::cmp(__self_0, __arg_1_0), - (&Array(ref __self_0, ref __self_1), &Array(ref __arg_1_0, ref __arg_1_1)) => { - match Ord::cmp(__self_0, __arg_1_0) { - Ordering::Equal => Ord::cmp(__self_1, __arg_1_1), - cmp => cmp, - } + (FnDef(a_d, a_s), FnDef(b_d, b_s)) => a_d.cmp(b_d).then_with(|| a_s.cmp(b_s)), + (FnPtr(a_s), FnPtr(b_s)) => a_s.cmp(b_s), + (Dynamic(a_p, a_r, a_repr), Dynamic(b_p, b_r, b_repr)) => { + a_p.cmp(b_p).then_with(|| a_r.cmp(b_r).then_with(|| a_repr.cmp(b_repr))) } - (&Slice(ref __self_0), &Slice(ref __arg_1_0)) => Ord::cmp(__self_0, __arg_1_0), - (&RawPtr(ref __self_0), &RawPtr(ref __arg_1_0)) => Ord::cmp(__self_0, __arg_1_0), - ( - &Ref(ref __self_0, ref __self_1, ref __self_2), - &Ref(ref __arg_1_0, ref __arg_1_1, ref __arg_1_2), - ) => match Ord::cmp(__self_0, __arg_1_0) { - Ordering::Equal => match Ord::cmp(__self_1, __arg_1_1) { - Ordering::Equal => Ord::cmp(__self_2, __arg_1_2), - cmp => cmp, - }, - cmp => cmp, - }, - (&FnDef(ref __self_0, ref __self_1), &FnDef(ref __arg_1_0, ref __arg_1_1)) => { - match Ord::cmp(__self_0, __arg_1_0) { - Ordering::Equal => Ord::cmp(__self_1, __arg_1_1), - cmp => cmp, - } + (Closure(a_p, a_s), Closure(b_p, b_s)) => a_p.cmp(b_p).then_with(|| a_s.cmp(b_s)), + (Generator(a_d, a_s, a_m), Generator(b_d, b_s, b_m)) => { + a_d.cmp(b_d).then_with(|| a_s.cmp(b_s).then_with(|| a_m.cmp(b_m))) } - (&FnPtr(ref __self_0), &FnPtr(ref __arg_1_0)) => Ord::cmp(__self_0, __arg_1_0), - ( - &Dynamic(ref __self_0, ref __self_1, ref self_repr), - &Dynamic(ref __arg_1_0, ref __arg_1_1, ref arg_repr), - ) => match Ord::cmp(__self_0, __arg_1_0) { - Ordering::Equal => match Ord::cmp(__self_1, __arg_1_1) { - Ordering::Equal => Ord::cmp(self_repr, arg_repr), - cmp => cmp, - }, - cmp => cmp, - }, - (&Closure(ref __self_0, ref __self_1), &Closure(ref __arg_1_0, ref __arg_1_1)) => { - match Ord::cmp(__self_0, __arg_1_0) { - Ordering::Equal => Ord::cmp(__self_1, __arg_1_1), - cmp => cmp, - } - } - ( - &Generator(ref __self_0, ref __self_1, ref __self_2), - &Generator(ref __arg_1_0, ref __arg_1_1, ref __arg_1_2), - ) => match Ord::cmp(__self_0, __arg_1_0) { - Ordering::Equal => match Ord::cmp(__self_1, __arg_1_1) { - Ordering::Equal => Ord::cmp(__self_2, __arg_1_2), - cmp => cmp, - }, - cmp => cmp, - }, - (&GeneratorWitness(ref __self_0), &GeneratorWitness(ref __arg_1_0)) => { - Ord::cmp(__self_0, __arg_1_0) - } - (&Tuple(ref __self_0), &Tuple(ref __arg_1_0)) => Ord::cmp(__self_0, __arg_1_0), - (&Projection(ref __self_0), &Projection(ref __arg_1_0)) => { - Ord::cmp(__self_0, __arg_1_0) - } - (&Opaque(ref __self_0, ref __self_1), &Opaque(ref __arg_1_0, ref __arg_1_1)) => { - match Ord::cmp(__self_0, __arg_1_0) { - Ordering::Equal => Ord::cmp(__self_1, __arg_1_1), - cmp => cmp, - } - } - (&Param(ref __self_0), &Param(ref __arg_1_0)) => Ord::cmp(__self_0, __arg_1_0), - (&Bound(ref __self_0, ref __self_1), &Bound(ref __arg_1_0, ref __arg_1_1)) => { - match Ord::cmp(__self_0, __arg_1_0) { - Ordering::Equal => Ord::cmp(__self_1, __arg_1_1), - cmp => cmp, - } - } - (&Placeholder(ref __self_0), &Placeholder(ref __arg_1_0)) => { - Ord::cmp(__self_0, __arg_1_0) - } - (&Infer(ref __self_0), &Infer(ref __arg_1_0)) => Ord::cmp(__self_0, __arg_1_0), - (&Error(ref __self_0), &Error(ref __arg_1_0)) => Ord::cmp(__self_0, __arg_1_0), - _ => Ordering::Equal, + (GeneratorWitness(a_g), GeneratorWitness(b_g)) => a_g.cmp(b_g), + (Tuple(a_t), Tuple(b_t)) => a_t.cmp(b_t), + (Projection(a_p), Projection(b_p)) => a_p.cmp(b_p), + (Opaque(a_d, a_s), Opaque(b_d, b_s)) => a_d.cmp(b_d).then_with(|| a_s.cmp(b_s)), + (Param(a_p), Param(b_p)) => a_p.cmp(b_p), + (Bound(a_d, a_b), Bound(b_d, b_b)) => a_d.cmp(b_d).then_with(|| a_b.cmp(b_b)), + (Placeholder(a_p), Placeholder(b_p)) => a_p.cmp(b_p), + (Infer(a_t), Infer(b_t)) => a_t.cmp(b_t), + (Error(a_e), Error(b_e)) => a_e.cmp(b_e), + _ => Ordering::Equal, // unreachable } - } else { - Ord::cmp(&__self_vi, &__arg_1_vi) - } + }) } } // This is manually implemented because a derive would require `I: Hash` impl hash::Hash for TyKind { fn hash<__H: hash::Hasher>(&self, state: &mut __H) -> () { - match (&*self,) { - (&Int(ref __self_0),) => { - hash::Hash::hash(&tykind_discriminant(self), state); - hash::Hash::hash(__self_0, state) + tykind_discriminant(self).hash(state); + match self { + Int(i) => i.hash(state), + Uint(u) => u.hash(state), + Float(f) => f.hash(state), + Adt(d, s) => { + d.hash(state); + s.hash(state) } - (&Uint(ref __self_0),) => { - hash::Hash::hash(&tykind_discriminant(self), state); - hash::Hash::hash(__self_0, state) + Foreign(d) => d.hash(state), + Array(t, c) => { + t.hash(state); + c.hash(state) } - (&Float(ref __self_0),) => { - hash::Hash::hash(&tykind_discriminant(self), state); - hash::Hash::hash(__self_0, state) + Slice(t) => t.hash(state), + RawPtr(t) => t.hash(state), + Ref(r, t, m) => { + r.hash(state); + t.hash(state); + m.hash(state) } - (&Adt(ref __self_0, ref __self_1),) => { - hash::Hash::hash(&tykind_discriminant(self), state); - hash::Hash::hash(__self_0, state); - hash::Hash::hash(__self_1, state) + FnDef(d, s) => { + d.hash(state); + s.hash(state) } - (&Foreign(ref __self_0),) => { - hash::Hash::hash(&tykind_discriminant(self), state); - hash::Hash::hash(__self_0, state) + FnPtr(s) => s.hash(state), + Dynamic(p, r, repr) => { + p.hash(state); + r.hash(state); + repr.hash(state) } - (&Array(ref __self_0, ref __self_1),) => { - hash::Hash::hash(&tykind_discriminant(self), state); - hash::Hash::hash(__self_0, state); - hash::Hash::hash(__self_1, state) + Closure(d, s) => { + d.hash(state); + s.hash(state) } - (&Slice(ref __self_0),) => { - hash::Hash::hash(&tykind_discriminant(self), state); - hash::Hash::hash(__self_0, state) + Generator(d, s, m) => { + d.hash(state); + s.hash(state); + m.hash(state) } - (&RawPtr(ref __self_0),) => { - hash::Hash::hash(&tykind_discriminant(self), state); - hash::Hash::hash(__self_0, state) + GeneratorWitness(g) => g.hash(state), + Tuple(t) => t.hash(state), + Projection(p) => p.hash(state), + Opaque(d, s) => { + d.hash(state); + s.hash(state) } - (&Ref(ref __self_0, ref __self_1, ref __self_2),) => { - hash::Hash::hash(&tykind_discriminant(self), state); - hash::Hash::hash(__self_0, state); - hash::Hash::hash(__self_1, state); - hash::Hash::hash(__self_2, state) + Param(p) => p.hash(state), + Bound(d, b) => { + d.hash(state); + b.hash(state) } - (&FnDef(ref __self_0, ref __self_1),) => { - hash::Hash::hash(&tykind_discriminant(self), state); - hash::Hash::hash(__self_0, state); - hash::Hash::hash(__self_1, state) - } - (&FnPtr(ref __self_0),) => { - hash::Hash::hash(&tykind_discriminant(self), state); - hash::Hash::hash(__self_0, state) - } - (&Dynamic(ref __self_0, ref __self_1, ref repr),) => { - hash::Hash::hash(&tykind_discriminant(self), state); - hash::Hash::hash(__self_0, state); - hash::Hash::hash(__self_1, state); - hash::Hash::hash(repr, state) - } - (&Closure(ref __self_0, ref __self_1),) => { - hash::Hash::hash(&tykind_discriminant(self), state); - hash::Hash::hash(__self_0, state); - hash::Hash::hash(__self_1, state) - } - (&Generator(ref __self_0, ref __self_1, ref __self_2),) => { - hash::Hash::hash(&tykind_discriminant(self), state); - hash::Hash::hash(__self_0, state); - hash::Hash::hash(__self_1, state); - hash::Hash::hash(__self_2, state) - } - (&GeneratorWitness(ref __self_0),) => { - hash::Hash::hash(&tykind_discriminant(self), state); - hash::Hash::hash(__self_0, state) - } - (&Tuple(ref __self_0),) => { - hash::Hash::hash(&tykind_discriminant(self), state); - hash::Hash::hash(__self_0, state) - } - (&Projection(ref __self_0),) => { - hash::Hash::hash(&tykind_discriminant(self), state); - hash::Hash::hash(__self_0, state) - } - (&Opaque(ref __self_0, ref __self_1),) => { - hash::Hash::hash(&tykind_discriminant(self), state); - hash::Hash::hash(__self_0, state); - hash::Hash::hash(__self_1, state) - } - (&Param(ref __self_0),) => { - hash::Hash::hash(&tykind_discriminant(self), state); - hash::Hash::hash(__self_0, state) - } - (&Bound(ref __self_0, ref __self_1),) => { - hash::Hash::hash(&tykind_discriminant(self), state); - hash::Hash::hash(__self_0, state); - hash::Hash::hash(__self_1, state) - } - (&Placeholder(ref __self_0),) => { - hash::Hash::hash(&tykind_discriminant(self), state); - hash::Hash::hash(__self_0, state) - } - (&Infer(ref __self_0),) => { - hash::Hash::hash(&tykind_discriminant(self), state); - hash::Hash::hash(__self_0, state) - } - (&Error(ref __self_0),) => { - hash::Hash::hash(&tykind_discriminant(self), state); - hash::Hash::hash(__self_0, state) - } - _ => hash::Hash::hash(&tykind_discriminant(self), state), + Placeholder(p) => p.hash(state), + Infer(t) => t.hash(state), + Error(e) => e.hash(state), + Bool | Char | Str | Never => (), } } } @@ -588,37 +453,34 @@ impl hash::Hash for TyKind { // This is manually implemented because a derive would require `I: Debug` impl fmt::Debug for TyKind { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - use std::fmt::*; match self { - Bool => Formatter::write_str(f, "Bool"), - Char => Formatter::write_str(f, "Char"), - Int(f0) => Formatter::debug_tuple_field1_finish(f, "Int", f0), - Uint(f0) => Formatter::debug_tuple_field1_finish(f, "Uint", f0), - Float(f0) => Formatter::debug_tuple_field1_finish(f, "Float", f0), - Adt(f0, f1) => Formatter::debug_tuple_field2_finish(f, "Adt", f0, f1), - Foreign(f0) => Formatter::debug_tuple_field1_finish(f, "Foreign", f0), - Str => Formatter::write_str(f, "Str"), - Array(f0, f1) => Formatter::debug_tuple_field2_finish(f, "Array", f0, f1), - Slice(f0) => Formatter::debug_tuple_field1_finish(f, "Slice", f0), - RawPtr(f0) => Formatter::debug_tuple_field1_finish(f, "RawPtr", f0), - Ref(f0, f1, f2) => Formatter::debug_tuple_field3_finish(f, "Ref", f0, f1, f2), - FnDef(f0, f1) => Formatter::debug_tuple_field2_finish(f, "FnDef", f0, f1), - FnPtr(f0) => Formatter::debug_tuple_field1_finish(f, "FnPtr", f0), - Dynamic(f0, f1, f2) => Formatter::debug_tuple_field3_finish(f, "Dynamic", f0, f1, f2), - Closure(f0, f1) => Formatter::debug_tuple_field2_finish(f, "Closure", f0, f1), - Generator(f0, f1, f2) => { - Formatter::debug_tuple_field3_finish(f, "Generator", f0, f1, f2) - } - GeneratorWitness(f0) => Formatter::debug_tuple_field1_finish(f, "GeneratorWitness", f0), - Never => Formatter::write_str(f, "Never"), - Tuple(f0) => Formatter::debug_tuple_field1_finish(f, "Tuple", f0), - Projection(f0) => Formatter::debug_tuple_field1_finish(f, "Projection", f0), - Opaque(f0, f1) => Formatter::debug_tuple_field2_finish(f, "Opaque", f0, f1), - Param(f0) => Formatter::debug_tuple_field1_finish(f, "Param", f0), - Bound(f0, f1) => Formatter::debug_tuple_field2_finish(f, "Bound", f0, f1), - Placeholder(f0) => Formatter::debug_tuple_field1_finish(f, "Placeholder", f0), - Infer(f0) => Formatter::debug_tuple_field1_finish(f, "Infer", f0), - TyKind::Error(f0) => Formatter::debug_tuple_field1_finish(f, "Error", f0), + Bool => f.write_str("Bool"), + Char => f.write_str("Char"), + Int(i) => f.debug_tuple_field1_finish("Int", i), + Uint(u) => f.debug_tuple_field1_finish("Uint", u), + Float(float) => f.debug_tuple_field1_finish("Float", float), + Adt(d, s) => f.debug_tuple_field2_finish("Adt", d, s), + Foreign(d) => f.debug_tuple_field1_finish("Foreign", d), + Str => f.write_str("Str"), + Array(t, c) => f.debug_tuple_field2_finish("Array", t, c), + Slice(t) => f.debug_tuple_field1_finish("Slice", t), + RawPtr(t) => f.debug_tuple_field1_finish("RawPtr", t), + Ref(r, t, m) => f.debug_tuple_field3_finish("Ref", r, t, m), + FnDef(d, s) => f.debug_tuple_field2_finish("FnDef", d, s), + FnPtr(s) => f.debug_tuple_field1_finish("FnPtr", s), + Dynamic(p, r, repr) => f.debug_tuple_field3_finish("Dynamic", p, r, repr), + Closure(d, s) => f.debug_tuple_field2_finish("Closure", d, s), + Generator(d, s, m) => f.debug_tuple_field3_finish("Generator", d, s, m), + GeneratorWitness(g) => f.debug_tuple_field1_finish("GeneratorWitness", g), + Never => f.write_str("Never"), + Tuple(t) => f.debug_tuple_field1_finish("Tuple", t), + Projection(p) => f.debug_tuple_field1_finish("Projection", p), + Opaque(d, s) => f.debug_tuple_field2_finish("Opaque", d, s), + Param(p) => f.debug_tuple_field1_finish("Param", p), + Bound(d, b) => f.debug_tuple_field2_finish("Bound", d, b), + Placeholder(p) => f.debug_tuple_field1_finish("Placeholder", p), + Infer(t) => f.debug_tuple_field1_finish("Infer", t), + TyKind::Error(e) => f.debug_tuple_field1_finish("Error", e), } } } @@ -1091,12 +953,12 @@ where impl Clone for RegionKind { fn clone(&self) -> Self { match self { - ReEarlyBound(a) => ReEarlyBound(a.clone()), - ReLateBound(a, b) => ReLateBound(a.clone(), b.clone()), - ReFree(a) => ReFree(a.clone()), + ReEarlyBound(r) => ReEarlyBound(r.clone()), + ReLateBound(d, r) => ReLateBound(d.clone(), r.clone()), + ReFree(r) => ReFree(r.clone()), ReStatic => ReStatic, - ReVar(a) => ReVar(a.clone()), - RePlaceholder(a) => RePlaceholder(a.clone()), + ReVar(r) => ReVar(r.clone()), + RePlaceholder(r) => RePlaceholder(r.clone()), ReErased => ReErased, } } @@ -1106,29 +968,17 @@ impl Clone for RegionKind { impl PartialEq for RegionKind { #[inline] fn eq(&self, other: &RegionKind) -> bool { - let __self_vi = regionkind_discriminant(self); - let __arg_1_vi = regionkind_discriminant(other); - if __self_vi == __arg_1_vi { - match (&*self, &*other) { - (&ReEarlyBound(ref __self_0), &ReEarlyBound(ref __arg_1_0)) => { - __self_0 == __arg_1_0 - } - ( - &ReLateBound(ref __self_0, ref __self_1), - &ReLateBound(ref __arg_1_0, ref __arg_1_1), - ) => __self_0 == __arg_1_0 && __self_1 == __arg_1_1, - (&ReFree(ref __self_0), &ReFree(ref __arg_1_0)) => __self_0 == __arg_1_0, - (&ReStatic, &ReStatic) => true, - (&ReVar(ref __self_0), &ReVar(ref __arg_1_0)) => __self_0 == __arg_1_0, - (&RePlaceholder(ref __self_0), &RePlaceholder(ref __arg_1_0)) => { - __self_0 == __arg_1_0 - } - (&ReErased, &ReErased) => true, - _ => true, + regionkind_discriminant(self) == regionkind_discriminant(other) + && match (self, other) { + (ReEarlyBound(a_r), ReEarlyBound(b_r)) => a_r == b_r, + (ReLateBound(a_d, a_r), ReLateBound(b_d, b_r)) => a_d == b_d && a_r == b_r, + (ReFree(a_r), ReFree(b_r)) => a_r == b_r, + (ReStatic, ReStatic) => true, + (ReVar(a_r), ReVar(b_r)) => a_r == b_r, + (RePlaceholder(a_r), RePlaceholder(b_r)) => a_r == b_r, + (ReErased, ReErased) => true, + _ => true, // unreachable } - } else { - false - } } } @@ -1139,7 +989,7 @@ impl Eq for RegionKind {} impl PartialOrd for RegionKind { #[inline] fn partial_cmp(&self, other: &RegionKind) -> Option { - Some(Ord::cmp(self, other)) + Some(self.cmp(other)) } } @@ -1147,66 +997,38 @@ impl PartialOrd for RegionKind { impl Ord for RegionKind { #[inline] fn cmp(&self, other: &RegionKind) -> Ordering { - let __self_vi = regionkind_discriminant(self); - let __arg_1_vi = regionkind_discriminant(other); - if __self_vi == __arg_1_vi { - match (&*self, &*other) { - (&ReEarlyBound(ref __self_0), &ReEarlyBound(ref __arg_1_0)) => { - Ord::cmp(__self_0, __arg_1_0) + regionkind_discriminant(self).cmp(®ionkind_discriminant(other)).then_with(|| { + match (self, other) { + (ReEarlyBound(a_r), ReEarlyBound(b_r)) => a_r.cmp(b_r), + (ReLateBound(a_d, a_r), ReLateBound(b_d, b_r)) => { + a_d.cmp(b_d).then_with(|| a_r.cmp(b_r)) } - ( - &ReLateBound(ref __self_0, ref __self_1), - &ReLateBound(ref __arg_1_0, ref __arg_1_1), - ) => match Ord::cmp(__self_0, __arg_1_0) { - Ordering::Equal => Ord::cmp(__self_1, __arg_1_1), - cmp => cmp, - }, - (&ReFree(ref __self_0), &ReFree(ref __arg_1_0)) => Ord::cmp(__self_0, __arg_1_0), - (&ReStatic, &ReStatic) => Ordering::Equal, - (&ReVar(ref __self_0), &ReVar(ref __arg_1_0)) => Ord::cmp(__self_0, __arg_1_0), - (&RePlaceholder(ref __self_0), &RePlaceholder(ref __arg_1_0)) => { - Ord::cmp(__self_0, __arg_1_0) - } - (&ReErased, &ReErased) => Ordering::Equal, - _ => Ordering::Equal, + (ReFree(a_r), ReFree(b_r)) => a_r.cmp(b_r), + (ReStatic, ReStatic) => Ordering::Equal, + (ReVar(a_r), ReVar(b_r)) => a_r.cmp(b_r), + (RePlaceholder(a_r), RePlaceholder(b_r)) => a_r.cmp(b_r), + (ReErased, ReErased) => Ordering::Equal, + _ => Ordering::Equal, // unreachable } - } else { - Ord::cmp(&__self_vi, &__arg_1_vi) - } + }) } } // This is manually implemented because a derive would require `I: Hash` impl hash::Hash for RegionKind { - fn hash<__H: hash::Hasher>(&self, state: &mut __H) -> () { - match (&*self,) { - (&ReEarlyBound(ref __self_0),) => { - hash::Hash::hash(®ionkind_discriminant(self), state); - hash::Hash::hash(__self_0, state) - } - (&ReLateBound(ref __self_0, ref __self_1),) => { - hash::Hash::hash(®ionkind_discriminant(self), state); - hash::Hash::hash(__self_0, state); - hash::Hash::hash(__self_1, state) - } - (&ReFree(ref __self_0),) => { - hash::Hash::hash(®ionkind_discriminant(self), state); - hash::Hash::hash(__self_0, state) - } - (&ReStatic,) => { - hash::Hash::hash(®ionkind_discriminant(self), state); - } - (&ReVar(ref __self_0),) => { - hash::Hash::hash(®ionkind_discriminant(self), state); - hash::Hash::hash(__self_0, state) - } - (&RePlaceholder(ref __self_0),) => { - hash::Hash::hash(®ionkind_discriminant(self), state); - hash::Hash::hash(__self_0, state) - } - (&ReErased,) => { - hash::Hash::hash(®ionkind_discriminant(self), state); + fn hash(&self, state: &mut H) -> () { + regionkind_discriminant(self).hash(state); + match self { + ReEarlyBound(r) => r.hash(state), + ReLateBound(d, r) => { + d.hash(state); + r.hash(state) } + ReFree(r) => r.hash(state), + ReStatic => (), + ReVar(r) => r.hash(state), + RePlaceholder(r) => r.hash(state), + ReErased => (), } } } @@ -1215,21 +1037,21 @@ impl hash::Hash for RegionKind { impl fmt::Debug for RegionKind { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - ReEarlyBound(ref data) => write!(f, "ReEarlyBound({:?})", data), + ReEarlyBound(data) => write!(f, "ReEarlyBound({:?})", data), - ReLateBound(binder_id, ref bound_region) => { + ReLateBound(binder_id, bound_region) => { write!(f, "ReLateBound({:?}, {:?})", binder_id, bound_region) } - ReFree(ref fr) => fr.fmt(f), + ReFree(fr) => fr.fmt(f), - ReStatic => write!(f, "ReStatic"), + ReStatic => f.write_str("ReStatic"), - ReVar(ref vid) => vid.fmt(f), + ReVar(vid) => vid.fmt(f), RePlaceholder(placeholder) => write!(f, "RePlaceholder({:?})", placeholder), - ReErased => write!(f, "ReErased"), + ReErased => f.write_str("ReErased"), } } } @@ -1317,18 +1139,18 @@ where ReErased | ReStatic => { // No variant fields to hash for these ... } - ReLateBound(db, br) => { - db.hash_stable(hcx, hasher); - br.hash_stable(hcx, hasher); + ReLateBound(d, r) => { + d.hash_stable(hcx, hasher); + r.hash_stable(hcx, hasher); } - ReEarlyBound(eb) => { - eb.hash_stable(hcx, hasher); + ReEarlyBound(r) => { + r.hash_stable(hcx, hasher); } - ReFree(ref free_region) => { - free_region.hash_stable(hcx, hasher); + ReFree(r) => { + r.hash_stable(hcx, hasher); } - RePlaceholder(p) => { - p.hash_stable(hcx, hasher); + RePlaceholder(r) => { + r.hash_stable(hcx, hasher); } ReVar(_) => { panic!("region variables should not be hashed: {self:?}") From e12d22239aeef111b92a0d7d0ed5ca1c8872bab5 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Tue, 6 Dec 2022 12:20:02 +0000 Subject: [PATCH 090/115] Add debug asserts to hand-implemented `Ord`/`Eq` impls --- compiler/rustc_type_ir/src/sty.rs | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_type_ir/src/sty.rs b/compiler/rustc_type_ir/src/sty.rs index a6537f41d1e5..3ed616d709b1 100644 --- a/compiler/rustc_type_ir/src/sty.rs +++ b/compiler/rustc_type_ir/src/sty.rs @@ -330,7 +330,14 @@ impl PartialEq for TyKind { (Placeholder(a_p), Placeholder(b_p)) => a_p == b_p, (Infer(a_t), Infer(b_t)) => a_t == b_t, (Error(a_e), Error(b_e)) => a_e == b_e, - _ => true, // unreachable + (Bool, Bool) | (Char, Char) | (Str, Str) | (Never, Never) => true, + _ => { + debug_assert!( + false, + "This branch must be unreachable, maybe the match is missing an arm? self = self = {self:?}, other = {other:?}" + ); + true + } } } } @@ -381,7 +388,11 @@ impl Ord for TyKind { (Placeholder(a_p), Placeholder(b_p)) => a_p.cmp(b_p), (Infer(a_t), Infer(b_t)) => a_t.cmp(b_t), (Error(a_e), Error(b_e)) => a_e.cmp(b_e), - _ => Ordering::Equal, // unreachable + (Bool, Bool) | (Char, Char) | (Str, Str) | (Never, Never) => Ordering::Equal, + _ => { + debug_assert!(false, "This branch must be unreachable, maybe the match is missing an arm? self = self = {self:?}, other = {other:?}"); + Ordering::Equal + } } }) } @@ -977,7 +988,13 @@ impl PartialEq for RegionKind { (ReVar(a_r), ReVar(b_r)) => a_r == b_r, (RePlaceholder(a_r), RePlaceholder(b_r)) => a_r == b_r, (ReErased, ReErased) => true, - _ => true, // unreachable + _ => { + debug_assert!( + false, + "This branch must be unreachable, maybe the match is missing an arm? self = self = {self:?}, other = {other:?}" + ); + true + } } } } @@ -1008,7 +1025,10 @@ impl Ord for RegionKind { (ReVar(a_r), ReVar(b_r)) => a_r.cmp(b_r), (RePlaceholder(a_r), RePlaceholder(b_r)) => a_r.cmp(b_r), (ReErased, ReErased) => Ordering::Equal, - _ => Ordering::Equal, // unreachable + _ => { + debug_assert!(false, "This branch must be unreachable, maybe the match is missing an arm? self = self = {self:?}, other = {other:?}"); + Ordering::Equal + } } }) } From 12ce0c2a891d872c8fb32eb17b6258ea99a971ad Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Tue, 6 Dec 2022 13:45:11 +0000 Subject: [PATCH 091/115] Remove outdated syntax from trait alias pretty printing --- .../rustc_ast_pretty/src/pprust/state/item.rs | 15 ++------------- compiler/rustc_hir_pretty/src/lib.rs | 13 +------------ 2 files changed, 3 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs index e68a7b3f202b..5b6a07721e2b 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs @@ -348,21 +348,10 @@ impl<'a> State<'a> { self.head(visibility_qualified(&item.vis, "trait")); self.print_ident(item.ident); self.print_generic_params(&generics.params); - let mut real_bounds = Vec::with_capacity(bounds.len()); - // FIXME(durka) this seems to be some quite outdated syntax - for b in bounds.iter() { - if let GenericBound::Trait(ptr, ast::TraitBoundModifier::Maybe) = b { - self.space(); - self.word_space("for ?"); - self.print_trait_ref(&ptr.trait_ref); - } else { - real_bounds.push(b.clone()); - } - } self.nbsp(); - if !real_bounds.is_empty() { + if !bounds.is_empty() { self.word_nbsp("="); - self.print_type_bounds(&real_bounds); + self.print_type_bounds(&bounds); } self.print_where_clause(&generics.where_clause); self.word(";"); diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 3791b2c8661a..94bab9f339d8 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -695,19 +695,8 @@ impl<'a> State<'a> { self.head("trait"); self.print_ident(item.ident); self.print_generic_params(generics.params); - let mut real_bounds = Vec::with_capacity(bounds.len()); - // FIXME(durka) this seems to be some quite outdated syntax - for b in bounds { - if let GenericBound::Trait(ptr, hir::TraitBoundModifier::Maybe) = b { - self.space(); - self.word_space("for ?"); - self.print_trait_ref(&ptr.trait_ref); - } else { - real_bounds.push(b); - } - } self.nbsp(); - self.print_bounds("=", real_bounds); + self.print_bounds("=", bounds); self.print_where_clause(generics); self.word(";"); self.end(); // end inner head-block From c75817fb1bba30e915fc856b21a571d01411ac45 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Fri, 2 Dec 2022 19:07:57 +0000 Subject: [PATCH 092/115] `rustc_borrowck`: remove `ref` patterns --- compiler/rustc_borrowck/src/borrow_set.rs | 8 +-- compiler/rustc_borrowck/src/dataflow.rs | 10 +-- .../src/diagnostics/bound_region_errors.rs | 12 ++-- .../src/diagnostics/conflict_errors.rs | 16 ++--- .../src/diagnostics/explain_borrow.rs | 23 +++---- .../rustc_borrowck/src/diagnostics/mod.rs | 47 ++++++------- .../src/diagnostics/mutability_errors.rs | 6 +- .../src/diagnostics/region_errors.rs | 2 +- .../src/diagnostics/region_name.rs | 2 +- compiler/rustc_borrowck/src/invalidation.rs | 65 +++++++++-------- compiler/rustc_borrowck/src/lib.rs | 69 ++++++++++--------- compiler/rustc_borrowck/src/type_check/mod.rs | 39 +++++------ .../rustc_borrowck/src/universal_regions.rs | 6 +- 13 files changed, 145 insertions(+), 160 deletions(-) diff --git a/compiler/rustc_borrowck/src/borrow_set.rs b/compiler/rustc_borrowck/src/borrow_set.rs index 563ff056ae46..5bb92a358261 100644 --- a/compiler/rustc_borrowck/src/borrow_set.rs +++ b/compiler/rustc_borrowck/src/borrow_set.rs @@ -198,7 +198,7 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'tcx> { rvalue: &mir::Rvalue<'tcx>, location: mir::Location, ) { - if let mir::Rvalue::Ref(region, kind, ref borrowed_place) = *rvalue { + if let &mir::Rvalue::Ref(region, kind, borrowed_place) = rvalue { if borrowed_place.ignore_borrow(self.tcx, self.body, &self.locals_state_at_exit) { debug!("ignoring_borrow of {:?}", borrowed_place); return; @@ -211,7 +211,7 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'tcx> { region, reserve_location: location, activation_location: TwoPhaseActivation::NotTwoPhase, - borrowed_place: *borrowed_place, + borrowed_place, assigned_place: *assigned_place, }; let (idx, _) = self.location_map.insert_full(location, borrow); @@ -273,14 +273,14 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'tcx> { } fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'tcx>, location: mir::Location) { - if let mir::Rvalue::Ref(region, kind, ref place) = *rvalue { + if let &mir::Rvalue::Ref(region, kind, place) = rvalue { // double-check that we already registered a BorrowData for this let borrow_data = &self.location_map[&location]; assert_eq!(borrow_data.reserve_location, location); assert_eq!(borrow_data.kind, kind); assert_eq!(borrow_data.region, region.to_region_vid()); - assert_eq!(borrow_data.borrowed_place, *place); + assert_eq!(borrow_data.borrowed_place, place); } self.super_rvalue(rvalue, location) diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs index 8070c0e6710e..f825b1d8f70e 100644 --- a/compiler/rustc_borrowck/src/dataflow.rs +++ b/compiler/rustc_borrowck/src/dataflow.rs @@ -358,9 +358,9 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> { stmt: &mir::Statement<'tcx>, location: Location, ) { - match stmt.kind { - mir::StatementKind::Assign(box (lhs, ref rhs)) => { - if let mir::Rvalue::Ref(_, _, place) = *rhs { + match &stmt.kind { + mir::StatementKind::Assign(box (lhs, rhs)) => { + if let mir::Rvalue::Ref(_, _, place) = rhs { if place.ignore_borrow( self.tcx, self.body, @@ -377,13 +377,13 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> { // Make sure there are no remaining borrows for variables // that are assigned over. - self.kill_borrows_on_place(trans, lhs); + self.kill_borrows_on_place(trans, *lhs); } mir::StatementKind::StorageDead(local) => { // Make sure there are no remaining borrows for locals that // are gone out of scope. - self.kill_borrows_on_place(trans, Place::from(local)); + self.kill_borrows_on_place(trans, Place::from(*local)); } mir::StatementKind::FakeRead(..) diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs index e05566dc2c74..1550958ab8ee 100644 --- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs @@ -243,9 +243,9 @@ impl<'tcx> TypeOpInfo<'tcx> for PredicateQuery<'tcx> { placeholder_region: ty::Region<'tcx>, error_region: Option>, ) -> Option> { - let (ref infcx, key, _) = + let (infcx, key, _) = mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query); - let ocx = ObligationCtxt::new(infcx); + let ocx = ObligationCtxt::new(&infcx); type_op_prove_predicate_with_cause(&ocx, key, cause); try_extract_error_from_fulfill_cx(&ocx, placeholder_region, error_region) } @@ -284,9 +284,9 @@ where placeholder_region: ty::Region<'tcx>, error_region: Option>, ) -> Option> { - let (ref infcx, key, _) = + let (infcx, key, _) = mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query); - let ocx = ObligationCtxt::new(infcx); + let ocx = ObligationCtxt::new(&infcx); // FIXME(lqd): Unify and de-duplicate the following with the actual // `rustc_traits::type_op::type_op_normalize` query to allow the span we need in the @@ -328,9 +328,9 @@ impl<'tcx> TypeOpInfo<'tcx> for AscribeUserTypeQuery<'tcx> { placeholder_region: ty::Region<'tcx>, error_region: Option>, ) -> Option> { - let (ref infcx, key, _) = + let (infcx, key, _) = mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query); - let ocx = ObligationCtxt::new(infcx); + let ocx = ObligationCtxt::new(&infcx); type_op_ascribe_user_type_with_span(&ocx, key, Some(cause.span)).ok()?; try_extract_error_from_fulfill_cx(&ocx, placeholder_region, error_region) } diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index d221da5c17ed..5e3745f17353 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -265,7 +265,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { DescribePlaceOpt { including_downcast: true, including_tuple_field: true }, ); let note_msg = match opt_name { - Some(ref name) => format!("`{}`", name), + Some(name) => format!("`{}`", name), None => "value".to_owned(), }; if self.suggest_borrow_fn_like(&mut err, ty, &move_site_vec, ¬e_msg) { @@ -1417,7 +1417,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // then just use the normal error. The closure isn't escaping // and `move` will not help here. ( - Some(ref name), + Some(name), BorrowExplanation::MustBeValidFor { category: category @ (ConstraintCategory::Return(_) @@ -1438,7 +1438,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { &format!("`{}`", name), ), ( - ref name, + name, BorrowExplanation::MustBeValidFor { category: ConstraintCategory::Assignment, from_closure: false, @@ -1450,7 +1450,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { span, .. }, - ) => self.report_escaping_data(borrow_span, name, upvar_span, upvar_name, span), + ) => self.report_escaping_data(borrow_span, &name, upvar_span, upvar_name, span), (Some(name), explanation) => self.report_local_value_does_not_live_long_enough( location, &name, @@ -2452,7 +2452,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // and it'll make sense. let location = borrow.reserve_location; debug!("annotate_argument_and_return_for_borrow: location={:?}", location); - if let Some(&Statement { kind: StatementKind::Assign(box (ref reservation, _)), .. }) = + if let Some(Statement { kind: StatementKind::Assign(box (reservation, _)), .. }) = &self.body[location.block].statements.get(location.statement_index) { debug!("annotate_argument_and_return_for_borrow: reservation={:?}", reservation); @@ -2480,8 +2480,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // Check if our `target` was captured by a closure. if let Rvalue::Aggregate( box AggregateKind::Closure(def_id, substs), - ref operands, - ) = *rvalue + operands, + ) = rvalue { for operand in operands { let (Operand::Copy(assigned_from) | Operand::Move(assigned_from)) = operand else { @@ -2505,7 +2505,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // into a place then we should annotate the closure in // case it ends up being assigned into the return place. annotated_closure = - self.annotate_fn_sig(def_id, substs.as_closure().sig()); + self.annotate_fn_sig(*def_id, substs.as_closure().sig()); debug!( "annotate_argument_and_return_for_borrow: \ annotated_closure={:?} assigned_from_local={:?} \ diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index 582d683dd359..304683618d83 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -469,8 +469,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } else if self.was_captured_by_trait_object(borrow) { LaterUseKind::TraitCapture } else if location.statement_index == block.statements.len() { - if let TerminatorKind::Call { ref func, from_hir_call: true, .. } = - block.terminator().kind + if let TerminatorKind::Call { func, from_hir_call: true, .. } = + &block.terminator().kind { // Just point to the function, to reduce the chance of overlapping spans. let function_span = match func { @@ -515,19 +515,16 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // will only ever have one item at any given time, but by using a vector, we can pop from // it which simplifies the termination logic. let mut queue = vec![location]; - let mut target = if let Some(&Statement { - kind: StatementKind::Assign(box (ref place, _)), - .. - }) = stmt - { - if let Some(local) = place.as_local() { - local + let mut target = + if let Some(Statement { kind: StatementKind::Assign(box (place, _)), .. }) = stmt { + if let Some(local) = place.as_local() { + local + } else { + return false; + } } else { return false; - } - } else { - return false; - }; + }; debug!("was_captured_by_trait: target={:?} queue={:?}", target, queue); while let Some(current_location) = queue.pop() { diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 86c5d9cfa812..4e2271a30672 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -78,7 +78,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if let StatementKind::Assign(box (into, Rvalue::Use(from))) = &stmt.kind { debug!("add_fnonce_closure_note: into={:?} from={:?}", into, from); match from { - Operand::Copy(ref place) | Operand::Move(ref place) + Operand::Copy(place) | Operand::Move(place) if target == place.local_or_deref_local() => { target = into.local_or_deref_local() @@ -101,7 +101,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { debug!("add_moved_or_invoked_closure_note: id={:?}", id); if Some(self.infcx.tcx.parent(id)) == self.infcx.tcx.lang_items().fn_once_trait() { let closure = match args.first() { - Some(Operand::Copy(ref place)) | Some(Operand::Move(ref place)) + Some(Operand::Copy(place) | Operand::Move(place)) if target == place.local_or_deref_local() => { place.local_or_deref_local().unwrap() @@ -439,9 +439,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if !is_terminator { continue; } else if let Some(Terminator { - kind: TerminatorKind::Call { ref func, from_hir_call: false, .. }, + kind: TerminatorKind::Call { func, from_hir_call: false, .. }, .. - }) = bbd.terminator + }) = &bbd.terminator { if let Some(source) = BorrowedContentSource::from_call(func.ty(self.body, tcx), tcx) @@ -811,33 +811,30 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { }; debug!("move_spans: moved_place={:?} location={:?} stmt={:?}", moved_place, location, stmt); - if let StatementKind::Assign(box (_, Rvalue::Aggregate(ref kind, ref places))) = stmt.kind { - match **kind { - AggregateKind::Closure(def_id, _) | AggregateKind::Generator(def_id, _, _) => { - debug!("move_spans: def_id={:?} places={:?}", def_id, places); - if let Some((args_span, generator_kind, capture_kind_span, path_span)) = - self.closure_span(def_id, moved_place, places) - { - return ClosureUse { - generator_kind, - args_span, - capture_kind_span, - path_span, - }; - } - } - _ => {} + if let StatementKind::Assign(box (_, Rvalue::Aggregate(kind, places))) = &stmt.kind + && let AggregateKind::Closure(def_id, _) | AggregateKind::Generator(def_id, _, _) = **kind + { + debug!("move_spans: def_id={:?} places={:?}", def_id, places); + if let Some((args_span, generator_kind, capture_kind_span, path_span)) = + self.closure_span(def_id, moved_place, places) + { + return ClosureUse { + generator_kind, + args_span, + capture_kind_span, + path_span, + }; } } // StatementKind::FakeRead only contains a def_id if they are introduced as a result // of pattern matching within a closure. - if let StatementKind::FakeRead(box (cause, ref place)) = stmt.kind { + if let StatementKind::FakeRead(box (cause, place)) = stmt.kind { match cause { FakeReadCause::ForMatchedPlace(Some(closure_def_id)) | FakeReadCause::ForLet(Some(closure_def_id)) => { debug!("move_spans: def_id={:?} place={:?}", closure_def_id, place); - let places = &[Operand::Move(*place)]; + let places = &[Operand::Move(place)]; if let Some((args_span, generator_kind, capture_kind_span, path_span)) = self.closure_span(closure_def_id, moved_place, places) { @@ -924,7 +921,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { debug!("borrow_spans: use_span={:?} location={:?}", use_span, location); let target = match self.body[location.block].statements.get(location.statement_index) { - Some(&Statement { kind: StatementKind::Assign(box (ref place, _)), .. }) => { + Some(Statement { kind: StatementKind::Assign(box (place, _)), .. }) => { if let Some(local) = place.as_local() { local } else { @@ -940,9 +937,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } for stmt in &self.body[location.block].statements[location.statement_index + 1..] { - if let StatementKind::Assign(box (_, Rvalue::Aggregate(ref kind, ref places))) = - stmt.kind - { + if let StatementKind::Assign(box (_, Rvalue::Aggregate(kind, places))) = &stmt.kind { let (&def_id, is_generator) = match kind { box AggregateKind::Closure(def_id, _) => (def_id, false), box AggregateKind::Generator(def_id, _, _) => (def_id, true), diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 0cf66e41001f..3319a80681fd 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -219,8 +219,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { PlaceRef { local, projection: - &[ - ref proj_base @ .., + [ + proj_base @ .., ProjectionElem::Deref, ProjectionElem::Field(field, _), ProjectionElem::Deref, @@ -231,7 +231,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { if let Some(span) = get_mut_span_in_struct_field( self.infcx.tcx, Place::ty_from(local, proj_base, self.body, self.infcx.tcx).ty, - field, + *field, ) { err.span_suggestion_verbose( span, diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 7aa099433a76..9bc2e79e29bc 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -921,7 +921,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } } hir::ExprKind::Block(blk, _) => { - if let Some(ref expr) = blk.expr { + if let Some(expr) = blk.expr { // only when the block is a closure if let hir::ExprKind::Closure(hir::Closure { capture_clause: hir::CaptureBy::Ref, diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index 39173e70acfe..171e62d91e13 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -254,7 +254,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { .or_else(|| self.give_name_if_anonymous_region_appears_in_impl_signature(fr)) .or_else(|| self.give_name_if_anonymous_region_appears_in_arg_position_impl_trait(fr)); - if let Some(ref value) = value { + if let Some(value) = &value { self.region_names.try_borrow_mut().unwrap().insert(fr, value.clone()); } diff --git a/compiler/rustc_borrowck/src/invalidation.rs b/compiler/rustc_borrowck/src/invalidation.rs index f5317a143aed..f66a7ab3c031 100644 --- a/compiler/rustc_borrowck/src/invalidation.rs +++ b/compiler/rustc_borrowck/src/invalidation.rs @@ -69,9 +69,9 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> { self.consume_operand(location, op); } StatementKind::Intrinsic(box NonDivergingIntrinsic::CopyNonOverlapping(mir::CopyNonOverlapping { - ref src, - ref dst, - ref count, + src, + dst, + count, })) => { self.consume_operand(location, src); self.consume_operand(location, dst); @@ -106,7 +106,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> { self.check_activations(location); match &terminator.kind { - TerminatorKind::SwitchInt { ref discr, switch_ty: _, targets: _ } => { + TerminatorKind::SwitchInt { discr, switch_ty: _, targets: _ } => { self.consume_operand(location, discr); } TerminatorKind::Drop { place: drop_place, target: _, unwind: _ } => { @@ -119,7 +119,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> { } TerminatorKind::DropAndReplace { place: drop_place, - value: ref new_value, + value: new_value, target: _, unwind: _, } => { @@ -127,8 +127,8 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> { self.consume_operand(location, new_value); } TerminatorKind::Call { - ref func, - ref args, + func, + args, destination, target: _, cleanup: _, @@ -141,15 +141,15 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> { } self.mutate_place(location, *destination, Deep); } - TerminatorKind::Assert { ref cond, expected: _, ref msg, target: _, cleanup: _ } => { + TerminatorKind::Assert { cond, expected: _, msg, target: _, cleanup: _ } => { self.consume_operand(location, cond); use rustc_middle::mir::AssertKind; - if let AssertKind::BoundsCheck { ref len, ref index } = *msg { + if let AssertKind::BoundsCheck { len, index } = msg { self.consume_operand(location, len); self.consume_operand(location, index); } } - TerminatorKind::Yield { ref value, resume, resume_arg, drop: _ } => { + TerminatorKind::Yield { value, resume, resume_arg, drop: _ } => { self.consume_operand(location, value); // Invalidate all borrows of local places @@ -175,25 +175,25 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> { } TerminatorKind::InlineAsm { template: _, - ref operands, + operands, options: _, line_spans: _, destination: _, cleanup: _, } => { for op in operands { - match *op { - InlineAsmOperand::In { reg: _, ref value } => { + match op { + InlineAsmOperand::In { reg: _, value } => { self.consume_operand(location, value); } InlineAsmOperand::Out { reg: _, late: _, place, .. } => { - if let Some(place) = place { + if let &Some(place) = place { self.mutate_place(location, place, Shallow(None)); } } - InlineAsmOperand::InOut { reg: _, late: _, ref in_value, out_place } => { + InlineAsmOperand::InOut { reg: _, late: _, in_value, out_place } => { self.consume_operand(location, in_value); - if let Some(out_place) = out_place { + if let &Some(out_place) = out_place { self.mutate_place(location, out_place, Shallow(None)); } } @@ -252,8 +252,8 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> { // Simulates consumption of an rvalue fn consume_rvalue(&mut self, location: Location, rvalue: &Rvalue<'tcx>) { - match *rvalue { - Rvalue::Ref(_ /*rgn*/, bk, place) => { + match rvalue { + &Rvalue::Ref(_ /*rgn*/, bk, place) => { let access_kind = match bk { BorrowKind::Shallow => { (Shallow(Some(ArtificialField::ShallowBorrow)), Read(ReadKind::Borrow(bk))) @@ -272,7 +272,7 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> { self.access_place(location, place, access_kind, LocalMutationIsAllowed::No); } - Rvalue::AddressOf(mutability, place) => { + &Rvalue::AddressOf(mutability, place) => { let access_kind = match mutability { Mutability::Mut => ( Deep, @@ -288,20 +288,19 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> { Rvalue::ThreadLocalRef(_) => {} - Rvalue::Use(ref operand) - | Rvalue::Repeat(ref operand, _) - | Rvalue::UnaryOp(_ /*un_op*/, ref operand) - | Rvalue::Cast(_ /*cast_kind*/, ref operand, _ /*ty*/) - | Rvalue::ShallowInitBox(ref operand, _ /*ty*/) => { - self.consume_operand(location, operand) - } - Rvalue::CopyForDeref(ref place) => { - let op = &Operand::Copy(*place); + Rvalue::Use(operand) + | Rvalue::Repeat(operand, _) + | Rvalue::UnaryOp(_ /*un_op*/, operand) + | Rvalue::Cast(_ /*cast_kind*/, operand, _ /*ty*/) + | Rvalue::ShallowInitBox(operand, _ /*ty*/) => self.consume_operand(location, operand), + + &Rvalue::CopyForDeref(place) => { + let op = &Operand::Copy(place); self.consume_operand(location, op); } - Rvalue::Len(place) | Rvalue::Discriminant(place) => { - let af = match *rvalue { + &(Rvalue::Len(place) | Rvalue::Discriminant(place)) => { + let af = match rvalue { Rvalue::Len(..) => Some(ArtificialField::ArrayLength), Rvalue::Discriminant(..) => None, _ => unreachable!(), @@ -314,15 +313,15 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> { ); } - Rvalue::BinaryOp(_bin_op, box (ref operand1, ref operand2)) - | Rvalue::CheckedBinaryOp(_bin_op, box (ref operand1, ref operand2)) => { + Rvalue::BinaryOp(_bin_op, box (operand1, operand2)) + | Rvalue::CheckedBinaryOp(_bin_op, box (operand1, operand2)) => { self.consume_operand(location, operand1); self.consume_operand(location, operand2); } Rvalue::NullaryOp(_op, _ty) => {} - Rvalue::Aggregate(_, ref operands) => { + Rvalue::Aggregate(_, operands) => { for operand in operands { self.consume_operand(location, operand); } diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 4d87ecf5e44b..74b4e4a0cabd 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -578,12 +578,12 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx self.check_activations(location, span, flow_state); match &stmt.kind { - StatementKind::Assign(box (lhs, ref rhs)) => { + StatementKind::Assign(box (lhs, rhs)) => { self.consume_rvalue(location, (rhs, span), flow_state); self.mutate_place(location, (*lhs, span), Shallow(None), flow_state); } - StatementKind::FakeRead(box (_, ref place)) => { + StatementKind::FakeRead(box (_, place)) => { // Read for match doesn't access any memory and is used to // assert that a place is safe and live. So we don't have to // do any checks here. @@ -601,7 +601,7 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx flow_state, ); } - StatementKind::Intrinsic(box ref kind) => match kind { + StatementKind::Intrinsic(box kind) => match kind { NonDivergingIntrinsic::Assume(op) => self.consume_operand(location, (op, span), flow_state), NonDivergingIntrinsic::CopyNonOverlapping(..) => span_bug!( span, @@ -643,8 +643,8 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx self.check_activations(loc, span, flow_state); - match term.kind { - TerminatorKind::SwitchInt { ref discr, switch_ty: _, targets: _ } => { + match &term.kind { + TerminatorKind::SwitchInt { discr, switch_ty: _, targets: _ } => { self.consume_operand(loc, (discr, span), flow_state); } TerminatorKind::Drop { place, target: _, unwind: _ } => { @@ -656,7 +656,7 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx self.access_place( loc, - (place, span), + (*place, span), (AccessDepth::Drop, Write(WriteKind::StorageDeadOrDrop)), LocalMutationIsAllowed::Yes, flow_state, @@ -664,16 +664,16 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx } TerminatorKind::DropAndReplace { place: drop_place, - value: ref new_value, + value: new_value, target: _, unwind: _, } => { - self.mutate_place(loc, (drop_place, span), Deep, flow_state); + self.mutate_place(loc, (*drop_place, span), Deep, flow_state); self.consume_operand(loc, (new_value, span), flow_state); } TerminatorKind::Call { - ref func, - ref args, + func, + args, destination, target: _, cleanup: _, @@ -684,43 +684,43 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx for arg in args { self.consume_operand(loc, (arg, span), flow_state); } - self.mutate_place(loc, (destination, span), Deep, flow_state); + self.mutate_place(loc, (*destination, span), Deep, flow_state); } - TerminatorKind::Assert { ref cond, expected: _, ref msg, target: _, cleanup: _ } => { + TerminatorKind::Assert { cond, expected: _, msg, target: _, cleanup: _ } => { self.consume_operand(loc, (cond, span), flow_state); use rustc_middle::mir::AssertKind; - if let AssertKind::BoundsCheck { ref len, ref index } = *msg { + if let AssertKind::BoundsCheck { len, index } = msg { self.consume_operand(loc, (len, span), flow_state); self.consume_operand(loc, (index, span), flow_state); } } - TerminatorKind::Yield { ref value, resume: _, resume_arg, drop: _ } => { + TerminatorKind::Yield { value, resume: _, resume_arg, drop: _ } => { self.consume_operand(loc, (value, span), flow_state); - self.mutate_place(loc, (resume_arg, span), Deep, flow_state); + self.mutate_place(loc, (*resume_arg, span), Deep, flow_state); } TerminatorKind::InlineAsm { template: _, - ref operands, + operands, options: _, line_spans: _, destination: _, cleanup: _, } => { for op in operands { - match *op { - InlineAsmOperand::In { reg: _, ref value } => { + match op { + InlineAsmOperand::In { reg: _, value } => { self.consume_operand(loc, (value, span), flow_state); } InlineAsmOperand::Out { reg: _, late: _, place, .. } => { if let Some(place) = place { - self.mutate_place(loc, (place, span), Shallow(None), flow_state); + self.mutate_place(loc, (*place, span), Shallow(None), flow_state); } } - InlineAsmOperand::InOut { reg: _, late: _, ref in_value, out_place } => { + InlineAsmOperand::InOut { reg: _, late: _, in_value, out_place } => { self.consume_operand(loc, (in_value, span), flow_state); - if let Some(out_place) = out_place { + if let &Some(out_place) = out_place { self.mutate_place( loc, (out_place, span), @@ -1164,8 +1164,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { (rvalue, span): (&'cx Rvalue<'tcx>, Span), flow_state: &Flows<'cx, 'tcx>, ) { - match *rvalue { - Rvalue::Ref(_ /*rgn*/, bk, place) => { + match rvalue { + &Rvalue::Ref(_ /*rgn*/, bk, place) => { let access_kind = match bk { BorrowKind::Shallow => { (Shallow(Some(ArtificialField::ShallowBorrow)), Read(ReadKind::Borrow(bk))) @@ -1203,7 +1203,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ); } - Rvalue::AddressOf(mutability, place) => { + &Rvalue::AddressOf(mutability, place) => { let access_kind = match mutability { Mutability::Mut => ( Deep, @@ -1232,14 +1232,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { Rvalue::ThreadLocalRef(_) => {} - Rvalue::Use(ref operand) - | Rvalue::Repeat(ref operand, _) - | Rvalue::UnaryOp(_ /*un_op*/, ref operand) - | Rvalue::Cast(_ /*cast_kind*/, ref operand, _ /*ty*/) - | Rvalue::ShallowInitBox(ref operand, _ /*ty*/) => { + Rvalue::Use(operand) + | Rvalue::Repeat(operand, _) + | Rvalue::UnaryOp(_ /*un_op*/, operand) + | Rvalue::Cast(_ /*cast_kind*/, operand, _ /*ty*/) + | Rvalue::ShallowInitBox(operand, _ /*ty*/) => { self.consume_operand(location, (operand, span), flow_state) } - Rvalue::CopyForDeref(place) => { + + &Rvalue::CopyForDeref(place) => { self.access_place( location, (place, span), @@ -1257,7 +1258,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ); } - Rvalue::Len(place) | Rvalue::Discriminant(place) => { + &(Rvalue::Len(place) | Rvalue::Discriminant(place)) => { let af = match *rvalue { Rvalue::Len(..) => Some(ArtificialField::ArrayLength), Rvalue::Discriminant(..) => None, @@ -1278,8 +1279,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ); } - Rvalue::BinaryOp(_bin_op, box (ref operand1, ref operand2)) - | Rvalue::CheckedBinaryOp(_bin_op, box (ref operand1, ref operand2)) => { + Rvalue::BinaryOp(_bin_op, box (operand1, operand2)) + | Rvalue::CheckedBinaryOp(_bin_op, box (operand1, operand2)) => { self.consume_operand(location, (operand1, span), flow_state); self.consume_operand(location, (operand2, span), flow_state); } @@ -1288,7 +1289,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // nullary ops take no dynamic input; no borrowck effect. } - Rvalue::Aggregate(ref aggregate_kind, ref operands) => { + Rvalue::Aggregate(aggregate_kind, operands) => { // We need to report back the list of mutable upvars that were // moved into the closure and subsequently used by the closure, // in order to populate our used_mut set. diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 18e3cbbb86a0..6d4ec6b726eb 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1189,8 +1189,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { fn check_stmt(&mut self, body: &Body<'tcx>, stmt: &Statement<'tcx>, location: Location) { let tcx = self.tcx(); debug!("stmt kind: {:?}", stmt.kind); - match stmt.kind { - StatementKind::Assign(box (ref place, ref rv)) => { + match &stmt.kind { + StatementKind::Assign(box (place, rv)) => { // Assignments to temporaries are not "interesting"; // they are not caused by the user, but rather artifacts // of lowering. Assignments to other sorts of places *are* interesting @@ -1279,11 +1279,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ); } } - StatementKind::AscribeUserType(box (ref place, ref projection), variance) => { + StatementKind::AscribeUserType(box (place, projection), variance) => { let place_ty = place.ty(body, tcx).ty; if let Err(terr) = self.relate_type_and_user_type( place_ty, - variance, + *variance, projection, Locations::All(stmt.source_info.span), ConstraintCategory::TypeAnnotation, @@ -1300,7 +1300,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ); } } - StatementKind::Intrinsic(box ref kind) => match kind { + StatementKind::Intrinsic(box kind) => match kind { NonDivergingIntrinsic::Assume(op) => self.check_operand(op, location), NonDivergingIntrinsic::CopyNonOverlapping(..) => span_bug!( stmt.source_info.span, @@ -1328,7 +1328,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ) { let tcx = self.tcx(); debug!("terminator kind: {:?}", term.kind); - match term.kind { + match &term.kind { TerminatorKind::Goto { .. } | TerminatorKind::Resume | TerminatorKind::Abort @@ -1342,7 +1342,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // no checks needed for these } - TerminatorKind::DropAndReplace { ref place, ref value, target: _, unwind: _ } => { + TerminatorKind::DropAndReplace { place, value, target: _, unwind: _ } => { let place_ty = place.ty(body, tcx).ty; let rv_ty = value.ty(body, tcx); @@ -1360,13 +1360,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ); } } - TerminatorKind::SwitchInt { ref discr, switch_ty, .. } => { + TerminatorKind::SwitchInt { discr, switch_ty, .. } => { self.check_operand(discr, term_location); let discr_ty = discr.ty(body, tcx); if let Err(terr) = self.sub_types( discr_ty, - switch_ty, + *switch_ty, term_location.to_locations(), ConstraintCategory::Assignment, ) { @@ -1384,14 +1384,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } // FIXME: check the values } - TerminatorKind::Call { - ref func, - ref args, - ref destination, - from_hir_call, - target, - .. - } => { + TerminatorKind::Call { func, args, destination, from_hir_call, target, .. } => { self.check_operand(func, term_location); for arg in args { self.check_operand(arg, term_location); @@ -1431,7 +1424,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ConstraintCategory::Boring, ); let sig = self.normalize(sig, term_location); - self.check_call_dest(body, term, &sig, *destination, target, term_location); + self.check_call_dest(body, term, &sig, *destination, *target, term_location); // The ordinary liveness rules will ensure that all // regions in the type of the callee are live here. We @@ -1449,9 +1442,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { .add_element(region_vid, term_location); } - self.check_call_inputs(body, term, &sig, args, term_location, from_hir_call); + self.check_call_inputs(body, term, &sig, args, term_location, *from_hir_call); } - TerminatorKind::Assert { ref cond, ref msg, .. } => { + TerminatorKind::Assert { cond, msg, .. } => { self.check_operand(cond, term_location); let cond_ty = cond.ty(body, tcx); @@ -1459,7 +1452,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { span_mirbug!(self, term, "bad Assert ({:?}, not bool", cond_ty); } - if let AssertKind::BoundsCheck { ref len, ref index } = *msg { + if let AssertKind::BoundsCheck { len, index } = msg { if len.ty(body, tcx) != tcx.types.usize { span_mirbug!(self, len, "bounds-check length non-usize {:?}", len) } @@ -1468,7 +1461,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } } } - TerminatorKind::Yield { ref value, .. } => { + TerminatorKind::Yield { value, .. } => { self.check_operand(value, term_location); let value_ty = value.ty(body, tcx); @@ -2630,7 +2623,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { substs: SubstsRef<'tcx>, location: Location, ) -> ty::InstantiatedPredicates<'tcx> { - if let Some(ref closure_requirements) = tcx.mir_borrowck(def_id).closure_requirements { + if let Some(closure_requirements) = &tcx.mir_borrowck(def_id).closure_requirements { constraint_conversion::ConstraintConversion::new( self.infcx, self.borrowck_context.universal_regions, diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index 618da9e32532..a4a0c5b90fed 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -587,9 +587,9 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { let typeck_root_def_id = tcx.typeck_root_def_id(self.mir_def.did.to_def_id()); let identity_substs = InternalSubsts::identity_for_item(tcx, typeck_root_def_id); let fr_substs = match defining_ty { - DefiningTy::Closure(_, ref substs) - | DefiningTy::Generator(_, ref substs, _) - | DefiningTy::InlineConst(_, ref substs) => { + DefiningTy::Closure(_, substs) + | DefiningTy::Generator(_, substs, _) + | DefiningTy::InlineConst(_, substs) => { // In the case of closures, we rely on the fact that // the first N elements in the ClosureSubsts are // inherited from the `typeck_root_def_id`. From 244990a6e91843289e094b384d67294756891fe9 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Tue, 6 Dec 2022 12:24:57 +0000 Subject: [PATCH 093/115] `rustc_attr` remove `ref` patterns ...and some if-let-elses too :P --- compiler/rustc_attr/src/builtin.rs | 134 +++++++++++++++-------------- 1 file changed, 69 insertions(+), 65 deletions(-) diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index 13b48d8f89ab..ab5e19050ead 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -277,8 +277,7 @@ where allowed_through_unstable_modules = true; } // attributes with data - else if let Some(MetaItem { kind: MetaItemKind::List(ref metas), .. }) = meta { - let meta = meta.as_ref().unwrap(); + else if let Some(meta @ MetaItem { kind: MetaItemKind::List(metas), .. }) = &meta { let get = |meta: &MetaItem, item: &mut Option| { if item.is_some() { handle_errors( @@ -533,25 +532,24 @@ where // Merge the const-unstable info into the stability info if promotable { - if let Some((ref mut stab, _)) = const_stab { - stab.promotable = promotable; - } else { - sess.emit_err(session_diagnostics::RustcPromotablePairing { span: item_sp }); + match &mut const_stab { + Some((stab, _)) => stab.promotable = promotable, + _ => _ = sess.emit_err(session_diagnostics::RustcPromotablePairing { span: item_sp }), } } if allowed_through_unstable_modules { - if let Some(( - Stability { - level: StabilityLevel::Stable { ref mut allowed_through_unstable_modules, .. }, - .. - }, - _, - )) = stab - { - *allowed_through_unstable_modules = true; - } else { - sess.emit_err(session_diagnostics::RustcAllowedUnstablePairing { span: item_sp }); + match &mut stab { + Some(( + Stability { + level: StabilityLevel::Stable { allowed_through_unstable_modules, .. }, + .. + }, + _, + )) => *allowed_through_unstable_modules = true, + _ => { + sess.emit_err(session_diagnostics::RustcAllowedUnstablePairing { span: item_sp }); + } } } @@ -654,8 +652,8 @@ pub fn eval_condition( features: Option<&Features>, eval: &mut impl FnMut(Condition) -> bool, ) -> bool { - match cfg.kind { - ast::MetaItemKind::List(ref mis) if cfg.name_or_empty() == sym::version => { + match &cfg.kind { + ast::MetaItemKind::List(mis) if cfg.name_or_empty() == sym::version => { try_gate_cfg(sym::version, cfg.span, sess, features); let (min_version, span) = match &mis[..] { [NestedMetaItem::Lit(MetaItemLit { kind: LitKind::Str(sym, ..), span, .. })] => { @@ -688,7 +686,7 @@ pub fn eval_condition( rustc_version >= min_version } } - ast::MetaItemKind::List(ref mis) => { + ast::MetaItemKind::List(mis) => { for mi in mis.iter() { if !mi.is_meta_item() { handle_errors( @@ -759,7 +757,7 @@ pub fn eval_condition( sess.emit_err(session_diagnostics::CfgPredicateIdentifier { span: cfg.path.span }); true } - MetaItemKind::NameValue(ref lit) if !lit.kind.is_str() => { + MetaItemKind::NameValue(lit) if !lit.kind.is_str() => { handle_errors( sess, lit.span, @@ -1036,52 +1034,58 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec { }); } } else if let Some(meta_item) = item.meta_item() { - if let MetaItemKind::NameValue(ref value) = meta_item.kind { - if meta_item.has_name(sym::align) || meta_item.has_name(sym::packed) { - let name = meta_item.name_or_empty().to_ident_string(); - recognised = true; - sess.emit_err(session_diagnostics::IncorrectReprFormatGeneric { - span: item.span(), - repr_arg: &name, - cause: IncorrectReprFormatGenericCause::from_lit_kind( - item.span(), - &value.kind, - &name, - ), - }); - } else if matches!( - meta_item.name_or_empty(), - sym::C | sym::simd | sym::transparent - ) || int_type_of_word(meta_item.name_or_empty()).is_some() - { - recognised = true; - sess.emit_err(session_diagnostics::InvalidReprHintNoValue { - span: meta_item.span, - name: meta_item.name_or_empty().to_ident_string(), - }); + match &meta_item.kind { + MetaItemKind::NameValue(value) => { + if meta_item.has_name(sym::align) || meta_item.has_name(sym::packed) { + let name = meta_item.name_or_empty().to_ident_string(); + recognised = true; + sess.emit_err(session_diagnostics::IncorrectReprFormatGeneric { + span: item.span(), + repr_arg: &name, + cause: IncorrectReprFormatGenericCause::from_lit_kind( + item.span(), + &value.kind, + &name, + ), + }); + } else if matches!( + meta_item.name_or_empty(), + sym::C | sym::simd | sym::transparent + ) || int_type_of_word(meta_item.name_or_empty()).is_some() + { + recognised = true; + sess.emit_err(session_diagnostics::InvalidReprHintNoValue { + span: meta_item.span, + name: meta_item.name_or_empty().to_ident_string(), + }); + } } - } else if let MetaItemKind::List(_) = meta_item.kind { - if meta_item.has_name(sym::align) { - recognised = true; - sess.emit_err(session_diagnostics::IncorrectReprFormatAlignOneArg { - span: meta_item.span, - }); - } else if meta_item.has_name(sym::packed) { - recognised = true; - sess.emit_err(session_diagnostics::IncorrectReprFormatPackedOneOrZeroArg { - span: meta_item.span, - }); - } else if matches!( - meta_item.name_or_empty(), - sym::C | sym::simd | sym::transparent - ) || int_type_of_word(meta_item.name_or_empty()).is_some() - { - recognised = true; - sess.emit_err(session_diagnostics::InvalidReprHintNoParen { - span: meta_item.span, - name: meta_item.name_or_empty().to_ident_string(), - }); + MetaItemKind::List(_) => { + if meta_item.has_name(sym::align) { + recognised = true; + sess.emit_err(session_diagnostics::IncorrectReprFormatAlignOneArg { + span: meta_item.span, + }); + } else if meta_item.has_name(sym::packed) { + recognised = true; + sess.emit_err( + session_diagnostics::IncorrectReprFormatPackedOneOrZeroArg { + span: meta_item.span, + }, + ); + } else if matches!( + meta_item.name_or_empty(), + sym::C | sym::simd | sym::transparent + ) || int_type_of_word(meta_item.name_or_empty()).is_some() + { + recognised = true; + sess.emit_err(session_diagnostics::InvalidReprHintNoParen { + span: meta_item.span, + name: meta_item.name_or_empty().to_ident_string(), + }); + } } + _ => (), } } if !recognised { From 700c095306ce89b0b18e2487aae9c0721e60a5e3 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Tue, 6 Dec 2022 13:22:36 +0000 Subject: [PATCH 094/115] `rustc_builtin_macros`: remove `ref` patterns ... and other pattern matching improvements --- .../src/alloc_error_handler.rs | 37 +++----- .../src/assert/context.rs | 38 ++++---- compiler/rustc_builtin_macros/src/concat.rs | 2 +- .../rustc_builtin_macros/src/concat_bytes.rs | 10 +- .../src/deriving/clone.rs | 16 ++-- .../src/deriving/decodable.rs | 20 ++-- .../src/deriving/default.rs | 13 +-- .../src/deriving/encodable.rs | 8 +- .../src/deriving/generic/mod.rs | 48 +++++----- .../src/deriving/generic/ty.rs | 9 +- .../rustc_builtin_macros/src/deriving/mod.rs | 6 +- compiler/rustc_builtin_macros/src/env.rs | 2 +- .../src/format_foreign.rs | 34 +++---- .../src/global_allocator.rs | 32 +++---- compiler/rustc_builtin_macros/src/test.rs | 94 ++++++++++--------- .../rustc_builtin_macros/src/test_harness.rs | 5 +- 16 files changed, 177 insertions(+), 197 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs index 460175ed2ac8..95e38e4b053f 100644 --- a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs +++ b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs @@ -17,32 +17,23 @@ pub fn expand( check_builtin_macro_attribute(ecx, meta_item, sym::alloc_error_handler); let orig_item = item.clone(); - let not_function = || { - ecx.sess - .parse_sess - .span_diagnostic - .span_err(item.span(), "alloc_error_handler must be a function"); - vec![orig_item.clone()] - }; // Allow using `#[alloc_error_handler]` on an item statement // FIXME - if we get deref patterns, use them to reduce duplication here - let (item, is_stmt, sig_span) = match &item { - Annotatable::Item(item) => match item.kind { - ItemKind::Fn(ref fn_kind) => (item, false, ecx.with_def_site_ctxt(fn_kind.sig.span)), - _ => return not_function(), - }, - Annotatable::Stmt(stmt) => match &stmt.kind { - StmtKind::Item(item_) => match item_.kind { - ItemKind::Fn(ref fn_kind) => { - (item_, true, ecx.with_def_site_ctxt(fn_kind.sig.span)) - } - _ => return not_function(), - }, - _ => return not_function(), - }, - _ => return not_function(), - }; + let (item, is_stmt, sig_span) = + if let Annotatable::Item(item) = &item + && let ItemKind::Fn(fn_kind) = &item.kind + { + (item, false, ecx.with_def_site_ctxt(fn_kind.sig.span)) + } else if let Annotatable::Stmt(stmt) = &item + && let StmtKind::Item(item) = &stmt.kind + && let ItemKind::Fn(fn_kind) = &item.kind + { + (item, true, ecx.with_def_site_ctxt(fn_kind.sig.span)) + } else { + ecx.sess.parse_sess.span_diagnostic.span_err(item.span(), "alloc_error_handler must be a function"); + return vec![orig_item.clone()]; + }; // Generate a bunch of new items using the AllocFnFactory let span = ecx.with_def_site_ctxt(item.span); diff --git a/compiler/rustc_builtin_macros/src/assert/context.rs b/compiler/rustc_builtin_macros/src/assert/context.rs index d82bc0453f57..93b07801e035 100644 --- a/compiler/rustc_builtin_macros/src/assert/context.rs +++ b/compiler/rustc_builtin_macros/src/assert/context.rs @@ -191,19 +191,19 @@ impl<'cx, 'a> Context<'cx, 'a> { /// /// See [Self::manage_initial_capture] and [Self::manage_try_capture] fn manage_cond_expr(&mut self, expr: &mut P) { - match (*expr).kind { - ExprKind::AddrOf(_, mutability, ref mut local_expr) => { + match &mut expr.kind { + ExprKind::AddrOf(_, mutability, local_expr) => { self.with_is_consumed_management( matches!(mutability, Mutability::Mut), |this| this.manage_cond_expr(local_expr) ); } - ExprKind::Array(ref mut local_exprs) => { + ExprKind::Array(local_exprs) => { for local_expr in local_exprs { self.manage_cond_expr(local_expr); } } - ExprKind::Binary(ref op, ref mut lhs, ref mut rhs) => { + ExprKind::Binary(op, lhs, rhs) => { self.with_is_consumed_management( matches!( op.node, @@ -226,56 +226,56 @@ impl<'cx, 'a> Context<'cx, 'a> { } ); } - ExprKind::Call(_, ref mut local_exprs) => { + ExprKind::Call(_, local_exprs) => { for local_expr in local_exprs { self.manage_cond_expr(local_expr); } } - ExprKind::Cast(ref mut local_expr, _) => { + ExprKind::Cast(local_expr, _) => { self.manage_cond_expr(local_expr); } - ExprKind::Index(ref mut prefix, ref mut suffix) => { + ExprKind::Index(prefix, suffix) => { self.manage_cond_expr(prefix); self.manage_cond_expr(suffix); } - ExprKind::MethodCall(ref mut call) => { - for arg in call.args.iter_mut() { + ExprKind::MethodCall(call) => { + for arg in &mut call.args { self.manage_cond_expr(arg); } } - ExprKind::Path(_, Path { ref segments, .. }) if let &[ref path_segment] = &segments[..] => { + ExprKind::Path(_, Path { segments, .. }) if let [path_segment] = &segments[..] => { let path_ident = path_segment.ident; self.manage_initial_capture(expr, path_ident); } - ExprKind::Paren(ref mut local_expr) => { + ExprKind::Paren(local_expr) => { self.manage_cond_expr(local_expr); } - ExprKind::Range(ref mut prefix, ref mut suffix, _) => { - if let Some(ref mut elem) = prefix { + ExprKind::Range(prefix, suffix, _) => { + if let Some(elem) = prefix { self.manage_cond_expr(elem); } - if let Some(ref mut elem) = suffix { + if let Some(elem) = suffix { self.manage_cond_expr(elem); } } - ExprKind::Repeat(ref mut local_expr, ref mut elem) => { + ExprKind::Repeat(local_expr, elem) => { self.manage_cond_expr(local_expr); self.manage_cond_expr(&mut elem.value); } - ExprKind::Struct(ref mut elem) => { + ExprKind::Struct(elem) => { for field in &mut elem.fields { self.manage_cond_expr(&mut field.expr); } - if let StructRest::Base(ref mut local_expr) = elem.rest { + if let StructRest::Base(local_expr) = &mut elem.rest { self.manage_cond_expr(local_expr); } } - ExprKind::Tup(ref mut local_exprs) => { + ExprKind::Tup(local_exprs) => { for local_expr in local_exprs { self.manage_cond_expr(local_expr); } } - ExprKind::Unary(un_op, ref mut local_expr) => { + ExprKind::Unary(un_op, local_expr) => { self.with_is_consumed_management( matches!(un_op, UnOp::Neg | UnOp::Not), |this| this.manage_cond_expr(local_expr) diff --git a/compiler/rustc_builtin_macros/src/concat.rs b/compiler/rustc_builtin_macros/src/concat.rs index d579616ad1b8..e2d71825d556 100644 --- a/compiler/rustc_builtin_macros/src/concat.rs +++ b/compiler/rustc_builtin_macros/src/concat.rs @@ -20,7 +20,7 @@ pub fn expand_concat( for e in es { match e.kind { ast::ExprKind::Lit(token_lit) => match ast::LitKind::from_token_lit(token_lit) { - Ok(ast::LitKind::Str(ref s, _) | ast::LitKind::Float(ref s, _)) => { + Ok(ast::LitKind::Str(s, _) | ast::LitKind::Float(s, _)) => { accumulator.push_str(s.as_str()); } Ok(ast::LitKind::Char(c)) => { diff --git a/compiler/rustc_builtin_macros/src/concat_bytes.rs b/compiler/rustc_builtin_macros/src/concat_bytes.rs index 161e3499584e..d1124145dcbb 100644 --- a/compiler/rustc_builtin_macros/src/concat_bytes.rs +++ b/compiler/rustc_builtin_macros/src/concat_bytes.rs @@ -144,8 +144,8 @@ pub fn expand_concat_bytes( let mut missing_literals = vec![]; let mut has_errors = false; for e in es { - match e.kind { - ast::ExprKind::Array(ref exprs) => { + match &e.kind { + ast::ExprKind::Array(exprs) => { for expr in exprs { if let Some(elem) = handle_array_element(cx, &mut has_errors, &mut missing_literals, expr) @@ -154,7 +154,7 @@ pub fn expand_concat_bytes( } } } - ast::ExprKind::Repeat(ref expr, ref count) => { + ast::ExprKind::Repeat(expr, count) => { if let ast::ExprKind::Lit(token_lit) = count.value.kind && let Ok(ast::LitKind::Int(count_val, _)) = ast::LitKind::from_token_lit(token_lit) @@ -170,7 +170,7 @@ pub fn expand_concat_bytes( cx.span_err(count.value.span, "repeat count is not a positive number"); } } - ast::ExprKind::Lit(token_lit) => match ast::LitKind::from_token_lit(token_lit) { + &ast::ExprKind::Lit(token_lit) => match ast::LitKind::from_token_lit(token_lit) { Ok(ast::LitKind::Byte(val)) => { accumulator.push(val); } @@ -184,7 +184,7 @@ pub fn expand_concat_bytes( has_errors = true; } }, - ast::ExprKind::IncludedBytes(ref bytes) => { + ast::ExprKind::IncludedBytes(bytes) => { accumulator.extend_from_slice(bytes); } ast::ExprKind::Err => { diff --git a/compiler/rustc_builtin_macros/src/deriving/clone.rs b/compiler/rustc_builtin_macros/src/deriving/clone.rs index 23b96d4176d3..d59b3b8c86d3 100644 --- a/compiler/rustc_builtin_macros/src/deriving/clone.rs +++ b/compiler/rustc_builtin_macros/src/deriving/clone.rs @@ -32,10 +32,10 @@ pub fn expand_deriving_clone( let bounds; let substructure; let is_simple; - match *item { - Annotatable::Item(ref annitem) => match annitem.kind { - ItemKind::Struct(_, Generics { ref params, .. }) - | ItemKind::Enum(_, Generics { ref params, .. }) => { + match item { + Annotatable::Item(annitem) => match &annitem.kind { + ItemKind::Struct(_, Generics { params, .. }) + | ItemKind::Enum(_, Generics { params, .. }) => { let container_id = cx.current_expansion.id.expn_data().parent.expect_local(); let has_derive_copy = cx.resolver.has_derive_copy(container_id); if has_derive_copy @@ -166,13 +166,13 @@ fn cs_clone( }; let vdata; - match *substr.fields { - Struct(vdata_, ref af) => { + match substr.fields { + Struct(vdata_, af) => { ctor_path = cx.path(trait_span, vec![substr.type_ident]); all_fields = af; - vdata = vdata_; + vdata = *vdata_; } - EnumMatching(.., variant, ref af) => { + EnumMatching(.., variant, af) => { ctor_path = cx.path(trait_span, vec![substr.type_ident, variant.ident]); all_fields = af; vdata = &variant.data; diff --git a/compiler/rustc_builtin_macros/src/deriving/decodable.rs b/compiler/rustc_builtin_macros/src/deriving/decodable.rs index 6d14875a9832..62af02c2bb4b 100644 --- a/compiler/rustc_builtin_macros/src/deriving/decodable.rs +++ b/compiler/rustc_builtin_macros/src/deriving/decodable.rs @@ -78,11 +78,11 @@ fn decodable_substructure( let blkarg = Ident::new(sym::_d, trait_span); let blkdecoder = cx.expr_ident(trait_span, blkarg); - let expr = match *substr.fields { - StaticStruct(_, ref summary) => { - let nfields = match *summary { - Unnamed(ref fields, _) => fields.len(), - Named(ref fields) => fields.len(), + let expr = match substr.fields { + StaticStruct(_, summary) => { + let nfields = match summary { + Unnamed(fields, _) => fields.len(), + Named(fields) => fields.len(), }; let fn_read_struct_field_path: Vec<_> = cx.def_site_path(&[sym::rustc_serialize, sym::Decoder, sym::read_struct_field]); @@ -119,7 +119,7 @@ fn decodable_substructure( ], ) } - StaticEnum(_, ref fields) => { + StaticEnum(_, fields) => { let variant = Ident::new(sym::i, trait_span); let mut arms = Vec::with_capacity(fields.len() + 1); @@ -194,10 +194,10 @@ fn decode_static_fields( where F: FnMut(&mut ExtCtxt<'_>, Span, Symbol, usize) -> P, { - match *fields { - Unnamed(ref fields, is_tuple) => { + match fields { + Unnamed(fields, is_tuple) => { let path_expr = cx.expr_path(outer_pat_path); - if !is_tuple { + if !*is_tuple { path_expr } else { let fields = fields @@ -209,7 +209,7 @@ where cx.expr_call(trait_span, path_expr, fields) } } - Named(ref fields) => { + Named(fields) => { // use the field's span to get nicer error messages. let fields = fields .iter() diff --git a/compiler/rustc_builtin_macros/src/deriving/default.rs b/compiler/rustc_builtin_macros/src/deriving/default.rs index e88d2e409c63..eb66c4a69a69 100644 --- a/compiler/rustc_builtin_macros/src/deriving/default.rs +++ b/compiler/rustc_builtin_macros/src/deriving/default.rs @@ -62,15 +62,12 @@ fn default_struct_substructure( let default_call = |span| cx.expr_call_global(span, default_ident.clone(), Vec::new()); let expr = match summary { - Unnamed(ref fields, is_tuple) => { - if !is_tuple { - cx.expr_ident(trait_span, substr.type_ident) - } else { - let exprs = fields.iter().map(|sp| default_call(*sp)).collect(); - cx.expr_call_ident(trait_span, substr.type_ident, exprs) - } + Unnamed(_, false) => cx.expr_ident(trait_span, substr.type_ident), + Unnamed(fields, true) => { + let exprs = fields.iter().map(|sp| default_call(*sp)).collect(); + cx.expr_call_ident(trait_span, substr.type_ident, exprs) } - Named(ref fields) => { + Named(fields) => { let default_fields = fields .iter() .map(|&(ident, span)| cx.field_imm(span, ident, default_call(span))) diff --git a/compiler/rustc_builtin_macros/src/deriving/encodable.rs b/compiler/rustc_builtin_macros/src/deriving/encodable.rs index 9a46ca815372..68bc0ff2ec0b 100644 --- a/compiler/rustc_builtin_macros/src/deriving/encodable.rs +++ b/compiler/rustc_builtin_macros/src/deriving/encodable.rs @@ -164,8 +164,8 @@ fn encodable_substructure( ], )); - match *substr.fields { - Struct(_, ref fields) => { + match substr.fields { + Struct(_, fields) => { let fn_emit_struct_field_path = cx.def_site_path(&[sym::rustc_serialize, sym::Encoder, sym::emit_struct_field]); let mut stmts = Vec::new(); @@ -224,7 +224,7 @@ fn encodable_substructure( BlockOrExpr::new_expr(expr) } - EnumMatching(idx, _, variant, ref fields) => { + EnumMatching(idx, _, variant, fields) => { // We're not generating an AST that the borrow checker is expecting, // so we need to generate a unique local variable to take the // mutable loan out on, otherwise we get conflicts which don't @@ -274,7 +274,7 @@ fn encodable_substructure( vec![ blkencoder, name, - cx.expr_usize(trait_span, idx), + cx.expr_usize(trait_span, *idx), cx.expr_usize(trait_span, fields.len()), blk, ], diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index 7fcaf0b436b9..beac591bfc87 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -369,15 +369,14 @@ fn find_type_parameters( impl<'a, 'b> visit::Visitor<'a> for Visitor<'a, 'b> { fn visit_ty(&mut self, ty: &'a ast::Ty) { - if let ast::TyKind::Path(_, ref path) = ty.kind { - if let Some(segment) = path.segments.first() { - if self.ty_param_names.contains(&segment.ident.name) { - self.type_params.push(TypeParameter { - bound_generic_params: self.bound_generic_params_stack.clone(), - ty: P(ty.clone()), - }); - } - } + if let ast::TyKind::Path(_, path) = &ty.kind + && let Some(segment) = path.segments.first() + && self.ty_param_names.contains(&segment.ident.name) + { + self.type_params.push(TypeParameter { + bound_generic_params: self.bound_generic_params_stack.clone(), + ty: P(ty.clone()), + }); } visit::walk_ty(self, ty) @@ -428,8 +427,8 @@ impl<'a> TraitDef<'a> { push: &mut dyn FnMut(Annotatable), from_scratch: bool, ) { - match *item { - Annotatable::Item(ref item) => { + match item { + Annotatable::Item(item) => { let is_packed = item.attrs.iter().any(|attr| { for r in attr::find_repr_attrs(&cx.sess, attr) { if let attr::ReprPacked(_) = r { @@ -438,10 +437,10 @@ impl<'a> TraitDef<'a> { } false }); - let has_no_type_params = match item.kind { - ast::ItemKind::Struct(_, ref generics) - | ast::ItemKind::Enum(_, ref generics) - | ast::ItemKind::Union(_, ref generics) => !generics + let has_no_type_params = match &item.kind { + ast::ItemKind::Struct(_, generics) + | ast::ItemKind::Enum(_, generics) + | ast::ItemKind::Union(_, generics) => !generics .params .iter() .any(|param| matches!(param.kind, ast::GenericParamKind::Type { .. })), @@ -451,8 +450,8 @@ impl<'a> TraitDef<'a> { let copy_fields = is_packed && has_no_type_params && cx.resolver.has_derive_copy(container_id); - let newitem = match item.kind { - ast::ItemKind::Struct(ref struct_def, ref generics) => self.expand_struct_def( + let newitem = match &item.kind { + ast::ItemKind::Struct(struct_def, generics) => self.expand_struct_def( cx, &struct_def, item.ident, @@ -460,7 +459,7 @@ impl<'a> TraitDef<'a> { from_scratch, copy_fields, ), - ast::ItemKind::Enum(ref enum_def, ref generics) => { + ast::ItemKind::Enum(enum_def, generics) => { // We ignore `is_packed` here, because `repr(packed)` // enums cause an error later on. // @@ -468,7 +467,7 @@ impl<'a> TraitDef<'a> { // downstream in blatantly illegal code, so it is fine. self.expand_enum_def(cx, enum_def, item.ident, generics, from_scratch) } - ast::ItemKind::Union(ref struct_def, ref generics) => { + ast::ItemKind::Union(struct_def, generics) => { if self.supports_unions { self.expand_struct_def( cx, @@ -663,12 +662,11 @@ impl<'a> TraitDef<'a> { for field_ty_param in field_ty_params { // if we have already handled this type, skip it - if let ast::TyKind::Path(_, ref p) = field_ty_param.ty.kind { - if p.segments.len() == 1 - && ty_param_names.contains(&p.segments[0].ident.name) - { - continue; - }; + if let ast::TyKind::Path(_, p) = &field_ty_param.ty.kind + && let [sole_segment] = &*p.segments + && ty_param_names.contains(&sole_segment.ident.name) + { + continue; } let mut bounds: Vec<_> = self .additional_bounds diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs b/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs index 36e2e2930869..eaa4881906a8 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs @@ -115,7 +115,7 @@ impl Ty { self_ty: Ident, generics: &Generics, ) -> ast::Path { - match *self { + match self { Self_ => { let params: Vec<_> = generics .params @@ -135,7 +135,7 @@ impl Ty { cx.path_all(span, false, vec![self_ty], params) } - Path(ref p) => p.to_path(cx, span, self_ty, generics), + Path(p) => p.to_path(cx, span, self_ty, generics), Ref(..) => cx.span_bug(span, "ref in a path in generic `derive`"), Unit => cx.span_bug(span, "unit in a path in generic `derive`"), } @@ -180,10 +180,7 @@ impl Bounds { let params = self .bounds .iter() - .map(|t| { - let (name, ref bounds) = *t; - mk_ty_param(cx, span, name, &bounds, self_ty, self_generics) - }) + .map(|&(name, ref bounds)| mk_ty_param(cx, span, name, &bounds, self_ty, self_generics)) .collect(); Generics { diff --git a/compiler/rustc_builtin_macros/src/deriving/mod.rs b/compiler/rustc_builtin_macros/src/deriving/mod.rs index 13fdd4fa68c4..de657e4e6006 100644 --- a/compiler/rustc_builtin_macros/src/deriving/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/mod.rs @@ -125,12 +125,12 @@ fn inject_impl_of_structural_trait( structural_path: generic::ty::Path, push: &mut dyn FnMut(Annotatable), ) { - let Annotatable::Item(ref item) = *item else { + let Annotatable::Item(item) = item else { unreachable!(); }; - let generics = match item.kind { - ItemKind::Struct(_, ref generics) | ItemKind::Enum(_, ref generics) => generics, + let generics = match &item.kind { + ItemKind::Struct(_, generics) | ItemKind::Enum(_, generics) => generics, // Do not inject `impl Structural for Union`. (`PartialEq` does not // support unions, so we will see error downstream.) ItemKind::Union(..) => return, diff --git a/compiler/rustc_builtin_macros/src/env.rs b/compiler/rustc_builtin_macros/src/env.rs index b8828fa671a5..0b4e545f7a3d 100644 --- a/compiler/rustc_builtin_macros/src/env.rs +++ b/compiler/rustc_builtin_macros/src/env.rs @@ -53,7 +53,7 @@ pub fn expand_env<'cx>( tts: TokenStream, ) -> Box { let mut exprs = match get_exprs_from_tts(cx, sp, tts) { - Some(ref exprs) if exprs.is_empty() => { + Some(exprs) if exprs.is_empty() => { cx.span_err(sp, "env! takes 1 or 2 arguments"); return DummyResult::any(sp); } diff --git a/compiler/rustc_builtin_macros/src/format_foreign.rs b/compiler/rustc_builtin_macros/src/format_foreign.rs index ecd16736e7c3..6f7fc3a95ba6 100644 --- a/compiler/rustc_builtin_macros/src/format_foreign.rs +++ b/compiler/rustc_builtin_macros/src/format_foreign.rs @@ -13,23 +13,23 @@ pub(crate) mod printf { impl<'a> Substitution<'a> { pub fn as_str(&self) -> &str { - match *self { - Substitution::Format(ref fmt) => fmt.span, + match self { + Substitution::Format(fmt) => fmt.span, Substitution::Escape(_) => "%%", } } pub fn position(&self) -> Option { - match *self { - Substitution::Format(ref fmt) => Some(fmt.position), - Substitution::Escape((start, end)) => Some(InnerSpan::new(start, end)), + match self { + Substitution::Format(fmt) => Some(fmt.position), + &Substitution::Escape((start, end)) => Some(InnerSpan::new(start, end)), } } pub fn set_position(&mut self, start: usize, end: usize) { match self { - Substitution::Format(ref mut fmt) => fmt.position = InnerSpan::new(start, end), - Substitution::Escape(ref mut pos) => *pos = (start, end), + Substitution::Format(fmt) => fmt.position = InnerSpan::new(start, end), + Substitution::Escape(pos) => *pos = (start, end), } } @@ -38,8 +38,8 @@ pub(crate) mod printf { /// This ignores cases where the substitution does not have an exact equivalent, or where /// the substitution would be unnecessary. pub fn translate(&self) -> Result> { - match *self { - Substitution::Format(ref fmt) => fmt.translate(), + match self { + Substitution::Format(fmt) => fmt.translate(), Substitution::Escape(_) => Err(None), } } @@ -635,23 +635,17 @@ pub mod shell { } pub fn position(&self) -> Option { - match self { - Substitution::Ordinal(_, pos) - | Substitution::Name(_, pos) - | Substitution::Escape(pos) => Some(InnerSpan::new(pos.0, pos.1)), - } + let (Self::Ordinal(_, pos) | Self::Name(_, pos) | Self::Escape(pos)) = self; + Some(InnerSpan::new(pos.0, pos.1)) } pub fn set_position(&mut self, start: usize, end: usize) { - match self { - Substitution::Ordinal(_, ref mut pos) - | Substitution::Name(_, ref mut pos) - | Substitution::Escape(ref mut pos) => *pos = (start, end), - } + let (Self::Ordinal(_, pos) | Self::Name(_, pos) | Self::Escape(pos)) = self; + *pos = (start, end); } pub fn translate(&self) -> Result> { - match *self { + match self { Substitution::Ordinal(n, _) => Ok(format!("{{{}}}", n)), Substitution::Name(n, _) => Ok(format!("{{{}}}", n)), Substitution::Escape(_) => Err(None), diff --git a/compiler/rustc_builtin_macros/src/global_allocator.rs b/compiler/rustc_builtin_macros/src/global_allocator.rs index 0817aed037ef..41531580c198 100644 --- a/compiler/rustc_builtin_macros/src/global_allocator.rs +++ b/compiler/rustc_builtin_macros/src/global_allocator.rs @@ -20,27 +20,23 @@ pub fn expand( check_builtin_macro_attribute(ecx, meta_item, sym::global_allocator); let orig_item = item.clone(); - let not_static = || { - ecx.sess.parse_sess.span_diagnostic.span_err(item.span(), "allocators must be statics"); - vec![orig_item.clone()] - }; // Allow using `#[global_allocator]` on an item statement // FIXME - if we get deref patterns, use them to reduce duplication here - let (item, is_stmt, ty_span) = match &item { - Annotatable::Item(item) => match item.kind { - ItemKind::Static(ref ty, ..) => (item, false, ecx.with_def_site_ctxt(ty.span)), - _ => return not_static(), - }, - Annotatable::Stmt(stmt) => match &stmt.kind { - StmtKind::Item(item_) => match item_.kind { - ItemKind::Static(ref ty, ..) => (item_, true, ecx.with_def_site_ctxt(ty.span)), - _ => return not_static(), - }, - _ => return not_static(), - }, - _ => return not_static(), - }; + let (item, is_stmt, ty_span) = + if let Annotatable::Item(item) = &item + && let ItemKind::Static(ty, ..) = &item.kind + { + (item, false, ecx.with_def_site_ctxt(ty.span)) + } else if let Annotatable::Stmt(stmt) = &item + && let StmtKind::Item(item) = &stmt.kind + && let ItemKind::Static(ty, ..) = &item.kind + { + (item, true, ecx.with_def_site_ctxt(ty.span)) + } else { + ecx.sess.parse_sess.span_diagnostic.span_err(item.span(), "allocators must be statics"); + return vec![orig_item.clone()] + }; // Generate a bunch of new items using the AllocFnFactory let span = ecx.with_def_site_ctxt(item.span); diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index 3bcb60478efb..f5f02fc772ab 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -466,61 +466,67 @@ fn test_type(cx: &ExtCtxt<'_>) -> TestType { fn has_test_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool { let has_should_panic_attr = cx.sess.contains_name(&i.attrs, sym::should_panic); let sd = &cx.sess.parse_sess.span_diagnostic; - if let ast::ItemKind::Fn(box ast::Fn { ref sig, ref generics, .. }) = i.kind { - if let ast::Unsafe::Yes(span) = sig.header.unsafety { - sd.struct_span_err(i.span, "unsafe functions cannot be used for tests") - .span_label(span, "`unsafe` because of this") - .emit(); - return false; - } - if let ast::Async::Yes { span, .. } = sig.header.asyncness { - sd.struct_span_err(i.span, "async functions cannot be used for tests") - .span_label(span, "`async` because of this") - .emit(); - return false; - } - - // If the termination trait is active, the compiler will check that the output - // type implements the `Termination` trait as `libtest` enforces that. - let has_output = match sig.decl.output { - ast::FnRetTy::Default(..) => false, - ast::FnRetTy::Ty(ref t) if t.kind.is_unit() => false, - _ => true, - }; - - if !sig.decl.inputs.is_empty() { - sd.span_err(i.span, "functions used as tests can not have any arguments"); - return false; - } - - match (has_output, has_should_panic_attr) { - (true, true) => { - sd.span_err(i.span, "functions using `#[should_panic]` must return `()`"); - false + match &i.kind { + ast::ItemKind::Fn(box ast::Fn { sig, generics, .. }) => { + if let ast::Unsafe::Yes(span) = sig.header.unsafety { + sd.struct_span_err(i.span, "unsafe functions cannot be used for tests") + .span_label(span, "`unsafe` because of this") + .emit(); + return false; } - (true, false) => { - if !generics.params.is_empty() { - sd.span_err(i.span, "functions used as tests must have signature fn() -> ()"); + if let ast::Async::Yes { span, .. } = sig.header.asyncness { + sd.struct_span_err(i.span, "async functions cannot be used for tests") + .span_label(span, "`async` because of this") + .emit(); + return false; + } + + // If the termination trait is active, the compiler will check that the output + // type implements the `Termination` trait as `libtest` enforces that. + let has_output = match &sig.decl.output { + ast::FnRetTy::Default(..) => false, + ast::FnRetTy::Ty(t) if t.kind.is_unit() => false, + _ => true, + }; + + if !sig.decl.inputs.is_empty() { + sd.span_err(i.span, "functions used as tests can not have any arguments"); + return false; + } + + match (has_output, has_should_panic_attr) { + (true, true) => { + sd.span_err(i.span, "functions using `#[should_panic]` must return `()`"); false - } else { - true } + (true, false) => { + if !generics.params.is_empty() { + sd.span_err( + i.span, + "functions used as tests must have signature fn() -> ()", + ); + false + } else { + true + } + } + (false, _) => true, } - (false, _) => true, } - } else { - // should be unreachable because `is_test_fn_item` should catch all non-fn items - false + _ => { + // should be unreachable because `is_test_fn_item` should catch all non-fn items + debug_assert!(false); + false + } } } fn has_bench_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool { - let has_sig = if let ast::ItemKind::Fn(box ast::Fn { ref sig, .. }) = i.kind { + let has_sig = match &i.kind { // N.B., inadequate check, but we're running // well before resolve, can't get too deep. - sig.decl.inputs.len() == 1 - } else { - false + ast::ItemKind::Fn(box ast::Fn { sig, .. }) => sig.decl.inputs.len() == 1, + _ => false, }; if !has_sig { diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs index b5bce9278a90..ad8871080910 100644 --- a/compiler/rustc_builtin_macros/src/test_harness.rs +++ b/compiler/rustc_builtin_macros/src/test_harness.rs @@ -131,8 +131,9 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> { // We don't want to recurse into anything other than mods, since // mods or tests inside of functions will break things - if let ast::ItemKind::Mod(_, ModKind::Loaded(.., ref spans)) = item.kind { - let ast::ModSpans { inner_span: span, inject_use_span: _ } = *spans; + if let ast::ItemKind::Mod(_, ModKind::Loaded(.., ast::ModSpans { inner_span: span, .. })) = + item.kind + { let prev_tests = mem::take(&mut self.tests); noop_visit_item_kind(&mut item.kind, self); self.add_test_cases(item.id, span, prev_tests); From 50f090002ad782620ff00842b9f163c6bbc00d7d Mon Sep 17 00:00:00 2001 From: Boxy Date: Tue, 6 Dec 2022 16:33:19 +0000 Subject: [PATCH 095/115] add cg ping files things --- triagebot.toml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/triagebot.toml b/triagebot.toml index bc0b88b2babd..54523b029dfa 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -332,7 +332,15 @@ cc = ["@rust-lang/wg-mir-opt"] [mentions."compiler/rustc_trait_selection/src/traits/const_evaluatable.rs"] message = "Some changes occurred in const_evaluatable.rs" -cc = ["@lcnr"] +cc = ["@BoxyUwU"] + +[mentions."compiler/rustc_middle/src/ty/abstract_const.rs"] +message = "Some changes occured in `abstract_const.rs`" +cc = ["@BoxyUwU"] + +[mentions."compiler/rustc_ty_utils/src/consts.rs"] +message = "Some changes occured in `rustc_ty_utils::consts.rs`" +cc = ["@BoxyUwU"] [mentions."compiler/rustc_trait_selection/src/traits/engine.rs"] message = """ From 0070fae2dcbcdef6f107fc0acb2f078412b1e6fb Mon Sep 17 00:00:00 2001 From: Boxy Date: Tue, 6 Dec 2022 16:40:57 +0000 Subject: [PATCH 096/115] typo :( --- compiler/rustc_trait_selection/src/traits/const_evaluatable.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index d01c6bac2963..7cc0999478a3 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -64,7 +64,7 @@ pub fn is_const_evaluatable<'tcx>( ty::ConstKind::Expr(_) => { // FIXME(generic_const_exprs): we have a `ConstKind::Expr` which is fully concrete, but // currently it is not possible to evaluate `ConstKind::Expr` so we are unable to tell if it - // is evaluatable or not. For now we just ICE until this is implemented this. + // is evaluatable or not. For now we just ICE until this is implemented. Err(NotConstEvaluatable::Error(tcx.sess.delay_span_bug( span, "evaluating `ConstKind::Expr` is not currently supported", From 3ca5c821c250a8f7b3b99fc515521890c357da5c Mon Sep 17 00:00:00 2001 From: Boxy Date: Tue, 6 Dec 2022 16:45:11 +0000 Subject: [PATCH 097/115] CONSISTENCY Co-authored-by: lcnr --- triagebot.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/triagebot.toml b/triagebot.toml index 54523b029dfa..49945e5c533c 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -331,7 +331,7 @@ message = "Some changes occurred to MIR optimizations" cc = ["@rust-lang/wg-mir-opt"] [mentions."compiler/rustc_trait_selection/src/traits/const_evaluatable.rs"] -message = "Some changes occurred in const_evaluatable.rs" +message = "Some changes occurred in `const_evaluatable.rs`" cc = ["@BoxyUwU"] [mentions."compiler/rustc_middle/src/ty/abstract_const.rs"] From 93b774a2a47e813fd01481dab480d4be785c4427 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Tue, 6 Dec 2022 16:54:32 +0000 Subject: [PATCH 098/115] Don't set `STARTF_USESTDHANDLES` if none are set --- library/std/src/sys/windows/process.rs | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/library/std/src/sys/windows/process.rs b/library/std/src/sys/windows/process.rs index 32be07aee8f4..31e9b34fb9ef 100644 --- a/library/std/src/sys/windows/process.rs +++ b/library/std/src/sys/windows/process.rs @@ -252,10 +252,6 @@ impl Command { ) -> io::Result<(Process, StdioPipes)> { let maybe_env = self.env.capture_if_changed(); - let mut si = zeroed_startupinfo(); - si.cb = mem::size_of::() as c::DWORD; - si.dwFlags = c::STARTF_USESTDHANDLES; - let child_paths = if let Some(env) = maybe_env.as_ref() { env.get(&EnvKey::new("PATH")).map(|s| s.as_os_str()) } else { @@ -314,9 +310,21 @@ impl Command { let stdin = stdin.to_handle(c::STD_INPUT_HANDLE, &mut pipes.stdin)?; let stdout = stdout.to_handle(c::STD_OUTPUT_HANDLE, &mut pipes.stdout)?; let stderr = stderr.to_handle(c::STD_ERROR_HANDLE, &mut pipes.stderr)?; - si.hStdInput = stdin.as_raw_handle(); - si.hStdOutput = stdout.as_raw_handle(); - si.hStdError = stderr.as_raw_handle(); + + let mut si = zeroed_startupinfo(); + si.cb = mem::size_of::() as c::DWORD; + + // If at least one of stdin, stdout or stderr are set (i.e. are non null) + // then set the `hStd` fields in `STARTUPINFO`. + // Otherwise skip this and allow the OS to apply its default behaviour. + // This provides more consistent behaviour between Win7 and Win8+. + let is_set = |stdio: &Handle| !stdio.as_raw_handle().is_null(); + if is_set(&stderr) || is_set(&stdout) || is_set(&stdin) { + si.dwFlags |= c::STARTF_USESTDHANDLES; + si.hStdInput = stdin.as_raw_handle(); + si.hStdOutput = stdout.as_raw_handle(); + si.hStdError = stderr.as_raw_handle(); + } unsafe { cvt(c::CreateProcessW( From 75aec4703dea7ef8e13924ccfa3a3d2e8c5c7cff Mon Sep 17 00:00:00 2001 From: Krasimir Georgiev Date: Mon, 5 Dec 2022 12:04:25 +0000 Subject: [PATCH 099/115] llvm-wrapper: adapt for and LLVM API change --- compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp | 11 ++++++++++- compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp | 16 ++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 7f4d63eed8bd..1a3d458c3006 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -205,7 +205,12 @@ enum class LLVMRustCodeModel { None, }; -static Optional fromRust(LLVMRustCodeModel Model) { +#if LLVM_VERSION_LT(16, 0) +static Optional +#else +static std::optional +#endif +fromRust(LLVMRustCodeModel Model) { switch (Model) { case LLVMRustCodeModel::Tiny: return CodeModel::Tiny; @@ -638,7 +643,11 @@ LLVMRustOptimize( LLVMSelfProfileInitializeCallbacks(PIC,LlvmSelfProfiler,BeforePassCallback,AfterPassCallback); } +#if LLVM_VERSION_LT(16, 0) Optional PGOOpt; +#else + std::optional PGOOpt; +#endif if (PGOGenPath) { assert(!PGOUsePath && !PGOSampleUsePath); PGOOpt = PGOOptions(PGOGenPath, "", "", PGOOptions::IRInstr, diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index 216c35d6da07..c717479a6a6d 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -17,7 +17,9 @@ #include "llvm/Pass.h" #include "llvm/Bitcode/BitcodeWriter.h" #include "llvm/Support/Signals.h" +#if LLVM_VERSION_LT(16, 0) #include "llvm/ADT/Optional.h" +#endif #include @@ -708,7 +710,11 @@ enum class LLVMRustChecksumKind { SHA256, }; +#if LLVM_VERSION_LT(16, 0) static Optional fromRust(LLVMRustChecksumKind Kind) { +#else +static std::optional fromRust(LLVMRustChecksumKind Kind) { +#endif switch (Kind) { case LLVMRustChecksumKind::None: return None; @@ -787,8 +793,18 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFile( const char *Filename, size_t FilenameLen, const char *Directory, size_t DirectoryLen, LLVMRustChecksumKind CSKind, const char *Checksum, size_t ChecksumLen) { + +#if LLVM_VERSION_LT(16, 0) Optional llvmCSKind = fromRust(CSKind); +#else + std::optional llvmCSKind = fromRust(CSKind); +#endif + +#if LLVM_VERSION_LT(16, 0) Optional> CSInfo{}; +#else + std::optional> CSInfo{}; +#endif if (llvmCSKind) CSInfo.emplace(*llvmCSKind, StringRef{Checksum, ChecksumLen}); return wrap(Builder->createFile(StringRef(Filename, FilenameLen), From 958a1ae0f764471e911ccf35582d1fb9bf063d61 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Tue, 6 Dec 2022 11:56:22 -0700 Subject: [PATCH 100/115] rustdoc: remove redundant CSS `.import-item .stab { font-size }` This sets the exact same font size that `.stab` has by default anyway. It used to be slightly different, but dd5ff428edbc7cd4fa600b81f27bbec28589704f made it identical. --- src/librustdoc/html/static/css/rustdoc.css | 1 - 1 file changed, 1 deletion(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 528e99d2ce0f..a4df41b15c01 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -1015,7 +1015,6 @@ so that we can apply CSS-filters to change the arrow color in themes */ .import-item .stab { border-radius: 3px; display: inline-block; - font-size: 0.875rem; line-height: 1.2; margin-bottom: 0; margin-left: 0.3125em; From bc38c2ae67e5a5b6e67c592e3fdf67737785dbe0 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Tue, 6 Dec 2022 14:22:56 -0500 Subject: [PATCH 101/115] unstable-book: Add `ignore` to `abi_efiapi` example code This example doesn't compile on targets that don't support UEFI, as reported here: https://github.com/rust-lang/rust/pull/104793#issuecomment-1339783727 --- src/doc/unstable-book/src/language-features/abi-efiapi.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/unstable-book/src/language-features/abi-efiapi.md b/src/doc/unstable-book/src/language-features/abi-efiapi.md index 11ef0cfdb142..b492da88474e 100644 --- a/src/doc/unstable-book/src/language-features/abi-efiapi.md +++ b/src/doc/unstable-book/src/language-features/abi-efiapi.md @@ -12,7 +12,7 @@ Specification]. Example: -```rust +```rust,ignore (not-all-targets-support-uefi) #![feature(abi_efiapi)] extern "efiapi" { fn f1(); } From 3e671fee5ffa83e7145d85006bd316bd07e40b31 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Tue, 6 Dec 2022 13:08:30 -0800 Subject: [PATCH 102/115] Update the wasi toolchain. Update the WASI build to LLVM 15.0 and the wasi-libc version from [wasi-sdk-17]. This will require a ci-mirrors.rust-lang.org file load. Specifically, we need [this LLVM release tarball] uploaded to be downloadable from [this URL]. [this LLVM release tarball]: https://github.com/llvm/llvm-project/releases/download/llvmorg-15.0.6/clang+llvm-15.0.6-x86_64-linux-gnu-ubuntu-18.04.tar.xz [this URL]: https://ci-mirrors.rust-lang.org/rustc/2022-12-06-clang%2Bllvm-15.0.6-x86_64-linux-gnu-ubuntu-18.04.tar.xz [wasi-sdk-17]: https://github.com/WebAssembly/wasi-sdk/releases/tag/wasi-sdk-17 --- .../host-x86_64/dist-various-2/build-wasi-toolchain.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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 36c94458da7b..67cee0148b24 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 @@ -2,15 +2,15 @@ set -ex -# Originally from https://github.com/llvm/llvm-project/releases/download/llvmorg-14.0.0/clang+llvm-14.0.0-x86_64-linux-gnu-ubuntu-18.04.tar.xz -curl https://ci-mirrors.rust-lang.org/rustc/2022-05-10-clang%2Bllvm-14.0.0-x86_64-linux-gnu-ubuntu-18.04.tar.xz | \ +# Originally from https://github.com/llvm/llvm-project/releases/download/llvmorg-15.0.6/clang+llvm-15.0.6-x86_64-linux-gnu-ubuntu-18.04.tar.xz +curl https://ci-mirrors.rust-lang.org/rustc/2022-12-06-clang%2Bllvm-15.0.6-x86_64-linux-gnu-ubuntu-18.04.tar.xz | \ tar xJf - -bin="$PWD/clang+llvm-14.0.0-x86_64-linux-gnu-ubuntu-18.04/bin" +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 9886d3d6200fcc3726329966860fc058707406cd +git reset --hard 8b7148f69ae241a2749b3defe4606da8143b72e0 make -j$(nproc) \ CC="$bin/clang" \ NM="$bin/llvm-nm" \ From 9f438bef0b0a1f9249525fc8a1230eaf78753362 Mon Sep 17 00:00:00 2001 From: Boxy Date: Tue, 6 Dec 2022 22:53:08 +0000 Subject: [PATCH 103/115] normalize before matching on `ConstKind` --- .../src/traits/const_evaluatable.rs | 2 +- .../normed_to_param_is_evaluatable.rs | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/const-generics/generic_const_exprs/normed_to_param_is_evaluatable.rs diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index d01c6bac2963..7446309bcfa6 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -30,7 +30,7 @@ pub fn is_const_evaluatable<'tcx>( span: Span, ) -> Result<(), NotConstEvaluatable> { let tcx = infcx.tcx; - match unexpanded_ct.kind() { + match tcx.expand_abstract_consts(unexpanded_ct).kind() { ty::ConstKind::Unevaluated(_) | ty::ConstKind::Expr(_) => (), ty::ConstKind::Param(_) | ty::ConstKind::Bound(_, _) diff --git a/src/test/ui/const-generics/generic_const_exprs/normed_to_param_is_evaluatable.rs b/src/test/ui/const-generics/generic_const_exprs/normed_to_param_is_evaluatable.rs new file mode 100644 index 000000000000..b37b354ae214 --- /dev/null +++ b/src/test/ui/const-generics/generic_const_exprs/normed_to_param_is_evaluatable.rs @@ -0,0 +1,12 @@ +// check-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features, unused_braces)] + +#[rustfmt::skip] +fn foo() { + bar::<{{{{{{ N }}}}}}>(); +} + +fn bar() {} + +fn main() {} From 75aef7036f3e6b45a68f3ff9ece379615dc222da Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Tue, 6 Dec 2022 17:05:43 -0700 Subject: [PATCH 104/115] rustdoc: simplify CSS selectors for item table `.stab` The module-item and import-item classes are attached to the item-left. Just target that, instead. --- src/librustdoc/html/static/css/rustdoc.css | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 0cd15768ac6e..88fb1038c6b3 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -212,8 +212,7 @@ pre.rust a, .mobile-topbar h2 a, h1 a, .search-results a, -.module-item .stab, -.import-item .stab, +.item-left .stab, .result-name .primitive > i, .result-name .keyword > i { color: var(--main-color); } @@ -1010,8 +1009,7 @@ so that we can apply CSS-filters to change the arrow color in themes */ 0 -1px 0 black; } -.module-item .stab, -.import-item .stab { +.item-left .stab { border-radius: 3px; display: inline-block; font-size: 0.875rem; From 3a07aa9b5e9612a0b4fd0852763c34e1f244794b Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Tue, 6 Dec 2022 16:50:29 -0800 Subject: [PATCH 105/115] Stop passing -export-dynamic to wasm-ld. -export-dynamic was a temporary hack added in the early days of the Rust wasm32 target when Rust didn't have a way to specify wasm exports in the source code. This flag causes all global symbols, and some compiler-internal symbols, to be exported, which is often more than needed. Rust now does have a way to specify exports in the source code: `#[export_name = "..."]`. So as the original comment suggests, -export-dynamic can now be removed, allowing users to have smaller binaries and better encapsulation in their wasm32-unknown-unknown modules. It's possible that this change will require existing wasm32-unknown-unknown users will to add explicit `#[export_name = "..."]` directives to exporrt the symbols that their programs depend on having exported. --- compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs b/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs index 8dad941b534b..06529c2e4039 100644 --- a/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs +++ b/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs @@ -33,12 +33,6 @@ pub fn target() -> Target { // For now this target just never has an entry symbol no matter the output // type, so unconditionally pass this. "--no-entry", - // Rust really needs a way for users to specify exports and imports in - // the source code. --export-dynamic isn't the right tool for this job, - // however it does have the side effect of automatically exporting a lot - // of symbols, which approximates what people want when compiling for - // wasm32-unknown-unknown expect, so use it for now. - "--export-dynamic", ], ); options.add_pre_link_args( @@ -48,7 +42,6 @@ pub fn target() -> Target { // otherwise "--target=wasm32-unknown-unknown", "-Wl,--no-entry", - "-Wl,--export-dynamic", ], ); From e9dd59131bc02986ec17f88307e1b0ae252dc5ad Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 6 Dec 2022 17:53:50 -0800 Subject: [PATCH 106/115] Add help for `#![feature(impl_trait_in_fn_trait_return)]` This adds a new variant `ImplTraitContext::FeatureGated`, so we can generalize the help for `return_position_impl_trait_in_trait` to also work for `impl_trait_in_fn_trait_return`. --- compiler/rustc_ast_lowering/src/lib.rs | 32 ++++++++++++------- compiler/rustc_ast_lowering/src/path.rs | 19 +++++++---- ...-gate-impl_trait_in_fn_trait_return.stderr | 6 ++++ 3 files changed, 40 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 0258f8fd2d9a..f05a441ff81c 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -259,6 +259,8 @@ enum ImplTraitContext { }, /// Impl trait in type aliases. TypeAliasesOpaqueTy, + /// `impl Trait` is unstably accepted in this position. + FeatureGated(ImplTraitPosition, Symbol), /// `impl Trait` is not accepted in this position. Disallowed(ImplTraitPosition), } @@ -1372,17 +1374,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } path } - ImplTraitContext::Disallowed( - position @ (ImplTraitPosition::TraitReturn | ImplTraitPosition::ImplReturn), - ) => { + ImplTraitContext::FeatureGated(position, feature) => { self.tcx .sess .create_feature_err( MisplacedImplTrait { span: t.span, - position: DiagnosticArgFromDisplay(&position), + position: DiagnosticArgFromDisplay(position), }, - sym::return_position_impl_trait_in_trait, + *feature, ) .emit(); hir::TyKind::Err @@ -1390,7 +1390,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ImplTraitContext::Disallowed(position) => { self.tcx.sess.emit_err(MisplacedImplTrait { span: t.span, - position: DiagnosticArgFromDisplay(&position), + position: DiagnosticArgFromDisplay(position), }); hir::TyKind::Err } @@ -1739,14 +1739,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } else { match &decl.output { FnRetTy::Ty(ty) => { - let mut context = if kind.return_impl_trait_allowed(self.tcx) { + let context = if kind.return_impl_trait_allowed(self.tcx) { let fn_def_id = self.local_def_id(fn_node_id); ImplTraitContext::ReturnPositionOpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), in_trait: matches!(kind, FnDeclKind::Trait), } } else { - ImplTraitContext::Disallowed(match kind { + let position = match kind { FnDeclKind::Fn | FnDeclKind::Inherent => { unreachable!("fn should allow in-band lifetimes") } @@ -1755,9 +1755,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { FnDeclKind::Pointer => ImplTraitPosition::PointerReturn, FnDeclKind::Trait => ImplTraitPosition::TraitReturn, FnDeclKind::Impl => ImplTraitPosition::ImplReturn, - }) + }; + match kind { + FnDeclKind::Trait | FnDeclKind::Impl => ImplTraitContext::FeatureGated( + position, + sym::return_position_impl_trait_in_trait, + ), + _ => ImplTraitContext::Disallowed(position), + } }; - hir::FnRetTy::Return(self.lower_ty(ty, &mut context)) + hir::FnRetTy::Return(self.lower_ty(ty, &context)) } FnRetTy::Default(span) => hir::FnRetTy::DefaultReturn(self.lower_span(*span)), } @@ -1938,7 +1945,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { output, span, if in_trait && !this.tcx.features().return_position_impl_trait_in_trait { - ImplTraitContext::Disallowed(ImplTraitPosition::TraitReturn) + ImplTraitContext::FeatureGated( + ImplTraitPosition::TraitReturn, + sym::return_position_impl_trait_in_trait, + ) } else { ImplTraitContext::ReturnPositionOpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index 8d23c26e603b..592fc5aa6456 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -9,7 +9,7 @@ use rustc_ast::{self as ast, *}; use rustc_hir as hir; use rustc_hir::def::{DefKind, PartialRes, Res}; use rustc_hir::GenericArg; -use rustc_span::symbol::{kw, Ident}; +use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::{BytePos, Span, DUMMY_SP}; use smallvec::{smallvec, SmallVec}; @@ -352,11 +352,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // fn f(_: impl Fn() -> impl Debug) -> impl Fn() -> impl Debug // // disallowed --^^^^^^^^^^ allowed --^^^^^^^^^^ // ``` - FnRetTy::Ty(ty) - if matches!(itctx, ImplTraitContext::ReturnPositionOpaqueTy { .. }) - && self.tcx.features().impl_trait_in_fn_trait_return => - { - self.lower_ty(&ty, itctx) + FnRetTy::Ty(ty) if matches!(itctx, ImplTraitContext::ReturnPositionOpaqueTy { .. }) => { + if self.tcx.features().impl_trait_in_fn_trait_return { + self.lower_ty(&ty, itctx) + } else { + self.lower_ty( + &ty, + &ImplTraitContext::FeatureGated( + ImplTraitPosition::FnTraitReturn, + sym::impl_trait_in_fn_trait_return, + ), + ) + } } FnRetTy::Ty(ty) => { self.lower_ty(&ty, &ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitReturn)) diff --git a/src/test/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.stderr b/src/test/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.stderr index c485bc5c3ab9..760dcb615c87 100644 --- a/src/test/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.stderr +++ b/src/test/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.stderr @@ -3,12 +3,18 @@ error[E0562]: `impl Trait` only allowed in function and inherent method return t | LL | fn f() -> impl Fn() -> impl Sized { || () } | ^^^^^^^^^^ + | + = note: see issue #99697 for more information + = help: add `#![feature(impl_trait_in_fn_trait_return)]` to the crate attributes to enable error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return --> $DIR/feature-gate-impl_trait_in_fn_trait_return.rs:3:32 | LL | fn g() -> &'static dyn Fn() -> impl Sized { &|| () } | ^^^^^^^^^^ + | + = note: see issue #99697 for more information + = help: add `#![feature(impl_trait_in_fn_trait_return)]` to the crate attributes to enable error: aborting due to 2 previous errors From 530a687a4bb0bd0e8ab7b3f7d80f2c773be120ef Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Wed, 7 Dec 2022 08:40:49 +0100 Subject: [PATCH 107/115] Update LLVM submodule --- .gitmodules | 2 +- src/llvm-project | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index c85049378061..4011a6fa6b95 100644 --- a/.gitmodules +++ b/.gitmodules @@ -28,7 +28,7 @@ [submodule "src/llvm-project"] path = src/llvm-project url = https://github.com/rust-lang/llvm-project.git - branch = rustc/15.0-2022-08-09 + branch = rustc/15.0-2022-12-07 [submodule "src/doc/embedded-book"] path = src/doc/embedded-book url = https://github.com/rust-embedded/book.git diff --git a/src/llvm-project b/src/llvm-project index a1232c451fc2..3dfd4d93fa01 160000 --- a/src/llvm-project +++ b/src/llvm-project @@ -1 +1 @@ -Subproject commit a1232c451fc27173f8718e05d174b2503ca0b607 +Subproject commit 3dfd4d93fa013e1c0578d3ceac5c8f4ebba4b6ec From a9cf163c08136be23efab4ee5ed9649ad7e6c89c Mon Sep 17 00:00:00 2001 From: Daniil Belov <70999565+BelovDV@users.noreply.github.com> Date: Wed, 7 Dec 2022 13:13:58 +0300 Subject: [PATCH 108/115] fix: remove hack from link.rs (moved to libc) --- compiler/rustc_codegen_ssa/src/back/link.rs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 7cb4f5503a10..540f15c89e92 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -2352,15 +2352,6 @@ fn add_native_libs_from_crate( &search_paths.get_or_init(|| archive_search_paths(sess)), ); } else { - // HACK/FIXME: Fixup a circular dependency between libgcc and libc - // with glibc. This logic should be moved to the libc crate. - if cnum != LOCAL_CRATE - && sess.target.os == "linux" - && sess.target.env == "gnu" - && name == "c" - { - cmd.link_staticlib("gcc", false); - } cmd.link_staticlib(name, verbatim) } } From d30848b30a4ba328b482e2e601de7517be2e5397 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 6 Dec 2022 12:46:10 +0000 Subject: [PATCH 109/115] Use `Symbol` for the crate name instead of `String`/`str` --- compiler/rustc_codegen_ssa/src/back/link.rs | 2 +- compiler/rustc_driver/src/lib.rs | 9 +++-- compiler/rustc_expand/src/base.rs | 2 +- compiler/rustc_expand/src/expand.rs | 2 +- compiler/rustc_hir/src/tests.rs | 38 ++++++++++-------- compiler/rustc_incremental/src/persist/fs.rs | 5 ++- compiler/rustc_interface/src/passes.rs | 40 ++++++++++--------- compiler/rustc_interface/src/queries.rs | 21 +++++----- compiler/rustc_metadata/src/creader.rs | 6 +-- compiler/rustc_metadata/src/fs.rs | 3 +- compiler/rustc_middle/src/ty/context.rs | 4 +- compiler/rustc_resolve/src/lib.rs | 2 +- .../rustc_save_analysis/src/dump_visitor.rs | 6 +-- compiler/rustc_save_analysis/src/lib.rs | 8 ++-- compiler/rustc_session/src/errors.rs | 8 ++-- compiler/rustc_session/src/output.rs | 29 +++++++------- compiler/rustc_span/src/def_id.rs | 8 ++-- .../hotplug_codegen_backend/the_backend.rs | 2 +- 18 files changed, 103 insertions(+), 92 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 7cb4f5503a10..9e1481593233 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -102,7 +102,7 @@ pub fn link_binary<'a>( sess, crate_type, outputs, - codegen_results.crate_info.local_crate_name.as_str(), + codegen_results.crate_info.local_crate_name, ); match crate_type { CrateType::Rlib => { diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index 22f87514dd8f..f06ca5a0733a 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -25,6 +25,7 @@ use rustc_data_structures::sync::SeqCst; use rustc_errors::registry::{InvalidErrorCode, Registry}; use rustc_errors::{ErrorGuaranteed, PResult}; use rustc_feature::find_gated_cfg; +use rustc_hir::def_id::LOCAL_CRATE; use rustc_interface::util::{self, collect_crate_types, get_codegen_backend}; use rustc_interface::{interface, Queries}; use rustc_lint::LintStore; @@ -374,14 +375,14 @@ fn run_compiler( queries.global_ctxt()?.peek_mut().enter(|tcx| { let result = tcx.analysis(()); if sess.opts.unstable_opts.save_analysis { - let crate_name = queries.crate_name()?.peek().clone(); + let crate_name = tcx.crate_name(LOCAL_CRATE); sess.time("save_analysis", || { save::process_crate( tcx, - &crate_name, + crate_name, compiler.input(), None, - DumpHandler::new(compiler.output_dir().as_deref(), &crate_name), + DumpHandler::new(compiler.output_dir().as_deref(), crate_name), ) }); } @@ -678,7 +679,7 @@ fn print_crate_info( let crate_types = collect_crate_types(sess, attrs); for &style in &crate_types { let fname = - rustc_session::output::filename_for_input(sess, style, &id, &t_outputs); + rustc_session::output::filename_for_input(sess, style, id, &t_outputs); println!("{}", fname.file_name().unwrap().to_string_lossy()); } } diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 13e2d1ebbe78..9d6a4f9a1fd7 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -960,7 +960,7 @@ pub trait LintStoreExpand { node_id: NodeId, attrs: &[Attribute], items: &[P], - name: &str, + name: Symbol, ); } diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index e799fa404f6f..1014ec2209c6 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -1122,7 +1122,7 @@ impl InvocationCollectorNode for P { ecx.current_expansion.lint_node_id, &attrs, &items, - ident.name.as_str(), + ident.name, ); } diff --git a/compiler/rustc_hir/src/tests.rs b/compiler/rustc_hir/src/tests.rs index 4636d515249d..d4791150947f 100644 --- a/compiler/rustc_hir/src/tests.rs +++ b/compiler/rustc_hir/src/tests.rs @@ -1,5 +1,7 @@ use crate::definitions::{DefKey, DefPathData, DisambiguatedDefPathData}; use rustc_span::def_id::{DefPathHash, StableCrateId}; +use rustc_span::edition::Edition; +use rustc_span::{create_session_if_not_set_then, Symbol}; #[test] fn def_path_hash_depends_on_crate_id() { @@ -11,26 +13,28 @@ fn def_path_hash_depends_on_crate_id() { // the crate by changing the crate disambiguator (e.g. via bumping the // crate's version number). - let id0 = StableCrateId::new("foo", false, vec!["1".to_string()]); - let id1 = StableCrateId::new("foo", false, vec!["2".to_string()]); + create_session_if_not_set_then(Edition::Edition2024, |_| { + let id0 = StableCrateId::new(Symbol::intern("foo"), false, vec!["1".to_string()]); + let id1 = StableCrateId::new(Symbol::intern("foo"), false, vec!["2".to_string()]); - let h0 = mk_test_hash(id0); - let h1 = mk_test_hash(id1); + let h0 = mk_test_hash(id0); + let h1 = mk_test_hash(id1); - assert_ne!(h0.stable_crate_id(), h1.stable_crate_id()); - assert_ne!(h0.local_hash(), h1.local_hash()); + assert_ne!(h0.stable_crate_id(), h1.stable_crate_id()); + assert_ne!(h0.local_hash(), h1.local_hash()); - fn mk_test_hash(stable_crate_id: StableCrateId) -> DefPathHash { - let parent_hash = DefPathHash::new(stable_crate_id, 0); + fn mk_test_hash(stable_crate_id: StableCrateId) -> DefPathHash { + let parent_hash = DefPathHash::new(stable_crate_id, 0); - let key = DefKey { - parent: None, - disambiguated_data: DisambiguatedDefPathData { - data: DefPathData::CrateRoot, - disambiguator: 0, - }, - }; + let key = DefKey { + parent: None, + disambiguated_data: DisambiguatedDefPathData { + data: DefPathData::CrateRoot, + disambiguator: 0, + }, + }; - key.compute_stable_hash(parent_hash) - } + key.compute_stable_hash(parent_hash) + } + }) } diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs index 58d6e6d7efd6..97ebed058557 100644 --- a/compiler/rustc_incremental/src/persist/fs.rs +++ b/compiler/rustc_incremental/src/persist/fs.rs @@ -109,6 +109,7 @@ use rustc_data_structures::{base_n, flock}; use rustc_errors::ErrorGuaranteed; use rustc_fs_util::{link_or_copy, LinkOrCopy}; use rustc_session::{Session, StableCrateId}; +use rustc_span::Symbol; use std::fs as std_fs; use std::io::{self, ErrorKind}; @@ -202,7 +203,7 @@ pub fn in_incr_comp_dir(incr_comp_session_dir: &Path, file_name: &str) -> PathBu /// [`rustc_interface::queries::dep_graph`]: ../../rustc_interface/struct.Queries.html#structfield.dep_graph pub fn prepare_session_directory( sess: &Session, - crate_name: &str, + crate_name: Symbol, stable_crate_id: StableCrateId, ) -> Result<(), ErrorGuaranteed> { if sess.opts.incremental.is_none() { @@ -657,7 +658,7 @@ fn string_to_timestamp(s: &str) -> Result { Ok(UNIX_EPOCH + duration) } -fn crate_path(sess: &Session, crate_name: &str, stable_crate_id: StableCrateId) -> PathBuf { +fn crate_path(sess: &Session, crate_name: Symbol, stable_crate_id: StableCrateId) -> PathBuf { let incr_dir = sess.opts.incremental.as_ref().unwrap().clone(); let stable_crate_id = base_n::encode(stable_crate_id.to_u64() as u128, INT_ENCODE_BASE); diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index f75c8669fa1e..f808c1438bfc 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -158,7 +158,7 @@ pub fn create_resolver( sess: Lrc, metadata_loader: Box, krate: &ast::Crate, - crate_name: &str, + crate_name: Symbol, ) -> BoxedResolver { trace!("create_resolver"); BoxedResolver::new(sess, move |sess, resolver_arenas| { @@ -171,7 +171,7 @@ pub fn register_plugins<'a>( metadata_loader: &'a dyn MetadataLoader, register_lints: impl Fn(&Session, &mut LintStore), mut krate: ast::Crate, - crate_name: &str, + crate_name: Symbol, ) -> Result<(ast::Crate, LintStore)> { krate = sess.time("attributes_injection", || { rustc_builtin_macros::cmdline_attrs::inject( @@ -228,19 +228,21 @@ fn pre_expansion_lint<'a>( lint_store: &LintStore, registered_tools: &RegisteredTools, check_node: impl EarlyCheckNode<'a>, - node_name: &str, + node_name: Symbol, ) { - sess.prof.generic_activity_with_arg("pre_AST_expansion_lint_checks", node_name).run(|| { - rustc_lint::check_ast_node( - sess, - true, - lint_store, - registered_tools, - None, - rustc_lint::BuiltinCombinedPreExpansionLintPass::new(), - check_node, - ); - }); + sess.prof.generic_activity_with_arg("pre_AST_expansion_lint_checks", node_name.as_str()).run( + || { + rustc_lint::check_ast_node( + sess, + true, + lint_store, + registered_tools, + None, + rustc_lint::BuiltinCombinedPreExpansionLintPass::new(), + check_node, + ); + }, + ); } // Cannot implement directly for `LintStore` due to trait coherence. @@ -254,7 +256,7 @@ impl LintStoreExpand for LintStoreExpandImpl<'_> { node_id: ast::NodeId, attrs: &[ast::Attribute], items: &[rustc_ast::ptr::P], - name: &str, + name: Symbol, ) { pre_expansion_lint(sess, self.0, registered_tools, (node_id, attrs, items), name); } @@ -268,7 +270,7 @@ pub fn configure_and_expand( sess: &Session, lint_store: &LintStore, mut krate: ast::Crate, - crate_name: &str, + crate_name: Symbol, resolver: &mut Resolver<'_>, ) -> Result { trace!("configure_and_expand"); @@ -462,7 +464,7 @@ fn generated_output_paths( sess: &Session, outputs: &OutputFilenames, exact_name: bool, - crate_name: &str, + crate_name: Symbol, ) -> Vec { let mut out_filenames = Vec::new(); for output_type in sess.opts.output_types.keys() { @@ -661,7 +663,7 @@ pub fn prepare_outputs( compiler: &Compiler, krate: &ast::Crate, boxed_resolver: &RefCell, - crate_name: &str, + crate_name: Symbol, ) -> Result { let _timer = sess.timer("prepare_outputs"); @@ -771,7 +773,7 @@ pub fn create_global_ctxt<'tcx>( dep_graph: DepGraph, resolver: Rc>, outputs: OutputFilenames, - crate_name: &str, + crate_name: Symbol, queries: &'tcx OnceCell>, global_ctxt: &'tcx OnceCell>, arena: &'tcx WorkerLocal>, diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index f5ddd647b243..39e1f2204b00 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -17,6 +17,7 @@ use rustc_query_impl::Queries as TcxQueries; use rustc_session::config::{self, OutputFilenames, OutputType}; use rustc_session::{output::find_crate_name, Session}; use rustc_span::symbol::sym; +use rustc_span::Symbol; use std::any::Any; use std::cell::{Ref, RefCell, RefMut}; use std::rc::Rc; @@ -74,7 +75,7 @@ pub struct Queries<'tcx> { dep_graph_future: Query>, parse: Query, - crate_name: Query, + crate_name: Query, register_plugins: Query<(ast::Crate, Lrc)>, expansion: Query<(Lrc, Rc>, Lrc)>, dep_graph: Query, @@ -135,7 +136,7 @@ impl<'tcx> Queries<'tcx> { &*self.codegen_backend().metadata_loader(), self.compiler.register_lints.as_deref().unwrap_or_else(|| empty), krate, - &crate_name, + crate_name, )?; // Compute the dependency graph (in the background). We want to do @@ -149,7 +150,7 @@ impl<'tcx> Queries<'tcx> { }) } - pub fn crate_name(&self) -> Result<&Query> { + pub fn crate_name(&self) -> Result<&Query> { self.crate_name.compute(|| { Ok({ let parse_result = self.parse()?; @@ -165,7 +166,7 @@ impl<'tcx> Queries<'tcx> { ) -> Result<&Query<(Lrc, Rc>, Lrc)>> { trace!("expansion"); self.expansion.compute(|| { - let crate_name = self.crate_name()?.peek().clone(); + let crate_name = *self.crate_name()?.peek(); let (krate, lint_store) = self.register_plugins()?.take(); let _timer = self.session().timer("configure_and_expand"); let sess = self.session(); @@ -173,10 +174,10 @@ impl<'tcx> Queries<'tcx> { sess.clone(), self.codegen_backend().metadata_loader(), &krate, - &crate_name, + crate_name, ); let krate = resolver.access(|resolver| { - passes::configure_and_expand(sess, &lint_store, krate, &crate_name, resolver) + passes::configure_and_expand(sess, &lint_store, krate, crate_name, resolver) })?; Ok((Lrc::new(krate), Rc::new(RefCell::new(resolver)), lint_store)) }) @@ -201,20 +202,20 @@ impl<'tcx> Queries<'tcx> { pub fn prepare_outputs(&self) -> Result<&Query> { self.prepare_outputs.compute(|| { let (krate, boxed_resolver, _) = &*self.expansion()?.peek(); - let crate_name = self.crate_name()?.peek(); + let crate_name = *self.crate_name()?.peek(); passes::prepare_outputs( self.session(), self.compiler, krate, &*boxed_resolver, - &crate_name, + crate_name, ) }) } pub fn global_ctxt(&'tcx self) -> Result<&Query>> { self.global_ctxt.compute(|| { - let crate_name = self.crate_name()?.peek().clone(); + let crate_name = *self.crate_name()?.peek(); let outputs = self.prepare_outputs()?.take(); let dep_graph = self.dep_graph()?.peek().clone(); let (krate, resolver, lint_store) = self.expansion()?.take(); @@ -225,7 +226,7 @@ impl<'tcx> Queries<'tcx> { dep_graph, resolver, outputs, - &crate_name, + crate_name, &self.queries, &self.gcx, &self.arena, diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index 1a2389c7a844..efeaac8fe9a0 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -245,7 +245,7 @@ impl<'a> CrateLoader<'a> { pub fn new( sess: &'a Session, metadata_loader: Box, - local_crate_name: &str, + local_crate_name: Symbol, ) -> Self { let mut stable_crate_ids = FxHashMap::default(); stable_crate_ids.insert(sess.local_stable_crate_id(), LOCAL_CRATE); @@ -253,7 +253,7 @@ impl<'a> CrateLoader<'a> { CrateLoader { sess, metadata_loader, - local_crate_name: Symbol::intern(local_crate_name), + local_crate_name, cstore: CStore { // We add an empty entry for LOCAL_CRATE (which maps to zero) in // order to make array indices in `metas` match with the @@ -1000,7 +1000,7 @@ impl<'a> CrateLoader<'a> { ); let name = match orig_name { Some(orig_name) => { - validate_crate_name(self.sess, orig_name.as_str(), Some(item.span)); + validate_crate_name(self.sess, orig_name, Some(item.span)); orig_name } None => item.ident.name, diff --git a/compiler/rustc_metadata/src/fs.rs b/compiler/rustc_metadata/src/fs.rs index 4fa440c7ca69..7601f6bd3221 100644 --- a/compiler/rustc_metadata/src/fs.rs +++ b/compiler/rustc_metadata/src/fs.rs @@ -61,8 +61,7 @@ pub fn encode_and_write_metadata(tcx: TyCtxt<'_>) -> (EncodedMetadata, bool) { .unwrap_or(MetadataKind::None); let crate_name = tcx.crate_name(LOCAL_CRATE); - let out_filename = - filename_for_metadata(tcx.sess, crate_name.as_str(), tcx.output_filenames(())); + let out_filename = filename_for_metadata(tcx.sess, crate_name, tcx.output_filenames(())); // To avoid races with another rustc process scanning the output directory, // we need to write the file somewhere else and atomically move it to its // final destination, with an `fs::rename` call. In order for the rename to diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index c39d04d38193..bbd7eb9de90b 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1281,7 +1281,7 @@ impl<'tcx> TyCtxt<'tcx> { on_disk_cache: Option<&'tcx dyn OnDiskCache<'tcx>>, queries: &'tcx dyn query::QueryEngine<'tcx>, query_kinds: &'tcx [DepKindStruct<'tcx>], - crate_name: &str, + crate_name: Symbol, output_filenames: OutputFilenames, ) -> GlobalCtxt<'tcx> { let data_layout = s.target.parse_data_layout().unwrap_or_else(|err| { @@ -1321,7 +1321,7 @@ impl<'tcx> TyCtxt<'tcx> { pred_rcache: Default::default(), selection_cache: Default::default(), evaluation_cache: Default::default(), - crate_name: Symbol::intern(crate_name), + crate_name, data_layout, alloc_map: Lock::new(interpret::AllocMap::new()), output_filenames: Arc::new(output_filenames), diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 4ef89cfb2554..82f5d0f534a4 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1196,7 +1196,7 @@ impl<'a> Resolver<'a> { pub fn new( session: &'a Session, krate: &Crate, - crate_name: &str, + crate_name: Symbol, metadata_loader: Box, arenas: &'a ResolverArenas<'a>, ) -> Resolver<'a> { diff --git a/compiler/rustc_save_analysis/src/dump_visitor.rs b/compiler/rustc_save_analysis/src/dump_visitor.rs index b45288538256..9ae07cb005bd 100644 --- a/compiler/rustc_save_analysis/src/dump_visitor.rs +++ b/compiler/rustc_save_analysis/src/dump_visitor.rs @@ -111,7 +111,7 @@ impl<'tcx> DumpVisitor<'tcx> { self.save_ctxt.lookup_def_id(ref_id) } - pub fn dump_crate_info(&mut self, name: &str) { + pub fn dump_crate_info(&mut self, name: Symbol) { let source_file = self.tcx.sess.local_crate_source_file.as_ref(); let crate_root = source_file.map(|source_file| { let source_file = Path::new(source_file); @@ -124,7 +124,7 @@ impl<'tcx> DumpVisitor<'tcx> { let data = CratePreludeData { crate_id: GlobalCrateId { - name: name.into(), + name: name.to_string(), disambiguator: (self.tcx.sess.local_stable_crate_id().to_u64(), 0), }, crate_root: crate_root.unwrap_or_else(|| "".to_owned()), @@ -135,7 +135,7 @@ impl<'tcx> DumpVisitor<'tcx> { self.dumper.crate_prelude(data); } - pub fn dump_compilation_options(&mut self, input: &Input, crate_name: &str) { + pub fn dump_compilation_options(&mut self, input: &Input, crate_name: Symbol) { // Apply possible `remap-path-prefix` remapping to the input source file // (and don't include remapping args anymore) let (program, arguments) = { diff --git a/compiler/rustc_save_analysis/src/lib.rs b/compiler/rustc_save_analysis/src/lib.rs index f05eb2b7432b..7735c571310d 100644 --- a/compiler/rustc_save_analysis/src/lib.rs +++ b/compiler/rustc_save_analysis/src/lib.rs @@ -95,7 +95,7 @@ impl<'tcx> SaveContext<'tcx> { } /// Returns path to the compilation output (e.g., libfoo-12345678.rmeta) - pub fn compilation_output(&self, crate_name: &str) -> PathBuf { + pub fn compilation_output(&self, crate_name: Symbol) -> PathBuf { let sess = &self.tcx.sess; // Save-analysis is emitted per whole session, not per each crate type let crate_type = sess.crate_types()[0]; @@ -894,8 +894,8 @@ pub struct DumpHandler<'a> { } impl<'a> DumpHandler<'a> { - pub fn new(odir: Option<&'a Path>, cratename: &str) -> DumpHandler<'a> { - DumpHandler { odir, cratename: cratename.to_owned() } + pub fn new(odir: Option<&'a Path>, cratename: Symbol) -> DumpHandler<'a> { + DumpHandler { odir, cratename: cratename.to_string() } } fn output_file(&self, ctx: &SaveContext<'_>) -> (BufWriter, PathBuf) { @@ -960,7 +960,7 @@ impl SaveHandler for CallbackHandler<'_> { pub fn process_crate<'l, 'tcx, H: SaveHandler>( tcx: TyCtxt<'tcx>, - cratename: &str, + cratename: Symbol, input: &'l Input, config: Option, mut handler: H, diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index 8cb9e1a6f1ae..ee492f802a70 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -129,10 +129,10 @@ pub struct FileIsNotWriteable<'a> { #[derive(Diagnostic)] #[diag(session_crate_name_does_not_match)] -pub struct CrateNameDoesNotMatch<'a> { +pub struct CrateNameDoesNotMatch { #[primary_span] pub span: Span, - pub s: &'a str, + pub s: Symbol, pub name: Symbol, } @@ -151,11 +151,11 @@ pub struct CrateNameEmpty { #[derive(Diagnostic)] #[diag(session_invalid_character_in_create_name)] -pub struct InvalidCharacterInCrateName<'a> { +pub struct InvalidCharacterInCrateName { #[primary_span] pub span: Option, pub character: char, - pub crate_name: &'a str, + pub crate_name: Symbol, } #[derive(Subdiagnostic)] diff --git a/compiler/rustc_session/src/output.rs b/compiler/rustc_session/src/output.rs index 2511bee46afe..8ee3057de625 100644 --- a/compiler/rustc_session/src/output.rs +++ b/compiler/rustc_session/src/output.rs @@ -7,14 +7,14 @@ use crate::errors::{ use crate::Session; use rustc_ast as ast; use rustc_span::symbol::sym; -use rustc_span::Span; +use rustc_span::{Span, Symbol}; use std::path::{Path, PathBuf}; pub fn out_filename( sess: &Session, crate_type: CrateType, outputs: &OutputFilenames, - crate_name: &str, + crate_name: Symbol, ) -> PathBuf { let default_filename = filename_for_input(sess, crate_type, crate_name, outputs); let out_filename = outputs @@ -45,9 +45,9 @@ fn is_writeable(p: &Path) -> bool { } } -pub fn find_crate_name(sess: &Session, attrs: &[ast::Attribute], input: &Input) -> String { - let validate = |s: String, span: Option| { - validate_crate_name(sess, &s, span); +pub fn find_crate_name(sess: &Session, attrs: &[ast::Attribute], input: &Input) -> Symbol { + let validate = |s: Symbol, span: Option| { + validate_crate_name(sess, s, span); s }; @@ -59,38 +59,39 @@ pub fn find_crate_name(sess: &Session, attrs: &[ast::Attribute], input: &Input) sess.find_by_name(attrs, sym::crate_name).and_then(|at| at.value_str().map(|s| (at, s))); if let Some(ref s) = sess.opts.crate_name { + let s = Symbol::intern(s); if let Some((attr, name)) = attr_crate_name { - if name.as_str() != s { + if name != s { sess.emit_err(CrateNameDoesNotMatch { span: attr.span, s, name }); } } - return validate(s.clone(), None); + return validate(s, None); } if let Some((attr, s)) = attr_crate_name { - return validate(s.to_string(), Some(attr.span)); + return validate(s, Some(attr.span)); } if let Input::File(ref path) = *input { if let Some(s) = path.file_stem().and_then(|s| s.to_str()) { if s.starts_with('-') { sess.emit_err(CrateNameInvalid { s }); } else { - return validate(s.replace('-', "_"), None); + return validate(Symbol::intern(&s.replace('-', "_")), None); } } } - "rust_out".to_string() + Symbol::intern("rust_out") } -pub fn validate_crate_name(sess: &Session, s: &str, sp: Option) { +pub fn validate_crate_name(sess: &Session, s: Symbol, sp: Option) { let mut err_count = 0; { if s.is_empty() { err_count += 1; sess.emit_err(CrateNameEmpty { span: sp }); } - for c in s.chars() { + for c in s.as_str().chars() { if c.is_alphanumeric() { continue; } @@ -109,7 +110,7 @@ pub fn validate_crate_name(sess: &Session, s: &str, sp: Option) { pub fn filename_for_metadata( sess: &Session, - crate_name: &str, + crate_name: Symbol, outputs: &OutputFilenames, ) -> PathBuf { // If the command-line specified the path, use that directly. @@ -132,7 +133,7 @@ pub fn filename_for_metadata( pub fn filename_for_input( sess: &Session, crate_type: CrateType, - crate_name: &str, + crate_name: Symbol, outputs: &OutputFilenames, ) -> PathBuf { let libname = format!("{}{}", crate_name, sess.opts.cg.extra_filename); diff --git a/compiler/rustc_span/src/def_id.rs b/compiler/rustc_span/src/def_id.rs index f5555846d20a..b122bd0722d9 100644 --- a/compiler/rustc_span/src/def_id.rs +++ b/compiler/rustc_span/src/def_id.rs @@ -1,4 +1,4 @@ -use crate::HashStableContext; +use crate::{HashStableContext, Symbol}; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey}; use rustc_data_structures::AtomicRef; @@ -149,9 +149,11 @@ impl StableCrateId { /// Computes the stable ID for a crate with the given name and /// `-Cmetadata` arguments. - pub fn new(crate_name: &str, is_exe: bool, mut metadata: Vec) -> StableCrateId { + pub fn new(crate_name: Symbol, is_exe: bool, mut metadata: Vec) -> StableCrateId { let mut hasher = StableHasher::new(); - crate_name.hash(&mut hasher); + // We must hash the string text of the crate name, not the id, as the id is not stable + // across builds. + crate_name.as_str().hash(&mut hasher); // We don't want the stable crate ID to depend on the order of // -C metadata arguments, so sort them: diff --git a/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs b/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs index 2c4309fbe66f..3aa57d58908b 100644 --- a/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs +++ b/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs @@ -67,7 +67,7 @@ impl CodegenBackend for TheBackend { if crate_type != CrateType::Rlib { sess.fatal(&format!("Crate type is {:?}", crate_type)); } - let output_name = out_filename(sess, crate_type, &outputs, &*crate_name.as_str()); + let output_name = out_filename(sess, crate_type, &outputs, crate_name); let mut out_file = ::std::fs::File::create(output_name).unwrap(); write!(out_file, "This has been \"compiled\" successfully.").unwrap(); } From 8bc30cb0f1ec744517d0e5e87fb95c01a7095b2f Mon Sep 17 00:00:00 2001 From: Dan Johnson Date: Wed, 7 Dec 2022 14:15:56 -0800 Subject: [PATCH 110/115] CI: add missing line continuation marker Resolves this docker warning: ``` [WARNING]: Empty continuation line found in: RUN apt-get update && apt-get install -y --no-install-recommends g++ gcc-multilib make ninja-build file curl ca-certificates python2.7 python3.9 git cmake sudo gdb llvm-13-tools llvm-13-dev libedit-dev libssl-dev pkg-config zlib1g-dev xz-utils nodejs apt-transport-https software-properties-common && curl -s "https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/packages-microsoft-prod.deb" > packages-microsoft-prod.deb && dpkg -i packages-microsoft-prod.deb && apt-get update && apt-get install -y powershell && rm -rf /var/lib/apt/lists/* Warning: : Empty continuation lines will become errors in a future release. ``` --- src/ci/docker/host-x86_64/x86_64-gnu-llvm-13/Dockerfile | 2 +- src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-13/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-13/Dockerfile index c3b47c3510d4..06f15bd12117 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-13/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-13/Dockerfile @@ -25,7 +25,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ zlib1g-dev \ xz-utils \ nodejs \ - + \ # Install powershell so we can test x.ps1 on Linux apt-transport-https software-properties-common && \ curl -s "https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/packages-microsoft-prod.deb" > packages-microsoft-prod.deb && \ diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile index 501d27816462..58c0c5db1a5d 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile @@ -15,7 +15,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ sudo \ xz-utils \ tidy \ - + \ # Install dependencies for chromium browser gconf-service \ libasound2 \ From a3c4c2ee1d8d94141328d2b955ec7dc4aa67aa54 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Thu, 8 Dec 2022 00:07:00 +0000 Subject: [PATCH 111/115] Fix warning when libcore is compiled with no_fp_fmt_parse --- library/core/src/num/mod.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index b2328b001de9..ac7f579ebb5a 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -4,12 +4,14 @@ use crate::ascii; use crate::convert::TryInto; -use crate::error::Error; use crate::intrinsics; use crate::mem; use crate::ops::{Add, Mul, Sub}; use crate::str::FromStr; +#[cfg(not(no_fp_fmt_parse))] +use crate::error::Error; + // Used because the `?` operator is not allowed in a const context. macro_rules! try_opt { ($e:expr) => { From 7a4669285ac270a4a3deb9cf10bc9d5e40e6b2df Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 8 Dec 2022 15:42:12 +1100 Subject: [PATCH 112/115] Remove `UnsafetyState`. `FnCtxt::ps` is the only occurrence. It gets updated during HIR typechecking, but is never looked at. --- compiler/rustc_hir_typeck/src/check.rs | 3 +- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 3 -- compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs | 5 +-- compiler/rustc_hir_typeck/src/lib.rs | 32 ------------------- 4 files changed, 2 insertions(+), 41 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs index 0c9a350c295f..32f86b8042c1 100644 --- a/compiler/rustc_hir_typeck/src/check.rs +++ b/compiler/rustc_hir_typeck/src/check.rs @@ -1,7 +1,7 @@ use crate::coercion::CoerceMany; use crate::gather_locals::GatherLocalsVisitor; use crate::FnCtxt; -use crate::{GeneratorTypes, UnsafetyState}; +use crate::GeneratorTypes; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::intravisit::Visitor; @@ -30,7 +30,6 @@ pub(super) fn check_fn<'a, 'tcx>( can_be_generator: Option, ) -> Option> { let fn_id = fcx.tcx.hir().local_def_id_to_hir_id(fn_def_id); - fcx.ps.set(UnsafetyState::function(fn_sig.unsafety, fn_id)); let tcx = fcx.tcx; let hir = tcx.hir(); diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 8a875e05b19b..60fec05d36d6 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -1393,8 +1393,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { blk: &'tcx hir::Block<'tcx>, expected: Expectation<'tcx>, ) -> Ty<'tcx> { - let prev = self.ps.replace(self.ps.get().recurse(blk)); - // In some cases, blocks have just one exit, but other blocks // can be targeted by multiple breaks. This can happen both // with labeled blocks as well as when we desugar @@ -1558,7 +1556,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.write_ty(blk.hir_id, ty); - self.ps.set(prev); ty } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index 1e9b57521308..30b59da7852d 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -8,7 +8,7 @@ use rustc_errors::ErrorGuaranteed; pub use suggestions::*; use crate::coercion::DynamicCoerceMany; -use crate::{Diverges, EnclosingBreakables, Inherited, UnsafetyState}; +use crate::{Diverges, EnclosingBreakables, Inherited}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir_analysis::astconv::AstConv; @@ -74,8 +74,6 @@ pub struct FnCtxt<'a, 'tcx> { pub(super) resume_yield_tys: Option<(Ty<'tcx>, Ty<'tcx>)>, - pub(super) ps: Cell, - /// Whether the last checked node generates a divergence (e.g., /// `return` will set this to `Always`). In general, when entering /// an expression or other node in the tree, the initial value @@ -129,7 +127,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ret_coercion: None, ret_coercion_span: Cell::new(None), resume_yield_tys: None, - ps: Cell::new(UnsafetyState::function(hir::Unsafety::Normal, hir::CRATE_HIR_ID)), diverges: Cell::new(Diverges::Maybe), enclosing_breakables: RefCell::new(EnclosingBreakables { stack: Vec::new(), diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 09bd123350df..5b2352cda34b 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -89,38 +89,6 @@ pub struct LocalTy<'tcx> { revealed_ty: Ty<'tcx>, } -#[derive(Copy, Clone)] -pub struct UnsafetyState { - pub def: hir::HirId, - pub unsafety: hir::Unsafety, - from_fn: bool, -} - -impl UnsafetyState { - pub fn function(unsafety: hir::Unsafety, def: hir::HirId) -> UnsafetyState { - UnsafetyState { def, unsafety, from_fn: true } - } - - pub fn recurse(self, blk: &hir::Block<'_>) -> UnsafetyState { - use hir::BlockCheckMode; - match self.unsafety { - // If this unsafe, then if the outer function was already marked as - // unsafe we shouldn't attribute the unsafe'ness to the block. This - // way the block can be warned about instead of ignoring this - // extraneous block (functions are never warned about). - hir::Unsafety::Unsafe if self.from_fn => self, - - unsafety => { - let (unsafety, def) = match blk.rules { - BlockCheckMode::UnsafeBlock(..) => (hir::Unsafety::Unsafe, blk.hir_id), - BlockCheckMode::DefaultBlock => (unsafety, self.def), - }; - UnsafetyState { def, unsafety, from_fn: false } - } - } - } -} - /// If this `DefId` is a "primary tables entry", returns /// `Some((body_id, body_ty, fn_sig))`. Otherwise, returns `None`. /// From 9af48e5ab6a9eab1c966d78355513469514e16db Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 8 Dec 2022 15:53:31 +1100 Subject: [PATCH 113/115] Fix a typo. --- compiler/rustc_hir/src/hir.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 636e6e1b48d0..8bc022e1e178 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -827,7 +827,7 @@ impl<'tcx> AttributeMap<'tcx> { pub struct OwnerNodes<'tcx> { /// Pre-computed hash of the full HIR. pub hash_including_bodies: Fingerprint, - /// Pre-computed hash of the item signature, sithout recursing into the body. + /// Pre-computed hash of the item signature, without recursing into the body. pub hash_without_bodies: Fingerprint, /// Full HIR for the current owner. // The zeroth node's parent should never be accessed: the owner's parent is computed by the From c1d5a5a246d50ab22bec6f3102f8c4179ecf98d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Thu, 8 Dec 2022 00:00:00 +0000 Subject: [PATCH 114/115] Ignore errors when including clear_expected_if_blessed Include is there only for the effect executing the rule. The file is not intended to be remade successfully to be actually included. --- src/test/run-make/coverage-reports/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/run-make/coverage-reports/Makefile b/src/test/run-make/coverage-reports/Makefile index 436aebf1174d..d06cd9c6a54f 100644 --- a/src/test/run-make/coverage-reports/Makefile +++ b/src/test/run-make/coverage-reports/Makefile @@ -80,7 +80,7 @@ ifdef RUSTC_BLESS_TEST rm -f expected_* endif -include clear_expected_if_blessed +-include clear_expected_if_blessed %: $(SOURCEDIR)/lib/%.rs # Compile the test library with coverage instrumentation From b70a869d8f49e87d8432de6af6d209243a7053a4 Mon Sep 17 00:00:00 2001 From: yukang Date: Sat, 10 Dec 2022 01:31:34 +0800 Subject: [PATCH 115/115] fix #105366, suggest impl in the scenario of typo with fn --- .../locales/en-US/parse.ftl | 3 +++ compiler/rustc_parse/src/errors.rs | 8 ++++++++ compiler/rustc_parse/src/parser/item.rs | 20 +++++++++++++++++-- src/test/ui/parser/issue-105366.fixed | 12 +++++++++++ src/test/ui/parser/issue-105366.rs | 12 +++++++++++ src/test/ui/parser/issue-105366.stderr | 13 ++++++++++++ 6 files changed, 66 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/parser/issue-105366.fixed create mode 100644 src/test/ui/parser/issue-105366.rs create mode 100644 src/test/ui/parser/issue-105366.stderr diff --git a/compiler/rustc_error_messages/locales/en-US/parse.ftl b/compiler/rustc_error_messages/locales/en-US/parse.ftl index 114b7ec16288..b53550e5fd55 100644 --- a/compiler/rustc_error_messages/locales/en-US/parse.ftl +++ b/compiler/rustc_error_messages/locales/en-US/parse.ftl @@ -362,3 +362,6 @@ parse_fn_ptr_with_generics = function pointer types may not have generic paramet parse_invalid_identifier_with_leading_number = expected identifier, found number literal .label = identifiers cannot start with a number + +parse_maybe_fn_typo_with_impl = you might have meant to write `impl` instead of `fn` + .suggestion = replace `fn` with `impl` here diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 9875cde4a05e..18a0bee9c2e5 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -1221,3 +1221,11 @@ pub(crate) struct UnexpectedIfWithIf( #[suggestion(applicability = "machine-applicable", code = " ", style = "verbose")] pub Span, ); + +#[derive(Diagnostic)] +#[diag(parse_maybe_fn_typo_with_impl)] +pub(crate) struct FnTypoWithImpl { + #[primary_span] + #[suggestion(applicability = "maybe-incorrect", code = "impl", style = "verbose")] + pub fn_span: Span, +} diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 03f25392a7c1..ce4bc929c5cd 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -3,6 +3,7 @@ use crate::errors::{DocCommentDoesNotDocumentAnything, UseEmptyBlockNotSemi}; use super::diagnostics::{dummy_arg, ConsumeClosingDelim}; use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign}; use super::{AttrWrapper, FollowedByType, ForceCollect, Parser, PathStyle, TrailingToken}; +use crate::errors::FnTypoWithImpl; use rustc_ast::ast::*; use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter, TokenKind}; @@ -2126,11 +2127,26 @@ impl<'a> Parser<'a> { vis: &Visibility, case: Case, ) -> PResult<'a, (Ident, FnSig, Generics, Option>)> { + let fn_span = self.token.span; let header = self.parse_fn_front_matter(vis, case)?; // `const ... fn` let ident = self.parse_ident()?; // `foo` let mut generics = self.parse_generics()?; // `<'a, T, ...>` - let decl = - self.parse_fn_decl(fn_parse_mode.req_name, AllowPlus::Yes, RecoverReturnSign::Yes)?; // `(p: u8, ...)` + let decl = match self.parse_fn_decl( + fn_parse_mode.req_name, + AllowPlus::Yes, + RecoverReturnSign::Yes, + ) { + Ok(decl) => decl, + Err(old_err) => { + // If we see `for Ty ...` then user probably meant `impl` item. + if self.token.is_keyword(kw::For) { + old_err.cancel(); + return Err(self.sess.create_err(FnTypoWithImpl { fn_span })); + } else { + return Err(old_err); + } + } + }; generics.where_clause = self.parse_where_clause()?; // `where T: Ord` let mut sig_hi = self.prev_token.span; diff --git a/src/test/ui/parser/issue-105366.fixed b/src/test/ui/parser/issue-105366.fixed new file mode 100644 index 000000000000..ad26643c3279 --- /dev/null +++ b/src/test/ui/parser/issue-105366.fixed @@ -0,0 +1,12 @@ +// run-rustfix + +struct Foo; + +impl From for Foo { + //~^ ERROR you might have meant to write `impl` instead of `fn` + fn from(_a: i32) -> Self { + Foo + } +} + +fn main() {} diff --git a/src/test/ui/parser/issue-105366.rs b/src/test/ui/parser/issue-105366.rs new file mode 100644 index 000000000000..311b6a60f1a2 --- /dev/null +++ b/src/test/ui/parser/issue-105366.rs @@ -0,0 +1,12 @@ +// run-rustfix + +struct Foo; + +fn From for Foo { + //~^ ERROR you might have meant to write `impl` instead of `fn` + fn from(_a: i32) -> Self { + Foo + } +} + +fn main() {} diff --git a/src/test/ui/parser/issue-105366.stderr b/src/test/ui/parser/issue-105366.stderr new file mode 100644 index 000000000000..0a7408e2c173 --- /dev/null +++ b/src/test/ui/parser/issue-105366.stderr @@ -0,0 +1,13 @@ +error: you might have meant to write `impl` instead of `fn` + --> $DIR/issue-105366.rs:5:1 + | +LL | fn From for Foo { + | ^^ + | +help: replace `fn` with `impl` here + | +LL | impl From for Foo { + | ~~~~ + +error: aborting due to previous error +