From 74e7709485c7597ff7446ac9b420153e22f834fc Mon Sep 17 00:00:00 2001 From: Zachary Mayhew Date: Sat, 26 Nov 2022 15:41:48 -0800 Subject: [PATCH 001/105] reword Option::as_ref and Option::map examples --- library/core/src/option.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 505d964e518d..6bfe34390cc4 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -608,10 +608,10 @@ impl Option { /// /// # Examples /// - /// Converts an Option<[String]> into an Option<[usize]>, preserving - /// the original. The [`map`] method takes the `self` argument by value, consuming the original, - /// so this technique uses `as_ref` to first take an `Option` to a reference - /// to the value inside the original. + /// Calculates the length of an Option<[String]> as an Option<[usize]> + /// without moving the [`String`]. The [`map`] method takes the `self` argument by value, + /// consuming the original, so this technique uses `as_ref` to first take an `Option` to a + /// reference to the value inside the original. /// /// [`map`]: Option::map /// [String]: ../../std/string/struct.String.html "String" @@ -902,8 +902,8 @@ impl Option { /// /// # Examples /// - /// Converts an Option<[String]> into an Option<[usize]>, consuming - /// the original: + /// Calculates the length of an Option<[String]> as an + /// Option<[usize]>, consuming the original: /// /// [String]: ../../std/string/struct.String.html "String" /// ``` From 123e2038d4cd6b29ff3d30cf766e94b67efcb637 Mon Sep 17 00:00:00 2001 From: Zachary Mayhew Date: Sat, 26 Nov 2022 17:30:17 -0800 Subject: [PATCH 002/105] add link for string to as_ref docs --- library/core/src/option.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 6bfe34390cc4..48e6af36ac75 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -615,6 +615,7 @@ impl Option { /// /// [`map`]: Option::map /// [String]: ../../std/string/struct.String.html "String" + /// [`String`]: ../../std/string/struct.String.html "String" /// /// ``` /// let text: Option = Some("Hello, world!".to_string()); From a8b5d4b7f113975e35b1924af608989e0cd620cd Mon Sep 17 00:00:00 2001 From: Xiretza Date: Sat, 10 Dec 2022 09:27:07 +0100 Subject: [PATCH 003/105] libcore: make result type of iter::from_generator concrete This allows for propagating trait impls on the iterator type. --- .../core/src/iter/sources/from_generator.rs | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/library/core/src/iter/sources/from_generator.rs b/library/core/src/iter/sources/from_generator.rs index 8e7cbd34a4f6..a974d3c892d0 100644 --- a/library/core/src/iter/sources/from_generator.rs +++ b/library/core/src/iter/sources/from_generator.rs @@ -1,3 +1,4 @@ +use crate::fmt; use crate::ops::{Generator, GeneratorState}; use crate::pin::Pin; @@ -23,14 +24,20 @@ use crate::pin::Pin; /// ``` #[inline] #[unstable(feature = "iter_from_generator", issue = "43122", reason = "generators are unstable")] -pub fn from_generator + Unpin>( - generator: G, -) -> impl Iterator { +pub fn from_generator + Unpin>(generator: G) -> FromGenerator { FromGenerator(generator) } -struct FromGenerator(G); +/// An iterator over the values yielded by an underlying generator. +/// +/// This `struct` is created by the [`iter::from_generator()`] function. See its documentation for +/// more. +/// +/// [`iter::from_generator()`]: from_generator +#[unstable(feature = "iter_from_generator", issue = "43122", reason = "generators are unstable")] +pub struct FromGenerator(G); +#[unstable(feature = "iter_from_generator", issue = "43122", reason = "generators are unstable")] impl + Unpin> Iterator for FromGenerator { type Item = G::Yield; @@ -41,3 +48,10 @@ impl + Unpin> Iterator for FromGenerator { } } } + +#[unstable(feature = "iter_from_generator", issue = "43122", reason = "generators are unstable")] +impl fmt::Debug for FromGenerator { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("FromGenerator").finish() + } +} From 17a0740ebb1798ee29fc39c1ec025f0949144541 Mon Sep 17 00:00:00 2001 From: Xiretza Date: Sat, 10 Dec 2022 09:03:14 +0100 Subject: [PATCH 004/105] libcore: make result of iter::from_generator Clone This is currently only relevant with #![feature(generator_clone)]. --- library/core/src/iter/sources/from_generator.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/core/src/iter/sources/from_generator.rs b/library/core/src/iter/sources/from_generator.rs index a974d3c892d0..4cbe731b222f 100644 --- a/library/core/src/iter/sources/from_generator.rs +++ b/library/core/src/iter/sources/from_generator.rs @@ -35,6 +35,7 @@ pub fn from_generator + Unpin>(generator: G) -> FromGe /// /// [`iter::from_generator()`]: from_generator #[unstable(feature = "iter_from_generator", issue = "43122", reason = "generators are unstable")] +#[derive(Clone)] pub struct FromGenerator(G); #[unstable(feature = "iter_from_generator", issue = "43122", reason = "generators are unstable")] From c466be040f123289935c1f3a10fa8aba202bfcc8 Mon Sep 17 00:00:00 2001 From: Alexander Shirokov Date: Fri, 2 Dec 2022 14:10:45 +0100 Subject: [PATCH 005/105] Added error documentation for write_fmt This continuation of work at rust-lang#98861 --- library/core/src/fmt/mod.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 51e6a76cea84..fa5073e3304d 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -174,6 +174,11 @@ pub trait Write { /// This method should generally not be invoked manually, but rather through /// the [`write!`] macro itself. /// + /// # Errors + /// + /// This function will return an instance of [`Error`] on error. Please see + /// [write_str](Write::write_str) for details. + /// /// # Examples /// /// ``` From 1d7d10a93d7a7f3e761a9b1fc6aeeff84d7483ef Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 4 Jan 2023 14:05:58 -0800 Subject: [PATCH 006/105] tidy: Don't include wasm32 in compiler dependency check --- Cargo.lock | 1 + src/tools/tidy/Cargo.toml | 1 + src/tools/tidy/src/deps.rs | 168 ++++++++++++++----------------------- 3 files changed, 67 insertions(+), 103 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d7381b6c9386..77c8809785a2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5596,6 +5596,7 @@ dependencies = [ name = "tidy" version = "0.1.0" dependencies = [ + "cargo-platform 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "cargo_metadata 0.14.0", "ignore", "lazy_static", diff --git a/src/tools/tidy/Cargo.toml b/src/tools/tidy/Cargo.toml index 5f5ae3a65efa..714bdace8488 100644 --- a/src/tools/tidy/Cargo.toml +++ b/src/tools/tidy/Cargo.toml @@ -6,6 +6,7 @@ autobins = false [dependencies] cargo_metadata = "0.14" +cargo-platform = "0.1.2" regex = "1" miropt-test-tools = { path = "../miropt-test-tools" } lazy_static = "1" diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index f649e391b798..9870af86d7ea 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -1,7 +1,7 @@ //! Checks the licenses of third-party dependencies. -use cargo_metadata::{Metadata, Package, PackageId, Resolve}; -use std::collections::{BTreeSet, HashSet}; +use cargo_metadata::{DepKindInfo, Metadata, Package, PackageId}; +use std::collections::HashSet; use std::path::Path; /// These are licenses that are allowed for all crates, including the runtime, @@ -98,14 +98,12 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "autocfg", "bitflags", "block-buffer", - "bumpalo", // Included in Cargo's dep graph but only activated on wasm32-*-unknown. "cc", "cfg-if", "chalk-derive", "chalk-engine", "chalk-ir", "chalk-solve", - "chrono", "convert_case", // dependency of derive_more "compiler_builtins", "cpufeatures", @@ -124,11 +122,9 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "dlmalloc", "either", "ena", - "env_logger", "expect-test", "fallible-iterator", // dependency of `thorin` "fastrand", - "filetime", "fixedbitset", "flate2", "fluent-bundle", @@ -142,13 +138,11 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "gsgdt", "hashbrown", "hermit-abi", - "humantime", "icu_list", "icu_locid", "icu_provider", "icu_provider_adapters", "icu_provider_macros", - "if_chain", "indexmap", "instant", "intl-memoizer", @@ -156,7 +150,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "itertools", "itoa", "jobserver", - "js-sys", // Included in Cargo's dep graph but only activated on wasm32-*-unknown. "lazy_static", "libc", "libloading", @@ -171,8 +164,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "memmap2", "memoffset", "miniz_oxide", - "num-integer", - "num-traits", "num_cpus", "object", "odht", @@ -190,7 +181,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "proc-macro2", "psm", "punycode", - "quick-error", "quote", "rand", "rand_chacha", @@ -236,7 +226,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "thiserror-impl", "thorin-dwp", "thread_local", - "time", "tinystr", "tinyvec", "tinyvec_macros", @@ -269,13 +258,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "valuable", "version_check", "wasi", - // vvv Included in Cargo's dep graph but only activated on wasm32-*-unknown. - "wasm-bindgen", - "wasm-bindgen-backend", - "wasm-bindgen-macro", - "wasm-bindgen-macro-support", - "wasm-bindgen-shared", - // ^^^ Included in Cargo's dep graph but only activated on wasm32-*-unknown. "winapi", "winapi-i686-pc-windows-gnu", "winapi-util", @@ -486,75 +468,57 @@ fn check_permitted_dependencies( restricted_dependency_crates: &[&'static str], bad: &mut bool, ) { + let mut deps = HashSet::new(); + for to_check in restricted_dependency_crates { + let to_check = pkg_from_name(metadata, to_check); + use cargo_platform::Cfg; + use std::str::FromStr; + // We don't expect the compiler to ever run on wasm32, so strip + // out those dependencies to avoid polluting the permitted list. + deps_of_filtered(metadata, &to_check.id, &mut deps, &|dep_kinds| { + dep_kinds.iter().any(|dep_kind| { + dep_kind + .target + .as_ref() + .map(|target| { + !target.matches( + "wasm32-unknown-unknown", + &[ + Cfg::from_str("target_arch=\"wasm32\"").unwrap(), + Cfg::from_str("target_os=\"unknown\"").unwrap(), + ], + ) + }) + .unwrap_or(true) + }) + }); + } + // Check that the PERMITTED_DEPENDENCIES does not have unused entries. - for name in permitted_dependencies { - if !metadata.packages.iter().any(|p| p.name == *name) { + for permitted in permitted_dependencies { + if !deps.iter().any(|dep_id| &pkg_from_id(metadata, dep_id).name == permitted) { tidy_error!( bad, - "could not find allowed package `{}`\n\ + "could not find allowed package `{permitted}`\n\ Remove from PERMITTED_DEPENDENCIES list if it is no longer used.", - name ); } } - // Get the list in a convenient form. + + // Get in a convenient form. let permitted_dependencies: HashSet<_> = permitted_dependencies.iter().cloned().collect(); - // Check dependencies. - let mut visited = BTreeSet::new(); - let mut unapproved = BTreeSet::new(); - for &krate in restricted_dependency_crates.iter() { - let pkg = pkg_from_name(metadata, krate); - let mut bad = - check_crate_dependencies(&permitted_dependencies, metadata, &mut visited, pkg); - unapproved.append(&mut bad); - } - - if !unapproved.is_empty() { - tidy_error!(bad, "Dependencies for {} not explicitly permitted:", descr); - for dep in unapproved { - println!("* {dep}"); + for dep in deps { + let dep = pkg_from_id(metadata, dep); + // If this path is in-tree, we don't require it to be explicitly permitted. + if dep.source.is_some() { + if !permitted_dependencies.contains(dep.name.as_str()) { + tidy_error!(bad, "Dependency for {descr} not explicitly permitted: {}", dep.id); + } } } } -/// Checks the dependencies of the given crate from the given cargo metadata to see if they are on -/// the list of permitted dependencies. Returns a list of disallowed dependencies. -fn check_crate_dependencies<'a>( - permitted_dependencies: &'a HashSet<&'static str>, - metadata: &'a Metadata, - visited: &mut BTreeSet<&'a PackageId>, - krate: &'a Package, -) -> BTreeSet<&'a PackageId> { - // This will contain bad deps. - let mut unapproved = BTreeSet::new(); - - // Check if we have already visited this crate. - if visited.contains(&krate.id) { - return unapproved; - } - - visited.insert(&krate.id); - - // If this path is in-tree, we don't require it to be explicitly permitted. - if krate.source.is_some() { - // If this dependency is not on `PERMITTED_DEPENDENCIES`, add to bad set. - if !permitted_dependencies.contains(krate.name.as_str()) { - unapproved.insert(&krate.id); - } - } - - // Do a DFS in the crate graph. - let to_check = deps_of(metadata, &krate.id); - - for dep in to_check { - let mut bad = check_crate_dependencies(permitted_dependencies, metadata, visited, dep); - unapproved.append(&mut bad); - } - - unapproved -} - /// Prevents multiple versions of some expensive crates. fn check_crate_duplicate( metadata: &Metadata, @@ -589,24 +553,6 @@ fn check_crate_duplicate( } } -/// Returns a list of dependencies for the given package. -fn deps_of<'a>(metadata: &'a Metadata, pkg_id: &'a PackageId) -> Vec<&'a Package> { - let resolve = metadata.resolve.as_ref().unwrap(); - let node = resolve - .nodes - .iter() - .find(|n| &n.id == pkg_id) - .unwrap_or_else(|| panic!("could not find `{pkg_id}` in resolve")); - node.deps - .iter() - .map(|dep| { - metadata.packages.iter().find(|pkg| pkg.id == dep.pkg).unwrap_or_else(|| { - panic!("could not find dep `{}` for pkg `{}` in resolve", dep.pkg, pkg_id) - }) - }) - .collect() -} - /// Finds a package with the given name. fn pkg_from_name<'a>(metadata: &'a Metadata, name: &'static str) -> &'a Package { let mut i = metadata.packages.iter().filter(|p| p.name == name); @@ -616,41 +562,57 @@ fn pkg_from_name<'a>(metadata: &'a Metadata, name: &'static str) -> &'a Package result } +fn pkg_from_id<'a>(metadata: &'a Metadata, id: &PackageId) -> &'a Package { + metadata.packages.iter().find(|p| &p.id == id).unwrap() +} + /// Finds all the packages that are in the rust runtime. fn compute_runtime_crates<'a>(metadata: &'a Metadata) -> HashSet<&'a PackageId> { - let resolve = metadata.resolve.as_ref().unwrap(); let mut result = HashSet::new(); for name in RUNTIME_CRATES { let id = &pkg_from_name(metadata, name).id; - normal_deps_of_r(resolve, id, &mut result); + deps_of_filtered(metadata, id, &mut result, &|_| true); } result } -/// Recursively find all normal dependencies. -fn normal_deps_of_r<'a>( - resolve: &'a Resolve, +/// Recursively find all dependencies. +fn deps_of_filtered<'a>( + metadata: &'a Metadata, pkg_id: &'a PackageId, result: &mut HashSet<&'a PackageId>, + filter: &dyn Fn(&[DepKindInfo]) -> bool, ) { if !result.insert(pkg_id) { return; } - let node = resolve + let node = metadata + .resolve + .as_ref() + .unwrap() .nodes .iter() .find(|n| &n.id == pkg_id) .unwrap_or_else(|| panic!("could not find `{pkg_id}` in resolve")); for dep in &node.deps { - normal_deps_of_r(resolve, &dep.pkg, result); + if !filter(&dep.dep_kinds) { + continue; + } + deps_of_filtered(metadata, &dep.pkg, result, filter); } } +fn direct_deps_of<'a>(metadata: &'a Metadata, pkg_id: &'a PackageId) -> Vec<&'a Package> { + let resolve = metadata.resolve.as_ref().unwrap(); + let node = resolve.nodes.iter().find(|n| &n.id == pkg_id).unwrap(); + node.deps.iter().map(|dep| pkg_from_id(metadata, &dep.pkg)).collect() +} + fn check_rustfix(metadata: &Metadata, bad: &mut bool) { let cargo = pkg_from_name(metadata, "cargo"); let compiletest = pkg_from_name(metadata, "compiletest"); - let cargo_deps = deps_of(metadata, &cargo.id); - let compiletest_deps = deps_of(metadata, &compiletest.id); + let cargo_deps = direct_deps_of(metadata, &cargo.id); + let compiletest_deps = direct_deps_of(metadata, &compiletest.id); let cargo_rustfix = cargo_deps.iter().find(|p| p.name == "rustfix").unwrap(); let compiletest_rustfix = compiletest_deps.iter().find(|p| p.name == "rustfix").unwrap(); if cargo_rustfix.version != compiletest_rustfix.version { From 6dd1086ead75fe11515382f107c3ac0d00e265c1 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sun, 8 Jan 2023 15:03:42 -0700 Subject: [PATCH 007/105] rustdoc: fix outdated lint section of the book --- src/doc/rustdoc/src/lints.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustdoc/src/lints.md b/src/doc/rustdoc/src/lints.md index bff01d7cb7c1..45db3bb9b007 100644 --- a/src/doc/rustdoc/src/lints.md +++ b/src/doc/rustdoc/src/lints.md @@ -261,7 +261,7 @@ typo mistakes for some common attributes. ## `invalid_html_tags` -This lint is **allowed by default** and is **nightly-only**. It detects unclosed +This lint **warns by default**. It detects unclosed or invalid HTML tags. For example: ```rust From a529ba8f67861c21a6f4d1c497aa1f602b335ecb Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Mon, 9 Jan 2023 17:49:24 +0000 Subject: [PATCH 008/105] Fix aarch64-unknown-linux-gnu_ilp32 target This was broken because the synthetic object files produced by rustc were for 64-bit AArch64, which caused link failures when combined with 32-bit ILP32 object files. This PR updates the object crate to 0.30.1 which adds support for generating ILP32 AArch64 object files. --- Cargo.lock | 73 +++++++++++++------ compiler/rustc_codegen_llvm/Cargo.toml | 5 +- compiler/rustc_codegen_ssa/Cargo.toml | 4 +- .../rustc_codegen_ssa/src/back/metadata.rs | 8 +- 4 files changed, 64 insertions(+), 26 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 117295014e6b..4f28a0cb3581 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -35,6 +35,17 @@ dependencies = [ "version_check", ] +[[package]] +name = "ahash" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf6ccdb167abbf410dcb915cabd428929d7f6a04980b54a11f26a39f1c7f7107" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", +] + [[package]] name = "aho-corasick" version = "0.7.18" @@ -107,7 +118,7 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "276881980556fdadeb88aa1ffc667e4d2e8fe72531dfabcb7a82bb3c9ea9ba31" dependencies = [ - "object", + "object 0.29.0", ] [[package]] @@ -193,7 +204,7 @@ dependencies = [ "cfg-if", "libc", "miniz_oxide", - "object", + "object 0.29.0", "rustc-demangle", ] @@ -1650,9 +1661,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.26.1" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" +checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" dependencies = [ "compiler_builtins", "fallible-iterator", @@ -1752,12 +1763,21 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" dependencies = [ - "ahash", + "ahash 0.7.4", "compiler_builtins", "rustc-std-workspace-alloc", "rustc-std-workspace-core", ] +[[package]] +name = "hashbrown" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ff8ae62cd3a9102e5637afc8452c55acf3844001bd5374e0b0bd7b6616c038" +dependencies = [ + "ahash 0.8.2", +] + [[package]] name = "heck" version = "0.4.0" @@ -1976,12 +1996,12 @@ checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" [[package]] name = "indexmap" -version = "1.9.1" +version = "1.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" +checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" dependencies = [ "autocfg", - "hashbrown", + "hashbrown 0.12.3", "rustc-rayon", "serde", ] @@ -2578,15 +2598,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53" dependencies = [ "compiler_builtins", - "crc32fast", - "flate2", - "hashbrown", - "indexmap", "memchr", "rustc-std-workspace-alloc", "rustc-std-workspace-core", ] +[[package]] +name = "object" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d864c91689fdc196779b98dba0aceac6118594c2df6ee5d943eb6a8df4d107a" +dependencies = [ + "crc32fast", + "flate2", + "hashbrown 0.13.1", + "indexmap", + "memchr", +] + [[package]] name = "odht" version = "0.3.1" @@ -3596,7 +3625,7 @@ dependencies = [ "cstr", "libc", "measureme", - "object", + "object 0.30.1", "rustc-demangle", "rustc_ast", "rustc_attr", @@ -3631,7 +3660,7 @@ dependencies = [ "itertools", "jobserver", "libc", - "object", + "object 0.30.1", "pathdiff", "regex", "rustc_arena", @@ -5062,11 +5091,11 @@ dependencies = [ "core", "dlmalloc", "fortanix-sgx-abi", - "hashbrown", + "hashbrown 0.12.3", "hermit-abi 0.2.6", "libc", "miniz_oxide", - "object", + "object 0.29.0", "panic_abort", "panic_unwind", "profiler_builtins", @@ -5298,13 +5327,13 @@ dependencies = [ [[package]] name = "thorin-dwp" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6cb0c7868d7f90407531108ab03263d9452a8811b7cdd87675343a40d4aa254" +checksum = "da8fbf660a019b6bf11ea95762041464aa9099cc293b6a66d77cea5107619671" dependencies = [ "gimli", - "hashbrown", - "object", + "hashbrown 0.12.3", + "object 0.30.1", "tracing", ] @@ -5813,9 +5842,9 @@ checksum = "6454029bf181f092ad1b853286f23e2c507d8e8194d01d92da4a55c274a5508c" [[package]] name = "version_check" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "vte" diff --git a/compiler/rustc_codegen_llvm/Cargo.toml b/compiler/rustc_codegen_llvm/Cargo.toml index 93d6234dc884..9c1bcd431ec4 100644 --- a/compiler/rustc_codegen_llvm/Cargo.toml +++ b/compiler/rustc_codegen_llvm/Cargo.toml @@ -11,7 +11,10 @@ bitflags = "1.0" cstr = "0.2" libc = "0.2" measureme = "10.0.0" -object = { version = "0.29.0", default-features = false, features = ["std", "read"] } +object = { version = "0.30.1", default-features = false, features = [ + "std", + "read", +] } tracing = "0.1" rustc_middle = { path = "../rustc_middle" } rustc-demangle = "0.1.21" diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml index 345174fb595a..7ada9c0e12a1 100644 --- a/compiler/rustc_codegen_ssa/Cargo.toml +++ b/compiler/rustc_codegen_ssa/Cargo.toml @@ -15,7 +15,7 @@ tracing = "0.1" libc = "0.2.50" jobserver = "0.1.22" tempfile = "3.2" -thorin-dwp = "0.3" +thorin-dwp = "0.4" pathdiff = "0.2.0" serde_json = "1.0.59" snap = "1" @@ -43,6 +43,6 @@ rustc_session = { path = "../rustc_session" } rustc_const_eval = { path = "../rustc_const_eval" } [dependencies.object] -version = "0.29.0" +version = "0.30.1" default-features = false features = ["read_core", "elf", "macho", "pe", "unaligned", "archive", "write"] diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs index 51c5c375d519..237b8849a352 100644 --- a/compiler/rustc_codegen_ssa/src/back/metadata.rs +++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs @@ -100,7 +100,13 @@ pub(crate) fn create_object_file(sess: &Session) -> Option Architecture::Arm, - "aarch64" => Architecture::Aarch64, + "aarch64" => { + if sess.target.pointer_width == 32 { + Architecture::Aarch64_Ilp32 + } else { + Architecture::Aarch64 + } + } "x86" => Architecture::I386, "s390x" => Architecture::S390x, "mips" => Architecture::Mips, From 2717f600935174aa3ee5e743a3d1901d6be149a9 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 5 Jan 2023 17:20:59 -0800 Subject: [PATCH 009/105] Update mdbook --- Cargo.lock | 49 +++++++++++++++++++------------- src/bootstrap/bin/rustc.rs | 35 +++++++++++++++++++++++ src/bootstrap/builder.rs | 52 ++++++++++++++++++++++++++-------- src/bootstrap/check.rs | 4 +-- src/bootstrap/test.rs | 4 ++- src/bootstrap/tool.rs | 25 ++++++++++++++-- src/tools/rustbook/Cargo.toml | 4 +-- src/tools/rustbook/src/main.rs | 22 +++++++------- 8 files changed, 146 insertions(+), 49 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d7381b6c9386..06ab91e06cab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -329,7 +329,7 @@ dependencies = [ "cargo-test-macro", "cargo-test-support", "cargo-util", - "clap 4.0.15", + "clap 4.0.32", "crates-io", "curl", "curl-sys", @@ -631,26 +631,27 @@ dependencies = [ [[package]] name = "clap" -version = "4.0.15" +version = "4.0.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bf8832993da70a4c6d13c581f4463c2bdda27b9bf1c5498dc4365543abe6d6f" +checksum = "a7db700bc935f9e43e88d00b0850dae18a63773cfbec6d8e070fccf7fef89a39" dependencies = [ - "atty", "bitflags", - "clap_derive 4.0.13", + "clap_derive 4.0.21", "clap_lex 0.3.0", + "is-terminal", "once_cell", "strsim", "termcolor", + "terminal_size", ] [[package]] name = "clap_complete" -version = "3.1.1" +version = "4.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df6f3613c0a3cddfd78b41b10203eb322cb29b600cbdf808a7d3db95691b8e25" +checksum = "10861370d2ba66b0f5989f83ebf35db6421713fd92351790e7fdd6c36774c56b" dependencies = [ - "clap 3.2.20", + "clap 4.0.32", ] [[package]] @@ -668,9 +669,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.0.13" +version = "4.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c42f169caba89a7d512b5418b09864543eeb4d497416c917d7137863bd2076ad" +checksum = "0177313f9f02afc995627906bbd8967e2be069f5261954222dac78290c2b9014" dependencies = [ "heck", "proc-macro-error", @@ -2271,7 +2272,7 @@ name = "jsondoclint" version = "0.1.0" dependencies = [ "anyhow", - "clap 4.0.15", + "clap 4.0.32", "fs-err", "rustdoc-json-types", "serde", @@ -2527,21 +2528,21 @@ dependencies = [ [[package]] name = "mdbook" -version = "0.4.21" +version = "0.4.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23f3e133c6d515528745ffd3b9f0c7d975ae039f0b6abb099f2168daa2afb4f9" +checksum = "d1ed28d5903dde77bd5182645078a37ee57014cac6ccb2d54e1d6496386648e4" dependencies = [ "ammonia", "anyhow", "chrono", - "clap 3.2.20", + "clap 4.0.32", "clap_complete", "elasticlunr-rs", - "env_logger 0.9.0", + "env_logger 0.10.0", "handlebars 4.3.3", - "lazy_static", "log", "memchr", + "once_cell", "opener", "pulldown-cmark 0.9.2", "regex", @@ -3537,7 +3538,7 @@ dependencies = [ name = "rustbook" version = "0.1.0" dependencies = [ - "clap 3.2.20", + "clap 4.0.32", "env_logger 0.7.1", "mdbook", ] @@ -5502,6 +5503,16 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "terminal_size" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb20089a8ba2b69debd491f8d2d023761cbf196e999218c591fa1e7e15a21907" +dependencies = [ + "rustix", + "windows-sys", +] + [[package]] name = "termize" version = "0.1.1" @@ -5718,9 +5729,9 @@ dependencies = [ [[package]] name = "topological-sort" -version = "0.1.0" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa7c7f42dea4b1b99439786f5633aeb9c14c1b53f75e282803c2ec2ad545873c" +checksum = "ea68304e134ecd095ac6c3574494fc62b909f416c4fca77e440530221e549d3d" [[package]] name = "tracing" diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index 1d5260228121..9611c866df59 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -154,6 +154,41 @@ fn main() { cmd.arg("-Z").arg("force-unstable-if-unmarked"); } + // allow-features is handled from within this rustc wrapper because of + // issues with build scripts. Some packages use build scripts to + // dynamically detect if certain nightly features are available. + // There are different ways this causes problems: + // + // * rustix runs `rustc` on a small test program to see if the feature is + // available (and sets a `cfg` if it is). It does not honor + // CARGO_ENCODED_RUSTFLAGS. + // * proc-macro2 detects if `rustc -vV` says "nighty" or "dev" and enables + // nightly features. It will scan CARGO_ENCODED_RUSTFLAGS for + // -Zallow-features. Unfortunately CARGO_ENCODED_RUSTFLAGS is not set + // for build-dependencies when --target is used. + // + // The issues above means we can't just use RUSTFLAGS, and we can't use + // `cargo -Zallow-features=…`. Passing it through here ensures that it + // always gets set. Unfortunately that also means we need to enable more + // features than we really want (like those for proc-macro2), but there + // isn't much of a way around it. + // + // I think it is unfortunate that build scripts are doing this at all, + // since changes to nightly features can cause crates to break even if the + // user didn't want or care about the use of the nightly features. I think + // nightly features should be opt-in only. Unfortunately the dynamic + // checks are now too wide spread that we just need to deal with it. + // + // If you want to try to remove this, I suggest working with the crate + // authors to remove the dynamic checking. Another option is to pursue + // https://github.com/rust-lang/cargo/issues/11244 and + // https://github.com/rust-lang/cargo/issues/4423, which will likely be + // very difficult, but could help expose -Zallow-features into build + // scripts so they could try to honor them. + if let Ok(allow_features) = env::var("RUSTC_ALLOW_FEATURES") { + cmd.arg(format!("-Zallow-features={allow_features}")); + } + if let Ok(flags) = env::var("MAGIC_EXTRA_RUSTFLAGS") { for flag in flags.split(' ') { cmd.arg(flag); diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index b54bf4326219..1ae4ff52047e 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -1381,18 +1381,29 @@ impl<'a> Builder<'a> { // this), as well as #63012 which is the tracking issue for this // feature on the rustc side. cargo.arg("-Zbinary-dep-depinfo"); - match mode { - Mode::ToolBootstrap => { - // Restrict the allowed features to those passed by rustbuild, so we don't depend on nightly accidentally. - rustflags.arg("-Zallow-features=binary-dep-depinfo"); + let allow_features = match mode { + Mode::ToolBootstrap | Mode::ToolStd => { + // Restrict the allowed features so we don't depend on nightly + // accidentally. + // + // binary-dep-depinfo is used by rustbuild itself for all + // compilations. + // + // Lots of tools depend on proc_macro2 and proc-macro-error. + // Those have build scripts which assume nightly features are + // available if the `rustc` version is "nighty" or "dev". See + // bin/rustc.rs for why that is a problem. Instead of labeling + // those features for each individual tool that needs them, + // just blanket allow them here. + // + // If this is ever removed, be sure to add something else in + // its place to keep the restrictions in place (or make a way + // to unset RUSTC_BOOTSTRAP). + "binary-dep-depinfo,proc_macro_span,proc_macro_span_shrink,proc_macro_diagnostic" + .to_string() } - Mode::ToolStd => { - // Right now this is just compiletest and a few other tools that build on stable. - // Allow them to use `feature(test)`, but nothing else. - rustflags.arg("-Zallow-features=binary-dep-depinfo,test,proc_macro_internals,proc_macro_diagnostic,proc_macro_span"); - } - Mode::Std | Mode::Rustc | Mode::Codegen | Mode::ToolRustc => {} - } + Mode::Std | Mode::Rustc | Mode::Codegen | Mode::ToolRustc => String::new(), + }; cargo.arg("-j").arg(self.jobs().to_string()); @@ -1915,7 +1926,7 @@ impl<'a> Builder<'a> { } } - Cargo { command: cargo, rustflags, rustdocflags } + Cargo { command: cargo, rustflags, rustdocflags, allow_features } } /// Ensure that a given step is built, returning its output. This will @@ -2094,6 +2105,7 @@ pub struct Cargo { command: Command, rustflags: Rustflags, rustdocflags: Rustflags, + allow_features: String, } impl Cargo { @@ -2138,6 +2150,18 @@ impl Cargo { self.command.current_dir(dir); self } + + /// Adds nightly-only features that this invocation is allowed to use. + /// + /// By default, all nightly features are allowed. Once this is called, it + /// will be restricted to the given set. + pub fn allow_features(&mut self, features: &str) -> &mut Cargo { + if !self.allow_features.is_empty() { + self.allow_features.push(','); + } + self.allow_features.push_str(features); + self + } } impl From for Command { @@ -2152,6 +2176,10 @@ impl From for Command { cargo.command.env("RUSTDOCFLAGS", rustdocflags); } + if !cargo.allow_features.is_empty() { + cargo.command.env("RUSTC_ALLOW_FEATURES", cargo.allow_features); + } + cargo.command } } diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index b203ecd3844b..72e5dc6f4dfa 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -332,9 +332,7 @@ impl Step for RustAnalyzer { &["rust-analyzer/in-rust-tree".to_owned()], ); - cargo.rustflag( - "-Zallow-features=proc_macro_internals,proc_macro_diagnostic,proc_macro_span", - ); + cargo.allow_features(crate::tool::RustAnalyzer::ALLOW_FEATURES); // For ./x.py clippy, don't check those targets because // linting tests and benchmarks can produce very noisy results diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index ea906be7e3ac..208321c7bfde 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -378,6 +378,7 @@ impl Step for RustAnalyzer { SourceType::InTree, &["sysroot-abi".to_owned()], ); + cargo.allow_features(tool::RustAnalyzer::ALLOW_FEATURES); let dir = builder.src.join(workspace_path); // needed by rust-analyzer to find its own text fixtures, cf. @@ -690,7 +691,7 @@ impl Step for CompiletestTest { // We need `ToolStd` for the locally-built sysroot because // compiletest uses unstable features of the `test` crate. builder.ensure(compile::Std::new(compiler, host)); - let cargo = tool::prepare_tool_cargo( + let mut cargo = tool::prepare_tool_cargo( builder, compiler, Mode::ToolStd, @@ -700,6 +701,7 @@ impl Step for CompiletestTest { SourceType::InTree, &[], ); + cargo.allow_features("test"); try_run(builder, &mut cargo.into()); } diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 63026bd44d47..08c747824555 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -29,6 +29,8 @@ struct ToolBuild { is_optional_tool: bool, source_type: SourceType, extra_features: Vec, + /// Nightly-only features that are allowed (comma-separated list). + allow_features: &'static str, } impl Step for ToolBuild { @@ -59,7 +61,7 @@ impl Step for ToolBuild { _ => panic!("unexpected Mode for tool build"), } - let cargo = prepare_tool_cargo( + let mut cargo = prepare_tool_cargo( builder, compiler, self.mode, @@ -69,6 +71,9 @@ impl Step for ToolBuild { self.source_type, &self.extra_features, ); + if !self.allow_features.is_empty() { + cargo.allow_features(self.allow_features); + } builder.info(&format!("Building stage{} tool {} ({})", compiler.stage, tool, target)); let mut duplicates = Vec::new(); @@ -292,6 +297,7 @@ macro_rules! bootstrap_tool { $name:ident, $path:expr, $tool_name:expr $(,is_external_tool = $external:expr)* $(,is_unstable_tool = $unstable:expr)* + $(,allow_features = $allow_features:expr)? ; )+) => { #[derive(Copy, PartialEq, Eq, Clone)] @@ -355,6 +361,7 @@ macro_rules! bootstrap_tool { SourceType::InTree }, extra_features: vec![], + allow_features: concat!($($allow_features)*), }).expect("expected to build -- essential tool") } } @@ -368,7 +375,7 @@ bootstrap_tool!( Tidy, "src/tools/tidy", "tidy"; Linkchecker, "src/tools/linkchecker", "linkchecker"; CargoTest, "src/tools/cargotest", "cargotest"; - Compiletest, "src/tools/compiletest", "compiletest", is_unstable_tool = true; + Compiletest, "src/tools/compiletest", "compiletest", is_unstable_tool = true, allow_features = "test"; BuildManifest, "src/tools/build-manifest", "build-manifest"; RemoteTestClient, "src/tools/remote-test-client", "remote-test-client"; RustInstaller, "src/tools/rust-installer", "rust-installer", is_external_tool = true; @@ -435,6 +442,7 @@ impl Step for ErrorIndex { is_optional_tool: false, source_type: SourceType::InTree, extra_features: Vec::new(), + allow_features: "", }) .expect("expected to build -- essential tool") } @@ -471,6 +479,7 @@ impl Step for RemoteTestServer { is_optional_tool: false, source_type: SourceType::InTree, extra_features: Vec::new(), + allow_features: "", }) .expect("expected to build -- essential tool") } @@ -622,6 +631,7 @@ impl Step for Cargo { is_optional_tool: false, source_type: SourceType::Submodule, extra_features: Vec::new(), + allow_features: "", }) .expect("expected to build -- essential tool"); @@ -637,6 +647,7 @@ impl Step for Cargo { is_optional_tool: true, source_type: SourceType::Submodule, extra_features: Vec::new(), + allow_features: "", }); }; @@ -684,6 +695,7 @@ impl Step for LldWrapper { is_optional_tool: false, source_type: SourceType::InTree, extra_features: Vec::new(), + allow_features: "", }) .expect("expected to build -- essential tool"); @@ -697,6 +709,11 @@ pub struct RustAnalyzer { pub target: TargetSelection, } +impl RustAnalyzer { + pub const ALLOW_FEATURES: &str = + "proc_macro_internals,proc_macro_diagnostic,proc_macro_span,proc_macro_span_shrink"; +} + impl Step for RustAnalyzer { type Output = Option; const DEFAULT: bool = true; @@ -731,6 +748,7 @@ impl Step for RustAnalyzer { extra_features: vec!["rust-analyzer/in-rust-tree".to_owned()], is_optional_tool: false, source_type: SourceType::InTree, + allow_features: RustAnalyzer::ALLOW_FEATURES, }) } } @@ -769,6 +787,7 @@ impl Step for RustAnalyzerProcMacroSrv { extra_features: vec!["proc-macro-srv/sysroot-abi".to_owned()], is_optional_tool: false, source_type: SourceType::InTree, + allow_features: RustAnalyzer::ALLOW_FEATURES, })?; // Copy `rust-analyzer-proc-macro-srv` to `/libexec/` @@ -788,6 +807,7 @@ macro_rules! tool_extended { $tool_name:expr, stable = $stable:expr $(,tool_std = $tool_std:literal)? + $(,allow_features = $allow_features:expr)? ;)+) => { $( #[derive(Debug, Clone, Hash, PartialEq, Eq)] @@ -839,6 +859,7 @@ macro_rules! tool_extended { extra_features: $sel.extra_features, is_optional_tool: true, source_type: SourceType::InTree, + allow_features: concat!($($allow_features)*), }) } } diff --git a/src/tools/rustbook/Cargo.toml b/src/tools/rustbook/Cargo.toml index 33c051804081..b296aa2f4e6d 100644 --- a/src/tools/rustbook/Cargo.toml +++ b/src/tools/rustbook/Cargo.toml @@ -5,10 +5,10 @@ license = "MIT OR Apache-2.0" edition = "2021" [dependencies] -clap = "3.1.1" +clap = "4.0.32" env_logger = "0.7.1" [dependencies.mdbook] -version = "0.4.21" +version = "0.4.25" default-features = false features = ["search"] diff --git a/src/tools/rustbook/src/main.rs b/src/tools/rustbook/src/main.rs index 3c7dc0183d77..1368ec653de1 100644 --- a/src/tools/rustbook/src/main.rs +++ b/src/tools/rustbook/src/main.rs @@ -9,18 +9,21 @@ use mdbook::errors::Result as Result3; use mdbook::MDBook; fn main() { - let crate_version = format!("v{}", crate_version!()); + let crate_version = concat!("v", crate_version!()); env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("warn")).init(); let d_arg = arg!(-d --"dest-dir" "The output directory for your book\n(Defaults to ./book when omitted)") - .required(false); - let dir_arg = arg!([dir] -"A directory for your book\n(Defaults to Current Directory when omitted)"); + .required(false) + .value_parser(clap::value_parser!(PathBuf)); + + let dir_arg = arg!([dir] "Root directory for the book\n\ + (Defaults to the current directory when omitted)") + .value_parser(clap::value_parser!(PathBuf)); let matches = Command::new("rustbook") .about("Build a book with mdBook") .author("Steve Klabnik ") - .version(&*crate_version) + .version(crate_version) .subcommand_required(true) .arg_required_else_help(true) .subcommand( @@ -60,8 +63,8 @@ pub fn build(args: &ArgMatches) -> Result3<()> { // Set this to allow us to catch bugs in advance. book.config.build.create_missing = false; - if let Some(dest_dir) = args.value_of("dest-dir") { - book.config.build.build_dir = PathBuf::from(dest_dir); + if let Some(dest_dir) = args.get_one::("dest-dir") { + book.config.build.build_dir = dest_dir.into(); } book.build()?; @@ -76,10 +79,9 @@ fn test(args: &ArgMatches) -> Result3<()> { } fn get_book_dir(args: &ArgMatches) -> PathBuf { - if let Some(dir) = args.value_of("dir") { + if let Some(p) = args.get_one::("dir") { // Check if path is relative from current dir, or absolute... - let p = Path::new(dir); - if p.is_relative() { env::current_dir().unwrap().join(dir) } else { p.to_path_buf() } + if p.is_relative() { env::current_dir().unwrap().join(p) } else { p.to_path_buf() } } else { env::current_dir().unwrap() } From 1300c8d272e6b721077ec96b10aad0b42d376131 Mon Sep 17 00:00:00 2001 From: Albert Larsan <74931857+albertlarsan68@users.noreply.github.com> Date: Tue, 10 Jan 2023 08:43:54 +0000 Subject: [PATCH 010/105] Check compiler docs in PR CI --- src/ci/docker/host-x86_64/mingw-check/Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ci/docker/host-x86_64/mingw-check/Dockerfile b/src/ci/docker/host-x86_64/mingw-check/Dockerfile index adf6bb4b3775..d5bc76eeb23d 100644 --- a/src/ci/docker/host-x86_64/mingw-check/Dockerfile +++ b/src/ci/docker/host-x86_64/mingw-check/Dockerfile @@ -45,6 +45,7 @@ ENV SCRIPT python3 ../x.py --stage 2 test src/tools/expand-yaml-anchors && \ python3 ../x.py test --stage 0 src/tools/compiletest && \ python3 ../x.py test --stage 0 core alloc std test proc_macro && \ # Build both public and internal documentation. + RUSTDOCFLAGS=\"--document-private-items --document-hidden-items\" python3 ../x.py doc --stage 0 compiler && \ RUSTDOCFLAGS=\"--document-private-items --document-hidden-items\" python3 ../x.py doc --stage 0 library/test && \ /scripts/validate-toolstate.sh && \ /scripts/validate-error-codes.sh && \ From 1a87ed9a45c6e979b07cc3b30e89850763d3c0a0 Mon Sep 17 00:00:00 2001 From: Alan Egerton Date: Tue, 10 Jan 2023 18:01:39 +0000 Subject: [PATCH 011/105] mv binary_heap.rs binary_heap/mod.rs --- .../alloc/src/collections/{binary_heap.rs => binary_heap/mod.rs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename library/alloc/src/collections/{binary_heap.rs => binary_heap/mod.rs} (100%) diff --git a/library/alloc/src/collections/binary_heap.rs b/library/alloc/src/collections/binary_heap/mod.rs similarity index 100% rename from library/alloc/src/collections/binary_heap.rs rename to library/alloc/src/collections/binary_heap/mod.rs From 2538c0c17095834c994cbfdc4909338a31f83fb7 Mon Sep 17 00:00:00 2001 From: Ibraheem Ahmed Date: Tue, 10 Jan 2023 21:39:02 -0500 Subject: [PATCH 012/105] fix `SyncSender` spinning behavior --- library/std/src/sync/mpmc/utils.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/sync/mpmc/utils.rs b/library/std/src/sync/mpmc/utils.rs index e030c55ce8f6..a9b365daeec4 100644 --- a/library/std/src/sync/mpmc/utils.rs +++ b/library/std/src/sync/mpmc/utils.rs @@ -139,6 +139,6 @@ impl Backoff { /// Returns `true` if quadratic backoff has completed and blocking the thread is advised. #[inline] pub fn is_completed(&self) -> bool { - self.step.get() > YIELD_LIMIT + self.step.get() > SPIN_LIMIT } } From f8276c94ac06b272e88fb1bb9c5f6615fc5876ef Mon Sep 17 00:00:00 2001 From: Ibraheem Ahmed Date: Tue, 10 Jan 2023 21:54:53 -0500 Subject: [PATCH 013/105] add `SyncSender::send_timeout` test --- library/std/src/sync/mpmc/mod.rs | 2 +- library/std/src/sync/mpsc/mod.rs | 9 +++++++++ library/std/src/sync/mpsc/sync_tests.rs | 8 ++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/library/std/src/sync/mpmc/mod.rs b/library/std/src/sync/mpmc/mod.rs index cef99c588430..7a602cecd3b8 100644 --- a/library/std/src/sync/mpmc/mod.rs +++ b/library/std/src/sync/mpmc/mod.rs @@ -43,7 +43,7 @@ mod zero; use crate::fmt; use crate::panic::{RefUnwindSafe, UnwindSafe}; use crate::time::{Duration, Instant}; -use error::*; +pub use error::*; /// Creates a channel of unbounded capacity. /// diff --git a/library/std/src/sync/mpsc/mod.rs b/library/std/src/sync/mpsc/mod.rs index adb488d4378f..6e3c28f10bb1 100644 --- a/library/std/src/sync/mpsc/mod.rs +++ b/library/std/src/sync/mpsc/mod.rs @@ -738,6 +738,15 @@ impl SyncSender { pub fn try_send(&self, t: T) -> Result<(), TrySendError> { self.inner.try_send(t) } + + // Attempts to send for a value on this receiver, returning an error if the + // corresponding channel has hung up, or if it waits more than `timeout`. + // + // This method is currently private and only used for tests. + #[allow(unused)] + fn send_timeout(&self, t: T, timeout: Duration) -> Result<(), mpmc::SendTimeoutError> { + self.inner.send_timeout(t, timeout) + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/std/src/sync/mpsc/sync_tests.rs b/library/std/src/sync/mpsc/sync_tests.rs index 63c79436974d..9d2f92ffc9b1 100644 --- a/library/std/src/sync/mpsc/sync_tests.rs +++ b/library/std/src/sync/mpsc/sync_tests.rs @@ -1,5 +1,6 @@ use super::*; use crate::env; +use crate::sync::mpmc::SendTimeoutError; use crate::thread; use crate::time::Duration; @@ -41,6 +42,13 @@ fn recv_timeout() { assert_eq!(rx.recv_timeout(Duration::from_millis(1)), Ok(1)); } +#[test] +fn send_timeout() { + let (tx, _rx) = sync_channel::(1); + assert_eq!(tx.send_timeout(1, Duration::from_millis(1)), Ok(())); + assert_eq!(tx.send_timeout(1, Duration::from_millis(1)), Err(SendTimeoutError::Timeout(1))); +} + #[test] fn smoke_threads() { let (tx, rx) = sync_channel::(0); From bb60a764f61aff49295163fdb11e7ea60a1ff78d Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 10 Jan 2023 11:09:52 -0800 Subject: [PATCH 014/105] Remove duplicate sha-1 dependency --- Cargo.lock | 43 +++++++++++++--------------------- compiler/rustc_span/Cargo.toml | 2 +- src/tools/tidy/src/deps.rs | 2 +- 3 files changed, 18 insertions(+), 29 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2a88152b5194..5b67b9f33280 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3013,9 +3013,9 @@ dependencies = [ [[package]] name = "pest" -version = "2.3.0" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b0560d531d1febc25a3c9398a62a71256c0178f2e3443baedd9ad4bb8c9deb4" +checksum = "0f6e86fb9e7026527a0d46bc308b841d73170ef8f443e1807f6ef88526a816d4" dependencies = [ "thiserror", "ucd-trie", @@ -3023,9 +3023,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.3.0" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "905708f7f674518498c1f8d644481440f476d39ca6ecae83319bba7c6c12da91" +checksum = "96504449aa860c8dcde14f9fba5c58dc6658688ca1fe363589d6327b8662c603" dependencies = [ "pest", "pest_generator", @@ -3033,9 +3033,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.3.0" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5803d8284a629cc999094ecd630f55e91b561a1d1ba75e233b00ae13b91a69ad" +checksum = "798e0220d1111ae63d66cb66a5dcb3fc2d986d520b98e49e1852bfdb11d7c5e7" dependencies = [ "pest", "pest_meta", @@ -3046,13 +3046,13 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.3.0" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1538eb784f07615c6d9a8ab061089c6c54a344c5b4301db51990ca1c241e8c04" +checksum = "984298b75898e30a843e278a9f2452c31e349a073a0ce6fd950a12a74464e065" dependencies = [ "once_cell", "pest", - "sha-1", + "sha1", ] [[package]] @@ -4683,7 +4683,7 @@ dependencies = [ "rustc_macros", "rustc_serialize", "scoped-tls", - "sha-1", + "sha1", "sha2", "tracing", "unicode-width", @@ -5092,17 +5092,6 @@ dependencies = [ "serde", ] -[[package]] -name = "sha-1" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - [[package]] name = "sha1" version = "0.10.5" @@ -5528,18 +5517,18 @@ checksum = "ceb05e71730d396f960f8f3901cdb41be2d339b303e9d7d3a07c5ff0536e671b" [[package]] name = "thiserror" -version = "1.0.33" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d0a539a918745651435ac7db7a18761589a94cd7e94cd56999f828bf73c8a57" +checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.33" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c251e90f708e16c49a16f4917dc2131e75222b72edfa9cb7f7c58ae56aae0c09" +checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" dependencies = [ "proc-macro2", "quote", @@ -5821,9 +5810,9 @@ dependencies = [ [[package]] name = "ucd-trie" -version = "0.1.3" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" +checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81" [[package]] name = "ui_test" diff --git a/compiler/rustc_span/Cargo.toml b/compiler/rustc_span/Cargo.toml index 5ce2577b63c1..ae81d95e2796 100644 --- a/compiler/rustc_span/Cargo.toml +++ b/compiler/rustc_span/Cargo.toml @@ -15,6 +15,6 @@ scoped-tls = "1.0" unicode-width = "0.1.4" cfg-if = "1.0" tracing = "0.1" -sha1 = { package = "sha-1", version = "0.10.0" } +sha1 = "0.10.0" sha2 = "0.10.1" md5 = { package = "md-5", version = "0.10.0" } diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 29501d2d3b6b..845eb5af0d6b 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -217,7 +217,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "serde", "serde_derive", "serde_json", - "sha-1", + "sha1", "sha2", "sharded-slab", "smallvec", From 4e2a3567bc14ad7b7e9d28f31fc1a468976ebc81 Mon Sep 17 00:00:00 2001 From: Yuki Omoto Date: Thu, 12 Jan 2023 00:17:48 +0900 Subject: [PATCH 015/105] Add log-backtrace option to show backtraces along with logging --- Cargo.lock | 1 + compiler/rustc_driver/src/lib.rs | 14 ++++++- compiler/rustc_interface/src/tests.rs | 1 + compiler/rustc_log/Cargo.toml | 1 + compiler/rustc_log/src/lib.rs | 58 ++++++++++++++++++++++++++- compiler/rustc_session/src/options.rs | 2 + tests/rustdoc-ui/z-help.stdout | 1 + tests/ui/attributes/log-backtrace.rs | 9 +++++ 8 files changed, 83 insertions(+), 4 deletions(-) create mode 100644 tests/ui/attributes/log-backtrace.rs diff --git a/Cargo.lock b/Cargo.lock index 2a88152b5194..b0f050a85d2f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4273,6 +4273,7 @@ version = "0.0.0" dependencies = [ "rustc_span", "tracing", + "tracing-core", "tracing-subscriber", "tracing-tree", ] diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index fcb73c64356f..dcce56ba7638 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -231,6 +231,10 @@ fn run_compiler( registry: diagnostics_registry(), }; + if !tracing::dispatcher::has_been_set() { + init_rustc_env_logger_with_backtrace_option(&config.opts.unstable_opts.log_backtrace); + } + match make_input(config.opts.error_format, &matches.free) { Err(reported) => return Err(reported), Ok(Some((input, input_file_path))) => { @@ -1299,7 +1303,14 @@ pub fn install_ice_hook() { /// This allows tools to enable rust logging without having to magically match rustc's /// tracing crate version. pub fn init_rustc_env_logger() { - if let Err(error) = rustc_log::init_rustc_env_logger() { + init_rustc_env_logger_with_backtrace_option(&None); +} + +/// This allows tools to enable rust logging without having to magically match rustc's +/// tracing crate version. In contrast to `init_rustc_env_logger` it allows you to +/// choose a target module you wish to show backtraces along with its logging. +pub fn init_rustc_env_logger_with_backtrace_option(backtrace_target: &Option) { + if let Err(error) = rustc_log::init_rustc_env_logger_with_backtrace_option(backtrace_target) { early_error(ErrorOutputType::default(), &error.to_string()); } } @@ -1365,7 +1376,6 @@ mod signal_handler { pub fn main() -> ! { let start_time = Instant::now(); let start_rss = get_resident_set_size(); - init_rustc_env_logger(); signal_handler::install(); let mut callbacks = TimePassesCallbacks::default(); install_ice_hook(); diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index a3b9891ee64e..07b28cc86cee 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -748,6 +748,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!(log_backtrace, Some("filter".to_string())); tracked!(maximal_hir_to_mir_coverage, true); tracked!(merge_functions, Some(MergeFunctions::Disabled)); tracked!(mir_emit_retag, true); diff --git a/compiler/rustc_log/Cargo.toml b/compiler/rustc_log/Cargo.toml index 3c50827c1abc..7f955b0a7509 100644 --- a/compiler/rustc_log/Cargo.toml +++ b/compiler/rustc_log/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" tracing = "0.1.28" tracing-subscriber = { version = "0.3.3", default-features = false, features = ["fmt", "env-filter", "smallvec", "parking_lot", "ansi"] } tracing-tree = "0.2.0" +tracing-core = "0.1.28" [dev-dependencies] rustc_span = { path = "../rustc_span" } diff --git a/compiler/rustc_log/src/lib.rs b/compiler/rustc_log/src/lib.rs index 4cac88aff640..fc1cabd2de95 100644 --- a/compiler/rustc_log/src/lib.rs +++ b/compiler/rustc_log/src/lib.rs @@ -45,16 +45,34 @@ use std::env::{self, VarError}; use std::fmt::{self, Display}; use std::io::{self, IsTerminal}; +use tracing_core::{Event, Subscriber}; use tracing_subscriber::filter::{Directive, EnvFilter, LevelFilter}; +use tracing_subscriber::fmt::{ + format::{self, FormatEvent, FormatFields}, + FmtContext, +}; use tracing_subscriber::layer::SubscriberExt; pub fn init_rustc_env_logger() -> Result<(), Error> { - init_env_logger("RUSTC_LOG") + init_rustc_env_logger_with_backtrace_option(&None) +} + +pub fn init_rustc_env_logger_with_backtrace_option( + backtrace_target: &Option, +) -> Result<(), Error> { + init_env_logger_with_backtrace_option("RUSTC_LOG", backtrace_target) } /// In contrast to `init_rustc_env_logger` this allows you to choose an env var /// other than `RUSTC_LOG`. pub fn init_env_logger(env: &str) -> Result<(), Error> { + init_env_logger_with_backtrace_option(env, &None) +} + +pub fn init_env_logger_with_backtrace_option( + env: &str, + backtrace_target: &Option, +) -> Result<(), Error> { let filter = match env::var(env) { Ok(env) => EnvFilter::new(env), _ => EnvFilter::default().add_directive(Directive::from(LevelFilter::WARN)), @@ -88,11 +106,47 @@ pub fn init_env_logger(env: &str) -> Result<(), Error> { let layer = layer.with_thread_ids(true).with_thread_names(true); let subscriber = tracing_subscriber::Registry::default().with(filter).with(layer); - tracing::subscriber::set_global_default(subscriber).unwrap(); + match backtrace_target { + Some(str) => { + let fmt_layer = tracing_subscriber::fmt::layer() + .with_writer(io::stderr) + .without_time() + .event_format(BacktraceFormatter { backtrace_target: str.to_string() }); + let subscriber = subscriber.with(fmt_layer); + tracing::subscriber::set_global_default(subscriber).unwrap(); + } + None => { + tracing::subscriber::set_global_default(subscriber).unwrap(); + } + }; Ok(()) } +struct BacktraceFormatter { + backtrace_target: String, +} + +impl FormatEvent for BacktraceFormatter +where + S: Subscriber + for<'a> tracing_subscriber::registry::LookupSpan<'a>, + N: for<'a> FormatFields<'a> + 'static, +{ + fn format_event( + &self, + _ctx: &FmtContext<'_, S, N>, + mut writer: format::Writer<'_>, + event: &Event<'_>, + ) -> fmt::Result { + let target = event.metadata().target(); + if !target.contains(&self.backtrace_target) { + return Ok(()); + } + let backtrace = std::backtrace::Backtrace::capture(); + writeln!(writer, "stack backtrace: \n{:?}", backtrace) + } +} + pub fn stdout_isatty() -> bool { io::stdout().is_terminal() } diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index b062b43873b2..7b5fd6cc2a81 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1411,6 +1411,8 @@ options! { "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`)"), + log_backtrace: Option = (None, parse_opt_string, [TRACKED], + "add a backtrace along with logging"), ls: bool = (false, parse_bool, [UNTRACKED], "list the symbols defined by a library crate (default: no)"), macro_backtrace: bool = (false, parse_bool, [UNTRACKED], diff --git a/tests/rustdoc-ui/z-help.stdout b/tests/rustdoc-ui/z-help.stdout index 43f30f3d6e80..4bdecdc1b794 100644 --- a/tests/rustdoc-ui/z-help.stdout +++ b/tests/rustdoc-ui/z-help.stdout @@ -76,6 +76,7 @@ -Z llvm-plugins=val -- a list LLVM plugins to enable (space separated) -Z llvm-time-trace=val -- generate JSON tracing data file from LLVM data (default: no) -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 log-backtrace=val -- add a backtrace along with logging -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) diff --git a/tests/ui/attributes/log-backtrace.rs b/tests/ui/attributes/log-backtrace.rs new file mode 100644 index 000000000000..3979d2001fc5 --- /dev/null +++ b/tests/ui/attributes/log-backtrace.rs @@ -0,0 +1,9 @@ +// run-pass +// +// This test makes sure that log-backtrace option doesn't give a compilation error. +// +// dont-check-compiler-stdout +// dont-check-compiler-stderr +// rustc-env:RUSTC_LOG=info +// compile-flags: -Zlog-backtrace=rustc_metadata::creader +fn main() {} From 753e57672296e13c534f87b6e2672a73fff4965c Mon Sep 17 00:00:00 2001 From: Mateusz Guzik Date: Wed, 11 Jan 2023 17:05:15 +0000 Subject: [PATCH 016/105] Fix up stat test in libc-fs-with-isolation The test relied on Error::last_os_error() coming from the stat call on the passed file, but there is no guarantee this will be the case. Instead extract errno from the error returned by the routine. Patch de facto written by joboet. Co-authored-by: joboet --- .../miri/tests/pass-dep/shims/libc-fs-with-isolation.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/tools/miri/tests/pass-dep/shims/libc-fs-with-isolation.rs b/src/tools/miri/tests/pass-dep/shims/libc-fs-with-isolation.rs index f1838cf64f7f..d6d19a3fe815 100644 --- a/src/tools/miri/tests/pass-dep/shims/libc-fs-with-isolation.rs +++ b/src/tools/miri/tests/pass-dep/shims/libc-fs-with-isolation.rs @@ -22,7 +22,8 @@ fn main() { } // test `stat` - assert_eq!(fs::metadata("foo.txt").unwrap_err().kind(), ErrorKind::PermissionDenied); + let err = fs::metadata("foo.txt").unwrap_err(); + assert_eq!(err.kind(), ErrorKind::PermissionDenied); // check that it is the right kind of `PermissionDenied` - assert_eq!(Error::last_os_error().raw_os_error(), Some(libc::EACCES)); + assert_eq!(err.raw_os_error(), Some(libc::EACCES)); } From b49aa8d53e2e1424f5d9997734cfd71b2ae647b4 Mon Sep 17 00:00:00 2001 From: Mateusz Guzik Date: Tue, 10 Jan 2023 02:08:07 +0000 Subject: [PATCH 017/105] Stop probing for statx unless necessary As is the current toy program: fn main() -> std::io::Result<()> { use std::fs; let metadata = fs::metadata("foo.txt")?; assert!(!metadata.is_dir()); Ok(()) } ... observed under strace will issue: [snip] statx(0, NULL, AT_STATX_SYNC_AS_STAT, STATX_ALL, NULL) = -1 EFAULT (Bad address) statx(AT_FDCWD, "foo.txt", AT_STATX_SYNC_AS_STAT, STATX_ALL, {stx_mask=STATX_ALL|STATX_MNT_ID, stx_attributes=0, stx_mode=S_IFREG|0644, stx_size=0, ...}) = 0 While statx is not necessarily always present, checking for it can be delayed to the first error condition. Said condition may very well never happen, in which case the check got avoided altogether. Note this is still suboptimal as there still will be programs issuing it, but bulk of the problem is removed. Tested by forbidding the syscall for the binary and observing it correctly falls back to newfstatat. While here tidy up the commentary, in particular by denoting some problems with the current approach. --- library/std/src/sys/unix/fs.rs | 68 ++++++++++++++++++++-------------- 1 file changed, 41 insertions(+), 27 deletions(-) diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs index aea0c26ee8b6..0e7d23a5c7c9 100644 --- a/library/std/src/sys/unix/fs.rs +++ b/library/std/src/sys/unix/fs.rs @@ -149,12 +149,13 @@ cfg_has_statx! {{ ) -> Option> { use crate::sync::atomic::{AtomicU8, Ordering}; - // Linux kernel prior to 4.11 or glibc prior to glibc 2.28 don't support `statx` - // We store the availability in global to avoid unnecessary syscalls. - // 0: Unknown - // 1: Not available - // 2: Available - static STATX_STATE: AtomicU8 = AtomicU8::new(0); + // Linux kernel prior to 4.11 or glibc prior to glibc 2.28 don't support `statx`. + // We check for it on first failure and remember availability to avoid having to + // do it again. + #[repr(u8)] + enum STATX_STATE{ Unknown = 0, Present, Unavailable } + static STATX_SAVED_STATE: AtomicU8 = AtomicU8::new(STATX_STATE::Unknown as u8); + syscall! { fn statx( fd: c_int, @@ -165,31 +166,44 @@ cfg_has_statx! {{ ) -> c_int } - match STATX_STATE.load(Ordering::Relaxed) { - 0 => { - // It is a trick to call `statx` with null pointers to check if the syscall - // is available. According to the manual, it is expected to fail with EFAULT. - // We do this mainly for performance, since it is nearly hundreds times - // faster than a normal successful call. - let err = cvt(statx(0, ptr::null(), 0, libc::STATX_ALL, ptr::null_mut())) - .err() - .and_then(|e| e.raw_os_error()); - // We don't check `err == Some(libc::ENOSYS)` because the syscall may be limited - // and returns `EPERM`. Listing all possible errors seems not a good idea. - // See: https://github.com/rust-lang/rust/issues/65662 - if err != Some(libc::EFAULT) { - STATX_STATE.store(1, Ordering::Relaxed); - return None; - } - STATX_STATE.store(2, Ordering::Relaxed); - } - 1 => return None, - _ => {} + if STATX_SAVED_STATE.load(Ordering::Relaxed) == STATX_STATE::Unavailable as u8 { + return None; } let mut buf: libc::statx = mem::zeroed(); if let Err(err) = cvt(statx(fd, path, flags, mask, &mut buf)) { - return Some(Err(err)); + if STATX_SAVED_STATE.load(Ordering::Relaxed) == STATX_STATE::Present as u8 { + return Some(Err(err)); + } + + // Availability not checked yet. + // + // First try the cheap way. + if err.raw_os_error() == Some(libc::ENOSYS) { + STATX_SAVED_STATE.store(STATX_STATE::Unavailable as u8, Ordering::Relaxed); + return None; + } + + // Error other than `ENOSYS` is not a good enough indicator -- it is + // known that `EPERM` can be returned as a result of using seccomp to + // block the syscall. + // Availability is checked by performing a call which expects `EFAULT` + // if the syscall is usable. + // See: https://github.com/rust-lang/rust/issues/65662 + // FIXME this can probably just do the call if `EPERM` was received, but + // previous iteration of the code checked it for all errors and for now + // this is retained. + // FIXME what about transient conditions like `ENOMEM`? + let err2 = cvt(statx(0, ptr::null(), 0, libc::STATX_ALL, ptr::null_mut())) + .err() + .and_then(|e| e.raw_os_error()); + if err2 == Some(libc::EFAULT) { + STATX_SAVED_STATE.store(STATX_STATE::Present as u8, Ordering::Relaxed); + return Some(Err(err)); + } else { + STATX_SAVED_STATE.store(STATX_STATE::Unavailable as u8, Ordering::Relaxed); + return None; + } } // We cannot fill `stat64` exhaustively because of private padding fields. From 12ddf778113b291027ff64406ce9d585281debf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 8 Jan 2023 06:54:52 +0000 Subject: [PATCH 018/105] When suggesting writing a fully qualified path probe for appropriate types Fix #46585. --- .../rustc_hir_analysis/src/astconv/mod.rs | 177 ++++++++++++++++-- .../associated-item-duplicate-names-3.stderr | 2 +- ...sociated-types-in-ambiguous-context.stderr | 25 ++- tests/ui/did_you_mean/bad-assoc-ty.stderr | 62 +++++- tests/ui/error-codes/E0223.rs | 4 + tests/ui/error-codes/E0223.stderr | 4 +- tests/ui/impl-trait/impl_trait_projections.rs | 2 +- .../impl-trait/impl_trait_projections.stderr | 9 +- tests/ui/issues/issue-23073.stderr | 7 +- tests/ui/issues/issue-78622.stderr | 7 +- tests/ui/lint/bare-trait-objects-path.stderr | 2 +- .../qualified/qualified-path-params-2.stderr | 7 +- tests/ui/resolve/issue-103202.stderr | 7 +- tests/ui/self/self-impl.stderr | 4 +- .../struct-path-associated-type.stderr | 6 +- .../let-binding-init-expr-as-ty.stderr | 7 +- tests/ui/traits/item-privacy.stderr | 11 +- tests/ui/ufcs/ufcs-partially-resolved.stderr | 7 +- 18 files changed, 295 insertions(+), 55 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 5a7957be318e..7127dadc1e16 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -24,6 +24,7 @@ use rustc_hir::def::{CtorOf, DefKind, Namespace, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::{walk_generics, Visitor as _}; use rustc_hir::{GenericArg, GenericArgs, OpaqueTyOrigin}; +use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::middle::stability::AllowUnstable; use rustc_middle::ty::subst::{self, GenericArgKind, InternalSubsts, SubstsRef}; use rustc_middle::ty::GenericParamDefKind; @@ -1633,8 +1634,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { fn report_ambiguous_associated_type( &self, span: Span, - type_str: &str, - trait_str: &str, + types: &[String], + traits: &[String], name: Symbol, ) -> ErrorGuaranteed { let mut err = struct_span_err!(self.tcx().sess, span, E0223, "ambiguous associated type"); @@ -1645,19 +1646,92 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .keys() .any(|full_span| full_span.contains(span)) { - err.span_suggestion( + err.span_suggestion_verbose( span.shrink_to_lo(), "you are looking for the module in `std`, not the primitive type", "std::", Applicability::MachineApplicable, ); } else { - err.span_suggestion( - span, - "use fully-qualified syntax", - format!("<{} as {}>::{}", type_str, trait_str, name), - Applicability::HasPlaceholders, - ); + match (types, traits) { + ([], []) => { + err.span_suggestion_verbose( + span, + &format!( + "if there were a type named `Type` that implements a trait named \ + `Trait` with associated type `{name}`, you could use the \ + fully-qualified path", + ), + format!("::{name}"), + Applicability::HasPlaceholders, + ); + } + ([], [trait_str]) => { + err.span_suggestion_verbose( + span, + &format!( + "if there were a type named `Example` that implemented `{trait_str}`, \ + you could use the fully-qualified path", + ), + format!("::{name}"), + Applicability::HasPlaceholders, + ); + } + ([], traits) => { + err.span_suggestions( + span, + &format!( + "if there were a type named `Example` that implemented one of the \ + traits with associated type `{name}`, you could use the \ + fully-qualified path", + ), + traits + .iter() + .map(|trait_str| format!("::{name}")) + .collect::>(), + Applicability::HasPlaceholders, + ); + } + ([type_str], []) => { + err.span_suggestion_verbose( + span, + &format!( + "if there were a trait named `Example` with associated type `{name}` \ + implemented for `{type_str}`, you could use the fully-qualified path", + ), + format!("<{type_str} as Example>::{name}"), + Applicability::HasPlaceholders, + ); + } + (types, []) => { + err.span_suggestions( + span, + &format!( + "if there were a trait named `Example` with associated type `{name}` \ + implemented for one of the types, you could use the fully-qualified \ + path", + ), + types + .into_iter() + .map(|type_str| format!("<{type_str} as Example>::{name}")), + Applicability::HasPlaceholders, + ); + } + (types, traits) => { + let mut suggestions = vec![]; + for type_str in types { + for trait_str in traits { + suggestions.push(format!("<{type_str} as {trait_str}>::{name}")); + } + } + err.span_suggestions( + span, + "use the fully-qualified path", + suggestions, + Applicability::MachineApplicable, + ); + } + } } err.emit() } @@ -2040,12 +2114,67 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { err.emit() } else if let Err(reported) = qself_ty.error_reported() { reported + } else if let ty::Alias(ty::Opaque, alias_ty) = qself_ty.kind() { + // `::Assoc` makes no sense. + struct_span_err!( + tcx.sess, + tcx.def_span(alias_ty.def_id), + E0667, + "`impl Trait` is not allowed in path parameters" + ) + .emit() // Already reported in an earlier stage. } else { + // Find all the `impl`s that `qself_ty` has for any trait that has the + // associated type, so that we suggest the right one. + let infcx = tcx.infer_ctxt().build(); + // We create a fresh `ty::ParamEnv` instead of the one for `self.item_def_id()` + // to avoid a cycle error in `src/test/ui/resolve/issue-102946.rs`. + let param_env = ty::ParamEnv::new( + ty::List::empty(), + traits::Reveal::All, + hir::Constness::NotConst, + ); + let traits: Vec<_> = self + .tcx() + .all_traits() + .filter(|trait_def_id| { + // Consider only traits with the associated type + tcx.associated_items(*trait_def_id) + .in_definition_order() + .find(|i| { + i.kind.namespace() == Namespace::TypeNS + && i.ident(tcx).normalize_to_macros_2_0() == assoc_ident + && matches!(i.kind, ty::AssocKind::Type) + }) + .is_some() + // Consider only accessible traits + && tcx.visibility(*trait_def_id) + .is_accessible_from(self.item_def_id(), tcx) + && tcx.all_impls(*trait_def_id) + .filter(|impl_def_id| { + let trait_ref = tcx.impl_trait_ref(impl_def_id); + trait_ref.map_or(false, |impl_| { + infcx + .can_eq( + param_env, + tcx.erase_regions(impl_.self_ty()), + tcx.erase_regions(qself_ty), + ) + .is_ok() + }) + && tcx.impl_polarity(impl_def_id) != ty::ImplPolarity::Negative + }) + .next() + .is_some() + }) + .map(|trait_def_id| tcx.def_path_str(trait_def_id)) + .collect(); + // Don't print `TyErr` to the user. self.report_ambiguous_associated_type( span, - &qself_ty.to_string(), - "Trait", + &[qself_ty.to_string()], + &traits, assoc_ident.name, ) }; @@ -2163,16 +2292,30 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let is_part_of_self_trait_constraints = def_id == trait_def_id; let is_part_of_fn_in_self_trait = parent_def_id == Some(trait_def_id); - let type_name = if is_part_of_self_trait_constraints || is_part_of_fn_in_self_trait { - "Self" + let type_names = if is_part_of_self_trait_constraints || is_part_of_fn_in_self_trait { + vec!["Self".to_string()] } else { - "Type" + // Find all the types that have an `impl` for the trait. + tcx.all_impls(trait_def_id) + .filter(|impl_def_id| { + // Consider only accessible traits + tcx.visibility(*impl_def_id).is_accessible_from(self.item_def_id(), tcx) + && tcx.impl_polarity(impl_def_id) != ty::ImplPolarity::Negative + }) + .filter_map(|impl_def_id| tcx.impl_trait_ref(impl_def_id)) + .map(|impl_| impl_.self_ty()) + // We don't care about blanket impls. + .filter(|self_ty| !self_ty.has_non_region_infer()) + .map(|self_ty| tcx.erase_regions(self_ty).to_string()) + .collect() }; - + // FIXME: also look at `tcx.generics_of(self.item_def_id()).params` any that + // references the trait. Relevant for the first case in + // `src/test/ui/associated-types/associated-types-in-ambiguous-context.rs` let reported = self.report_ambiguous_associated_type( span, - type_name, - &path_str, + &type_names, + &[path_str], item_segment.ident.name, ); return tcx.ty_error_with_guaranteed(reported) diff --git a/tests/ui/associated-item/associated-item-duplicate-names-3.stderr b/tests/ui/associated-item/associated-item-duplicate-names-3.stderr index bf4bd634cf1d..d0c170620766 100644 --- a/tests/ui/associated-item/associated-item-duplicate-names-3.stderr +++ b/tests/ui/associated-item/associated-item-duplicate-names-3.stderr @@ -13,7 +13,7 @@ error[E0223]: ambiguous associated type --> $DIR/associated-item-duplicate-names-3.rs:18:12 | LL | let x: Baz::Bar = 5; - | ^^^^^^^^ help: use fully-qualified syntax: `::Bar` + | ^^^^^^^^ help: use the fully-qualified path: `::Bar` error: aborting due to 2 previous errors diff --git a/tests/ui/associated-types/associated-types-in-ambiguous-context.stderr b/tests/ui/associated-types/associated-types-in-ambiguous-context.stderr index 289911779ff7..00856b55df5e 100644 --- a/tests/ui/associated-types/associated-types-in-ambiguous-context.stderr +++ b/tests/ui/associated-types/associated-types-in-ambiguous-context.stderr @@ -2,31 +2,46 @@ error[E0223]: ambiguous associated type --> $DIR/associated-types-in-ambiguous-context.rs:6:36 | LL | fn get(x: T, y: U) -> Get::Value {} - | ^^^^^^^^^^ help: use fully-qualified syntax: `::Value` + | ^^^^^^^^^^ + | +help: if there were a type named `Example` that implemented `Get`, you could use the fully-qualified path + | +LL | fn get(x: T, y: U) -> ::Value {} + | ~~~~~~~~~~~~~~~~~~~~~~~ error[E0223]: ambiguous associated type --> $DIR/associated-types-in-ambiguous-context.rs:20:17 | LL | trait Foo where Foo::Assoc: Bar { - | ^^^^^^^^^^ help: use fully-qualified syntax: `::Assoc` + | ^^^^^^^^^^ help: use the fully-qualified path: `::Assoc` error[E0223]: ambiguous associated type --> $DIR/associated-types-in-ambiguous-context.rs:25:10 | LL | type X = std::ops::Deref::Target; - | ^^^^^^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `::Target` + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: if there were a type named `Example` that implemented `Deref`, you could use the fully-qualified path + | +LL | type X = ::Target; + | ~~~~~~~~~~~~~~~~~~~~~~~~~~ error[E0223]: ambiguous associated type --> $DIR/associated-types-in-ambiguous-context.rs:11:23 | LL | fn grab(&self) -> Grab::Value; - | ^^^^^^^^^^^ help: use fully-qualified syntax: `::Value` + | ^^^^^^^^^^^ help: use the fully-qualified path: `::Value` error[E0223]: ambiguous associated type --> $DIR/associated-types-in-ambiguous-context.rs:14:22 | LL | fn get(&self) -> Get::Value; - | ^^^^^^^^^^ help: use fully-qualified syntax: `::Value` + | ^^^^^^^^^^ + | +help: if there were a type named `Example` that implemented `Get`, you could use the fully-qualified path + | +LL | fn get(&self) -> ::Value; + | ~~~~~~~~~~~~~~~~~~~~~~~ error: aborting due to 5 previous errors diff --git a/tests/ui/did_you_mean/bad-assoc-ty.stderr b/tests/ui/did_you_mean/bad-assoc-ty.stderr index 21f957ab549a..7cd349c7507f 100644 --- a/tests/ui/did_you_mean/bad-assoc-ty.stderr +++ b/tests/ui/did_you_mean/bad-assoc-ty.stderr @@ -61,25 +61,45 @@ error[E0223]: ambiguous associated type --> $DIR/bad-assoc-ty.rs:1:10 | LL | type A = [u8; 4]::AssocTy; - | ^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<[u8; 4] as Trait>::AssocTy` + | ^^^^^^^^^^^^^^^^ + | +help: if there were a trait named `Example` with associated type `AssocTy` implemented for `[u8; 4]`, you could use the fully-qualified path + | +LL | type A = <[u8; 4] as Example>::AssocTy; + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error[E0223]: ambiguous associated type --> $DIR/bad-assoc-ty.rs:5:10 | LL | type B = [u8]::AssocTy; - | ^^^^^^^^^^^^^ help: use fully-qualified syntax: `<[u8] as Trait>::AssocTy` + | ^^^^^^^^^^^^^ + | +help: if there were a trait named `Example` with associated type `AssocTy` implemented for `[u8]`, you could use the fully-qualified path + | +LL | type B = <[u8] as Example>::AssocTy; + | ~~~~~~~~~~~~~~~~~~~~~~~~~~ error[E0223]: ambiguous associated type --> $DIR/bad-assoc-ty.rs:9:10 | LL | type C = (u8)::AssocTy; - | ^^^^^^^^^^^^^ help: use fully-qualified syntax: `::AssocTy` + | ^^^^^^^^^^^^^ + | +help: if there were a trait named `Example` with associated type `AssocTy` implemented for `u8`, you could use the fully-qualified path + | +LL | type C = ::AssocTy; + | ~~~~~~~~~~~~~~~~~~~~~~~~ error[E0223]: ambiguous associated type --> $DIR/bad-assoc-ty.rs:13:10 | LL | type D = (u8, u8)::AssocTy; - | ^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<(u8, u8) as Trait>::AssocTy` + | ^^^^^^^^^^^^^^^^^ + | +help: if there were a trait named `Example` with associated type `AssocTy` implemented for `(u8, u8)`, you could use the fully-qualified path + | +LL | type D = <(u8, u8) as Example>::AssocTy; + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error[E0121]: the placeholder `_` is not allowed within types on item signatures for type aliases --> $DIR/bad-assoc-ty.rs:17:10 @@ -91,13 +111,23 @@ error[E0223]: ambiguous associated type --> $DIR/bad-assoc-ty.rs:21:19 | LL | type F = &'static (u8)::AssocTy; - | ^^^^^^^^^^^^^ help: use fully-qualified syntax: `::AssocTy` + | ^^^^^^^^^^^^^ + | +help: if there were a trait named `Example` with associated type `AssocTy` implemented for `u8`, you could use the fully-qualified path + | +LL | type F = &'static ::AssocTy; + | ~~~~~~~~~~~~~~~~~~~~~~~~ error[E0223]: ambiguous associated type --> $DIR/bad-assoc-ty.rs:27:10 | LL | type G = dyn 'static + (Send)::AssocTy; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<(dyn Send + 'static) as Trait>::AssocTy` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: if there were a trait named `Example` with associated type `AssocTy` implemented for `(dyn Send + 'static)`, you could use the fully-qualified path + | +LL | type G = <(dyn Send + 'static) as Example>::AssocTy; + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ warning: trait objects without an explicit `dyn` are deprecated --> $DIR/bad-assoc-ty.rs:33:10 @@ -117,24 +147,38 @@ error[E0223]: ambiguous associated type --> $DIR/bad-assoc-ty.rs:33:10 | LL | type H = Fn(u8) -> (u8)::Output; - | ^^^^^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<(dyn Fn(u8) -> u8 + 'static) as Trait>::Output` + | ^^^^^^^^^^^^^^^^^^^^^^ + | +help: if there were a trait named `Example` with associated type `Output` implemented for `(dyn Fn(u8) -> u8 + 'static)`, you could use the fully-qualified path + | +LL | type H = <(dyn Fn(u8) -> u8 + 'static) as Example>::Output; + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error[E0223]: ambiguous associated type --> $DIR/bad-assoc-ty.rs:39:19 | LL | ($ty: ty) => ($ty::AssocTy); - | ^^^^^^^^^^^^ help: use fully-qualified syntax: `::AssocTy` + | ^^^^^^^^^^^^ ... LL | type J = ty!(u8); | ------- in this macro invocation | = note: this error originates in the macro `ty` (in Nightly builds, run with -Z macro-backtrace for more info) +help: if there were a trait named `Example` with associated type `AssocTy` implemented for `u8`, you could use the fully-qualified path + | +LL | ($ty: ty) => (::AssocTy); + | ~~~~~~~~~~~~~~~~~~~~~~~~ error[E0223]: ambiguous associated type --> $DIR/bad-assoc-ty.rs:46:10 | LL | type I = ty!()::AssocTy; - | ^^^^^^^^^^^^^^ help: use fully-qualified syntax: `::AssocTy` + | ^^^^^^^^^^^^^^ + | +help: if there were a trait named `Example` with associated type `AssocTy` implemented for `u8`, you could use the fully-qualified path + | +LL | type I = ::AssocTy; + | ~~~~~~~~~~~~~~~~~~~~~~~~ error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions --> $DIR/bad-assoc-ty.rs:51:13 diff --git a/tests/ui/error-codes/E0223.rs b/tests/ui/error-codes/E0223.rs index 6031b682d72a..2fe252de2566 100644 --- a/tests/ui/error-codes/E0223.rs +++ b/tests/ui/error-codes/E0223.rs @@ -1,4 +1,8 @@ trait MyTrait { type X; } +struct MyStruct; +impl MyTrait for MyStruct { + type X = (); +} fn main() { let foo: MyTrait::X; diff --git a/tests/ui/error-codes/E0223.stderr b/tests/ui/error-codes/E0223.stderr index 726f39e11f13..42945e42f6ea 100644 --- a/tests/ui/error-codes/E0223.stderr +++ b/tests/ui/error-codes/E0223.stderr @@ -1,8 +1,8 @@ error[E0223]: ambiguous associated type - --> $DIR/E0223.rs:4:14 + --> $DIR/E0223.rs:8:14 | LL | let foo: MyTrait::X; - | ^^^^^^^^^^ help: use fully-qualified syntax: `::X` + | ^^^^^^^^^^ help: use the fully-qualified path: `::X` error: aborting due to previous error diff --git a/tests/ui/impl-trait/impl_trait_projections.rs b/tests/ui/impl-trait/impl_trait_projections.rs index fd0986d7c0a9..b3ff2ce5a7bf 100644 --- a/tests/ui/impl-trait/impl_trait_projections.rs +++ b/tests/ui/impl-trait/impl_trait_projections.rs @@ -11,7 +11,7 @@ fn path_parametrized_type_is_allowed() -> option::Option { fn projection_is_disallowed(x: impl Iterator) -> ::Item { //~^ ERROR `impl Trait` is not allowed in path parameters -//~^^ ERROR ambiguous associated type +//~| ERROR `impl Trait` is not allowed in path parameters x.next().unwrap() } diff --git a/tests/ui/impl-trait/impl_trait_projections.stderr b/tests/ui/impl-trait/impl_trait_projections.stderr index 82d2422c4077..4deb24731bc0 100644 --- a/tests/ui/impl-trait/impl_trait_projections.stderr +++ b/tests/ui/impl-trait/impl_trait_projections.stderr @@ -22,13 +22,12 @@ error[E0667]: `impl Trait` is not allowed in path parameters LL | -> as Iterator>::Item | ^^^^^^^^^^ -error[E0223]: ambiguous associated type - --> $DIR/impl_trait_projections.rs:12:50 +error[E0667]: `impl Trait` is not allowed in path parameters + --> $DIR/impl_trait_projections.rs:12:51 | LL | fn projection_is_disallowed(x: impl Iterator) -> ::Item { - | ^^^^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `::Item` + | ^^^^^^^^^^^^^ error: aborting due to 5 previous errors -Some errors have detailed explanations: E0223, E0667. -For more information about an error, try `rustc --explain E0223`. +For more information about this error, try `rustc --explain E0667`. diff --git a/tests/ui/issues/issue-23073.stderr b/tests/ui/issues/issue-23073.stderr index 3a10a1ab11ac..3a9f49ef167d 100644 --- a/tests/ui/issues/issue-23073.stderr +++ b/tests/ui/issues/issue-23073.stderr @@ -2,7 +2,12 @@ error[E0223]: ambiguous associated type --> $DIR/issue-23073.rs:6:17 | LL | type FooT = <::Foo>::T; - | ^^^^^^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<::Foo as Trait>::T` + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: if there were a trait named `Example` with associated type `T` implemented for `::Foo`, you could use the fully-qualified path + | +LL | type FooT = <::Foo as Example>::T; + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: aborting due to previous error diff --git a/tests/ui/issues/issue-78622.stderr b/tests/ui/issues/issue-78622.stderr index f7d44f21d3be..70daf8a2f1a6 100644 --- a/tests/ui/issues/issue-78622.stderr +++ b/tests/ui/issues/issue-78622.stderr @@ -2,7 +2,12 @@ error[E0223]: ambiguous associated type --> $DIR/issue-78622.rs:5:5 | LL | S::A:: {} - | ^^^^ help: use fully-qualified syntax: `::A` + | ^^^^ + | +help: if there were a trait named `Example` with associated type `A` implemented for `S`, you could use the fully-qualified path + | +LL | ::A:: {} + | ~~~~~~~~~~~~~~~~~ error: aborting due to previous error diff --git a/tests/ui/lint/bare-trait-objects-path.stderr b/tests/ui/lint/bare-trait-objects-path.stderr index 8ed303ca6069..a19f4963c239 100644 --- a/tests/ui/lint/bare-trait-objects-path.stderr +++ b/tests/ui/lint/bare-trait-objects-path.stderr @@ -16,7 +16,7 @@ error[E0223]: ambiguous associated type --> $DIR/bare-trait-objects-path.rs:23:12 | LL | let _: Dyn::Ty; - | ^^^^^^^ help: use fully-qualified syntax: `::Ty` + | ^^^^^^^ help: use the fully-qualified path: `::Ty` warning: trait objects without an explicit `dyn` are deprecated --> $DIR/bare-trait-objects-path.rs:14:5 diff --git a/tests/ui/qualified/qualified-path-params-2.stderr b/tests/ui/qualified/qualified-path-params-2.stderr index 948f21fce4bd..b6cf19b8286c 100644 --- a/tests/ui/qualified/qualified-path-params-2.stderr +++ b/tests/ui/qualified/qualified-path-params-2.stderr @@ -2,7 +2,12 @@ error[E0223]: ambiguous associated type --> $DIR/qualified-path-params-2.rs:18:10 | LL | type A = ::A::f; - | ^^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<::A as Trait>::f` + | ^^^^^^^^^^^^^^^^^^^ + | +help: if there were a trait named `Example` with associated type `f` implemented for `::A`, you could use the fully-qualified path + | +LL | type A = <::A as Example>::f; + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: aborting due to previous error diff --git a/tests/ui/resolve/issue-103202.stderr b/tests/ui/resolve/issue-103202.stderr index 880389371ef7..d4d141fb06f3 100644 --- a/tests/ui/resolve/issue-103202.stderr +++ b/tests/ui/resolve/issue-103202.stderr @@ -2,7 +2,12 @@ error[E0223]: ambiguous associated type --> $DIR/issue-103202.rs:4:17 | LL | fn f(self: &S::x) {} - | ^^^^ help: use fully-qualified syntax: `::x` + | ^^^^ + | +help: if there were a trait named `Example` with associated type `x` implemented for `S`, you could use the fully-qualified path + | +LL | fn f(self: &::x) {} + | ~~~~~~~~~~~~~~~~~ error: aborting due to previous error diff --git a/tests/ui/self/self-impl.stderr b/tests/ui/self/self-impl.stderr index fb47f27e022f..36372b644d6e 100644 --- a/tests/ui/self/self-impl.stderr +++ b/tests/ui/self/self-impl.stderr @@ -2,13 +2,13 @@ error[E0223]: ambiguous associated type --> $DIR/self-impl.rs:23:16 | LL | let _: ::Baz = true; - | ^^^^^^^^^^^ help: use fully-qualified syntax: `::Baz` + | ^^^^^^^^^^^ help: use the fully-qualified path: `::Baz` error[E0223]: ambiguous associated type --> $DIR/self-impl.rs:25:16 | LL | let _: Self::Baz = true; - | ^^^^^^^^^ help: use fully-qualified syntax: `::Baz` + | ^^^^^^^^^ help: use the fully-qualified path: `::Baz` error: aborting due to 2 previous errors diff --git a/tests/ui/structs/struct-path-associated-type.stderr b/tests/ui/structs/struct-path-associated-type.stderr index abb445214f36..ca5f0b7e21e7 100644 --- a/tests/ui/structs/struct-path-associated-type.stderr +++ b/tests/ui/structs/struct-path-associated-type.stderr @@ -48,19 +48,19 @@ error[E0223]: ambiguous associated type --> $DIR/struct-path-associated-type.rs:32:13 | LL | let s = S::A {}; - | ^^^^ help: use fully-qualified syntax: `::A` + | ^^^^ help: use the fully-qualified path: `::A` error[E0223]: ambiguous associated type --> $DIR/struct-path-associated-type.rs:33:13 | LL | let z = S::A:: {}; - | ^^^^ help: use fully-qualified syntax: `::A` + | ^^^^ help: use the fully-qualified path: `::A` error[E0223]: ambiguous associated type --> $DIR/struct-path-associated-type.rs:35:9 | LL | S::A {} => {} - | ^^^^ help: use fully-qualified syntax: `::A` + | ^^^^ help: use the fully-qualified path: `::A` error: aborting due to 8 previous errors diff --git a/tests/ui/suggestions/let-binding-init-expr-as-ty.stderr b/tests/ui/suggestions/let-binding-init-expr-as-ty.stderr index 2bf072ef5217..b90ae051fb77 100644 --- a/tests/ui/suggestions/let-binding-init-expr-as-ty.stderr +++ b/tests/ui/suggestions/let-binding-init-expr-as-ty.stderr @@ -21,7 +21,12 @@ error[E0223]: ambiguous associated type --> $DIR/let-binding-init-expr-as-ty.rs:2:14 | LL | let foo: i32::from_be(num); - | ^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `::from_be` + | ^^^^^^^^^^^^^^^^^ + | +help: if there were a trait named `Example` with associated type `from_be` implemented for `i32`, you could use the fully-qualified path + | +LL | let foo: ::from_be; + | ~~~~~~~~~~~~~~~~~~~~~~~~~ error: aborting due to 3 previous errors diff --git a/tests/ui/traits/item-privacy.stderr b/tests/ui/traits/item-privacy.stderr index f137a298a7f4..293cfbda86c4 100644 --- a/tests/ui/traits/item-privacy.stderr +++ b/tests/ui/traits/item-privacy.stderr @@ -148,19 +148,24 @@ error[E0223]: ambiguous associated type --> $DIR/item-privacy.rs:115:12 | LL | let _: S::A; - | ^^^^ help: use fully-qualified syntax: `::A` + | ^^^^ + | +help: if there were a trait named `Example` with associated type `A` implemented for `S`, you could use the fully-qualified path + | +LL | let _: ::A; + | ~~~~~~~~~~~~~~~~~ error[E0223]: ambiguous associated type --> $DIR/item-privacy.rs:116:12 | LL | let _: S::B; - | ^^^^ help: use fully-qualified syntax: `::B` + | ^^^^ help: use the fully-qualified path: `::B` error[E0223]: ambiguous associated type --> $DIR/item-privacy.rs:117:12 | LL | let _: S::C; - | ^^^^ help: use fully-qualified syntax: `::C` + | ^^^^ help: use the fully-qualified path: `::C` error[E0624]: associated type `A` is private --> $DIR/item-privacy.rs:119:12 diff --git a/tests/ui/ufcs/ufcs-partially-resolved.stderr b/tests/ui/ufcs/ufcs-partially-resolved.stderr index 5f7f6aa9f6ec..72fccea8ae39 100644 --- a/tests/ui/ufcs/ufcs-partially-resolved.stderr +++ b/tests/ui/ufcs/ufcs-partially-resolved.stderr @@ -205,7 +205,12 @@ error[E0223]: ambiguous associated type --> $DIR/ufcs-partially-resolved.rs:36:12 | LL | let _: ::Y::NN; - | ^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<::Y as Trait>::NN` + | ^^^^^^^^^^^^^^^^^ + | +help: if there were a trait named `Example` with associated type `NN` implemented for `::Y`, you could use the fully-qualified path + | +LL | let _: <::Y as Example>::NN; + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error[E0599]: no associated item named `NN` found for type `u16` in the current scope --> $DIR/ufcs-partially-resolved.rs:38:20 From 147c9bf4d56d7a9cf5fb70270b3e68c730da7d95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 8 Jan 2023 07:24:36 +0000 Subject: [PATCH 019/105] review comments --- compiler/rustc_hir_analysis/src/astconv/mod.rs | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 7127dadc1e16..315a2a2af1bc 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -2129,11 +2129,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let infcx = tcx.infer_ctxt().build(); // We create a fresh `ty::ParamEnv` instead of the one for `self.item_def_id()` // to avoid a cycle error in `src/test/ui/resolve/issue-102946.rs`. - let param_env = ty::ParamEnv::new( - ty::List::empty(), - traits::Reveal::All, - hir::Constness::NotConst, - ); + let param_env = ty::ParamEnv::empty(); let traits: Vec<_> = self .tcx() .all_traits() @@ -2141,17 +2137,16 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // Consider only traits with the associated type tcx.associated_items(*trait_def_id) .in_definition_order() - .find(|i| { + .any(|i| { i.kind.namespace() == Namespace::TypeNS && i.ident(tcx).normalize_to_macros_2_0() == assoc_ident && matches!(i.kind, ty::AssocKind::Type) }) - .is_some() // Consider only accessible traits && tcx.visibility(*trait_def_id) .is_accessible_from(self.item_def_id(), tcx) && tcx.all_impls(*trait_def_id) - .filter(|impl_def_id| { + .any(|impl_def_id| { let trait_ref = tcx.impl_trait_ref(impl_def_id); trait_ref.map_or(false, |impl_| { infcx @@ -2164,8 +2159,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { }) && tcx.impl_polarity(impl_def_id) != ty::ImplPolarity::Negative }) - .next() - .is_some() }) .map(|trait_def_id| tcx.def_path_str(trait_def_id)) .collect(); @@ -2305,7 +2298,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .filter_map(|impl_def_id| tcx.impl_trait_ref(impl_def_id)) .map(|impl_| impl_.self_ty()) // We don't care about blanket impls. - .filter(|self_ty| !self_ty.has_non_region_infer()) + .filter(|self_ty| !self_ty.has_non_region_param()) .map(|self_ty| tcx.erase_regions(self_ty).to_string()) .collect() }; From c6f322bf300c7c963a4e4e8bb642c3959b74888a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 8 Jan 2023 20:51:40 +0000 Subject: [PATCH 020/105] review comments: account for generics --- compiler/rustc_hir_analysis/src/astconv/mod.rs | 8 ++++++-- .../ambiguous-associated-type-with-generics.fixed | 14 ++++++++++++++ .../ambiguous-associated-type-with-generics.rs | 14 ++++++++++++++ .../ambiguous-associated-type-with-generics.stderr | 9 +++++++++ tests/ui/did_you_mean/bad-assoc-ty.stderr | 7 +------ 5 files changed, 44 insertions(+), 8 deletions(-) create mode 100644 tests/ui/associated-item/ambiguous-associated-type-with-generics.fixed create mode 100644 tests/ui/associated-item/ambiguous-associated-type-with-generics.rs create mode 100644 tests/ui/associated-item/ambiguous-associated-type-with-generics.stderr diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 315a2a2af1bc..5baaaf09edb6 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -2147,8 +2147,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .is_accessible_from(self.item_def_id(), tcx) && tcx.all_impls(*trait_def_id) .any(|impl_def_id| { - let trait_ref = tcx.impl_trait_ref(impl_def_id); - trait_ref.map_or(false, |impl_| { + let trait_ref = tcx.bound_impl_trait_ref(impl_def_id); + trait_ref.map_or(false, |trait_ref| { + let impl_ = trait_ref.subst( + tcx, + infcx.fresh_substs_for_item(span, impl_def_id), + ); infcx .can_eq( param_env, diff --git a/tests/ui/associated-item/ambiguous-associated-type-with-generics.fixed b/tests/ui/associated-item/ambiguous-associated-type-with-generics.fixed new file mode 100644 index 000000000000..23f715200400 --- /dev/null +++ b/tests/ui/associated-item/ambiguous-associated-type-with-generics.fixed @@ -0,0 +1,14 @@ +// run-rustfix +trait Trait {} + +trait Assoc { + type Ty; +} + +impl Assoc for dyn Trait { + type Ty = i32; +} + +fn main() { + let _x: as Assoc>::Ty; //~ ERROR ambiguous associated type +} diff --git a/tests/ui/associated-item/ambiguous-associated-type-with-generics.rs b/tests/ui/associated-item/ambiguous-associated-type-with-generics.rs new file mode 100644 index 000000000000..9c26e339a449 --- /dev/null +++ b/tests/ui/associated-item/ambiguous-associated-type-with-generics.rs @@ -0,0 +1,14 @@ +// run-rustfix +trait Trait {} + +trait Assoc { + type Ty; +} + +impl Assoc for dyn Trait { + type Ty = i32; +} + +fn main() { + let _x: >::Ty; //~ ERROR ambiguous associated type +} diff --git a/tests/ui/associated-item/ambiguous-associated-type-with-generics.stderr b/tests/ui/associated-item/ambiguous-associated-type-with-generics.stderr new file mode 100644 index 000000000000..97088b79fd67 --- /dev/null +++ b/tests/ui/associated-item/ambiguous-associated-type-with-generics.stderr @@ -0,0 +1,9 @@ +error[E0223]: ambiguous associated type + --> $DIR/ambiguous-associated-type-with-generics.rs:13:13 + | +LL | let _x: >::Ty; + | ^^^^^^^^^^^^^^^^^^^^ help: use the fully-qualified path: ` as Assoc>::Ty` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0223`. diff --git a/tests/ui/did_you_mean/bad-assoc-ty.stderr b/tests/ui/did_you_mean/bad-assoc-ty.stderr index 7cd349c7507f..55096e95df7e 100644 --- a/tests/ui/did_you_mean/bad-assoc-ty.stderr +++ b/tests/ui/did_you_mean/bad-assoc-ty.stderr @@ -147,12 +147,7 @@ error[E0223]: ambiguous associated type --> $DIR/bad-assoc-ty.rs:33:10 | LL | type H = Fn(u8) -> (u8)::Output; - | ^^^^^^^^^^^^^^^^^^^^^^ - | -help: if there were a trait named `Example` with associated type `Output` implemented for `(dyn Fn(u8) -> u8 + 'static)`, you could use the fully-qualified path - | -LL | type H = <(dyn Fn(u8) -> u8 + 'static) as Example>::Output; - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ^^^^^^^^^^^^^^^^^^^^^^ help: use the fully-qualified path: `<(dyn Fn(u8) -> u8 + 'static) as IntoFuture>::Output` error[E0223]: ambiguous associated type --> $DIR/bad-assoc-ty.rs:39:19 From 337a97d3741bb78319cde745119cf96941b78325 Mon Sep 17 00:00:00 2001 From: asquared31415 <34665709+asquared31415@users.noreply.github.com> Date: Fri, 23 Dec 2022 13:54:14 -0500 Subject: [PATCH 021/105] add checks for the signature of the lang item --- .../locales/en-US/hir_typeck.ftl | 11 ++ compiler/rustc_hir_typeck/src/check.rs | 133 +++++++++++++++++- compiler/rustc_hir_typeck/src/errors.rs | 33 +++++ src/tools/clippy/tests/ui/def_id_nocore.rs | 2 +- tests/run-make-fulldeps/target-specs/foo.rs | 2 +- .../start_lang_item_args.argc.stderr | 8 ++ .../start_lang_item_args.argv.stderr | 8 ++ ...start_lang_item_args.argv_inner_ptr.stderr | 13 ++ .../start_lang_item_args.main_args.stderr | 13 ++ .../start_lang_item_args.main_ret.stderr | 13 ++ .../start_lang_item_args.main_ty.stderr | 8 ++ ...art_lang_item_args.missing_all_args.stderr | 11 ++ .../start_lang_item_args.missing_ret.stderr | 8 ++ ..._lang_item_args.missing_sigpipe_arg.stderr | 11 ++ tests/ui/lang-items/start_lang_item_args.rs | 101 +++++++++++++ .../start_lang_item_args.sigpipe.stderr | 8 ++ .../start_lang_item_args.start_ret.stderr | 8 ++ .../start_lang_item_args.too_many_args.stderr | 17 +++ 18 files changed, 405 insertions(+), 3 deletions(-) create mode 100644 tests/ui/lang-items/start_lang_item_args.argc.stderr create mode 100644 tests/ui/lang-items/start_lang_item_args.argv.stderr create mode 100644 tests/ui/lang-items/start_lang_item_args.argv_inner_ptr.stderr create mode 100644 tests/ui/lang-items/start_lang_item_args.main_args.stderr create mode 100644 tests/ui/lang-items/start_lang_item_args.main_ret.stderr create mode 100644 tests/ui/lang-items/start_lang_item_args.main_ty.stderr create mode 100644 tests/ui/lang-items/start_lang_item_args.missing_all_args.stderr create mode 100644 tests/ui/lang-items/start_lang_item_args.missing_ret.stderr create mode 100644 tests/ui/lang-items/start_lang_item_args.missing_sigpipe_arg.stderr create mode 100644 tests/ui/lang-items/start_lang_item_args.rs create mode 100644 tests/ui/lang-items/start_lang_item_args.sigpipe.stderr create mode 100644 tests/ui/lang-items/start_lang_item_args.start_ret.stderr create mode 100644 tests/ui/lang-items/start_lang_item_args.too_many_args.stderr diff --git a/compiler/rustc_error_messages/locales/en-US/hir_typeck.ftl b/compiler/rustc_error_messages/locales/en-US/hir_typeck.ftl index 0612dbae0b63..ca72b7faa928 100644 --- a/compiler/rustc_error_messages/locales/en-US/hir_typeck.ftl +++ b/compiler/rustc_error_messages/locales/en-US/hir_typeck.ftl @@ -46,3 +46,14 @@ hir_typeck_add_missing_parentheses_in_range = you must surround the range in par hir_typeck_op_trait_generic_params = `{$method_name}` must not have any generic parameters + +hir_typeck_lang_start_incorrect_number_params = incorrect number of parameters for the `start` lang item +hir_typeck_lang_start_incorrect_number_params_note_expected_count = the `start` lang item should have four parameters, but found {$found_param_count} + +hir_typeck_lang_start_expected_sig_note = the `start` lang item should have the signature `fn(fn() -> T, isize, *const *const u8, u8) -> isize` + +hir_typeck_lang_start_incorrect_param = parameter {$param_num} of the `start` lang item is incorrect + .suggestion = change the type from `{$found_ty}` to `{$expected_ty}` + +hir_typeck_lang_start_incorrect_ret_ty = the return type of the `start` lang item is incorrect + .suggestion = change the type from `{$found_ty}` to `{$expected_ty}` diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs index 32f86b8042c1..57feefbcab6c 100644 --- a/compiler/rustc_hir_typeck/src/check.rs +++ b/compiler/rustc_hir_typeck/src/check.rs @@ -1,4 +1,7 @@ use crate::coercion::CoerceMany; +use crate::errors::{ + LangStartIncorrectNumberArgs, LangStartIncorrectParam, LangStartIncorrectRetTy, +}; use crate::gather_locals::GatherLocalsVisitor; use crate::FnCtxt; use crate::GeneratorTypes; @@ -9,8 +12,9 @@ use rustc_hir::lang_items::LangItem; use rustc_hir_analysis::check::fn_maybe_err; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::RegionVariableOrigin; -use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_middle::ty::{self, Binder, Ty, TyCtxt}; use rustc_span::def_id::LocalDefId; +use rustc_target::spec::abi::Abi; use rustc_trait_selection::traits; use std::cell::RefCell; @@ -168,6 +172,10 @@ pub(super) fn check_fn<'a, 'tcx>( check_panic_info_fn(tcx, panic_impl_did.expect_local(), fn_sig, decl, declared_ret_ty); } + if let Some(lang_start_defid) = tcx.lang_items().start_fn() && lang_start_defid == hir.local_def_id(fn_id).to_def_id() { + check_lang_start_fn(tcx, fn_sig, decl, fn_def_id); + } + gen_ty } @@ -223,3 +231,126 @@ fn check_panic_info_fn( tcx.sess.span_err(span, "should have no const parameters"); } } + +fn check_lang_start_fn<'tcx>( + tcx: TyCtxt<'tcx>, + fn_sig: ty::FnSig<'tcx>, + decl: &'tcx hir::FnDecl<'tcx>, + def_id: LocalDefId, +) { + let inputs = fn_sig.inputs(); + + let arg_count = inputs.len(); + if arg_count != 4 { + tcx.sess.emit_err(LangStartIncorrectNumberArgs { + params_span: tcx.def_span(def_id), + found_param_count: arg_count, + }); + } + + // only check args if they should exist by checking the count + // note: this does not handle args being shifted or their order swapped very nicely + // but it's a lang item, users shouldn't frequently encounter this + + // first arg is `main: fn() -> T` + if let Some(&main_arg) = inputs.get(0) { + // make a Ty for the generic on the fn for diagnostics + // FIXME: make the lang item generic checks check for the right generic *kind* + // for example `start`'s generic should be a type parameter + let generics = tcx.generics_of(def_id); + let fn_generic = generics.param_at(0, tcx); + let generic_tykind = + ty::Param(ty::ParamTy { index: fn_generic.index, name: fn_generic.name }); + let generic_ty = tcx.mk_ty(generic_tykind); + let expected_fn_sig = + tcx.mk_fn_sig([].iter(), &generic_ty, false, hir::Unsafety::Normal, Abi::Rust); + let expected_ty = tcx.mk_fn_ptr(Binder::dummy(expected_fn_sig)); + + // we emit the same error to suggest changing the arg no matter what's wrong with the arg + let emit_main_fn_arg_err = || { + tcx.sess.emit_err(LangStartIncorrectParam { + param_span: decl.inputs[0].span, + param_num: 1, + expected_ty: expected_ty, + found_ty: main_arg, + }); + }; + + if let ty::FnPtr(main_fn_sig) = main_arg.kind() { + let main_fn_inputs = main_fn_sig.inputs(); + if main_fn_inputs.iter().count() != 0 { + emit_main_fn_arg_err(); + } + + let output = main_fn_sig.output(); + output.map_bound(|ret_ty| { + // if the output ty is a generic, it's probably the right one + if !matches!(ret_ty.kind(), ty::Param(_)) { + emit_main_fn_arg_err(); + } + }); + } else { + emit_main_fn_arg_err(); + } + } + + // second arg is isize + if let Some(&argc_arg) = inputs.get(1) { + if argc_arg != tcx.types.isize { + tcx.sess.emit_err(LangStartIncorrectParam { + param_span: decl.inputs[1].span, + param_num: 2, + expected_ty: tcx.types.isize, + found_ty: argc_arg, + }); + } + } + + // third arg is `*const *const u8` + if let Some(&argv_arg) = inputs.get(2) { + let mut argv_is_okay = false; + if let ty::RawPtr(outer_ptr) = argv_arg.kind() { + if outer_ptr.mutbl.is_not() { + if let ty::RawPtr(inner_ptr) = outer_ptr.ty.kind() { + if inner_ptr.mutbl.is_not() && inner_ptr.ty == tcx.types.u8 { + argv_is_okay = true; + } + } + } + } + + if !argv_is_okay { + let inner_ptr_ty = + tcx.mk_ptr(ty::TypeAndMut { mutbl: hir::Mutability::Not, ty: tcx.types.u8 }); + let expected_ty = + tcx.mk_ptr(ty::TypeAndMut { mutbl: hir::Mutability::Not, ty: inner_ptr_ty }); + tcx.sess.emit_err(LangStartIncorrectParam { + param_span: decl.inputs[2].span, + param_num: 3, + expected_ty, + found_ty: argv_arg, + }); + } + } + + // fourth arg is `sigpipe: u8` + if let Some(&sigpipe_arg) = inputs.get(3) { + if sigpipe_arg != tcx.types.u8 { + tcx.sess.emit_err(LangStartIncorrectParam { + param_span: decl.inputs[3].span, + param_num: 4, + expected_ty: tcx.types.u8, + found_ty: sigpipe_arg, + }); + } + } + + // output type is isize + if fn_sig.output() != tcx.types.isize { + tcx.sess.emit_err(LangStartIncorrectRetTy { + ret_span: decl.output.span(), + expected_ty: tcx.types.isize, + found_ty: fn_sig.output(), + }); + } +} diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index 507272fdec5d..5b4fd5e4a528 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -172,3 +172,36 @@ impl AddToDiagnostic for TypeMismatchFruTypo { ); } } + +#[derive(Diagnostic)] +#[diag(hir_typeck_lang_start_incorrect_number_params)] +#[note(hir_typeck_lang_start_incorrect_number_params_note_expected_count)] +#[note(hir_typeck_lang_start_expected_sig_note)] +pub struct LangStartIncorrectNumberArgs { + #[primary_span] + pub params_span: Span, + pub found_param_count: usize, +} + +#[derive(Diagnostic)] +#[diag(hir_typeck_lang_start_incorrect_param)] +pub struct LangStartIncorrectParam<'tcx> { + #[primary_span] + #[suggestion(style = "short", code = "{expected_ty}", applicability = "machine-applicable")] + pub param_span: Span, + + pub param_num: usize, + pub expected_ty: Ty<'tcx>, + pub found_ty: Ty<'tcx>, +} + +#[derive(Diagnostic)] +#[diag(hir_typeck_lang_start_incorrect_ret_ty)] +pub struct LangStartIncorrectRetTy<'tcx> { + #[primary_span] + #[suggestion(style = "short", code = "{expected_ty}", applicability = "machine-applicable")] + pub ret_span: Span, + + pub expected_ty: Ty<'tcx>, + pub found_ty: Ty<'tcx>, +} diff --git a/src/tools/clippy/tests/ui/def_id_nocore.rs b/src/tools/clippy/tests/ui/def_id_nocore.rs index a7da8f89aa3d..1af77d1a25b2 100644 --- a/src/tools/clippy/tests/ui/def_id_nocore.rs +++ b/src/tools/clippy/tests/ui/def_id_nocore.rs @@ -15,7 +15,7 @@ pub trait Copy {} pub unsafe trait Freeze {} #[lang = "start"] -fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8) -> isize { +fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize { 0 } diff --git a/tests/run-make-fulldeps/target-specs/foo.rs b/tests/run-make-fulldeps/target-specs/foo.rs index d576a1dd2819..22939e87912c 100644 --- a/tests/run-make-fulldeps/target-specs/foo.rs +++ b/tests/run-make-fulldeps/target-specs/foo.rs @@ -11,7 +11,7 @@ trait Sized {} auto trait Freeze {} #[lang = "start"] -fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8) -> isize { +fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize { 0 } diff --git a/tests/ui/lang-items/start_lang_item_args.argc.stderr b/tests/ui/lang-items/start_lang_item_args.argc.stderr new file mode 100644 index 000000000000..65c99a93c751 --- /dev/null +++ b/tests/ui/lang-items/start_lang_item_args.argc.stderr @@ -0,0 +1,8 @@ +error: parameter 2 of the `start` lang item is incorrect + --> $DIR/start_lang_item_args.rs:75:38 + | +LL | fn start(_main: fn() -> T, _argc: i8, _argv: *const *const u8, _sigpipe: u8) -> isize { + | ^^ help: change the type from `i8` to `isize` + +error: aborting due to previous error + diff --git a/tests/ui/lang-items/start_lang_item_args.argv.stderr b/tests/ui/lang-items/start_lang_item_args.argv.stderr new file mode 100644 index 000000000000..f0947a9b3e93 --- /dev/null +++ b/tests/ui/lang-items/start_lang_item_args.argv.stderr @@ -0,0 +1,8 @@ +error: parameter 3 of the `start` lang item is incorrect + --> $DIR/start_lang_item_args.rs:89:52 + | +LL | fn start(_main: fn() -> T, _argc: isize, _argv: u8, _sigpipe: u8) -> isize { + | ^^ help: change the type from `u8` to `*const *const u8` + +error: aborting due to previous error + diff --git a/tests/ui/lang-items/start_lang_item_args.argv_inner_ptr.stderr b/tests/ui/lang-items/start_lang_item_args.argv_inner_ptr.stderr new file mode 100644 index 000000000000..08efd5088f99 --- /dev/null +++ b/tests/ui/lang-items/start_lang_item_args.argv_inner_ptr.stderr @@ -0,0 +1,13 @@ +error: parameter 3 of the `start` lang item is incorrect + --> $DIR/start_lang_item_args.rs:82:52 + | +LL | fn start(_main: fn() -> T, _argc: isize, _argv: *const *const usize, _sigpipe: u8) -> isize { + | ^^^^^^^^^^^^^^^^^^^ + | +help: change the type from `*const *const usize` to `*const *const u8` + | +LL | fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize { + | ~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + diff --git a/tests/ui/lang-items/start_lang_item_args.main_args.stderr b/tests/ui/lang-items/start_lang_item_args.main_args.stderr new file mode 100644 index 000000000000..c20a744661d4 --- /dev/null +++ b/tests/ui/lang-items/start_lang_item_args.main_args.stderr @@ -0,0 +1,13 @@ +error: parameter 1 of the `start` lang item is incorrect + --> $DIR/start_lang_item_args.rs:61:20 + | +LL | fn start(_main: fn(i32) -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize { + | ^^^^^^^^^^^^ + | +help: change the type from `fn(i32) -> T` to `fn() -> T` + | +LL | fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize { + | ~~~~~~~~~ + +error: aborting due to previous error + diff --git a/tests/ui/lang-items/start_lang_item_args.main_ret.stderr b/tests/ui/lang-items/start_lang_item_args.main_ret.stderr new file mode 100644 index 000000000000..8f967252f49b --- /dev/null +++ b/tests/ui/lang-items/start_lang_item_args.main_ret.stderr @@ -0,0 +1,13 @@ +error: parameter 1 of the `start` lang item is incorrect + --> $DIR/start_lang_item_args.rs:68:20 + | +LL | fn start(_main: fn() -> u16, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize { + | ^^^^^^^^^^^ + | +help: change the type from `fn() -> u16` to `fn() -> T` + | +LL | fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize { + | ~~~~~~~~~ + +error: aborting due to previous error + diff --git a/tests/ui/lang-items/start_lang_item_args.main_ty.stderr b/tests/ui/lang-items/start_lang_item_args.main_ty.stderr new file mode 100644 index 000000000000..deb37b868ea8 --- /dev/null +++ b/tests/ui/lang-items/start_lang_item_args.main_ty.stderr @@ -0,0 +1,8 @@ +error: parameter 1 of the `start` lang item is incorrect + --> $DIR/start_lang_item_args.rs:54:20 + | +LL | fn start(_main: u64, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize { + | ^^^ help: change the type from `u64` to `fn() -> T` + +error: aborting due to previous error + diff --git a/tests/ui/lang-items/start_lang_item_args.missing_all_args.stderr b/tests/ui/lang-items/start_lang_item_args.missing_all_args.stderr new file mode 100644 index 000000000000..004c2a67f62f --- /dev/null +++ b/tests/ui/lang-items/start_lang_item_args.missing_all_args.stderr @@ -0,0 +1,11 @@ +error: incorrect number of parameters for the `start` lang item + --> $DIR/start_lang_item_args.rs:15:1 + | +LL | fn start() -> isize { + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the `start` lang item should have four parameters, but found 0 + = note: the `start` lang item should have the signature `fn(fn() -> T, isize, *const *const u8, u8) -> isize` + +error: aborting due to previous error + diff --git a/tests/ui/lang-items/start_lang_item_args.missing_ret.stderr b/tests/ui/lang-items/start_lang_item_args.missing_ret.stderr new file mode 100644 index 000000000000..1d8285b59000 --- /dev/null +++ b/tests/ui/lang-items/start_lang_item_args.missing_ret.stderr @@ -0,0 +1,8 @@ +error: the return type of the `start` lang item is incorrect + --> $DIR/start_lang_item_args.rs:29:84 + | +LL | fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) {} + | ^ help: change the type from `()` to `isize` + +error: aborting due to previous error + diff --git a/tests/ui/lang-items/start_lang_item_args.missing_sigpipe_arg.stderr b/tests/ui/lang-items/start_lang_item_args.missing_sigpipe_arg.stderr new file mode 100644 index 000000000000..e545a750f24a --- /dev/null +++ b/tests/ui/lang-items/start_lang_item_args.missing_sigpipe_arg.stderr @@ -0,0 +1,11 @@ +error: incorrect number of parameters for the `start` lang item + --> $DIR/start_lang_item_args.rs:22:1 + | +LL | fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8) -> isize { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the `start` lang item should have four parameters, but found 3 + = note: the `start` lang item should have the signature `fn(fn() -> T, isize, *const *const u8, u8) -> isize` + +error: aborting due to previous error + diff --git a/tests/ui/lang-items/start_lang_item_args.rs b/tests/ui/lang-items/start_lang_item_args.rs new file mode 100644 index 000000000000..0dbfba39cb60 --- /dev/null +++ b/tests/ui/lang-items/start_lang_item_args.rs @@ -0,0 +1,101 @@ +// check-fail +// revisions: missing_all_args missing_sigpipe_arg missing_ret start_ret too_many_args +// revisions: main_ty main_args main_ret argc argv_inner_ptr argv sigpipe + +#![feature(lang_items, no_core)] +#![no_core] + +#[lang = "copy"] +pub trait Copy {} +#[lang = "sized"] +pub trait Sized {} + +#[cfg(missing_all_args)] +#[lang = "start"] +fn start() -> isize { + //[missing_all_args]~^ ERROR incorrect number of parameters + 100 +} + +#[cfg(missing_sigpipe_arg)] +#[lang = "start"] +fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8) -> isize { + //[missing_sigpipe_arg]~^ ERROR incorrect number of parameters + 100 +} + +#[cfg(missing_ret)] +#[lang = "start"] +fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) {} +//[missing_ret]~^ ERROR the return type of the `start` lang item is incorrect + +#[cfg(start_ret)] +#[lang = "start"] +fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> u8 { + //[start_ret]~^ ERROR the return type of the `start` lang item is incorrect + 100 +} + +#[cfg(too_many_args)] +#[lang = "start"] +fn start( + //[too_many_args]~^ ERROR incorrect number of parameters + _main: fn() -> T, + _argc: isize, + _argv: *const *const u8, + _sigpipe: u8, + _extra_arg: (), +) -> isize { + 100 +} + +#[cfg(main_ty)] +#[lang = "start"] +fn start(_main: u64, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize { + //[main_ty]~^ ERROR parameter 1 of the `start` lang item is incorrect + 100 +} + +#[cfg(main_args)] +#[lang = "start"] +fn start(_main: fn(i32) -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize { + //[main_args]~^ ERROR parameter 1 of the `start` lang item is incorrect + 100 +} + +#[cfg(main_ret)] +#[lang = "start"] +fn start(_main: fn() -> u16, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize { + //[main_ret]~^ ERROR parameter 1 of the `start` lang item is incorrect + 100 +} + +#[cfg(argc)] +#[lang = "start"] +fn start(_main: fn() -> T, _argc: i8, _argv: *const *const u8, _sigpipe: u8) -> isize { + //[argc]~^ ERROR parameter 2 of the `start` lang item is incorrect + 100 +} + +#[cfg(argv_inner_ptr)] +#[lang = "start"] +fn start(_main: fn() -> T, _argc: isize, _argv: *const *const usize, _sigpipe: u8) -> isize { + //[argv_inner_ptr]~^ ERROR parameter 3 of the `start` lang item is incorrect + 100 +} + +#[cfg(argv)] +#[lang = "start"] +fn start(_main: fn() -> T, _argc: isize, _argv: u8, _sigpipe: u8) -> isize { + //[argv]~^ ERROR parameter 3 of the `start` lang item is incorrect + 100 +} + +#[cfg(sigpipe)] +#[lang = "start"] +fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: i64) -> isize { + //[sigpipe]~^ ERROR parameter 4 of the `start` lang item is incorrect + 100 +} + +fn main() {} diff --git a/tests/ui/lang-items/start_lang_item_args.sigpipe.stderr b/tests/ui/lang-items/start_lang_item_args.sigpipe.stderr new file mode 100644 index 000000000000..b20ae3128013 --- /dev/null +++ b/tests/ui/lang-items/start_lang_item_args.sigpipe.stderr @@ -0,0 +1,8 @@ +error: parameter 4 of the `start` lang item is incorrect + --> $DIR/start_lang_item_args.rs:96:80 + | +LL | fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: i64) -> isize { + | ^^^ help: change the type from `i64` to `u8` + +error: aborting due to previous error + diff --git a/tests/ui/lang-items/start_lang_item_args.start_ret.stderr b/tests/ui/lang-items/start_lang_item_args.start_ret.stderr new file mode 100644 index 000000000000..935d5f3c8b42 --- /dev/null +++ b/tests/ui/lang-items/start_lang_item_args.start_ret.stderr @@ -0,0 +1,8 @@ +error: the return type of the `start` lang item is incorrect + --> $DIR/start_lang_item_args.rs:34:87 + | +LL | fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> u8 { + | ^^ help: change the type from `u8` to `isize` + +error: aborting due to previous error + diff --git a/tests/ui/lang-items/start_lang_item_args.too_many_args.stderr b/tests/ui/lang-items/start_lang_item_args.too_many_args.stderr new file mode 100644 index 000000000000..30a7ed18a3d2 --- /dev/null +++ b/tests/ui/lang-items/start_lang_item_args.too_many_args.stderr @@ -0,0 +1,17 @@ +error: incorrect number of parameters for the `start` lang item + --> $DIR/start_lang_item_args.rs:41:1 + | +LL | / fn start( +LL | | +LL | | _main: fn() -> T, +LL | | _argc: isize, +... | +LL | | _extra_arg: (), +LL | | ) -> isize { + | |__________^ + | + = note: the `start` lang item should have four parameters, but found 5 + = note: the `start` lang item should have the signature `fn(fn() -> T, isize, *const *const u8, u8) -> isize` + +error: aborting due to previous error + From a3d6bc34684f67b9b5b2a419d57dc0afe5af4a67 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Sat, 7 Jan 2023 16:33:05 +0000 Subject: [PATCH 022/105] Emit a single error for contiguous sequences of Unicode homoglyphs --- compiler/rustc_parse/src/lexer/mod.rs | 28 +++++++++++++++--- .../rustc_parse/src/lexer/unicode_chars.rs | 10 +++++-- tests/rustdoc-ui/invalid-syntax.stderr | 2 -- tests/ui/parser/issues/issue-66473.stderr | Bin 5260 -> 1061 bytes tests/ui/parser/issues/issue-68629.stderr | Bin 1831 -> 1637 bytes tests/ui/parser/issues/issue-68730.stderr | Bin 1226 -> 1266 bytes tests/ui/parser/unicode-chars.rs | 4 +++ tests/ui/parser/unicode-chars.stderr | 14 ++++++++- 8 files changed, 49 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index f027843e6b43..8761c23625b2 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -79,7 +79,7 @@ impl<'a> StringReader<'a> { /// preceded by whitespace. fn next_token(&mut self) -> (Token, bool) { let mut preceded_by_whitespace = false; - + let mut swallow_next_invalid = 0; // Skip trivial (whitespace & comments) tokens loop { let token = self.cursor.advance_token(); @@ -232,19 +232,34 @@ impl<'a> StringReader<'a> { rustc_lexer::TokenKind::Percent => token::BinOp(token::Percent), rustc_lexer::TokenKind::Unknown | rustc_lexer::TokenKind::InvalidIdent => { - let c = self.str_from(start).chars().next().unwrap(); + // Don't emit diagnostics for sequences of the same invalid token + if swallow_next_invalid > 0 { + swallow_next_invalid -= 1; + continue; + } + let mut it = self.str_from_to_end(start).chars(); + let c = it.next().unwrap(); + let repeats = it.take_while(|c1| *c1 == c).count(); let mut err = - self.struct_err_span_char(start, self.pos, "unknown start of token", c); + self.struct_err_span_char(start, self.pos + Pos::from_usize(repeats * c.len_utf8()), "unknown start of token", c); // FIXME: the lexer could be used to turn the ASCII version of unicode // homoglyphs, instead of keeping a table in `check_for_substitution`into the // token. Ideally, this should be inside `rustc_lexer`. However, we should // first remove compound tokens like `<<` from `rustc_lexer`, and then add // fancier error recovery to it, as there will be less overall work to do this // way. - let token = unicode_chars::check_for_substitution(self, start, c, &mut err); + let token = unicode_chars::check_for_substitution(self, start, c, &mut err, repeats+1); if c == '\x00' { err.help("source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used"); } + if repeats > 0 { + if repeats == 1 { + err.note(format!("character appears once more")); + } else { + err.note(format!("character appears {repeats} more times")); + } + swallow_next_invalid = repeats; + } err.emit(); if let Some(token) = token { token @@ -486,6 +501,11 @@ impl<'a> StringReader<'a> { &self.src[self.src_index(start)..self.src_index(end)] } + /// Slice of the source text spanning from `start` until the end + fn str_from_to_end(&self, start: BytePos) -> &str { + &self.src[self.src_index(start)..] + } + fn report_raw_str_error(&self, start: BytePos, prefix_len: u32) -> ! { match rustc_lexer::validate_raw_str(self.str_from(start), prefix_len) { Err(RawStrError::InvalidStarter { bad_char }) => { diff --git a/compiler/rustc_parse/src/lexer/unicode_chars.rs b/compiler/rustc_parse/src/lexer/unicode_chars.rs index f1b50296e256..65479b341d7a 100644 --- a/compiler/rustc_parse/src/lexer/unicode_chars.rs +++ b/compiler/rustc_parse/src/lexer/unicode_chars.rs @@ -337,10 +337,11 @@ pub(super) fn check_for_substitution<'a>( pos: BytePos, ch: char, err: &mut Diagnostic, + count: usize, ) -> Option { let &(_u_char, u_name, ascii_char) = UNICODE_ARRAY.iter().find(|&&(c, _, _)| c == ch)?; - let span = Span::with_root_ctxt(pos, pos + Pos::from_usize(ch.len_utf8())); + let span = Span::with_root_ctxt(pos, pos + Pos::from_usize(ch.len_utf8() * count)); let Some((_ascii_char, ascii_name, token)) = ASCII_ARRAY.iter().find(|&&(c, _, _)| c == ascii_char) else { let msg = format!("substitution character not found for '{}'", ch); @@ -369,7 +370,12 @@ pub(super) fn check_for_substitution<'a>( "Unicode character '{}' ({}) looks like '{}' ({}), but it is not", ch, u_name, ascii_char, ascii_name ); - err.span_suggestion(span, &msg, ascii_char, Applicability::MaybeIncorrect); + err.span_suggestion( + span, + &msg, + ascii_char.to_string().repeat(count), + Applicability::MaybeIncorrect, + ); } token.clone() } diff --git a/tests/rustdoc-ui/invalid-syntax.stderr b/tests/rustdoc-ui/invalid-syntax.stderr index 597d19e748cb..6140a06c555f 100644 --- a/tests/rustdoc-ui/invalid-syntax.stderr +++ b/tests/rustdoc-ui/invalid-syntax.stderr @@ -77,8 +77,6 @@ LL | /// ``` | ^^^ | = note: error from rustc: unknown start of token: ` - = note: error from rustc: unknown start of token: ` - = note: error from rustc: unknown start of token: ` warning: could not parse code block as Rust code --> $DIR/invalid-syntax.rs:64:5 diff --git a/tests/ui/parser/issues/issue-66473.stderr b/tests/ui/parser/issues/issue-66473.stderr index 8a16d7f955129811997464d47c4e10238db77340..0e8b0a5da220569b607fe3512ae59ee94e3fcf1b 100644 GIT binary patch delta 122 zcmeCtT*|Q_no&zZLBUobFTW(!N+CHTu_!UQB(+E(v7jI|v8Y(V&|D!mzbI9qBr`X) wc=7~6m(AsZ;f!i{_2lOzr-F4&UL$-)*i50ID77pzzqD8(wWuh+sF;fj0L7&#-~a#s delta 252 zcmZ3=(WAK`nsKrtlLNDfmC3{ntD#I&1k((`G)FKk5KK!blf}f!&;W^Th{QI6vYAb+ z3@1-y)|hy`1!NOQ3(Qs!8)hwt4YL=-hFJ_^!)ykzk*qd?TCKc!C1W|rM^21plUtbP eOm=5JEn;M%P*9XwmYH8#tdLq%lwVZL#RUM5qEb2l diff --git a/tests/ui/parser/issues/issue-68629.stderr b/tests/ui/parser/issues/issue-68629.stderr index b2c7dddc8011c21e1f3d21185bc48a97dbadf79c..43a903e6c4698e59840cdf18f73ed830c8b50c32 100644 GIT binary patch delta 75 zcmZ3^_mpQtHSR}z f+nfDZjxh;aC=?W>mSyIb7AvF{73CKdb8!Ix $DIR/unicode-chars.rs:5:5 + | +LL |     let x = 0; + | ^^^^ + | + = note: character appears 3 more times +help: Unicode character ' ' (No-Break Space) looks like ' ' (Space), but it is not + | +LL | let x = 0; + | ++++ + +error: aborting due to 2 previous errors From 8917e9936282f855a08808ed8874c4117210da6e Mon Sep 17 00:00:00 2001 From: Ibraheem Ahmed Date: Wed, 11 Jan 2023 21:29:14 -0500 Subject: [PATCH 023/105] rework and document backoff behavior of `sync::mpsc` --- library/std/src/sync/mpmc/array.rs | 14 +++++++------- library/std/src/sync/mpmc/list.rs | 16 ++++++++-------- library/std/src/sync/mpmc/utils.rs | 29 ++++++++++++++--------------- library/std/src/sync/mpmc/zero.rs | 2 +- 4 files changed, 30 insertions(+), 31 deletions(-) diff --git a/library/std/src/sync/mpmc/array.rs b/library/std/src/sync/mpmc/array.rs index f71edc6c525a..c1e3e48b0446 100644 --- a/library/std/src/sync/mpmc/array.rs +++ b/library/std/src/sync/mpmc/array.rs @@ -168,7 +168,7 @@ impl Channel { return true; } Err(_) => { - backoff.spin(); + backoff.spin_light(); tail = self.tail.load(Ordering::Relaxed); } } @@ -182,11 +182,11 @@ impl Channel { return false; } - backoff.spin(); + backoff.spin_light(); tail = self.tail.load(Ordering::Relaxed); } else { // Snooze because we need to wait for the stamp to get updated. - backoff.snooze(); + backoff.spin_heavy(); tail = self.tail.load(Ordering::Relaxed); } } @@ -251,7 +251,7 @@ impl Channel { return true; } Err(_) => { - backoff.spin(); + backoff.spin_light(); head = self.head.load(Ordering::Relaxed); } } @@ -273,11 +273,11 @@ impl Channel { } } - backoff.spin(); + backoff.spin_light(); head = self.head.load(Ordering::Relaxed); } else { // Snooze because we need to wait for the stamp to get updated. - backoff.snooze(); + backoff.spin_heavy(); head = self.head.load(Ordering::Relaxed); } } @@ -330,7 +330,7 @@ impl Channel { if backoff.is_completed() { break; } else { - backoff.spin(); + backoff.spin_light(); } } diff --git a/library/std/src/sync/mpmc/list.rs b/library/std/src/sync/mpmc/list.rs index 2d5b2fb3b231..ec6c0726ac79 100644 --- a/library/std/src/sync/mpmc/list.rs +++ b/library/std/src/sync/mpmc/list.rs @@ -46,7 +46,7 @@ impl Slot { fn wait_write(&self) { let backoff = Backoff::new(); while self.state.load(Ordering::Acquire) & WRITE == 0 { - backoff.snooze(); + backoff.spin_heavy(); } } } @@ -82,7 +82,7 @@ impl Block { if !next.is_null() { return next; } - backoff.snooze(); + backoff.spin_heavy(); } } @@ -191,7 +191,7 @@ impl Channel { // If we reached the end of the block, wait until the next one is installed. if offset == BLOCK_CAP { - backoff.snooze(); + backoff.spin_heavy(); tail = self.tail.index.load(Ordering::Acquire); block = self.tail.block.load(Ordering::Acquire); continue; @@ -247,7 +247,7 @@ impl Channel { return true; }, Err(_) => { - backoff.spin(); + backoff.spin_light(); tail = self.tail.index.load(Ordering::Acquire); block = self.tail.block.load(Ordering::Acquire); } @@ -286,7 +286,7 @@ impl Channel { // If we reached the end of the block, wait until the next one is installed. if offset == BLOCK_CAP { - backoff.snooze(); + backoff.spin_heavy(); head = self.head.index.load(Ordering::Acquire); block = self.head.block.load(Ordering::Acquire); continue; @@ -320,7 +320,7 @@ impl Channel { // The block can be null here only if the first message is being sent into the channel. // In that case, just wait until it gets initialized. if block.is_null() { - backoff.snooze(); + backoff.spin_heavy(); head = self.head.index.load(Ordering::Acquire); block = self.head.block.load(Ordering::Acquire); continue; @@ -351,7 +351,7 @@ impl Channel { return true; }, Err(_) => { - backoff.spin(); + backoff.spin_light(); head = self.head.index.load(Ordering::Acquire); block = self.head.block.load(Ordering::Acquire); } @@ -542,7 +542,7 @@ impl Channel { // New updates to tail will be rejected by MARK_BIT and aborted unless it's // at boundary. We need to wait for the updates take affect otherwise there // can be memory leaks. - backoff.snooze(); + backoff.spin_heavy(); tail = self.tail.index.load(Ordering::Acquire); } diff --git a/library/std/src/sync/mpmc/utils.rs b/library/std/src/sync/mpmc/utils.rs index a9b365daeec4..cfe42750d523 100644 --- a/library/std/src/sync/mpmc/utils.rs +++ b/library/std/src/sync/mpmc/utils.rs @@ -91,9 +91,8 @@ impl DerefMut for CachePadded { } const SPIN_LIMIT: u32 = 6; -const YIELD_LIMIT: u32 = 10; -/// Performs exponential backoff in spin loops. +/// Performs quadratic backoff in spin loops. pub struct Backoff { step: Cell, } @@ -104,25 +103,27 @@ impl Backoff { Backoff { step: Cell::new(0) } } - /// Backs off in a lock-free loop. + /// Backs off using lightweight spinning. /// - /// This method should be used when we need to retry an operation because another thread made - /// progress. + /// This method should be used for: + /// - Retrying an operation because another thread made progress. i.e. on CAS failure. + /// - Waiting for an operation to complete by spinning optimistically for a few iterations + /// before falling back to parking the thread (see `Backoff::is_completed`). #[inline] - pub fn spin(&self) { + pub fn spin_light(&self) { let step = self.step.get().min(SPIN_LIMIT); for _ in 0..step.pow(2) { crate::hint::spin_loop(); } - if self.step.get() <= SPIN_LIMIT { - self.step.set(self.step.get() + 1); - } + self.step.set(self.step.get() + 1); } - /// Backs off in a blocking loop. + /// Backs off using heavyweight spinning. + /// + /// This method should be used in blocking loops where parking the thread is not an option. #[inline] - pub fn snooze(&self) { + pub fn spin_heavy(&self) { if self.step.get() <= SPIN_LIMIT { for _ in 0..self.step.get().pow(2) { crate::hint::spin_loop() @@ -131,12 +132,10 @@ impl Backoff { crate::thread::yield_now(); } - if self.step.get() <= YIELD_LIMIT { - self.step.set(self.step.get() + 1); - } + self.step.set(self.step.get() + 1); } - /// Returns `true` if quadratic backoff has completed and blocking the thread is advised. + /// Returns `true` if quadratic backoff has completed and parking the thread is advised. #[inline] pub fn is_completed(&self) -> bool { self.step.get() > SPIN_LIMIT diff --git a/library/std/src/sync/mpmc/zero.rs b/library/std/src/sync/mpmc/zero.rs index fccd6c29a7e4..33f768dcbe90 100644 --- a/library/std/src/sync/mpmc/zero.rs +++ b/library/std/src/sync/mpmc/zero.rs @@ -57,7 +57,7 @@ impl Packet { fn wait_ready(&self) { let backoff = Backoff::new(); while !self.ready.load(Ordering::Acquire) { - backoff.snooze(); + backoff.spin_heavy(); } } } From a513c84a5b54e83b158d0083385864c37cca358c Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Thu, 12 Jan 2023 07:27:36 +0000 Subject: [PATCH 024/105] Add `AtomicPtr::as_mut_ptr` --- library/core/src/sync/atomic.rs | 36 +++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index edc68d6fae51..8a7c3c3c3038 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -1786,6 +1786,42 @@ impl AtomicPtr { // SAFETY: data races are prevented by atomic intrinsics. unsafe { atomic_xor(self.p.get(), core::ptr::invalid_mut(val), order).cast() } } + + /// Returns a mutable pointer to the underlying pointer. + /// + /// Doing non-atomic reads and writes on the resulting integer can be a data race. + /// This method is mostly useful for FFI, where the function signature may use + /// `*mut *mut T` instead of `&AtomicPtr`. + /// + /// Returning an `*mut` pointer from a shared reference to this atomic is safe because the + /// atomic types work with interior mutability. All modifications of an atomic change the value + /// through a shared reference, and can do so safely as long as they use atomic operations. Any + /// use of the returned raw pointer requires an `unsafe` block and still has to uphold the same + /// restriction: operations on it must be atomic. + /// + /// # Examples + /// + /// ```ignore (extern-declaration) + /// #![feature(atomic_mut_ptr)] + //// use std::sync::atomic::AtomicPtr; + /// + /// extern "C" { + /// fn my_atomic_op(arg: *mut *mut u32); + /// } + /// + /// let mut value = 17; + /// let atomic = AtomicPtr::new(&mut value); + /// + /// // SAFETY: Safe as long as `my_atomic_op` is atomic. + /// unsafe { + /// my_atomic_op(atomic.as_mut_ptr()); + /// } + /// ``` + #[inline] + #[unstable(feature = "atomic_mut_ptr", reason = "recently added", issue = "66893")] + pub fn as_mut_ptr(&self) -> *mut *mut T { + self.p.get() + } } #[cfg(target_has_atomic_load_store = "8")] From f1a63bc2dd5a092ef5384c11f77c8d16d4b9fcc1 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Thu, 12 Jan 2023 07:27:51 +0000 Subject: [PATCH 025/105] Remove unused `mut` from a doctest --- library/core/src/sync/atomic.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 8a7c3c3c3038..0c1ebaf77f8d 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -2714,7 +2714,7 @@ macro_rules! atomic_int { #[doc = concat!(" fn my_atomic_op(arg: *mut ", stringify!($int_type), ");")] /// } /// - #[doc = concat!("let mut atomic = ", stringify!($atomic_type), "::new(1);")] + #[doc = concat!("let atomic = ", stringify!($atomic_type), "::new(1);")] /// // SAFETY: Safe as long as `my_atomic_op` is atomic. /// unsafe { From 22b4c688956de0925f7a10a79cb0e1ca35f55425 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Thu, 12 Jan 2023 07:28:43 +0000 Subject: [PATCH 026/105] Make `// SAFETY` comment part of the doctest, and not surrounding code --- library/core/src/sync/atomic.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 0c1ebaf77f8d..14367eb09bc7 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -2716,7 +2716,7 @@ macro_rules! atomic_int { /// #[doc = concat!("let atomic = ", stringify!($atomic_type), "::new(1);")] /// - // SAFETY: Safe as long as `my_atomic_op` is atomic. + /// // SAFETY: Safe as long as `my_atomic_op` is atomic. /// unsafe { /// my_atomic_op(atomic.as_mut_ptr()); /// } From 0482a48dab150882363f65a9689d45707a396fc4 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 12 Jan 2023 11:34:26 +0100 Subject: [PATCH 027/105] Remove dead code in rustdoc stripper --- src/librustdoc/passes/stripper.rs | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/src/librustdoc/passes/stripper.rs b/src/librustdoc/passes/stripper.rs index f8a0d77538d3..1938875dce7a 100644 --- a/src/librustdoc/passes/stripper.rs +++ b/src/librustdoc/passes/stripper.rs @@ -97,17 +97,7 @@ impl<'a, 'tcx> DocFolder for Stripper<'a, 'tcx> { } // handled in the `strip-priv-imports` pass - clean::ExternCrateItem { .. } => {} - clean::ImportItem(ref imp) => { - // Because json doesn't inline imports from private modules, we need to mark - // the imported item as retained so it's impls won't be stripped. - // - // FIXME: Is it necessary to check for json output here: See - // https://github.com/rust-lang/rust/pull/100325#discussion_r941495215 - if let Some(did) = imp.source.did && self.is_json_output { - self.retained.insert(did.into()); - } - } + clean::ExternCrateItem { .. } | clean::ImportItem(_) => {} clean::ImplItem(..) => {} From 7dd45bafb448ac7e24e751e51cdd2f65c9b7db3d Mon Sep 17 00:00:00 2001 From: Caio Date: Thu, 12 Jan 2023 08:41:21 -0300 Subject: [PATCH 028/105] [RFC 2397] Deny incorrect locations --- .../locales/en-US/passes.ftl | 3 ++ compiler/rustc_passes/src/check_attr.rs | 11 ++++ compiler/rustc_passes/src/errors.rs | 7 +++ .../incorrect-locations.rs | 45 +++++++++++++++++ .../incorrect-locations.stderr | 50 +++++++++++++++++++ .../unstable-feature.rs | 5 +- .../unstable-feature.stderr | 2 +- 7 files changed, 121 insertions(+), 2 deletions(-) create mode 100644 tests/ui/rfc-2397-do-not-recommend/incorrect-locations.rs create mode 100644 tests/ui/rfc-2397-do-not-recommend/incorrect-locations.stderr diff --git a/compiler/rustc_error_messages/locales/en-US/passes.ftl b/compiler/rustc_error_messages/locales/en-US/passes.ftl index 001e53d1d0e4..91857dd227dd 100644 --- a/compiler/rustc_error_messages/locales/en-US/passes.ftl +++ b/compiler/rustc_error_messages/locales/en-US/passes.ftl @@ -4,6 +4,9 @@ -passes_see_issue = see issue #{$issue} for more information +passes_incorrect_do_not_recommend_location = + `#[do_not_recommend]` can only be placed on trait implementations + passes_outer_crate_level_attr = crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index c59c06ac31ed..f9f9799d3e4f 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -82,6 +82,7 @@ impl CheckAttrVisitor<'_> { let attrs = self.tcx.hir().attrs(hir_id); for attr in attrs { let attr_is_valid = match attr.name_or_empty() { + sym::do_not_recommend => self.check_do_not_recommend(attr.span, target), sym::inline => self.check_inline(hir_id, attr, span, target), sym::no_coverage => self.check_no_coverage(hir_id, attr, span, target), sym::non_exhaustive => self.check_non_exhaustive(hir_id, attr, span, target), @@ -241,6 +242,16 @@ impl CheckAttrVisitor<'_> { ); } + /// Checks if `#[do_not_recommend]` is applied on a trait impl. + fn check_do_not_recommend(&self, attr_span: Span, target: Target) -> bool { + if let Target::Impl = target { + true + } else { + self.tcx.sess.emit_err(errors::IncorrectDoNotRecommendLocation { span: attr_span }); + false + } + } + /// Checks if an `#[inline]` is applied to a function or a closure. Returns `true` if valid. fn check_inline(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) -> bool { match target { diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index c6cd69add28a..9c6519ea4bb2 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -14,6 +14,13 @@ use rustc_span::{Span, Symbol, DUMMY_SP}; use crate::lang_items::Duplicate; +#[derive(Diagnostic)] +#[diag(passes_incorrect_do_not_recommend_location)] +pub struct IncorrectDoNotRecommendLocation { + #[primary_span] + pub span: Span, +} + #[derive(LintDiagnostic)] #[diag(passes_outer_crate_level_attr)] pub struct OuterCrateLevelAttr; diff --git a/tests/ui/rfc-2397-do-not-recommend/incorrect-locations.rs b/tests/ui/rfc-2397-do-not-recommend/incorrect-locations.rs new file mode 100644 index 000000000000..91863f5e4978 --- /dev/null +++ b/tests/ui/rfc-2397-do-not-recommend/incorrect-locations.rs @@ -0,0 +1,45 @@ +#![feature(do_not_recommend)] + +#[do_not_recommend] +//~^ `#[do_not_recommend]` can only be placed +const CONST: () = (); + +#[do_not_recommend] +//~^ `#[do_not_recommend]` can only be placed +static Static: () = (); + +#[do_not_recommend] +//~^ `#[do_not_recommend]` can only be placed +type Type = (); + +#[do_not_recommend] +//~^ `#[do_not_recommend]` can only be placed +enum Enum { +} + +#[do_not_recommend] +//~^ `#[do_not_recommend]` can only be placed +extern { +} + +#[do_not_recommend] +//~^ `#[do_not_recommend]` can only be placed +fn fun() { +} + +#[do_not_recommend] +//~^ `#[do_not_recommend]` can only be placed +struct Struct { +} + +#[do_not_recommend] +//~^ `#[do_not_recommend]` can only be placed +trait Trait { +} + +#[do_not_recommend] +impl Trait for i32 { +} + +fn main() { +} diff --git a/tests/ui/rfc-2397-do-not-recommend/incorrect-locations.stderr b/tests/ui/rfc-2397-do-not-recommend/incorrect-locations.stderr new file mode 100644 index 000000000000..01ebc23c86e1 --- /dev/null +++ b/tests/ui/rfc-2397-do-not-recommend/incorrect-locations.stderr @@ -0,0 +1,50 @@ +error: `#[do_not_recommend]` can only be placed on trait implementations + --> $DIR/incorrect-locations.rs:3:1 + | +LL | #[do_not_recommend] + | ^^^^^^^^^^^^^^^^^^^ + +error: `#[do_not_recommend]` can only be placed on trait implementations + --> $DIR/incorrect-locations.rs:7:1 + | +LL | #[do_not_recommend] + | ^^^^^^^^^^^^^^^^^^^ + +error: `#[do_not_recommend]` can only be placed on trait implementations + --> $DIR/incorrect-locations.rs:11:1 + | +LL | #[do_not_recommend] + | ^^^^^^^^^^^^^^^^^^^ + +error: `#[do_not_recommend]` can only be placed on trait implementations + --> $DIR/incorrect-locations.rs:15:1 + | +LL | #[do_not_recommend] + | ^^^^^^^^^^^^^^^^^^^ + +error: `#[do_not_recommend]` can only be placed on trait implementations + --> $DIR/incorrect-locations.rs:20:1 + | +LL | #[do_not_recommend] + | ^^^^^^^^^^^^^^^^^^^ + +error: `#[do_not_recommend]` can only be placed on trait implementations + --> $DIR/incorrect-locations.rs:25:1 + | +LL | #[do_not_recommend] + | ^^^^^^^^^^^^^^^^^^^ + +error: `#[do_not_recommend]` can only be placed on trait implementations + --> $DIR/incorrect-locations.rs:30:1 + | +LL | #[do_not_recommend] + | ^^^^^^^^^^^^^^^^^^^ + +error: `#[do_not_recommend]` can only be placed on trait implementations + --> $DIR/incorrect-locations.rs:35:1 + | +LL | #[do_not_recommend] + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 8 previous errors + diff --git a/tests/ui/rfc-2397-do-not-recommend/unstable-feature.rs b/tests/ui/rfc-2397-do-not-recommend/unstable-feature.rs index b816c4a19da1..f0c5c222e786 100644 --- a/tests/ui/rfc-2397-do-not-recommend/unstable-feature.rs +++ b/tests/ui/rfc-2397-do-not-recommend/unstable-feature.rs @@ -1,6 +1,9 @@ +trait Foo { +} + #[do_not_recommend] //~^ ERROR the `#[do_not_recommend]` attribute is an experimental feature -trait Foo { +impl Foo for i32 { } fn main() { diff --git a/tests/ui/rfc-2397-do-not-recommend/unstable-feature.stderr b/tests/ui/rfc-2397-do-not-recommend/unstable-feature.stderr index 425d7e4bca0b..1597e5be45f8 100644 --- a/tests/ui/rfc-2397-do-not-recommend/unstable-feature.stderr +++ b/tests/ui/rfc-2397-do-not-recommend/unstable-feature.stderr @@ -1,5 +1,5 @@ error[E0658]: the `#[do_not_recommend]` attribute is an experimental feature - --> $DIR/unstable-feature.rs:1:1 + --> $DIR/unstable-feature.rs:4:1 | LL | #[do_not_recommend] | ^^^^^^^^^^^^^^^^^^^ From c82545955ea526c0bb6878ee12fa9959e8de3b89 Mon Sep 17 00:00:00 2001 From: yukang Date: Sat, 7 Jan 2023 14:02:59 +0800 Subject: [PATCH 029/105] Provide help on closures capturing self causing borrow checker errors --- .../src/diagnostics/conflict_errors.rs | 150 +++++++++++++++++- .../src/diagnostics/mutability_errors.rs | 2 +- ...ssue-105761-suggest-self-for-closure.fixed | 28 ++++ .../issue-105761-suggest-self-for-closure.rs | 28 ++++ ...sue-105761-suggest-self-for-closure.stderr | 49 ++++++ 5 files changed, 252 insertions(+), 5 deletions(-) create mode 100644 tests/ui/suggestions/issue-105761-suggest-self-for-closure.fixed create mode 100644 tests/ui/suggestions/issue-105761-suggest-self-for-closure.rs create mode 100644 tests/ui/suggestions/issue-105761-suggest-self-for-closure.stderr diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 6658ee89ad6f..04bbceadd5a5 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -1,4 +1,6 @@ +use crate::diagnostics::mutability_errors::mut_borrow_of_mutable_ref; use either::Either; +use hir::Closure; use rustc_const_eval::util::CallKind; use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxHashSet; @@ -20,7 +22,7 @@ use rustc_middle::ty::{self, suggest_constraining_type_params, PredicateKind, Ty use rustc_mir_dataflow::move_paths::{InitKind, MoveOutIndex, MovePathIndex}; use rustc_span::def_id::LocalDefId; use rustc_span::hygiene::DesugaringKind; -use rustc_span::symbol::sym; +use rustc_span::symbol::{kw, sym}; use rustc_span::{BytePos, Span, Symbol}; use rustc_trait_selection::infer::InferCtxtExt; @@ -39,6 +41,8 @@ use super::{ DescribePlaceOpt, RegionName, RegionNameSource, UseSpans, }; +use rustc_hir::def::Res; + #[derive(Debug)] struct MoveSite { /// Index of the "move out" that we found. The `MoveData` can @@ -356,7 +360,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if let Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. - })) = hir.find(hir.local_def_id_to_hir_id(self.mir_def_id())) + })) = hir.find(self.mir_hir_id()) && let Some(hir::Node::Expr(expr)) = hir.find(body_id.hir_id) { let place = &self.move_data.move_paths[mpi].place; @@ -948,7 +952,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } (BorrowKind::Mut { .. }, BorrowKind::Shared) => { first_borrow_desc = "immutable "; - self.cannot_reborrow_already_borrowed( + let mut err = self.cannot_reborrow_already_borrowed( span, &desc_place, &msg_place, @@ -958,7 +962,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { "immutable", &msg_borrow, None, - ) + ); + self.suggest_binding_for_closure_capture_self( + &mut err, + issued_borrow.borrowed_place, + &issued_spans, + ); + err } (BorrowKind::Mut { .. }, BorrowKind::Mut { .. }) => { @@ -1240,6 +1250,138 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } } + fn suggest_binding_for_closure_capture_self( + &self, + err: &mut Diagnostic, + borrowed_place: Place<'tcx>, + issued_spans: &UseSpans<'tcx>, + ) { + let UseSpans::ClosureUse { capture_kind_span, .. } = issued_spans else { return }; + let hir = self.infcx.tcx.hir(); + + // check whether the borrowed place is capturing `self` by mut reference + let local = borrowed_place.local; + let Some(_) = self + .body + .local_decls + .get(local) + .map(|l| mut_borrow_of_mutable_ref(l, self.local_names[local])) else { return }; + + struct ExpressionFinder<'hir> { + capture_span: Span, + closure_change_spans: Vec, + closure_arg_span: Option, + in_closure: bool, + suggest_arg: String, + hir: rustc_middle::hir::map::Map<'hir>, + closure_local_id: Option, + closure_call_changes: Vec<(Span, String)>, + } + impl<'hir> Visitor<'hir> for ExpressionFinder<'hir> { + fn visit_expr(&mut self, e: &'hir hir::Expr<'hir>) { + if e.span.contains(self.capture_span) { + if let hir::ExprKind::Closure(&Closure { + movability: None, + body, + fn_arg_span, + fn_decl: hir::FnDecl{ inputs, .. }, + .. + }) = e.kind && + let Some(hir::Node::Expr(body )) = self.hir.find(body.hir_id) { + self.suggest_arg = "this: &Self".to_string(); + if inputs.len() > 0 { + self.suggest_arg.push_str(", "); + } + self.in_closure = true; + self.closure_arg_span = fn_arg_span; + self.visit_expr(body); + self.in_closure = false; + } + } + if let hir::Expr { kind: hir::ExprKind::Path(path), .. } = e { + if let hir::QPath::Resolved(_, hir::Path { segments: [seg], ..}) = path && + seg.ident.name == kw::SelfLower && self.in_closure { + self.closure_change_spans.push(e.span); + } + } + hir::intravisit::walk_expr(self, e); + } + + fn visit_local(&mut self, local: &'hir hir::Local<'hir>) { + if let hir::Pat { kind: hir::PatKind::Binding(_, hir_id, _ident, _), .. } = local.pat && + let Some(init) = local.init + { + if let hir::Expr { kind: hir::ExprKind::Closure(&Closure { + movability: None, + .. + }), .. } = init && + init.span.contains(self.capture_span) { + self.closure_local_id = Some(*hir_id); + } + } + hir::intravisit::walk_local(self, local); + } + + fn visit_stmt(&mut self, s: &'hir hir::Stmt<'hir>) { + if let hir::StmtKind::Semi(e) = s.kind && + let hir::ExprKind::Call(hir::Expr { kind: hir::ExprKind::Path(path), ..}, args) = e.kind && + let hir::QPath::Resolved(_, hir::Path { segments: [seg], ..}) = path && + let Res::Local(hir_id) = seg.res && + Some(hir_id) == self.closure_local_id { + let mut arg_str = "self".to_string(); + if args.len() > 0 { + arg_str.push_str(", "); + } + self.closure_call_changes.push((seg.ident.span, arg_str)); + } + hir::intravisit::walk_stmt(self, s); + } + } + + if let Some(hir::Node::ImplItem( + hir::ImplItem { kind: hir::ImplItemKind::Fn(_fn_sig, body_id), .. } + )) = hir.find(self.mir_hir_id()) && + let Some(hir::Node::Expr(expr)) = hir.find(body_id.hir_id) { + let mut finder = ExpressionFinder { + capture_span: *capture_kind_span, + closure_change_spans: vec![], + closure_arg_span: None, + in_closure: false, + suggest_arg: String::new(), + closure_local_id: None, + closure_call_changes: vec![], + hir, + }; + finder.visit_expr(expr); + + if finder.closure_change_spans.is_empty() || finder.closure_call_changes.is_empty() { + return; + } + + let mut sugg = vec![]; + let sm = self.infcx.tcx.sess.source_map(); + + if let Some(span) = finder.closure_arg_span { + sugg.push((sm.next_point(span.shrink_to_lo()).shrink_to_hi(), finder.suggest_arg)); + } + for span in finder.closure_change_spans { + sugg.push((span, "this".to_string())); + } + + for (span, suggest) in finder.closure_call_changes { + if let Ok(span) = sm.span_extend_while(span, |c| c != '(') { + sugg.push((sm.next_point(span).shrink_to_hi(), suggest)); + } + } + + err.multipart_suggestion_verbose( + "try explicitly pass `&Self` into the Closure as an argument", + sugg, + Applicability::MachineApplicable, + ); + } + } + /// Returns the description of the root place for a conflicting borrow and the full /// descriptions of the places that caused the conflict. /// diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index b9cfc7e69610..45b15c2c5bd7 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -1094,7 +1094,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } } -fn mut_borrow_of_mutable_ref(local_decl: &LocalDecl<'_>, local_name: Option) -> bool { +pub fn mut_borrow_of_mutable_ref(local_decl: &LocalDecl<'_>, local_name: Option) -> bool { debug!("local_info: {:?}, ty.kind(): {:?}", local_decl.local_info, local_decl.ty.kind()); match local_decl.local_info.as_deref() { diff --git a/tests/ui/suggestions/issue-105761-suggest-self-for-closure.fixed b/tests/ui/suggestions/issue-105761-suggest-self-for-closure.fixed new file mode 100644 index 000000000000..78e48364bba0 --- /dev/null +++ b/tests/ui/suggestions/issue-105761-suggest-self-for-closure.fixed @@ -0,0 +1,28 @@ +//run-rustfix +#![allow(unused)] + +struct S; +impl S { + fn foo(&mut self) { + let x = |this: &Self, v: i32| { + this.bar(); + this.hel(); + }; + self.qux(); //~ ERROR cannot borrow `*self` as mutable because it is also borrowed as immutable + x(self, 1); + x(self, 3); + } + fn bar(&self) {} + fn hel(&self) {} + fn qux(&mut self) {} + + fn hello(&mut self) { + let y = |this: &Self| { + this.bar(); + }; + self.qux(); //~ ERROR cannot borrow `*self` as mutable because it is also borrowed as immutable + y(self); + } +} + +fn main() {} diff --git a/tests/ui/suggestions/issue-105761-suggest-self-for-closure.rs b/tests/ui/suggestions/issue-105761-suggest-self-for-closure.rs new file mode 100644 index 000000000000..6d8a9ffc12d3 --- /dev/null +++ b/tests/ui/suggestions/issue-105761-suggest-self-for-closure.rs @@ -0,0 +1,28 @@ +//run-rustfix +#![allow(unused)] + +struct S; +impl S { + fn foo(&mut self) { + let x = |v: i32| { + self.bar(); + self.hel(); + }; + self.qux(); //~ ERROR cannot borrow `*self` as mutable because it is also borrowed as immutable + x(1); + x(3); + } + fn bar(&self) {} + fn hel(&self) {} + fn qux(&mut self) {} + + fn hello(&mut self) { + let y = || { + self.bar(); + }; + self.qux(); //~ ERROR cannot borrow `*self` as mutable because it is also borrowed as immutable + y(); + } +} + +fn main() {} diff --git a/tests/ui/suggestions/issue-105761-suggest-self-for-closure.stderr b/tests/ui/suggestions/issue-105761-suggest-self-for-closure.stderr new file mode 100644 index 000000000000..bc97d32ebb6e --- /dev/null +++ b/tests/ui/suggestions/issue-105761-suggest-self-for-closure.stderr @@ -0,0 +1,49 @@ +error[E0502]: cannot borrow `*self` as mutable because it is also borrowed as immutable + --> $DIR/issue-105761-suggest-self-for-closure.rs:11:9 + | +LL | let x = |v: i32| { + | -------- immutable borrow occurs here +LL | self.bar(); + | ---- first borrow occurs due to use of `self` in closure +... +LL | self.qux(); + | ^^^^^^^^^^ mutable borrow occurs here +LL | x(1); + | - immutable borrow later used here + | +help: try explicitly pass `&Self` into the Closure as an argument + | +LL ~ let x = |this: &Self, v: i32| { +LL ~ this.bar(); +LL ~ this.hel(); +LL | }; +LL | self.qux(); +LL ~ x(self, 1); +LL ~ x(self, 3); + | + +error[E0502]: cannot borrow `*self` as mutable because it is also borrowed as immutable + --> $DIR/issue-105761-suggest-self-for-closure.rs:23:9 + | +LL | let y = || { + | -- immutable borrow occurs here +LL | self.bar(); + | ---- first borrow occurs due to use of `self` in closure +LL | }; +LL | self.qux(); + | ^^^^^^^^^^ mutable borrow occurs here +LL | y(); + | - immutable borrow later used here + | +help: try explicitly pass `&Self` into the Closure as an argument + | +LL ~ let y = |this: &Self| { +LL ~ this.bar(); +LL | }; +LL | self.qux(); +LL ~ y(self); + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0502`. From eafbca916632ef8a92570fe3bf2c88ac6fbb3665 Mon Sep 17 00:00:00 2001 From: yukang Date: Sun, 8 Jan 2023 00:32:40 +0800 Subject: [PATCH 030/105] take care when there is no args in method call --- .../src/diagnostics/conflict_errors.rs | 26 +++++++++---------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 04bbceadd5a5..968c1f49b95c 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -1,6 +1,4 @@ -use crate::diagnostics::mutability_errors::mut_borrow_of_mutable_ref; use either::Either; -use hir::Closure; use rustc_const_eval::util::CallKind; use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxHashSet; @@ -8,6 +6,7 @@ use rustc_errors::{ struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan, }; use rustc_hir as hir; +use rustc_hir::def::Res; use rustc_hir::intravisit::{walk_block, walk_expr, Visitor}; use rustc_hir::{AsyncGeneratorKind, GeneratorKind, LangItem}; use rustc_infer::infer::TyCtxtInferExt; @@ -31,6 +30,7 @@ use crate::borrowck_errors; use crate::diagnostics::conflict_errors::StorageDeadOrDrop::LocalStorageDead; use crate::diagnostics::find_all_local_uses; +use crate::diagnostics::mutability_errors::mut_borrow_of_mutable_ref; use crate::{ borrow_set::BorrowData, diagnostics::Instance, prefixes::IsPrefixOf, InitializationRequiringAction, MirBorrowckCtxt, PrefixSet, WriteKind, @@ -41,8 +41,6 @@ use super::{ DescribePlaceOpt, RegionName, RegionNameSource, UseSpans, }; -use rustc_hir::def::Res; - #[derive(Debug)] struct MoveSite { /// Index of the "move out" that we found. The `MoveData` can @@ -1280,7 +1278,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { impl<'hir> Visitor<'hir> for ExpressionFinder<'hir> { fn visit_expr(&mut self, e: &'hir hir::Expr<'hir>) { if e.span.contains(self.capture_span) { - if let hir::ExprKind::Closure(&Closure { + if let hir::ExprKind::Closure(&hir::Closure { movability: None, body, fn_arg_span, @@ -1311,7 +1309,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if let hir::Pat { kind: hir::PatKind::Binding(_, hir_id, _ident, _), .. } = local.pat && let Some(init) = local.init { - if let hir::Expr { kind: hir::ExprKind::Closure(&Closure { + if let hir::Expr { kind: hir::ExprKind::Closure(&hir::Closure { movability: None, .. }), .. } = init && @@ -1328,11 +1326,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let hir::QPath::Resolved(_, hir::Path { segments: [seg], ..}) = path && let Res::Local(hir_id) = seg.res && Some(hir_id) == self.closure_local_id { - let mut arg_str = "self".to_string(); - if args.len() > 0 { - arg_str.push_str(", "); - } - self.closure_call_changes.push((seg.ident.span, arg_str)); + let (span, arg_str) = if args.len() > 0 { + (args[0].span.shrink_to_lo(), "self, ".to_string()) + } else { + let span = e.span.trim_start(seg.ident.span).unwrap_or(e.span); + (span, "(self)".to_string()) + }; + self.closure_call_changes.push((span, arg_str)); } hir::intravisit::walk_stmt(self, s); } @@ -1369,9 +1369,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } for (span, suggest) in finder.closure_call_changes { - if let Ok(span) = sm.span_extend_while(span, |c| c != '(') { - sugg.push((sm.next_point(span).shrink_to_hi(), suggest)); - } + sugg.push((span, suggest)); } err.multipart_suggestion_verbose( From 6885733c41844ac0ea24b965e91616a16a631697 Mon Sep 17 00:00:00 2001 From: Ulrich Weigand Date: Thu, 22 Dec 2022 16:33:12 +0100 Subject: [PATCH 031/105] Fix mir-opt tests for big-endian platforms The test cases src/test/mir-opt/building/custom/consts.rs and src/test/mir-opt/const_prop/mutable_variable_no_prop.rs are currently failing on big-endian platforms as the binary encoding of some constants is hard-coded in the MIR test files. Fix this by choosing constant values that have the same encoding on big- and little-endian platforms. The test case src/test/mir-opt/issues/issue_75439.rs is failing as well, but since the purpose of the test is to validate handling of big-endian integer encodings on a little-endian platform, it does not make much sense to run it on big-endian platforms in the first place - we can just ignore it there. Fixed part of https://github.com/rust-lang/rust/issues/105383. --- tests/mir-opt/building/custom/consts.rs | 4 ++-- tests/mir-opt/building/custom/consts.statics.built.after.mir | 4 ++-- .../const_prop/mutable_variable_no_prop.main.ConstProp.diff | 2 +- tests/mir-opt/const_prop/mutable_variable_no_prop.rs | 2 +- .../issues/issue_75439.foo.MatchBranchSimplification.diff | 4 ++-- tests/mir-opt/issues/issue_75439.rs | 1 + 6 files changed, 9 insertions(+), 8 deletions(-) diff --git a/tests/mir-opt/building/custom/consts.rs b/tests/mir-opt/building/custom/consts.rs index ff4fe1a93246..16d10eb5968c 100644 --- a/tests/mir-opt/building/custom/consts.rs +++ b/tests/mir-opt/building/custom/consts.rs @@ -18,8 +18,8 @@ fn consts() { }) } -static S: i32 = 5; -static mut T: i32 = 10; +static S: i32 = 0x05050505; +static mut T: i32 = 0x0a0a0a0a; // EMIT_MIR consts.statics.built.after.mir #[custom_mir(dialect = "built")] fn statics() { diff --git a/tests/mir-opt/building/custom/consts.statics.built.after.mir b/tests/mir-opt/building/custom/consts.statics.built.after.mir index ee768e263ecd..bfef976aa027 100644 --- a/tests/mir-opt/building/custom/consts.statics.built.after.mir +++ b/tests/mir-opt/building/custom/consts.statics.built.after.mir @@ -19,9 +19,9 @@ fn statics() -> () { } alloc2 (static: T, size: 4, align: 4) { - 0a 00 00 00 │ .... + 0a 0a 0a 0a │ .... } alloc1 (static: S, size: 4, align: 4) { - 05 00 00 00 │ .... + 05 05 05 05 │ .... } diff --git a/tests/mir-opt/const_prop/mutable_variable_no_prop.main.ConstProp.diff b/tests/mir-opt/const_prop/mutable_variable_no_prop.main.ConstProp.diff index b9d551c5e5fc..7fa29cccd50d 100644 --- a/tests/mir-opt/const_prop/mutable_variable_no_prop.main.ConstProp.diff +++ b/tests/mir-opt/const_prop/mutable_variable_no_prop.main.ConstProp.diff @@ -38,6 +38,6 @@ } alloc1 (static: STATIC, size: 4, align: 4) { - 2a 00 00 00 │ *... + 42 42 42 42 │ BBBB } diff --git a/tests/mir-opt/const_prop/mutable_variable_no_prop.rs b/tests/mir-opt/const_prop/mutable_variable_no_prop.rs index 8c23c5fcf0f8..b69ec931a631 100644 --- a/tests/mir-opt/const_prop/mutable_variable_no_prop.rs +++ b/tests/mir-opt/const_prop/mutable_variable_no_prop.rs @@ -1,7 +1,7 @@ // unit-test // compile-flags: -O -static mut STATIC: u32 = 42; +static mut STATIC: u32 = 0x42424242; // EMIT_MIR mutable_variable_no_prop.main.ConstProp.diff fn main() { diff --git a/tests/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff b/tests/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff index 1c69a6232d60..93804780371c 100644 --- a/tests/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff +++ b/tests/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff @@ -26,7 +26,7 @@ _3 = _1; // scope 2 at $DIR/issue_75439.rs:+2:47: +2:52 _2 = transmute::<[u8; 16], [u32; 4]>(move _3) -> bb1; // scope 2 at $DIR/issue_75439.rs:+2:37: +2:53 // mir::Constant - // + span: $DIR/issue_75439.rs:7:37: 7:46 + // + span: $DIR/issue_75439.rs:8:37: 8:46 // + literal: Const { ty: unsafe extern "rust-intrinsic" fn([u8; 16]) -> [u32; 4] {transmute::<[u8; 16], [u32; 4]>}, val: Value() } } @@ -49,7 +49,7 @@ _6 = _4; // scope 4 at $DIR/issue_75439.rs:+5:33: +5:35 _5 = transmute::(move _6) -> bb7; // scope 4 at $DIR/issue_75439.rs:+5:23: +5:36 // mir::Constant - // + span: $DIR/issue_75439.rs:10:23: 10:32 + // + span: $DIR/issue_75439.rs:11:23: 11:32 // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(u32) -> [u8; 4] {transmute::}, val: Value() } } diff --git a/tests/mir-opt/issues/issue_75439.rs b/tests/mir-opt/issues/issue_75439.rs index ae2e036312e8..4c749a150c09 100644 --- a/tests/mir-opt/issues/issue_75439.rs +++ b/tests/mir-opt/issues/issue_75439.rs @@ -1,4 +1,5 @@ // EMIT_MIR issue_75439.foo.MatchBranchSimplification.diff +// ignore-endian-big use std::mem::transmute; From 408ae0fcb9d154691470ce8fc644394c20a97405 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 5 Dec 2022 16:19:14 +0000 Subject: [PATCH 032/105] Feed `resolutions` query instead of it being a thin wrapper around an untracked field --- compiler/rustc_interface/src/passes.rs | 6 +++--- compiler/rustc_middle/src/arena.rs | 1 + compiler/rustc_middle/src/query/mod.rs | 2 +- compiler/rustc_middle/src/ty/context.rs | 6 +----- 4 files changed, 6 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 86d56385bc96..e8656e0dbc2a 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -817,7 +817,6 @@ pub fn create_global_ctxt<'tcx>( lint_store, arena, hir_arena, - untracked_resolutions, untracked, krate, dep_graph, @@ -832,8 +831,9 @@ pub fn create_global_ctxt<'tcx>( let mut qcx = QueryContext { gcx }; qcx.enter(|tcx| { - tcx.feed_unit_query() - .resolver_for_lowering(tcx.arena.alloc(Steal::new(untracked_resolver_for_lowering))) + let feed = tcx.feed_unit_query(); + feed.resolver_for_lowering(tcx.arena.alloc(Steal::new(untracked_resolver_for_lowering))); + feed.resolutions(tcx.arena.alloc(untracked_resolutions)); }); qcx } diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index 75282f958b53..ca058cc3c6d8 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -31,6 +31,7 @@ macro_rules! arena_types { [decode] borrowck_result: rustc_middle::mir::BorrowCheckResult<'tcx>, [] resolver: rustc_data_structures::steal::Steal, + [] resolutions: rustc_middle::ty::ResolverGlobalCtxt, [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 076ce1bdb348..4315247eace2 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -27,7 +27,7 @@ rustc_queries! { } query resolutions(_: ()) -> &'tcx ty::ResolverGlobalCtxt { - eval_always + feedable no_hash desc { "getting the resolver outputs" } } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 5de414077a2b..276aadcb66be 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -428,8 +428,7 @@ pub struct GlobalCtxt<'tcx> { pub consts: CommonConsts<'tcx>, untracked: Untracked, - /// Output of the resolver. - pub(crate) untracked_resolutions: ty::ResolverGlobalCtxt, + /// 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>, @@ -592,7 +591,6 @@ impl<'tcx> TyCtxt<'tcx> { lint_store: Lrc, arena: &'tcx WorkerLocal>, hir_arena: &'tcx WorkerLocal>, - untracked_resolutions: ty::ResolverGlobalCtxt, untracked: Untracked, krate: Lrc, dep_graph: DepGraph, @@ -622,7 +620,6 @@ impl<'tcx> TyCtxt<'tcx> { lifetimes: common_lifetimes, consts: common_consts, untracked, - untracked_resolutions, untracked_crate: Steal::new(krate), on_disk_cache, queries, @@ -2407,7 +2404,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.module_reexports = |tcx, id| tcx.resolutions(()).reexport_map.get(&id).map(|v| &v[..]); providers.crate_name = |tcx, id| { From 194b4a2adbda6809d9fd878bfbb4998f0a0e90bb Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 5 Dec 2022 16:37:44 +0000 Subject: [PATCH 033/105] Feed `crate_name` query --- compiler/rustc_interface/src/passes.rs | 3 ++- compiler/rustc_middle/src/query/mod.rs | 2 +- compiler/rustc_middle/src/ty/context.rs | 15 ++++----------- 3 files changed, 7 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index e8656e0dbc2a..82327af65e27 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -823,7 +823,6 @@ pub fn create_global_ctxt<'tcx>( queries.on_disk_cache.as_ref().map(OnDiskCache::as_dyn), queries.as_dyn(), rustc_query_impl::query_callbacks(arena), - crate_name, outputs, ) }) @@ -834,6 +833,8 @@ pub fn create_global_ctxt<'tcx>( let feed = tcx.feed_unit_query(); feed.resolver_for_lowering(tcx.arena.alloc(Steal::new(untracked_resolver_for_lowering))); feed.resolutions(tcx.arena.alloc(untracked_resolutions)); + let feed = tcx.feed_local_crate(); + feed.crate_name(crate_name); }); qcx } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 4315247eace2..0b551b5a4828 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1673,7 +1673,7 @@ rustc_queries! { /// Gets the name of the crate. query crate_name(_: CrateNum) -> Symbol { - eval_always + feedable desc { "fetching what a crate is named" } separate_provide_extern } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 276aadcb66be..dbf8f4cbf3b4 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -363,6 +363,9 @@ impl<'tcx> TyCtxt<'tcx> { pub fn feed_unit_query(self) -> TyCtxtFeed<'tcx, ()> { TyCtxtFeed { tcx: self, key: () } } + pub fn feed_local_crate(self) -> TyCtxtFeed<'tcx, CrateNum> { + TyCtxtFeed { tcx: self, key: LOCAL_CRATE } + } } impl<'tcx, KEY: Copy> TyCtxtFeed<'tcx, KEY> { @@ -456,10 +459,6 @@ pub struct GlobalCtxt<'tcx> { /// Merge this with `selection_cache`? pub evaluation_cache: traits::EvaluationCache<'tcx>, - /// The definite name of the current crate after taking into account - /// attributes, commandline parameters, etc. - crate_name: Symbol, - /// Data layout specification for the current target. pub data_layout: TargetDataLayout, @@ -597,7 +596,6 @@ 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: Symbol, output_filenames: OutputFilenames, ) -> GlobalCtxt<'tcx> { let data_layout = s.target.parse_data_layout().unwrap_or_else(|err| { @@ -629,7 +627,6 @@ impl<'tcx> TyCtxt<'tcx> { pred_rcache: Default::default(), selection_cache: Default::default(), evaluation_cache: Default::default(), - crate_name, data_layout, alloc_map: Lock::new(interpret::AllocMap::new()), output_filenames: Arc::new(output_filenames), @@ -807,7 +804,7 @@ impl<'tcx> TyCtxt<'tcx> { // statements within the query system and we'd run into endless // recursion otherwise. let (crate_name, stable_crate_id) = if def_id.is_local() { - (self.crate_name, self.sess.local_stable_crate_id()) + (self.crate_name(LOCAL_CRATE), self.sess.local_stable_crate_id()) } else { let cstore = &*self.untracked.cstore; (cstore.crate_name(def_id.krate), cstore.stable_crate_id(def_id.krate)) @@ -2406,10 +2403,6 @@ fn ptr_eq(t: *const T, u: *const U) -> bool { pub fn provide(providers: &mut ty::query::Providers) { providers.module_reexports = |tcx, id| tcx.resolutions(()).reexport_map.get(&id).map(|v| &v[..]); - providers.crate_name = |tcx, id| { - assert_eq!(id, LOCAL_CRATE); - tcx.crate_name - }; providers.maybe_unused_trait_imports = |tcx, ()| &tcx.resolutions(()).maybe_unused_trait_imports; providers.maybe_unused_extern_crates = From 33b6a7790eb6de10f0d240ec92008e7faa1da44c Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 5 Dec 2022 16:43:06 +0000 Subject: [PATCH 034/105] Remove `untracked_crate` field and instead pass it along with the resolver. --- compiler/rustc_ast_lowering/src/lib.rs | 3 +-- compiler/rustc_interface/src/passes.rs | 5 +++-- compiler/rustc_middle/src/arena.rs | 5 ++++- compiler/rustc_middle/src/query/mod.rs | 2 +- compiler/rustc_middle/src/ty/context.rs | 6 ------ 5 files changed, 9 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 2e135aafb1e0..41d4a5679f1a 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -416,8 +416,7 @@ fn compute_hir_hash( pub fn lower_to_hir(tcx: TyCtxt<'_>, (): ()) -> hir::Crate<'_> { let sess = tcx.sess; - let krate = tcx.untracked_crate.steal(); - let mut resolver = tcx.resolver_for_lowering(()).steal(); + let (mut resolver, krate) = tcx.resolver_for_lowering(()).steal(); let ast_index = index_crate(&resolver.node_id_to_def_id, &krate); let mut owners = IndexVec::from_fn_n( diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 82327af65e27..62441646b757 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -818,7 +818,6 @@ pub fn create_global_ctxt<'tcx>( arena, hir_arena, untracked, - krate, dep_graph, queries.on_disk_cache.as_ref().map(OnDiskCache::as_dyn), queries.as_dyn(), @@ -831,7 +830,9 @@ pub fn create_global_ctxt<'tcx>( let mut qcx = QueryContext { gcx }; qcx.enter(|tcx| { let feed = tcx.feed_unit_query(); - feed.resolver_for_lowering(tcx.arena.alloc(Steal::new(untracked_resolver_for_lowering))); + feed.resolver_for_lowering( + tcx.arena.alloc(Steal::new((untracked_resolver_for_lowering, krate))), + ); feed.resolutions(tcx.arena.alloc(untracked_resolutions)); let feed = tcx.feed_local_crate(); feed.crate_name(crate_name); diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index ca058cc3c6d8..9ab2d4c2106a 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -30,7 +30,10 @@ 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, + [] resolver: rustc_data_structures::steal::Steal<( + rustc_middle::ty::ResolverAstLowering, + rustc_data_structures::sync::Lrc, + )>, [] resolutions: rustc_middle::ty::ResolverGlobalCtxt, [decode] unsafety_check_result: rustc_middle::mir::UnsafetyCheckResult, [decode] code_region: rustc_middle::mir::coverage::CodeRegion, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 0b551b5a4828..88048c9775cb 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -32,7 +32,7 @@ rustc_queries! { desc { "getting the resolver outputs" } } - query resolver_for_lowering(_: ()) -> &'tcx Steal { + query resolver_for_lowering(_: ()) -> &'tcx Steal<(ty::ResolverAstLowering, Lrc)> { 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 dbf8f4cbf3b4..60c7d9ad3d0c 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -432,10 +432,6 @@ pub struct GlobalCtxt<'tcx> { untracked: Untracked, - /// 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>, - /// This provides access to the incremental compilation on-disk cache for query results. /// Do not access this directly. It is only meant to be used by /// `DepGraph::try_mark_green()` and the query infrastructure. @@ -591,7 +587,6 @@ impl<'tcx> TyCtxt<'tcx> { arena: &'tcx WorkerLocal>, hir_arena: &'tcx WorkerLocal>, untracked: Untracked, - krate: Lrc, dep_graph: DepGraph, on_disk_cache: Option<&'tcx dyn OnDiskCache<'tcx>>, queries: &'tcx dyn query::QueryEngine<'tcx>, @@ -618,7 +613,6 @@ impl<'tcx> TyCtxt<'tcx> { lifetimes: common_lifetimes, consts: common_consts, untracked, - untracked_crate: Steal::new(krate), on_disk_cache, queries, query_caches: query::QueryCaches::default(), From fbe2d5aad2912e718541443357784cea4b65a0b8 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 5 Dec 2022 17:00:26 +0000 Subject: [PATCH 035/105] Remove `output_filenames` field from TyCtxt and feed the query instead --- compiler/rustc_interface/src/passes.rs | 2 +- compiler/rustc_middle/src/arena.rs | 1 + compiler/rustc_middle/src/query/mod.rs | 2 +- compiler/rustc_middle/src/ty/context.rs | 8 +------- 4 files changed, 4 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 62441646b757..8d9e1ee7c2c4 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -822,7 +822,6 @@ pub fn create_global_ctxt<'tcx>( queries.on_disk_cache.as_ref().map(OnDiskCache::as_dyn), queries.as_dyn(), rustc_query_impl::query_callbacks(arena), - outputs, ) }) }); @@ -834,6 +833,7 @@ pub fn create_global_ctxt<'tcx>( tcx.arena.alloc(Steal::new((untracked_resolver_for_lowering, krate))), ); feed.resolutions(tcx.arena.alloc(untracked_resolutions)); + feed.output_filenames(tcx.arena.alloc(std::sync::Arc::new(outputs))); let feed = tcx.feed_local_crate(); feed.crate_name(crate_name); }); diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index 9ab2d4c2106a..f816d614500a 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -34,6 +34,7 @@ macro_rules! arena_types { rustc_middle::ty::ResolverAstLowering, rustc_data_structures::sync::Lrc, )>, + [] output_filenames: std::sync::Arc, [] resolutions: rustc_middle::ty::ResolverGlobalCtxt, [decode] unsafety_check_result: rustc_middle::mir::UnsafetyCheckResult, [decode] code_region: rustc_middle::mir::coverage::CodeRegion, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 88048c9775cb..6efdbfff19de 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1857,7 +1857,7 @@ rustc_queries! { /// This query returns an `&Arc` because codegen backends need the value even after the `TyCtxt` /// has been destroyed. query output_filenames(_: ()) -> &'tcx Arc { - eval_always + feedable desc { "getting output filenames" } } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 60c7d9ad3d0c..74537ea6a183 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -51,7 +51,7 @@ use rustc_macros::HashStable; use rustc_query_system::dep_graph::DepNodeIndex; use rustc_query_system::ich::StableHashingContext; use rustc_serialize::opaque::{FileEncodeResult, FileEncoder}; -use rustc_session::config::{CrateType, OutputFilenames}; +use rustc_session::config::CrateType; use rustc_session::cstore::{CrateStoreDyn, Untracked}; use rustc_session::lint::Lint; use rustc_session::Limit; @@ -74,7 +74,6 @@ use std::hash::{Hash, Hasher}; use std::iter; use std::mem; use std::ops::{Bound, Deref}; -use std::sync::Arc; pub trait OnDiskCache<'tcx>: rustc_data_structures::sync::Sync { /// Creates a new `OnDiskCache` instance from the serialized data in `data`. @@ -460,8 +459,6 @@ pub struct GlobalCtxt<'tcx> { /// Stores memory for globals (statics/consts). pub(crate) alloc_map: Lock>, - - output_filenames: Arc, } impl<'tcx> TyCtxt<'tcx> { @@ -591,7 +588,6 @@ impl<'tcx> TyCtxt<'tcx> { on_disk_cache: Option<&'tcx dyn OnDiskCache<'tcx>>, queries: &'tcx dyn query::QueryEngine<'tcx>, query_kinds: &'tcx [DepKindStruct<'tcx>], - output_filenames: OutputFilenames, ) -> GlobalCtxt<'tcx> { let data_layout = s.target.parse_data_layout().unwrap_or_else(|err| { s.emit_fatal(err); @@ -623,7 +619,6 @@ impl<'tcx> TyCtxt<'tcx> { evaluation_cache: Default::default(), data_layout, alloc_map: Lock::new(interpret::AllocMap::new()), - output_filenames: Arc::new(output_filenames), } } @@ -2407,7 +2402,6 @@ pub fn provide(providers: &mut ty::query::Providers) { providers.extern_mod_stmt_cnum = |tcx, id| tcx.resolutions(()).extern_crate_map.get(&id).cloned(); - providers.output_filenames = |tcx, ()| &tcx.output_filenames; providers.features_query = |tcx, ()| tcx.sess.features_untracked(); providers.is_panic_runtime = |tcx, cnum| { assert_eq!(cnum, LOCAL_CRATE); From d36db0d2a0c4fa0adaf49b2e795670bfc235d390 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 5 Dec 2022 17:52:17 +0000 Subject: [PATCH 036/105] Feed the `features_query` instead of grabbing it from the session lazily --- compiler/rustc_interface/src/passes.rs | 1 + compiler/rustc_lint/src/expect.rs | 2 +- compiler/rustc_middle/src/query/mod.rs | 2 +- compiler/rustc_middle/src/ty/context.rs | 1 - src/librustdoc/doctest.rs | 2 +- src/tools/clippy/clippy_lints/src/attrs.rs | 2 +- 6 files changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 8d9e1ee7c2c4..2a6852d44eba 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -834,6 +834,7 @@ pub fn create_global_ctxt<'tcx>( ); feed.resolutions(tcx.arena.alloc(untracked_resolutions)); feed.output_filenames(tcx.arena.alloc(std::sync::Arc::new(outputs))); + feed.features_query(sess.features_untracked()); let feed = tcx.feed_local_crate(); feed.crate_name(crate_name); }); diff --git a/compiler/rustc_lint/src/expect.rs b/compiler/rustc_lint/src/expect.rs index cf8f31bcbd06..bf00ade5f0bd 100644 --- a/compiler/rustc_lint/src/expect.rs +++ b/compiler/rustc_lint/src/expect.rs @@ -12,7 +12,7 @@ pub(crate) fn provide(providers: &mut Providers) { } fn check_expectations(tcx: TyCtxt<'_>, tool_filter: Option) { - if !tcx.sess.features_untracked().enabled(sym::lint_reasons) { + if !tcx.features().enabled(sym::lint_reasons) { return; } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 6efdbfff19de..866559157369 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -2041,7 +2041,7 @@ rustc_queries! { } query features_query(_: ()) -> &'tcx rustc_feature::Features { - eval_always + feedable desc { "looking up enabled feature gates" } } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 74537ea6a183..63f31e5a11f3 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -2402,7 +2402,6 @@ pub fn provide(providers: &mut ty::query::Providers) { providers.extern_mod_stmt_cnum = |tcx, id| tcx.resolutions(()).extern_crate_map.get(&id).cloned(); - providers.features_query = |tcx, ()| tcx.sess.features_untracked(); providers.is_panic_runtime = |tcx, cnum| { assert_eq!(cnum, LOCAL_CRATE); tcx.sess.contains_name(tcx.hir().krate_attrs(), sym::panic_runtime) diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 5f8c777f32a5..d1b6d470e86c 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -1221,7 +1221,7 @@ impl<'a, 'hir, 'tcx> HirCollector<'a, 'hir, 'tcx> { ) { let ast_attrs = self.tcx.hir().attrs(hir_id); if let Some(ref cfg) = ast_attrs.cfg(self.tcx, &FxHashSet::default()) { - if !cfg.matches(&self.sess.parse_sess, Some(self.sess.features_untracked())) { + if !cfg.matches(&self.sess.parse_sess, Some(self.tcx.features())) { return; } } diff --git a/src/tools/clippy/clippy_lints/src/attrs.rs b/src/tools/clippy/clippy_lints/src/attrs.rs index 0710ac0bb0a7..751c262673b1 100644 --- a/src/tools/clippy/clippy_lints/src/attrs.rs +++ b/src/tools/clippy/clippy_lints/src/attrs.rs @@ -472,7 +472,7 @@ fn check_clippy_lint_names(cx: &LateContext<'_>, name: Symbol, items: &[NestedMe fn check_lint_reason(cx: &LateContext<'_>, name: Symbol, items: &[NestedMetaItem], attr: &'_ Attribute) { // Check for the feature - if !cx.tcx.sess.features_untracked().lint_reasons { + if !cx.tcx.features().lint_reasons { return; } From d76e168f01e5ed6fc4bbdc127dacb121b51de098 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 12 Jan 2023 18:51:09 +0000 Subject: [PATCH 037/105] Point at HIR types when impl trait ref doesn't normalize --- .../rustc_hir_analysis/src/check/wfcheck.rs | 6 ++- .../rustc_hir_analysis/src/hir_wf_check.rs | 46 ++++++++++++------- .../min_specialization/issue-79224.stderr | 4 +- tests/ui/traits/issue-91594.stderr | 4 +- 4 files changed, 38 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index d1f4dbc8d845..ca45e16d9d9f 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1254,7 +1254,11 @@ fn check_impl<'tcx>( // therefore don't need to be WF (the trait's `Self: Trait` predicate // won't hold). let trait_ref = tcx.impl_trait_ref(item.owner_id).unwrap(); - let trait_ref = wfcx.normalize(ast_trait_ref.path.span, None, trait_ref); + let trait_ref = wfcx.normalize( + ast_trait_ref.path.span, + Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)), + trait_ref, + ); let trait_pred = ty::TraitPredicate { trait_ref, constness: match constness { diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs index 4f9d5826583c..2dbfc1bc9a22 100644 --- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs @@ -114,34 +114,46 @@ fn diagnostic_hir_wf_check<'tcx>( // Get the starting `hir::Ty` using our `WellFormedLoc`. // We will walk 'into' this type to try to find // a more precise span for our predicate. - let ty = match loc { + let tys = match loc { WellFormedLoc::Ty(_) => match hir.get(hir_id) { hir::Node::ImplItem(item) => match item.kind { - hir::ImplItemKind::Type(ty) => Some(ty), - hir::ImplItemKind::Const(ty, _) => Some(ty), + hir::ImplItemKind::Type(ty) => vec![ty], + hir::ImplItemKind::Const(ty, _) => vec![ty], ref item => bug!("Unexpected ImplItem {:?}", item), }, hir::Node::TraitItem(item) => match item.kind { - hir::TraitItemKind::Type(_, ty) => ty, - hir::TraitItemKind::Const(ty, _) => Some(ty), + hir::TraitItemKind::Type(_, ty) => ty.into_iter().collect(), + hir::TraitItemKind::Const(ty, _) => vec![ty], ref item => bug!("Unexpected TraitItem {:?}", item), }, hir::Node::Item(item) => match item.kind { - hir::ItemKind::Static(ty, _, _) | hir::ItemKind::Const(ty, _) => Some(ty), - hir::ItemKind::Impl(ref impl_) => { - assert!(impl_.of_trait.is_none(), "Unexpected trait impl: {:?}", impl_); - Some(impl_.self_ty) - } + hir::ItemKind::Static(ty, _, _) | hir::ItemKind::Const(ty, _) => vec![ty], + hir::ItemKind::Impl(ref impl_) => match &impl_.of_trait { + Some(t) => t + .path + .segments + .last() + .iter() + .flat_map(|seg| seg.args().args) + .filter_map(|arg| { + if let hir::GenericArg::Type(ty) = arg { Some(*ty) } else { None } + }) + .chain([impl_.self_ty]) + .collect(), + None => { + vec![impl_.self_ty] + } + }, ref item => bug!("Unexpected item {:?}", item), }, - hir::Node::Field(field) => Some(field.ty), + hir::Node::Field(field) => vec![field.ty], hir::Node::ForeignItem(ForeignItem { kind: ForeignItemKind::Static(ty, _), .. - }) => Some(*ty), + }) => vec![*ty], hir::Node::GenericParam(hir::GenericParam { kind: hir::GenericParamKind::Type { default: Some(ty), .. }, .. - }) => Some(*ty), + }) => vec![*ty], ref node => bug!("Unexpected node {:?}", node), }, WellFormedLoc::Param { function: _, param_idx } => { @@ -149,16 +161,16 @@ fn diagnostic_hir_wf_check<'tcx>( // Get return type if param_idx as usize == fn_decl.inputs.len() { match fn_decl.output { - hir::FnRetTy::Return(ty) => Some(ty), + hir::FnRetTy::Return(ty) => vec![ty], // The unit type `()` is always well-formed - hir::FnRetTy::DefaultReturn(_span) => None, + hir::FnRetTy::DefaultReturn(_span) => vec![], } } else { - Some(&fn_decl.inputs[param_idx as usize]) + vec![&fn_decl.inputs[param_idx as usize]] } } }; - if let Some(ty) = ty { + for ty in tys { visitor.visit_ty(ty); } visitor.cause diff --git a/tests/ui/specialization/min_specialization/issue-79224.stderr b/tests/ui/specialization/min_specialization/issue-79224.stderr index be6f04ae62a0..505baa23ca33 100644 --- a/tests/ui/specialization/min_specialization/issue-79224.stderr +++ b/tests/ui/specialization/min_specialization/issue-79224.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `B: Clone` is not satisfied - --> $DIR/issue-79224.rs:18:17 + --> $DIR/issue-79224.rs:18:29 | LL | impl Display for Cow<'_, B> { - | ^^^^^^^ the trait `Clone` is not implemented for `B` + | ^^^^^^^^^^ the trait `Clone` is not implemented for `B` | = note: required for `B` to implement `ToOwned` help: consider further restricting this bound diff --git a/tests/ui/traits/issue-91594.stderr b/tests/ui/traits/issue-91594.stderr index 6b314fa586d3..85d903fadd12 100644 --- a/tests/ui/traits/issue-91594.stderr +++ b/tests/ui/traits/issue-91594.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `Foo: HasComponent<()>` is not satisfied - --> $DIR/issue-91594.rs:10:6 + --> $DIR/issue-91594.rs:10:19 | LL | impl HasComponent<>::Interface> for Foo {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HasComponent<()>` is not implemented for `Foo` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HasComponent<()>` is not implemented for `Foo` | = help: the trait `HasComponent<>::Interface>` is implemented for `Foo` note: required for `Foo` to implement `Component` From 2aabb0fd5da283129205acb9c3e4d70a01238a93 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 12 Jan 2023 20:15:00 +0000 Subject: [PATCH 038/105] Point at impl self type for impl wf obligations --- .../rustc_hir_analysis/src/check/wfcheck.rs | 2 +- .../hr-associated-type-bound-param-6.stderr | 4 +-- .../hr-associated-type-projection-1.stderr | 4 +-- ...builtin-superkinds-double-superkind.stderr | 8 ++--- .../builtin-superkinds-in-metadata.stderr | 4 +-- .../builtin-superkinds-self-type.stderr | 4 +-- .../builtin-superkinds-simple.stderr | 4 +-- ...builtin-superkinds-typaram-not-send.stderr | 4 +-- tests/ui/chalkify/impl_wf.stderr | 8 ++--- .../coherence-overlap-trait-alias.stderr | 4 +-- .../issues/issue-67185-2.stderr | 8 ++--- tests/ui/dst/dst-sized-trait-param.stderr | 8 ++--- tests/ui/error-codes/E0308-2.stderr | 4 +-- ...ied-bounds-unnorm-associated-type-5.stderr | 4 +-- ...e-param-can-reference-self-in-trait.stderr | 4 +-- tests/ui/issues/issue-10412.stderr | 4 +-- tests/ui/issues/issue-65230.stderr | 4 +-- ...rker-trait-with-underscore-lifetime.stderr | 8 ++--- .../marker_trait_attr/region-overlap.stderr | 8 ++--- .../overloaded-calls-nontuple.stderr | 8 ++--- .../super-traits-fail.stderr | 8 ++--- tests/ui/span/issue-71363.stderr | 8 ++--- .../defaultimpl/specialization-wfcheck.stderr | 4 +-- tests/ui/static/static-lifetime.stderr | 4 +-- tests/ui/trait-bounds/unsized-bound.stderr | 36 +++++++++---------- .../on-structs-and-enums-in-impls.stderr | 4 +-- tests/ui/traits/impl-bounds-checking.stderr | 4 +-- ...trait-has-wrong-lifetime-parameters.stderr | 8 ++--- tests/ui/traits/issue-43784-supertrait.stderr | 4 +-- .../unsized-trait-impl-trait-arg.stderr | 4 +-- tests/ui/unsized/unsized7.stderr | 4 +-- 31 files changed, 97 insertions(+), 97 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index ca45e16d9d9f..9bd49f5e053b 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1272,7 +1272,7 @@ fn check_impl<'tcx>( wfcx.param_env, wfcx.body_id, &trait_pred, - ast_trait_ref.path.span, + ast_self_ty.span, item, ); debug!(?obligations); diff --git a/tests/ui/associated-types/hr-associated-type-bound-param-6.stderr b/tests/ui/associated-types/hr-associated-type-bound-param-6.stderr index bd6e627a3d0d..a07a634b28a2 100644 --- a/tests/ui/associated-types/hr-associated-type-bound-param-6.stderr +++ b/tests/ui/associated-types/hr-associated-type-bound-param-6.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `for<'b> T: X<'b, T>` is not satisfied - --> $DIR/hr-associated-type-bound-param-6.rs:12:12 + --> $DIR/hr-associated-type-bound-param-6.rs:12:25 | LL | impl X<'_, T> for (S,) { - | ^^^^^^^^ the trait `for<'b> X<'b, T>` is not implemented for `T` + | ^^^^ the trait `for<'b> X<'b, T>` is not implemented for `T` | help: consider restricting type parameter `T` | diff --git a/tests/ui/associated-types/hr-associated-type-projection-1.stderr b/tests/ui/associated-types/hr-associated-type-projection-1.stderr index a65f84ae58ea..ad83a5ca88c3 100644 --- a/tests/ui/associated-types/hr-associated-type-projection-1.stderr +++ b/tests/ui/associated-types/hr-associated-type-projection-1.stderr @@ -1,8 +1,8 @@ error[E0271]: type mismatch resolving `::Target == T` - --> $DIR/hr-associated-type-projection-1.rs:13:33 + --> $DIR/hr-associated-type-projection-1.rs:13:55 | LL | impl UnsafeCopy<'_, T> for T { - | - this type parameter ^^^^^^^^^^^^^^^^^ expected type parameter `T`, found associated type + | - this type parameter ^ expected type parameter `T`, found associated type | = note: expected type parameter `T` found associated type `::Target` diff --git a/tests/ui/builtin-superkinds/builtin-superkinds-double-superkind.stderr b/tests/ui/builtin-superkinds/builtin-superkinds-double-superkind.stderr index 492316f0027e..592aa4369ce0 100644 --- a/tests/ui/builtin-superkinds/builtin-superkinds-double-superkind.stderr +++ b/tests/ui/builtin-superkinds/builtin-superkinds-double-superkind.stderr @@ -1,8 +1,8 @@ error[E0277]: `T` cannot be sent between threads safely - --> $DIR/builtin-superkinds-double-superkind.rs:6:24 + --> $DIR/builtin-superkinds-double-superkind.rs:6:32 | LL | impl Foo for (T,) { } - | ^^^ `T` cannot be sent between threads safely + | ^^^^ `T` cannot be sent between threads safely | = note: required because it appears within the type `(T,)` note: required by a bound in `Foo` @@ -16,10 +16,10 @@ LL | impl Foo for (T,) { } | +++++++++++++++++++ error[E0277]: `T` cannot be shared between threads safely - --> $DIR/builtin-superkinds-double-superkind.rs:9:16 + --> $DIR/builtin-superkinds-double-superkind.rs:9:24 | LL | impl Foo for (T,T) { } - | ^^^ `T` cannot be shared between threads safely + | ^^^^^ `T` cannot be shared between threads safely | = note: required because it appears within the type `(T, T)` note: required by a bound in `Foo` diff --git a/tests/ui/builtin-superkinds/builtin-superkinds-in-metadata.stderr b/tests/ui/builtin-superkinds/builtin-superkinds-in-metadata.stderr index a46e4b2337cc..f9d548bb8fbe 100644 --- a/tests/ui/builtin-superkinds/builtin-superkinds-in-metadata.stderr +++ b/tests/ui/builtin-superkinds/builtin-superkinds-in-metadata.stderr @@ -1,8 +1,8 @@ error[E0277]: `T` cannot be sent between threads safely - --> $DIR/builtin-superkinds-in-metadata.rs:13:23 + --> $DIR/builtin-superkinds-in-metadata.rs:13:56 | LL | impl RequiresRequiresShareAndSend for X { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `T` cannot be sent between threads safely + | ^^^^ `T` cannot be sent between threads safely | note: required because it appears within the type `X` --> $DIR/builtin-superkinds-in-metadata.rs:9:8 diff --git a/tests/ui/builtin-superkinds/builtin-superkinds-self-type.stderr b/tests/ui/builtin-superkinds/builtin-superkinds-self-type.stderr index e2b177b951cc..e51fab0dcea5 100644 --- a/tests/ui/builtin-superkinds/builtin-superkinds-self-type.stderr +++ b/tests/ui/builtin-superkinds/builtin-superkinds-self-type.stderr @@ -1,8 +1,8 @@ error[E0310]: the parameter type `T` may not live long enough - --> $DIR/builtin-superkinds-self-type.rs:10:16 + --> $DIR/builtin-superkinds-self-type.rs:10:24 | LL | impl Foo for T { } - | ^^^ ...so that the type `T` will meet its required lifetime bounds... + | ^ ...so that the type `T` will meet its required lifetime bounds... | note: ...that is required by this bound --> $DIR/builtin-superkinds-self-type.rs:6:24 diff --git a/tests/ui/builtin-superkinds/builtin-superkinds-simple.stderr b/tests/ui/builtin-superkinds/builtin-superkinds-simple.stderr index 9db9cbfdb910..8b19170b0f10 100644 --- a/tests/ui/builtin-superkinds/builtin-superkinds-simple.stderr +++ b/tests/ui/builtin-superkinds/builtin-superkinds-simple.stderr @@ -1,8 +1,8 @@ error[E0277]: `Rc` cannot be sent between threads safely - --> $DIR/builtin-superkinds-simple.rs:6:6 + --> $DIR/builtin-superkinds-simple.rs:6:14 | LL | impl Foo for std::rc::Rc { } - | ^^^ `Rc` cannot be sent between threads safely + | ^^^^^^^^^^^^^^^ `Rc` cannot be sent between threads safely | = help: the trait `Send` is not implemented for `Rc` note: required by a bound in `Foo` diff --git a/tests/ui/builtin-superkinds/builtin-superkinds-typaram-not-send.stderr b/tests/ui/builtin-superkinds/builtin-superkinds-typaram-not-send.stderr index 3ec0b907d0cb..0cfea72d5f18 100644 --- a/tests/ui/builtin-superkinds/builtin-superkinds-typaram-not-send.stderr +++ b/tests/ui/builtin-superkinds/builtin-superkinds-typaram-not-send.stderr @@ -1,8 +1,8 @@ error[E0277]: `T` cannot be sent between threads safely - --> $DIR/builtin-superkinds-typaram-not-send.rs:5:24 + --> $DIR/builtin-superkinds-typaram-not-send.rs:5:32 | LL | impl Foo for T { } - | ^^^ `T` cannot be sent between threads safely + | ^ `T` cannot be sent between threads safely | note: required by a bound in `Foo` --> $DIR/builtin-superkinds-typaram-not-send.rs:3:13 diff --git a/tests/ui/chalkify/impl_wf.stderr b/tests/ui/chalkify/impl_wf.stderr index a142459bcb4a..84c32fa3771a 100644 --- a/tests/ui/chalkify/impl_wf.stderr +++ b/tests/ui/chalkify/impl_wf.stderr @@ -1,8 +1,8 @@ error[E0277]: the size for values of type `str` cannot be known at compilation time - --> $DIR/impl_wf.rs:11:6 + --> $DIR/impl_wf.rs:11:14 | LL | impl Foo for str { } - | ^^^ doesn't have a size known at compile-time + | ^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `str` note: required by a bound in `Foo` @@ -12,10 +12,10 @@ LL | trait Foo: Sized { } | ^^^^^ required by this bound in `Foo` error[E0277]: the trait bound `f32: Foo` is not satisfied - --> $DIR/impl_wf.rs:22:6 + --> $DIR/impl_wf.rs:22:19 | LL | impl Baz for f32 { } - | ^^^^^^^^ the trait `Foo` is not implemented for `f32` + | ^^^ the trait `Foo` is not implemented for `f32` | = help: the trait `Foo` is implemented for `i32` note: required by a bound in `Baz` diff --git a/tests/ui/coherence/coherence-overlap-trait-alias.stderr b/tests/ui/coherence/coherence-overlap-trait-alias.stderr index e324c1e799f9..668b8319b387 100644 --- a/tests/ui/coherence/coherence-overlap-trait-alias.stderr +++ b/tests/ui/coherence/coherence-overlap-trait-alias.stderr @@ -1,8 +1,8 @@ error[E0283]: type annotations needed: cannot satisfy `u32: C` - --> $DIR/coherence-overlap-trait-alias.rs:15:6 + --> $DIR/coherence-overlap-trait-alias.rs:15:12 | LL | impl C for u32 {} - | ^ + | ^^^ | note: multiple `impl`s satisfying `u32: C` found --> $DIR/coherence-overlap-trait-alias.rs:14:1 diff --git a/tests/ui/const-generics/issues/issue-67185-2.stderr b/tests/ui/const-generics/issues/issue-67185-2.stderr index c7be8e14a10d..7deb4b36fabf 100644 --- a/tests/ui/const-generics/issues/issue-67185-2.stderr +++ b/tests/ui/const-generics/issues/issue-67185-2.stderr @@ -23,10 +23,10 @@ LL | [::Quaks; 2]: Bar, = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable error[E0277]: the trait bound `[u16; 3]: Bar` is not satisfied - --> $DIR/issue-67185-2.rs:21:6 + --> $DIR/issue-67185-2.rs:21:14 | LL | impl Foo for FooImpl {} - | ^^^ the trait `Bar` is not implemented for `[u16; 3]` + | ^^^^^^^ the trait `Bar` is not implemented for `[u16; 3]` | = help: the following other types implement trait `Bar`: [[u16; 3]; 3] @@ -41,10 +41,10 @@ LL | ::Quaks: Bar, | ^^^ required by this bound in `Foo` error[E0277]: the trait bound `[[u16; 3]; 2]: Bar` is not satisfied - --> $DIR/issue-67185-2.rs:21:6 + --> $DIR/issue-67185-2.rs:21:14 | LL | impl Foo for FooImpl {} - | ^^^ the trait `Bar` is not implemented for `[[u16; 3]; 2]` + | ^^^^^^^ the trait `Bar` is not implemented for `[[u16; 3]; 2]` | = help: the following other types implement trait `Bar`: [[u16; 3]; 3] diff --git a/tests/ui/dst/dst-sized-trait-param.stderr b/tests/ui/dst/dst-sized-trait-param.stderr index 8ec94f5a3c0a..5dd517d4d939 100644 --- a/tests/ui/dst/dst-sized-trait-param.stderr +++ b/tests/ui/dst/dst-sized-trait-param.stderr @@ -1,8 +1,8 @@ error[E0277]: the size for values of type `[isize]` cannot be known at compilation time - --> $DIR/dst-sized-trait-param.rs:7:6 + --> $DIR/dst-sized-trait-param.rs:7:23 | LL | impl Foo<[isize]> for usize { } - | ^^^^^^^^^^^^ doesn't have a size known at compile-time + | ^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[isize]` note: required by a bound in `Foo` @@ -16,10 +16,10 @@ LL | trait Foo : Sized { fn take(self, x: &T) { } } // Note: T is siz | ++++++++ error[E0277]: the size for values of type `[usize]` cannot be known at compilation time - --> $DIR/dst-sized-trait-param.rs:10:6 + --> $DIR/dst-sized-trait-param.rs:10:21 | LL | impl Foo for [usize] { } - | ^^^^^^^^^^ doesn't have a size known at compile-time + | ^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[usize]` note: required by a bound in `Foo` diff --git a/tests/ui/error-codes/E0308-2.stderr b/tests/ui/error-codes/E0308-2.stderr index de54a417253d..3a8a81a73a6c 100644 --- a/tests/ui/error-codes/E0308-2.stderr +++ b/tests/ui/error-codes/E0308-2.stderr @@ -1,8 +1,8 @@ error[E0308]: mismatched types - --> $DIR/E0308-2.rs:9:6 + --> $DIR/E0308-2.rs:9:13 | LL | impl Eq for &dyn DynEq {} - | ^^ lifetime mismatch + | ^^^^^^^^^^ lifetime mismatch | = note: expected trait `<&dyn DynEq as PartialEq>` found trait `<&(dyn DynEq + 'static) as PartialEq>` diff --git a/tests/ui/fn/implied-bounds-unnorm-associated-type-5.stderr b/tests/ui/fn/implied-bounds-unnorm-associated-type-5.stderr index 458756a3dcd9..1a50eadb5f0a 100644 --- a/tests/ui/fn/implied-bounds-unnorm-associated-type-5.stderr +++ b/tests/ui/fn/implied-bounds-unnorm-associated-type-5.stderr @@ -1,8 +1,8 @@ error[E0309]: the parameter type `T` may not live long enough - --> $DIR/implied-bounds-unnorm-associated-type-5.rs:6:13 + --> $DIR/implied-bounds-unnorm-associated-type-5.rs:6:27 | LL | impl<'a, T> Trait<'a> for T { - | ^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds... + | ^ ...so that the type `T` will meet its required lifetime bounds... | note: ...that is required by this bound --> $DIR/implied-bounds-unnorm-associated-type-5.rs:1:18 diff --git a/tests/ui/generics/issue-61631-default-type-param-can-reference-self-in-trait.stderr b/tests/ui/generics/issue-61631-default-type-param-can-reference-self-in-trait.stderr index 6791182238c7..260a0ce6142c 100644 --- a/tests/ui/generics/issue-61631-default-type-param-can-reference-self-in-trait.stderr +++ b/tests/ui/generics/issue-61631-default-type-param-can-reference-self-in-trait.stderr @@ -1,8 +1,8 @@ error[E0277]: the size for values of type `[()]` cannot be known at compilation time - --> $DIR/issue-61631-default-type-param-can-reference-self-in-trait.rs:19:6 + --> $DIR/issue-61631-default-type-param-can-reference-self-in-trait.rs:19:17 | LL | impl Tsized for () {} - | ^^^^^^ doesn't have a size known at compile-time + | ^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[()]` note: required by a bound in `Tsized` diff --git a/tests/ui/issues/issue-10412.stderr b/tests/ui/issues/issue-10412.stderr index 46b9fd541adf..ebaf87630fe7 100644 --- a/tests/ui/issues/issue-10412.stderr +++ b/tests/ui/issues/issue-10412.stderr @@ -53,10 +53,10 @@ LL | impl<'self> Serializable<'_, str> for &'self str { | +++ error[E0277]: the size for values of type `str` cannot be known at compilation time - --> $DIR/issue-10412.rs:7:13 + --> $DIR/issue-10412.rs:7:35 | LL | impl<'self> Serializable for &'self str { - | ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | ^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `str` note: required by a bound in `Serializable` diff --git a/tests/ui/issues/issue-65230.stderr b/tests/ui/issues/issue-65230.stderr index fcabcdea74fc..7ccab8894837 100644 --- a/tests/ui/issues/issue-65230.stderr +++ b/tests/ui/issues/issue-65230.stderr @@ -1,8 +1,8 @@ error[E0308]: mismatched types - --> $DIR/issue-65230.rs:8:6 + --> $DIR/issue-65230.rs:8:13 | LL | impl T1 for &dyn T2 {} - | ^^ lifetime mismatch + | ^^^^^^^ lifetime mismatch | = note: expected trait `<&dyn T2 as T0>` found trait `<&(dyn T2 + 'static) as T0>` diff --git a/tests/ui/marker_trait_attr/overlap-marker-trait-with-underscore-lifetime.stderr b/tests/ui/marker_trait_attr/overlap-marker-trait-with-underscore-lifetime.stderr index 235c89e200ae..3cd59d6926eb 100644 --- a/tests/ui/marker_trait_attr/overlap-marker-trait-with-underscore-lifetime.stderr +++ b/tests/ui/marker_trait_attr/overlap-marker-trait-with-underscore-lifetime.stderr @@ -1,8 +1,8 @@ error[E0283]: type annotations needed: cannot satisfy `&(): Marker` - --> $DIR/overlap-marker-trait-with-underscore-lifetime.rs:6:6 + --> $DIR/overlap-marker-trait-with-underscore-lifetime.rs:6:17 | LL | impl Marker for &'_ () {} - | ^^^^^^ + | ^^^^^^ | note: multiple `impl`s satisfying `&(): Marker` found --> $DIR/overlap-marker-trait-with-underscore-lifetime.rs:6:1 @@ -13,10 +13,10 @@ LL | impl Marker for &'_ () {} | ^^^^^^^^^^^^^^^^^^^^^^ error[E0283]: type annotations needed: cannot satisfy `&(): Marker` - --> $DIR/overlap-marker-trait-with-underscore-lifetime.rs:7:6 + --> $DIR/overlap-marker-trait-with-underscore-lifetime.rs:7:17 | LL | impl Marker for &'_ () {} - | ^^^^^^ + | ^^^^^^ | note: multiple `impl`s satisfying `&(): Marker` found --> $DIR/overlap-marker-trait-with-underscore-lifetime.rs:6:1 diff --git a/tests/ui/marker_trait_attr/region-overlap.stderr b/tests/ui/marker_trait_attr/region-overlap.stderr index 6631fe987e27..c6497b4669de 100644 --- a/tests/ui/marker_trait_attr/region-overlap.stderr +++ b/tests/ui/marker_trait_attr/region-overlap.stderr @@ -1,8 +1,8 @@ error[E0283]: type annotations needed: cannot satisfy `(&'static (), &'a ()): A` - --> $DIR/region-overlap.rs:5:10 + --> $DIR/region-overlap.rs:5:16 | LL | impl<'a> A for (&'static (), &'a ()) {} - | ^ + | ^^^^^^^^^^^^^^^^^^^^^ | note: multiple `impl`s satisfying `(&'static (), &'a ()): A` found --> $DIR/region-overlap.rs:5:1 @@ -13,10 +13,10 @@ LL | impl<'a> A for (&'a (), &'static ()) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0283]: type annotations needed: cannot satisfy `(&'a (), &'static ()): A` - --> $DIR/region-overlap.rs:6:10 + --> $DIR/region-overlap.rs:6:16 | LL | impl<'a> A for (&'a (), &'static ()) {} - | ^ + | ^^^^^^^^^^^^^^^^^^^^^ | note: multiple `impl`s satisfying `(&'a (), &'static ()): A` found --> $DIR/region-overlap.rs:5:1 diff --git a/tests/ui/overloaded/overloaded-calls-nontuple.stderr b/tests/ui/overloaded/overloaded-calls-nontuple.stderr index 2e1600782593..8a17446130b6 100644 --- a/tests/ui/overloaded/overloaded-calls-nontuple.stderr +++ b/tests/ui/overloaded/overloaded-calls-nontuple.stderr @@ -1,17 +1,17 @@ error[E0059]: type parameter to bare `FnMut` trait must be a tuple - --> $DIR/overloaded-calls-nontuple.rs:10:6 + --> $DIR/overloaded-calls-nontuple.rs:10:23 | LL | impl FnMut for S { - | ^^^^^^^^^^^^ the trait `Tuple` is not implemented for `isize` + | ^ the trait `Tuple` is not implemented for `isize` | note: required by a bound in `FnMut` --> $SRC_DIR/core/src/ops/function.rs:LL:COL error[E0059]: type parameter to bare `FnOnce` trait must be a tuple - --> $DIR/overloaded-calls-nontuple.rs:18:6 + --> $DIR/overloaded-calls-nontuple.rs:18:24 | LL | impl FnOnce for S { - | ^^^^^^^^^^^^^ the trait `Tuple` is not implemented for `isize` + | ^ the trait `Tuple` is not implemented for `isize` | note: required by a bound in `FnOnce` --> $SRC_DIR/core/src/ops/function.rs:LL:COL diff --git a/tests/ui/rfc-2632-const-trait-impl/super-traits-fail.stderr b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail.stderr index 1f8f312df012..bf12ef1ca77d 100644 --- a/tests/ui/rfc-2632-const-trait-impl/super-traits-fail.stderr +++ b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail.stderr @@ -1,14 +1,14 @@ error[E0277]: the trait bound `S: ~const Foo` is not satisfied - --> $DIR/super-traits-fail.rs:15:12 + --> $DIR/super-traits-fail.rs:15:20 | LL | impl const Bar for S {} - | ^^^ the trait `~const Foo` is not implemented for `S` + | ^ the trait `~const Foo` is not implemented for `S` | note: the trait `Foo` is implemented for `S`, but that implementation is not `const` - --> $DIR/super-traits-fail.rs:15:12 + --> $DIR/super-traits-fail.rs:15:20 | LL | impl const Bar for S {} - | ^^^ + | ^ note: required by a bound in `Bar` --> $DIR/super-traits-fail.rs:8:12 | diff --git a/tests/ui/span/issue-71363.stderr b/tests/ui/span/issue-71363.stderr index 6c7ea007ee03..cb5cc320276d 100644 --- a/tests/ui/span/issue-71363.stderr +++ b/tests/ui/span/issue-71363.stderr @@ -1,8 +1,8 @@ error[E0277]: `MyError` doesn't implement `std::fmt::Display` - --> $DIR/issue-71363.rs:4:6 + --> $DIR/issue-71363.rs:4:28 | 4 | impl std::error::Error for MyError {} - | ^^^^^^^^^^^^^^^^^ `MyError` cannot be formatted with the default formatter + | ^^^^^^^ `MyError` cannot be formatted with the default formatter | = help: the trait `std::fmt::Display` is not implemented for `MyError` = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead @@ -10,10 +10,10 @@ note: required by a bound in `std::error::Error` --> $SRC_DIR/core/src/error.rs:LL:COL error[E0277]: `MyError` doesn't implement `Debug` - --> $DIR/issue-71363.rs:4:6 + --> $DIR/issue-71363.rs:4:28 | 4 | impl std::error::Error for MyError {} - | ^^^^^^^^^^^^^^^^^ `MyError` cannot be formatted using `{:?}` + | ^^^^^^^ `MyError` cannot be formatted using `{:?}` | = help: the trait `Debug` is not implemented for `MyError` = note: add `#[derive(Debug)]` to `MyError` or manually `impl Debug for MyError` diff --git a/tests/ui/specialization/defaultimpl/specialization-wfcheck.stderr b/tests/ui/specialization/defaultimpl/specialization-wfcheck.stderr index e7801603493d..1d9014a26430 100644 --- a/tests/ui/specialization/defaultimpl/specialization-wfcheck.stderr +++ b/tests/ui/specialization/defaultimpl/specialization-wfcheck.stderr @@ -9,10 +9,10 @@ LL | #![feature(specialization)] = note: `#[warn(incomplete_features)]` on by default error[E0277]: the trait bound `U: Eq` is not satisfied - --> $DIR/specialization-wfcheck.rs:7:17 + --> $DIR/specialization-wfcheck.rs:7:37 | LL | default impl Foo<'static, U> for () {} - | ^^^^^^^^^^^^^^^ the trait `Eq` is not implemented for `U` + | ^^ the trait `Eq` is not implemented for `U` | note: required by a bound in `Foo` --> $DIR/specialization-wfcheck.rs:5:18 diff --git a/tests/ui/static/static-lifetime.stderr b/tests/ui/static/static-lifetime.stderr index 4af3370c7994..4191ab054cb9 100644 --- a/tests/ui/static/static-lifetime.stderr +++ b/tests/ui/static/static-lifetime.stderr @@ -1,8 +1,8 @@ error[E0478]: lifetime bound not satisfied - --> $DIR/static-lifetime.rs:3:20 + --> $DIR/static-lifetime.rs:3:34 | LL | impl<'a, A: Clone> Arbitrary for ::std::borrow::Cow<'a, A> {} - | ^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ | note: lifetime parameter instantiated with the lifetime `'a` as defined here --> $DIR/static-lifetime.rs:3:6 diff --git a/tests/ui/trait-bounds/unsized-bound.stderr b/tests/ui/trait-bounds/unsized-bound.stderr index ec85ada7a8d4..f3c8464abeb5 100644 --- a/tests/ui/trait-bounds/unsized-bound.stderr +++ b/tests/ui/trait-bounds/unsized-bound.stderr @@ -1,8 +1,8 @@ error[E0277]: the size for values of type `B` cannot be known at compilation time - --> $DIR/unsized-bound.rs:2:12 + --> $DIR/unsized-bound.rs:2:30 | LL | impl Trait<(A, B)> for (A, B) where A: ?Sized, B: ?Sized, {} - | - ^^^^^^^^^^^^^ doesn't have a size known at compile-time + | - ^^^^^^ doesn't have a size known at compile-time | | | this type parameter needs to be `std::marker::Sized` | @@ -38,10 +38,10 @@ LL + impl Trait<(A, B)> for (A, B) where B: ?Sized, {} | error[E0277]: the size for values of type `C` cannot be known at compilation time - --> $DIR/unsized-bound.rs:5:31 + --> $DIR/unsized-bound.rs:5:52 | LL | impl Trait<(A, B, C)> for (A, B, C) where A: ?Sized, {} - | - ^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | - ^^^^^^^^^ doesn't have a size known at compile-time | | | this type parameter needs to be `std::marker::Sized` | @@ -92,10 +92,10 @@ LL + impl Trait<(A, B, C)> for (A, B, C) where A: ?Sized, {} | error[E0277]: the size for values of type `B` cannot be known at compilation time - --> $DIR/unsized-bound.rs:10:28 + --> $DIR/unsized-bound.rs:10:47 | LL | impl Trait2<(A, B)> for (A, B) {} - | - ^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | - ^^^^^^ doesn't have a size known at compile-time | | | this type parameter needs to be `std::marker::Sized` | @@ -131,10 +131,10 @@ LL + impl Trait2<(A, B)> for (A, B) {} | error[E0277]: the size for values of type `A` cannot be known at compilation time - --> $DIR/unsized-bound.rs:14:9 + --> $DIR/unsized-bound.rs:14:23 | LL | impl Trait3 for A where A: ?Sized {} - | - ^^^^^^^^^ doesn't have a size known at compile-time + | - ^ doesn't have a size known at compile-time | | | this type parameter needs to be `std::marker::Sized` | @@ -154,10 +154,10 @@ LL | trait Trait3 {} | ++++++++ error[E0277]: the size for values of type `A` cannot be known at compilation time - --> $DIR/unsized-bound.rs:17:17 + --> $DIR/unsized-bound.rs:17:31 | LL | impl Trait4 for A {} - | - ^^^^^^^^^ doesn't have a size known at compile-time + | - ^ doesn't have a size known at compile-time | | | this type parameter needs to be `std::marker::Sized` | @@ -177,10 +177,10 @@ LL | trait Trait4 {} | ++++++++ error[E0277]: the size for values of type `X` cannot be known at compilation time - --> $DIR/unsized-bound.rs:20:12 + --> $DIR/unsized-bound.rs:20:29 | LL | impl Trait5 for X where X: ?Sized {} - | - ^^^^^^^^^^^^ doesn't have a size known at compile-time + | - ^ doesn't have a size known at compile-time | | | this type parameter needs to be `std::marker::Sized` | @@ -200,10 +200,10 @@ LL | trait Trait5 {} | ++++++++ error[E0277]: the size for values of type `X` cannot be known at compilation time - --> $DIR/unsized-bound.rs:23:20 + --> $DIR/unsized-bound.rs:23:37 | LL | impl Trait6 for X {} - | - ^^^^^^^^^^^^ doesn't have a size known at compile-time + | - ^ doesn't have a size known at compile-time | | | this type parameter needs to be `std::marker::Sized` | @@ -223,10 +223,10 @@ LL | trait Trait6 {} | ++++++++ error[E0277]: the size for values of type `Y` cannot be known at compilation time - --> $DIR/unsized-bound.rs:26:12 + --> $DIR/unsized-bound.rs:26:29 | LL | impl Trait7 for X where Y: ?Sized {} - | - ^^^^^^^^^^^^ doesn't have a size known at compile-time + | - ^ doesn't have a size known at compile-time | | | this type parameter needs to be `std::marker::Sized` | @@ -246,10 +246,10 @@ LL | trait Trait7 {} | ++++++++ error[E0277]: the size for values of type `Y` cannot be known at compilation time - --> $DIR/unsized-bound.rs:29:20 + --> $DIR/unsized-bound.rs:29:37 | LL | impl Trait8 for X {} - | - ^^^^^^^^^^^^ doesn't have a size known at compile-time + | - ^ doesn't have a size known at compile-time | | | this type parameter needs to be `std::marker::Sized` | diff --git a/tests/ui/traits/bound/on-structs-and-enums-in-impls.stderr b/tests/ui/traits/bound/on-structs-and-enums-in-impls.stderr index 8a43742260bb..903961b4be2b 100644 --- a/tests/ui/traits/bound/on-structs-and-enums-in-impls.stderr +++ b/tests/ui/traits/bound/on-structs-and-enums-in-impls.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `u16: Trait` is not satisfied - --> $DIR/on-structs-and-enums-in-impls.rs:20:6 + --> $DIR/on-structs-and-enums-in-impls.rs:20:30 | LL | impl PolyTrait> for Struct { - | ^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `u16` + | ^^^^^^ the trait `Trait` is not implemented for `u16` | note: required by a bound in `Foo` --> $DIR/on-structs-and-enums-in-impls.rs:3:14 diff --git a/tests/ui/traits/impl-bounds-checking.stderr b/tests/ui/traits/impl-bounds-checking.stderr index b01bacdb87dc..1f969efe1141 100644 --- a/tests/ui/traits/impl-bounds-checking.stderr +++ b/tests/ui/traits/impl-bounds-checking.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `isize: Clone2` is not satisfied - --> $DIR/impl-bounds-checking.rs:10:6 + --> $DIR/impl-bounds-checking.rs:10:24 | LL | impl Getter for isize { - | ^^^^^^^^^^^^^ the trait `Clone2` is not implemented for `isize` + | ^^^^^ the trait `Clone2` is not implemented for `isize` | note: required by a bound in `Getter` --> $DIR/impl-bounds-checking.rs:6:17 diff --git a/tests/ui/traits/impl-of-supertrait-has-wrong-lifetime-parameters.stderr b/tests/ui/traits/impl-of-supertrait-has-wrong-lifetime-parameters.stderr index 5572c6515ff9..1bace8ab2864 100644 --- a/tests/ui/traits/impl-of-supertrait-has-wrong-lifetime-parameters.stderr +++ b/tests/ui/traits/impl-of-supertrait-has-wrong-lifetime-parameters.stderr @@ -1,8 +1,8 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'b` due to conflicting requirements - --> $DIR/impl-of-supertrait-has-wrong-lifetime-parameters.rs:24:13 + --> $DIR/impl-of-supertrait-has-wrong-lifetime-parameters.rs:24:28 | LL | impl<'a,'b> T2<'a, 'b> for S<'a, 'b> { - | ^^^^^^^^^^ + | ^^^^^^^^^ | note: first, the lifetime cannot outlive the lifetime `'a` as defined here... --> $DIR/impl-of-supertrait-has-wrong-lifetime-parameters.rs:24:6 @@ -15,10 +15,10 @@ note: ...but the lifetime must also be valid for the lifetime `'b` as defined he LL | impl<'a,'b> T2<'a, 'b> for S<'a, 'b> { | ^^ note: ...so that the types are compatible - --> $DIR/impl-of-supertrait-has-wrong-lifetime-parameters.rs:24:13 + --> $DIR/impl-of-supertrait-has-wrong-lifetime-parameters.rs:24:28 | LL | impl<'a,'b> T2<'a, 'b> for S<'a, 'b> { - | ^^^^^^^^^^ + | ^^^^^^^^^ = note: expected `T1<'a>` found `T1<'_>` diff --git a/tests/ui/traits/issue-43784-supertrait.stderr b/tests/ui/traits/issue-43784-supertrait.stderr index bb890cb99ee3..4fe12731475b 100644 --- a/tests/ui/traits/issue-43784-supertrait.stderr +++ b/tests/ui/traits/issue-43784-supertrait.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `T: Copy` is not satisfied - --> $DIR/issue-43784-supertrait.rs:8:9 + --> $DIR/issue-43784-supertrait.rs:8:22 | LL | impl Complete for T {} - | ^^^^^^^^ the trait `Copy` is not implemented for `T` + | ^ the trait `Copy` is not implemented for `T` | note: required by a bound in `Complete` --> $DIR/issue-43784-supertrait.rs:4:21 diff --git a/tests/ui/unsized/unsized-trait-impl-trait-arg.stderr b/tests/ui/unsized/unsized-trait-impl-trait-arg.stderr index f81487d5231a..5b24c571f6c9 100644 --- a/tests/ui/unsized/unsized-trait-impl-trait-arg.stderr +++ b/tests/ui/unsized/unsized-trait-impl-trait-arg.stderr @@ -1,8 +1,8 @@ error[E0277]: the size for values of type `X` cannot be known at compilation time - --> $DIR/unsized-trait-impl-trait-arg.rs:8:17 + --> $DIR/unsized-trait-impl-trait-arg.rs:8:27 | LL | impl T2 for S4 { - | - ^^^^^ doesn't have a size known at compile-time + | - ^^^^^ doesn't have a size known at compile-time | | | this type parameter needs to be `std::marker::Sized` | diff --git a/tests/ui/unsized/unsized7.stderr b/tests/ui/unsized/unsized7.stderr index 1555b9df4f8d..1b62bb433146 100644 --- a/tests/ui/unsized/unsized7.stderr +++ b/tests/ui/unsized/unsized7.stderr @@ -1,8 +1,8 @@ error[E0277]: the size for values of type `X` cannot be known at compilation time - --> $DIR/unsized7.rs:12:21 + --> $DIR/unsized7.rs:12:31 | LL | impl T1 for S3 { - | - ^^^^^ doesn't have a size known at compile-time + | - ^^^^^ doesn't have a size known at compile-time | | | this type parameter needs to be `std::marker::Sized` | From 54571407b2ac4bd29f6509b680a19b49d7fbaa16 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 4 Jan 2023 20:55:37 +0000 Subject: [PATCH 039/105] Bump IMPLIED_BOUNDS_ENTAILMENT to Deny + ReportNow --- compiler/rustc_lint_defs/src/builtin.rs | 4 ++-- ...plied-bounds-compatibility-unnormalized.stderr | 15 +++++++++++++++ .../impl-implied-bounds-compatibility.stderr | 15 +++++++++++++++ 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 28317d6cea02..6cdf50970836 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -4033,10 +4033,10 @@ declare_lint! { /// /// This can be used to implement an unsound API if used incorrectly. pub IMPLIED_BOUNDS_ENTAILMENT, - Warn, + Deny, "impl method assumes more implied bounds than its corresponding trait method", @future_incompatible = FutureIncompatibleInfo { reference: "issue #105572 ", - reason: FutureIncompatibilityReason::FutureReleaseError, + reason: FutureIncompatibilityReason::FutureReleaseErrorReportNow, }; } diff --git a/tests/ui/implied-bounds/impl-implied-bounds-compatibility-unnormalized.stderr b/tests/ui/implied-bounds/impl-implied-bounds-compatibility-unnormalized.stderr index 0ac31c642eb1..961ff573e504 100644 --- a/tests/ui/implied-bounds/impl-implied-bounds-compatibility-unnormalized.stderr +++ b/tests/ui/implied-bounds/impl-implied-bounds-compatibility-unnormalized.stderr @@ -14,3 +14,18 @@ LL | #![deny(implied_bounds_entailment)] error: aborting due to previous error +Future incompatibility report: Future breakage diagnostic: +error: impl method assumes more implied bounds than the corresponding trait method + --> $DIR/impl-implied-bounds-compatibility-unnormalized.rs:13:5 + | +LL | fn get<'s>(s: &'s str, _: <&'static &'s () as Project>::Ty) -> &'static str { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #105572 +note: the lint level is defined here + --> $DIR/impl-implied-bounds-compatibility-unnormalized.rs:1:9 + | +LL | #![deny(implied_bounds_entailment)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/implied-bounds/impl-implied-bounds-compatibility.stderr b/tests/ui/implied-bounds/impl-implied-bounds-compatibility.stderr index 0dfa8167a996..4841f2b17993 100644 --- a/tests/ui/implied-bounds/impl-implied-bounds-compatibility.stderr +++ b/tests/ui/implied-bounds/impl-implied-bounds-compatibility.stderr @@ -14,3 +14,18 @@ LL | #![deny(implied_bounds_entailment)] error: aborting due to previous error +Future incompatibility report: Future breakage diagnostic: +error: impl method assumes more implied bounds than the corresponding trait method + --> $DIR/impl-implied-bounds-compatibility.rs:14:5 + | +LL | fn listeners<'b>(&'b self) -> &'a MessageListeners<'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #105572 +note: the lint level is defined here + --> $DIR/impl-implied-bounds-compatibility.rs:1:9 + | +LL | #![deny(implied_bounds_entailment)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + From 5a31d5ebe253827f971352b5cac43884a35c6aaa Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 10 Jan 2023 20:24:10 +0000 Subject: [PATCH 040/105] Implement dummy query responses and a jank instantiate --- .../src/solve/assembly.rs | 11 ++-- .../rustc_trait_selection/src/solve/cache.rs | 54 ++++++++++++++---- .../src/solve/fulfill.rs | 2 +- .../rustc_trait_selection/src/solve/mod.rs | 55 ++++++++++++++----- .../src/solve/overflow.rs | 13 +++-- 5 files changed, 97 insertions(+), 38 deletions(-) diff --git a/compiler/rustc_trait_selection/src/solve/assembly.rs b/compiler/rustc_trait_selection/src/solve/assembly.rs index e9ddad11ff23..ba68da0686fe 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly.rs @@ -2,8 +2,8 @@ use super::infcx_ext::InferCtxtExt; use super::{ - fixme_instantiate_canonical_query_response, CanonicalGoal, CanonicalResponse, Certainty, - EvalCtxt, Goal, + instantiate_canonical_query_response, CanonicalGoal, CanonicalResponse, Certainty, EvalCtxt, + Goal, }; use rustc_hir::def_id::DefId; use rustc_infer::infer::TyCtxtInferExt; @@ -121,11 +121,8 @@ impl<'a, 'tcx, G: GoalKind<'tcx>> AssemblyCtxt<'a, 'tcx, G> { // canonical wrt the caller. for Candidate { source, result } in normalized_candidates { self.infcx.probe(|_| { - let candidate_certainty = fixme_instantiate_canonical_query_response( - &self.infcx, - &orig_values, - result, - ); + let candidate_certainty = + instantiate_canonical_query_response(&self.infcx, &orig_values, result); // FIXME: This is a bit scary if the `normalizes_to_goal` overflows. // diff --git a/compiler/rustc_trait_selection/src/solve/cache.rs b/compiler/rustc_trait_selection/src/solve/cache.rs index 993b79890669..f1ee73a5b853 100644 --- a/compiler/rustc_trait_selection/src/solve/cache.rs +++ b/compiler/rustc_trait_selection/src/solve/cache.rs @@ -9,11 +9,12 @@ //! FIXME(@lcnr): Write that section, feel free to ping me if you need help here //! before then or if I still haven't done that before January 2023. use super::overflow::OverflowData; -use super::CanonicalGoal; +use super::{CanonicalGoal, Certainty, MaybeCause, Response}; use super::{EvalCtxt, QueryResult}; use rustc_data_structures::fx::FxHashMap; -use rustc_middle::ty::TyCtxt; +use rustc_infer::infer::canonical::{Canonical, CanonicalVarKind, CanonicalVarValues}; +use rustc_middle::ty::{self, TyCtxt}; use std::{cmp::Ordering, collections::hash_map::Entry}; #[derive(Debug, Clone)] @@ -111,11 +112,11 @@ impl<'tcx> EvalCtxt<'tcx> { // No entry, simply push this goal on the stack after dealing with overflow. Entry::Vacant(v) => { if self.overflow_data.has_overflow(cache.stack.len()) { - return Err(self.deal_with_overflow()); + return Err(self.deal_with_overflow(goal)); } v.insert(ProvisionalEntry { - response: fixme_response_yes_no_constraints(), + response: response_no_constraints(self.tcx, goal, Certainty::Yes), depth: cache.stack.len(), }); cache.stack.push(StackElem { goal, has_been_used: false }); @@ -150,7 +151,11 @@ impl<'tcx> EvalCtxt<'tcx> { { Err(entry.response) } else { - Err(fixme_response_maybe_no_constraints()) + Err(response_no_constraints( + self.tcx, + goal, + Certainty::Maybe(MaybeCause::Ambiguity), + )) } } } @@ -248,10 +253,39 @@ impl<'tcx> EvalCtxt<'tcx> { } } -fn fixme_response_yes_no_constraints<'tcx>() -> QueryResult<'tcx> { - unimplemented!() -} +pub(super) fn response_no_constraints<'tcx>( + tcx: TyCtxt<'tcx>, + goal: Canonical<'tcx, impl Sized>, + certainty: Certainty, +) -> QueryResult<'tcx> { + let var_values = goal + .variables + .iter() + .enumerate() + .map(|(i, info)| match info.kind { + CanonicalVarKind::Ty(_) | CanonicalVarKind::PlaceholderTy(_) => { + tcx.mk_ty(ty::Bound(ty::INNERMOST, ty::BoundVar::from_usize(i).into())).into() + } + CanonicalVarKind::Region(_) | CanonicalVarKind::PlaceholderRegion(_) => { + let br = ty::BoundRegion { + var: ty::BoundVar::from_usize(i), + kind: ty::BrAnon(i as u32, None), + }; + tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)).into() + } + CanonicalVarKind::Const(_, ty) | CanonicalVarKind::PlaceholderConst(_, ty) => tcx + .mk_const(ty::ConstKind::Bound(ty::INNERMOST, ty::BoundVar::from_usize(i)), ty) + .into(), + }) + .collect(); -fn fixme_response_maybe_no_constraints<'tcx>() -> QueryResult<'tcx> { - unimplemented!() + Ok(Canonical { + max_universe: goal.max_universe, + variables: goal.variables, + value: Response { + var_values: CanonicalVarValues { var_values }, + external_constraints: Default::default(), + certainty, + }, + }) } diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index c014d682a9aa..dfc2b5ed3294 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -62,7 +62,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> { let mut errors = Vec::new(); for i in 0.. { if !infcx.tcx.recursion_limit().value_within_limit(i) { - unimplemented!("overflow") + unimplemented!("overflowed on pending obligations: {:?}", self.obligations); } let mut has_changed = false; diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index 7f5e3208f4e7..35bb68b6fce5 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -19,15 +19,19 @@ use std::mem; -use rustc_infer::infer::canonical::OriginalQueryValues; -use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; +use rustc_infer::infer::canonical::{OriginalQueryValues, QueryRegionConstraints, QueryResponse}; +use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt}; use rustc_infer::traits::query::NoSolution; use rustc_infer::traits::Obligation; +use rustc_middle::infer::canonical::Certainty as OldCertainty; use rustc_middle::infer::canonical::{Canonical, CanonicalVarValues}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{RegionOutlivesPredicate, ToPredicate, TypeOutlivesPredicate}; use rustc_span::DUMMY_SP; +use crate::traits::ObligationCause; + +use self::cache::response_no_constraints; use self::infcx_ext::InferCtxtExt; mod assembly; @@ -119,7 +123,7 @@ pub enum MaybeCause { } /// Additional constraints returned on success. -#[derive(Debug, PartialEq, Eq, Clone, Hash, TypeFoldable, TypeVisitable)] +#[derive(Debug, PartialEq, Eq, Clone, Hash, TypeFoldable, TypeVisitable, Default)] pub struct ExternalConstraints<'tcx> { // FIXME: implement this. regions: (), @@ -175,7 +179,7 @@ impl<'tcx> EvalCtxt<'tcx> { let canonical_response = self.evaluate_canonical_goal(canonical_goal)?; Ok(( true, // FIXME: check whether `var_values` are an identity substitution. - fixme_instantiate_canonical_query_response(infcx, &orig_values, canonical_response), + instantiate_canonical_query_response(infcx, &orig_values, canonical_response), )) } @@ -208,6 +212,7 @@ impl<'tcx> EvalCtxt<'tcx> { // of `PredicateKind` this is the case and it is and faster than instantiating and // recanonicalizing. let Goal { param_env, predicate } = canonical_goal.value; + if let Some(kind) = predicate.kind().no_bound_vars() { match kind { ty::PredicateKind::Clause(ty::Clause::Trait(predicate)) => self.compute_trait_goal( @@ -234,7 +239,10 @@ impl<'tcx> EvalCtxt<'tcx> { | ty::PredicateKind::ConstEvaluatable(_) | ty::PredicateKind::ConstEquate(_, _) | ty::PredicateKind::TypeWellFormedFromEnv(_) - | ty::PredicateKind::Ambiguous => unimplemented!(), + | ty::PredicateKind::Ambiguous => { + // FIXME + response_no_constraints(self.tcx, canonical_goal, Certainty::Yes) + } } } else { let (infcx, goal, var_values) = @@ -248,16 +256,18 @@ impl<'tcx> EvalCtxt<'tcx> { fn compute_type_outlives_goal( &mut self, - _goal: CanonicalGoal<'tcx, TypeOutlivesPredicate<'tcx>>, + goal: CanonicalGoal<'tcx, TypeOutlivesPredicate<'tcx>>, ) -> QueryResult<'tcx> { - todo!() + // FIXME + response_no_constraints(self.tcx, goal, Certainty::Yes) } fn compute_region_outlives_goal( &mut self, - _goal: CanonicalGoal<'tcx, RegionOutlivesPredicate<'tcx>>, + goal: CanonicalGoal<'tcx, RegionOutlivesPredicate<'tcx>>, ) -> QueryResult<'tcx> { - todo!() + // FIXME + response_no_constraints(self.tcx, goal, Certainty::Yes) } } @@ -300,10 +310,27 @@ impl<'tcx> EvalCtxt<'tcx> { } } -fn fixme_instantiate_canonical_query_response<'tcx>( - _: &InferCtxt<'tcx>, - _: &OriginalQueryValues<'tcx>, - _: CanonicalResponse<'tcx>, +fn instantiate_canonical_query_response<'tcx>( + infcx: &InferCtxt<'tcx>, + original_values: &OriginalQueryValues<'tcx>, + response: CanonicalResponse<'tcx>, ) -> Certainty { - unimplemented!() + let Ok(InferOk { value, obligations }) = infcx + .instantiate_query_response_and_region_obligations( + &ObligationCause::dummy(), + ty::ParamEnv::empty(), + original_values, + &response.unchecked_map(|resp| QueryResponse { + var_values: resp.var_values, + region_constraints: QueryRegionConstraints::default(), + certainty: match resp.certainty { + Certainty::Yes => OldCertainty::Proven, + Certainty::Maybe(_) => OldCertainty::Ambiguous, + }, + opaque_types: resp.external_constraints.opaque_types, + value: resp.certainty, + }), + ) else { bug!(); }; + assert!(obligations.is_empty()); + value } diff --git a/compiler/rustc_trait_selection/src/solve/overflow.rs b/compiler/rustc_trait_selection/src/solve/overflow.rs index fdd6adb681be..8bbb9f63e786 100644 --- a/compiler/rustc_trait_selection/src/solve/overflow.rs +++ b/compiler/rustc_trait_selection/src/solve/overflow.rs @@ -1,7 +1,9 @@ +use rustc_infer::infer::canonical::Canonical; use rustc_infer::traits::query::NoSolution; use rustc_middle::ty::TyCtxt; use rustc_session::Limit; +use super::cache::response_no_constraints; use super::{Certainty, EvalCtxt, MaybeCause, QueryResult}; /// When detecting a solver overflow, we return ambiguity. Overflow can be @@ -49,9 +51,12 @@ impl OverflowData { } impl<'tcx> EvalCtxt<'tcx> { - pub(super) fn deal_with_overflow(&mut self) -> QueryResult<'tcx> { + pub(super) fn deal_with_overflow( + &mut self, + goal: Canonical<'tcx, impl Sized>, + ) -> QueryResult<'tcx> { self.overflow_data.deal_with_overflow(); - fixme_response_overflow_no_constraints() + response_no_constraints(self.tcx, goal, Certainty::Maybe(MaybeCause::Overflow)) } /// A `while`-loop which tracks overflow. @@ -74,7 +79,3 @@ impl<'tcx> EvalCtxt<'tcx> { Ok(Certainty::Maybe(MaybeCause::Overflow)) } } - -fn fixme_response_overflow_no_constraints<'tcx>() -> QueryResult<'tcx> { - unimplemented!() -} From 1de196fef308c236aee8804c7b452ad5f5bbaf88 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 10 Jan 2023 23:41:43 +0000 Subject: [PATCH 041/105] HACK: Handle escaping bound vars from the canonical query --- compiler/rustc_middle/src/ty/sty.rs | 90 ++++++++++++++++++- .../rustc_trait_selection/src/solve/mod.rs | 2 +- 2 files changed, 89 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index f7e4c8215698..0d811d333beb 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -7,8 +7,8 @@ use crate::ty::subst::{GenericArg, InternalSubsts, SubstsRef}; use crate::ty::visit::ValidateBoundVars; use crate::ty::InferTy::*; use crate::ty::{ - self, AdtDef, DefIdTree, Discr, Term, Ty, TyCtxt, TypeFlags, TypeSuperVisitable, TypeVisitable, - TypeVisitor, + self, AdtDef, DefIdTree, Discr, FallibleTypeFolder, Term, Ty, TyCtxt, TypeFlags, TypeFoldable, + TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitor, }; use crate::ty::{List, ParamEnv}; use hir::def::DefKind; @@ -1106,6 +1106,17 @@ impl<'tcx, T> Binder<'tcx, T> { if self.0.has_escaping_bound_vars() { None } else { Some(self.skip_binder()) } } + pub fn no_bound_vars_ignoring_escaping(self, tcx: TyCtxt<'tcx>) -> Option + where + T: TypeFoldable<'tcx>, + { + if !self.0.has_escaping_bound_vars() { + Some(self.skip_binder()) + } else { + self.0.try_fold_with(&mut SkipBindersAt { index: ty::INNERMOST, tcx }).ok() + } + } + /// Splits the contents into two things that share the same binder /// level as the original, returning two distinct binders. /// @@ -1135,6 +1146,81 @@ impl<'tcx, T: IntoIterator> Binder<'tcx, T> { } } +struct SkipBindersAt<'tcx> { + tcx: TyCtxt<'tcx>, + index: ty::DebruijnIndex, +} + +impl<'tcx> FallibleTypeFolder<'tcx> for SkipBindersAt<'tcx> { + type Error = (); + + fn tcx(&self) -> TyCtxt<'tcx> { + self.tcx + } + + fn try_fold_binder(&mut self, t: Binder<'tcx, T>) -> Result, Self::Error> + where + T: ty::TypeFoldable<'tcx>, + { + self.index.shift_in(1); + let value = t.try_map_bound(|t| t.try_fold_with(self)); + self.index.shift_out(1); + value + } + + fn try_fold_ty(&mut self, ty: Ty<'tcx>) -> Result, Self::Error> { + if !ty.has_escaping_bound_vars() { + Ok(ty) + } else if let ty::Bound(index, bv) = *ty.kind() { + if index == self.index { + Err(()) + } else { + Ok(self.tcx().mk_ty(ty::Bound(index.shifted_out(1), bv))) + } + } else { + ty.try_super_fold_with(self) + } + } + + fn try_fold_region(&mut self, r: ty::Region<'tcx>) -> Result, Self::Error> { + if !r.has_escaping_bound_vars() { + Ok(r) + } else if let ty::ReLateBound(index, bv) = r.kind() { + if index == self.index { + Err(()) + } else { + Ok(self.tcx().mk_region(ty::ReLateBound(index.shifted_out(1), bv))) + } + } else { + r.try_super_fold_with(self) + } + } + + fn try_fold_const(&mut self, ct: ty::Const<'tcx>) -> Result, Self::Error> { + if !ct.has_escaping_bound_vars() { + Ok(ct) + } else if let ty::ConstKind::Bound(index, bv) = ct.kind() { + if index == self.index { + Err(()) + } else { + Ok(self.tcx().mk_const( + ty::ConstKind::Bound(index.shifted_out(1), bv), + ct.ty().try_fold_with(self)?, + )) + } + } else { + ct.try_super_fold_with(self) + } + } + + fn try_fold_predicate( + &mut self, + p: ty::Predicate<'tcx>, + ) -> Result, Self::Error> { + if !p.has_escaping_bound_vars() { Ok(p) } else { p.try_super_fold_with(self) } + } +} + /// Represents the projection of an associated type. /// /// For a projection, this would be `>::N`. diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index 35bb68b6fce5..042ba96b379e 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -213,7 +213,7 @@ impl<'tcx> EvalCtxt<'tcx> { // recanonicalizing. let Goal { param_env, predicate } = canonical_goal.value; - if let Some(kind) = predicate.kind().no_bound_vars() { + if let Some(kind) = predicate.kind().no_bound_vars_ignoring_escaping(self.tcx) { match kind { ty::PredicateKind::Clause(ty::Clause::Trait(predicate)) => self.compute_trait_goal( canonical_goal.unchecked_rebind(Goal { param_env, predicate }), From 950b47fb967ac8db2ad67da87fb167bf88963bbf Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 8 Jan 2023 23:21:46 +0000 Subject: [PATCH 042/105] Render missing generics suggestion verbosely --- compiler/rustc_resolve/src/diagnostics.rs | 2 +- ...lp-with-err-generic-is-not-function.stderr | 9 ++++--- tests/ui/issues/issue-58712.stderr | 9 ++++--- tests/ui/issues/issue-77919.stderr | 9 ++++--- tests/ui/issues/issue-86756.stderr | 7 +++-- .../ui/parser/dyn-trait-compatibility.stderr | 27 ++++++++++++------- .../type-not-found-in-adt-field.stderr | 7 +++-- tests/ui/traits/ignore-err-impls.stderr | 9 ++++--- tests/ui/traits/issue-50480.stderr | 27 ++++++++++++------- tests/ui/traits/issue-75627.stderr | 9 ++++--- tests/ui/traits/issue-78372.stderr | 9 ++++--- .../unknown_dst.stderr | 8 +++--- .../unknown_src.stderr | 8 +++--- .../autoderef-with-param-env-error.stderr | 8 +++--- tests/ui/typeck/issue-104513-ice.stderr | 7 +++-- 15 files changed, 103 insertions(+), 52 deletions(-) diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 1a852de8eed6..fb2aebbd18a3 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -167,7 +167,7 @@ impl<'a> Resolver<'a> { ); err.emit(); } else if let Some((span, msg, sugg, appl)) = suggestion { - err.span_suggestion(span, msg, sugg, appl); + err.span_suggestion_verbose(span, msg, sugg, appl); err.emit(); } else if let [segment] = path.as_slice() && is_call { err.stash(segment.ident.span, rustc_errors::StashKey::CallIntoMethod); diff --git a/tests/ui/functions-closures/fn-help-with-err-generic-is-not-function.stderr b/tests/ui/functions-closures/fn-help-with-err-generic-is-not-function.stderr index 26bdf460f5e4..9d4ea01152cc 100644 --- a/tests/ui/functions-closures/fn-help-with-err-generic-is-not-function.stderr +++ b/tests/ui/functions-closures/fn-help-with-err-generic-is-not-function.stderr @@ -2,9 +2,12 @@ error[E0412]: cannot find type `T` in this scope --> $DIR/fn-help-with-err-generic-is-not-function.rs:2:13 | LL | impl Struct - | - ^ not found in this scope - | | - | help: you might be missing a type parameter: `` + | ^ not found in this scope + | +help: you might be missing a type parameter + | +LL | impl Struct + | +++ error[E0412]: cannot find type `T` in this scope --> $DIR/fn-help-with-err-generic-is-not-function.rs:7:5 diff --git a/tests/ui/issues/issue-58712.stderr b/tests/ui/issues/issue-58712.stderr index 87c16aa993b6..f4bd4d1e826a 100644 --- a/tests/ui/issues/issue-58712.stderr +++ b/tests/ui/issues/issue-58712.stderr @@ -2,9 +2,12 @@ error[E0412]: cannot find type `DeviceId` in this scope --> $DIR/issue-58712.rs:6:20 | LL | impl AddrVec { - | - ^^^^^^^^ not found in this scope - | | - | help: you might be missing a type parameter: `, DeviceId` + | ^^^^^^^^ not found in this scope + | +help: you might be missing a type parameter + | +LL | impl AddrVec { + | ++++++++++ error[E0412]: cannot find type `DeviceId` in this scope --> $DIR/issue-58712.rs:8:29 diff --git a/tests/ui/issues/issue-77919.stderr b/tests/ui/issues/issue-77919.stderr index ca256847b1f3..d154bfe0cb55 100644 --- a/tests/ui/issues/issue-77919.stderr +++ b/tests/ui/issues/issue-77919.stderr @@ -13,9 +13,12 @@ error[E0412]: cannot find type `VAL` in this scope --> $DIR/issue-77919.rs:11:63 | LL | impl TypeVal for Multiply where N: TypeVal {} - | - ^^^ not found in this scope - | | - | help: you might be missing a type parameter: `, VAL` + | ^^^ not found in this scope + | +help: you might be missing a type parameter + | +LL | impl TypeVal for Multiply where N: TypeVal {} + | +++++ error[E0046]: not all trait items implemented, missing: `VAL` --> $DIR/issue-77919.rs:11:1 diff --git a/tests/ui/issues/issue-86756.stderr b/tests/ui/issues/issue-86756.stderr index 6c5917bdf6ec..e0f37129fd2e 100644 --- a/tests/ui/issues/issue-86756.stderr +++ b/tests/ui/issues/issue-86756.stderr @@ -9,10 +9,13 @@ LL | trait Foo {} error[E0412]: cannot find type `dyn` in this scope --> $DIR/issue-86756.rs:5:10 | -LL | fn eq() { - | - help: you might be missing a type parameter: `, dyn` LL | eq:: | ^^^ not found in this scope + | +help: you might be missing a type parameter + | +LL | fn eq() { + | +++++ warning: trait objects without an explicit `dyn` are deprecated --> $DIR/issue-86756.rs:5:15 diff --git a/tests/ui/parser/dyn-trait-compatibility.stderr b/tests/ui/parser/dyn-trait-compatibility.stderr index 9218ae9d5daa..6a946ea2ae09 100644 --- a/tests/ui/parser/dyn-trait-compatibility.stderr +++ b/tests/ui/parser/dyn-trait-compatibility.stderr @@ -26,17 +26,23 @@ error[E0412]: cannot find type `dyn` in this scope --> $DIR/dyn-trait-compatibility.rs:5:15 | LL | type A2 = dyn; - | - ^^^ not found in this scope - | | - | help: you might be missing a type parameter: `` + | ^^^ not found in this scope + | +help: you might be missing a type parameter + | +LL | type A2 = dyn; + | +++++ error[E0412]: cannot find type `dyn` in this scope --> $DIR/dyn-trait-compatibility.rs:5:20 | LL | type A2 = dyn; - | - ^^^ not found in this scope - | | - | help: you might be missing a type parameter: `` + | ^^^ not found in this scope + | +help: you might be missing a type parameter + | +LL | type A2 = dyn; + | +++++ error[E0412]: cannot find type `dyn` in this scope --> $DIR/dyn-trait-compatibility.rs:9:11 @@ -48,9 +54,12 @@ error[E0412]: cannot find type `dyn` in this scope --> $DIR/dyn-trait-compatibility.rs:9:16 | LL | type A3 = dyn<::dyn>; - | - ^^^ not found in this scope - | | - | help: you might be missing a type parameter: `` + | ^^^ not found in this scope + | +help: you might be missing a type parameter + | +LL | type A3 = dyn<::dyn>; + | +++++ error: aborting due to 8 previous errors diff --git a/tests/ui/suggestions/type-not-found-in-adt-field.stderr b/tests/ui/suggestions/type-not-found-in-adt-field.stderr index e990fb5ba121..934ba87bbaa8 100644 --- a/tests/ui/suggestions/type-not-found-in-adt-field.stderr +++ b/tests/ui/suggestions/type-not-found-in-adt-field.stderr @@ -7,10 +7,13 @@ LL | m: Vec>, error[E0412]: cannot find type `K` in this scope --> $DIR/type-not-found-in-adt-field.rs:6:8 | -LL | struct OtherStruct { - | - help: you might be missing a type parameter: `` LL | m: K, | ^ not found in this scope + | +help: you might be missing a type parameter + | +LL | struct OtherStruct { + | +++ error: aborting due to 2 previous errors diff --git a/tests/ui/traits/ignore-err-impls.stderr b/tests/ui/traits/ignore-err-impls.stderr index 1390106a2912..45bd533b5c6f 100644 --- a/tests/ui/traits/ignore-err-impls.stderr +++ b/tests/ui/traits/ignore-err-impls.stderr @@ -2,9 +2,12 @@ error[E0412]: cannot find type `Type` in this scope --> $DIR/ignore-err-impls.rs:6:14 | LL | impl Generic for S {} - | - ^^^^ not found in this scope - | | - | help: you might be missing a type parameter: `` + | ^^^^ not found in this scope + | +help: you might be missing a type parameter + | +LL | impl Generic for S {} + | ++++++ error: aborting due to previous error diff --git a/tests/ui/traits/issue-50480.stderr b/tests/ui/traits/issue-50480.stderr index 0bb1f9ae0350..aa8384e98053 100644 --- a/tests/ui/traits/issue-50480.stderr +++ b/tests/ui/traits/issue-50480.stderr @@ -2,9 +2,12 @@ error[E0412]: cannot find type `N` in this scope --> $DIR/issue-50480.rs:3:12 | LL | struct Foo(N, NotDefined, ::Item, Vec, String); - | -^ not found in this scope - | | - | help: you might be missing a type parameter: `` + | ^ not found in this scope + | +help: you might be missing a type parameter + | +LL | struct Foo(N, NotDefined, ::Item, Vec, String); + | +++ error[E0412]: cannot find type `NotDefined` in this scope --> $DIR/issue-50480.rs:3:15 @@ -16,17 +19,23 @@ error[E0412]: cannot find type `N` in this scope --> $DIR/issue-50480.rs:3:12 | LL | struct Foo(N, NotDefined, ::Item, Vec, String); - | -^ not found in this scope - | | - | help: you might be missing a type parameter: `` + | ^ not found in this scope + | +help: you might be missing a type parameter + | +LL | struct Foo(N, NotDefined, ::Item, Vec, String); + | +++ error[E0412]: cannot find type `NotDefined` in this scope --> $DIR/issue-50480.rs:3:15 | LL | struct Foo(N, NotDefined, ::Item, Vec, String); - | - ^^^^^^^^^^ not found in this scope - | | - | help: you might be missing a type parameter: `` + | ^^^^^^^^^^ not found in this scope + | +help: you might be missing a type parameter + | +LL | struct Foo(N, NotDefined, ::Item, Vec, String); + | ++++++++++++ error[E0412]: cannot find type `N` in this scope --> $DIR/issue-50480.rs:12:18 diff --git a/tests/ui/traits/issue-75627.stderr b/tests/ui/traits/issue-75627.stderr index 432ddf2dcdbd..1675edc9ff0b 100644 --- a/tests/ui/traits/issue-75627.stderr +++ b/tests/ui/traits/issue-75627.stderr @@ -2,9 +2,12 @@ error[E0412]: cannot find type `T` in this scope --> $DIR/issue-75627.rs:3:26 | LL | unsafe impl Send for Foo {} - | - ^ not found in this scope - | | - | help: you might be missing a type parameter: `` + | ^ not found in this scope + | +help: you might be missing a type parameter + | +LL | unsafe impl Send for Foo {} + | +++ error: aborting due to previous error diff --git a/tests/ui/traits/issue-78372.stderr b/tests/ui/traits/issue-78372.stderr index 7e781016e1f0..8e7fd5f25571 100644 --- a/tests/ui/traits/issue-78372.stderr +++ b/tests/ui/traits/issue-78372.stderr @@ -30,9 +30,12 @@ error[E0412]: cannot find type `MISC` in this scope --> $DIR/issue-78372.rs:3:34 | LL | impl DispatchFromDyn> for T {} - | - ^^^^ not found in this scope - | | - | help: you might be missing a type parameter: `, MISC` + | ^^^^ not found in this scope + | +help: you might be missing a type parameter + | +LL | impl DispatchFromDyn> for T {} + | ++++++ error[E0658]: use of unstable library feature 'dispatch_from_dyn' --> $DIR/issue-78372.rs:1:5 diff --git a/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst.stderr b/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst.stderr index 85087282d3a6..b4591778f8e7 100644 --- a/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst.stderr +++ b/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst.stderr @@ -1,11 +1,13 @@ error[E0412]: cannot find type `Dst` in this scope --> $DIR/unknown_dst.rs:20:36 | -LL | fn should_gracefully_handle_unknown_dst() { - | - help: you might be missing a type parameter: `` -... LL | assert::is_transmutable::(); | ^^^ not found in this scope + | +help: you might be missing a type parameter + | +LL | fn should_gracefully_handle_unknown_dst() { + | +++++ error: aborting due to previous error diff --git a/tests/ui/transmutability/malformed-program-gracefulness/unknown_src.stderr b/tests/ui/transmutability/malformed-program-gracefulness/unknown_src.stderr index 9bedbe87c3f7..a55d71d80682 100644 --- a/tests/ui/transmutability/malformed-program-gracefulness/unknown_src.stderr +++ b/tests/ui/transmutability/malformed-program-gracefulness/unknown_src.stderr @@ -1,11 +1,13 @@ error[E0412]: cannot find type `Src` in this scope --> $DIR/unknown_src.rs:20:31 | -LL | fn should_gracefully_handle_unknown_src() { - | - help: you might be missing a type parameter: `` -... LL | assert::is_transmutable::(); | ^^^ not found in this scope + | +help: you might be missing a type parameter + | +LL | fn should_gracefully_handle_unknown_src() { + | +++++ error: aborting due to previous error diff --git a/tests/ui/typeck/autoderef-with-param-env-error.stderr b/tests/ui/typeck/autoderef-with-param-env-error.stderr index cde800336dd3..182612d5ee70 100644 --- a/tests/ui/typeck/autoderef-with-param-env-error.stderr +++ b/tests/ui/typeck/autoderef-with-param-env-error.stderr @@ -1,11 +1,13 @@ error[E0412]: cannot find type `T` in this scope --> $DIR/autoderef-with-param-env-error.rs:3:5 | -LL | fn foo() - | - help: you might be missing a type parameter: `` -LL | where LL | T: Send, | ^ not found in this scope + | +help: you might be missing a type parameter + | +LL | fn foo() + | +++ error: aborting due to previous error diff --git a/tests/ui/typeck/issue-104513-ice.stderr b/tests/ui/typeck/issue-104513-ice.stderr index 2b3b1b9efdfa..5561673f3c67 100644 --- a/tests/ui/typeck/issue-104513-ice.stderr +++ b/tests/ui/typeck/issue-104513-ice.stderr @@ -1,10 +1,13 @@ error[E0405]: cannot find trait `Oops` in this scope --> $DIR/issue-104513-ice.rs:3:19 | -LL | fn f() { - | - help: you might be missing a type parameter: `` LL | let _: S = S; | ^^^^ not found in this scope + | +help: you might be missing a type parameter + | +LL | fn f() { + | ++++++ error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable binding --> $DIR/issue-104513-ice.rs:3:14 From bf0623e3633a371374341265c8729f6255bfde4c Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 8 Jan 2023 23:27:22 +0000 Subject: [PATCH 043/105] Don't suggest dyn as parameter to add --- compiler/rustc_resolve/src/late/diagnostics.rs | 6 +++++- src/tools/clippy/tests/ui/crashes/ice-6252.stderr | 9 ++++++--- tests/ui/issues/issue-86756.stderr | 5 ----- tests/ui/parser/dyn-trait-compatibility.stderr | 15 --------------- 4 files changed, 11 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index d92f5a7c05e6..d92b046d0b9f 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -2065,7 +2065,11 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { path: &[Segment], ) -> Option<(Span, &'static str, String, Applicability)> { let (ident, span) = match path { - [segment] if !segment.has_generic_args && segment.ident.name != kw::SelfUpper => { + [segment] + if !segment.has_generic_args + && segment.ident.name != kw::SelfUpper + && segment.ident.name != kw::Dyn => + { (segment.ident.to_string(), segment.ident.span) } _ => return None, diff --git a/src/tools/clippy/tests/ui/crashes/ice-6252.stderr b/src/tools/clippy/tests/ui/crashes/ice-6252.stderr index 638e4a548493..efdd56dd47d3 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-6252.stderr +++ b/src/tools/clippy/tests/ui/crashes/ice-6252.stderr @@ -17,9 +17,12 @@ error[E0412]: cannot find type `VAL` in this scope --> $DIR/ice-6252.rs:10:63 | LL | impl TypeVal for Multiply where N: TypeVal {} - | - ^^^ not found in this scope - | | - | help: you might be missing a type parameter: `, VAL` + | ^^^ not found in this scope + | +help: you might be missing a type parameter + | +LL | impl TypeVal for Multiply where N: TypeVal {} + | +++++ error[E0046]: not all trait items implemented, missing: `VAL` --> $DIR/ice-6252.rs:10:1 diff --git a/tests/ui/issues/issue-86756.stderr b/tests/ui/issues/issue-86756.stderr index e0f37129fd2e..bfa7459ab4a3 100644 --- a/tests/ui/issues/issue-86756.stderr +++ b/tests/ui/issues/issue-86756.stderr @@ -11,11 +11,6 @@ error[E0412]: cannot find type `dyn` in this scope | LL | eq:: | ^^^ not found in this scope - | -help: you might be missing a type parameter - | -LL | fn eq() { - | +++++ warning: trait objects without an explicit `dyn` are deprecated --> $DIR/issue-86756.rs:5:15 diff --git a/tests/ui/parser/dyn-trait-compatibility.stderr b/tests/ui/parser/dyn-trait-compatibility.stderr index 6a946ea2ae09..0cae01bd1e32 100644 --- a/tests/ui/parser/dyn-trait-compatibility.stderr +++ b/tests/ui/parser/dyn-trait-compatibility.stderr @@ -27,22 +27,12 @@ error[E0412]: cannot find type `dyn` in this scope | LL | type A2 = dyn; | ^^^ not found in this scope - | -help: you might be missing a type parameter - | -LL | type A2 = dyn; - | +++++ error[E0412]: cannot find type `dyn` in this scope --> $DIR/dyn-trait-compatibility.rs:5:20 | LL | type A2 = dyn; | ^^^ not found in this scope - | -help: you might be missing a type parameter - | -LL | type A2 = dyn; - | +++++ error[E0412]: cannot find type `dyn` in this scope --> $DIR/dyn-trait-compatibility.rs:9:11 @@ -55,11 +45,6 @@ error[E0412]: cannot find type `dyn` in this scope | LL | type A3 = dyn<::dyn>; | ^^^ not found in this scope - | -help: you might be missing a type parameter - | -LL | type A3 = dyn<::dyn>; - | +++++ error: aborting due to 8 previous errors From 5924c2511e43dd077df78d9936ccd0d76168ad30 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 12 Jan 2023 20:28:57 +0000 Subject: [PATCH 044/105] Only point at impl self ty in WF if trait predicate shares self ty --- compiler/rustc_hir_analysis/src/check/wfcheck.rs | 11 +++++++++-- .../hr-associated-type-bound-param-6.stderr | 4 ++-- .../hr-associated-type-projection-1.stderr | 4 ++-- .../builtin-superkinds-self-type.stderr | 4 ++-- tests/ui/const-generics/issues/issue-67185-2.stderr | 8 ++++---- tests/ui/dst/dst-sized-trait-param.stderr | 4 ++-- .../fn/implied-bounds-unnorm-associated-type-5.stderr | 4 ++-- ...ault-type-param-can-reference-self-in-trait.stderr | 4 ++-- tests/ui/issues/issue-10412.stderr | 4 ++-- tests/ui/overloaded/overloaded-calls-nontuple.stderr | 8 ++++---- .../defaultimpl/specialization-wfcheck.stderr | 4 ++-- tests/ui/static/static-lifetime.stderr | 4 ++-- tests/ui/trait-bounds/unsized-bound.stderr | 8 ++++---- .../traits/bound/on-structs-and-enums-in-impls.stderr | 4 ++-- tests/ui/unsized/unsized-trait-impl-trait-arg.stderr | 4 ++-- tests/ui/unsized/unsized7.stderr | 4 ++-- 16 files changed, 45 insertions(+), 38 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 9bd49f5e053b..92fd4625ee83 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1267,14 +1267,21 @@ fn check_impl<'tcx>( }, polarity: ty::ImplPolarity::Positive, }; - let obligations = traits::wf::trait_obligations( + let mut obligations = traits::wf::trait_obligations( wfcx.infcx, wfcx.param_env, wfcx.body_id, &trait_pred, - ast_self_ty.span, + ast_trait_ref.path.span, item, ); + for obligation in &mut obligations { + if let Some(pred) = obligation.predicate.to_opt_poly_trait_pred() + && pred.self_ty().skip_binder() == trait_ref.self_ty() + { + obligation.cause.span = ast_self_ty.span; + } + } debug!(?obligations); wfcx.register_obligations(obligations); } diff --git a/tests/ui/associated-types/hr-associated-type-bound-param-6.stderr b/tests/ui/associated-types/hr-associated-type-bound-param-6.stderr index a07a634b28a2..bd6e627a3d0d 100644 --- a/tests/ui/associated-types/hr-associated-type-bound-param-6.stderr +++ b/tests/ui/associated-types/hr-associated-type-bound-param-6.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `for<'b> T: X<'b, T>` is not satisfied - --> $DIR/hr-associated-type-bound-param-6.rs:12:25 + --> $DIR/hr-associated-type-bound-param-6.rs:12:12 | LL | impl X<'_, T> for (S,) { - | ^^^^ the trait `for<'b> X<'b, T>` is not implemented for `T` + | ^^^^^^^^ the trait `for<'b> X<'b, T>` is not implemented for `T` | help: consider restricting type parameter `T` | diff --git a/tests/ui/associated-types/hr-associated-type-projection-1.stderr b/tests/ui/associated-types/hr-associated-type-projection-1.stderr index ad83a5ca88c3..a65f84ae58ea 100644 --- a/tests/ui/associated-types/hr-associated-type-projection-1.stderr +++ b/tests/ui/associated-types/hr-associated-type-projection-1.stderr @@ -1,8 +1,8 @@ error[E0271]: type mismatch resolving `::Target == T` - --> $DIR/hr-associated-type-projection-1.rs:13:55 + --> $DIR/hr-associated-type-projection-1.rs:13:33 | LL | impl UnsafeCopy<'_, T> for T { - | - this type parameter ^ expected type parameter `T`, found associated type + | - this type parameter ^^^^^^^^^^^^^^^^^ expected type parameter `T`, found associated type | = note: expected type parameter `T` found associated type `::Target` diff --git a/tests/ui/builtin-superkinds/builtin-superkinds-self-type.stderr b/tests/ui/builtin-superkinds/builtin-superkinds-self-type.stderr index e51fab0dcea5..e2b177b951cc 100644 --- a/tests/ui/builtin-superkinds/builtin-superkinds-self-type.stderr +++ b/tests/ui/builtin-superkinds/builtin-superkinds-self-type.stderr @@ -1,8 +1,8 @@ error[E0310]: the parameter type `T` may not live long enough - --> $DIR/builtin-superkinds-self-type.rs:10:24 + --> $DIR/builtin-superkinds-self-type.rs:10:16 | LL | impl Foo for T { } - | ^ ...so that the type `T` will meet its required lifetime bounds... + | ^^^ ...so that the type `T` will meet its required lifetime bounds... | note: ...that is required by this bound --> $DIR/builtin-superkinds-self-type.rs:6:24 diff --git a/tests/ui/const-generics/issues/issue-67185-2.stderr b/tests/ui/const-generics/issues/issue-67185-2.stderr index 7deb4b36fabf..c7be8e14a10d 100644 --- a/tests/ui/const-generics/issues/issue-67185-2.stderr +++ b/tests/ui/const-generics/issues/issue-67185-2.stderr @@ -23,10 +23,10 @@ LL | [::Quaks; 2]: Bar, = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable error[E0277]: the trait bound `[u16; 3]: Bar` is not satisfied - --> $DIR/issue-67185-2.rs:21:14 + --> $DIR/issue-67185-2.rs:21:6 | LL | impl Foo for FooImpl {} - | ^^^^^^^ the trait `Bar` is not implemented for `[u16; 3]` + | ^^^ the trait `Bar` is not implemented for `[u16; 3]` | = help: the following other types implement trait `Bar`: [[u16; 3]; 3] @@ -41,10 +41,10 @@ LL | ::Quaks: Bar, | ^^^ required by this bound in `Foo` error[E0277]: the trait bound `[[u16; 3]; 2]: Bar` is not satisfied - --> $DIR/issue-67185-2.rs:21:14 + --> $DIR/issue-67185-2.rs:21:6 | LL | impl Foo for FooImpl {} - | ^^^^^^^ the trait `Bar` is not implemented for `[[u16; 3]; 2]` + | ^^^ the trait `Bar` is not implemented for `[[u16; 3]; 2]` | = help: the following other types implement trait `Bar`: [[u16; 3]; 3] diff --git a/tests/ui/dst/dst-sized-trait-param.stderr b/tests/ui/dst/dst-sized-trait-param.stderr index 5dd517d4d939..60e9de90332c 100644 --- a/tests/ui/dst/dst-sized-trait-param.stderr +++ b/tests/ui/dst/dst-sized-trait-param.stderr @@ -1,8 +1,8 @@ error[E0277]: the size for values of type `[isize]` cannot be known at compilation time - --> $DIR/dst-sized-trait-param.rs:7:23 + --> $DIR/dst-sized-trait-param.rs:7:6 | LL | impl Foo<[isize]> for usize { } - | ^^^^^ doesn't have a size known at compile-time + | ^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[isize]` note: required by a bound in `Foo` diff --git a/tests/ui/fn/implied-bounds-unnorm-associated-type-5.stderr b/tests/ui/fn/implied-bounds-unnorm-associated-type-5.stderr index 1a50eadb5f0a..458756a3dcd9 100644 --- a/tests/ui/fn/implied-bounds-unnorm-associated-type-5.stderr +++ b/tests/ui/fn/implied-bounds-unnorm-associated-type-5.stderr @@ -1,8 +1,8 @@ error[E0309]: the parameter type `T` may not live long enough - --> $DIR/implied-bounds-unnorm-associated-type-5.rs:6:27 + --> $DIR/implied-bounds-unnorm-associated-type-5.rs:6:13 | LL | impl<'a, T> Trait<'a> for T { - | ^ ...so that the type `T` will meet its required lifetime bounds... + | ^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds... | note: ...that is required by this bound --> $DIR/implied-bounds-unnorm-associated-type-5.rs:1:18 diff --git a/tests/ui/generics/issue-61631-default-type-param-can-reference-self-in-trait.stderr b/tests/ui/generics/issue-61631-default-type-param-can-reference-self-in-trait.stderr index 260a0ce6142c..6791182238c7 100644 --- a/tests/ui/generics/issue-61631-default-type-param-can-reference-self-in-trait.stderr +++ b/tests/ui/generics/issue-61631-default-type-param-can-reference-self-in-trait.stderr @@ -1,8 +1,8 @@ error[E0277]: the size for values of type `[()]` cannot be known at compilation time - --> $DIR/issue-61631-default-type-param-can-reference-self-in-trait.rs:19:17 + --> $DIR/issue-61631-default-type-param-can-reference-self-in-trait.rs:19:6 | LL | impl Tsized for () {} - | ^^ doesn't have a size known at compile-time + | ^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[()]` note: required by a bound in `Tsized` diff --git a/tests/ui/issues/issue-10412.stderr b/tests/ui/issues/issue-10412.stderr index ebaf87630fe7..46b9fd541adf 100644 --- a/tests/ui/issues/issue-10412.stderr +++ b/tests/ui/issues/issue-10412.stderr @@ -53,10 +53,10 @@ LL | impl<'self> Serializable<'_, str> for &'self str { | +++ error[E0277]: the size for values of type `str` cannot be known at compilation time - --> $DIR/issue-10412.rs:7:35 + --> $DIR/issue-10412.rs:7:13 | LL | impl<'self> Serializable for &'self str { - | ^^^^^^^^^^ doesn't have a size known at compile-time + | ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `str` note: required by a bound in `Serializable` diff --git a/tests/ui/overloaded/overloaded-calls-nontuple.stderr b/tests/ui/overloaded/overloaded-calls-nontuple.stderr index 8a17446130b6..2e1600782593 100644 --- a/tests/ui/overloaded/overloaded-calls-nontuple.stderr +++ b/tests/ui/overloaded/overloaded-calls-nontuple.stderr @@ -1,17 +1,17 @@ error[E0059]: type parameter to bare `FnMut` trait must be a tuple - --> $DIR/overloaded-calls-nontuple.rs:10:23 + --> $DIR/overloaded-calls-nontuple.rs:10:6 | LL | impl FnMut for S { - | ^ the trait `Tuple` is not implemented for `isize` + | ^^^^^^^^^^^^ the trait `Tuple` is not implemented for `isize` | note: required by a bound in `FnMut` --> $SRC_DIR/core/src/ops/function.rs:LL:COL error[E0059]: type parameter to bare `FnOnce` trait must be a tuple - --> $DIR/overloaded-calls-nontuple.rs:18:24 + --> $DIR/overloaded-calls-nontuple.rs:18:6 | LL | impl FnOnce for S { - | ^ the trait `Tuple` is not implemented for `isize` + | ^^^^^^^^^^^^^ the trait `Tuple` is not implemented for `isize` | note: required by a bound in `FnOnce` --> $SRC_DIR/core/src/ops/function.rs:LL:COL diff --git a/tests/ui/specialization/defaultimpl/specialization-wfcheck.stderr b/tests/ui/specialization/defaultimpl/specialization-wfcheck.stderr index 1d9014a26430..e7801603493d 100644 --- a/tests/ui/specialization/defaultimpl/specialization-wfcheck.stderr +++ b/tests/ui/specialization/defaultimpl/specialization-wfcheck.stderr @@ -9,10 +9,10 @@ LL | #![feature(specialization)] = note: `#[warn(incomplete_features)]` on by default error[E0277]: the trait bound `U: Eq` is not satisfied - --> $DIR/specialization-wfcheck.rs:7:37 + --> $DIR/specialization-wfcheck.rs:7:17 | LL | default impl Foo<'static, U> for () {} - | ^^ the trait `Eq` is not implemented for `U` + | ^^^^^^^^^^^^^^^ the trait `Eq` is not implemented for `U` | note: required by a bound in `Foo` --> $DIR/specialization-wfcheck.rs:5:18 diff --git a/tests/ui/static/static-lifetime.stderr b/tests/ui/static/static-lifetime.stderr index 4191ab054cb9..4af3370c7994 100644 --- a/tests/ui/static/static-lifetime.stderr +++ b/tests/ui/static/static-lifetime.stderr @@ -1,8 +1,8 @@ error[E0478]: lifetime bound not satisfied - --> $DIR/static-lifetime.rs:3:34 + --> $DIR/static-lifetime.rs:3:20 | LL | impl<'a, A: Clone> Arbitrary for ::std::borrow::Cow<'a, A> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^ | note: lifetime parameter instantiated with the lifetime `'a` as defined here --> $DIR/static-lifetime.rs:3:6 diff --git a/tests/ui/trait-bounds/unsized-bound.stderr b/tests/ui/trait-bounds/unsized-bound.stderr index f3c8464abeb5..da27ba1c58db 100644 --- a/tests/ui/trait-bounds/unsized-bound.stderr +++ b/tests/ui/trait-bounds/unsized-bound.stderr @@ -223,10 +223,10 @@ LL | trait Trait6 {} | ++++++++ error[E0277]: the size for values of type `Y` cannot be known at compilation time - --> $DIR/unsized-bound.rs:26:29 + --> $DIR/unsized-bound.rs:26:12 | LL | impl Trait7 for X where Y: ?Sized {} - | - ^ doesn't have a size known at compile-time + | - ^^^^^^^^^^^^ doesn't have a size known at compile-time | | | this type parameter needs to be `std::marker::Sized` | @@ -246,10 +246,10 @@ LL | trait Trait7 {} | ++++++++ error[E0277]: the size for values of type `Y` cannot be known at compilation time - --> $DIR/unsized-bound.rs:29:37 + --> $DIR/unsized-bound.rs:29:20 | LL | impl Trait8 for X {} - | - ^ doesn't have a size known at compile-time + | - ^^^^^^^^^^^^ doesn't have a size known at compile-time | | | this type parameter needs to be `std::marker::Sized` | diff --git a/tests/ui/traits/bound/on-structs-and-enums-in-impls.stderr b/tests/ui/traits/bound/on-structs-and-enums-in-impls.stderr index 903961b4be2b..8a43742260bb 100644 --- a/tests/ui/traits/bound/on-structs-and-enums-in-impls.stderr +++ b/tests/ui/traits/bound/on-structs-and-enums-in-impls.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `u16: Trait` is not satisfied - --> $DIR/on-structs-and-enums-in-impls.rs:20:30 + --> $DIR/on-structs-and-enums-in-impls.rs:20:6 | LL | impl PolyTrait> for Struct { - | ^^^^^^ the trait `Trait` is not implemented for `u16` + | ^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `u16` | note: required by a bound in `Foo` --> $DIR/on-structs-and-enums-in-impls.rs:3:14 diff --git a/tests/ui/unsized/unsized-trait-impl-trait-arg.stderr b/tests/ui/unsized/unsized-trait-impl-trait-arg.stderr index 5b24c571f6c9..f81487d5231a 100644 --- a/tests/ui/unsized/unsized-trait-impl-trait-arg.stderr +++ b/tests/ui/unsized/unsized-trait-impl-trait-arg.stderr @@ -1,8 +1,8 @@ error[E0277]: the size for values of type `X` cannot be known at compilation time - --> $DIR/unsized-trait-impl-trait-arg.rs:8:27 + --> $DIR/unsized-trait-impl-trait-arg.rs:8:17 | LL | impl T2 for S4 { - | - ^^^^^ doesn't have a size known at compile-time + | - ^^^^^ doesn't have a size known at compile-time | | | this type parameter needs to be `std::marker::Sized` | diff --git a/tests/ui/unsized/unsized7.stderr b/tests/ui/unsized/unsized7.stderr index 1b62bb433146..1555b9df4f8d 100644 --- a/tests/ui/unsized/unsized7.stderr +++ b/tests/ui/unsized/unsized7.stderr @@ -1,8 +1,8 @@ error[E0277]: the size for values of type `X` cannot be known at compilation time - --> $DIR/unsized7.rs:12:31 + --> $DIR/unsized7.rs:12:21 | LL | impl T1 for S3 { - | - ^^^^^ doesn't have a size known at compile-time + | - ^^^^^ doesn't have a size known at compile-time | | | this type parameter needs to be `std::marker::Sized` | From 06a2d2d001c7d75bfd6c006711f635f9f5f5effb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 12 Jan 2023 23:46:58 +0000 Subject: [PATCH 045/105] Fix ICE formatting --- compiler/rustc_borrowck/src/diagnostics/region_errors.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index e8a4d1c37c18..f3050a6ef3f0 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -79,7 +79,7 @@ impl<'tcx> RegionErrors<'tcx> { #[track_caller] pub fn push(&mut self, val: impl Into>) { let val = val.into(); - self.1.sess.delay_span_bug(DUMMY_SP, "{val:?}"); + self.1.sess.delay_span_bug(DUMMY_SP, format!("{val:?}")); self.0.push(val); } pub fn is_empty(&self) -> bool { From 8e27211dbc8b6fd334e33c767641522f1ebb785f Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 11 Jan 2023 22:20:56 +0000 Subject: [PATCH 046/105] is_ty_infer -> is_ty_or_numeric_infer --- compiler/rustc_infer/src/infer/error_reporting/mod.rs | 4 ++-- .../src/infer/error_reporting/need_type_info.rs | 10 +++++----- compiler/rustc_middle/src/ty/sty.rs | 2 +- compiler/rustc_middle/src/ty/subst.rs | 2 +- .../src/traits/error_reporting/mod.rs | 7 +++++-- 5 files changed, 14 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 080ae6b94669..533a3c768eb1 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -1782,9 +1782,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { // like when you have two references but one is `usize` and the other // is `f32`. In those cases we still want to show the `note`. If the // value from `ef` is `Infer(_)`, then we ignore it. - if !ef.expected.is_ty_infer() { + if !ef.expected.is_ty_or_numeric_infer() { ef.expected != values.expected - } else if !ef.found.is_ty_infer() { + } else if !ef.found.is_ty_or_numeric_infer() { ef.found != values.found } else { false diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index a4c36b4c9cd5..b8c843a8a5a2 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -78,7 +78,7 @@ impl InferenceDiagnosticsData { } fn where_x_is_kind(&self, in_type: Ty<'_>) -> &'static str { - if in_type.is_ty_infer() { + if in_type.is_ty_or_numeric_infer() { "" } else if self.name == "_" { // FIXME: Consider specializing this message if there is a single `_` @@ -195,12 +195,12 @@ fn ty_to_string<'tcx>( // invalid pseudo-syntax, we want the `fn`-pointer output instead. (ty::FnDef(..), _) => ty.fn_sig(infcx.tcx).print(printer).unwrap().into_buffer(), (_, Some(def_id)) - if ty.is_ty_infer() + if ty.is_ty_or_numeric_infer() && infcx.tcx.get_diagnostic_item(sym::iterator_collect_fn) == Some(def_id) => { "Vec<_>".to_string() } - _ if ty.is_ty_infer() => "/* Type */".to_string(), + _ if ty.is_ty_or_numeric_infer() => "/* Type */".to_string(), // FIXME: The same thing for closures, but this only works when the closure // does not capture anything. // @@ -680,7 +680,7 @@ impl<'tcx> InferSourceKind<'tcx> { | InferSourceKind::ClosureReturn { ty, .. } => { if ty.is_closure() { ("closure", closure_as_fn_str(infcx, ty)) - } else if !ty.is_ty_infer() { + } else if !ty.is_ty_or_numeric_infer() { ("normal", ty_to_string(infcx, ty, None)) } else { ("other", String::new()) @@ -813,7 +813,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { self.attempt += 1; if let Some(InferSource { kind: InferSourceKind::GenericArg { def_id: did, ..}, .. }) = self.infer_source && let InferSourceKind::LetBinding { ref ty, ref mut def_id, ..} = new_source.kind - && ty.is_ty_infer() + && ty.is_ty_or_numeric_infer() { // Customize the output so we talk about `let x: Vec<_> = iter.collect();` instead of // `let x: _ = iter.collect();`, as this is a very common case. diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index f7e4c8215698..bd5b04d5b2ba 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1686,7 +1686,7 @@ impl<'tcx> Ty<'tcx> { } #[inline] - pub fn is_ty_infer(self) -> bool { + pub fn is_ty_or_numeric_infer(self) -> bool { matches!(self.kind(), Infer(_)) } diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs index 0c33e5bda1a5..2dec58ea82a3 100644 --- a/compiler/rustc_middle/src/ty/subst.rs +++ b/compiler/rustc_middle/src/ty/subst.rs @@ -202,7 +202,7 @@ impl<'tcx> GenericArg<'tcx> { pub fn is_non_region_infer(self) -> bool { match self.unpack() { GenericArgKind::Lifetime(_) => false, - GenericArgKind::Type(ty) => ty.is_ty_infer(), + GenericArgKind::Type(ty) => ty.is_ty_or_numeric_infer(), GenericArgKind::Const(ct) => ct.is_ct_infer(), } } 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 20bede22c342..0c7ffb056cc0 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -2252,8 +2252,11 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { Ok(None) => { let ambiguities = ambiguity::recompute_applicable_impls(self.infcx, &obligation); - let has_non_region_infer = - trait_ref.skip_binder().substs.types().any(|t| !t.is_ty_infer()); + let has_non_region_infer = trait_ref + .skip_binder() + .substs + .types() + .any(|t| !t.is_ty_or_numeric_infer()); // It doesn't make sense to talk about applicable impls if there are more // than a handful of them. if ambiguities.len() > 1 && ambiguities.len() < 10 && has_non_region_infer { From eaa7cc84d358a0113c063d445e5d0d7caeeea94c Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 12 Jan 2023 20:43:44 +0000 Subject: [PATCH 047/105] Add logic to make IMPLIED_BOUNDS_ENTAILMENT easier to understand --- .../src/check/compare_impl_item.rs | 160 ++++++++++++++++-- ...d-bounds-compatibility-unnormalized.stderr | 8 +- .../impl-implied-bounds-compatibility.stderr | 8 +- 3 files changed, 156 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 7af89934d142..2cdf75794713 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -2,7 +2,9 @@ use super::potentially_plural_count; use crate::errors::LifetimesOrBoundsMismatchOnTrait; use hir::def_id::{DefId, LocalDefId}; use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; -use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId, ErrorGuaranteed}; +use rustc_errors::{ + pluralize, struct_span_err, Applicability, DiagnosticId, ErrorGuaranteed, MultiSpan, +}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit; @@ -320,15 +322,6 @@ fn compare_method_predicate_entailment<'tcx>( ty::Binder::dummy(ty::PredicateKind::WellFormed(unnormalized_impl_fty.into())), )); } - let emit_implied_wf_lint = || { - infcx.tcx.struct_span_lint_hir( - rustc_session::lint::builtin::IMPLIED_BOUNDS_ENTAILMENT, - impl_m_hir_id, - infcx.tcx.def_span(impl_m.def_id), - "impl method assumes more implied bounds than the corresponding trait method", - |lint| lint, - ); - }; // Check that all obligations are satisfied by the implementation's // version. @@ -346,7 +339,7 @@ fn compare_method_predicate_entailment<'tcx>( ) .map(|()| { // If the skip-mode was successful, emit a lint. - emit_implied_wf_lint(); + emit_implied_wf_lint(infcx.tcx, impl_m, impl_m_hir_id, vec![]); }); } CheckImpliedWfMode::Skip => { @@ -382,8 +375,16 @@ fn compare_method_predicate_entailment<'tcx>( CheckImpliedWfMode::Skip, ) .map(|()| { + let bad_args = extract_bad_args_for_implies_lint( + tcx, + &errors, + (trait_m, trait_sig), + // Unnormalized impl sig corresponds to the HIR types written + (impl_m, unnormalized_impl_sig), + impl_m_hir_id, + ); // If the skip-mode was successful, emit a lint. - emit_implied_wf_lint(); + emit_implied_wf_lint(tcx, impl_m, impl_m_hir_id, bad_args); }); } CheckImpliedWfMode::Skip => { @@ -400,6 +401,141 @@ fn compare_method_predicate_entailment<'tcx>( Ok(()) } +fn extract_bad_args_for_implies_lint<'tcx>( + tcx: TyCtxt<'tcx>, + errors: &[infer::RegionResolutionError<'tcx>], + (trait_m, trait_sig): (&ty::AssocItem, ty::FnSig<'tcx>), + (impl_m, impl_sig): (&ty::AssocItem, ty::FnSig<'tcx>), + hir_id: hir::HirId, +) -> Vec<(Span, Option)> { + let mut blame_generics = vec![]; + for error in errors { + // Look for the subregion origin that contains an input/output type + let origin = match error { + infer::RegionResolutionError::ConcreteFailure(o, ..) => o, + infer::RegionResolutionError::GenericBoundFailure(o, ..) => o, + infer::RegionResolutionError::SubSupConflict(_, _, o, ..) => o, + infer::RegionResolutionError::UpperBoundUniverseConflict(.., o, _) => o, + }; + // Extract (possible) input/output types from origin + match origin { + infer::SubregionOrigin::Subtype(trace) => { + if let Some((a, b)) = trace.values.ty() { + blame_generics.extend([a, b]); + } + } + infer::SubregionOrigin::RelateParamBound(_, ty, _) => blame_generics.push(*ty), + infer::SubregionOrigin::ReferenceOutlivesReferent(ty, _) => blame_generics.push(*ty), + _ => {} + } + } + + let fn_decl = tcx.hir().fn_decl_by_hir_id(hir_id).unwrap(); + let opt_ret_ty = match fn_decl.output { + hir::FnRetTy::DefaultReturn(_) => None, + hir::FnRetTy::Return(ty) => Some(ty), + }; + + // Map late-bound regions from trait to impl, so the names are right. + let mapping = std::iter::zip( + tcx.fn_sig(trait_m.def_id).bound_vars(), + tcx.fn_sig(impl_m.def_id).bound_vars(), + ) + .filter_map(|(impl_bv, trait_bv)| { + if let ty::BoundVariableKind::Region(impl_bv) = impl_bv + && let ty::BoundVariableKind::Region(trait_bv) = trait_bv + { + Some((impl_bv, trait_bv)) + } else { + None + } + }) + .collect(); + + // For each arg, see if it was in the "blame" of any of the region errors. + // If so, then try to produce a suggestion to replace the argument type with + // one from the trait. + let mut bad_args = vec![]; + for (idx, (ty, hir_ty)) in + std::iter::zip(impl_sig.inputs_and_output, fn_decl.inputs.iter().chain(opt_ret_ty)) + .enumerate() + { + let expected_ty = trait_sig.inputs_and_output[idx] + .fold_with(&mut RemapLateBound { tcx, mapping: &mapping }); + if blame_generics.iter().any(|blame| ty.contains(*blame)) { + let expected_ty_sugg = expected_ty.to_string(); + bad_args.push(( + hir_ty.span, + // Only suggest something if it actually changed. + (expected_ty_sugg != ty.to_string()).then_some(expected_ty_sugg), + )); + } + } + + bad_args +} + +struct RemapLateBound<'a, 'tcx> { + tcx: TyCtxt<'tcx>, + mapping: &'a FxHashMap, +} + +impl<'tcx> TypeFolder<'tcx> for RemapLateBound<'_, 'tcx> { + fn tcx(&self) -> TyCtxt<'tcx> { + self.tcx + } + + fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { + if let ty::ReFree(fr) = *r { + self.tcx.mk_region(ty::ReFree(ty::FreeRegion { + bound_region: self + .mapping + .get(&fr.bound_region) + .copied() + .unwrap_or(fr.bound_region), + ..fr + })) + } else { + r + } + } +} + +fn emit_implied_wf_lint<'tcx>( + tcx: TyCtxt<'tcx>, + impl_m: &ty::AssocItem, + hir_id: hir::HirId, + bad_args: Vec<(Span, Option)>, +) { + let span: MultiSpan = if bad_args.is_empty() { + tcx.def_span(impl_m.def_id).into() + } else { + bad_args.iter().map(|(span, _)| *span).collect::>().into() + }; + tcx.struct_span_lint_hir( + rustc_session::lint::builtin::IMPLIED_BOUNDS_ENTAILMENT, + hir_id, + span, + "impl method assumes more implied bounds than the corresponding trait method", + |lint| { + let bad_args: Vec<_> = + bad_args.into_iter().filter_map(|(span, sugg)| Some((span, sugg?))).collect(); + if !bad_args.is_empty() { + lint.multipart_suggestion( + format!( + "replace {} type{} to make the impl signature compatible", + pluralize!("this", bad_args.len()), + pluralize!(bad_args.len()) + ), + bad_args, + Applicability::MaybeIncorrect, + ); + } + lint + }, + ); +} + #[derive(Debug, PartialEq, Eq)] enum CheckImpliedWfMode { /// Checks implied well-formedness of the impl method. If it fails, we will diff --git a/tests/ui/implied-bounds/impl-implied-bounds-compatibility-unnormalized.stderr b/tests/ui/implied-bounds/impl-implied-bounds-compatibility-unnormalized.stderr index 961ff573e504..ebe07027d2fa 100644 --- a/tests/ui/implied-bounds/impl-implied-bounds-compatibility-unnormalized.stderr +++ b/tests/ui/implied-bounds/impl-implied-bounds-compatibility-unnormalized.stderr @@ -1,8 +1,8 @@ error: impl method assumes more implied bounds than the corresponding trait method - --> $DIR/impl-implied-bounds-compatibility-unnormalized.rs:13:5 + --> $DIR/impl-implied-bounds-compatibility-unnormalized.rs:13:31 | LL | fn get<'s>(s: &'s str, _: <&'static &'s () as Project>::Ty) -> &'static str { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace this type to make the impl signature compatible: `()` | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #105572 @@ -16,10 +16,10 @@ error: aborting due to previous error Future incompatibility report: Future breakage diagnostic: error: impl method assumes more implied bounds than the corresponding trait method - --> $DIR/impl-implied-bounds-compatibility-unnormalized.rs:13:5 + --> $DIR/impl-implied-bounds-compatibility-unnormalized.rs:13:31 | LL | fn get<'s>(s: &'s str, _: <&'static &'s () as Project>::Ty) -> &'static str { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace this type to make the impl signature compatible: `()` | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #105572 diff --git a/tests/ui/implied-bounds/impl-implied-bounds-compatibility.stderr b/tests/ui/implied-bounds/impl-implied-bounds-compatibility.stderr index 4841f2b17993..43d3e058ffeb 100644 --- a/tests/ui/implied-bounds/impl-implied-bounds-compatibility.stderr +++ b/tests/ui/implied-bounds/impl-implied-bounds-compatibility.stderr @@ -1,8 +1,8 @@ error: impl method assumes more implied bounds than the corresponding trait method - --> $DIR/impl-implied-bounds-compatibility.rs:14:5 + --> $DIR/impl-implied-bounds-compatibility.rs:14:35 | LL | fn listeners<'b>(&'b self) -> &'a MessageListeners<'b> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace this type to make the impl signature compatible: `&'b MessageListeners<'b>` | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #105572 @@ -16,10 +16,10 @@ error: aborting due to previous error Future incompatibility report: Future breakage diagnostic: error: impl method assumes more implied bounds than the corresponding trait method - --> $DIR/impl-implied-bounds-compatibility.rs:14:5 + --> $DIR/impl-implied-bounds-compatibility.rs:14:35 | LL | fn listeners<'b>(&'b self) -> &'a MessageListeners<'b> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace this type to make the impl signature compatible: `&'b MessageListeners<'b>` | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #105572 From 95ef76b8aa0563192d549314a375913ce68b4902 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Thu, 12 Jan 2023 21:28:20 -0500 Subject: [PATCH 048/105] Normalize test output more thoroughly This prevents differences in local environments, which may (for example) end up with a longer backtrace with more digits in the backtrace prefix, as happened to me. While we're at it, clean more of the output up, including the exact location of the error in the compiler. --- tests/ui/chalkify/bugs/async.rs | 17 ++++++-- tests/ui/chalkify/bugs/async.stderr | 60 +++++++++++++++++++---------- 2 files changed, 52 insertions(+), 25 deletions(-) diff --git a/tests/ui/chalkify/bugs/async.rs b/tests/ui/chalkify/bugs/async.rs index 86ce42631b43..1c69b07e3d4a 100644 --- a/tests/ui/chalkify/bugs/async.rs +++ b/tests/ui/chalkify/bugs/async.rs @@ -2,12 +2,21 @@ // known-bug // unset-rustc-env:RUST_BACKTRACE // compile-flags:-Z trait-solver=chalk --edition=2021 -// error-pattern:stack backtrace: +// error-pattern:internal compiler error // failure-status:101 -// normalize-stderr-test "note: .*" -> "" -// normalize-stderr-test "thread 'rustc' .*" -> "" -// normalize-stderr-test " .*\n" -> "" // normalize-stderr-test "DefId([^)]*)" -> "..." +// normalize-stderr-test "\nerror: internal compiler error.*\n\n" -> "" +// normalize-stderr-test "note:.*unexpectedly panicked.*\n\n" -> "" +// normalize-stderr-test "note: we would appreciate a bug report.*\n\n" -> "" +// normalize-stderr-test "note: compiler flags.*\n\n" -> "" +// normalize-stderr-test "note: rustc.*running on.*\n\n" -> "" +// normalize-stderr-test "thread.*panicked.*\n" -> "" +// normalize-stderr-test "stack backtrace:\n" -> "" +// normalize-stderr-test "\s\d{1,}: .*\n" -> "" +// normalize-stderr-test "\s at .*\n" -> "" +// normalize-stderr-test ".*note: Some details.*\n" -> "" +// normalize-stderr-test "\n\n[ ]*\n" -> "" +// normalize-stderr-test "compiler/.*: projection" -> "projection" fn main() -> () {} diff --git a/tests/ui/chalkify/bugs/async.stderr b/tests/ui/chalkify/bugs/async.stderr index 7e2466dece43..d1508cb17001 100644 --- a/tests/ui/chalkify/bugs/async.stderr +++ b/tests/ui/chalkify/bugs/async.stderr @@ -1,29 +1,47 @@ -error[E0277]: `[async fn body@$DIR/async.rs:14:29: 16:2]` is not a future -LL |LL | |LL | | } +error[E0277]: `[async fn body@$DIR/async.rs:23:29: 25:2]` is not a future + --> $DIR/async.rs:23:29 + | +LL | async fn foo(x: u32) -> u32 { + | _____________________________- +LL | | x +LL | | } + | | ^ + | | | + | |_`[async fn body@$DIR/async.rs:23:29: 25:2]` is not a future + | required by a bound introduced by this call + | + = help: the trait `Future` is not implemented for `[async fn body@$DIR/async.rs:23:29: 25:2]` + = note: [async fn body@$DIR/async.rs:23:29: 25:2] must be a future or must implement `IntoFuture` to be awaited +note: required by a bound in `identity_future` + --> $SRC_DIR/core/src/future/mod.rs:LL:COL +error[E0277]: the size for values of type `<[async fn body@$DIR/async.rs:23:29: 25:2] as Future>::Output` cannot be known at compilation time + --> $DIR/async.rs:23:29 + | +LL | async fn foo(x: u32) -> u32 { + | _____________________________^ +LL | | x +LL | | } + | |_^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `<[async fn body@$DIR/async.rs:23:29: 25:2] as Future>::Output` +note: required by a bound in `identity_future` + --> $SRC_DIR/core/src/future/mod.rs:LL:COL -error[E0277]: the size for values of type `<[async fn body@$DIR/async.rs:14:29: 16:2] as Future>::Output` cannot be known at compilation time -LL |LL | |LL | | } - - -error[E0277]: `[async fn body@$DIR/async.rs:14:29: 16:2]` is not a future +error[E0277]: `[async fn body@$DIR/async.rs:23:29: 25:2]` is not a future + --> $DIR/async.rs:23:25 + | LL | async fn foo(x: u32) -> u32 { + | ^^^ `[async fn body@$DIR/async.rs:23:29: 25:2]` is not a future + | + = help: the trait `Future` is not implemented for `[async fn body@$DIR/async.rs:23:29: 25:2]` + = note: [async fn body@$DIR/async.rs:23:29: 25:2] must be a future or must implement `IntoFuture` to be awaited -error: internal compiler error: compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs:1114:25: projection clauses should be implied from elsewhere. obligation: `Obligation(predicate=Binder(ProjectionPredicate(AliasTy { substs: [[async fn body@$DIR/async.rs:14:29: 16:2]], def_id: ...), _use_mk_alias_ty_instead: () }, Term::Ty(u32)), []), depth=0)` +error: internal compiler error: projection clauses should be implied from elsewhere. obligation: `Obligation(predicate=Binder(ProjectionPredicate(AliasTy { substs: [[async fn body@$DIR/async.rs:23:29: 25:2]], def_id: ...), _use_mk_alias_ty_instead: () }, Term::Ty(u32)), []), depth=0)` + --> $DIR/async.rs:23:25 + | LL | async fn foo(x: u32) -> u32 { - - -stack backtrace: - - - - - - - - - -query stack during panic: + | ^^^query stack during panic: #0 [typeck] type-checking `foo` #1 [thir_body] building THIR for `foo` #2 [mir_built] building MIR for `foo` From a3cf3822d267524e3d9fa45309f2718793f3cf7f Mon Sep 17 00:00:00 2001 From: Robin Schroer Date: Sun, 8 Jan 2023 21:10:48 +0900 Subject: [PATCH 049/105] Emit a hint for bad call return types due to generic arguments When the return type of a function call depends on the type of an argument, e.g. ``` fn foo(x: T) -> T { x } ``` and the expected type is set due to either an explicitly typed binding, or because the call to the function is in a tail position without semicolon, the current error implies that the argument in the call has the wrong type. This new hint highlights that the expected type doesn't match the returned type, which matches the argument type, and that that's why we're flagging the argument type. Fixes #43608. --- compiler/rustc_hir_typeck/src/demand.rs | 74 ++++++++++ tests/ui/closures/issue-84128.stderr | 7 + tests/ui/closures/issue-87461.stderr | 21 +++ .../missing-bounds.stderr | 7 + tests/ui/mismatched_types/issue-35030.stderr | 7 + .../args-instead-of-tuple-errors.stderr | 21 +++ .../suggestions/sugg-else-for-closure.stderr | 7 + tests/ui/traits/issue-52893.stderr | 7 + ...ong-call-return-type-due-to-generic-arg.rs | 28 ++++ ...call-return-type-due-to-generic-arg.stderr | 131 ++++++++++++++++++ tests/ui/typeck/issue-46112.stderr | 7 + tests/ui/typeck/issue-84768.stderr | 7 + tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr | 14 ++ 13 files changed, 338 insertions(+) create mode 100644 tests/ui/type/wrong-call-return-type-due-to-generic-arg.rs create mode 100644 tests/ui/type/wrong-call-return-type-due-to-generic-arg.stderr diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 6c128d0aa1a6..665dc8b6a2f2 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -85,6 +85,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.note_internal_mutation_in_method(err, expr, expected, expr_ty); self.check_for_range_as_method_call(err, expr, expr_ty, expected); self.check_for_binding_assigned_block_without_tail_expression(err, expr, expr_ty, expected); + self.check_wrong_return_type_due_to_generic_arg(err, expr, expr_ty); } /// Requires that the two types unify, and prints an error message if @@ -1941,4 +1942,77 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.span_label(block.span, "this block is missing a tail expression"); } } + + fn check_wrong_return_type_due_to_generic_arg( + &self, + err: &mut Diagnostic, + expr: &hir::Expr<'_>, + checked_ty: Ty<'tcx>, + ) { + let Some(hir::Node::Expr(parent_expr)) = self.tcx.hir().find_parent(expr.hir_id) else { return; }; + enum CallableKind { + Function, + Method, + Constructor, + } + let mut maybe_emit_help = |def_id: hir::def_id::DefId, + callable: rustc_span::symbol::Ident, + args: &[hir::Expr<'_>], + kind: CallableKind| { + let arg_idx = args.iter().position(|a| a.hir_id == expr.hir_id).unwrap(); + let fn_ty = self.tcx.bound_type_of(def_id).0; + if !fn_ty.is_fn() { + return; + } + let fn_sig = fn_ty.fn_sig(self.tcx).skip_binder(); + let Some(&arg) = fn_sig.inputs().get(arg_idx + if matches!(kind, CallableKind::Method) { 1 } else { 0 }) else { return; }; + if matches!(arg.kind(), ty::Param(_)) + && fn_sig.output().contains(arg) + && self.node_ty(args[arg_idx].hir_id) == checked_ty + { + let mut multi_span: MultiSpan = parent_expr.span.into(); + multi_span.push_span_label( + args[arg_idx].span, + format!( + "this argument influences the {} of `{}`", + if matches!(kind, CallableKind::Constructor) { + "type" + } else { + "return type" + }, + callable + ), + ); + err.span_help( + multi_span, + format!( + "the {} `{}` due to the type of the argument passed", + match kind { + CallableKind::Function => "return type of this call is", + CallableKind::Method => "return type of this call is", + CallableKind::Constructor => "type constructed contains", + }, + checked_ty + ), + ); + } + }; + match parent_expr.kind { + hir::ExprKind::Call(fun, args) => { + let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = fun.kind else { return; }; + let hir::def::Res::Def(kind, def_id) = path.res else { return; }; + let callable_kind = if matches!(kind, hir::def::DefKind::Ctor(_, _)) { + CallableKind::Constructor + } else { + CallableKind::Function + }; + maybe_emit_help(def_id, path.segments[0].ident, args, callable_kind); + } + hir::ExprKind::MethodCall(method, _receiver, args, _span) => { + let Some(def_id) = self.typeck_results.borrow().type_dependent_def_id(parent_expr.hir_id) else { return; }; + maybe_emit_help(def_id, method.ident, args, CallableKind::Method) + } + _ => return, + } + } } diff --git a/tests/ui/closures/issue-84128.stderr b/tests/ui/closures/issue-84128.stderr index 59607afec8f8..1cd8949b8c4b 100644 --- a/tests/ui/closures/issue-84128.stderr +++ b/tests/ui/closures/issue-84128.stderr @@ -6,6 +6,13 @@ LL | Foo(()) | | | arguments to this struct are incorrect | +help: the type constructed contains `()` due to the type of the argument passed + --> $DIR/issue-84128.rs:13:9 + | +LL | Foo(()) + | ^^^^--^ + | | + | this argument influences the type of `Foo` note: tuple struct defined here --> $DIR/issue-84128.rs:5:8 | diff --git a/tests/ui/closures/issue-87461.stderr b/tests/ui/closures/issue-87461.stderr index 72337892734e..b492251c0169 100644 --- a/tests/ui/closures/issue-87461.stderr +++ b/tests/ui/closures/issue-87461.stderr @@ -6,6 +6,13 @@ LL | Ok(()) | | | arguments to this enum variant are incorrect | +help: the type constructed contains `()` due to the type of the argument passed + --> $DIR/issue-87461.rs:10:5 + | +LL | Ok(()) + | ^^^--^ + | | + | this argument influences the type of `Ok` note: tuple variant defined here --> $SRC_DIR/core/src/result.rs:LL:COL @@ -17,6 +24,13 @@ LL | Ok(()) | | | arguments to this enum variant are incorrect | +help: the type constructed contains `()` due to the type of the argument passed + --> $DIR/issue-87461.rs:17:5 + | +LL | Ok(()) + | ^^^--^ + | | + | this argument influences the type of `Ok` note: tuple variant defined here --> $SRC_DIR/core/src/result.rs:LL:COL @@ -28,6 +42,13 @@ LL | Ok(()) | | | arguments to this enum variant are incorrect | +help: the type constructed contains `()` due to the type of the argument passed + --> $DIR/issue-87461.rs:26:9 + | +LL | Ok(()) + | ^^^--^ + | | + | this argument influences the type of `Ok` note: tuple variant defined here --> $SRC_DIR/core/src/result.rs:LL:COL diff --git a/tests/ui/generic-associated-types/missing-bounds.stderr b/tests/ui/generic-associated-types/missing-bounds.stderr index c913483a8747..9f669b9a5214 100644 --- a/tests/ui/generic-associated-types/missing-bounds.stderr +++ b/tests/ui/generic-associated-types/missing-bounds.stderr @@ -23,6 +23,13 @@ LL | A(self.0 + rhs.0) | = note: expected type parameter `B` found associated type `::Output` +help: the type constructed contains `::Output` due to the type of the argument passed + --> $DIR/missing-bounds.rs:11:9 + | +LL | A(self.0 + rhs.0) + | ^^--------------^ + | | + | this argument influences the type of `A` note: tuple struct defined here --> $DIR/missing-bounds.rs:5:8 | diff --git a/tests/ui/mismatched_types/issue-35030.stderr b/tests/ui/mismatched_types/issue-35030.stderr index 680aff1726f9..de4e067fead4 100644 --- a/tests/ui/mismatched_types/issue-35030.stderr +++ b/tests/ui/mismatched_types/issue-35030.stderr @@ -11,6 +11,13 @@ LL | Some(true) | = note: expected type parameter `bool` (type parameter `bool`) found type `bool` (`bool`) +help: the type constructed contains `bool` due to the type of the argument passed + --> $DIR/issue-35030.rs:9:9 + | +LL | Some(true) + | ^^^^^----^ + | | + | this argument influences the type of `Some` note: tuple variant defined here --> $SRC_DIR/core/src/option.rs:LL:COL diff --git a/tests/ui/suggestions/args-instead-of-tuple-errors.stderr b/tests/ui/suggestions/args-instead-of-tuple-errors.stderr index 44a39efdf254..bc097bf6eb45 100644 --- a/tests/ui/suggestions/args-instead-of-tuple-errors.stderr +++ b/tests/ui/suggestions/args-instead-of-tuple-errors.stderr @@ -11,6 +11,13 @@ LL | let _: Option<(i32, bool)> = Some(1, 2); | ^ = note: expected tuple `(i32, bool)` found type `{integer}` +help: the type constructed contains `{integer}` due to the type of the argument passed + --> $DIR/args-instead-of-tuple-errors.rs:6:34 + | +LL | let _: Option<(i32, bool)> = Some(1, 2); + | ^^^^^-^^^^ + | | + | this argument influences the type of `Some` note: tuple variant defined here --> $SRC_DIR/core/src/option.rs:LL:COL help: remove the extra argument @@ -64,6 +71,13 @@ LL | let _: Option<(i32,)> = Some(5_usize); | = note: expected tuple `(i32,)` found type `usize` +help: the type constructed contains `usize` due to the type of the argument passed + --> $DIR/args-instead-of-tuple-errors.rs:14:29 + | +LL | let _: Option<(i32,)> = Some(5_usize); + | ^^^^^-------^ + | | + | this argument influences the type of `Some` note: tuple variant defined here --> $SRC_DIR/core/src/option.rs:LL:COL @@ -77,6 +91,13 @@ LL | let _: Option<(i32,)> = Some((5_usize)); | = note: expected tuple `(i32,)` found type `usize` +help: the type constructed contains `usize` due to the type of the argument passed + --> $DIR/args-instead-of-tuple-errors.rs:17:29 + | +LL | let _: Option<(i32,)> = Some((5_usize)); + | ^^^^^---------^ + | | + | this argument influences the type of `Some` note: tuple variant defined here --> $SRC_DIR/core/src/option.rs:LL:COL diff --git a/tests/ui/suggestions/sugg-else-for-closure.stderr b/tests/ui/suggestions/sugg-else-for-closure.stderr index 5f59d0f541c9..7f05832bcd72 100644 --- a/tests/ui/suggestions/sugg-else-for-closure.stderr +++ b/tests/ui/suggestions/sugg-else-for-closure.stderr @@ -8,6 +8,13 @@ LL | let _s = y.unwrap_or(|| x.split('.').nth(1).unwrap()); | = note: expected reference `&str` found closure `[closure@$DIR/sugg-else-for-closure.rs:6:26: 6:28]` +help: the return type of this call is `[closure@$DIR/sugg-else-for-closure.rs:6:26: 6:28]` due to the type of the argument passed + --> $DIR/sugg-else-for-closure.rs:6:14 + | +LL | let _s = y.unwrap_or(|| x.split('.').nth(1).unwrap()); + | ^^^^^^^^^^^^-------------------------------^ + | | + | this argument influences the return type of `unwrap_or` note: associated function defined here --> $SRC_DIR/core/src/option.rs:LL:COL help: try calling `unwrap_or_else` instead diff --git a/tests/ui/traits/issue-52893.stderr b/tests/ui/traits/issue-52893.stderr index 7924d3db06f3..a11867c03a68 100644 --- a/tests/ui/traits/issue-52893.stderr +++ b/tests/ui/traits/issue-52893.stderr @@ -11,6 +11,13 @@ LL | builder.push(output); | = note: expected type parameter `F` found struct `Class

` +help: the return type of this call is `Class

` due to the type of the argument passed + --> $DIR/issue-52893.rs:53:9 + | +LL | builder.push(output); + | ^^^^^^^^^^^^^------^ + | | + | this argument influences the return type of `push` note: associated function defined here --> $DIR/issue-52893.rs:11:8 | diff --git a/tests/ui/type/wrong-call-return-type-due-to-generic-arg.rs b/tests/ui/type/wrong-call-return-type-due-to-generic-arg.rs new file mode 100644 index 000000000000..ba5b9f54246e --- /dev/null +++ b/tests/ui/type/wrong-call-return-type-due-to-generic-arg.rs @@ -0,0 +1,28 @@ +fn function(x: T, y: bool) -> T { + x +} + +struct S {} +impl S { + fn method(&self, x: T) -> T { + x + } +} + +fn wrong_arg_type(x: u32) -> u32 { + x +} + +fn main() { + // Should not trigger. + let x = wrong_arg_type(0u16); //~ ERROR mismatched types + let x: u16 = function(0, 0u8); //~ ERROR mismatched types + + // Should trigger exactly once for the first argument. + let x: u16 = function(0u32, 0u8); //~ ERROR arguments to this function are incorrect + + // Should trigger. + let x: u16 = function(0u32, true); //~ ERROR mismatched types + let x: u16 = (S {}).method(0u32); //~ ERROR mismatched types + function(0u32, 8u8) //~ ERROR arguments to this function are incorrect +} diff --git a/tests/ui/type/wrong-call-return-type-due-to-generic-arg.stderr b/tests/ui/type/wrong-call-return-type-due-to-generic-arg.stderr new file mode 100644 index 000000000000..4d012cb156bb --- /dev/null +++ b/tests/ui/type/wrong-call-return-type-due-to-generic-arg.stderr @@ -0,0 +1,131 @@ +error[E0308]: mismatched types + --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:18:28 + | +LL | let x = wrong_arg_type(0u16); + | -------------- ^^^^ expected `u32`, found `u16` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:12:4 + | +LL | fn wrong_arg_type(x: u32) -> u32 { + | ^^^^^^^^^^^^^^ ------ +help: change the type of the numeric literal from `u16` to `u32` + | +LL | let x = wrong_arg_type(0u32); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:19:30 + | +LL | let x: u16 = function(0, 0u8); + | -------- ^^^ expected `bool`, found `u8` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:1:4 + | +LL | fn function(x: T, y: bool) -> T { + | ^^^^^^^^ ------- + +error[E0308]: arguments to this function are incorrect + --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:22:18 + | +LL | let x: u16 = function(0u32, 0u8); + | ^^^^^^^^ ---- --- expected `bool`, found `u8` + | | + | expected `u16`, found `u32` + | +help: the return type of this call is `u32` due to the type of the argument passed + --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:22:18 + | +LL | let x: u16 = function(0u32, 0u8); + | ^^^^^^^^^----^^^^^^ + | | + | this argument influences the return type of `function` +note: function defined here + --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:1:4 + | +LL | fn function(x: T, y: bool) -> T { + | ^^^^^^^^ ---- ------- +help: change the type of the numeric literal from `u32` to `u16` + | +LL | let x: u16 = function(0u16, 0u8); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:25:27 + | +LL | let x: u16 = function(0u32, true); + | -------- ^^^^ expected `u16`, found `u32` + | | + | arguments to this function are incorrect + | +help: the return type of this call is `u32` due to the type of the argument passed + --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:25:18 + | +LL | let x: u16 = function(0u32, true); + | ^^^^^^^^^----^^^^^^^ + | | + | this argument influences the return type of `function` +note: function defined here + --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:1:4 + | +LL | fn function(x: T, y: bool) -> T { + | ^^^^^^^^ ---- +help: change the type of the numeric literal from `u32` to `u16` + | +LL | let x: u16 = function(0u16, true); + | ~~~ + +error[E0308]: mismatched types + --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:26:32 + | +LL | let x: u16 = (S {}).method(0u32); + | ------ ^^^^ expected `u16`, found `u32` + | | + | arguments to this method are incorrect + | +help: the return type of this call is `u32` due to the type of the argument passed + --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:26:18 + | +LL | let x: u16 = (S {}).method(0u32); + | ^^^^^^^^^^^^^^----^ + | | + | this argument influences the return type of `method` +note: associated function defined here + --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:7:8 + | +LL | fn method(&self, x: T) -> T { + | ^^^^^^ ---- +help: change the type of the numeric literal from `u32` to `u16` + | +LL | let x: u16 = (S {}).method(0u16); + | ~~~ + +error[E0308]: arguments to this function are incorrect + --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:27:5 + | +LL | function(0u32, 8u8) + | ^^^^^^^^ ---- --- expected `bool`, found `u8` + | | + | expected `()`, found `u32` + | +help: the return type of this call is `u32` due to the type of the argument passed + --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:27:5 + | +LL | function(0u32, 8u8) + | ^^^^^^^^^----^^^^^^ + | | + | this argument influences the return type of `function` +note: function defined here + --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:1:4 + | +LL | fn function(x: T, y: bool) -> T { + | ^^^^^^^^ ---- ------- + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/typeck/issue-46112.stderr b/tests/ui/typeck/issue-46112.stderr index f488463ae3ce..8f5ff51fbe10 100644 --- a/tests/ui/typeck/issue-46112.stderr +++ b/tests/ui/typeck/issue-46112.stderr @@ -8,6 +8,13 @@ LL | fn main() { test(Ok(())); } | = note: expected enum `Option<()>` found unit type `()` +help: the type constructed contains `()` due to the type of the argument passed + --> $DIR/issue-46112.rs:9:18 + | +LL | fn main() { test(Ok(())); } + | ^^^--^ + | | + | this argument influences the type of `Ok` note: tuple variant defined here --> $SRC_DIR/core/src/result.rs:LL:COL help: try wrapping the expression in `Some` diff --git a/tests/ui/typeck/issue-84768.stderr b/tests/ui/typeck/issue-84768.stderr index 00d23389720b..09f3aee2d9ec 100644 --- a/tests/ui/typeck/issue-84768.stderr +++ b/tests/ui/typeck/issue-84768.stderr @@ -14,6 +14,13 @@ LL | ::call_once(f, 1) | = note: expected tuple `(&mut u8,)` found type `{integer}` +help: the return type of this call is `{integer}` due to the type of the argument passed + --> $DIR/issue-84768.rs:7:5 + | +LL | ::call_once(f, 1) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-^ + | | + | this argument influences the return type of `FnOnce` note: associated function defined here --> $SRC_DIR/core/src/ops/function.rs:LL:COL diff --git a/tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr b/tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr index a2fe627868ae..e85144a31ca9 100644 --- a/tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr +++ b/tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr @@ -21,6 +21,13 @@ LL | >::add(1u32, 2); | | | arguments to this function are incorrect | +help: the return type of this call is `u32` due to the type of the argument passed + --> $DIR/ufcs-qpath-self-mismatch.rs:7:5 + | +LL | >::add(1u32, 2); + | ^^^^^^^^^^^^^^^^^^^^^^^----^^^^ + | | + | this argument influences the return type of `Add` note: associated function defined here --> $SRC_DIR/core/src/ops/arith.rs:LL:COL help: change the type of the numeric literal from `u32` to `i32` @@ -36,6 +43,13 @@ LL | >::add(1, 2u32); | | | arguments to this function are incorrect | +help: the return type of this call is `u32` due to the type of the argument passed + --> $DIR/ufcs-qpath-self-mismatch.rs:9:5 + | +LL | >::add(1, 2u32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^----^ + | | + | this argument influences the return type of `Add` note: associated function defined here --> $SRC_DIR/core/src/ops/arith.rs:LL:COL help: change the type of the numeric literal from `u32` to `i32` From 138a1d26b53cab16066b0faa3846722358a2c09f Mon Sep 17 00:00:00 2001 From: Fawaz Date: Mon, 9 Jan 2023 00:17:58 -0800 Subject: [PATCH 050/105] riscv: Fix ELF header flags The previous version added both `EF_RISCV_FLOAT_ABI_DOUBLE` and `EF_RISCV_RVC` if the "D" extension was enabled on riscv64 targets. riscv32 targets were not accounted for. This patch changes this so that: - Only add `EF_RISCV_RVC` if the "C" extension is enabled - Add `EF_RISCV_FLOAT_ABI_SINGLE` if the "F" extension is enabled and the "D" extension is not - Add these ELF flags for riscv32 as well --- .../rustc_codegen_ssa/src/back/metadata.rs | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs index 51c5c375d519..5ad2744f61de 100644 --- a/compiler/rustc_codegen_ssa/src/back/metadata.rs +++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs @@ -165,11 +165,23 @@ pub(crate) fn create_object_file(sess: &Session) -> Option { - // copied from `riscv64-linux-gnu-gcc foo.c -c`, note though - // that the `+d` target feature represents whether the double - // float abi is enabled. - let e_flags = elf::EF_RISCV_RVC | elf::EF_RISCV_FLOAT_ABI_DOUBLE; + Architecture::Riscv32 | Architecture::Riscv64 => { + // Source: https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/079772828bd10933d34121117a222b4cc0ee2200/riscv-elf.adoc + let mut e_flags: u32 = 0x0; + let features = &sess.target.options.features; + // Check if compressed is enabled + if features.contains("+c") { + e_flags |= elf::EF_RISCV_RVC; + } + + // Select the appropriate floating-point ABI + if features.contains("+d") { + e_flags |= elf::EF_RISCV_FLOAT_ABI_DOUBLE; + } else if features.contains("+f") { + e_flags |= elf::EF_RISCV_FLOAT_ABI_SINGLE; + } else { + e_flags |= elf::EF_RISCV_FLOAT_ABI_SOFT; + } e_flags } _ => 0, From 4a3c072d109c0285036e544044b78b91a1fba21e Mon Sep 17 00:00:00 2001 From: Albert Larsan <74931857+albertlarsan68@users.noreply.github.com> Date: Thu, 12 Jan 2023 18:20:51 +0000 Subject: [PATCH 051/105] Ignore tests move in git blame --- .git-blame-ignore-revs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index 71adf9b00911..d20f19e60e86 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -8,3 +8,5 @@ a06baa56b95674fc626b3c3fd680d6a65357fe60 283abbf0e7d20176f76006825b5c52e9a4234e4c # format libstd/sys c34fbfaad38cf5829ef5cfe780dc9d58480adeaa +# move tests +cf2dff2b1e3fa55fa5415d524200070d0d7aacfe From 4949fb0419a58e937b5098d76e89dff4c91f3f7e Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Thu, 12 Jan 2023 22:55:58 -0800 Subject: [PATCH 052/105] Stop having unused lifetimes on some `impl`s --- library/std/src/path.rs | 58 ++++++++++++++++++++--------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/library/std/src/path.rs b/library/std/src/path.rs index 82d68369312f..a2dcee0e2bdb 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -3177,9 +3177,9 @@ impl<'a> IntoIterator for &'a Path { } macro_rules! impl_cmp { - ($lhs:ty, $rhs: ty) => { + (<$($life:lifetime),*> $lhs:ty, $rhs: ty) => { #[stable(feature = "partialeq_path", since = "1.6.0")] - impl<'a, 'b> PartialEq<$rhs> for $lhs { + impl<$($life),*> PartialEq<$rhs> for $lhs { #[inline] fn eq(&self, other: &$rhs) -> bool { ::eq(self, other) @@ -3187,7 +3187,7 @@ macro_rules! impl_cmp { } #[stable(feature = "partialeq_path", since = "1.6.0")] - impl<'a, 'b> PartialEq<$lhs> for $rhs { + impl<$($life),*> PartialEq<$lhs> for $rhs { #[inline] fn eq(&self, other: &$lhs) -> bool { ::eq(self, other) @@ -3195,7 +3195,7 @@ macro_rules! impl_cmp { } #[stable(feature = "cmp_path", since = "1.8.0")] - impl<'a, 'b> PartialOrd<$rhs> for $lhs { + impl<$($life),*> PartialOrd<$rhs> for $lhs { #[inline] fn partial_cmp(&self, other: &$rhs) -> Option { ::partial_cmp(self, other) @@ -3203,7 +3203,7 @@ macro_rules! impl_cmp { } #[stable(feature = "cmp_path", since = "1.8.0")] - impl<'a, 'b> PartialOrd<$lhs> for $rhs { + impl<$($life),*> PartialOrd<$lhs> for $rhs { #[inline] fn partial_cmp(&self, other: &$lhs) -> Option { ::partial_cmp(self, other) @@ -3212,16 +3212,16 @@ macro_rules! impl_cmp { }; } -impl_cmp!(PathBuf, Path); -impl_cmp!(PathBuf, &'a Path); -impl_cmp!(Cow<'a, Path>, Path); -impl_cmp!(Cow<'a, Path>, &'b Path); -impl_cmp!(Cow<'a, Path>, PathBuf); +impl_cmp!(<> PathBuf, Path); +impl_cmp!(<'a> PathBuf, &'a Path); +impl_cmp!(<'a> Cow<'a, Path>, Path); +impl_cmp!(<'a, 'b> Cow<'a, Path>, &'b Path); +impl_cmp!(<'a> Cow<'a, Path>, PathBuf); macro_rules! impl_cmp_os_str { - ($lhs:ty, $rhs: ty) => { + (<$($life:lifetime),*> $lhs:ty, $rhs: ty) => { #[stable(feature = "cmp_path", since = "1.8.0")] - impl<'a, 'b> PartialEq<$rhs> for $lhs { + impl<$($life),*> PartialEq<$rhs> for $lhs { #[inline] fn eq(&self, other: &$rhs) -> bool { ::eq(self, other.as_ref()) @@ -3229,7 +3229,7 @@ macro_rules! impl_cmp_os_str { } #[stable(feature = "cmp_path", since = "1.8.0")] - impl<'a, 'b> PartialEq<$lhs> for $rhs { + impl<$($life),*> PartialEq<$lhs> for $rhs { #[inline] fn eq(&self, other: &$lhs) -> bool { ::eq(self.as_ref(), other) @@ -3237,7 +3237,7 @@ macro_rules! impl_cmp_os_str { } #[stable(feature = "cmp_path", since = "1.8.0")] - impl<'a, 'b> PartialOrd<$rhs> for $lhs { + impl<$($life),*> PartialOrd<$rhs> for $lhs { #[inline] fn partial_cmp(&self, other: &$rhs) -> Option { ::partial_cmp(self, other.as_ref()) @@ -3245,7 +3245,7 @@ macro_rules! impl_cmp_os_str { } #[stable(feature = "cmp_path", since = "1.8.0")] - impl<'a, 'b> PartialOrd<$lhs> for $rhs { + impl<$($life),*> PartialOrd<$lhs> for $rhs { #[inline] fn partial_cmp(&self, other: &$lhs) -> Option { ::partial_cmp(self.as_ref(), other) @@ -3254,20 +3254,20 @@ macro_rules! impl_cmp_os_str { }; } -impl_cmp_os_str!(PathBuf, OsStr); -impl_cmp_os_str!(PathBuf, &'a OsStr); -impl_cmp_os_str!(PathBuf, Cow<'a, OsStr>); -impl_cmp_os_str!(PathBuf, OsString); -impl_cmp_os_str!(Path, OsStr); -impl_cmp_os_str!(Path, &'a OsStr); -impl_cmp_os_str!(Path, Cow<'a, OsStr>); -impl_cmp_os_str!(Path, OsString); -impl_cmp_os_str!(&'a Path, OsStr); -impl_cmp_os_str!(&'a Path, Cow<'b, OsStr>); -impl_cmp_os_str!(&'a Path, OsString); -impl_cmp_os_str!(Cow<'a, Path>, OsStr); -impl_cmp_os_str!(Cow<'a, Path>, &'b OsStr); -impl_cmp_os_str!(Cow<'a, Path>, OsString); +impl_cmp_os_str!(<> PathBuf, OsStr); +impl_cmp_os_str!(<'a> PathBuf, &'a OsStr); +impl_cmp_os_str!(<'a> PathBuf, Cow<'a, OsStr>); +impl_cmp_os_str!(<> PathBuf, OsString); +impl_cmp_os_str!(<> Path, OsStr); +impl_cmp_os_str!(<'a> Path, &'a OsStr); +impl_cmp_os_str!(<'a> Path, Cow<'a, OsStr>); +impl_cmp_os_str!(<> Path, OsString); +impl_cmp_os_str!(<'a> &'a Path, OsStr); +impl_cmp_os_str!(<'a, 'b> &'a Path, Cow<'b, OsStr>); +impl_cmp_os_str!(<'a> &'a Path, OsString); +impl_cmp_os_str!(<'a> Cow<'a, Path>, OsStr); +impl_cmp_os_str!(<'a, 'b> Cow<'a, Path>, &'b OsStr); +impl_cmp_os_str!(<'a> Cow<'a, Path>, OsString); #[stable(since = "1.7.0", feature = "strip_prefix")] impl fmt::Display for StripPrefixError { From 549ece703393bf78c7567605862496435cae7202 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 10 Jan 2023 13:57:42 +0100 Subject: [PATCH 053/105] Warn when using panic-strategy abort for proc-macro crates --- compiler/rustc_error_messages/locales/en-US/interface.ftl | 3 +++ compiler/rustc_interface/Cargo.toml | 1 + compiler/rustc_interface/src/errors.rs | 4 ++++ compiler/rustc_interface/src/passes.rs | 8 +++++++- tests/ui/proc-macro/panic-abort.rs | 4 ++++ tests/ui/proc-macro/panic-abort.stderr | 4 ++++ 6 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 tests/ui/proc-macro/panic-abort.rs create mode 100644 tests/ui/proc-macro/panic-abort.stderr diff --git a/compiler/rustc_error_messages/locales/en-US/interface.ftl b/compiler/rustc_error_messages/locales/en-US/interface.ftl index bbcb8fc28cff..688b04472226 100644 --- a/compiler/rustc_error_messages/locales/en-US/interface.ftl +++ b/compiler/rustc_error_messages/locales/en-US/interface.ftl @@ -41,3 +41,6 @@ interface_rustc_error_unexpected_annotation = interface_failed_writing_file = failed to write file {$path}: {$error}" + +interface_proc_macro_crate_panic_abort = + building proc macro crate with `panic=abort` may crash the compiler should the proc-macro panic diff --git a/compiler/rustc_interface/Cargo.toml b/compiler/rustc_interface/Cargo.toml index e67dec31dcee..f817c5bc1cd7 100644 --- a/compiler/rustc_interface/Cargo.toml +++ b/compiler/rustc_interface/Cargo.toml @@ -45,6 +45,7 @@ rustc_plugin_impl = { path = "../rustc_plugin_impl" } rustc_privacy = { path = "../rustc_privacy" } rustc_query_impl = { path = "../rustc_query_impl" } rustc_resolve = { path = "../rustc_resolve" } +rustc_target = { path = "../rustc_target" } rustc_trait_selection = { path = "../rustc_trait_selection" } rustc_ty_utils = { path = "../rustc_ty_utils" } diff --git a/compiler/rustc_interface/src/errors.rs b/compiler/rustc_interface/src/errors.rs index f5135c78dc83..15d7e977bbe8 100644 --- a/compiler/rustc_interface/src/errors.rs +++ b/compiler/rustc_interface/src/errors.rs @@ -87,3 +87,7 @@ pub struct FailedWritingFile<'a> { pub path: &'a Path, pub error: io::Error, } + +#[derive(Diagnostic)] +#[diag(interface_proc_macro_crate_panic_abort)] +pub struct ProcMacroCratePanicAbort; diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 86d56385bc96..c8085e91dfae 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -1,7 +1,8 @@ use crate::errors::{ CantEmitMIR, EmojiIdentifier, ErrorWritingDependencies, FerrisIdentifier, GeneratedFileConflictsWithDirectory, InputFileWouldBeOverWritten, MixedBinCrate, - MixedProcMacroCrate, OutDirError, ProcMacroDocWithoutArg, TempsDirError, + MixedProcMacroCrate, OutDirError, ProcMacroCratePanicAbort, ProcMacroDocWithoutArg, + TempsDirError, }; use crate::interface::{Compiler, Result}; use crate::proc_macro_decls; @@ -36,6 +37,7 @@ use rustc_session::search_paths::PathKind; use rustc_session::{Limit, Session}; use rustc_span::symbol::{sym, Symbol}; use rustc_span::FileName; +use rustc_target::spec::PanicStrategy; use rustc_trait_selection::traits; use std::any::Any; @@ -380,6 +382,10 @@ pub fn configure_and_expand( } } + if is_proc_macro_crate && sess.panic_strategy() == PanicStrategy::Abort { + sess.emit_warning(ProcMacroCratePanicAbort); + } + // For backwards compatibility, we don't try to run proc macro injection // if rustdoc is run on a proc macro crate without '--crate-type proc-macro' being // specified. This should only affect users who manually invoke 'rustdoc', as diff --git a/tests/ui/proc-macro/panic-abort.rs b/tests/ui/proc-macro/panic-abort.rs new file mode 100644 index 000000000000..ad312a875e39 --- /dev/null +++ b/tests/ui/proc-macro/panic-abort.rs @@ -0,0 +1,4 @@ +// error-pattern: building proc macro crate with `panic=abort` may crash the compiler should the proc-macro panic +// compile-flags: --crate-type proc-macro -Cpanic=abort +// force-host +// check-pass diff --git a/tests/ui/proc-macro/panic-abort.stderr b/tests/ui/proc-macro/panic-abort.stderr new file mode 100644 index 000000000000..a6e18614f8f0 --- /dev/null +++ b/tests/ui/proc-macro/panic-abort.stderr @@ -0,0 +1,4 @@ +warning: building proc macro crate with `panic=abort` may crash the compiler should the proc-macro panic + +warning: 1 warning emitted + From 184057bd9d59666a6ea532f8d27b678dfaec1e4d Mon Sep 17 00:00:00 2001 From: Albert Larsan <74931857+albertlarsan68@users.noreply.github.com> Date: Thu, 12 Jan 2023 17:17:20 +0100 Subject: [PATCH 054/105] Remove stale reference to the test suite location --- src/README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/README.md b/src/README.md index 90ab80269708..7b357da2ffc4 100644 --- a/src/README.md +++ b/src/README.md @@ -1,8 +1,7 @@ -This directory contains the source code of the rust project, including: +This directory contains some source code for the Rust project, including: -- The test suite - The bootstrapping build system -- Various submodules for tools, like cargo, etc. +- Various submodules for tools, like cargo, tidy, etc. For more information on how various parts of the compiler work, see the [rustc dev guide]. From 60cc7783dabeb349c7eacb100f2a454b4546bfca Mon Sep 17 00:00:00 2001 From: klensy Date: Thu, 12 Jan 2023 19:47:53 +0300 Subject: [PATCH 055/105] evade clones --- src/librustdoc/html/render/mod.rs | 4 ++-- src/librustdoc/html/render/print_item.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 8bccf68029aa..03a960da75fb 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -2769,8 +2769,8 @@ fn collect_paths_for_type(first_ty: clean::Type, cache: &Cache) -> Vec { let mut work = VecDeque::new(); let mut process_path = |did: DefId| { - let get_extern = || cache.external_paths.get(&did).map(|s| s.0.clone()); - let fqp = cache.exact_paths.get(&did).cloned().or_else(get_extern); + let get_extern = || cache.external_paths.get(&did).map(|s| &s.0); + let fqp = cache.exact_paths.get(&did).or_else(get_extern); if let Some(path) = fqp { out.push(join_with_double_colon(&path)); diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index c16d6477fc37..73cb135bbf8c 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -1027,8 +1027,8 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: .chain(std::iter::once("implementors")) .collect(); if let Some(did) = it.item_id.as_def_id() && - let get_extern = { || cache.external_paths.get(&did).map(|s| s.0.clone()) } && - let Some(fqp) = cache.exact_paths.get(&did).cloned().or_else(get_extern) { + let get_extern = { || cache.external_paths.get(&did).map(|s| &s.0) } && + let Some(fqp) = cache.exact_paths.get(&did).or_else(get_extern) { js_src_path.extend(fqp[..fqp.len() - 1].iter().copied()); js_src_path.push_fmt(format_args!("{}.{}.js", it.type_(), fqp.last().unwrap())); } else { From 4e1258c6b6f67df77157c7aea0f800854da99294 Mon Sep 17 00:00:00 2001 From: klensy Date: Fri, 13 Jan 2023 15:39:16 +0300 Subject: [PATCH 056/105] IndexItem.name String -> Symbol --- src/librustdoc/formats/cache.rs | 9 +++++---- src/librustdoc/html/render/mod.rs | 2 +- src/librustdoc/html/render/search_index.rs | 8 ++++---- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index d027fb6e8763..3149c22b8e55 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -242,7 +242,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { } // Index this method for searching later on. - if let Some(ref s) = item.name.or_else(|| { + if let Some(s) = item.name.or_else(|| { if item.is_stripped() { None } else if let clean::ImportItem(ref i) = *item.kind && @@ -317,14 +317,15 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { short_markdown_summary(x.as_str(), &item.link_names(self.cache)) }); let ty = item.type_(); - let name = s.to_string(); - if ty != ItemType::StructField || u16::from_str_radix(&name, 10).is_err() { + if ty != ItemType::StructField + || u16::from_str_radix(s.as_str(), 10).is_err() + { // In case this is a field from a tuple struct, we don't add it into // the search index because its name is something like "0", which is // not useful for rustdoc search. self.cache.search_index.push(IndexItem { ty, - name, + name: s, path: join_with_double_colon(path), desc, parent, diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 03a960da75fb..8d018d45c106 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -100,7 +100,7 @@ pub(crate) fn ensure_trailing_slash(v: &str) -> impl fmt::Display + '_ { #[derive(Debug)] pub(crate) struct IndexItem { pub(crate) ty: ItemType, - pub(crate) name: String, + pub(crate) name: Symbol, pub(crate) path: String, pub(crate) desc: String, pub(crate) parent: Option, diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index bc74d9cf9697..b0ae0dae0d6d 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -35,7 +35,7 @@ pub(crate) fn build_index<'tcx>( .map_or_else(String::new, |s| short_markdown_summary(&s, &item.link_names(cache))); cache.search_index.push(IndexItem { ty: item.type_(), - name: item.name.unwrap().to_string(), + name: item.name.unwrap(), path: join_with_double_colon(&fqp[..fqp.len() - 1]), desc, parent: Some(parent), @@ -58,8 +58,8 @@ pub(crate) fn build_index<'tcx>( // Sort search index items. This improves the compressibility of the search index. cache.search_index.sort_unstable_by(|k1, k2| { // `sort_unstable_by_key` produces lifetime errors - let k1 = (&k1.path, &k1.name, &k1.ty, &k1.parent); - let k2 = (&k2.path, &k2.name, &k2.ty, &k2.parent); + let k1 = (&k1.path, k1.name.as_str(), &k1.ty, &k1.parent); + let k2 = (&k2.path, k2.name.as_str(), &k2.ty, &k2.parent); std::cmp::Ord::cmp(&k1, &k2) }); @@ -240,7 +240,7 @@ pub(crate) fn build_index<'tcx>( )?; crate_data.serialize_field( "n", - &self.items.iter().map(|item| &item.name).collect::>(), + &self.items.iter().map(|item| item.name.as_str()).collect::>(), )?; crate_data.serialize_field( "q", From cda6efeeb8d6e6155b776c7fedd32cfeeb37233e Mon Sep 17 00:00:00 2001 From: klensy Date: Fri, 13 Jan 2023 17:33:07 +0300 Subject: [PATCH 057/105] generate_macro_def_id_path: don't eagerly stringify Symbols --- src/librustdoc/html/format.rs | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 5ad24bf26813..83fde5fd7205 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -569,7 +569,7 @@ fn generate_macro_def_id_path( root_path: Option<&str>, ) -> Result<(String, ItemType, Vec), HrefError> { let tcx = cx.shared.tcx; - let crate_name = tcx.crate_name(def_id.krate).to_string(); + let crate_name = tcx.crate_name(def_id.krate); let cache = cx.cache(); let fqp: Vec = tcx @@ -584,7 +584,7 @@ fn generate_macro_def_id_path( } }) .collect(); - let mut relative = fqp.iter().map(|elem| elem.to_string()); + let mut relative = fqp.iter().copied(); let cstore = CStore::from_tcx(tcx); // We need this to prevent a `panic` when this function is used from intra doc links... if !cstore.has_crate_data(def_id.krate) { @@ -602,9 +602,9 @@ fn generate_macro_def_id_path( }; let mut path = if is_macro_2 { - once(crate_name.clone()).chain(relative).collect() + once(crate_name).chain(relative).collect() } else { - vec![crate_name.clone(), relative.next_back().unwrap()] + vec![crate_name, relative.next_back().unwrap()] }; if path.len() < 2 { // The minimum we can have is the crate name followed by the macro name. If shorter, then @@ -614,17 +614,22 @@ fn generate_macro_def_id_path( } if let Some(last) = path.last_mut() { - *last = format!("macro.{}.html", last); + *last = Symbol::intern(&format!("macro.{}.html", last.as_str())); } let url = match cache.extern_locations[&def_id.krate] { ExternalLocation::Remote(ref s) => { // `ExternalLocation::Remote` always end with a `/`. - format!("{}{}", s, path.join("/")) + format!("{}{}", s, path.iter().map(|p| p.as_str()).join("/")) } ExternalLocation::Local => { // `root_path` always end with a `/`. - format!("{}{}/{}", root_path.unwrap_or(""), crate_name, path.join("/")) + format!( + "{}{}/{}", + root_path.unwrap_or(""), + crate_name, + path.iter().map(|p| p.as_str()).join("/") + ) } ExternalLocation::Unknown => { debug!("crate {} not in cache when linkifying macros", crate_name); From 81b637b6f2b410e81fb47919c8b3817979ec7073 Mon Sep 17 00:00:00 2001 From: klensy Date: Fri, 13 Jan 2023 17:54:16 +0300 Subject: [PATCH 058/105] fmt_type: don't alloc const String, use &str instead --- src/librustdoc/html/format.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 83fde5fd7205..006076baf725 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -1055,7 +1055,7 @@ fn fmt_type<'cx>( _ => String::new(), }; let m = mutability.print_with_space(); - let amp = if f.alternate() { "&".to_string() } else { "&".to_string() }; + let amp = if f.alternate() { "&" } else { "&" }; match **ty { clean::DynTrait(ref bounds, ref trait_lt) if bounds.len() > 1 || trait_lt.is_some() => From ffb2e843196060820130134a0815eccf198b487f Mon Sep 17 00:00:00 2001 From: klensy Date: Fri, 13 Jan 2023 18:05:16 +0300 Subject: [PATCH 059/105] Playground.crate_name String -> Symbol --- src/librustdoc/html/markdown.rs | 6 +++--- src/librustdoc/html/render/context.rs | 5 ++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index aeaee524fd45..4ff67fe1551d 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -30,7 +30,7 @@ use rustc_hir::def_id::DefId; use rustc_hir::HirId; use rustc_middle::ty::TyCtxt; use rustc_span::edition::Edition; -use rustc_span::Span; +use rustc_span::{Span, Symbol}; use once_cell::sync::Lazy; use std::borrow::Cow; @@ -198,7 +198,7 @@ fn slugify(c: char) -> Option { #[derive(Clone, Debug)] pub struct Playground { - pub crate_name: Option, + pub crate_name: Option, pub url: String, } @@ -290,7 +290,7 @@ impl<'a, I: Iterator>> Iterator for CodeBlocks<'_, 'a, I> { .map(|l| map_line(l).for_code()) .intersperse("\n".into()) .collect::(); - let krate = krate.as_ref().map(|s| &**s); + let krate = krate.as_ref().map(|s| s.as_str()); let (test, _, _) = doctest::make_test(&test, krate, false, &Default::default(), edition, None); let channel = if test.contains("#![feature(") { "&version=nightly" } else { "" }; diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index c8899ee62b5f..9f266568769c 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -464,8 +464,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { // If user passed in `--playground-url` arg, we fill in crate name here let mut playground = None; if let Some(url) = playground_url { - playground = - Some(markdown::Playground { crate_name: Some(krate.name(tcx).to_string()), url }); + playground = Some(markdown::Playground { crate_name: Some(krate.name(tcx)), url }); } let mut layout = layout::Layout { logo: String::new(), @@ -491,7 +490,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { } (sym::html_playground_url, Some(s)) => { playground = Some(markdown::Playground { - crate_name: Some(krate.name(tcx).to_string()), + crate_name: Some(krate.name(tcx)), url: s.to_string(), }); } From 8998bd35ed2ebd5889f7726e971e95e642c3fdca Mon Sep 17 00:00:00 2001 From: klensy Date: Fri, 13 Jan 2023 18:27:30 +0300 Subject: [PATCH 060/105] CrateData: don't allocate String when Serialize, &str is enough --- src/librustdoc/html/render/search_index.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index b0ae0dae0d6d..c64349f413ce 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -299,7 +299,7 @@ pub(crate) fn build_index<'tcx>( )?; crate_data.serialize_field( "p", - &self.paths.iter().map(|(it, s)| (it, s.to_string())).collect::>(), + &self.paths.iter().map(|(it, s)| (it, s.as_str())).collect::>(), )?; if has_aliases { crate_data.serialize_field("a", &self.aliases)?; From 4aca7beab0fd7e45dc4f901db5aa10c46ba9cf1b Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 8 Dec 2022 09:39:48 +0000 Subject: [PATCH 061/105] Remove redundant session field --- compiler/rustc_resolve/src/lib.rs | 6 ++++- src/librustdoc/lib.rs | 3 --- .../passes/collect_intra_doc_links/early.rs | 22 +++++++++---------- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 2182b7369377..e5c9169358d3 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1133,7 +1133,7 @@ impl<'a, 'b> DefIdTree for &'a Resolver<'b> { } } -impl Resolver<'_> { +impl<'a> Resolver<'a> { fn opt_local_def_id(&self, node: NodeId) -> Option { self.node_id_to_def_id.get(&node).copied() } @@ -1190,6 +1190,10 @@ impl Resolver<'_> { self.cstore().item_generics_num_lifetimes(def_id, self.session) } } + + pub fn sess(&self) -> &'a Session { + self.session + } } impl<'a> Resolver<'a> { diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index ed77de200a9b..86454e1f2eb7 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -772,7 +772,6 @@ fn main_args(at_args: &[String]) -> MainResult { let crate_version = options.crate_version.clone(); let output_format = options.output_format; - let externs = options.externs.clone(); let scrape_examples_options = options.scrape_examples_options.clone(); let bin_crate = options.bin_crate; @@ -805,9 +804,7 @@ fn main_args(at_args: &[String]) -> MainResult { let resolver_caches = resolver.borrow_mut().access(|resolver| { collect_intra_doc_links::early_resolve_intra_doc_links( resolver, - sess, krate, - externs, render_options.document_private, ) }); diff --git a/src/librustdoc/passes/collect_intra_doc_links/early.rs b/src/librustdoc/passes/collect_intra_doc_links/early.rs index 1b373cfe5bb7..42677bd84974 100644 --- a/src/librustdoc/passes/collect_intra_doc_links/early.rs +++ b/src/librustdoc/passes/collect_intra_doc_links/early.rs @@ -12,8 +12,6 @@ use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, CRATE_DEF_ID}; use rustc_hir::TraitCandidate; use rustc_middle::ty::{DefIdTree, Visibility}; use rustc_resolve::{ParentScope, Resolver}; -use rustc_session::config::Externs; -use rustc_session::Session; use rustc_span::symbol::sym; use rustc_span::{Symbol, SyntaxContext}; @@ -22,16 +20,13 @@ use std::mem; pub(crate) fn early_resolve_intra_doc_links( resolver: &mut Resolver<'_>, - sess: &Session, krate: &ast::Crate, - externs: Externs, document_private_items: bool, ) -> ResolverCaches { let parent_scope = ParentScope::module(resolver.expect_module(CRATE_DEF_ID.to_def_id()), resolver); let mut link_resolver = EarlyDocLinkResolver { resolver, - sess, parent_scope, visited_mods: Default::default(), markdown_links: Default::default(), @@ -52,7 +47,9 @@ pub(crate) fn early_resolve_intra_doc_links( // the known necessary crates. Load them all unconditionally until we find a way to fix this. // DO NOT REMOVE THIS without first testing on the reproducer in // https://github.com/jyn514/objr/commit/edcee7b8124abf0e4c63873e8422ff81beb11ebb - for (extern_name, _) in externs.iter().filter(|(_, entry)| entry.add_prelude) { + for (extern_name, _) in + link_resolver.resolver.sess().opts.externs.iter().filter(|(_, entry)| entry.add_prelude) + { link_resolver.resolver.resolve_rustdoc_path(extern_name, TypeNS, parent_scope); } @@ -73,7 +70,6 @@ fn doc_attrs<'a>(attrs: impl Iterator) -> Attributes struct EarlyDocLinkResolver<'r, 'ra> { resolver: &'r mut Resolver<'ra>, - sess: &'r Session, parent_scope: ParentScope<'ra>, visited_mods: DefIdSet, markdown_links: FxHashMap>, @@ -166,7 +162,7 @@ impl<'ra> EarlyDocLinkResolver<'_, 'ra> { fn resolve_doc_links_extern_impl(&mut self, def_id: DefId, is_inherent: bool) { self.resolve_doc_links_extern_outer_fixme(def_id, def_id); let assoc_item_def_ids = Vec::from_iter( - self.resolver.cstore().associated_item_def_ids_untracked(def_id, self.sess), + self.resolver.cstore().associated_item_def_ids_untracked(def_id, self.resolver.sess()), ); for assoc_def_id in assoc_item_def_ids { if !is_inherent || self.resolver.cstore().visibility_untracked(assoc_def_id).is_public() @@ -191,7 +187,9 @@ impl<'ra> EarlyDocLinkResolver<'_, 'ra> { if !self.resolver.cstore().may_have_doc_links_untracked(def_id) { return; } - let attrs = Vec::from_iter(self.resolver.cstore().item_attrs_untracked(def_id, self.sess)); + let attrs = Vec::from_iter( + self.resolver.cstore().item_attrs_untracked(def_id, self.resolver.sess()), + ); let parent_scope = ParentScope::module( self.resolver.get_nearest_non_block_module( self.resolver.opt_parent(scope_id).unwrap_or(scope_id), @@ -205,7 +203,9 @@ impl<'ra> EarlyDocLinkResolver<'_, 'ra> { if !self.resolver.cstore().may_have_doc_links_untracked(def_id) { return; } - let attrs = Vec::from_iter(self.resolver.cstore().item_attrs_untracked(def_id, self.sess)); + let attrs = Vec::from_iter( + self.resolver.cstore().item_attrs_untracked(def_id, self.resolver.sess()), + ); let parent_scope = ParentScope::module(self.resolver.expect_module(def_id), self.resolver); self.resolve_doc_links(doc_attrs(attrs.iter()), parent_scope); } @@ -321,7 +321,7 @@ impl<'ra> EarlyDocLinkResolver<'_, 'ra> { let field_def_ids = Vec::from_iter( self.resolver .cstore() - .associated_item_def_ids_untracked(def_id, self.sess), + .associated_item_def_ids_untracked(def_id, self.resolver.sess()), ); for field_def_id in field_def_ids { self.resolve_doc_links_extern_outer(field_def_id, scope_id); From 3bc2970a2e5f80f04ac2c1b1c1e4ec06a001f151 Mon Sep 17 00:00:00 2001 From: Jonathan Schwender Date: Thu, 5 Jan 2023 14:14:23 +0100 Subject: [PATCH 062/105] Improve linker-flavor detection Linker drivers such as gcc, clang or lld often have a version postfix, e.g clang-12. The previous logic would not account for this and would fall back to guessing the linker flavor to be the default linker flavor for the target, which causes linker errors when this is not the case. By accounting for the possible version postfix and also considering g++ and clang++, we considerably reduce the amount of times the fallback guess has to be used. To simplify matching check for a version postfix and match against the linker stem without any version postfix. In contrast to gcc, clang supports all architectures in one binary. This means there are no variants like `aarch64-linux-gnu-clang` and there is no need to check for `-clang` variants. --- compiler/rustc_codegen_ssa/src/back/link.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 8ca7103ed482..342abf81f6a7 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1231,12 +1231,21 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) { sess.emit_fatal(errors::LinkerFileStem); }); + // Remove any version postfix. + let stem = stem + .rsplit_once('-') + .and_then(|(lhs, rhs)| rhs.chars().all(char::is_numeric).then_some(lhs)) + .unwrap_or(stem); + + // GCC can have an optional target prefix. let flavor = if stem == "emcc" { LinkerFlavor::EmCc } else if stem == "gcc" || stem.ends_with("-gcc") + || stem == "g++" + || stem.ends_with("-g++") || stem == "clang" - || stem.ends_with("-clang") + || stem == "clang++" { LinkerFlavor::from_cli(LinkerFlavorCli::Gcc, &sess.target) } else if stem == "wasm-ld" || stem.ends_with("-wasm-ld") { From 39b90a5f6ee2183ac664ea91c4fb341695e4de37 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Fri, 13 Jan 2023 10:09:25 -0700 Subject: [PATCH 063/105] rustdoc: remove unnecessary DOM class `h1.fqn` It's misleading. The main heading sometimes isn't an fully qualified name at all. It's also redundant. It's always a child of `div.main-heading`, so just use that. --- src/librustdoc/html/render/context.rs | 4 ++-- src/librustdoc/html/render/mod.rs | 4 ++-- src/librustdoc/html/render/write_shared.rs | 2 +- src/librustdoc/html/static/css/rustdoc.css | 2 +- src/librustdoc/html/static/js/main.js | 2 +- src/librustdoc/html/templates/print_item.html | 2 +- tests/rustdoc-gui/anchors.goml | 20 +++++++++---------- tests/rustdoc-gui/headings.goml | 8 ++++---- .../search-result-go-to-first.goml | 6 +++--- tests/rustdoc-gui/toggle-click-deadspace.goml | 2 +- tests/rustdoc/index-page.rs | 2 +- tests/rustdoc/keyword.rs | 2 +- tests/rustdoc/primitive-reference.rs | 2 +- tests/rustdoc/primitive-slice-auto-trait.rs | 2 +- tests/rustdoc/primitive-tuple-auto-trait.rs | 2 +- tests/rustdoc/primitive-unit-auto-trait.rs | 2 +- tests/rustdoc/primitive.rs | 2 +- 17 files changed, 33 insertions(+), 33 deletions(-) diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index c8899ee62b5f..20b51336c350 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -639,7 +639,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { write!( buf, "

\ -

Rustdoc settings

\ +

Rustdoc settings

\ \
\ Back\ @@ -677,7 +677,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { write!( buf, "
\ -

Rustdoc help

\ +

Rustdoc help

\ \
\ Back\ diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 8bccf68029aa..5788a9aacca1 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -364,7 +364,7 @@ impl AllTypes { } } - f.write_str("

List of all items

"); + f.write_str("

List of all items

"); // Note: print_entries does not escape the title, because we know the current set of titles // doesn't require escaping. print_entries(f, &self.structs, ItemSection::Structs); @@ -394,7 +394,7 @@ fn scrape_examples_help(shared: &SharedContext<'_>) -> String { let mut ids = IdMap::default(); format!( "
\ -

About scraped examples

\ +

About scraped examples

\
\
{}
", Markdown { diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index 3ea4c4bea882..ca3e9916487a 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -345,7 +345,7 @@ if (typeof exports !== 'undefined') {exports.searchIndex = searchIndex}; }; let content = format!( - "

List of all crates

    {}
", + "

List of all crates

    {}
", krates .iter() .map(|s| { diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index b2fa6e82acce..32c98c04423a 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -139,7 +139,7 @@ h1, h2, h3, h4 { .docblock > h6:first-child { margin-top: 0; } -h1.fqn { +.main-heading h1 { margin: 0; padding: 0; flex-grow: 1; diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 51aee8e7c899..29af739cf9dd 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -526,7 +526,7 @@ function loadCss(cssUrl) { } let currentNbImpls = implementors.getElementsByClassName("impl").length; - const traitName = document.querySelector("h1.fqn > .trait").textContent; + const traitName = document.querySelector(".main-heading h1 > .trait").textContent; const baseIdName = "impl-" + traitName + "-"; const libs = Object.getOwnPropertyNames(imp); // We don't want to include impls from this JS file, when the HTML already has them. diff --git a/src/librustdoc/html/templates/print_item.html b/src/librustdoc/html/templates/print_item.html index 611d124d4b91..ee2880bf6d19 100644 --- a/src/librustdoc/html/templates/print_item.html +++ b/src/librustdoc/html/templates/print_item.html @@ -1,5 +1,5 @@
{#- -#} -

{#- -#} +

{#- -#} {{-typ-}} {#- The breadcrumbs of the item path, like std::string -#} {%- for component in path_components -%} diff --git a/tests/rustdoc-gui/anchors.goml b/tests/rustdoc-gui/anchors.goml index c9b53a1a0f76..85cb72274208 100644 --- a/tests/rustdoc-gui/anchors.goml +++ b/tests/rustdoc-gui/anchors.goml @@ -2,7 +2,7 @@ define-function: ( "check-colors", - (theme, main_color, title_color, fqn_color, fqn_type_color, src_link_color, sidebar_link_color), + (theme, main_color, title_color, main_heading_color, main_heading_type_color, src_link_color, sidebar_link_color), block { goto: "file://" + |DOC_PATH| + "/staged_api/struct.Foo.html" // This is needed to ensure that the text color is computed. @@ -14,8 +14,8 @@ define-function: ( reload: assert-css: ("#toggle-all-docs", {"color": |main_color|}) - assert-css: (".fqn a:nth-of-type(1)", {"color": |fqn_color|}) - assert-css: (".fqn a:nth-of-type(2)", {"color": |fqn_type_color|}) + assert-css: (".main-heading h1 a:nth-of-type(1)", {"color": |main_heading_color|}) + assert-css: (".main-heading a:nth-of-type(2)", {"color": |main_heading_type_color|}) assert-css: ( ".rightside .srclink", {"color": |src_link_color|, "text-decoration": "none solid " + |src_link_color|}, @@ -57,7 +57,7 @@ define-function: ( assert-css: ("#top-doc-prose-title", {"color": |title_color|}) assert-css: (".sidebar a", {"color": |sidebar_link_color|}) - assert-css: ("h1.fqn a", {"color": |title_color|}) + assert-css: (".main-heading h1 a", {"color": |title_color|}) // We move the cursor over the "Implementations" title so the anchor is displayed. move-cursor-to: "h2#implementations" @@ -77,8 +77,8 @@ call-function: ( "theme": "ayu", "main_color": "rgb(197, 197, 197)", "title_color": "rgb(255, 255, 255)", - "fqn_color": "rgb(255, 255, 255)", - "fqn_type_color": "rgb(255, 160, 165)", + "main_heading_color": "rgb(255, 255, 255)", + "main_heading_type_color": "rgb(255, 160, 165)", "src_link_color": "rgb(57, 175, 215)", "sidebar_link_color": "rgb(83, 177, 219)", }, @@ -89,8 +89,8 @@ call-function: ( "theme": "dark", "main_color": "rgb(221, 221, 221)", "title_color": "rgb(221, 221, 221)", - "fqn_color": "rgb(221, 221, 221)", - "fqn_type_color": "rgb(45, 191, 184)", + "main_heading_color": "rgb(221, 221, 221)", + "main_heading_type_color": "rgb(45, 191, 184)", "src_link_color": "rgb(210, 153, 29)", "sidebar_link_color": "rgb(253, 191, 53)", }, @@ -101,8 +101,8 @@ call-function: ( "theme": "light", "main_color": "rgb(0, 0, 0)", "title_color": "rgb(0, 0, 0)", - "fqn_color": "rgb(0, 0, 0)", - "fqn_type_color": "rgb(173, 55, 138)", + "main_heading_color": "rgb(0, 0, 0)", + "main_heading_type_color": "rgb(173, 55, 138)", "src_link_color": "rgb(56, 115, 173)", "sidebar_link_color": "rgb(53, 109, 164)", }, diff --git a/tests/rustdoc-gui/headings.goml b/tests/rustdoc-gui/headings.goml index 45b3fee26e41..e4ba5f1246d9 100644 --- a/tests/rustdoc-gui/headings.goml +++ b/tests/rustdoc-gui/headings.goml @@ -13,7 +13,7 @@ // 14px 0.875rem goto: "file://" + |DOC_PATH| + "/test_docs/struct.HeavilyDocumentedStruct.html" -assert-css: ("h1.fqn", {"font-size": "24px"}) +assert-css: (".main-heading h1", {"font-size": "24px"}) assert-css: ("h2#top-doc-prose-title", {"font-size": "22px"}) assert-css: ("h2#top-doc-prose-title", {"border-bottom-width": "1px"}) @@ -52,7 +52,7 @@ assert-css: ("h6#sub-sub-heading-for-struct-impl-item-doc", {"font-size": "14px" goto: "file://" + |DOC_PATH| + "/test_docs/enum.HeavilyDocumentedEnum.html" -assert-css: ("h1.fqn", {"font-size": "24px"}) +assert-css: (".main-heading h1", {"font-size": "24px"}) assert-css: ("h2#top-doc-prose-title", {"font-size": "22px"}) assert-css: ("h2#top-doc-prose-title", {"border-bottom-width": "1px"}) @@ -111,7 +111,7 @@ assert-css: ("//ul[@class='block mod']/preceding-sibling::h3", {"border-bottom-w goto: "file://" + |DOC_PATH| + "/test_docs/union.HeavilyDocumentedUnion.html" -assert-css: ("h1.fqn", {"font-size": "24px"}) +assert-css: (".main-heading h1", {"font-size": "24px"}) assert-css: ("h2#top-doc-prose-title", {"font-size": "22px"}) assert-css: ("h2#top-doc-prose-title", {"border-bottom-width": "1px"}) @@ -143,7 +143,7 @@ assert-css: ("h6#sub-heading-for-union-impl-item-doc", {"border-bottom-width": " goto: "file://" + |DOC_PATH| + "/test_docs/macro.heavily_documented_macro.html" -assert-css: ("h1.fqn", {"font-size": "24px"}) +assert-css: (".main-heading h1", {"font-size": "24px"}) assert-css: ("h2#top-doc-prose-title", {"font-size": "22px"}) assert-css: ("h2#top-doc-prose-title", {"border-bottom-width": "1px"}) diff --git a/tests/rustdoc-gui/search-result-go-to-first.goml b/tests/rustdoc-gui/search-result-go-to-first.goml index 994fd87c9966..f444baa6ce10 100644 --- a/tests/rustdoc-gui/search-result-go-to-first.goml +++ b/tests/rustdoc-gui/search-result-go-to-first.goml @@ -3,17 +3,17 @@ // First, we check that the first page doesn't have the string we're looking for to ensure // that the feature is changing page as expected. goto: "file://" + |DOC_PATH| + "/test_docs/index.html" -assert-text-false: (".fqn", "Struct test_docs::Foo") +assert-text-false: (".main-heading h1", "Struct test_docs::Foo") // We now check that we land on the search result page if "go_to_first" isn't set. goto: "file://" + |DOC_PATH| + "/test_docs/index.html?search=struct%3AFoo" // Waiting for the search results to appear... wait-for: "#search-tabs" -assert-text-false: (".fqn", "Struct test_docs::Foo") +assert-text-false: (".main-heading h1", "Struct test_docs::Foo") // Ensure that the search results are displayed, not the "normal" content. assert-css: ("#main-content", {"display": "none"}) // Now we can check that the feature is working as expected! goto: "file://" + |DOC_PATH| + "/test_docs/index.html?search=struct%3AFoo&go_to_first=true" // Waiting for the page to load... -wait-for-text: (".fqn", "Struct test_docs::Foo") +wait-for-text: (".main-heading h1", "Struct test_docs::Foo") diff --git a/tests/rustdoc-gui/toggle-click-deadspace.goml b/tests/rustdoc-gui/toggle-click-deadspace.goml index 029403ee13ee..854e945f9457 100644 --- a/tests/rustdoc-gui/toggle-click-deadspace.goml +++ b/tests/rustdoc-gui/toggle-click-deadspace.goml @@ -12,4 +12,4 @@ assert-attribute-false: (".impl-items .rustdoc-toggle", {"open": ""}) // Click the "Trait" part of "impl Trait" and verify it navigates. click: "#impl-Trait-for-Foo h3 a:first-of-type" -assert-text: (".fqn", "Trait lib2::Trait") +assert-text: (".main-heading h1", "Trait lib2::Trait") diff --git a/tests/rustdoc/index-page.rs b/tests/rustdoc/index-page.rs index 0c947ea2e287..fc755afda4a9 100644 --- a/tests/rustdoc/index-page.rs +++ b/tests/rustdoc/index-page.rs @@ -5,7 +5,7 @@ #![crate_name = "foo"] // @has foo/../index.html -// @has - '//h1[@class="fqn"]' 'List of all crates' +// @has - '//h1' 'List of all crates' // @has - '//ul[@class="all-items"]//a[@href="foo/index.html"]' 'foo' // @has - '//ul[@class="all-items"]//a[@href="all_item_types/index.html"]' 'all_item_types' pub struct Foo; diff --git a/tests/rustdoc/keyword.rs b/tests/rustdoc/keyword.rs index ea1273850912..4d047af32551 100644 --- a/tests/rustdoc/keyword.rs +++ b/tests/rustdoc/keyword.rs @@ -7,7 +7,7 @@ // @has foo/index.html '//div[@class="sidebar-elems"]//li/a' 'Keywords' // @has foo/index.html '//div[@class="sidebar-elems"]//li/a/@href' '#keywords' // @has foo/keyword.match.html '//a[@class="keyword"]' 'match' -// @has foo/keyword.match.html '//h1[@class="fqn"]' 'Keyword match' +// @has foo/keyword.match.html '//h1' 'Keyword match' // @has foo/keyword.match.html '//section[@id="main-content"]//div[@class="docblock"]//p' 'this is a test!' // @has foo/index.html '//a/@href' '../foo/index.html' // @!has foo/foo/index.html diff --git a/tests/rustdoc/primitive-reference.rs b/tests/rustdoc/primitive-reference.rs index ea8d2d166026..c3a5eb6d324a 100644 --- a/tests/rustdoc/primitive-reference.rs +++ b/tests/rustdoc/primitive-reference.rs @@ -9,7 +9,7 @@ // @has - '//div[@class="sidebar-elems"]//li/a/@href' '#primitives' // @has foo/primitive.reference.html // @has - '//a[@class="primitive"]' 'reference' -// @has - '//h1[@class="fqn"]' 'Primitive Type reference' +// @has - '//h1' 'Primitive Type reference' // @has - '//section[@id="main-content"]//div[@class="docblock"]//p' 'this is a test!' // There should be only one implementation listed. diff --git a/tests/rustdoc/primitive-slice-auto-trait.rs b/tests/rustdoc/primitive-slice-auto-trait.rs index cdddd6b65078..779224146761 100644 --- a/tests/rustdoc/primitive-slice-auto-trait.rs +++ b/tests/rustdoc/primitive-slice-auto-trait.rs @@ -4,7 +4,7 @@ #![feature(rustdoc_internals)] // @has foo/primitive.slice.html '//a[@class="primitive"]' 'slice' -// @has - '//h1[@class="fqn"]' 'Primitive Type slice' +// @has - '//h1' 'Primitive Type slice' // @has - '//section[@id="main-content"]//div[@class="docblock"]//p' 'this is a test!' // @has - '//h2[@id="synthetic-implementations"]' 'Auto Trait Implementations' // @has - '//div[@id="synthetic-implementations-list"]//h3' 'impl Send for [T]where T: Send' diff --git a/tests/rustdoc/primitive-tuple-auto-trait.rs b/tests/rustdoc/primitive-tuple-auto-trait.rs index df681457f0f1..4344d24f9865 100644 --- a/tests/rustdoc/primitive-tuple-auto-trait.rs +++ b/tests/rustdoc/primitive-tuple-auto-trait.rs @@ -4,7 +4,7 @@ #![feature(rustdoc_internals)] // @has foo/primitive.tuple.html '//a[@class="primitive"]' 'tuple' -// @has - '//h1[@class="fqn"]' 'Primitive Type tuple' +// @has - '//h1' 'Primitive Type tuple' // @has - '//section[@id="main-content"]//div[@class="docblock"]//p' 'this is a test!' // @has - '//h2[@id="synthetic-implementations"]' 'Auto Trait Implementations' // @has - '//div[@id="synthetic-implementations-list"]//h3' 'Send' diff --git a/tests/rustdoc/primitive-unit-auto-trait.rs b/tests/rustdoc/primitive-unit-auto-trait.rs index 391e33bea616..61850e2462d8 100644 --- a/tests/rustdoc/primitive-unit-auto-trait.rs +++ b/tests/rustdoc/primitive-unit-auto-trait.rs @@ -4,7 +4,7 @@ #![feature(rustdoc_internals)] // @has foo/primitive.unit.html '//a[@class="primitive"]' 'unit' -// @has - '//h1[@class="fqn"]' 'Primitive Type unit' +// @has - '//h1' 'Primitive Type unit' // @has - '//section[@id="main-content"]//div[@class="docblock"]//p' 'this is a test!' // @has - '//h2[@id="synthetic-implementations"]' 'Auto Trait Implementations' // @has - '//div[@id="synthetic-implementations-list"]//h3' 'impl Send for ()' diff --git a/tests/rustdoc/primitive.rs b/tests/rustdoc/primitive.rs index 6347fdac3db5..516c7c0c6fe9 100644 --- a/tests/rustdoc/primitive.rs +++ b/tests/rustdoc/primitive.rs @@ -7,7 +7,7 @@ // @has foo/index.html '//div[@class="sidebar-elems"]//li/a' 'Primitive Types' // @has foo/index.html '//div[@class="sidebar-elems"]//li/a/@href' '#primitives' // @has foo/primitive.i32.html '//a[@class="primitive"]' 'i32' -// @has foo/primitive.i32.html '//h1[@class="fqn"]' 'Primitive Type i32' +// @has foo/primitive.i32.html '//h1' 'Primitive Type i32' // @has foo/primitive.i32.html '//section[@id="main-content"]//div[@class="docblock"]//p' 'this is a test!' // @has foo/index.html '//a/@href' '../foo/index.html' // @!has foo/index.html '//span' '🔒' From f6e6d2a035d9e86e7053847aa60a99940f41064c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 12 Jan 2023 19:53:01 +0000 Subject: [PATCH 064/105] Elaborate unmet obligations in E0599 for more context --- compiler/rustc_hir_typeck/src/method/probe.rs | 28 ++++++++++++++---- tests/ui/derives/issue-91550.stderr | 29 ++++++++++++++++--- .../ui/missing-trait-bounds/issue-35677.fixed | 2 +- .../missing-trait-bounds/issue-35677.stderr | 6 ++-- 4 files changed, 53 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index dd827777df94..15f6e1171776 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -1587,11 +1587,29 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let o = self.resolve_vars_if_possible(o); if !self.predicate_may_hold(&o) { result = ProbeResult::NoMatch; - possibly_unsatisfied_predicates.push(( - o.predicate, - None, - Some(o.cause), - )); + let parent_o = o.clone(); + let implied_obligations = + traits::elaborate_obligations(self.tcx, vec![o]); + for o in implied_obligations { + let parent = if o == parent_o { + None + } else { + if o.predicate.to_opt_poly_trait_pred().map(|p| p.def_id()) + == self.tcx.lang_items().sized_trait() + { + // We don't care to talk about implicit `Sized` bounds. + continue; + } + Some(parent_o.predicate) + }; + if !self.predicate_may_hold(&o) { + possibly_unsatisfied_predicates.push(( + o.predicate, + parent, + Some(o.cause), + )); + } + } } } } diff --git a/tests/ui/derives/issue-91550.stderr b/tests/ui/derives/issue-91550.stderr index bf0bb3fbdf8f..381d860a9c36 100644 --- a/tests/ui/derives/issue-91550.stderr +++ b/tests/ui/derives/issue-91550.stderr @@ -6,12 +6,15 @@ LL | struct Value(u32); | | | doesn't satisfy `Value: Eq` | doesn't satisfy `Value: Hash` + | doesn't satisfy `Value: PartialEq` ... LL | hs.insert(Value(0)); | ^^^^^^ | = note: the following trait bounds were not satisfied: `Value: Eq` + `Value: PartialEq` + which is required by `Value: Eq` `Value: Hash` help: consider annotating `Value` with `#[derive(Eq, Hash, PartialEq)]` | @@ -22,7 +25,10 @@ error[E0599]: the method `use_eq` exists for struct `Object`, but its --> $DIR/issue-91550.rs:26:9 | LL | pub struct NoDerives; - | -------------------- doesn't satisfy `NoDerives: Eq` + | -------------------- + | | + | doesn't satisfy `NoDerives: Eq` + | doesn't satisfy `NoDerives: PartialEq` LL | LL | struct Object(T); | ---------------- method `use_eq` not found for this struct @@ -30,7 +36,9 @@ LL | struct Object(T); LL | foo.use_eq(); | ^^^^^^ method cannot be called on `Object` due to unsatisfied trait bounds | -note: trait bound `NoDerives: Eq` was not satisfied +note: the following trait bounds were not satisfied: + `NoDerives: Eq` + `NoDerives: PartialEq` --> $DIR/issue-91550.rs:15:9 | LL | impl Object { @@ -46,7 +54,12 @@ error[E0599]: the method `use_ord` exists for struct `Object`, but it --> $DIR/issue-91550.rs:27:9 | LL | pub struct NoDerives; - | -------------------- doesn't satisfy `NoDerives: Ord` + | -------------------- + | | + | doesn't satisfy `NoDerives: Eq` + | doesn't satisfy `NoDerives: Ord` + | doesn't satisfy `NoDerives: PartialEq` + | doesn't satisfy `NoDerives: PartialOrd` LL | LL | struct Object(T); | ---------------- method `use_ord` not found for this struct @@ -54,7 +67,11 @@ LL | struct Object(T); LL | foo.use_ord(); | ^^^^^^^ method cannot be called on `Object` due to unsatisfied trait bounds | -note: trait bound `NoDerives: Ord` was not satisfied +note: the following trait bounds were not satisfied: + `NoDerives: Eq` + `NoDerives: Ord` + `NoDerives: PartialEq` + `NoDerives: PartialOrd` --> $DIR/issue-91550.rs:18:9 | LL | impl Object { @@ -72,7 +89,9 @@ error[E0599]: the method `use_ord_and_partial_ord` exists for struct `Object(T); @@ -82,7 +101,9 @@ LL | foo.use_ord_and_partial_ord(); | ^^^^^^^^^^^^^^^^^^^^^^^ method cannot be called on `Object` due to unsatisfied trait bounds | note: the following trait bounds were not satisfied: + `NoDerives: Eq` `NoDerives: Ord` + `NoDerives: PartialEq` `NoDerives: PartialOrd` --> $DIR/issue-91550.rs:21:9 | diff --git a/tests/ui/missing-trait-bounds/issue-35677.fixed b/tests/ui/missing-trait-bounds/issue-35677.fixed index 08174d8d8d53..c76b6bc9c185 100644 --- a/tests/ui/missing-trait-bounds/issue-35677.fixed +++ b/tests/ui/missing-trait-bounds/issue-35677.fixed @@ -3,7 +3,7 @@ use std::collections::HashSet; use std::hash::Hash; -fn is_subset(this: &HashSet, other: &HashSet) -> bool where T: Eq, T: Hash { +fn is_subset(this: &HashSet, other: &HashSet) -> bool where T: Eq, T: Hash, T: PartialEq { this.is_subset(other) //~^ ERROR the method } diff --git a/tests/ui/missing-trait-bounds/issue-35677.stderr b/tests/ui/missing-trait-bounds/issue-35677.stderr index a2201b946a6f..067b10b873ab 100644 --- a/tests/ui/missing-trait-bounds/issue-35677.stderr +++ b/tests/ui/missing-trait-bounds/issue-35677.stderr @@ -6,11 +6,13 @@ LL | this.is_subset(other) | = note: the following trait bounds were not satisfied: `T: Eq` + `T: PartialEq` + which is required by `T: Eq` `T: Hash` help: consider restricting the type parameters to satisfy the trait bounds | -LL | fn is_subset(this: &HashSet, other: &HashSet) -> bool where T: Eq, T: Hash { - | ++++++++++++++++++++ +LL | fn is_subset(this: &HashSet, other: &HashSet) -> bool where T: Eq, T: Hash, T: PartialEq { + | ++++++++++++++++++++++++++++++++++ error: aborting due to previous error From 3d6b09e53e0b1d5920fe3c6106f676b7b95f4a70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 12 Jan 2023 21:32:06 +0000 Subject: [PATCH 065/105] Keep obligation chain when elaborating obligations --- .../rustc_hir_typeck/src/method/suggest.rs | 15 +++++++++- compiler/rustc_infer/src/traits/util.rs | 18 ++++++++++-- .../issue-43784-associated-type.stderr | 5 ++++ tests/ui/derives/issue-91550.stderr | 29 ++++++++++++------- .../issue-74824.stderr | 1 + tests/ui/traits/issue-43784-supertrait.stderr | 5 ++++ 6 files changed, 59 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 8166eb829904..338fabca3891 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -692,7 +692,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "auto trait is invoked with no method error, but no error reported?", ); } - Some(_) => unreachable!(), + Some(Node::Item(hir::Item { + ident, kind: hir::ItemKind::Trait(..), .. + })) => { + skip_list.insert(p); + let entry = spanned_predicates.entry(ident.span); + let entry = entry.or_insert_with(|| { + (FxHashSet::default(), FxHashSet::default(), Vec::new()) + }); + entry.0.insert(cause.span); + entry.1.insert((ident.span, "")); + entry.1.insert((cause.span, "unsatisfied trait bound introduced here")); + entry.2.push(p); + } + Some(node) => unreachable!("encountered `{node:?}`"), None => (), } } diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs index 8f0bd3a9abe5..1817bbf92285 100644 --- a/compiler/rustc_infer/src/traits/util.rs +++ b/compiler/rustc_infer/src/traits/util.rs @@ -1,7 +1,7 @@ use smallvec::smallvec; use crate::infer::outlives::components::{push_outlives_components, Component}; -use crate::traits::{Obligation, ObligationCause, PredicateObligation}; +use crate::traits::{self, Obligation, ObligationCause, PredicateObligation}; use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; use rustc_middle::ty::{self, ToPredicate, TyCtxt}; use rustc_span::symbol::Ident; @@ -145,16 +145,28 @@ impl<'tcx> Elaborator<'tcx> { // Get predicates declared on the trait. let predicates = tcx.super_predicates_of(data.def_id()); - let obligations = predicates.predicates.iter().map(|&(mut pred, _)| { + let obligations = predicates.predicates.iter().map(|&(mut pred, span)| { // when parent predicate is non-const, elaborate it to non-const predicates. if data.constness == ty::BoundConstness::NotConst { pred = pred.without_const(tcx); } + let cause = obligation.cause.clone().derived_cause( + bound_predicate.rebind(data), + |derived| { + traits::ImplDerivedObligation(Box::new( + traits::ImplDerivedObligationCause { + derived, + impl_def_id: data.def_id(), + span, + }, + )) + }, + ); predicate_obligation( pred.subst_supertrait(tcx, &bound_predicate.rebind(data.trait_ref)), obligation.param_env, - obligation.cause.clone(), + cause, ) }); debug!(?data, ?obligations, "super_predicates"); diff --git a/tests/ui/associated-types/issue-43784-associated-type.stderr b/tests/ui/associated-types/issue-43784-associated-type.stderr index f1677b822b4c..50fa7d1ac4d4 100644 --- a/tests/ui/associated-types/issue-43784-associated-type.stderr +++ b/tests/ui/associated-types/issue-43784-associated-type.stderr @@ -4,6 +4,11 @@ error[E0277]: the trait bound `T: Copy` is not satisfied LL | type Assoc = T; | ^ the trait `Copy` is not implemented for `T` | +note: required for `::Assoc` to implement `Partial` + --> $DIR/issue-43784-associated-type.rs:1:11 + | +LL | pub trait Partial: Copy { + | ^^^^^^^ note: required by a bound in `Complete::Assoc` --> $DIR/issue-43784-associated-type.rs:5:17 | diff --git a/tests/ui/derives/issue-91550.stderr b/tests/ui/derives/issue-91550.stderr index 381d860a9c36..af03f0e5e5f4 100644 --- a/tests/ui/derives/issue-91550.stderr +++ b/tests/ui/derives/issue-91550.stderr @@ -36,15 +36,16 @@ LL | struct Object(T); LL | foo.use_eq(); | ^^^^^^ method cannot be called on `Object` due to unsatisfied trait bounds | -note: the following trait bounds were not satisfied: - `NoDerives: Eq` - `NoDerives: PartialEq` +note: trait bound `NoDerives: Eq` was not satisfied --> $DIR/issue-91550.rs:15:9 | LL | impl Object { | ^^ --------- | | | unsatisfied trait bound introduced here + = note: the following trait bounds were not satisfied: + `NoDerives: PartialEq` + which is required by `NoDerives: Eq` help: consider annotating `NoDerives` with `#[derive(Eq, PartialEq)]` | LL | #[derive(Eq, PartialEq)] @@ -67,17 +68,20 @@ LL | struct Object(T); LL | foo.use_ord(); | ^^^^^^^ method cannot be called on `Object` due to unsatisfied trait bounds | -note: the following trait bounds were not satisfied: - `NoDerives: Eq` - `NoDerives: Ord` - `NoDerives: PartialEq` - `NoDerives: PartialOrd` +note: trait bound `NoDerives: Ord` was not satisfied --> $DIR/issue-91550.rs:18:9 | LL | impl Object { | ^^^ --------- | | | unsatisfied trait bound introduced here + = note: the following trait bounds were not satisfied: + `NoDerives: PartialOrd` + which is required by `NoDerives: Ord` + `NoDerives: PartialEq` + which is required by `NoDerives: Ord` + `NoDerives: Eq` + which is required by `NoDerives: Ord` help: consider annotating `NoDerives` with `#[derive(Eq, Ord, PartialEq, PartialOrd)]` | LL | #[derive(Eq, Ord, PartialEq, PartialOrd)] @@ -101,9 +105,7 @@ LL | foo.use_ord_and_partial_ord(); | ^^^^^^^^^^^^^^^^^^^^^^^ method cannot be called on `Object` due to unsatisfied trait bounds | note: the following trait bounds were not satisfied: - `NoDerives: Eq` `NoDerives: Ord` - `NoDerives: PartialEq` `NoDerives: PartialOrd` --> $DIR/issue-91550.rs:21:9 | @@ -112,6 +114,13 @@ LL | impl Object { | | | | | unsatisfied trait bound introduced here | unsatisfied trait bound introduced here + = note: the following trait bounds were not satisfied: + `NoDerives: PartialEq` + which is required by `NoDerives: Ord` + `NoDerives: Eq` + which is required by `NoDerives: Ord` + `NoDerives: PartialEq` + which is required by `NoDerives: PartialOrd` help: consider annotating `NoDerives` with `#[derive(Eq, Ord, PartialEq, PartialOrd)]` | LL | #[derive(Eq, Ord, PartialEq, PartialOrd)] diff --git a/tests/ui/generic-associated-types/issue-74824.stderr b/tests/ui/generic-associated-types/issue-74824.stderr index 623adb1c2ad1..e5638d90ee8e 100644 --- a/tests/ui/generic-associated-types/issue-74824.stderr +++ b/tests/ui/generic-associated-types/issue-74824.stderr @@ -17,6 +17,7 @@ LL | type Copy: Copy = Box; | ^^^^^^ the trait `Clone` is not implemented for `T` | = note: required for `Box` to implement `Clone` + = note: required for `::Copy` to implement `Copy` note: required by a bound in `UnsafeCopy::Copy` --> $DIR/issue-74824.rs:6:19 | diff --git a/tests/ui/traits/issue-43784-supertrait.stderr b/tests/ui/traits/issue-43784-supertrait.stderr index 4fe12731475b..6b5b721384cb 100644 --- a/tests/ui/traits/issue-43784-supertrait.stderr +++ b/tests/ui/traits/issue-43784-supertrait.stderr @@ -4,6 +4,11 @@ error[E0277]: the trait bound `T: Copy` is not satisfied LL | impl Complete for T {} | ^ the trait `Copy` is not implemented for `T` | +note: required for `T` to implement `Partial` + --> $DIR/issue-43784-supertrait.rs:1:11 + | +LL | pub trait Partial: Copy { + | ^^^^^^^ note: required by a bound in `Complete` --> $DIR/issue-43784-supertrait.rs:4:21 | From 81ba427a7b15d614a74812ef3fd1467c85d4768d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 12 Jan 2023 21:48:07 +0000 Subject: [PATCH 066/105] Add tests --- tests/ui/traits/track-obligations.rs | 88 ++++++++++++++++++++++++ tests/ui/traits/track-obligations.stderr | 76 ++++++++++++++++++++ 2 files changed, 164 insertions(+) create mode 100644 tests/ui/traits/track-obligations.rs create mode 100644 tests/ui/traits/track-obligations.stderr diff --git a/tests/ui/traits/track-obligations.rs b/tests/ui/traits/track-obligations.rs new file mode 100644 index 000000000000..77e753c13f73 --- /dev/null +++ b/tests/ui/traits/track-obligations.rs @@ -0,0 +1,88 @@ +// These are simplifications of the tower traits by the same name: + +pub trait Service { + type Response; +} + +pub trait Layer { + type Service; +} + +// Any type will do here: + +pub struct Req; +pub struct Res; + +// This is encoding a trait alias. + +pub trait ParticularService: + Service { +} + +impl ParticularService for T +where + T: Service, +{ +} + +// This is also a trait alias. +// The weird = bound is there so that users of the trait do not +// need to repeat the bounds. See https://github.com/rust-lang/rust/issues/20671 +// for context, and in particular the workaround in: +// https://github.com/rust-lang/rust/issues/20671#issuecomment-529752828 + +pub trait ParticularServiceLayer: + Layer>::Service> +{ + type Service: ParticularService; +} + +impl ParticularServiceLayer for T +where + T: Layer, + T::Service: ParticularService, +{ + type Service = T::Service; +} + +// These are types that implement the traits that the trait aliases refer to. +// They should also implement the alias traits due to the blanket impls. + +struct ALayer(C); +impl Layer for ALayer { + type Service = AService; +} + +struct AService; +impl Service for AService { + // However, AService does _not_ meet the blanket implementation, + // since its Response type is bool, not Res as it should be. + type Response = bool; +} + +// This is a wrapper type around ALayer that uses the trait alias +// as a way to communicate the requirements of the provided types. +struct Client(C); + +// The method and the free-standing function below both have the same bounds. + +impl Client +where + ALayer: ParticularServiceLayer, +{ + fn check(&self) {} +} + +fn check(_: C) where ALayer: ParticularServiceLayer {} + +// But, they give very different error messages. + +fn main() { + // This gives a very poor error message that does nothing to point the user + // at the underlying cause of why the types involved do not meet the bounds. + Client(()).check(); //~ ERROR E0599 + + // This gives a good(ish) error message that points the user at _why_ the + // bound isn't met, and thus how they might fix it. + check(()); //~ ERROR E0271 +} diff --git a/tests/ui/traits/track-obligations.stderr b/tests/ui/traits/track-obligations.stderr new file mode 100644 index 000000000000..89477475970f --- /dev/null +++ b/tests/ui/traits/track-obligations.stderr @@ -0,0 +1,76 @@ +error[E0599]: the method `check` exists for struct `Client<()>`, but its trait bounds were not satisfied + --> $DIR/track-obligations.rs:83:16 + | +LL | struct ALayer(C); + | ---------------- + | | + | doesn't satisfy `<_ as Layer<()>>::Service = as ParticularServiceLayer<()>>::Service` + | doesn't satisfy `ALayer<()>: ParticularServiceLayer<()>` +... +LL | struct Client(C); + | ---------------- method `check` not found for this struct +... +LL | Client(()).check(); + | ^^^^^ method cannot be called on `Client<()>` due to unsatisfied trait bounds + | +note: trait bound ` as Layer<()>>::Service = as ParticularServiceLayer<()>>::Service` was not satisfied + --> $DIR/track-obligations.rs:35:14 + | +LL | pub trait ParticularServiceLayer: + | ---------------------- +LL | Layer>::Service> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound introduced here +note: trait bound `ALayer<()>: ParticularServiceLayer<()>` was not satisfied + --> $DIR/track-obligations.rs:71:16 + | +LL | impl Client + | --------- +LL | where +LL | ALayer: ParticularServiceLayer, + | ^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound introduced here +note: the trait `ParticularServiceLayer` must be implemented + --> $DIR/track-obligations.rs:34:1 + | +LL | / pub trait ParticularServiceLayer: +LL | | Layer>::Service> + | |____________________________________________________________________^ + +error[E0271]: type mismatch resolving `>::Response == Res` + --> $DIR/track-obligations.rs:87:11 + | +LL | check(()); + | ----- ^^ type mismatch resolving `>::Response == Res` + | | + | required by a bound introduced by this call + | +note: expected this to be `Res` + --> $DIR/track-obligations.rs:60:21 + | +LL | type Response = bool; + | ^^^^ +note: required for `AService` to implement `ParticularService` + --> $DIR/track-obligations.rs:22:9 + | +LL | impl ParticularService for T + | ^^^^^^^^^^^^^^^^^ ^ +LL | where +LL | T: Service, + | -------------- unsatisfied trait bound introduced here +note: required for `ALayer<_>` to implement `ParticularServiceLayer<_>` + --> $DIR/track-obligations.rs:40:12 + | +LL | impl ParticularServiceLayer for T + | ^^^^^^^^^^^^^^^^^^^^^^^^^ ^ +... +LL | T::Service: ParticularService, + | ----------------- unsatisfied trait bound introduced here +note: required by a bound in `check` + --> $DIR/track-obligations.rs:76:36 + | +LL | fn check(_: C) where ALayer: ParticularServiceLayer {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0271, E0599. +For more information about an error, try `rustc --explain E0271`. From 1d328de3ec00bc5d204306da20cc166e5ae8857d Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Tue, 10 Jan 2023 11:35:37 -0700 Subject: [PATCH 067/105] rustdoc: rename CSS rustdoc-toggle -> toggle and toggle -> settings-toggle This swaps things around so that the class that gets used more often has the shorter name. --- src/librustdoc/html/render/mod.rs | 8 +-- src/librustdoc/html/render/print_item.rs | 6 +- src/librustdoc/html/static/css/rustdoc.css | 72 +++++++++---------- src/librustdoc/html/static/css/settings.css | 14 ++-- src/librustdoc/html/static/js/main.js | 8 +-- src/librustdoc/html/static/js/settings.js | 4 +- tests/rustdoc-gui/method-margins.goml | 10 +-- tests/rustdoc-gui/settings.goml | 4 +- tests/rustdoc-gui/toggle-click-deadspace.goml | 8 +-- tests/rustdoc-gui/toggle-docs.goml | 18 ++--- .../toggled-open-implementations.goml | 2 +- tests/rustdoc/issue-41783.rs | 2 +- tests/rustdoc/local-reexport-doc.rs | 2 +- .../rustdoc/mixing-doc-comments-and-attrs.rs | 6 +- tests/rustdoc/multiple-import-levels.rs | 6 +- .../rustdoc/strip-block-doc-comments-stars.rs | 2 +- tests/rustdoc/toggle-item-contents.rs | 40 +++++------ tests/rustdoc/toggle-method.rs | 6 +- tests/rustdoc/toggle-trait-fn.rs | 16 ++--- 19 files changed, 117 insertions(+), 117 deletions(-) diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 8bccf68029aa..19f7b2270a70 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -513,7 +513,7 @@ fn document_full_inner( debug!("Doc block: =====\n{}\n=====", s); if is_collapsible { w.write_str( - "
\ + "
\ \ Expand description\ ", @@ -1514,7 +1514,7 @@ fn render_impl( let toggled = !doc_buffer.is_empty(); if toggled { let method_toggle_class = if item_type.is_method() { " method-toggle" } else { "" }; - write!(w, "
", method_toggle_class); + write!(w, "
", method_toggle_class); } match &*item.kind { clean::MethodItem(..) | clean::TyMethodItem(_) => { @@ -1730,7 +1730,7 @@ fn render_impl( close_tags.insert_str(0, "
"); write!( w, - "
", + "
", if rendering_params.toggle_open_by_default { " open" } else { "" } ); write!(w, "") @@ -2999,7 +2999,7 @@ fn render_call_locations(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Ite if it.peek().is_some() { write!( w, - "
\ + "
\ \ More examples\ \ diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index c16d6477fc37..d6e57decdcf1 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -204,7 +204,7 @@ fn should_hide_fields(n_fields: usize) -> bool { fn toggle_open(w: &mut Buffer, text: impl fmt::Display) { write!( w, - "
\ + "
\ \ Show {}\ ", @@ -733,7 +733,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: let toggled = !content.is_empty(); if toggled { let method_toggle_class = if item_type.is_method() { " method-toggle" } else { "" }; - write!(w, "
"); + write!(w, "
"); } write!(w, "
", id); render_rightside(w, cx, m, t, RenderMode::Normal); @@ -1840,7 +1840,7 @@ fn document_non_exhaustive(w: &mut Buffer, item: &clean::Item) { if item.is_non_exhaustive() { write!( w, - "
\ + "
\ {}\
", { diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index b2fa6e82acce..8773bd2f1141 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -317,7 +317,7 @@ main { margin-right: auto; } -details:not(.rustdoc-toggle) summary { +details:not(.toggle) summary { margin-bottom: .6em; } @@ -1401,7 +1401,7 @@ details.dir-entry a { Unfortunately we can't yet specify contain: content or contain: strict because the [-]/[+] toggles extend past the boundaries of the
https://developer.mozilla.org/en-US/docs/Web/CSS/contain */ -details.rustdoc-toggle { +details.toggle { contain: layout; position: relative; } @@ -1409,26 +1409,26 @@ details.rustdoc-toggle { /* The hideme class is used on summary tags that contain a span with placeholder text shown only when the toggle is closed. For instance, "Expand description" or "Show methods". */ -details.rustdoc-toggle > summary.hideme { +details.toggle > summary.hideme { cursor: pointer; font-size: 1rem; } -details.rustdoc-toggle > summary { +details.toggle > summary { list-style: none; /* focus outline is shown on `::before` instead of this */ outline: none; } -details.rustdoc-toggle > summary::-webkit-details-marker, -details.rustdoc-toggle > summary::marker { +details.toggle > summary::-webkit-details-marker, +details.toggle > summary::marker { display: none; } -details.rustdoc-toggle > summary.hideme > span { +details.toggle > summary.hideme > span { margin-left: 9px; } -details.rustdoc-toggle > summary::before { +details.toggle > summary::before { background: url("toggle-plus-1092eb4930d581b0.svg") no-repeat top left; content: ""; cursor: pointer; @@ -1440,14 +1440,14 @@ details.rustdoc-toggle > summary::before { filter: var(--toggle-filter); } -details.rustdoc-toggle > summary.hideme > span, +details.toggle > summary.hideme > span, .more-examples-toggle summary, .more-examples-toggle .hide-more { color: var(--toggles-color); } /* Screen readers see the text version at the end the line. Visual readers see the icon at the start of the line, but small and transparent. */ -details.rustdoc-toggle > summary::after { +details.toggle > summary::after { content: "Expand"; overflow: hidden; width: 0; @@ -1455,17 +1455,17 @@ details.rustdoc-toggle > summary::after { position: absolute; } -details.rustdoc-toggle > summary.hideme::after { +details.toggle > summary.hideme::after { /* "hideme" toggles already have a description when they're contracted */ content: ""; } -details.rustdoc-toggle > summary:focus::before, -details.rustdoc-toggle > summary:hover::before { +details.toggle > summary:focus::before, +details.toggle > summary:hover::before { opacity: 1; } -details.rustdoc-toggle > summary:focus-visible::before { +details.toggle > summary:focus-visible::before { /* The SVG is black, and gets turned white using a filter in the dark themes. Do the same with the outline. The dotted 1px style is copied from Firefox's focus ring style. @@ -1478,17 +1478,17 @@ details.non-exhaustive { margin-bottom: 8px; } -details.rustdoc-toggle > summary.hideme::before { +details.toggle > summary.hideme::before { position: relative; } -details.rustdoc-toggle > summary:not(.hideme)::before { +details.toggle > summary:not(.hideme)::before { position: absolute; left: -24px; top: 4px; } -.impl-items > details.rustdoc-toggle > summary:not(.hideme)::before { +.impl-items > details.toggle > summary:not(.hideme)::before { position: absolute; left: -24px; } @@ -1498,19 +1498,19 @@ details.rustdoc-toggle > summary:not(.hideme)::before { affect the layout of the items to its right. To do that, we use absolute positioning. Note that we also set position: relative on the parent
to make this work properly. */ -details.rustdoc-toggle[open] > summary.hideme { +details.toggle[open] > summary.hideme { position: absolute; } -details.rustdoc-toggle[open] > summary.hideme > span { +details.toggle[open] > summary.hideme > span { display: none; } -details.rustdoc-toggle[open] > summary::before { +details.toggle[open] > summary::before { background: url("toggle-minus-31bbd6e4c77f5c96.svg") no-repeat top left; } -details.rustdoc-toggle[open] > summary::after { +details.toggle[open] > summary::after { content: "Collapse"; } @@ -1660,8 +1660,8 @@ in storage.js display: block; } - #main-content > details.rustdoc-toggle > summary::before, - #main-content > div > details.rustdoc-toggle > summary::before { + #main-content > details.toggle > summary::before, + #main-content > div > details.toggle > summary::before { left: -11px; } @@ -1715,12 +1715,12 @@ in storage.js } /* Position of the "[-]" element. */ - details.rustdoc-toggle:not(.top-doc) > summary { + details.toggle:not(.top-doc) > summary { margin-left: 10px; } - .impl-items > details.rustdoc-toggle > summary:not(.hideme)::before, - #main-content > details.rustdoc-toggle:not(.top-doc) > summary::before, - #main-content > div > details.rustdoc-toggle > summary::before { + .impl-items > details.toggle > summary:not(.hideme)::before, + #main-content > details.toggle:not(.top-doc) > summary::before, + #main-content > div > details.toggle > summary::before { left: -11px; } @@ -1753,8 +1753,8 @@ in storage.js @media print { nav.sidebar, nav.sub, .out-of-band, a.srclink, #copy-path, - details.rustdoc-toggle[open] > summary::before, details.rustdoc-toggle > summary::before, - details.rustdoc-toggle.top-doc > summary { + details.toggle[open] > summary::before, details.toggle > summary::before, + details.toggle.top-doc > summary { display: none; } @@ -1796,24 +1796,24 @@ in storage.js .impl, #implementors-list > .docblock, .impl-items > section, -.impl-items > .rustdoc-toggle > summary, +.impl-items > .toggle > summary, .methods > section, -.methods > .rustdoc-toggle > summary +.methods > .toggle > summary { margin-bottom: 0.75em; } .variants > .docblock, .implementors-toggle > .docblock, -.impl-items > .rustdoc-toggle[open]:not(:last-child), -.methods > .rustdoc-toggle[open]:not(:last-child), +.impl-items > .toggle[open]:not(:last-child), +.methods > .toggle[open]:not(:last-child), .implementors-toggle[open]:not(:last-child) { margin-bottom: 2em; } -#trait-implementations-list .impl-items > .rustdoc-toggle:not(:last-child), -#synthetic-implementations-list .impl-items > .rustdoc-toggle:not(:last-child), -#blanket-implementations-list .impl-items > .rustdoc-toggle:not(:last-child) { +#trait-implementations-list .impl-items > .toggle:not(:last-child), +#synthetic-implementations-list .impl-items > .toggle:not(:last-child), +#blanket-implementations-list .impl-items > .toggle:not(:last-child) { margin-bottom: 1em; } diff --git a/src/librustdoc/html/static/css/settings.css b/src/librustdoc/html/static/css/settings.css index 875a260c8115..91419093147d 100644 --- a/src/librustdoc/html/static/css/settings.css +++ b/src/librustdoc/html/static/css/settings.css @@ -9,7 +9,7 @@ } .setting-line .radio-line input, -.setting-line .toggle input { +.setting-line .settings-toggle input { margin-right: 0.3em; height: 1.2rem; width: 1.2rem; @@ -22,14 +22,14 @@ .setting-line .radio-line input { border-radius: 50%; } -.setting-line .toggle input:checked { +.setting-line .settings-toggle input:checked { content: url('data:image/svg+xml,\ \ '); } .setting-line .radio-line input + span, -.setting-line .toggle span { +.setting-line .settings-toggle span { padding-bottom: 1px; } @@ -50,7 +50,7 @@ margin-left: 0.5em; } -.toggle { +.settings-toggle { position: relative; width: 100%; margin-right: 20px; @@ -67,11 +67,11 @@ box-shadow: inset 0 0 0 3px var(--main-background-color); background-color: var(--settings-input-color); } -.setting-line .toggle input:checked { +.setting-line .settings-toggle input:checked { background-color: var(--settings-input-color); } .setting-line .radio-line input:focus, -.setting-line .toggle input:focus { +.setting-line .settings-toggle input:focus { box-shadow: 0 0 1px 1px var(--settings-input-color); } /* In here we combine both `:focus` and `:checked` properties. */ @@ -80,6 +80,6 @@ 0 0 2px 2px var(--settings-input-color); } .setting-line .radio-line input:hover, -.setting-line .toggle input:hover { +.setting-line .settings-toggle input:hover { border-color: var(--settings-input-color) !important; } diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 51aee8e7c899..b05151f39b8f 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -620,7 +620,7 @@ function loadCss(cssUrl) { function expandAllDocs() { const innerToggle = document.getElementById(toggleAllDocsId); removeClass(innerToggle, "will-expand"); - onEachLazy(document.getElementsByClassName("rustdoc-toggle"), e => { + onEachLazy(document.getElementsByClassName("toggle"), e => { if (!hasClass(e, "type-contents-toggle") && !hasClass(e, "more-examples-toggle")) { e.open = true; } @@ -632,7 +632,7 @@ function loadCss(cssUrl) { function collapseAllDocs() { const innerToggle = document.getElementById(toggleAllDocsId); addClass(innerToggle, "will-expand"); - onEachLazy(document.getElementsByClassName("rustdoc-toggle"), e => { + onEachLazy(document.getElementsByClassName("toggle"), e => { if (e.parentNode.id !== "implementations-list" || (!hasClass(e, "implementors-toggle") && !hasClass(e, "type-contents-toggle")) @@ -680,7 +680,7 @@ function loadCss(cssUrl) { setImplementorsTogglesOpen("blanket-implementations-list", false); } - onEachLazy(document.getElementsByClassName("rustdoc-toggle"), e => { + onEachLazy(document.getElementsByClassName("toggle"), e => { if (!hideLargeItemContents && hasClass(e, "type-contents-toggle")) { e.open = true; } @@ -823,7 +823,7 @@ function loadCss(cssUrl) { }); }); - onEachLazy(document.querySelectorAll(".rustdoc-toggle > summary:not(.hideme)"), el => { + onEachLazy(document.querySelectorAll(".toggle > summary:not(.hideme)"), el => { el.addEventListener("click", e => { if (e.target.tagName !== "SUMMARY" && e.target.tagName !== "A") { e.preventDefault(); diff --git a/src/librustdoc/html/static/js/settings.js b/src/librustdoc/html/static/js/settings.js index 589bfc79360c..9ed8f63610ff 100644 --- a/src/librustdoc/html/static/js/settings.js +++ b/src/librustdoc/html/static/js/settings.js @@ -150,10 +150,10 @@ }); output += "

"; } else { - // This is a toggle. + // This is a checkbox toggle. const checked = setting["default"] === true ? " checked" : ""; output += `\ -
. goto: "file://" + |DOC_PATH| + "/lib2/struct.Foo.html" -assert-attribute: (".impl-items .rustdoc-toggle", {"open": ""}) +assert-attribute: (".impl-items .toggle", {"open": ""}) click: "h4.code-header" // This is the position of "pub" in "pub fn a_method" -assert-attribute: (".impl-items .rustdoc-toggle", {"open": ""}) +assert-attribute: (".impl-items .toggle", {"open": ""}) click-with-offset: ( - ".impl-items .rustdoc-toggle summary", + ".impl-items .toggle summary", {"x": -24, "y": 8}, // This is the position of "[-]" next to that pub fn. ) -assert-attribute-false: (".impl-items .rustdoc-toggle", {"open": ""}) +assert-attribute-false: (".impl-items .toggle", {"open": ""}) // Click the "Trait" part of "impl Trait" and verify it navigates. click: "#impl-Trait-for-Foo h3 a:first-of-type" diff --git a/tests/rustdoc-gui/toggle-docs.goml b/tests/rustdoc-gui/toggle-docs.goml index 89ce78e3aab4..c9d236e9bba8 100644 --- a/tests/rustdoc-gui/toggle-docs.goml +++ b/tests/rustdoc-gui/toggle-docs.goml @@ -20,10 +20,10 @@ assert-text: ("#toggle-all-docs", "[−]") goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html" // We first check that everything is visible. assert-text: ("#toggle-all-docs", "[−]") -assert-attribute: ("#implementations-list details.rustdoc-toggle", {"open": ""}, ALL) -assert-attribute: ("#trait-implementations-list details.rustdoc-toggle", {"open": ""}, ALL) +assert-attribute: ("#implementations-list details.toggle", {"open": ""}, ALL) +assert-attribute: ("#trait-implementations-list details.toggle", {"open": ""}, ALL) assert-attribute-false: ( - "#blanket-implementations-list > details.rustdoc-toggle", + "#blanket-implementations-list > details.toggle", {"open": ""}, ALL, ) @@ -32,18 +32,18 @@ assert-attribute-false: ( click: "#toggle-all-docs" wait-for-text: ("#toggle-all-docs", "[+]") // We check that all
are collapsed (except for the impl block ones). -assert-attribute-false: ("details.rustdoc-toggle:not(.implementors-toggle)", {"open": ""}, ALL) +assert-attribute-false: ("details.toggle:not(.implementors-toggle)", {"open": ""}, ALL) assert-attribute: ("#implementations-list > details.implementors-toggle", {"open": ""}) // We now check that the other impl blocks are collapsed. assert-attribute-false: ( - "#blanket-implementations-list > details.rustdoc-toggle.implementors-toggle", + "#blanket-implementations-list > details.toggle.implementors-toggle", {"open": ""}, ALL, ) // We open them all again. click: "#toggle-all-docs" wait-for-text: ("#toggle-all-docs", "[−]") -assert-attribute: ("details.rustdoc-toggle", {"open": ""}, ALL) +assert-attribute: ("details.toggle", {"open": ""}, ALL) // Checking the toggles style. show-text: true @@ -56,12 +56,12 @@ define-function: ( // We reload the page so the local storage settings are being used. reload: - assert-css: ("details.rustdoc-toggle > summary::before", { + assert-css: ("details.toggle > summary::before", { "opacity": "0.5", "filter": |filter|, }, ALL) - move-cursor-to: "details.rustdoc-toggle summary" - assert-css: ("details.rustdoc-toggle > summary:hover::before", { + move-cursor-to: "details.toggle summary" + assert-css: ("details.toggle > summary:hover::before", { "opacity": "1", "filter": |filter|, }) diff --git a/tests/rustdoc-gui/toggled-open-implementations.goml b/tests/rustdoc-gui/toggled-open-implementations.goml index e4d59b5d7285..000293b555f8 100644 --- a/tests/rustdoc-gui/toggled-open-implementations.goml +++ b/tests/rustdoc-gui/toggled-open-implementations.goml @@ -2,4 +2,4 @@ // has all the implementations toggled open by default, so users can // find method names in those implementations with Ctrl-F. goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html" -assert-attribute: (".rustdoc-toggle.implementors-toggle", {"open": ""}) +assert-attribute: (".toggle.implementors-toggle", {"open": ""}) diff --git a/tests/rustdoc/issue-41783.rs b/tests/rustdoc/issue-41783.rs index 769f984a274a..7578d49daa50 100644 --- a/tests/rustdoc/issue-41783.rs +++ b/tests/rustdoc/issue-41783.rs @@ -5,7 +5,7 @@ // @!hasraw - '#[outer]' // @hasraw - '#![inner]' // @!hasraw - '#![inner]' -// @snapshot 'codeblock' - '//*[@class="rustdoc-toggle top-doc"]/*[@class="docblock"]//pre/code' +// @snapshot 'codeblock' - '//*[@class="toggle top-doc"]/*[@class="docblock"]//pre/code' /// ```no_run /// # # space diff --git a/tests/rustdoc/local-reexport-doc.rs b/tests/rustdoc/local-reexport-doc.rs index 1c8468008dd0..5dc857773a39 100644 --- a/tests/rustdoc/local-reexport-doc.rs +++ b/tests/rustdoc/local-reexport-doc.rs @@ -4,7 +4,7 @@ #![crate_name = "foo"] // @has 'foo/fn.g.html' -// @has - '//*[@class="rustdoc-toggle top-doc"]/*[@class="docblock"]' \ +// @has - '//*[@class="toggle top-doc"]/*[@class="docblock"]' \ // 'outer module inner module' mod inner_mod { diff --git a/tests/rustdoc/mixing-doc-comments-and-attrs.rs b/tests/rustdoc/mixing-doc-comments-and-attrs.rs index a27c5ae6d012..010058361faa 100644 --- a/tests/rustdoc/mixing-doc-comments-and-attrs.rs +++ b/tests/rustdoc/mixing-doc-comments-and-attrs.rs @@ -1,7 +1,7 @@ #![crate_name = "foo"] // @has 'foo/struct.S1.html' -// @snapshot S1_top-doc - '//details[@class="rustdoc-toggle top-doc"]/div[@class="docblock"]' +// @snapshot S1_top-doc - '//details[@class="toggle top-doc"]/div[@class="docblock"]' #[doc = "Hello world!\n\n"] /// Goodbye! @@ -9,7 +9,7 @@ pub struct S1; // @has 'foo/struct.S2.html' -// @snapshot S2_top-doc - '//details[@class="rustdoc-toggle top-doc"]/div[@class="docblock"]' +// @snapshot S2_top-doc - '//details[@class="toggle top-doc"]/div[@class="docblock"]' /// Hello world! /// @@ -18,7 +18,7 @@ pub struct S1; pub struct S2; // @has 'foo/struct.S3.html' -// @snapshot S3_top-doc - '//details[@class="rustdoc-toggle top-doc"]/div[@class="docblock"]' +// @snapshot S3_top-doc - '//details[@class="toggle top-doc"]/div[@class="docblock"]' /** Par 1 */ /// /// Par 2 diff --git a/tests/rustdoc/multiple-import-levels.rs b/tests/rustdoc/multiple-import-levels.rs index 1daae49cde9d..29b67c6b2b17 100644 --- a/tests/rustdoc/multiple-import-levels.rs +++ b/tests/rustdoc/multiple-import-levels.rs @@ -21,14 +21,14 @@ mod c { } // @has 'foo/struct.Type.html' -// @has - '//*[@class="rustdoc-toggle top-doc"]/*[@class="docblock"]' 'foo 2 1' +// @has - '//*[@class="toggle top-doc"]/*[@class="docblock"]' 'foo 2 1' /// foo pub use b::Type; // @has 'foo/struct.Whatever.html' -// @has - '//*[@class="rustdoc-toggle top-doc"]/*[@class="docblock"]' 'whatever 3 2 1' +// @has - '//*[@class="toggle top-doc"]/*[@class="docblock"]' 'whatever 3 2 1' /// whatever pub use c::Type as Whatever; // @has 'foo/struct.Woof.html' -// @has - '//*[@class="rustdoc-toggle top-doc"]/*[@class="docblock"]' 'a dog 4 2 1' +// @has - '//*[@class="toggle top-doc"]/*[@class="docblock"]' 'a dog 4 2 1' /// a dog pub use c::Woof; diff --git a/tests/rustdoc/strip-block-doc-comments-stars.rs b/tests/rustdoc/strip-block-doc-comments-stars.rs index ea28d84f1ffd..ca4c93f92e0a 100644 --- a/tests/rustdoc/strip-block-doc-comments-stars.rs +++ b/tests/rustdoc/strip-block-doc-comments-stars.rs @@ -4,7 +4,7 @@ // block doc comments can have their lines starting with a star. // @has foo/fn.foo.html -// @snapshot docblock - '//*[@class="rustdoc-toggle top-doc"]//*[@class="docblock"]' +// @snapshot docblock - '//*[@class="toggle top-doc"]//*[@class="docblock"]' /** * a */ diff --git a/tests/rustdoc/toggle-item-contents.rs b/tests/rustdoc/toggle-item-contents.rs index 47a1d62f5a7a..87240f233ff2 100644 --- a/tests/rustdoc/toggle-item-contents.rs +++ b/tests/rustdoc/toggle-item-contents.rs @@ -1,15 +1,15 @@ #![allow(unused)] // @has 'toggle_item_contents/struct.PubStruct.html' -// @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 0 +// @count - '//details[@class="toggle type-contents-toggle"]' 0 pub struct PubStruct { pub a: usize, pub b: usize, } // @has 'toggle_item_contents/struct.BigPubStruct.html' -// @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 1 -// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show 13 fields' +// @count - '//details[@class="toggle type-contents-toggle"]' 1 +// @has - '//details[@class="toggle type-contents-toggle"]' 'Show 13 fields' pub struct BigPubStruct { pub a: usize, pub b: usize, @@ -27,8 +27,8 @@ pub struct BigPubStruct { } // @has 'toggle_item_contents/union.BigUnion.html' -// @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 1 -// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show 13 fields' +// @count - '//details[@class="toggle type-contents-toggle"]' 1 +// @has - '//details[@class="toggle type-contents-toggle"]' 'Show 13 fields' pub union BigUnion { pub a: usize, pub b: usize, @@ -46,7 +46,7 @@ pub union BigUnion { } // @has 'toggle_item_contents/union.Union.html' -// @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 0 +// @count - '//details[@class="toggle type-contents-toggle"]' 0 pub union Union { pub a: usize, pub b: usize, @@ -54,7 +54,7 @@ pub union Union { } // @has 'toggle_item_contents/struct.PrivStruct.html' -// @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 0 +// @count - '//details[@class="toggle type-contents-toggle"]' 0 // @has - '//div[@class="item-decl"]' '/* private fields */' pub struct PrivStruct { a: usize, @@ -62,7 +62,7 @@ pub struct PrivStruct { } // @has 'toggle_item_contents/enum.Enum.html' -// @!has - '//details[@class="rustdoc-toggle type-contents-toggle"]' '' +// @!has - '//details[@class="toggle type-contents-toggle"]' '' pub enum Enum { A, B, C, D { @@ -72,7 +72,7 @@ pub enum Enum { } // @has 'toggle_item_contents/enum.EnumStructVariant.html' -// @!has - '//details[@class="rustdoc-toggle type-contents-toggle"]' '' +// @!has - '//details[@class="toggle type-contents-toggle"]' '' pub enum EnumStructVariant { A, B, C, D { @@ -81,14 +81,14 @@ pub enum EnumStructVariant { } // @has 'toggle_item_contents/enum.LargeEnum.html' -// @count - '//*[@class="rust enum"]//details[@class="rustdoc-toggle type-contents-toggle"]' 1 -// @has - '//*[@class="rust enum"]//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show 13 variants' +// @count - '//*[@class="rust enum"]//details[@class="toggle type-contents-toggle"]' 1 +// @has - '//*[@class="rust enum"]//details[@class="toggle type-contents-toggle"]' 'Show 13 variants' pub enum LargeEnum { A, B, C, D, E, F(u8), G, H, I, J, K, L, M } // @has 'toggle_item_contents/trait.Trait.html' -// @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 0 +// @count - '//details[@class="toggle type-contents-toggle"]' 0 pub trait Trait { type A; #[must_use] @@ -97,8 +97,8 @@ pub trait Trait { } // @has 'toggle_item_contents/trait.GinormousTrait.html' -// @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 1 -// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show 16 associated items' +// @count - '//details[@class="toggle type-contents-toggle"]' 1 +// @has - '//details[@class="toggle type-contents-toggle"]' 'Show 16 associated items' pub trait GinormousTrait { type A; type B; @@ -120,8 +120,8 @@ pub trait GinormousTrait { } // @has 'toggle_item_contents/trait.HugeTrait.html' -// @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 1 -// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show 12 associated constants and 2 methods' +// @count - '//details[@class="toggle type-contents-toggle"]' 1 +// @has - '//details[@class="toggle type-contents-toggle"]' 'Show 12 associated constants and 2 methods' pub trait HugeTrait { type A; const M: usize = 1; @@ -142,8 +142,8 @@ pub trait HugeTrait { } // @has 'toggle_item_contents/trait.GiganticTrait.html' -// @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 1 -// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show 1 associated constant and 1 method' +// @count - '//details[@class="toggle type-contents-toggle"]' 1 +// @has - '//details[@class="toggle type-contents-toggle"]' 'Show 1 associated constant and 1 method' pub trait GiganticTrait { type A; type B; @@ -163,8 +163,8 @@ pub trait GiganticTrait { } // @has 'toggle_item_contents/trait.BigTrait.html' -// @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 1 -// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show 14 methods' +// @count - '//details[@class="toggle type-contents-toggle"]' 1 +// @has - '//details[@class="toggle type-contents-toggle"]' 'Show 14 methods' pub trait BigTrait { type A; #[must_use] diff --git a/tests/rustdoc/toggle-method.rs b/tests/rustdoc/toggle-method.rs index 1aa74e596596..ebc316ca8ad2 100644 --- a/tests/rustdoc/toggle-method.rs +++ b/tests/rustdoc/toggle-method.rs @@ -4,9 +4,9 @@ // summary. Struct methods with no documentation should not be wrapped. // // @has foo/struct.Foo.html -// @has - '//details[@class="rustdoc-toggle method-toggle"]//summary//h4[@class="code-header"]' 'is_documented()' -// @has - '//details[@class="rustdoc-toggle method-toggle"]//*[@class="docblock"]' 'is_documented is documented' -// @!has - '//details[@class="rustdoc-toggle method-toggle"]//summary//h4[@class="code-header"]' 'not_documented()' +// @has - '//details[@class="toggle method-toggle"]//summary//h4[@class="code-header"]' 'is_documented()' +// @has - '//details[@class="toggle method-toggle"]//*[@class="docblock"]' 'is_documented is documented' +// @!has - '//details[@class="toggle method-toggle"]//summary//h4[@class="code-header"]' 'not_documented()' pub struct Foo { } diff --git a/tests/rustdoc/toggle-trait-fn.rs b/tests/rustdoc/toggle-trait-fn.rs index 0a1f088b9ab5..686a174fc8f9 100644 --- a/tests/rustdoc/toggle-trait-fn.rs +++ b/tests/rustdoc/toggle-trait-fn.rs @@ -4,14 +4,14 @@ // summary. Trait methods with no documentation should not be wrapped. // // @has foo/trait.Foo.html -// @has - '//details[@class="rustdoc-toggle"]//summary//h4[@class="code-header"]' 'type Item' -// @!has - '//details[@class="rustdoc-toggle"]//summary//h4[@class="code-header"]' 'type Item2' -// @has - '//details[@class="rustdoc-toggle method-toggle"]//summary//h4[@class="code-header"]' 'is_documented()' -// @!has - '//details[@class="rustdoc-toggle method-toggle"]//summary//h4[@class="code-header"]' 'not_documented()' -// @has - '//details[@class="rustdoc-toggle method-toggle"]//*[@class="docblock"]' 'is_documented is documented' -// @has - '//details[@class="rustdoc-toggle method-toggle"]//summary//h4[@class="code-header"]' 'is_documented_optional()' -// @!has - '//details[@class="rustdoc-toggle method-toggle"]//summary//h4[@class="code-header"]' 'not_documented_optional()' -// @has - '//details[@class="rustdoc-toggle method-toggle"]//*[@class="docblock"]' 'is_documented_optional is documented' +// @has - '//details[@class="toggle"]//summary//h4[@class="code-header"]' 'type Item' +// @!has - '//details[@class="toggle"]//summary//h4[@class="code-header"]' 'type Item2' +// @has - '//details[@class="toggle method-toggle"]//summary//h4[@class="code-header"]' 'is_documented()' +// @!has - '//details[@class="toggle method-toggle"]//summary//h4[@class="code-header"]' 'not_documented()' +// @has - '//details[@class="toggle method-toggle"]//*[@class="docblock"]' 'is_documented is documented' +// @has - '//details[@class="toggle method-toggle"]//summary//h4[@class="code-header"]' 'is_documented_optional()' +// @!has - '//details[@class="toggle method-toggle"]//summary//h4[@class="code-header"]' 'not_documented_optional()' +// @has - '//details[@class="toggle method-toggle"]//*[@class="docblock"]' 'is_documented_optional is documented' pub trait Foo { /// is documented type Item; From 8a755e6ca0a5510630b87f8d7d77f291e58b6163 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Fri, 13 Jan 2023 19:59:28 +0000 Subject: [PATCH 068/105] Update cargo 8 commits in d992ab4e9034930e7809749f04077045af8f4d79..1cd6d3803dfb0b342272862a8590f5dfc9f72573 2023-01-10 14:36:41 +0100 to 2023-01-12 18:40:36 +0000 - Fix for rust-lang/cargo#11555 (rust-lang/cargo#11568) - chore: Fix typos (rust-lang/cargo#11561) - fix(docs): fix typo learm => learn in cargo tree docs (rust-lang/cargo#11560) - Add fix for CVE-2022-46176 (rust-lang/cargo#11556) - Fix panic on target dependency errors. (rust-lang/cargo#11541) - Fix some doc links (rust-lang/cargo#11538) - Cargo by default saves credentials to `.cargo/credentials.toml` (rust-lang/cargo#11533) - Fix a typo in the registries documentation. (rust-lang/cargo#11535) --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index d992ab4e9034..1cd6d3803dfb 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit d992ab4e9034930e7809749f04077045af8f4d79 +Subproject commit 1cd6d3803dfb0b342272862a8590f5dfc9f72573 From 496edf97c5c150967217f886e14d355c4f9890d0 Mon Sep 17 00:00:00 2001 From: Tim Neumann Date: Fri, 6 Jan 2023 10:37:53 +0000 Subject: [PATCH 069/105] Update `rental` hack to work with remapped paths. --- compiler/rustc_expand/src/base.rs | 10 +- ...rr => pretty-print-hack-show.local.stderr} | 0 ...ut => pretty-print-hack-show.local.stdout} | 0 .../pretty-print-hack-show.remapped.stderr | 179 ++++++++++++++++++ .../pretty-print-hack-show.remapped.stdout | 44 +++++ tests/ui/proc-macro/pretty-print-hack-show.rs | 6 + 6 files changed, 235 insertions(+), 4 deletions(-) rename tests/ui/proc-macro/{pretty-print-hack-show.stderr => pretty-print-hack-show.local.stderr} (100%) rename tests/ui/proc-macro/{pretty-print-hack-show.stdout => pretty-print-hack-show.local.stdout} (100%) create mode 100644 tests/ui/proc-macro/pretty-print-hack-show.remapped.stderr create mode 100644 tests/ui/proc-macro/pretty-print-hack-show.remapped.stdout diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 00453f78287e..ffde8480c021 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -31,11 +31,11 @@ use rustc_span::edition::Edition; use rustc_span::hygiene::{AstPass, ExpnData, ExpnKind, LocalExpnId}; use rustc_span::source_map::SourceMap; use rustc_span::symbol::{kw, sym, Ident, Symbol}; -use rustc_span::{BytePos, FileName, RealFileName, Span, DUMMY_SP}; +use rustc_span::{BytePos, FileName, Span, DUMMY_SP}; use smallvec::{smallvec, SmallVec}; use std::iter; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::rc::Rc; pub(crate) use rustc_span::hygiene::MacroKind; @@ -1423,8 +1423,10 @@ fn pretty_printing_compatibility_hack(item: &Item, sess: &ParseSess) -> bool { if let [variant] = &*enum_def.variants { if variant.ident.name == sym::Input { let filename = sess.source_map().span_to_filename(item.ident.span); - if let FileName::Real(RealFileName::LocalPath(path)) = filename { - if let Some(c) = path + if let FileName::Real(real) = filename { + if let Some(c) = real + .local_path() + .unwrap_or(Path::new("")) .components() .flat_map(|c| c.as_os_str().to_str()) .find(|c| c.starts_with("rental") || c.starts_with("allsorts-rental")) diff --git a/tests/ui/proc-macro/pretty-print-hack-show.stderr b/tests/ui/proc-macro/pretty-print-hack-show.local.stderr similarity index 100% rename from tests/ui/proc-macro/pretty-print-hack-show.stderr rename to tests/ui/proc-macro/pretty-print-hack-show.local.stderr diff --git a/tests/ui/proc-macro/pretty-print-hack-show.stdout b/tests/ui/proc-macro/pretty-print-hack-show.local.stdout similarity index 100% rename from tests/ui/proc-macro/pretty-print-hack-show.stdout rename to tests/ui/proc-macro/pretty-print-hack-show.local.stdout diff --git a/tests/ui/proc-macro/pretty-print-hack-show.remapped.stderr b/tests/ui/proc-macro/pretty-print-hack-show.remapped.stderr new file mode 100644 index 000000000000..ab5013848891 --- /dev/null +++ b/tests/ui/proc-macro/pretty-print-hack-show.remapped.stderr @@ -0,0 +1,179 @@ +error: using an old version of `rental` + --> remapped/proc-macro/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + = note: `#[deny(proc_macro_back_compat)]` on by default + +error: using an old version of `rental` + --> remapped/proc-macro/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + +error: using an old version of `rental` + --> remapped/proc-macro/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + +error: using an old version of `rental` + --> remapped/proc-macro/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + +error: using an old version of `rental` + --> remapped/proc-macro/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + +error: using an old version of `rental` + --> remapped/proc-macro/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + +error: using an old version of `rental` + --> remapped/proc-macro/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + +error: using an old version of `rental` + --> remapped/proc-macro/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + +error: aborting due to 8 previous errors + +Future incompatibility report: Future breakage diagnostic: +error: using an old version of `rental` + --> remapped/proc-macro/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + = note: `#[deny(proc_macro_back_compat)]` on by default + +Future breakage diagnostic: +error: using an old version of `rental` + --> remapped/proc-macro/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + = note: `#[deny(proc_macro_back_compat)]` on by default + +Future breakage diagnostic: +error: using an old version of `rental` + --> remapped/proc-macro/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + = note: `#[deny(proc_macro_back_compat)]` on by default + +Future breakage diagnostic: +error: using an old version of `rental` + --> remapped/proc-macro/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + = note: `#[deny(proc_macro_back_compat)]` on by default + +Future breakage diagnostic: +error: using an old version of `rental` + --> remapped/proc-macro/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + = note: `#[deny(proc_macro_back_compat)]` on by default + +Future breakage diagnostic: +error: using an old version of `rental` + --> remapped/proc-macro/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + = note: `#[deny(proc_macro_back_compat)]` on by default + +Future breakage diagnostic: +error: using an old version of `rental` + --> remapped/proc-macro/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + = note: `#[deny(proc_macro_back_compat)]` on by default + +Future breakage diagnostic: +error: using an old version of `rental` + --> remapped/proc-macro/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6 + | +LL | enum ProceduralMasqueradeDummyType { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83125 + = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives + = note: `#[deny(proc_macro_back_compat)]` on by default + diff --git a/tests/ui/proc-macro/pretty-print-hack-show.remapped.stdout b/tests/ui/proc-macro/pretty-print-hack-show.remapped.stdout new file mode 100644 index 000000000000..61ca53b28d40 --- /dev/null +++ b/tests/ui/proc-macro/pretty-print-hack-show.remapped.stdout @@ -0,0 +1,44 @@ +PRINT-DERIVE INPUT (DISPLAY): enum ProceduralMasqueradeDummyType { Input, } +PRINT-DERIVE RE-COLLECTED (DISPLAY): enum ProceduralMasqueradeDummyType { Input } +PRINT-DERIVE INPUT (DEBUG): TokenStream [ + Ident { + ident: "enum", + span: remapped/proc-macro/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:1: 4:5 (#0), + }, + Ident { + ident: "ProceduralMasqueradeDummyType", + span: remapped/proc-macro/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6: 4:35 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "Input", + span: remapped/proc-macro/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:13:5: 13:10 (#0), + }, + ], + span: remapped/proc-macro/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:36: 14:2 (#0), + }, +] +PRINT-DERIVE INPUT (DISPLAY): enum ProceduralMasqueradeDummyType { Input, } +PRINT-DERIVE RE-COLLECTED (DISPLAY): enum ProceduralMasqueradeDummyType { Input } +PRINT-DERIVE INPUT (DEBUG): TokenStream [ + Ident { + ident: "enum", + span: remapped/proc-macro/pretty-print-hack/rental-0.5.5/src/lib.rs:4:1: 4:5 (#0), + }, + Ident { + ident: "ProceduralMasqueradeDummyType", + span: remapped/proc-macro/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6: 4:35 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Ident { + ident: "Input", + span: remapped/proc-macro/pretty-print-hack/rental-0.5.5/src/lib.rs:13:5: 13:10 (#0), + }, + ], + span: remapped/proc-macro/pretty-print-hack/rental-0.5.5/src/lib.rs:4:36: 14:2 (#0), + }, +] diff --git a/tests/ui/proc-macro/pretty-print-hack-show.rs b/tests/ui/proc-macro/pretty-print-hack-show.rs index 9b1899e49220..e9ff66ba45a0 100644 --- a/tests/ui/proc-macro/pretty-print-hack-show.rs +++ b/tests/ui/proc-macro/pretty-print-hack-show.rs @@ -1,5 +1,11 @@ // aux-build:test-macros.rs // compile-flags: -Z span-debug +// revisions: local remapped +// [remapped]compile-flags: --remap-path-prefix={{src-base}}=remapped + +// The remapped paths are not normalized by compiletest. +// normalize-stdout-test: "\\(proc-macro|pretty-print-hack)" -> "/$1" +// normalize-stderr-test: "\\(proc-macro|pretty-print-hack)" -> "/$1" #![no_std] // Don't load unnecessary hygiene information from std extern crate std; From 22a0e4fa6e08acf2de50ed87cfb909092ab0459d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 13 Jan 2023 20:50:34 +0000 Subject: [PATCH 070/105] Do not incorrectly suggest restricting implied bounds When we have already suggested bounds that imply the about to be suggested bound, skip them. --- .../rustc_hir_typeck/src/method/suggest.rs | 48 ++++++++++++++----- .../ui/missing-trait-bounds/issue-35677.fixed | 2 +- .../missing-trait-bounds/issue-35677.stderr | 4 +- 3 files changed, 38 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 338fabca3891..f49fde04e844 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -505,19 +505,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } _ => None, }; - if let Some(hir::Node::Item(hir::Item { kind, .. })) = node { - if let Some(g) = kind.generics() { - let key = ( - g.tail_span_for_predicate_suggestion(), - g.add_where_or_trailing_comma(), - ); - type_params - .entry(key) - .or_insert_with(FxHashSet::default) - .insert(obligation.to_owned()); - } + if let Some(hir::Node::Item(hir::Item { kind, .. })) = node + && let Some(g) = kind.generics() + { + let key = ( + g.tail_span_for_predicate_suggestion(), + g.add_where_or_trailing_comma(), + ); + type_params + .entry(key) + .or_insert_with(FxHashSet::default) + .insert(obligation.to_owned()); + return true; } } + false }; let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| { let msg = format!( @@ -732,19 +734,39 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { unsatisfied_bounds = true; } + let mut suggested_bounds = FxHashSet::default(); // The requirements that didn't have an `impl` span to show. let mut bound_list = unsatisfied_predicates .iter() .filter_map(|(pred, parent_pred, _cause)| { + let mut suggested = false; format_pred(*pred).map(|(p, self_ty)| { - collect_type_param_suggestions(self_ty, *pred, &p); + if let Some(parent) = parent_pred && suggested_bounds.contains(parent) { + // We don't suggest `PartialEq` when we already suggest `Eq`. + } else if !suggested_bounds.contains(pred) { + if collect_type_param_suggestions(self_ty, *pred, &p) { + suggested = true; + suggested_bounds.insert(pred); + } + } ( match parent_pred { None => format!("`{}`", &p), Some(parent_pred) => match format_pred(*parent_pred) { None => format!("`{}`", &p), Some((parent_p, _)) => { - collect_type_param_suggestions(self_ty, *parent_pred, &p); + if !suggested + && !suggested_bounds.contains(pred) + && !suggested_bounds.contains(parent_pred) + { + if collect_type_param_suggestions( + self_ty, + *parent_pred, + &p, + ) { + suggested_bounds.insert(pred); + } + } format!("`{}`\nwhich is required by `{}`", p, parent_p) } }, diff --git a/tests/ui/missing-trait-bounds/issue-35677.fixed b/tests/ui/missing-trait-bounds/issue-35677.fixed index c76b6bc9c185..08174d8d8d53 100644 --- a/tests/ui/missing-trait-bounds/issue-35677.fixed +++ b/tests/ui/missing-trait-bounds/issue-35677.fixed @@ -3,7 +3,7 @@ use std::collections::HashSet; use std::hash::Hash; -fn is_subset(this: &HashSet, other: &HashSet) -> bool where T: Eq, T: Hash, T: PartialEq { +fn is_subset(this: &HashSet, other: &HashSet) -> bool where T: Eq, T: Hash { this.is_subset(other) //~^ ERROR the method } diff --git a/tests/ui/missing-trait-bounds/issue-35677.stderr b/tests/ui/missing-trait-bounds/issue-35677.stderr index 067b10b873ab..05d3de80d844 100644 --- a/tests/ui/missing-trait-bounds/issue-35677.stderr +++ b/tests/ui/missing-trait-bounds/issue-35677.stderr @@ -11,8 +11,8 @@ LL | this.is_subset(other) `T: Hash` help: consider restricting the type parameters to satisfy the trait bounds | -LL | fn is_subset(this: &HashSet, other: &HashSet) -> bool where T: Eq, T: Hash, T: PartialEq { - | ++++++++++++++++++++++++++++++++++ +LL | fn is_subset(this: &HashSet, other: &HashSet) -> bool where T: Eq, T: Hash { + | ++++++++++++++++++++ error: aborting due to previous error From b047aec122c291a6e9e32e45ec2c4d715f6415ab Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 9 Jan 2023 09:00:09 -0800 Subject: [PATCH 071/105] Update the wasi-libc used for the wasm32-wasi target This commit updates the wasi-libc revision used to build with the wasm32-wasi target. This notably pulls in WebAssembly/wasi-libc#377 which is needed to fix a use case I've been working on recently. This should be a relatively small update hopefully and is not expected to have any user impact. --- .../docker/host-x86_64/dist-various-2/build-wasi-toolchain.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 67cee0148b24..5fbce36c39d2 100755 --- a/src/ci/docker/host-x86_64/dist-various-2/build-wasi-toolchain.sh +++ b/src/ci/docker/host-x86_64/dist-various-2/build-wasi-toolchain.sh @@ -10,7 +10,7 @@ bin="$PWD/clang+llvm-15.0.6-x86_64-linux-gnu-ubuntu-18.04/bin" git clone https://github.com/WebAssembly/wasi-libc cd wasi-libc -git reset --hard 8b7148f69ae241a2749b3defe4606da8143b72e0 +git reset --hard 4362b1885fd369e042a7c0ecd8df3b6cd47fb4e8 make -j$(nproc) \ CC="$bin/clang" \ NM="$bin/llvm-nm" \ From 5314ed5627f99a1956c792cd493493c0edf23a93 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Fri, 13 Jan 2023 15:42:29 -0700 Subject: [PATCH 072/105] rustdoc: remove `docblock` class from notable trait popover This commit builds on b72de9be74dd5ac1d8b23d5ece03a7690274a14c, which removes the `docblock` class from the All Items page, and 9457380ac902db3febf92077c5b645db55998ad4, which removes the `docblock` class from the item decl. Fixes #92974 --- src/librustdoc/html/render/mod.rs | 2 +- src/librustdoc/html/static/css/rustdoc.css | 8 ++++++-- src/librustdoc/html/static/js/main.js | 2 +- .../rustdoc/doc-notable_trait-slice.bare_fn_matches.html | 2 +- tests/rustdoc/doc-notable_trait.bare-fn.html | 2 +- tests/rustdoc/doc-notable_trait.some-struct-new.html | 2 +- tests/rustdoc/doc-notable_trait.wrap-me.html | 2 +- tests/rustdoc/spotlight-from-dependency.odd.html | 2 +- 8 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 8bccf68029aa..a3a89ae5c154 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -1343,7 +1343,7 @@ fn notable_traits_decl(ty: &clean::Type, cx: &Context<'_>) -> (String, String) { write!( &mut out, "

Notable traits for {}

\ -
",
+                     
",
                         impl_.for_.print(cx)
                     );
                 }
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index b2fa6e82acce..b7d324f8fa94 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -1214,11 +1214,11 @@ a.test-arrow:hover {
 	content: "\00a0";
 }
 
-.notable .docblock {
+.notable .content {
 	margin: 0.25em 0.5em;
 }
 
-.notable .docblock pre, .notable .docblock code {
+.notable .content pre, .notable .content code {
 	background: transparent;
 	margin: 0;
 	padding: 0;
@@ -1226,6 +1226,10 @@ a.test-arrow:hover {
 	white-space: pre-wrap;
 }
 
+.notable .content > h3:first-child {
+	margin: 0 0 5px 0;
+}
+
 .search-failed {
 	text-align: center;
 	margin-top: 20px;
diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js
index 51aee8e7c899..98f315632897 100644
--- a/src/librustdoc/html/static/js/main.js
+++ b/src/librustdoc/html/static/js/main.js
@@ -847,7 +847,7 @@ function loadCss(cssUrl) {
         window.hideAllModals(false);
         const ty = e.getAttribute("data-ty");
         const wrapper = document.createElement("div");
-        wrapper.innerHTML = "
" + window.NOTABLE_TRAITS[ty] + "
"; + wrapper.innerHTML = "
" + window.NOTABLE_TRAITS[ty] + "
"; wrapper.className = "notable popover"; const focusCatcher = document.createElement("div"); focusCatcher.setAttribute("tabindex", "0"); diff --git a/tests/rustdoc/doc-notable_trait-slice.bare_fn_matches.html b/tests/rustdoc/doc-notable_trait-slice.bare_fn_matches.html index f2ec8320a052..46be00a08048 100644 --- a/tests/rustdoc/doc-notable_trait-slice.bare_fn_matches.html +++ b/tests/rustdoc/doc-notable_trait-slice.bare_fn_matches.html @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/tests/rustdoc/doc-notable_trait.bare-fn.html b/tests/rustdoc/doc-notable_trait.bare-fn.html index b426a4d7a8b7..f592e3b375c0 100644 --- a/tests/rustdoc/doc-notable_trait.bare-fn.html +++ b/tests/rustdoc/doc-notable_trait.bare-fn.html @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/tests/rustdoc/doc-notable_trait.some-struct-new.html b/tests/rustdoc/doc-notable_trait.some-struct-new.html index 4f8063807e67..384be6689540 100644 --- a/tests/rustdoc/doc-notable_trait.some-struct-new.html +++ b/tests/rustdoc/doc-notable_trait.some-struct-new.html @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/tests/rustdoc/doc-notable_trait.wrap-me.html b/tests/rustdoc/doc-notable_trait.wrap-me.html index bed2a38b24a2..0cc1ee10fd33 100644 --- a/tests/rustdoc/doc-notable_trait.wrap-me.html +++ b/tests/rustdoc/doc-notable_trait.wrap-me.html @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/tests/rustdoc/spotlight-from-dependency.odd.html b/tests/rustdoc/spotlight-from-dependency.odd.html index 1d02c13ebfb3..5f54b7522ae3 100644 --- a/tests/rustdoc/spotlight-from-dependency.odd.html +++ b/tests/rustdoc/spotlight-from-dependency.odd.html @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file From b2df88bae1318689c86c69655268ca2d2afc0f81 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 27 Dec 2022 01:55:54 +0000 Subject: [PATCH 073/105] Consolidate two almost duplicated fn info extraction routines --- compiler/rustc_hir_typeck/src/callee.rs | 3 +- .../src/fn_ctxt/suggestions.rs | 103 +------- .../rustc_hir_typeck/src/method/suggest.rs | 6 +- .../src/traits/error_reporting/mod.rs | 1 + .../src/traits/error_reporting/suggestions.rs | 221 +++++++++++------- .../call-on-unimplemented-with-autoderef.rs | 13 ++ ...all-on-unimplemented-with-autoderef.stderr | 21 ++ 7 files changed, 183 insertions(+), 185 deletions(-) create mode 100644 tests/ui/suggestions/call-on-unimplemented-with-autoderef.rs create mode 100644 tests/ui/suggestions/call-on-unimplemented-with-autoderef.stderr diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index 8d417290407e..f1a4f94cd015 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -659,8 +659,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; if !self.maybe_suggest_bad_array_definition(&mut err, call_expr, callee_expr) { - if let Some((maybe_def, output_ty, _)) = - self.extract_callable_info(callee_expr, callee_ty) + if let Some((maybe_def, output_ty, _)) = self.extract_callable_info(callee_ty) && !self.type_is_sized_modulo_regions(self.param_env, output_ty, callee_expr.span) { let descr = match maybe_def { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 005bd164065d..76f33be7a389 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -11,7 +11,6 @@ use rustc_hir::{ Expr, ExprKind, GenericBound, Node, Path, QPath, Stmt, StmtKind, TyKind, WherePredicate, }; use rustc_hir_analysis::astconv::AstConv; -use rustc_infer::infer; use rustc_infer::traits::{self, StatementAsExpression}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::{ @@ -23,9 +22,9 @@ use rustc_span::source_map::Spanned; use rustc_span::symbol::{sym, Ident}; use rustc_span::{Span, Symbol}; use rustc_trait_selection::infer::InferCtxtExt; +use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt; use rustc_trait_selection::traits::error_reporting::DefIdOrName; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _; -use rustc_trait_selection::traits::NormalizeExt; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub(crate) fn body_fn_sig(&self) -> Option> { @@ -94,7 +93,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { found: Ty<'tcx>, can_satisfy: impl FnOnce(Ty<'tcx>) -> bool, ) -> bool { - let Some((def_id_or_name, output, inputs)) = self.extract_callable_info(expr, found) + let Some((def_id_or_name, output, inputs)) = self.extract_callable_info(found) else { return false; }; if can_satisfy(output) { let (sugg_call, mut applicability) = match inputs.len() { @@ -163,99 +162,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// because the callable type must also be well-formed to be called. pub(in super::super) fn extract_callable_info( &self, - expr: &Expr<'_>, - found: Ty<'tcx>, + ty: Ty<'tcx>, ) -> Option<(DefIdOrName, Ty<'tcx>, Vec>)> { - // Autoderef is useful here because sometimes we box callables, etc. - let Some((def_id_or_name, output, inputs)) = self.autoderef(expr.span, found).silence_errors().find_map(|(found, _)| { - match *found.kind() { - ty::FnPtr(fn_sig) => - Some((DefIdOrName::Name("function pointer"), fn_sig.output(), fn_sig.inputs())), - ty::FnDef(def_id, _) => { - let fn_sig = found.fn_sig(self.tcx); - Some((DefIdOrName::DefId(def_id), fn_sig.output(), fn_sig.inputs())) - } - ty::Closure(def_id, substs) => { - let fn_sig = substs.as_closure().sig(); - Some((DefIdOrName::DefId(def_id), fn_sig.output(), fn_sig.inputs().map_bound(|inputs| &inputs[1..]))) - } - ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => { - self.tcx.bound_item_bounds(def_id).subst(self.tcx, substs).iter().find_map(|pred| { - if let ty::PredicateKind::Clause(ty::Clause::Projection(proj)) = pred.kind().skip_binder() - && Some(proj.projection_ty.def_id) == self.tcx.lang_items().fn_once_output() - // args tuple will always be substs[1] - && let ty::Tuple(args) = proj.projection_ty.substs.type_at(1).kind() - { - Some(( - DefIdOrName::DefId(def_id), - pred.kind().rebind(proj.term.ty().unwrap()), - pred.kind().rebind(args.as_slice()), - )) - } else { - None - } - }) - } - ty::Dynamic(data, _, ty::Dyn) => { - data.iter().find_map(|pred| { - if let ty::ExistentialPredicate::Projection(proj) = pred.skip_binder() - && Some(proj.def_id) == self.tcx.lang_items().fn_once_output() - // for existential projection, substs are shifted over by 1 - && let ty::Tuple(args) = proj.substs.type_at(0).kind() - { - Some(( - DefIdOrName::Name("trait object"), - pred.rebind(proj.term.ty().unwrap()), - pred.rebind(args.as_slice()), - )) - } else { - None - } - }) - } - ty::Param(param) => { - let def_id = self.tcx.generics_of(self.body_id.owner).type_param(¶m, self.tcx).def_id; - self.tcx.predicates_of(self.body_id.owner).predicates.iter().find_map(|(pred, _)| { - if let ty::PredicateKind::Clause(ty::Clause::Projection(proj)) = pred.kind().skip_binder() - && Some(proj.projection_ty.def_id) == self.tcx.lang_items().fn_once_output() - && proj.projection_ty.self_ty() == found - // args tuple will always be substs[1] - && let ty::Tuple(args) = proj.projection_ty.substs.type_at(1).kind() - { - Some(( - DefIdOrName::DefId(def_id), - pred.kind().rebind(proj.term.ty().unwrap()), - pred.kind().rebind(args.as_slice()), - )) - } else { - None - } - }) - } - _ => None, - } - }) else { return None; }; - - let output = self.replace_bound_vars_with_fresh_vars(expr.span, infer::FnCall, output); - let inputs = inputs - .skip_binder() - .iter() - .map(|ty| { - self.replace_bound_vars_with_fresh_vars( - expr.span, - infer::FnCall, - inputs.rebind(*ty), - ) - }) - .collect(); - - // We don't want to register any extra obligations, which should be - // implied by wf, but also because that would possibly result in - // erroneous errors later on. - let infer::InferOk { value: output, obligations: _ } = - self.at(&self.misc(expr.span), self.param_env).normalize(output); - - if output.is_ty_var() { None } else { Some((def_id_or_name, output, inputs)) } + self.err_ctxt().extract_callable_info(self.body_id, self.param_env, ty) } pub fn suggest_two_fn_call( @@ -267,9 +176,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { rhs_ty: Ty<'tcx>, can_satisfy: impl FnOnce(Ty<'tcx>, Ty<'tcx>) -> bool, ) -> bool { - let Some((_, lhs_output_ty, lhs_inputs)) = self.extract_callable_info(lhs_expr, lhs_ty) + let Some((_, lhs_output_ty, lhs_inputs)) = self.extract_callable_info(lhs_ty) else { return false; }; - let Some((_, rhs_output_ty, rhs_inputs)) = self.extract_callable_info(rhs_expr, rhs_ty) + let Some((_, rhs_output_ty, rhs_inputs)) = self.extract_callable_info(rhs_ty) else { return false; }; if can_satisfy(lhs_output_ty, rhs_output_ty) { diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 8166eb829904..7e2581033724 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -2662,8 +2662,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { found: Ty<'tcx>, expected: Ty<'tcx>, ) -> bool { - let Some((_def_id_or_name, output, _inputs)) = self.extract_callable_info(expr, found) - else { return false; }; + let Some((_def_id_or_name, output, _inputs)) = + self.extract_callable_info(found) else { + return false; + }; if !self.can_coerce(output, expected) { return false; 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 0c7ffb056cc0..940fc29841b0 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -2912,6 +2912,7 @@ impl<'tcx> ty::TypeVisitor<'tcx> for HasNumericInferVisitor { } } +#[derive(Copy, Clone)] pub enum DefIdOrName { DefId(DefId), Name(&'static str), 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 1b98ead29f85..48c32a446c52 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -212,6 +212,13 @@ pub trait TypeErrCtxtExt<'tcx> { trait_pred: ty::PolyTraitPredicate<'tcx>, ) -> bool; + fn extract_callable_info( + &self, + hir_id: HirId, + param_env: ty::ParamEnv<'tcx>, + found: Ty<'tcx>, + ) -> Option<(DefIdOrName, Ty<'tcx>, Vec>)>; + fn suggest_add_reference_to_arg( &self, obligation: &PredicateObligation<'tcx>, @@ -885,92 +892,17 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { return false; } - // This is duplicated from `extract_callable_info` in typeck, which - // relies on autoderef, so we can't use it here. - let found = trait_pred.self_ty().skip_binder().peel_refs(); - let Some((def_id_or_name, output, inputs)) = (match *found.kind() - { - ty::FnPtr(fn_sig) => { - Some((DefIdOrName::Name("function pointer"), fn_sig.output(), fn_sig.inputs())) - } - ty::FnDef(def_id, _) => { - let fn_sig = found.fn_sig(self.tcx); - Some((DefIdOrName::DefId(def_id), fn_sig.output(), fn_sig.inputs())) - } - ty::Closure(def_id, substs) => { - let fn_sig = substs.as_closure().sig(); - Some(( - DefIdOrName::DefId(def_id), - fn_sig.output(), - fn_sig.inputs().map_bound(|inputs| &inputs[1..]), - )) - } - ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => { - self.tcx.bound_item_bounds(def_id).subst(self.tcx, substs).iter().find_map(|pred| { - if let ty::PredicateKind::Clause(ty::Clause::Projection(proj)) = pred.kind().skip_binder() - && Some(proj.projection_ty.def_id) == self.tcx.lang_items().fn_once_output() - // args tuple will always be substs[1] - && let ty::Tuple(args) = proj.projection_ty.substs.type_at(1).kind() - { - Some(( - DefIdOrName::DefId(def_id), - pred.kind().rebind(proj.term.ty().unwrap()), - pred.kind().rebind(args.as_slice()), - )) - } else { - None - } - }) - } - ty::Dynamic(data, _, ty::Dyn) => { - data.iter().find_map(|pred| { - if let ty::ExistentialPredicate::Projection(proj) = pred.skip_binder() - && Some(proj.def_id) == self.tcx.lang_items().fn_once_output() - // for existential projection, substs are shifted over by 1 - && let ty::Tuple(args) = proj.substs.type_at(0).kind() - { - Some(( - DefIdOrName::Name("trait object"), - pred.rebind(proj.term.ty().unwrap()), - pred.rebind(args.as_slice()), - )) - } else { - None - } - }) - } - ty::Param(_) => { - obligation.param_env.caller_bounds().iter().find_map(|pred| { - if let ty::PredicateKind::Clause(ty::Clause::Projection(proj)) = pred.kind().skip_binder() - && Some(proj.projection_ty.def_id) == self.tcx.lang_items().fn_once_output() - && proj.projection_ty.self_ty() == found - // args tuple will always be substs[1] - && let ty::Tuple(args) = proj.projection_ty.substs.type_at(1).kind() - { - Some(( - DefIdOrName::Name("type parameter"), - pred.kind().rebind(proj.term.ty().unwrap()), - pred.kind().rebind(args.as_slice()), - )) - } else { - None - } - }) - } - _ => None, - }) else { return false; }; - let output = self.replace_bound_vars_with_fresh_vars( - obligation.cause.span, + let self_ty = self.replace_bound_vars_with_fresh_vars( + DUMMY_SP, LateBoundRegionConversionTime::FnCall, - output, + trait_pred.self_ty(), ); - let inputs = inputs.skip_binder().iter().map(|ty| { - self.replace_bound_vars_with_fresh_vars( - obligation.cause.span, - LateBoundRegionConversionTime::FnCall, - inputs.rebind(*ty), - ) - }); + + let Some((def_id_or_name, output, inputs)) = self.extract_callable_info( + obligation.cause.body_id, + obligation.param_env, + self_ty, + ) else { return false; }; // Remapping bound vars here let trait_pred_and_self = trait_pred.map_bound(|trait_pred| (trait_pred, output)); @@ -998,6 +930,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { }; let args = inputs + .into_iter() .map(|ty| { if ty.is_suggestable(self.tcx, false) { format!("/* {ty} */") @@ -1161,6 +1094,126 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { false } + /// Extracts information about a callable type for diagnostics. This is a + /// heuristic -- it doesn't necessarily mean that a type is always callable, + /// because the callable type must also be well-formed to be called. + fn extract_callable_info( + &self, + hir_id: HirId, + param_env: ty::ParamEnv<'tcx>, + found: Ty<'tcx>, + ) -> Option<(DefIdOrName, Ty<'tcx>, Vec>)> { + // Autoderef is useful here because sometimes we box callables, etc. + let Some((def_id_or_name, output, inputs)) = Autoderef::new( + self, + param_env, + hir_id, + DUMMY_SP, + found, + ).silence_errors().find_map(|(found, _)| { + match *found.kind() { + ty::FnPtr(fn_sig) => + Some((DefIdOrName::Name("function pointer"), fn_sig.output(), fn_sig.inputs())), + ty::FnDef(def_id, _) => { + let fn_sig = found.fn_sig(self.tcx); + Some((DefIdOrName::DefId(def_id), fn_sig.output(), fn_sig.inputs())) + } + ty::Closure(def_id, substs) => { + let fn_sig = substs.as_closure().sig(); + Some((DefIdOrName::DefId(def_id), fn_sig.output(), fn_sig.inputs().map_bound(|inputs| &inputs[1..]))) + } + ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => { + self.tcx.bound_item_bounds(def_id).subst(self.tcx, substs).iter().find_map(|pred| { + if let ty::PredicateKind::Clause(ty::Clause::Projection(proj)) = pred.kind().skip_binder() + && Some(proj.projection_ty.def_id) == self.tcx.lang_items().fn_once_output() + // args tuple will always be substs[1] + && let ty::Tuple(args) = proj.projection_ty.substs.type_at(1).kind() + { + Some(( + DefIdOrName::DefId(def_id), + pred.kind().rebind(proj.term.ty().unwrap()), + pred.kind().rebind(args.as_slice()), + )) + } else { + None + } + }) + } + ty::Dynamic(data, _, ty::Dyn) => { + data.iter().find_map(|pred| { + if let ty::ExistentialPredicate::Projection(proj) = pred.skip_binder() + && Some(proj.def_id) == self.tcx.lang_items().fn_once_output() + // for existential projection, substs are shifted over by 1 + && let ty::Tuple(args) = proj.substs.type_at(0).kind() + { + Some(( + DefIdOrName::Name("trait object"), + pred.rebind(proj.term.ty().unwrap()), + pred.rebind(args.as_slice()), + )) + } else { + None + } + }) + } + ty::Param(param) => { + let generics = self.tcx.generics_of(hir_id.owner.to_def_id()); + let name = if generics.count() > param.index as usize + && let def = generics.param_at(param.index as usize, self.tcx) + && matches!(def.kind, ty::GenericParamDefKind::Type { .. }) + && def.name == param.name + { + DefIdOrName::DefId(def.def_id) + } else { + DefIdOrName::Name("type parameter") + }; + param_env.caller_bounds().iter().find_map(|pred| { + if let ty::PredicateKind::Clause(ty::Clause::Projection(proj)) = pred.kind().skip_binder() + && Some(proj.projection_ty.def_id) == self.tcx.lang_items().fn_once_output() + && proj.projection_ty.self_ty() == found + // args tuple will always be substs[1] + && let ty::Tuple(args) = proj.projection_ty.substs.type_at(1).kind() + { + Some(( + name, + pred.kind().rebind(proj.term.ty().unwrap()), + pred.kind().rebind(args.as_slice()), + )) + } else { + None + } + }) + } + _ => None, + } + }) else { return None; }; + + let output = self.replace_bound_vars_with_fresh_vars( + DUMMY_SP, + LateBoundRegionConversionTime::FnCall, + output, + ); + let inputs = inputs + .skip_binder() + .iter() + .map(|ty| { + self.replace_bound_vars_with_fresh_vars( + DUMMY_SP, + LateBoundRegionConversionTime::FnCall, + inputs.rebind(*ty), + ) + }) + .collect(); + + // We don't want to register any extra obligations, which should be + // implied by wf, but also because that would possibly result in + // erroneous errors later on. + let InferOk { value: output, obligations: _ } = + self.at(&ObligationCause::dummy(), param_env).normalize(output); + + if output.is_ty_var() { None } else { Some((def_id_or_name, output, inputs)) } + } + fn suggest_add_reference_to_arg( &self, obligation: &PredicateObligation<'tcx>, diff --git a/tests/ui/suggestions/call-on-unimplemented-with-autoderef.rs b/tests/ui/suggestions/call-on-unimplemented-with-autoderef.rs new file mode 100644 index 000000000000..9021dd752e7e --- /dev/null +++ b/tests/ui/suggestions/call-on-unimplemented-with-autoderef.rs @@ -0,0 +1,13 @@ +trait Foo {} + +impl Foo for i32 {} + +fn needs_foo(_: impl Foo) {} + +fn test(x: &Box i32>) { + needs_foo(x); + //~^ ERROR the trait bound + //~| HELP use parentheses to call this trait object +} + +fn main() {} diff --git a/tests/ui/suggestions/call-on-unimplemented-with-autoderef.stderr b/tests/ui/suggestions/call-on-unimplemented-with-autoderef.stderr new file mode 100644 index 000000000000..90f44cce06e4 --- /dev/null +++ b/tests/ui/suggestions/call-on-unimplemented-with-autoderef.stderr @@ -0,0 +1,21 @@ +error[E0277]: the trait bound `&Box i32>: Foo` is not satisfied + --> $DIR/call-on-unimplemented-with-autoderef.rs:8:15 + | +LL | needs_foo(x); + | --------- ^ the trait `Foo` is not implemented for `&Box i32>` + | | + | required by a bound introduced by this call + | +note: required by a bound in `needs_foo` + --> $DIR/call-on-unimplemented-with-autoderef.rs:5:22 + | +LL | fn needs_foo(_: impl Foo) {} + | ^^^ required by this bound in `needs_foo` +help: use parentheses to call this trait object + | +LL | needs_foo(x()); + | ++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. From c1a7dbc0e3511b144f7051a065b9467871ad6ef9 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 13 Jan 2023 22:12:06 +0000 Subject: [PATCH 074/105] Rebase conflicts --- .../src/traits/error_reporting/suggestions.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) 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 48c32a446c52..5211f873a1e3 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -885,6 +885,12 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { err: &mut Diagnostic, trait_pred: ty::PolyTraitPredicate<'tcx>, ) -> bool { + // It doesn't make sense to make this suggestion outside of typeck... + // (also autoderef will ICE...) + if self.typeck_results.is_none() { + return false; + } + if let ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) = obligation.predicate.kind().skip_binder() && Some(trait_pred.def_id()) == self.tcx.lang_items().sized_trait() { @@ -1104,13 +1110,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { found: Ty<'tcx>, ) -> Option<(DefIdOrName, Ty<'tcx>, Vec>)> { // Autoderef is useful here because sometimes we box callables, etc. - let Some((def_id_or_name, output, inputs)) = Autoderef::new( - self, - param_env, - hir_id, - DUMMY_SP, - found, - ).silence_errors().find_map(|(found, _)| { + let Some((def_id_or_name, output, inputs)) = (self.autoderef_steps)(found).into_iter().find_map(|(found, _)| { match *found.kind() { ty::FnPtr(fn_sig) => Some((DefIdOrName::Name("function pointer"), fn_sig.output(), fn_sig.inputs())), From a1614d0cf8472a20717135a377e55281fab440dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 14 Jan 2023 01:17:18 +0000 Subject: [PATCH 075/105] Use GitHub yaml templates for ICE, Docs and Diagnostics tickets --- .github/ISSUE_TEMPLATE/diagnostics.md | 46 ------------- .github/ISSUE_TEMPLATE/diagnostics.yaml | 65 ++++++++++++++++++ .github/ISSUE_TEMPLATE/documentation.md | 31 --------- .github/ISSUE_TEMPLATE/documentation.yaml | 38 +++++++++++ .github/ISSUE_TEMPLATE/ice.md | 52 -------------- .github/ISSUE_TEMPLATE/ice.yaml | 82 +++++++++++++++++++++++ 6 files changed, 185 insertions(+), 129 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/diagnostics.md create mode 100644 .github/ISSUE_TEMPLATE/diagnostics.yaml delete mode 100644 .github/ISSUE_TEMPLATE/documentation.md create mode 100644 .github/ISSUE_TEMPLATE/documentation.yaml delete mode 100644 .github/ISSUE_TEMPLATE/ice.md create mode 100644 .github/ISSUE_TEMPLATE/ice.yaml diff --git a/.github/ISSUE_TEMPLATE/diagnostics.md b/.github/ISSUE_TEMPLATE/diagnostics.md deleted file mode 100644 index a7b70cea927d..000000000000 --- a/.github/ISSUE_TEMPLATE/diagnostics.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -name: Diagnostic issue -about: Create a bug report or feature request for a change to `rustc`'s error output -labels: A-diagnostics, T-compiler ---- - - -Given the following code: - -```rust - -``` - -The current output is: - -``` - -``` - - -Ideally the output should look like: - -``` - -``` - - - - diff --git a/.github/ISSUE_TEMPLATE/diagnostics.yaml b/.github/ISSUE_TEMPLATE/diagnostics.yaml new file mode 100644 index 000000000000..873fbaaf654f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/diagnostics.yaml @@ -0,0 +1,65 @@ +name: Diagnostic issue +description: Create a bug report or feature request for a change to `rustc`'s error output +labels: ["A-diagnostics", "T-compiler"] +body: + - type: markdown + attributes: + value: | + Thank you for filing a diagnostics bug report! 🐛 + + Please provide a short summary of the bug, along with any information you feel relevant to replicating the bug. + + If you cannot produce a minimal reproduction case (something that would work in isolation), please provide the steps or even link to a repository that causes the problematic output to occur. + - type: textarea + id: code + attributes: + label: Code + description: Please provide code that can reproduce the problem + placeholder: code + render: Rust + validations: + required: true + - type: textarea + id: output + attributes: + label: Current output + description: Please provide the `rustc` output you see + placeholder: rustc output + render: Shell + validations: + required: true + - type: textarea + id: desired-output + attributes: + label: Desired output + description: Please provide what the output *should* be + placeholder: proposed output + render: Shell + validations: + required: false + - type: textarea + id: rationale + attributes: + label: Rationale and extra context + description: If the problem is not self-explanatory, please provide a rationale for the change. + validations: + required: false + - type: textarea + id: other-output + attributes: + label: Other cases + description: If dramatically different output is caused by small changes, consider also adding them here. + render: Rust + validations: + required: false + - type: markdown + attributes: + value: | + If you're using the stable version of the compiler, you should also check if the bug also exists in the beta or nightly versions. The output might also be different depending on the Edition. + - type: textarea + id: extra + attributes: + label: Anything else? + description: If you have more details you want to give us to reproduce this issue, please add it here + validations: + required: false \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/documentation.md b/.github/ISSUE_TEMPLATE/documentation.md deleted file mode 100644 index 9ccda17a6ef4..000000000000 --- a/.github/ISSUE_TEMPLATE/documentation.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -name: Documentation problem -about: Create a report for a documentation problem. -labels: A-docs ---- - - -### Location - -### Summary diff --git a/.github/ISSUE_TEMPLATE/documentation.yaml b/.github/ISSUE_TEMPLATE/documentation.yaml new file mode 100644 index 000000000000..712b32759ae0 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/documentation.yaml @@ -0,0 +1,38 @@ +name: Documentation problem +description: Create a report for a documentation problem. +labels: ["A-docs"] +body: + - type: markdown + attributes: + value: | + Thank you for finding a documentation problem! 📚 + + Documentation problems might be grammatical issues, typos, or unclear wording, please provide details regarding the documentation including where it is present. + + Note: If your issue is for one of these, please use their dedicated issue tracker instead: + - [The Rust Book](https://github.com/rust-lang/book/issues) + - [Rust by Example](https://github.com/rust-lang/rust-by-example/issues) + - [The Edition Guide](https://github.com/rust-lang/edition-guide/issues) + - [The Cargo Book](https://github.com/rust-lang/cargo/issues) + - [The Clippy Book](https://github.com/rust-lang/rust-clippy/issues) + - [The Reference](https://github.com/rust-lang/reference/issues) + - [The Rustonomicon](https://github.com/rust-lang/nomicon/issues) + - [The Embedded Book](https://github.com/rust-embedded/book/issues) + + All other documentation issues should be filed here. + + Or, if you find an issue related to rustdoc (e.g. doctest, rustdoc UI), please use the bug report or blank issue template instead. + + - type: textarea + id: location + attributes: + label: Location + validations: + required: true + + - type: textarea + id: summary + attributes: + label: Summary + validations: + required: true \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/ice.md b/.github/ISSUE_TEMPLATE/ice.md deleted file mode 100644 index 03bc4bab4513..000000000000 --- a/.github/ISSUE_TEMPLATE/ice.md +++ /dev/null @@ -1,52 +0,0 @@ ---- -name: Internal Compiler Error -about: Create a report for an internal compiler error in rustc. -labels: C-bug, I-ICE, T-compiler ---- - - -### Code - -```Rust - -``` - - -### Meta - - -`rustc --version --verbose`: -``` - -``` - -### Error output - -``` - -``` - - -
Backtrace -

- -``` - -``` - -

-
- diff --git a/.github/ISSUE_TEMPLATE/ice.yaml b/.github/ISSUE_TEMPLATE/ice.yaml new file mode 100644 index 000000000000..54136cc6d439 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/ice.yaml @@ -0,0 +1,82 @@ +name: Internal Compiler Error +description: Create a report for an internal compiler error in `rustc` +labels: ["C-bug", "I-ICE", "T-compiler"] +title: "[ICE]: " +body: + - type: markdown + attributes: + value: | + Thank you for finding an Internal Compiler Error! 🧊 + + If possible, try to provide a minimal verifiable example. + + You can read "[Rust Bug Minimization Patterns](http://blog.pnkfx.org/blog/2019/11/18/rust-bug-minimization-patterns/)" for how to create smaller examples. + + - type: textarea + id: code + attributes: + label: Code + description: Please provide code or a link to a repository that can reproduce the problem + placeholder: code + render: Rust + validations: + required: false + + - type: checkboxes + attributes: + label: Affected release channels + description: If you're using the stable version of the compiler, you should also check if the bug also exists in the beta or nightly versions + options: + - label: Previous Stable + required: false + - label: Current Stable + required: false + - label: Current Beta + required: false + - label: Current Nightly + required: false + + - type: textarea + id: version + attributes: + label: Rust Version + description: Please provide the `rustc` version, `rustc --version --verbose` + placeholder: | + $ rustc --version --verbose + rustc 1.XX.Y (SHORTHASH DATE) + binary: rustc + commit-hash: LONGHASHVALUE + commit-date: DATE + host: PLATFORMTRIPLE + release: 1.XX.Y + LLVM version: XX.YY.ZZ + render: Shell + validations: + required: true + + - type: textarea + id: output + attributes: + label: Current error output + description: Please provide the `rustc` output you see + placeholder: output + render: Shell + validations: + required: false + + - type: textarea + id: backtrace + attributes: + label: Backtrace + description: Include a backtrace in the code block by setting `RUST_BACKTRACE=full` in your environment, e.g. `RUST_BACKTRACE=full cargo build` + render: Shell + validations: + required: true + + - type: textarea + id: extra + attributes: + label: Anything else? + description: If you have more details you want to give us to reproduce this issue, please add it here + validations: + required: false \ No newline at end of file From c84917ad2efe6badd83d2acad64a2ad30ec68ddf Mon Sep 17 00:00:00 2001 From: Kyle Matsuda Date: Tue, 10 Jan 2023 11:53:35 -0700 Subject: [PATCH 076/105] add EarlyBinder::subst_identity; impl ParameterizedOverTcx (needed for rustc_metadata) and Value for EarlyBinder --- compiler/rustc_middle/src/ty/parameterized.rs | 4 ++++ compiler/rustc_middle/src/ty/subst.rs | 4 ++++ compiler/rustc_middle/src/values.rs | 12 ++++++++++++ 3 files changed, 20 insertions(+) diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs index 72f451985796..e32a7ee1c354 100644 --- a/compiler/rustc_middle/src/ty/parameterized.rs +++ b/compiler/rustc_middle/src/ty/parameterized.rs @@ -32,6 +32,10 @@ impl ParameterizedOverTcx for ty::Binder<'static, T> { type Value<'tcx> = ty::Binder<'tcx, T::Value<'tcx>>; } +impl ParameterizedOverTcx for ty::EarlyBinder { + type Value<'tcx> = ty::EarlyBinder>; +} + #[macro_export] macro_rules! trivially_parameterized_over_tcx { ($($ty:ty),+ $(,)?) => { diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs index 2dec58ea82a3..8f764011d0ac 100644 --- a/compiler/rustc_middle/src/ty/subst.rs +++ b/compiler/rustc_middle/src/ty/subst.rs @@ -713,6 +713,10 @@ impl<'tcx, T: TypeFoldable<'tcx>> ty::EarlyBinder { let mut folder = SubstFolder { tcx, substs, binders_passed: 0 }; self.0.fold_with(&mut folder) } + + pub fn subst_identity(self) -> T { + self.0 + } } /////////////////////////////////////////////////////////////////////////// diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_middle/src/values.rs index c242be570312..34e8a559784e 100644 --- a/compiler/rustc_middle/src/values.rs +++ b/compiler/rustc_middle/src/values.rs @@ -94,6 +94,18 @@ impl<'tcx> Value, DepKind> for Representability { } } +impl<'tcx> Value, DepKind> for ty::EarlyBinder> { + fn from_cycle_error(tcx: TyCtxt<'tcx>, cycle: &[QueryInfo]) -> Self { + ty::EarlyBinder(Ty::from_cycle_error(tcx, cycle)) + } +} + +impl<'tcx> Value, DepKind> for ty::EarlyBinder>> { + fn from_cycle_error(tcx: TyCtxt<'tcx>, cycle: &[QueryInfo]) -> Self { + ty::EarlyBinder(ty::Binder::from_cycle_error(tcx, cycle)) + } +} + // item_and_field_ids should form a cycle where each field contains the // type in the next element in the list pub fn recursive_type_error( From bd6c63597b9483aa65b0934f195716635a30a2b8 Mon Sep 17 00:00:00 2001 From: Kyle Matsuda Date: Tue, 10 Jan 2023 12:20:15 -0700 Subject: [PATCH 077/105] change usages of const_param_default query to bound_const_param_default --- compiler/rustc_hir_analysis/src/check/wfcheck.rs | 4 ++-- compiler/rustc_metadata/src/rmeta/encoder.rs | 2 +- compiler/rustc_privacy/src/lib.rs | 4 +++- src/librustdoc/clean/mod.rs | 4 +++- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 92fd4625ee83..cc29d40c0bec 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1350,7 +1350,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id // is incorrect when dealing with unused substs, for example // for `struct Foo` // we should eagerly error. - let default_ct = tcx.const_param_default(param.def_id); + let default_ct = tcx.bound_const_param_default(param.def_id).subst_identity(); if !default_ct.needs_subst() { wfcx.register_wf_obligation( tcx.def_span(param.def_id), @@ -1396,7 +1396,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id GenericParamDefKind::Const { .. } => { // If the param has a default, ... if is_our_default(param) { - let default_ct = tcx.const_param_default(param.def_id); + let default_ct = tcx.bound_const_param_default(param.def_id).subst_identity(); // ... and it's not a dependent default, ... if !default_ct.needs_subst() { // ... then substitute it with the default. diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 030328d1e26f..f7caf30c74c5 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -2070,7 +2070,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { hir::GenericParamKind::Const { ref default, .. } => { let def_id = param.def_id.to_def_id(); if default.is_some() { - record!(self.tables.const_param_default[def_id] <- self.tcx.const_param_default(def_id)) + record!(self.tables.const_param_default[def_id] <- self.tcx.bound_const_param_default(def_id).subst_identity()) } } } diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 564cb1baa690..9ee1e012ef20 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -838,7 +838,9 @@ impl ReachEverythingInTheInterfaceVisitor<'_, '_> { GenericParamDefKind::Const { has_default } => { self.visit(self.ev.tcx.type_of(param.def_id)); if has_default { - self.visit(self.ev.tcx.const_param_default(param.def_id)); + self.visit( + self.ev.tcx.bound_const_param_default(param.def_id).subst_identity(), + ); } } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 025a4379f45a..869c1e3512f4 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -506,7 +506,9 @@ fn clean_generic_param_def<'tcx>( Some(def.def_id), )), default: match has_default { - true => Some(Box::new(cx.tcx.const_param_default(def.def_id).to_string())), + true => Some(Box::new( + cx.tcx.bound_const_param_default(def.def_id).subst_identity().to_string(), + )), false => None, }, }, From ef58baf8b8fecc5ca8b5e34921d33650186d4205 Mon Sep 17 00:00:00 2001 From: Kyle Matsuda Date: Tue, 10 Jan 2023 12:27:41 -0700 Subject: [PATCH 078/105] change const_param_default query to return EarlyBinder; remove bound_const_param_default query; add EarlyBinder to const_param_default in metadata --- compiler/rustc_hir_analysis/src/astconv/mod.rs | 4 +--- compiler/rustc_hir_analysis/src/check/wfcheck.rs | 4 ++-- compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs | 4 +--- compiler/rustc_metadata/src/rmeta/encoder.rs | 2 +- compiler/rustc_metadata/src/rmeta/mod.rs | 2 +- compiler/rustc_middle/src/query/mod.rs | 2 +- compiler/rustc_middle/src/ty/consts.rs | 4 ++-- compiler/rustc_middle/src/ty/generics.rs | 2 +- compiler/rustc_middle/src/ty/util.rs | 4 ---- compiler/rustc_privacy/src/lib.rs | 4 +--- src/librustdoc/clean/mod.rs | 2 +- 11 files changed, 12 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 3521911b0552..d32c288337b5 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -511,9 +511,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { return tcx.const_error(ty).into(); } if !infer_args && has_default { - tcx.bound_const_param_default(param.def_id) - .subst(tcx, substs.unwrap()) - .into() + tcx.const_param_default(param.def_id).subst(tcx, substs.unwrap()).into() } else { if infer_args { self.astconv.ct_infer(ty, Some(param), self.span).into() diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index cc29d40c0bec..7c6da009dee3 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1350,7 +1350,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id // is incorrect when dealing with unused substs, for example // for `struct Foo` // we should eagerly error. - let default_ct = tcx.bound_const_param_default(param.def_id).subst_identity(); + let default_ct = tcx.const_param_default(param.def_id).subst_identity(); if !default_ct.needs_subst() { wfcx.register_wf_obligation( tcx.def_span(param.def_id), @@ -1396,7 +1396,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id GenericParamDefKind::Const { .. } => { // If the param has a default, ... if is_our_default(param) { - let default_ct = tcx.bound_const_param_default(param.def_id).subst_identity(); + let default_ct = tcx.const_param_default(param.def_id).subst_identity(); // ... and it's not a dependent default, ... if !default_ct.needs_subst() { // ... then substitute it with the default. diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 8570715b41e5..6ed8adb47425 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -1224,9 +1224,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } GenericParamDefKind::Const { has_default } => { if !infer_args && has_default { - tcx.bound_const_param_default(param.def_id) - .subst(tcx, substs.unwrap()) - .into() + tcx.const_param_default(param.def_id).subst(tcx, substs.unwrap()).into() } else { self.fcx.var_for_def(self.span, param) } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index f7caf30c74c5..030328d1e26f 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -2070,7 +2070,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { hir::GenericParamKind::Const { ref default, .. } => { let def_id = param.def_id.to_def_id(); if default.is_some() { - record!(self.tables.const_param_default[def_id] <- self.tcx.bound_const_param_default(def_id).subst_identity()) + record!(self.tables.const_param_default[def_id] <- self.tcx.const_param_default(def_id)) } } } diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index bf9be714daf7..5beee06d5211 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -360,7 +360,7 @@ define_tables! { fn_sig: Table>>, codegen_fn_attrs: Table>, impl_trait_ref: Table>>, - const_param_default: Table>>, + const_param_default: Table>>>, object_lifetime_default: Table>, optimized_mir: Table>>, mir_for_ctfe: Table>>, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 866559157369..cdc78a86349f 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -142,7 +142,7 @@ rustc_queries! { /// Given the def_id of a const-generic parameter, computes the associated default const /// parameter. e.g. `fn example` called on `N` would return `3`. - query const_param_default(param: DefId) -> ty::Const<'tcx> { + query const_param_default(param: DefId) -> ty::EarlyBinder> { desc { |tcx| "computing const default for a given parameter `{}`", tcx.def_path_str(param) } cache_on_disk_if { param.is_local() } separate_provide_extern diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 152a7e9d43fa..65cbac3e8f1c 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -239,7 +239,7 @@ impl<'tcx> Const<'tcx> { } } -pub fn const_param_default(tcx: TyCtxt<'_>, def_id: DefId) -> Const<'_> { +pub fn const_param_default(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder> { let default_def_id = match tcx.hir().get_by_def_id(def_id.expect_local()) { hir::Node::GenericParam(hir::GenericParam { kind: hir::GenericParamKind::Const { default: Some(ac), .. }, @@ -250,5 +250,5 @@ pub fn const_param_default(tcx: TyCtxt<'_>, def_id: DefId) -> Const<'_> { "`const_param_default` expected a generic parameter with a constant" ), }; - Const::from_anon_const(tcx, default_def_id) + ty::EarlyBinder(Const::from_anon_const(tcx, default_def_id)) } diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index 705adecd3b90..8a5e765b9a30 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -88,7 +88,7 @@ impl GenericParamDef { Some(tcx.bound_type_of(self.def_id).map_bound(|t| t.into())) } GenericParamDefKind::Const { has_default } if has_default => { - Some(tcx.bound_const_param_default(self.def_id).map_bound(|c| c.into())) + Some(tcx.const_param_default(self.def_id).map_bound(|c| c.into())) } _ => None, } diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index cc53659f8279..1f0c96a93b97 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -673,10 +673,6 @@ impl<'tcx> TyCtxt<'tcx> { ty::EarlyBinder(self.item_bounds(def_id)) } - pub fn bound_const_param_default(self, def_id: DefId) -> ty::EarlyBinder> { - ty::EarlyBinder(self.const_param_default(def_id)) - } - pub fn bound_predicates_of( self, def_id: DefId, diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 9ee1e012ef20..0d6d5ab5a183 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -838,9 +838,7 @@ impl ReachEverythingInTheInterfaceVisitor<'_, '_> { GenericParamDefKind::Const { has_default } => { self.visit(self.ev.tcx.type_of(param.def_id)); if has_default { - self.visit( - self.ev.tcx.bound_const_param_default(param.def_id).subst_identity(), - ); + self.visit(self.ev.tcx.const_param_default(param.def_id).subst_identity()); } } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 869c1e3512f4..415e7d5a360d 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -507,7 +507,7 @@ fn clean_generic_param_def<'tcx>( )), default: match has_default { true => Some(Box::new( - cx.tcx.bound_const_param_default(def.def_id).subst_identity().to_string(), + cx.tcx.const_param_default(def.def_id).subst_identity().to_string(), )), false => None, }, From be130b57d477069799158506d7e80145fdf71c73 Mon Sep 17 00:00:00 2001 From: Kyle Matsuda Date: Tue, 10 Jan 2023 14:22:52 -0700 Subject: [PATCH 079/105] change usages of impl_trait_ref to bound_impl_trait_ref --- compiler/rustc_hir_analysis/src/astconv/mod.rs | 4 ++-- compiler/rustc_hir_analysis/src/check/check.rs | 4 ++-- .../src/check/compare_impl_item.rs | 6 ++++-- .../rustc_hir_analysis/src/check/wfcheck.rs | 7 ++++--- .../src/coherence/builtin.rs | 4 ++-- .../rustc_hir_analysis/src/coherence/mod.rs | 2 +- .../rustc_hir_analysis/src/coherence/orphan.rs | 2 +- .../src/coherence/unsafety.rs | 4 +++- .../src/collect/predicates_of.rs | 6 ++++-- .../rustc_hir_analysis/src/collect/type_of.rs | 2 +- .../rustc_hir_analysis/src/impl_wf_check.rs | 3 ++- .../src/impl_wf_check/min_specialization.rs | 8 ++++---- .../rustc_hir_typeck/src/method/confirm.rs | 2 +- .../rustc_hir_typeck/src/method/suggest.rs | 18 +++++++++++------- .../src/infer/error_reporting/note.rs | 3 ++- compiler/rustc_lint/src/nonstandard_style.rs | 2 +- compiler/rustc_lint/src/pass_by_value.rs | 2 +- compiler/rustc_metadata/src/rmeta/encoder.rs | 12 +++++++++--- compiler/rustc_middle/src/hir/mod.rs | 3 ++- compiler/rustc_middle/src/ty/context.rs | 2 +- compiler/rustc_middle/src/ty/mod.rs | 14 +++++++++----- compiler/rustc_monomorphize/src/collector.rs | 5 ++++- compiler/rustc_passes/src/dead.rs | 6 +++--- compiler/rustc_passes/src/stability.rs | 2 +- compiler/rustc_privacy/src/lib.rs | 8 ++++---- .../src/traits/coherence.rs | 6 +++--- .../src/traits/error_reporting/mod.rs | 5 +++-- .../rustc_trait_selection/src/traits/mod.rs | 6 ++++-- .../src/traits/specialize/mod.rs | 4 ++-- .../traits/specialize/specialization_graph.rs | 12 ++++++------ compiler/rustc_traits/src/chalk/db.rs | 3 ++- compiler/rustc_ty_utils/src/implied_bounds.rs | 16 +++++++++------- compiler/rustc_ty_utils/src/ty.rs | 7 ++++--- src/librustdoc/clean/inline.rs | 2 +- src/librustdoc/clean/types.rs | 2 +- .../passes/collect_intra_doc_links.rs | 4 ++-- src/tools/clippy/clippy_lints/src/derive.rs | 8 ++++---- .../clippy_lints/src/fallible_impl_from.rs | 4 ++-- .../clippy/clippy_lints/src/from_over_into.rs | 2 +- .../src/implicit_saturating_sub.rs | 4 ++-- .../clippy_lints/src/methods/implicit_clone.rs | 2 +- .../src/methods/suspicious_splitn.rs | 2 +- .../clippy/clippy_lints/src/missing_doc.rs | 2 +- .../clippy/clippy_lints/src/missing_inline.rs | 2 +- .../src/non_send_fields_in_send_ty.rs | 4 ++-- .../clippy_lints/src/only_used_in_recursion.rs | 2 +- src/tools/clippy/clippy_lints/src/use_self.rs | 4 ++-- 47 files changed, 134 insertions(+), 100 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index d32c288337b5..28d83eea5ef4 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -2059,14 +2059,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { (_, Res::SelfTyAlias { alias_to: impl_def_id, is_trait_impl: true, .. }) => { // `Self` in an impl of a trait -- we have a concrete self type and a // trait reference. - let Some(trait_ref) = tcx.impl_trait_ref(impl_def_id) else { + let Some(trait_ref) = tcx.bound_impl_trait_ref(impl_def_id) else { // A cycle error occurred, most likely. let guar = tcx.sess.delay_span_bug(span, "expected cycle error"); return Err(guar); }; self.one_bound_for_assoc_type( - || traits::supertraits(tcx, ty::Binder::dummy(trait_ref)), + || traits::supertraits(tcx, ty::Binder::dummy(trait_ref.skip_binder())), || "Self".to_string(), assoc_ident, span, diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 43795cfba3fd..0042429c6c43 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -535,12 +535,12 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) { return; }; debug!("ItemKind::Impl {} with id {:?}", it.ident, it.owner_id); - if let Some(impl_trait_ref) = tcx.impl_trait_ref(it.owner_id) { + if let Some(impl_trait_ref) = tcx.bound_impl_trait_ref(it.owner_id.to_def_id()) { check_impl_items_against_trait( tcx, it.span, it.owner_id.def_id, - impl_trait_ref, + impl_trait_ref.skip_binder(), &impl_.items, ); check_on_unimplemented(tcx, it); diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 2cdf75794713..a420232ecbfd 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -616,7 +616,8 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( ) -> Result<&'tcx FxHashMap>, ErrorGuaranteed> { let impl_m = tcx.opt_associated_item(def_id).unwrap(); let trait_m = tcx.opt_associated_item(impl_m.trait_item_def_id.unwrap()).unwrap(); - let impl_trait_ref = tcx.impl_trait_ref(impl_m.impl_container(tcx).unwrap()).unwrap(); + let impl_trait_ref = + tcx.bound_impl_trait_ref(impl_m.impl_container(tcx).unwrap()).unwrap().subst_identity(); let param_env = tcx.param_env(def_id); // First, check a few of the same things as `compare_impl_method`, @@ -1684,7 +1685,8 @@ pub(super) fn compare_impl_const_raw( ) -> Result<(), ErrorGuaranteed> { let impl_const_item = tcx.associated_item(impl_const_item_def); let trait_const_item = tcx.associated_item(trait_const_item_def); - let impl_trait_ref = tcx.impl_trait_ref(impl_const_item.container_id(tcx)).unwrap(); + let impl_trait_ref = + tcx.bound_impl_trait_ref(impl_const_item.container_id(tcx)).unwrap().subst_identity(); debug!("compare_const_impl(impl_trait_ref={:?})", impl_trait_ref); let impl_c_span = tcx.def_span(impl_const_item_def.to_def_id()); diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 7c6da009dee3..6f85dfa4d91e 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -181,8 +181,8 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) { // for `T` hir::ItemKind::Impl(ref impl_) => { let is_auto = tcx - .impl_trait_ref(def_id) - .map_or(false, |trait_ref| tcx.trait_is_auto(trait_ref.def_id)); + .bound_impl_trait_ref(def_id.into()) + .map_or(false, |trait_ref| tcx.trait_is_auto(trait_ref.skip_binder().def_id)); if let (hir::Defaultness::Default { .. }, true) = (impl_.defaultness, is_auto) { let sp = impl_.of_trait.as_ref().map_or(item.span, |t| t.path.span); let mut err = @@ -1253,7 +1253,8 @@ fn check_impl<'tcx>( // `#[rustc_reservation_impl]` impls are not real impls and // therefore don't need to be WF (the trait's `Self: Trait` predicate // won't hold). - let trait_ref = tcx.impl_trait_ref(item.owner_id).unwrap(); + let trait_ref = + tcx.bound_impl_trait_ref(item.owner_id.to_def_id()).unwrap().subst_identity(); let trait_ref = wfcx.normalize( ast_trait_ref.path.span, Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)), diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index 2e2c1591e9b4..28a25780f96f 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -192,7 +192,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef let source = tcx.type_of(impl_did); assert!(!source.has_escaping_bound_vars()); let target = { - let trait_ref = tcx.impl_trait_ref(impl_did).unwrap(); + let trait_ref = tcx.bound_impl_trait_ref(impl_did.into()).unwrap().subst_identity(); assert_eq!(trait_ref.def_id, dispatch_from_dyn_trait); trait_ref.substs.type_at(1) @@ -354,7 +354,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn }); let source = tcx.type_of(impl_did); - let trait_ref = tcx.impl_trait_ref(impl_did).unwrap(); + let trait_ref = tcx.bound_impl_trait_ref(impl_did.into()).unwrap().subst_identity(); assert_eq!(trait_ref.def_id, coerce_unsized_trait); let target = trait_ref.substs.type_at(1); debug!("visit_implementation_of_coerce_unsized: {:?} -> {:?} (bound)", source, target); diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs index 1bf3768fead3..6bfb5a599149 100644 --- a/compiler/rustc_hir_analysis/src/coherence/mod.rs +++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs @@ -128,7 +128,7 @@ fn coherent_trait(tcx: TyCtxt<'_>, def_id: DefId) { let impls = tcx.hir().trait_impls(def_id); for &impl_def_id in impls { - let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap(); + let trait_ref = tcx.bound_impl_trait_ref(impl_def_id.into()).unwrap().subst_identity(); check_impl(tcx, impl_def_id, trait_ref); check_object_overlap(tcx, impl_def_id, trait_ref); diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index e8b3f139623e..9417901d1fdc 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs @@ -21,7 +21,7 @@ pub(crate) fn orphan_check_impl( tcx: TyCtxt<'_>, impl_def_id: LocalDefId, ) -> Result<(), ErrorGuaranteed> { - let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap(); + let trait_ref = tcx.bound_impl_trait_ref(impl_def_id.into()).unwrap().skip_binder(); trait_ref.error_reported()?; let ret = do_orphan_check_impl(tcx, trait_ref, impl_def_id); diff --git a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs index 70cc15b2f8c5..8db68067c69c 100644 --- a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs +++ b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs @@ -13,7 +13,9 @@ pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) { let item = tcx.hir().expect_item(def_id); let hir::ItemKind::Impl(ref impl_) = item.kind else { bug!() }; - if let Some(trait_ref) = tcx.impl_trait_ref(item.owner_id) { + if let Some(trait_ref) = + tcx.bound_impl_trait_ref(item.owner_id.to_def_id()).map(|t| t.subst_identity()) + { let trait_def = tcx.trait_def(trait_ref.def_id); let unsafe_attr = impl_.generics.params.iter().find(|p| p.pure_wrt_drop).map(|_| "may_dangle"); diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 234253556845..a44d9a6bddde 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -87,7 +87,9 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP Node::Item(item) => match item.kind { ItemKind::Impl(ref impl_) => { if impl_.defaultness.is_default() { - is_default_impl_trait = tcx.impl_trait_ref(def_id).map(ty::Binder::dummy); + is_default_impl_trait = tcx + .bound_impl_trait_ref(def_id) + .map(|t| ty::Binder::dummy(t.subst_identity())); } &impl_.generics } @@ -251,7 +253,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP // for details. if let Node::Item(&Item { kind: ItemKind::Impl { .. }, .. }) = node { let self_ty = tcx.type_of(def_id); - let trait_ref = tcx.impl_trait_ref(def_id); + let trait_ref = tcx.bound_impl_trait_ref(def_id).map(ty::EarlyBinder::subst_identity); cgp::setup_constraining_predicates( tcx, &mut predicates, diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 1f9a9f80302e..f845fa2ca5f0 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -286,7 +286,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { } } ImplItemKind::Type(ty) => { - if tcx.impl_trait_ref(tcx.hir().get_parent_item(hir_id)).is_none() { + if tcx.bound_impl_trait_ref(tcx.hir().get_parent_item(hir_id).to_def_id()).is_none() { check_feature_inherent_assoc_ty(tcx, item.span); } diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check.rs b/compiler/rustc_hir_analysis/src/impl_wf_check.rs index 136f6199911a..208f146ebbf6 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check.rs @@ -85,7 +85,8 @@ fn enforce_impl_params_are_constrained(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) } let impl_generics = tcx.generics_of(impl_def_id); let impl_predicates = tcx.predicates_of(impl_def_id); - let impl_trait_ref = tcx.impl_trait_ref(impl_def_id); + let impl_trait_ref = + tcx.bound_impl_trait_ref(impl_def_id.into()).map(ty::EarlyBinder::subst_identity); let mut input_parameters = cgp::parameters_for_impl(impl_self_ty, impl_trait_ref); cgp::identify_constrained_generic_params( diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs index 8b9034d9620e..ab40fa57acf3 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs @@ -89,8 +89,8 @@ pub(super) fn check_min_specialization(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) } fn parent_specialization_node(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId) -> Option { - let trait_ref = tcx.impl_trait_ref(impl1_def_id)?; - let trait_def = tcx.trait_def(trait_ref.def_id); + let trait_ref = tcx.bound_impl_trait_ref(impl1_def_id.into())?; + let trait_def = tcx.trait_def(trait_ref.skip_binder().def_id); let impl2_node = trait_def.ancestors(tcx, impl1_def_id.to_def_id()).ok()?.nth(1)?; @@ -207,7 +207,7 @@ fn unconstrained_parent_impl_substs<'tcx>( let impl_generic_predicates = tcx.predicates_of(impl_def_id); let mut unconstrained_parameters = FxHashSet::default(); let mut constrained_params = FxHashSet::default(); - let impl_trait_ref = tcx.impl_trait_ref(impl_def_id); + let impl_trait_ref = tcx.bound_impl_trait_ref(impl_def_id).map(ty::EarlyBinder::subst_identity); // Unfortunately the functions in `constrained_generic_parameters` don't do // what we want here. We want only a list of constrained parameters while @@ -370,7 +370,7 @@ fn check_predicates<'tcx>( }); // Include the well-formed predicates of the type parameters of the impl. - for arg in tcx.impl_trait_ref(impl1_def_id).unwrap().substs { + for arg in tcx.bound_impl_trait_ref(impl1_def_id.into()).unwrap().subst_identity().substs { let infcx = &tcx.infer_ctxt().build(); let obligations = wf::obligations( infcx, diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index 4a33a791e1b7..1a5a2ec7823b 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -240,7 +240,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { probe::InherentImplPick => { let impl_def_id = pick.item.container_id(self.tcx); assert!( - self.tcx.impl_trait_ref(impl_def_id).is_none(), + self.tcx.bound_impl_trait_ref(impl_def_id).is_none(), "impl {:?} is not an inherent impl", impl_def_id ); diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 8166eb829904..109ceb8956b4 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -1036,8 +1036,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Provide the best span we can. Use the item, if local to crate, else // the impl, if local to crate (item may be defaulted), else nothing. let Some(item) = self.associated_value(impl_did, item_name).or_else(|| { - let impl_trait_ref = self.tcx.impl_trait_ref(impl_did)?; - self.associated_value(impl_trait_ref.def_id, item_name) + let impl_trait_ref = self.tcx.bound_impl_trait_ref(impl_did)?; + self.associated_value(impl_trait_ref.skip_binder().def_id, item_name) }) else { continue; }; @@ -1052,10 +1052,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let impl_ty = self.tcx.at(span).type_of(impl_did); - let insertion = match self.tcx.impl_trait_ref(impl_did) { + let insertion = match self.tcx.bound_impl_trait_ref(impl_did) { None => String::new(), Some(trait_ref) => { - format!(" of the trait `{}`", self.tcx.def_path_str(trait_ref.def_id)) + format!( + " of the trait `{}`", + self.tcx.def_path_str(trait_ref.skip_binder().def_id) + ) } }; @@ -1085,8 +1088,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.note(¬e_str); } if let Some(sugg_span) = sugg_span - && let Some(trait_ref) = self.tcx.impl_trait_ref(impl_did) { - let path = self.tcx.def_path_str(trait_ref.def_id); + && let Some(trait_ref) = self.tcx.bound_impl_trait_ref(impl_did) { + let path = self.tcx.def_path_str(trait_ref.skip_binder().def_id); let ty = match item.kind { ty::AssocKind::Const | ty::AssocKind::Type => rcvr_ty, @@ -2581,7 +2584,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx.impl_polarity(*imp_did) == ty::ImplPolarity::Negative }) .any(|imp_did| { - let imp = self.tcx.impl_trait_ref(imp_did).unwrap(); + let imp = + self.tcx.bound_impl_trait_ref(imp_did).unwrap().subst_identity(); let imp_simp = simplify_type(self.tcx, imp.self_ty(), TreatParams::AsPlaceholder); imp_simp.map_or(false, |s| s == simp_rcvr_ty) diff --git a/compiler/rustc_infer/src/infer/error_reporting/note.rs b/compiler/rustc_infer/src/infer/error_reporting/note.rs index 7504ed094a3d..2670eb0d1455 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs @@ -317,9 +317,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { self.tcx.associated_item(impl_item_def_id).impl_container(self.tcx) else { return; }; let Some(trait_ref) = self .tcx - .impl_trait_ref(impl_def_id) + .bound_impl_trait_ref(impl_def_id) else { return; }; let trait_substs = trait_ref + .subst_identity() // Replace the explicit self type with `Self` for better suggestion rendering .with_self_ty(self.tcx, self.tcx.mk_ty_param(0, kw::SelfUpper)) .substs; diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs index 74d234fabea0..18a040ab8b18 100644 --- a/compiler/rustc_lint/src/nonstandard_style.rs +++ b/compiler/rustc_lint/src/nonstandard_style.rs @@ -26,7 +26,7 @@ pub fn method_context(cx: &LateContext<'_>, id: hir::HirId) -> MethodLateContext let item = cx.tcx.associated_item(def_id); match item.container { ty::TraitContainer => MethodLateContext::TraitAutoImpl, - ty::ImplContainer => match cx.tcx.impl_trait_ref(item.container_id(cx.tcx)) { + ty::ImplContainer => match cx.tcx.bound_impl_trait_ref(item.container_id(cx.tcx)) { Some(_) => MethodLateContext::TraitImpl, None => MethodLateContext::PlainImpl, }, diff --git a/compiler/rustc_lint/src/pass_by_value.rs b/compiler/rustc_lint/src/pass_by_value.rs index 57482a9edba8..212b8aa1574d 100644 --- a/compiler/rustc_lint/src/pass_by_value.rs +++ b/compiler/rustc_lint/src/pass_by_value.rs @@ -24,7 +24,7 @@ impl<'tcx> LateLintPass<'tcx> for PassByValue { match &ty.kind { TyKind::Ref(_, hir::MutTy { ty: inner_ty, mutbl: hir::Mutability::Not }) => { if let Some(impl_did) = cx.tcx.impl_of_method(ty.hir_id.owner.to_def_id()) { - if cx.tcx.impl_trait_ref(impl_did).is_some() { + if cx.tcx.bound_impl_trait_ref(impl_did).is_some() { return; } } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 030328d1e26f..3504a3bde450 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1555,7 +1555,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.tables.impl_defaultness.set(def_id.index, *defaultness); self.tables.constness.set(def_id.index, *constness); - let trait_ref = self.tcx.impl_trait_ref(def_id); + let trait_ref = + self.tcx.bound_impl_trait_ref(def_id).map(ty::EarlyBinder::skip_binder); if let Some(trait_ref) = trait_ref { let trait_def = self.tcx.trait_def(trait_ref.def_id); if let Ok(mut an) = trait_def.ancestors(self.tcx, def_id) { @@ -1632,7 +1633,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } } if let hir::ItemKind::Impl { .. } = item.kind { - if let Some(trait_ref) = self.tcx.impl_trait_ref(def_id) { + if let Some(trait_ref) = + self.tcx.bound_impl_trait_ref(def_id).map(ty::EarlyBinder::subst_identity) + { record!(self.tables.impl_trait_ref[def_id] <- trait_ref); } } @@ -1898,7 +1901,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { for id in tcx.hir().items() { if matches!(tcx.def_kind(id.owner_id), DefKind::Impl) { - if let Some(trait_ref) = tcx.impl_trait_ref(id.owner_id) { + if let Some(trait_ref) = tcx + .bound_impl_trait_ref(id.owner_id.to_def_id()) + .map(ty::EarlyBinder::subst_identity) + { let simplified_self_ty = fast_reject::simplify_type( self.tcx, trait_ref.self_ty(), diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index a633201e3d9a..e43e584b0b0d 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -101,7 +101,8 @@ impl<'tcx> TyCtxt<'tcx> { } pub fn impl_subject(self, def_id: DefId) -> ImplSubject<'tcx> { - self.impl_trait_ref(def_id) + self.bound_impl_trait_ref(def_id) + .map(|t| t.subst_identity()) .map(ImplSubject::Trait) .unwrap_or_else(|| ImplSubject::Inherent(self.type_of(def_id))) } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 63f31e5a11f3..6270c2ebb28f 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1027,7 +1027,7 @@ impl<'tcx> TyCtxt<'tcx> { /// Checks if the bound region is in Impl Item. pub fn is_bound_region_in_impl_item(self, suitable_region_binding_scope: LocalDefId) -> bool { let container_id = self.parent(suitable_region_binding_scope.to_def_id()); - if self.impl_trait_ref(container_id).is_some() { + if self.bound_impl_trait_ref(container_id).is_some() { // For now, we do not try to target impls of traits. This is // because this message is going to suggest that the user // change the fn signature, but they may not be free to do so, diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 993e95b35148..ac762b9dfb27 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2187,8 +2187,12 @@ impl<'tcx> TyCtxt<'tcx> { ) -> Option { // If either trait impl references an error, they're allowed to overlap, // as one of them essentially doesn't exist. - if self.impl_trait_ref(def_id1).map_or(false, |tr| tr.references_error()) - || self.impl_trait_ref(def_id2).map_or(false, |tr| tr.references_error()) + if self + .bound_impl_trait_ref(def_id1) + .map_or(false, |tr| tr.skip_binder().references_error()) + || self + .bound_impl_trait_ref(def_id2) + .map_or(false, |tr| tr.skip_binder().references_error()) { return Some(ImplOverlapKind::Permitted { marker: false }); } @@ -2217,8 +2221,8 @@ impl<'tcx> TyCtxt<'tcx> { let is_marker_overlap = { let is_marker_impl = |def_id: DefId| -> bool { - let trait_ref = self.impl_trait_ref(def_id); - trait_ref.map_or(false, |tr| self.trait_def(tr.def_id).is_marker) + let trait_ref = self.bound_impl_trait_ref(def_id); + trait_ref.map_or(false, |tr| self.trait_def(tr.skip_binder().def_id).is_marker) }; is_marker_impl(def_id1) && is_marker_impl(def_id2) }; @@ -2364,7 +2368,7 @@ impl<'tcx> TyCtxt<'tcx> { /// Given the `DefId` of an impl, returns the `DefId` of the trait it implements. /// If it implements no trait, returns `None`. pub fn trait_id_of_impl(self, def_id: DefId) -> Option { - self.impl_trait_ref(def_id).map(|tr| tr.def_id) + self.bound_impl_trait_ref(def_id).map(|tr| tr.skip_binder().def_id) } /// If the given `DefId` describes an item belonging to a trait, diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index b573df432505..070947410f38 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -1351,7 +1351,10 @@ fn create_mono_items_for_default_impls<'tcx>( tcx.def_path_str(item.owner_id.to_def_id()) ); - if let Some(trait_ref) = tcx.impl_trait_ref(item.owner_id) { + if let Some(trait_ref) = tcx + .bound_impl_trait_ref(item.owner_id.to_def_id()) + .map(ty::EarlyBinder::subst_identity) + { let param_env = ty::ParamEnv::reveal_all(); let trait_ref = tcx.normalize_erasing_regions(param_env, trait_ref); let overridden_methods = tcx.impl_item_implementor_ids(item.owner_id); diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index edb0e4367f27..88ad7b28f544 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -266,7 +266,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { if let Some(trait_of) = self.tcx.trait_id_of_impl(impl_of) && self.tcx.has_attr(trait_of, sym::rustc_trivial_field_reads) { - let trait_ref = self.tcx.impl_trait_ref(impl_of).unwrap(); + let trait_ref = self.tcx.bound_impl_trait_ref(impl_of).unwrap().subst_identity(); if let ty::Adt(adt_def, _) = trait_ref.self_ty().kind() && let Some(adt_def_id) = adt_def.did().as_local() { @@ -310,7 +310,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { } Node::ImplItem(impl_item) => { let item = self.tcx.local_parent(impl_item.owner_id.def_id); - if self.tcx.impl_trait_ref(item).is_none() { + if self.tcx.bound_impl_trait_ref(item.into()).is_none() { //// If it's a type whose items are live, then it's live, too. //// This is done to handle the case where, for example, the static //// method of a private type is used, but the type itself is never @@ -534,7 +534,7 @@ fn check_item<'tcx>( } } DefKind::Impl => { - let of_trait = tcx.impl_trait_ref(id.owner_id); + let of_trait = tcx.bound_impl_trait_ref(id.owner_id.to_def_id()); if of_trait.is_some() { worklist.push(id.owner_id.def_id); diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 96f7236de5cb..3ecc9faf7662 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -593,7 +593,7 @@ impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> { fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem<'tcx>) { let impl_def_id = self.tcx.hir().get_parent_item(ii.hir_id()); - if self.tcx.impl_trait_ref(impl_def_id).is_none() { + if self.tcx.bound_impl_trait_ref(impl_def_id.to_def_id()).is_none() { self.check_missing_stability(ii.owner_id.def_id, ii.span); self.check_missing_const_stability(ii.owner_id.def_id, ii.span); } diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 0d6d5ab5a183..69bfa8e2709a 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -337,8 +337,8 @@ trait VisibilityLike: Sized { ) -> Self { let mut find = FindMin { tcx, effective_visibilities, min: Self::MAX }; find.visit(tcx.type_of(def_id)); - if let Some(trait_ref) = tcx.impl_trait_ref(def_id) { - find.visit_trait(trait_ref); + if let Some(trait_ref) = tcx.bound_impl_trait_ref(def_id.into()) { + find.visit_trait(trait_ref.subst_identity()); } find.min } @@ -857,8 +857,8 @@ impl ReachEverythingInTheInterfaceVisitor<'_, '_> { } fn trait_ref(&mut self) -> &mut Self { - if let Some(trait_ref) = self.ev.tcx.impl_trait_ref(self.item_def_id) { - self.visit_trait(trait_ref); + if let Some(trait_ref) = self.ev.tcx.bound_impl_trait_ref(self.item_def_id.into()) { + self.visit_trait(trait_ref.subst_identity()); } self } diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 258d2e2d28c9..623ef7964bf0 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -77,8 +77,8 @@ pub fn overlapping_impls( // a quick check via fast_reject to tell if the impl headers could possibly // unify. let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::AsInfer }; - let impl1_ref = tcx.impl_trait_ref(impl1_def_id); - let impl2_ref = tcx.impl_trait_ref(impl2_def_id); + let impl1_ref = tcx.bound_impl_trait_ref(impl1_def_id).map(ty::EarlyBinder::subst_identity); + let impl2_ref = tcx.bound_impl_trait_ref(impl2_def_id).map(ty::EarlyBinder::subst_identity); let may_overlap = match (impl1_ref, impl2_ref) { (Some(a), Some(b)) => iter::zip(a.substs, b.substs) .all(|(arg1, arg2)| drcx.generic_args_may_unify(arg1, arg2)), @@ -461,7 +461,7 @@ pub fn orphan_check(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Result<(), OrphanChe // We only except this routine to be invoked on implementations // of a trait, not inherent implementations. - let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap(); + let trait_ref = tcx.bound_impl_trait_ref(impl_def_id).unwrap().skip_binder(); debug!("orphan_check: trait_ref={:?}", trait_ref); // If the *trait* is local to the crate, ok. 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 0c7ffb056cc0..8b9c6821dafe 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1940,7 +1940,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { return None; } - let imp = self.tcx.impl_trait_ref(def_id).unwrap(); + let imp = self.tcx.bound_impl_trait_ref(def_id).unwrap().subst_identity(); self.fuzzy_match_tys(trait_pred.skip_binder().self_ty(), imp.self_ty(), false) .map(|similarity| ImplCandidate { trait_ref: imp, similarity }) @@ -2039,7 +2039,8 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { self.tcx.impl_polarity(def_id) != ty::ImplPolarity::Negative || self.tcx.is_builtin_derive(def_id) }) - .filter_map(|def_id| self.tcx.impl_trait_ref(def_id)) + .filter_map(|def_id| self.tcx.bound_impl_trait_ref(def_id)) + .map(ty::EarlyBinder::subst_identity) .filter(|trait_ref| { let self_ty = trait_ref.self_ty(); // Avoid mentioning type parameters. diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 37b40a2f75ad..4c34dc64c26c 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -521,8 +521,10 @@ fn is_impossible_method(tcx: TyCtxt<'_>, (impl_def_id, trait_item_def_id): (DefI let generics = tcx.generics_of(trait_item_def_id); let predicates = tcx.predicates_of(trait_item_def_id); - let impl_trait_ref = - tcx.impl_trait_ref(impl_def_id).expect("expected impl to correspond to trait"); + let impl_trait_ref = tcx + .bound_impl_trait_ref(impl_def_id) + .expect("expected impl to correspond to trait") + .subst_identity(); let param_env = tcx.param_env(impl_def_id); let mut visitor = ReferencesOnlyParentGenerics { tcx, generics, trait_item_def_id }; diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index a251a508b48c..a352a65fb068 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs @@ -148,7 +148,7 @@ pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId, // create a parameter environment corresponding to a (placeholder) instantiation of impl1 let penv = tcx.param_env(impl1_def_id); - let impl1_trait_ref = tcx.impl_trait_ref(impl1_def_id).unwrap(); + let impl1_trait_ref = tcx.bound_impl_trait_ref(impl1_def_id).unwrap().subst_identity(); // Create an infcx, taking the predicates of impl1 as assumptions: let infcx = tcx.infer_ctxt().build(); @@ -431,7 +431,7 @@ fn report_conflicting_impls<'tcx>( pub(crate) fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Option { use std::fmt::Write; - let trait_ref = tcx.impl_trait_ref(impl_def_id)?; + let trait_ref = tcx.bound_impl_trait_ref(impl_def_id)?.skip_binder(); let mut w = "impl".to_owned(); let substs = InternalSubsts::identity_for_item(tcx, impl_def_id); diff --git a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs index 02b066777402..a2e39c53d15c 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs @@ -48,7 +48,7 @@ trait ChildrenExt<'tcx> { impl<'tcx> ChildrenExt<'tcx> for Children { /// Insert an impl into this set of children without comparing to any existing impls. fn insert_blindly(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) { - let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap(); + let trait_ref = tcx.bound_impl_trait_ref(impl_def_id).unwrap().subst_identity(); if let Some(st) = fast_reject::simplify_type(tcx, trait_ref.self_ty(), TreatParams::AsInfer) { debug!("insert_blindly: impl_def_id={:?} st={:?}", impl_def_id, st); @@ -63,7 +63,7 @@ impl<'tcx> ChildrenExt<'tcx> for Children { /// an impl with a parent. The impl must be present in the list of /// children already. fn remove_existing(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) { - let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap(); + let trait_ref = tcx.bound_impl_trait_ref(impl_def_id).unwrap().subst_identity(); let vec: &mut Vec; if let Some(st) = fast_reject::simplify_type(tcx, trait_ref.self_ty(), TreatParams::AsInfer) { @@ -181,7 +181,7 @@ impl<'tcx> ChildrenExt<'tcx> for Children { if le && !ge { debug!( "descending as child of TraitRef {:?}", - tcx.impl_trait_ref(possible_sibling).unwrap() + tcx.bound_impl_trait_ref(possible_sibling).unwrap().subst_identity() ); // The impl specializes `possible_sibling`. @@ -189,7 +189,7 @@ impl<'tcx> ChildrenExt<'tcx> for Children { } else if ge && !le { debug!( "placing as parent of TraitRef {:?}", - tcx.impl_trait_ref(possible_sibling).unwrap() + tcx.bound_impl_trait_ref(possible_sibling).unwrap().subst_identity() ); replace_children.push(possible_sibling); @@ -275,7 +275,7 @@ impl<'tcx> GraphExt<'tcx> for Graph { ) -> Result>, OverlapError<'tcx>> { assert!(impl_def_id.is_local()); - let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap(); + let trait_ref = tcx.bound_impl_trait_ref(impl_def_id).unwrap().subst_identity(); let trait_def_id = trait_ref.def_id; debug!( @@ -388,7 +388,7 @@ pub(crate) fn assoc_def( impl_def_id: DefId, assoc_def_id: DefId, ) -> Result { - let trait_def_id = tcx.impl_trait_ref(impl_def_id).unwrap().def_id; + let trait_def_id = tcx.bound_impl_trait_ref(impl_def_id).unwrap().skip_binder().def_id; let trait_def = tcx.trait_def(trait_def_id); // This function may be called while we are still building the diff --git a/compiler/rustc_traits/src/chalk/db.rs b/compiler/rustc_traits/src/chalk/db.rs index f288eb112582..dea33f896cf1 100644 --- a/compiler/rustc_traits/src/chalk/db.rs +++ b/compiler/rustc_traits/src/chalk/db.rs @@ -380,7 +380,8 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t let trait_def_id = auto_trait_id.0; let all_impls = self.interner.tcx.all_impls(trait_def_id); for impl_def_id in all_impls { - let trait_ref = self.interner.tcx.impl_trait_ref(impl_def_id).unwrap(); + let trait_ref = + self.interner.tcx.bound_impl_trait_ref(impl_def_id).unwrap().subst_identity(); let self_ty = trait_ref.self_ty(); let provides = match (self_ty.kind(), chalk_ty) { (&ty::Adt(impl_adt_def, ..), Adt(id, ..)) => impl_adt_def.did() == id.0.did(), diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs index b7a24a22c53e..d890a04599b1 100644 --- a/compiler/rustc_ty_utils/src/implied_bounds.rs +++ b/compiler/rustc_ty_utils/src/implied_bounds.rs @@ -21,14 +21,16 @@ fn assumed_wf_types(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::List> { assumed_wf_types.extend(liberated_sig.inputs_and_output); tcx.intern_type_list(&assumed_wf_types) } - DefKind::Impl => match tcx.impl_trait_ref(def_id) { - Some(trait_ref) => { - let types: Vec<_> = trait_ref.substs.types().collect(); - tcx.intern_type_list(&types) + DefKind::Impl => { + match tcx.bound_impl_trait_ref(def_id).map(ty::EarlyBinder::subst_identity) { + Some(trait_ref) => { + let types: Vec<_> = trait_ref.substs.types().collect(); + tcx.intern_type_list(&types) + } + // Only the impl self type + None => tcx.intern_type_list(&[tcx.type_of(def_id)]), } - // Only the impl self type - None => tcx.intern_type_list(&[tcx.type_of(def_id)]), - }, + } DefKind::AssocConst | DefKind::AssocTy => tcx.assumed_wf_types(tcx.parent(def_id)), DefKind::Mod | DefKind::Struct diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 87923ebbe4bc..78c3a208e889 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -289,7 +289,7 @@ fn well_formed_types_in_env(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::List { - let trait_ref = tcx.impl_trait_ref(def_id).expect("not an impl"); + let trait_ref = tcx.bound_impl_trait_ref(def_id).expect("not an impl").subst_identity(); // FIXME(chalk): this has problems because of late-bound regions //inputs.extend(trait_ref.substs.iter().flat_map(|arg| arg.walk())); @@ -359,8 +359,9 @@ fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option> { debug!("issue33140_self_ty({:?})", def_id); let trait_ref = tcx - .impl_trait_ref(def_id) - .unwrap_or_else(|| bug!("issue33140_self_ty called on inherent impl {:?}", def_id)); + .bound_impl_trait_ref(def_id) + .unwrap_or_else(|| bug!("issue33140_self_ty called on inherent impl {:?}", def_id)) + .skip_binder(); debug!("issue33140_self_ty({:?}), trait-ref={:?}", def_id, trait_ref); diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index aad24b4a0749..23330daa54bf 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -376,7 +376,7 @@ pub(crate) fn build_impl( let _prof_timer = cx.tcx.sess.prof.generic_activity("build_impl"); let tcx = cx.tcx; - let associated_trait = tcx.impl_trait_ref(did); + let associated_trait = tcx.bound_impl_trait_ref(did).map(ty::EarlyBinder::skip_binder); // Only inline impl if the implemented trait is // reachable in rustdoc generated documentation diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 87de41fde63c..cda90955ba11 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -734,7 +734,7 @@ impl Item { ty::ImplContainer => { // Trait impl items always inherit the impl's visibility -- // we don't want to show `pub`. - tcx.impl_trait_ref(tcx.parent(assoc_item.def_id)).is_some() + tcx.bound_impl_trait_ref(tcx.parent(assoc_item.def_id)).is_some() } }; if is_trait_item { diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 4f0eb8b8076e..fa9174287e27 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -784,9 +784,9 @@ fn trait_impls_for<'a>( // Look at each trait implementation to see if it's an impl for `did` tcx.find_map_relevant_impl(trait_, ty, |impl_| { - let trait_ref = tcx.impl_trait_ref(impl_).expect("this is not an inherent impl"); + let trait_ref = tcx.bound_impl_trait_ref(impl_).expect("this is not an inherent impl"); // Check if these are the same type. - let impl_type = trait_ref.self_ty(); + let impl_type = trait_ref.subst_identity().self_ty(); trace!( "comparing type {} with kind {:?} against type {:?}", impl_type, diff --git a/src/tools/clippy/clippy_lints/src/derive.rs b/src/tools/clippy/clippy_lints/src/derive.rs index f4b15e0916db..6b2b18fff76e 100644 --- a/src/tools/clippy/clippy_lints/src/derive.rs +++ b/src/tools/clippy/clippy_lints/src/derive.rs @@ -247,11 +247,11 @@ fn check_hash_peq<'tcx>( return; } - let trait_ref = cx.tcx.impl_trait_ref(impl_id).expect("must be a trait implementation"); + let trait_ref = cx.tcx.bound_impl_trait_ref(impl_id).expect("must be a trait implementation"); // Only care about `impl PartialEq for Foo` // For `impl PartialEq for A, input_types is [A, B] - if trait_ref.substs.type_at(1) == ty { + if trait_ref.subst_identity().substs.type_at(1) == ty { span_lint_and_then( cx, DERIVED_HASH_WITH_MANUAL_EQ, @@ -295,11 +295,11 @@ fn check_ord_partial_ord<'tcx>( return; } - let trait_ref = cx.tcx.impl_trait_ref(impl_id).expect("must be a trait implementation"); + let trait_ref = cx.tcx.bound_impl_trait_ref(impl_id).expect("must be a trait implementation"); // Only care about `impl PartialOrd for Foo` // For `impl PartialOrd for A, input_types is [A, B] - if trait_ref.substs.type_at(1) == ty { + if trait_ref.subst_identity().substs.type_at(1) == ty { let mess = if partial_ord_is_automatically_derived { "you are implementing `Ord` explicitly but have derived `PartialOrd`" } else { diff --git a/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs b/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs index 9a1058470e18..a8085122ccf9 100644 --- a/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs +++ b/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs @@ -55,8 +55,8 @@ impl<'tcx> LateLintPass<'tcx> for FallibleImplFrom { // check for `impl From for ..` if_chain! { if let hir::ItemKind::Impl(impl_) = &item.kind; - if let Some(impl_trait_ref) = cx.tcx.impl_trait_ref(item.owner_id); - if cx.tcx.is_diagnostic_item(sym::From, impl_trait_ref.def_id); + if let Some(impl_trait_ref) = cx.tcx.bound_impl_trait_ref(item.owner_id.to_def_id()); + if cx.tcx.is_diagnostic_item(sym::From, impl_trait_ref.skip_binder().def_id); then { lint_impl_body(cx, item.span, impl_.items); } diff --git a/src/tools/clippy/clippy_lints/src/from_over_into.rs b/src/tools/clippy/clippy_lints/src/from_over_into.rs index a92f7548ff25..97d414bfa95e 100644 --- a/src/tools/clippy/clippy_lints/src/from_over_into.rs +++ b/src/tools/clippy/clippy_lints/src/from_over_into.rs @@ -76,7 +76,7 @@ impl<'tcx> LateLintPass<'tcx> for FromOverInto { && let Some(into_trait_seg) = hir_trait_ref.path.segments.last() // `impl Into for self_ty` && let Some(GenericArgs { args: [GenericArg::Type(target_ty)], .. }) = into_trait_seg.args - && let Some(middle_trait_ref) = cx.tcx.impl_trait_ref(item.owner_id) + && let Some(middle_trait_ref) = cx.tcx.bound_impl_trait_ref(item.owner_id.to_def_id()).map(ty::EarlyBinder::subst_identity) && cx.tcx.is_diagnostic_item(sym::Into, middle_trait_ref.def_id) && !matches!(middle_trait_ref.substs.type_at(1).kind(), ty::Alias(ty::Opaque, _)) { diff --git a/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs b/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs index 29d59c26d92c..37e33529a9a6 100644 --- a/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs +++ b/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs @@ -101,7 +101,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingSub { if name.ident.as_str() == "MIN"; if let Some(const_id) = cx.typeck_results().type_dependent_def_id(cond_num_val.hir_id); if let Some(impl_id) = cx.tcx.impl_of_method(const_id); - if let None = cx.tcx.impl_trait_ref(impl_id); // An inherent impl + if let None = cx.tcx.bound_impl_trait_ref(impl_id); // An inherent impl if cx.tcx.type_of(impl_id).is_integral(); then { print_lint_and_sugg(cx, var_name, expr) @@ -114,7 +114,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingSub { if name.ident.as_str() == "min_value"; if let Some(func_id) = cx.typeck_results().type_dependent_def_id(func.hir_id); if let Some(impl_id) = cx.tcx.impl_of_method(func_id); - if let None = cx.tcx.impl_trait_ref(impl_id); // An inherent impl + if let None = cx.tcx.bound_impl_trait_ref(impl_id); // An inherent impl if cx.tcx.type_of(impl_id).is_integral(); then { print_lint_and_sugg(cx, var_name, expr) diff --git a/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs b/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs index 06ecbce4e70e..16a25a98800d 100644 --- a/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs +++ b/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs @@ -53,7 +53,7 @@ pub fn is_clone_like(cx: &LateContext<'_>, method_name: &str, method_def_id: hir "to_vec" => cx .tcx .impl_of_method(method_def_id) - .filter(|&impl_did| cx.tcx.type_of(impl_did).is_slice() && cx.tcx.impl_trait_ref(impl_did).is_none()) + .filter(|&impl_did| cx.tcx.type_of(impl_did).is_slice() && cx.tcx.bound_impl_trait_ref(impl_did).is_none()) .is_some(), _ => false, } diff --git a/src/tools/clippy/clippy_lints/src/methods/suspicious_splitn.rs b/src/tools/clippy/clippy_lints/src/methods/suspicious_splitn.rs index 219a9edd6576..dba0663467b7 100644 --- a/src/tools/clippy/clippy_lints/src/methods/suspicious_splitn.rs +++ b/src/tools/clippy/clippy_lints/src/methods/suspicious_splitn.rs @@ -12,7 +12,7 @@ pub(super) fn check(cx: &LateContext<'_>, method_name: &str, expr: &Expr<'_>, se if count <= 1; if let Some(call_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id); if let Some(impl_id) = cx.tcx.impl_of_method(call_id); - if cx.tcx.impl_trait_ref(impl_id).is_none(); + if cx.tcx.bound_impl_trait_ref(impl_id).is_none(); let self_ty = cx.tcx.type_of(impl_id); if self_ty.is_slice() || self_ty.is_str(); then { diff --git a/src/tools/clippy/clippy_lints/src/missing_doc.rs b/src/tools/clippy/clippy_lints/src/missing_doc.rs index 6fd100762b49..d0c99b352452 100644 --- a/src/tools/clippy/clippy_lints/src/missing_doc.rs +++ b/src/tools/clippy/clippy_lints/src/missing_doc.rs @@ -175,7 +175,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx hir::ImplItem<'_>) { // If the method is an impl for a trait, don't doc. if let Some(cid) = cx.tcx.associated_item(impl_item.owner_id).impl_container(cx.tcx) { - if cx.tcx.impl_trait_ref(cid).is_some() { + if cx.tcx.bound_impl_trait_ref(cid).is_some() { return; } } else { diff --git a/src/tools/clippy/clippy_lints/src/missing_inline.rs b/src/tools/clippy/clippy_lints/src/missing_inline.rs index 758ce47cf114..0594fb175458 100644 --- a/src/tools/clippy/clippy_lints/src/missing_inline.rs +++ b/src/tools/clippy/clippy_lints/src/missing_inline.rs @@ -155,7 +155,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline { let container_id = assoc_item.container_id(cx.tcx); let trait_def_id = match assoc_item.container { TraitContainer => Some(container_id), - ImplContainer => cx.tcx.impl_trait_ref(container_id).map(|t| t.def_id), + ImplContainer => cx.tcx.bound_impl_trait_ref(container_id).map(|t| t.skip_binder().def_id), }; if let Some(trait_def_id) = trait_def_id { diff --git a/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs b/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs index 714c0ff227bf..9c112ade948f 100644 --- a/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs +++ b/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs @@ -89,8 +89,8 @@ impl<'tcx> LateLintPass<'tcx> for NonSendFieldInSendTy { if let Some(trait_id) = trait_ref.trait_def_id(); if send_trait == trait_id; if hir_impl.polarity == ImplPolarity::Positive; - if let Some(ty_trait_ref) = cx.tcx.impl_trait_ref(item.owner_id); - if let self_ty = ty_trait_ref.self_ty(); + if let Some(ty_trait_ref) = cx.tcx.bound_impl_trait_ref(item.owner_id.to_def_id()); + if let self_ty = ty_trait_ref.subst_identity().self_ty(); if let ty::Adt(adt_def, impl_trait_substs) = self_ty.kind(); then { let mut non_send_fields = Vec::new(); diff --git a/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs b/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs index 7722a476d7b4..82b1716a216e 100644 --- a/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs +++ b/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs @@ -244,7 +244,7 @@ impl<'tcx> LateLintPass<'tcx> for OnlyUsedInRecursion { })) => { #[allow(trivial_casts)] if let Some(Node::Item(item)) = get_parent_node(cx.tcx, owner_id.into()) - && let Some(trait_ref) = cx.tcx.impl_trait_ref(item.owner_id) + && let Some(trait_ref) = cx.tcx.bound_impl_trait_ref(item.owner_id.to_def_id()).map(|t| t.subst_identity()) && let Some(trait_item_id) = cx.tcx.associated_item(owner_id).trait_item_def_id { ( diff --git a/src/tools/clippy/clippy_lints/src/use_self.rs b/src/tools/clippy/clippy_lints/src/use_self.rs index 4c755d812a0e..9f31a13aa984 100644 --- a/src/tools/clippy/clippy_lints/src/use_self.rs +++ b/src/tools/clippy/clippy_lints/src/use_self.rs @@ -133,11 +133,11 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf { ref mut types_to_skip, .. }) = self.stack.last_mut(); - if let Some(impl_trait_ref) = cx.tcx.impl_trait_ref(impl_id); + if let Some(impl_trait_ref) = cx.tcx.bound_impl_trait_ref(impl_id.to_def_id()); then { // `self_ty` is the semantic self type of `impl for `. This cannot be // `Self`. - let self_ty = impl_trait_ref.self_ty(); + let self_ty = impl_trait_ref.subst_identity().self_ty(); // `trait_method_sig` is the signature of the function, how it is declared in the // trait, not in the impl of the trait. From f29a334c90e29ffbe236f9abba9aa08bfda597c6 Mon Sep 17 00:00:00 2001 From: Kyle Matsuda Date: Tue, 10 Jan 2023 14:57:22 -0700 Subject: [PATCH 080/105] change impl_trait_ref query to return EarlyBinder; remove bound_impl_trait_ref query; add EarlyBinder to impl_trait_ref in metadata --- .../rustc_hir_analysis/src/astconv/mod.rs | 6 ++--- .../rustc_hir_analysis/src/check/check.rs | 2 +- .../src/check/compare_impl_item.rs | 4 ++-- .../rustc_hir_analysis/src/check/wfcheck.rs | 5 ++--- .../src/coherence/builtin.rs | 4 ++-- .../rustc_hir_analysis/src/coherence/mod.rs | 2 +- .../src/coherence/orphan.rs | 2 +- .../src/coherence/unsafety.rs | 4 +--- compiler/rustc_hir_analysis/src/collect.rs | 22 +++++++++++-------- .../src/collect/predicates_of.rs | 7 +++--- .../rustc_hir_analysis/src/collect/type_of.rs | 2 +- .../rustc_hir_analysis/src/impl_wf_check.rs | 3 +-- .../src/impl_wf_check/min_specialization.rs | 6 ++--- .../rustc_hir_typeck/src/method/confirm.rs | 2 +- .../rustc_hir_typeck/src/method/suggest.rs | 9 ++++---- .../src/infer/error_reporting/note.rs | 2 +- compiler/rustc_lint/src/nonstandard_style.rs | 2 +- compiler/rustc_lint/src/pass_by_value.rs | 2 +- compiler/rustc_metadata/src/rmeta/encoder.rs | 12 ++++------ compiler/rustc_metadata/src/rmeta/mod.rs | 2 +- compiler/rustc_middle/src/hir/mod.rs | 2 +- compiler/rustc_middle/src/query/mod.rs | 2 +- compiler/rustc_middle/src/ty/context.rs | 2 +- compiler/rustc_middle/src/ty/mod.rs | 12 ++++------ compiler/rustc_middle/src/ty/print/mod.rs | 2 +- compiler/rustc_middle/src/ty/util.rs | 7 ------ compiler/rustc_monomorphize/src/collector.rs | 5 ++--- compiler/rustc_passes/src/dead.rs | 6 ++--- compiler/rustc_passes/src/stability.rs | 2 +- compiler/rustc_privacy/src/lib.rs | 4 ++-- .../src/solve/project_goals.rs | 2 +- .../src/solve/trait_goals.rs | 2 +- .../src/traits/coherence.rs | 8 +++---- .../src/traits/error_reporting/ambiguity.rs | 2 +- .../src/traits/error_reporting/mod.rs | 4 ++-- .../error_reporting/on_unimplemented.rs | 2 +- .../rustc_trait_selection/src/traits/mod.rs | 2 +- .../src/traits/select/candidate_assembly.rs | 2 +- .../src/traits/select/mod.rs | 2 +- .../src/traits/specialize/mod.rs | 6 ++--- .../traits/specialize/specialization_graph.rs | 12 +++++----- compiler/rustc_traits/src/chalk/db.rs | 7 +++--- compiler/rustc_ty_utils/src/implied_bounds.rs | 2 +- compiler/rustc_ty_utils/src/ty.rs | 4 ++-- src/librustdoc/clean/blanket_impl.rs | 2 +- src/librustdoc/clean/inline.rs | 2 +- src/librustdoc/clean/types.rs | 2 +- .../passes/collect_intra_doc_links.rs | 2 +- src/tools/clippy/clippy_lints/src/derive.rs | 4 ++-- .../clippy_lints/src/fallible_impl_from.rs | 2 +- .../clippy/clippy_lints/src/from_over_into.rs | 2 +- .../src/implicit_saturating_sub.rs | 4 ++-- .../src/methods/implicit_clone.rs | 2 +- .../src/methods/suspicious_splitn.rs | 2 +- .../clippy/clippy_lints/src/missing_doc.rs | 2 +- .../clippy/clippy_lints/src/missing_inline.rs | 2 +- .../src/non_send_fields_in_send_ty.rs | 2 +- .../src/only_used_in_recursion.rs | 2 +- src/tools/clippy/clippy_lints/src/use_self.rs | 2 +- 59 files changed, 108 insertions(+), 127 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 28d83eea5ef4..7567a02d1454 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -2059,7 +2059,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { (_, Res::SelfTyAlias { alias_to: impl_def_id, is_trait_impl: true, .. }) => { // `Self` in an impl of a trait -- we have a concrete self type and a // trait reference. - let Some(trait_ref) = tcx.bound_impl_trait_ref(impl_def_id) else { + let Some(trait_ref) = tcx.impl_trait_ref(impl_def_id) else { // A cycle error occurred, most likely. let guar = tcx.sess.delay_span_bug(span, "expected cycle error"); return Err(guar); @@ -2155,7 +2155,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .is_accessible_from(self.item_def_id(), tcx) && tcx.all_impls(*trait_def_id) .any(|impl_def_id| { - let trait_ref = tcx.bound_impl_trait_ref(impl_def_id); + let trait_ref = tcx.impl_trait_ref(impl_def_id); trait_ref.map_or(false, |trait_ref| { let impl_ = trait_ref.subst( tcx, @@ -2308,7 +2308,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { && tcx.impl_polarity(impl_def_id) != ty::ImplPolarity::Negative }) .filter_map(|impl_def_id| tcx.impl_trait_ref(impl_def_id)) - .map(|impl_| impl_.self_ty()) + .map(|impl_| impl_.subst_identity().self_ty()) // We don't care about blanket impls. .filter(|self_ty| !self_ty.has_non_region_param()) .map(|self_ty| tcx.erase_regions(self_ty).to_string()) diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 0042429c6c43..7df19ba6d36b 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -535,7 +535,7 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) { return; }; debug!("ItemKind::Impl {} with id {:?}", it.ident, it.owner_id); - if let Some(impl_trait_ref) = tcx.bound_impl_trait_ref(it.owner_id.to_def_id()) { + if let Some(impl_trait_ref) = tcx.impl_trait_ref(it.owner_id) { check_impl_items_against_trait( tcx, it.span, diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index a420232ecbfd..770d7b6f927e 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -617,7 +617,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( let impl_m = tcx.opt_associated_item(def_id).unwrap(); let trait_m = tcx.opt_associated_item(impl_m.trait_item_def_id.unwrap()).unwrap(); let impl_trait_ref = - tcx.bound_impl_trait_ref(impl_m.impl_container(tcx).unwrap()).unwrap().subst_identity(); + tcx.impl_trait_ref(impl_m.impl_container(tcx).unwrap()).unwrap().subst_identity(); let param_env = tcx.param_env(def_id); // First, check a few of the same things as `compare_impl_method`, @@ -1686,7 +1686,7 @@ pub(super) fn compare_impl_const_raw( let impl_const_item = tcx.associated_item(impl_const_item_def); let trait_const_item = tcx.associated_item(trait_const_item_def); let impl_trait_ref = - tcx.bound_impl_trait_ref(impl_const_item.container_id(tcx)).unwrap().subst_identity(); + tcx.impl_trait_ref(impl_const_item.container_id(tcx)).unwrap().subst_identity(); debug!("compare_const_impl(impl_trait_ref={:?})", impl_trait_ref); let impl_c_span = tcx.def_span(impl_const_item_def.to_def_id()); diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 6f85dfa4d91e..912e0ec560b4 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -181,7 +181,7 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) { // for `T` hir::ItemKind::Impl(ref impl_) => { let is_auto = tcx - .bound_impl_trait_ref(def_id.into()) + .impl_trait_ref(def_id) .map_or(false, |trait_ref| tcx.trait_is_auto(trait_ref.skip_binder().def_id)); if let (hir::Defaultness::Default { .. }, true) = (impl_.defaultness, is_auto) { let sp = impl_.of_trait.as_ref().map_or(item.span, |t| t.path.span); @@ -1253,8 +1253,7 @@ fn check_impl<'tcx>( // `#[rustc_reservation_impl]` impls are not real impls and // therefore don't need to be WF (the trait's `Self: Trait` predicate // won't hold). - let trait_ref = - tcx.bound_impl_trait_ref(item.owner_id.to_def_id()).unwrap().subst_identity(); + let trait_ref = tcx.impl_trait_ref(item.owner_id).unwrap().subst_identity(); let trait_ref = wfcx.normalize( ast_trait_ref.path.span, Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)), diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index 28a25780f96f..5bdd18fcd637 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -192,7 +192,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef let source = tcx.type_of(impl_did); assert!(!source.has_escaping_bound_vars()); let target = { - let trait_ref = tcx.bound_impl_trait_ref(impl_did.into()).unwrap().subst_identity(); + let trait_ref = tcx.impl_trait_ref(impl_did).unwrap().subst_identity(); assert_eq!(trait_ref.def_id, dispatch_from_dyn_trait); trait_ref.substs.type_at(1) @@ -354,7 +354,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn }); let source = tcx.type_of(impl_did); - let trait_ref = tcx.bound_impl_trait_ref(impl_did.into()).unwrap().subst_identity(); + let trait_ref = tcx.impl_trait_ref(impl_did).unwrap().subst_identity(); assert_eq!(trait_ref.def_id, coerce_unsized_trait); let target = trait_ref.substs.type_at(1); debug!("visit_implementation_of_coerce_unsized: {:?} -> {:?} (bound)", source, target); diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs index 6bfb5a599149..2e9cd2fca01c 100644 --- a/compiler/rustc_hir_analysis/src/coherence/mod.rs +++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs @@ -128,7 +128,7 @@ fn coherent_trait(tcx: TyCtxt<'_>, def_id: DefId) { let impls = tcx.hir().trait_impls(def_id); for &impl_def_id in impls { - let trait_ref = tcx.bound_impl_trait_ref(impl_def_id.into()).unwrap().subst_identity(); + let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().subst_identity(); check_impl(tcx, impl_def_id, trait_ref); check_object_overlap(tcx, impl_def_id, trait_ref); diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index 9417901d1fdc..e8fe92814576 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs @@ -21,7 +21,7 @@ pub(crate) fn orphan_check_impl( tcx: TyCtxt<'_>, impl_def_id: LocalDefId, ) -> Result<(), ErrorGuaranteed> { - let trait_ref = tcx.bound_impl_trait_ref(impl_def_id.into()).unwrap().skip_binder(); + let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().skip_binder(); trait_ref.error_reported()?; let ret = do_orphan_check_impl(tcx, trait_ref, impl_def_id); diff --git a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs index 8db68067c69c..c7693cab4741 100644 --- a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs +++ b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs @@ -13,9 +13,7 @@ pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) { let item = tcx.hir().expect_item(def_id); let hir::ItemKind::Impl(ref impl_) = item.kind else { bug!() }; - if let Some(trait_ref) = - tcx.bound_impl_trait_ref(item.owner_id.to_def_id()).map(|t| t.subst_identity()) - { + if let Some(trait_ref) = tcx.impl_trait_ref(item.owner_id).map(|t| t.subst_identity()) { let trait_def = tcx.trait_def(trait_ref.def_id); let unsafe_attr = impl_.generics.params.iter().find(|p| p.pure_wrt_drop).map(|_| "may_dangle"); diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index cd745ee8cab6..35f47dfc1a5e 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1339,18 +1339,22 @@ fn suggest_impl_trait<'tcx>( None } -fn impl_trait_ref(tcx: TyCtxt<'_>, def_id: DefId) -> Option> { +fn impl_trait_ref(tcx: TyCtxt<'_>, def_id: DefId) -> Option>> { let icx = ItemCtxt::new(tcx, def_id); let item = tcx.hir().expect_item(def_id.expect_local()); match item.kind { - hir::ItemKind::Impl(ref impl_) => impl_.of_trait.as_ref().map(|ast_trait_ref| { - let selfty = tcx.type_of(def_id); - icx.astconv().instantiate_mono_trait_ref( - ast_trait_ref, - selfty, - check_impl_constness(tcx, impl_.constness, ast_trait_ref), - ) - }), + hir::ItemKind::Impl(ref impl_) => impl_ + .of_trait + .as_ref() + .map(|ast_trait_ref| { + let selfty = tcx.type_of(def_id); + icx.astconv().instantiate_mono_trait_ref( + ast_trait_ref, + selfty, + check_impl_constness(tcx, impl_.constness, ast_trait_ref), + ) + }) + .map(ty::EarlyBinder), _ => bug!(), } } diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index a44d9a6bddde..a7e6494c15ad 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -87,9 +87,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP Node::Item(item) => match item.kind { ItemKind::Impl(ref impl_) => { if impl_.defaultness.is_default() { - is_default_impl_trait = tcx - .bound_impl_trait_ref(def_id) - .map(|t| ty::Binder::dummy(t.subst_identity())); + is_default_impl_trait = + tcx.impl_trait_ref(def_id).map(|t| ty::Binder::dummy(t.subst_identity())); } &impl_.generics } @@ -253,7 +252,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP // for details. if let Node::Item(&Item { kind: ItemKind::Impl { .. }, .. }) = node { let self_ty = tcx.type_of(def_id); - let trait_ref = tcx.bound_impl_trait_ref(def_id).map(ty::EarlyBinder::subst_identity); + let trait_ref = tcx.impl_trait_ref(def_id).map(ty::EarlyBinder::subst_identity); cgp::setup_constraining_predicates( tcx, &mut predicates, diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index f845fa2ca5f0..1f9a9f80302e 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -286,7 +286,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { } } ImplItemKind::Type(ty) => { - if tcx.bound_impl_trait_ref(tcx.hir().get_parent_item(hir_id).to_def_id()).is_none() { + if tcx.impl_trait_ref(tcx.hir().get_parent_item(hir_id)).is_none() { check_feature_inherent_assoc_ty(tcx, item.span); } diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check.rs b/compiler/rustc_hir_analysis/src/impl_wf_check.rs index 208f146ebbf6..4fe893442b9b 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check.rs @@ -85,8 +85,7 @@ fn enforce_impl_params_are_constrained(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) } let impl_generics = tcx.generics_of(impl_def_id); let impl_predicates = tcx.predicates_of(impl_def_id); - let impl_trait_ref = - tcx.bound_impl_trait_ref(impl_def_id.into()).map(ty::EarlyBinder::subst_identity); + let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).map(ty::EarlyBinder::subst_identity); let mut input_parameters = cgp::parameters_for_impl(impl_self_ty, impl_trait_ref); cgp::identify_constrained_generic_params( diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs index ab40fa57acf3..bcda26c4cc85 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs @@ -89,7 +89,7 @@ pub(super) fn check_min_specialization(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) } fn parent_specialization_node(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId) -> Option { - let trait_ref = tcx.bound_impl_trait_ref(impl1_def_id.into())?; + let trait_ref = tcx.impl_trait_ref(impl1_def_id)?; let trait_def = tcx.trait_def(trait_ref.skip_binder().def_id); let impl2_node = trait_def.ancestors(tcx, impl1_def_id.to_def_id()).ok()?.nth(1)?; @@ -207,7 +207,7 @@ fn unconstrained_parent_impl_substs<'tcx>( let impl_generic_predicates = tcx.predicates_of(impl_def_id); let mut unconstrained_parameters = FxHashSet::default(); let mut constrained_params = FxHashSet::default(); - let impl_trait_ref = tcx.bound_impl_trait_ref(impl_def_id).map(ty::EarlyBinder::subst_identity); + let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).map(ty::EarlyBinder::subst_identity); // Unfortunately the functions in `constrained_generic_parameters` don't do // what we want here. We want only a list of constrained parameters while @@ -370,7 +370,7 @@ fn check_predicates<'tcx>( }); // Include the well-formed predicates of the type parameters of the impl. - for arg in tcx.bound_impl_trait_ref(impl1_def_id.into()).unwrap().subst_identity().substs { + for arg in tcx.impl_trait_ref(impl1_def_id).unwrap().subst_identity().substs { let infcx = &tcx.infer_ctxt().build(); let obligations = wf::obligations( infcx, diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index 1a5a2ec7823b..4a33a791e1b7 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -240,7 +240,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { probe::InherentImplPick => { let impl_def_id = pick.item.container_id(self.tcx); assert!( - self.tcx.bound_impl_trait_ref(impl_def_id).is_none(), + self.tcx.impl_trait_ref(impl_def_id).is_none(), "impl {:?} is not an inherent impl", impl_def_id ); diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 109ceb8956b4..723d489ec46f 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -1036,7 +1036,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Provide the best span we can. Use the item, if local to crate, else // the impl, if local to crate (item may be defaulted), else nothing. let Some(item) = self.associated_value(impl_did, item_name).or_else(|| { - let impl_trait_ref = self.tcx.bound_impl_trait_ref(impl_did)?; + let impl_trait_ref = self.tcx.impl_trait_ref(impl_did)?; self.associated_value(impl_trait_ref.skip_binder().def_id, item_name) }) else { continue; @@ -1052,7 +1052,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let impl_ty = self.tcx.at(span).type_of(impl_did); - let insertion = match self.tcx.bound_impl_trait_ref(impl_did) { + let insertion = match self.tcx.impl_trait_ref(impl_did) { None => String::new(), Some(trait_ref) => { format!( @@ -1088,7 +1088,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.note(¬e_str); } if let Some(sugg_span) = sugg_span - && let Some(trait_ref) = self.tcx.bound_impl_trait_ref(impl_did) { + && let Some(trait_ref) = self.tcx.impl_trait_ref(impl_did) { let path = self.tcx.def_path_str(trait_ref.skip_binder().def_id); let ty = match item.kind { @@ -2584,8 +2584,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx.impl_polarity(*imp_did) == ty::ImplPolarity::Negative }) .any(|imp_did| { - let imp = - self.tcx.bound_impl_trait_ref(imp_did).unwrap().subst_identity(); + let imp = self.tcx.impl_trait_ref(imp_did).unwrap().subst_identity(); let imp_simp = simplify_type(self.tcx, imp.self_ty(), TreatParams::AsPlaceholder); imp_simp.map_or(false, |s| s == simp_rcvr_ty) diff --git a/compiler/rustc_infer/src/infer/error_reporting/note.rs b/compiler/rustc_infer/src/infer/error_reporting/note.rs index 2670eb0d1455..021e741ee2f7 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs @@ -317,7 +317,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { self.tcx.associated_item(impl_item_def_id).impl_container(self.tcx) else { return; }; let Some(trait_ref) = self .tcx - .bound_impl_trait_ref(impl_def_id) + .impl_trait_ref(impl_def_id) else { return; }; let trait_substs = trait_ref .subst_identity() diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs index 18a040ab8b18..74d234fabea0 100644 --- a/compiler/rustc_lint/src/nonstandard_style.rs +++ b/compiler/rustc_lint/src/nonstandard_style.rs @@ -26,7 +26,7 @@ pub fn method_context(cx: &LateContext<'_>, id: hir::HirId) -> MethodLateContext let item = cx.tcx.associated_item(def_id); match item.container { ty::TraitContainer => MethodLateContext::TraitAutoImpl, - ty::ImplContainer => match cx.tcx.bound_impl_trait_ref(item.container_id(cx.tcx)) { + ty::ImplContainer => match cx.tcx.impl_trait_ref(item.container_id(cx.tcx)) { Some(_) => MethodLateContext::TraitImpl, None => MethodLateContext::PlainImpl, }, diff --git a/compiler/rustc_lint/src/pass_by_value.rs b/compiler/rustc_lint/src/pass_by_value.rs index 212b8aa1574d..57482a9edba8 100644 --- a/compiler/rustc_lint/src/pass_by_value.rs +++ b/compiler/rustc_lint/src/pass_by_value.rs @@ -24,7 +24,7 @@ impl<'tcx> LateLintPass<'tcx> for PassByValue { match &ty.kind { TyKind::Ref(_, hir::MutTy { ty: inner_ty, mutbl: hir::Mutability::Not }) => { if let Some(impl_did) = cx.tcx.impl_of_method(ty.hir_id.owner.to_def_id()) { - if cx.tcx.bound_impl_trait_ref(impl_did).is_some() { + if cx.tcx.impl_trait_ref(impl_did).is_some() { return; } } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 3504a3bde450..ba856a11890e 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1555,8 +1555,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.tables.impl_defaultness.set(def_id.index, *defaultness); self.tables.constness.set(def_id.index, *constness); - let trait_ref = - self.tcx.bound_impl_trait_ref(def_id).map(ty::EarlyBinder::skip_binder); + let trait_ref = self.tcx.impl_trait_ref(def_id).map(ty::EarlyBinder::skip_binder); if let Some(trait_ref) = trait_ref { let trait_def = self.tcx.trait_def(trait_ref.def_id); if let Ok(mut an) = trait_def.ancestors(self.tcx, def_id) { @@ -1633,9 +1632,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } } if let hir::ItemKind::Impl { .. } = item.kind { - if let Some(trait_ref) = - self.tcx.bound_impl_trait_ref(def_id).map(ty::EarlyBinder::subst_identity) - { + if let Some(trait_ref) = self.tcx.impl_trait_ref(def_id) { record!(self.tables.impl_trait_ref[def_id] <- trait_ref); } } @@ -1901,9 +1898,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { for id in tcx.hir().items() { if matches!(tcx.def_kind(id.owner_id), DefKind::Impl) { - if let Some(trait_ref) = tcx - .bound_impl_trait_ref(id.owner_id.to_def_id()) - .map(ty::EarlyBinder::subst_identity) + if let Some(trait_ref) = + tcx.impl_trait_ref(id.owner_id).map(ty::EarlyBinder::subst_identity) { let simplified_self_ty = fast_reject::simplify_type( self.tcx, diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 5beee06d5211..5b7b096b4edf 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -359,7 +359,7 @@ define_tables! { variances_of: Table>, fn_sig: Table>>, codegen_fn_attrs: Table>, - impl_trait_ref: Table>>, + impl_trait_ref: Table>>>, const_param_default: Table>>>, object_lifetime_default: Table>, optimized_mir: Table>>, diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index e43e584b0b0d..f567eaf96772 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -101,7 +101,7 @@ impl<'tcx> TyCtxt<'tcx> { } pub fn impl_subject(self, def_id: DefId) -> ImplSubject<'tcx> { - self.bound_impl_trait_ref(def_id) + self.impl_trait_ref(def_id) .map(|t| t.subst_identity()) .map(ImplSubject::Trait) .unwrap_or_else(|| ImplSubject::Inherent(self.type_of(def_id))) diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index cdc78a86349f..b3acf815e0c1 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -737,7 +737,7 @@ rustc_queries! { /// Given an `impl_id`, return the trait it implements. /// Return `None` if this is an inherent impl. - query impl_trait_ref(impl_id: DefId) -> Option> { + query impl_trait_ref(impl_id: DefId) -> Option>> { desc { |tcx| "computing trait implemented by `{}`", tcx.def_path_str(impl_id) } cache_on_disk_if { impl_id.is_local() } separate_provide_extern diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 6270c2ebb28f..63f31e5a11f3 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1027,7 +1027,7 @@ impl<'tcx> TyCtxt<'tcx> { /// Checks if the bound region is in Impl Item. pub fn is_bound_region_in_impl_item(self, suitable_region_binding_scope: LocalDefId) -> bool { let container_id = self.parent(suitable_region_binding_scope.to_def_id()); - if self.bound_impl_trait_ref(container_id).is_some() { + if self.impl_trait_ref(container_id).is_some() { // For now, we do not try to target impls of traits. This is // because this message is going to suggest that the user // change the fn signature, but they may not be free to do so, diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index ac762b9dfb27..7cc4ad4ca46c 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2187,12 +2187,8 @@ impl<'tcx> TyCtxt<'tcx> { ) -> Option { // If either trait impl references an error, they're allowed to overlap, // as one of them essentially doesn't exist. - if self - .bound_impl_trait_ref(def_id1) - .map_or(false, |tr| tr.skip_binder().references_error()) - || self - .bound_impl_trait_ref(def_id2) - .map_or(false, |tr| tr.skip_binder().references_error()) + if self.impl_trait_ref(def_id1).map_or(false, |tr| tr.skip_binder().references_error()) + || self.impl_trait_ref(def_id2).map_or(false, |tr| tr.skip_binder().references_error()) { return Some(ImplOverlapKind::Permitted { marker: false }); } @@ -2221,7 +2217,7 @@ impl<'tcx> TyCtxt<'tcx> { let is_marker_overlap = { let is_marker_impl = |def_id: DefId| -> bool { - let trait_ref = self.bound_impl_trait_ref(def_id); + let trait_ref = self.impl_trait_ref(def_id); trait_ref.map_or(false, |tr| self.trait_def(tr.skip_binder().def_id).is_marker) }; is_marker_impl(def_id1) && is_marker_impl(def_id2) @@ -2368,7 +2364,7 @@ impl<'tcx> TyCtxt<'tcx> { /// Given the `DefId` of an impl, returns the `DefId` of the trait it implements. /// If it implements no trait, returns `None`. pub fn trait_id_of_impl(self, def_id: DefId) -> Option { - self.bound_impl_trait_ref(def_id).map(|tr| tr.skip_binder().def_id) + self.impl_trait_ref(def_id).map(|tr| tr.skip_binder().def_id) } /// If the given `DefId` describes an item belonging to a trait, diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs index 29bad33e4bc0..c302c461195a 100644 --- a/compiler/rustc_middle/src/ty/print/mod.rs +++ b/compiler/rustc_middle/src/ty/print/mod.rs @@ -116,7 +116,7 @@ pub trait Printer<'tcx>: Sized { DefPathData::Impl => { let generics = self.tcx().generics_of(def_id); let self_ty = self.tcx().bound_type_of(def_id); - let impl_trait_ref = self.tcx().bound_impl_trait_ref(def_id); + let impl_trait_ref = self.tcx().impl_trait_ref(def_id); let (self_ty, impl_trait_ref) = if substs.len() >= generics.count() { ( self_ty.subst(self.tcx(), substs), diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 1f0c96a93b97..1286a5253c06 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -652,13 +652,6 @@ impl<'tcx> TyCtxt<'tcx> { ty::EarlyBinder(self.fn_sig(def_id)) } - pub fn bound_impl_trait_ref( - self, - def_id: DefId, - ) -> Option>> { - self.impl_trait_ref(def_id).map(|i| ty::EarlyBinder(i)) - } - pub fn bound_explicit_item_bounds( self, def_id: DefId, diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 070947410f38..3080248d5082 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -1351,9 +1351,8 @@ fn create_mono_items_for_default_impls<'tcx>( tcx.def_path_str(item.owner_id.to_def_id()) ); - if let Some(trait_ref) = tcx - .bound_impl_trait_ref(item.owner_id.to_def_id()) - .map(ty::EarlyBinder::subst_identity) + if let Some(trait_ref) = + tcx.impl_trait_ref(item.owner_id).map(ty::EarlyBinder::subst_identity) { let param_env = ty::ParamEnv::reveal_all(); let trait_ref = tcx.normalize_erasing_regions(param_env, trait_ref); diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 88ad7b28f544..94171b4b0c8f 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -266,7 +266,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { if let Some(trait_of) = self.tcx.trait_id_of_impl(impl_of) && self.tcx.has_attr(trait_of, sym::rustc_trivial_field_reads) { - let trait_ref = self.tcx.bound_impl_trait_ref(impl_of).unwrap().subst_identity(); + let trait_ref = self.tcx.impl_trait_ref(impl_of).unwrap().subst_identity(); if let ty::Adt(adt_def, _) = trait_ref.self_ty().kind() && let Some(adt_def_id) = adt_def.did().as_local() { @@ -310,7 +310,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { } Node::ImplItem(impl_item) => { let item = self.tcx.local_parent(impl_item.owner_id.def_id); - if self.tcx.bound_impl_trait_ref(item.into()).is_none() { + if self.tcx.impl_trait_ref(item).is_none() { //// If it's a type whose items are live, then it's live, too. //// This is done to handle the case where, for example, the static //// method of a private type is used, but the type itself is never @@ -534,7 +534,7 @@ fn check_item<'tcx>( } } DefKind::Impl => { - let of_trait = tcx.bound_impl_trait_ref(id.owner_id.to_def_id()); + let of_trait = tcx.impl_trait_ref(id.owner_id); if of_trait.is_some() { worklist.push(id.owner_id.def_id); diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 3ecc9faf7662..96f7236de5cb 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -593,7 +593,7 @@ impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> { fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem<'tcx>) { let impl_def_id = self.tcx.hir().get_parent_item(ii.hir_id()); - if self.tcx.bound_impl_trait_ref(impl_def_id.to_def_id()).is_none() { + if self.tcx.impl_trait_ref(impl_def_id).is_none() { self.check_missing_stability(ii.owner_id.def_id, ii.span); self.check_missing_const_stability(ii.owner_id.def_id, ii.span); } diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 69bfa8e2709a..fb55bb4afaac 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -337,7 +337,7 @@ trait VisibilityLike: Sized { ) -> Self { let mut find = FindMin { tcx, effective_visibilities, min: Self::MAX }; find.visit(tcx.type_of(def_id)); - if let Some(trait_ref) = tcx.bound_impl_trait_ref(def_id.into()) { + if let Some(trait_ref) = tcx.impl_trait_ref(def_id) { find.visit_trait(trait_ref.subst_identity()); } find.min @@ -857,7 +857,7 @@ impl ReachEverythingInTheInterfaceVisitor<'_, '_> { } fn trait_ref(&mut self) -> &mut Self { - if let Some(trait_ref) = self.ev.tcx.bound_impl_trait_ref(self.item_def_id.into()) { + if let Some(trait_ref) = self.ev.tcx.impl_trait_ref(self.item_def_id) { self.visit_trait(trait_ref.subst_identity()); } self diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs index 3d649bea19dd..e9140507192e 100644 --- a/compiler/rustc_trait_selection/src/solve/project_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs @@ -110,7 +110,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> { ) { let tcx = acx.cx.tcx; let goal_trait_ref = goal.predicate.projection_ty.trait_ref(tcx); - let impl_trait_ref = tcx.bound_impl_trait_ref(impl_def_id).unwrap(); + let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap(); let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::AsPlaceholder }; if iter::zip(goal_trait_ref.substs, impl_trait_ref.skip_binder().substs) .any(|(goal, imp)| !drcx.generic_args_may_unify(goal, imp)) diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index c69cc39acb53..a43fef5cdb0c 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -73,7 +73,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { ) { let tcx = acx.cx.tcx; - let impl_trait_ref = tcx.bound_impl_trait_ref(impl_def_id).unwrap(); + let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap(); let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::AsPlaceholder }; if iter::zip(goal.predicate.trait_ref.substs, impl_trait_ref.skip_binder().substs) .any(|(goal, imp)| !drcx.generic_args_may_unify(goal, imp)) diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 623ef7964bf0..185810ed3d8e 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -77,8 +77,8 @@ pub fn overlapping_impls( // a quick check via fast_reject to tell if the impl headers could possibly // unify. let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::AsInfer }; - let impl1_ref = tcx.bound_impl_trait_ref(impl1_def_id).map(ty::EarlyBinder::subst_identity); - let impl2_ref = tcx.bound_impl_trait_ref(impl2_def_id).map(ty::EarlyBinder::subst_identity); + let impl1_ref = tcx.impl_trait_ref(impl1_def_id).map(ty::EarlyBinder::subst_identity); + let impl2_ref = tcx.impl_trait_ref(impl2_def_id).map(ty::EarlyBinder::subst_identity); let may_overlap = match (impl1_ref, impl2_ref) { (Some(a), Some(b)) => iter::zip(a.substs, b.substs) .all(|(arg1, arg2)| drcx.generic_args_may_unify(arg1, arg2)), @@ -126,7 +126,7 @@ fn with_fresh_ty_vars<'cx, 'tcx>( let header = ty::ImplHeader { impl_def_id, self_ty: tcx.bound_type_of(impl_def_id).subst(tcx, impl_substs), - trait_ref: tcx.bound_impl_trait_ref(impl_def_id).map(|i| i.subst(tcx, impl_substs)), + trait_ref: tcx.impl_trait_ref(impl_def_id).map(|i| i.subst(tcx, impl_substs)), predicates: tcx.predicates_of(impl_def_id).instantiate(tcx, impl_substs).predicates, }; @@ -461,7 +461,7 @@ pub fn orphan_check(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Result<(), OrphanChe // We only except this routine to be invoked on implementations // of a trait, not inherent implementations. - let trait_ref = tcx.bound_impl_trait_ref(impl_def_id).unwrap().skip_binder(); + let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().skip_binder(); debug!("orphan_check: trait_ref={:?}", trait_ref); // If the *trait* is local to the crate, ok. diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs index 0c1717cff332..df57c0f60fa6 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs @@ -27,7 +27,7 @@ pub fn recompute_applicable_impls<'tcx>( ocx.normalize(&ObligationCause::dummy(), param_env, placeholder_obligation.trait_ref); let impl_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id); - let impl_trait_ref = tcx.bound_impl_trait_ref(impl_def_id).unwrap().subst(tcx, impl_substs); + let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().subst(tcx, impl_substs); let impl_trait_ref = ocx.normalize(&ObligationCause::dummy(), param_env, impl_trait_ref); if let Err(_) = 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 8b9c6821dafe..5d2e0bd5afa4 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1940,7 +1940,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { return None; } - let imp = self.tcx.bound_impl_trait_ref(def_id).unwrap().subst_identity(); + let imp = self.tcx.impl_trait_ref(def_id).unwrap().subst_identity(); self.fuzzy_match_tys(trait_pred.skip_binder().self_ty(), imp.self_ty(), false) .map(|similarity| ImplCandidate { trait_ref: imp, similarity }) @@ -2039,7 +2039,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { self.tcx.impl_polarity(def_id) != ty::ImplPolarity::Negative || self.tcx.is_builtin_derive(def_id) }) - .filter_map(|def_id| self.tcx.bound_impl_trait_ref(def_id)) + .filter_map(|def_id| self.tcx.impl_trait_ref(def_id)) .map(ty::EarlyBinder::subst_identity) .filter(|trait_ref| { let self_ty = trait_ref.self_ty(); diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs index e599996230f5..18d308f7123a 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs @@ -68,7 +68,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { self.tcx.for_each_relevant_impl(trait_ref.def_id, trait_self_ty, |def_id| { let impl_substs = self.fresh_substs_for_item(obligation.cause.span, def_id); - let impl_trait_ref = tcx.bound_impl_trait_ref(def_id).unwrap().subst(tcx, impl_substs); + let impl_trait_ref = tcx.impl_trait_ref(def_id).unwrap().subst(tcx, impl_substs); let impl_self_ty = impl_trait_ref.self_ty(); diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 4c34dc64c26c..241ae0275cec 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -522,7 +522,7 @@ fn is_impossible_method(tcx: TyCtxt<'_>, (impl_def_id, trait_item_def_id): (DefI let generics = tcx.generics_of(trait_item_def_id); let predicates = tcx.predicates_of(trait_item_def_id); let impl_trait_ref = tcx - .bound_impl_trait_ref(impl_def_id) + .impl_trait_ref(impl_def_id) .expect("expected impl to correspond to trait") .subst_identity(); let param_env = tcx.param_env(impl_def_id); diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 8c291d1595d9..e29ad30d5f2e 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -357,7 +357,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Before we create the substitutions and everything, first // consider a "quick reject". This avoids creating more types // and so forth that we need to. - let impl_trait_ref = self.tcx().bound_impl_trait_ref(impl_def_id).unwrap(); + let impl_trait_ref = self.tcx().impl_trait_ref(impl_def_id).unwrap(); if self.fast_reject_trait_refs(obligation, &impl_trait_ref.0) { return; } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 305902af7c82..ba4e668f52dd 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2335,7 +2335,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { impl_def_id: DefId, obligation: &TraitObligation<'tcx>, ) -> Normalized<'tcx, SubstsRef<'tcx>> { - let impl_trait_ref = self.tcx().bound_impl_trait_ref(impl_def_id).unwrap(); + let impl_trait_ref = self.tcx().impl_trait_ref(impl_def_id).unwrap(); match self.match_impl(impl_def_id, impl_trait_ref, obligation) { Ok(substs) => substs, Err(()) => { diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index a352a65fb068..69b671b27bd5 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs @@ -87,7 +87,7 @@ pub fn translate_substs<'tcx>( param_env, source_impl, source_substs, target_node ); let source_trait_ref = - infcx.tcx.bound_impl_trait_ref(source_impl).unwrap().subst(infcx.tcx, &source_substs); + infcx.tcx.impl_trait_ref(source_impl).unwrap().subst(infcx.tcx, &source_substs); // translate the Self and Param parts of the substitution, since those // vary across impls @@ -148,7 +148,7 @@ pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId, // create a parameter environment corresponding to a (placeholder) instantiation of impl1 let penv = tcx.param_env(impl1_def_id); - let impl1_trait_ref = tcx.bound_impl_trait_ref(impl1_def_id).unwrap().subst_identity(); + let impl1_trait_ref = tcx.impl_trait_ref(impl1_def_id).unwrap().subst_identity(); // Create an infcx, taking the predicates of impl1 as assumptions: let infcx = tcx.infer_ctxt().build(); @@ -431,7 +431,7 @@ fn report_conflicting_impls<'tcx>( pub(crate) fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Option { use std::fmt::Write; - let trait_ref = tcx.bound_impl_trait_ref(impl_def_id)?.skip_binder(); + let trait_ref = tcx.impl_trait_ref(impl_def_id)?.skip_binder(); let mut w = "impl".to_owned(); let substs = InternalSubsts::identity_for_item(tcx, impl_def_id); diff --git a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs index a2e39c53d15c..eb4815122c33 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs @@ -48,7 +48,7 @@ trait ChildrenExt<'tcx> { impl<'tcx> ChildrenExt<'tcx> for Children { /// Insert an impl into this set of children without comparing to any existing impls. fn insert_blindly(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) { - let trait_ref = tcx.bound_impl_trait_ref(impl_def_id).unwrap().subst_identity(); + let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().subst_identity(); if let Some(st) = fast_reject::simplify_type(tcx, trait_ref.self_ty(), TreatParams::AsInfer) { debug!("insert_blindly: impl_def_id={:?} st={:?}", impl_def_id, st); @@ -63,7 +63,7 @@ impl<'tcx> ChildrenExt<'tcx> for Children { /// an impl with a parent. The impl must be present in the list of /// children already. fn remove_existing(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) { - let trait_ref = tcx.bound_impl_trait_ref(impl_def_id).unwrap().subst_identity(); + let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().subst_identity(); let vec: &mut Vec; if let Some(st) = fast_reject::simplify_type(tcx, trait_ref.self_ty(), TreatParams::AsInfer) { @@ -181,7 +181,7 @@ impl<'tcx> ChildrenExt<'tcx> for Children { if le && !ge { debug!( "descending as child of TraitRef {:?}", - tcx.bound_impl_trait_ref(possible_sibling).unwrap().subst_identity() + tcx.impl_trait_ref(possible_sibling).unwrap().subst_identity() ); // The impl specializes `possible_sibling`. @@ -189,7 +189,7 @@ impl<'tcx> ChildrenExt<'tcx> for Children { } else if ge && !le { debug!( "placing as parent of TraitRef {:?}", - tcx.bound_impl_trait_ref(possible_sibling).unwrap().subst_identity() + tcx.impl_trait_ref(possible_sibling).unwrap().subst_identity() ); replace_children.push(possible_sibling); @@ -275,7 +275,7 @@ impl<'tcx> GraphExt<'tcx> for Graph { ) -> Result>, OverlapError<'tcx>> { assert!(impl_def_id.is_local()); - let trait_ref = tcx.bound_impl_trait_ref(impl_def_id).unwrap().subst_identity(); + let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().subst_identity(); let trait_def_id = trait_ref.def_id; debug!( @@ -388,7 +388,7 @@ pub(crate) fn assoc_def( impl_def_id: DefId, assoc_def_id: DefId, ) -> Result { - let trait_def_id = tcx.bound_impl_trait_ref(impl_def_id).unwrap().skip_binder().def_id; + let trait_def_id = tcx.impl_trait_ref(impl_def_id).unwrap().skip_binder().def_id; let trait_def = tcx.trait_def(trait_def_id); // This function may be called while we are still building the diff --git a/compiler/rustc_traits/src/chalk/db.rs b/compiler/rustc_traits/src/chalk/db.rs index dea33f896cf1..7c0cae1e7bdc 100644 --- a/compiler/rustc_traits/src/chalk/db.rs +++ b/compiler/rustc_traits/src/chalk/db.rs @@ -309,7 +309,7 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t let bound_vars = bound_vars_for_item(self.interner.tcx, def_id); let binders = binders_for(self.interner, bound_vars); - let trait_ref = self.interner.tcx.bound_impl_trait_ref(def_id).expect("not an impl"); + let trait_ref = self.interner.tcx.impl_trait_ref(def_id).expect("not an impl"); let trait_ref = trait_ref.subst(self.interner.tcx, bound_vars); let where_clauses = self.where_clauses_for(def_id, bound_vars); @@ -351,7 +351,7 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t let all_impls = self.interner.tcx.all_impls(def_id); let matched_impls = all_impls.filter(|impl_def_id| { use chalk_ir::could_match::CouldMatch; - let trait_ref = self.interner.tcx.bound_impl_trait_ref(*impl_def_id).unwrap(); + let trait_ref = self.interner.tcx.impl_trait_ref(*impl_def_id).unwrap(); let bound_vars = bound_vars_for_item(self.interner.tcx, *impl_def_id); let self_ty = trait_ref.map_bound(|t| t.self_ty()); @@ -380,8 +380,7 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t let trait_def_id = auto_trait_id.0; let all_impls = self.interner.tcx.all_impls(trait_def_id); for impl_def_id in all_impls { - let trait_ref = - self.interner.tcx.bound_impl_trait_ref(impl_def_id).unwrap().subst_identity(); + let trait_ref = self.interner.tcx.impl_trait_ref(impl_def_id).unwrap().subst_identity(); let self_ty = trait_ref.self_ty(); let provides = match (self_ty.kind(), chalk_ty) { (&ty::Adt(impl_adt_def, ..), Adt(id, ..)) => impl_adt_def.did() == id.0.did(), diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs index d890a04599b1..7a9c1d8ffe7d 100644 --- a/compiler/rustc_ty_utils/src/implied_bounds.rs +++ b/compiler/rustc_ty_utils/src/implied_bounds.rs @@ -22,7 +22,7 @@ fn assumed_wf_types(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::List> { tcx.intern_type_list(&assumed_wf_types) } DefKind::Impl => { - match tcx.bound_impl_trait_ref(def_id).map(ty::EarlyBinder::subst_identity) { + match tcx.impl_trait_ref(def_id).map(ty::EarlyBinder::subst_identity) { Some(trait_ref) => { let types: Vec<_> = trait_ref.substs.types().collect(); tcx.intern_type_list(&types) diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 78c3a208e889..eb5454bf2634 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -289,7 +289,7 @@ fn well_formed_types_in_env(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::List { - let trait_ref = tcx.bound_impl_trait_ref(def_id).expect("not an impl").subst_identity(); + let trait_ref = tcx.impl_trait_ref(def_id).expect("not an impl").subst_identity(); // FIXME(chalk): this has problems because of late-bound regions //inputs.extend(trait_ref.substs.iter().flat_map(|arg| arg.walk())); @@ -359,7 +359,7 @@ fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option> { debug!("issue33140_self_ty({:?})", def_id); let trait_ref = tcx - .bound_impl_trait_ref(def_id) + .impl_trait_ref(def_id) .unwrap_or_else(|| bug!("issue33140_self_ty called on inherent impl {:?}", def_id)) .skip_binder(); diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs index 4ef5747596bb..e6b2b2349452 100644 --- a/src/librustdoc/clean/blanket_impl.rs +++ b/src/librustdoc/clean/blanket_impl.rs @@ -33,7 +33,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> { trait_def_id, impl_def_id ); - let trait_ref = cx.tcx.bound_impl_trait_ref(impl_def_id).unwrap(); + let trait_ref = cx.tcx.impl_trait_ref(impl_def_id).unwrap(); if !matches!(trait_ref.0.self_ty().kind(), ty::Param(_)) { continue; } diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 23330daa54bf..c6939326144e 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -376,7 +376,7 @@ pub(crate) fn build_impl( let _prof_timer = cx.tcx.sess.prof.generic_activity("build_impl"); let tcx = cx.tcx; - let associated_trait = tcx.bound_impl_trait_ref(did).map(ty::EarlyBinder::skip_binder); + let associated_trait = tcx.impl_trait_ref(did).map(ty::EarlyBinder::skip_binder); // Only inline impl if the implemented trait is // reachable in rustdoc generated documentation diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index cda90955ba11..87de41fde63c 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -734,7 +734,7 @@ impl Item { ty::ImplContainer => { // Trait impl items always inherit the impl's visibility -- // we don't want to show `pub`. - tcx.bound_impl_trait_ref(tcx.parent(assoc_item.def_id)).is_some() + tcx.impl_trait_ref(tcx.parent(assoc_item.def_id)).is_some() } }; if is_trait_item { diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index fa9174287e27..62588040685f 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -784,7 +784,7 @@ fn trait_impls_for<'a>( // Look at each trait implementation to see if it's an impl for `did` tcx.find_map_relevant_impl(trait_, ty, |impl_| { - let trait_ref = tcx.bound_impl_trait_ref(impl_).expect("this is not an inherent impl"); + let trait_ref = tcx.impl_trait_ref(impl_).expect("this is not an inherent impl"); // Check if these are the same type. let impl_type = trait_ref.subst_identity().self_ty(); trace!( diff --git a/src/tools/clippy/clippy_lints/src/derive.rs b/src/tools/clippy/clippy_lints/src/derive.rs index 6b2b18fff76e..248d73884106 100644 --- a/src/tools/clippy/clippy_lints/src/derive.rs +++ b/src/tools/clippy/clippy_lints/src/derive.rs @@ -247,7 +247,7 @@ fn check_hash_peq<'tcx>( return; } - let trait_ref = cx.tcx.bound_impl_trait_ref(impl_id).expect("must be a trait implementation"); + let trait_ref = cx.tcx.impl_trait_ref(impl_id).expect("must be a trait implementation"); // Only care about `impl PartialEq for Foo` // For `impl PartialEq for A, input_types is [A, B] @@ -295,7 +295,7 @@ fn check_ord_partial_ord<'tcx>( return; } - let trait_ref = cx.tcx.bound_impl_trait_ref(impl_id).expect("must be a trait implementation"); + let trait_ref = cx.tcx.impl_trait_ref(impl_id).expect("must be a trait implementation"); // Only care about `impl PartialOrd for Foo` // For `impl PartialOrd for A, input_types is [A, B] diff --git a/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs b/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs index a8085122ccf9..2ef547526d4f 100644 --- a/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs +++ b/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs @@ -55,7 +55,7 @@ impl<'tcx> LateLintPass<'tcx> for FallibleImplFrom { // check for `impl From for ..` if_chain! { if let hir::ItemKind::Impl(impl_) = &item.kind; - if let Some(impl_trait_ref) = cx.tcx.bound_impl_trait_ref(item.owner_id.to_def_id()); + if let Some(impl_trait_ref) = cx.tcx.impl_trait_ref(item.owner_id); if cx.tcx.is_diagnostic_item(sym::From, impl_trait_ref.skip_binder().def_id); then { lint_impl_body(cx, item.span, impl_.items); diff --git a/src/tools/clippy/clippy_lints/src/from_over_into.rs b/src/tools/clippy/clippy_lints/src/from_over_into.rs index 97d414bfa95e..bd66ace4500a 100644 --- a/src/tools/clippy/clippy_lints/src/from_over_into.rs +++ b/src/tools/clippy/clippy_lints/src/from_over_into.rs @@ -76,7 +76,7 @@ impl<'tcx> LateLintPass<'tcx> for FromOverInto { && let Some(into_trait_seg) = hir_trait_ref.path.segments.last() // `impl Into for self_ty` && let Some(GenericArgs { args: [GenericArg::Type(target_ty)], .. }) = into_trait_seg.args - && let Some(middle_trait_ref) = cx.tcx.bound_impl_trait_ref(item.owner_id.to_def_id()).map(ty::EarlyBinder::subst_identity) + && let Some(middle_trait_ref) = cx.tcx.impl_trait_ref(item.owner_id).map(ty::EarlyBinder::subst_identity) && cx.tcx.is_diagnostic_item(sym::Into, middle_trait_ref.def_id) && !matches!(middle_trait_ref.substs.type_at(1).kind(), ty::Alias(ty::Opaque, _)) { diff --git a/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs b/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs index 37e33529a9a6..29d59c26d92c 100644 --- a/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs +++ b/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs @@ -101,7 +101,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingSub { if name.ident.as_str() == "MIN"; if let Some(const_id) = cx.typeck_results().type_dependent_def_id(cond_num_val.hir_id); if let Some(impl_id) = cx.tcx.impl_of_method(const_id); - if let None = cx.tcx.bound_impl_trait_ref(impl_id); // An inherent impl + if let None = cx.tcx.impl_trait_ref(impl_id); // An inherent impl if cx.tcx.type_of(impl_id).is_integral(); then { print_lint_and_sugg(cx, var_name, expr) @@ -114,7 +114,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingSub { if name.ident.as_str() == "min_value"; if let Some(func_id) = cx.typeck_results().type_dependent_def_id(func.hir_id); if let Some(impl_id) = cx.tcx.impl_of_method(func_id); - if let None = cx.tcx.bound_impl_trait_ref(impl_id); // An inherent impl + if let None = cx.tcx.impl_trait_ref(impl_id); // An inherent impl if cx.tcx.type_of(impl_id).is_integral(); then { print_lint_and_sugg(cx, var_name, expr) diff --git a/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs b/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs index 16a25a98800d..06ecbce4e70e 100644 --- a/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs +++ b/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs @@ -53,7 +53,7 @@ pub fn is_clone_like(cx: &LateContext<'_>, method_name: &str, method_def_id: hir "to_vec" => cx .tcx .impl_of_method(method_def_id) - .filter(|&impl_did| cx.tcx.type_of(impl_did).is_slice() && cx.tcx.bound_impl_trait_ref(impl_did).is_none()) + .filter(|&impl_did| cx.tcx.type_of(impl_did).is_slice() && cx.tcx.impl_trait_ref(impl_did).is_none()) .is_some(), _ => false, } diff --git a/src/tools/clippy/clippy_lints/src/methods/suspicious_splitn.rs b/src/tools/clippy/clippy_lints/src/methods/suspicious_splitn.rs index dba0663467b7..219a9edd6576 100644 --- a/src/tools/clippy/clippy_lints/src/methods/suspicious_splitn.rs +++ b/src/tools/clippy/clippy_lints/src/methods/suspicious_splitn.rs @@ -12,7 +12,7 @@ pub(super) fn check(cx: &LateContext<'_>, method_name: &str, expr: &Expr<'_>, se if count <= 1; if let Some(call_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id); if let Some(impl_id) = cx.tcx.impl_of_method(call_id); - if cx.tcx.bound_impl_trait_ref(impl_id).is_none(); + if cx.tcx.impl_trait_ref(impl_id).is_none(); let self_ty = cx.tcx.type_of(impl_id); if self_ty.is_slice() || self_ty.is_str(); then { diff --git a/src/tools/clippy/clippy_lints/src/missing_doc.rs b/src/tools/clippy/clippy_lints/src/missing_doc.rs index d0c99b352452..6fd100762b49 100644 --- a/src/tools/clippy/clippy_lints/src/missing_doc.rs +++ b/src/tools/clippy/clippy_lints/src/missing_doc.rs @@ -175,7 +175,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx hir::ImplItem<'_>) { // If the method is an impl for a trait, don't doc. if let Some(cid) = cx.tcx.associated_item(impl_item.owner_id).impl_container(cx.tcx) { - if cx.tcx.bound_impl_trait_ref(cid).is_some() { + if cx.tcx.impl_trait_ref(cid).is_some() { return; } } else { diff --git a/src/tools/clippy/clippy_lints/src/missing_inline.rs b/src/tools/clippy/clippy_lints/src/missing_inline.rs index 0594fb175458..5a459548153a 100644 --- a/src/tools/clippy/clippy_lints/src/missing_inline.rs +++ b/src/tools/clippy/clippy_lints/src/missing_inline.rs @@ -155,7 +155,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline { let container_id = assoc_item.container_id(cx.tcx); let trait_def_id = match assoc_item.container { TraitContainer => Some(container_id), - ImplContainer => cx.tcx.bound_impl_trait_ref(container_id).map(|t| t.skip_binder().def_id), + ImplContainer => cx.tcx.impl_trait_ref(container_id).map(|t| t.skip_binder().def_id), }; if let Some(trait_def_id) = trait_def_id { diff --git a/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs b/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs index 9c112ade948f..839c3a3815c2 100644 --- a/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs +++ b/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs @@ -89,7 +89,7 @@ impl<'tcx> LateLintPass<'tcx> for NonSendFieldInSendTy { if let Some(trait_id) = trait_ref.trait_def_id(); if send_trait == trait_id; if hir_impl.polarity == ImplPolarity::Positive; - if let Some(ty_trait_ref) = cx.tcx.bound_impl_trait_ref(item.owner_id.to_def_id()); + if let Some(ty_trait_ref) = cx.tcx.impl_trait_ref(item.owner_id); if let self_ty = ty_trait_ref.subst_identity().self_ty(); if let ty::Adt(adt_def, impl_trait_substs) = self_ty.kind(); then { diff --git a/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs b/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs index 82b1716a216e..7b1d974f2f87 100644 --- a/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs +++ b/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs @@ -244,7 +244,7 @@ impl<'tcx> LateLintPass<'tcx> for OnlyUsedInRecursion { })) => { #[allow(trivial_casts)] if let Some(Node::Item(item)) = get_parent_node(cx.tcx, owner_id.into()) - && let Some(trait_ref) = cx.tcx.bound_impl_trait_ref(item.owner_id.to_def_id()).map(|t| t.subst_identity()) + && let Some(trait_ref) = cx.tcx.impl_trait_ref(item.owner_id).map(|t| t.subst_identity()) && let Some(trait_item_id) = cx.tcx.associated_item(owner_id).trait_item_def_id { ( diff --git a/src/tools/clippy/clippy_lints/src/use_self.rs b/src/tools/clippy/clippy_lints/src/use_self.rs index 9f31a13aa984..6ae9d9d63538 100644 --- a/src/tools/clippy/clippy_lints/src/use_self.rs +++ b/src/tools/clippy/clippy_lints/src/use_self.rs @@ -133,7 +133,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf { ref mut types_to_skip, .. }) = self.stack.last_mut(); - if let Some(impl_trait_ref) = cx.tcx.bound_impl_trait_ref(impl_id.to_def_id()); + if let Some(impl_trait_ref) = cx.tcx.impl_trait_ref(impl_id); then { // `self_ty` is the semantic self type of `impl for `. This cannot be // `Self`. From 6e969ea85eb8f5e504c1a0a06c0a63c515fadf3b Mon Sep 17 00:00:00 2001 From: Kyle Matsuda Date: Wed, 11 Jan 2023 11:32:33 -0700 Subject: [PATCH 081/105] fix various subst_identity vs skip_binder --- compiler/rustc_hir_analysis/src/astconv/mod.rs | 2 +- compiler/rustc_hir_analysis/src/check/check.rs | 2 +- compiler/rustc_hir_analysis/src/coherence/orphan.rs | 2 +- compiler/rustc_hir_analysis/src/coherence/unsafety.rs | 3 ++- compiler/rustc_metadata/src/rmeta/encoder.rs | 6 +++--- compiler/rustc_middle/src/ty/mod.rs | 6 ++++-- compiler/rustc_monomorphize/src/collector.rs | 6 +++--- compiler/rustc_trait_selection/src/traits/coherence.rs | 8 ++++---- .../src/traits/error_reporting/mod.rs | 2 +- .../rustc_trait_selection/src/traits/specialize/mod.rs | 2 +- .../src/traits/specialize/specialization_graph.rs | 9 +++++---- compiler/rustc_ty_utils/src/implied_bounds.rs | 4 ++-- src/librustdoc/passes/collect_intra_doc_links.rs | 2 +- 13 files changed, 29 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 7567a02d1454..8d2cc70c05f1 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -2066,7 +2066,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { }; self.one_bound_for_assoc_type( - || traits::supertraits(tcx, ty::Binder::dummy(trait_ref.skip_binder())), + || traits::supertraits(tcx, ty::Binder::dummy(trait_ref.subst_identity())), || "Self".to_string(), assoc_ident, span, diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 7df19ba6d36b..e58669433e21 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -540,7 +540,7 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) { tcx, it.span, it.owner_id.def_id, - impl_trait_ref.skip_binder(), + impl_trait_ref.subst_identity(), &impl_.items, ); check_on_unimplemented(tcx, it); diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index e8fe92814576..0aadc9f311b0 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs @@ -21,7 +21,7 @@ pub(crate) fn orphan_check_impl( tcx: TyCtxt<'_>, impl_def_id: LocalDefId, ) -> Result<(), ErrorGuaranteed> { - let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().skip_binder(); + let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().subst_identity(); trait_ref.error_reported()?; let ret = do_orphan_check_impl(tcx, trait_ref, impl_def_id); diff --git a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs index c7693cab4741..a485768e37b8 100644 --- a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs +++ b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs @@ -13,7 +13,8 @@ pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) { let item = tcx.hir().expect_item(def_id); let hir::ItemKind::Impl(ref impl_) = item.kind else { bug!() }; - if let Some(trait_ref) = tcx.impl_trait_ref(item.owner_id).map(|t| t.subst_identity()) { + if let Some(trait_ref) = tcx.impl_trait_ref(item.owner_id) { + let trait_ref = trait_ref.subst_identity(); let trait_def = tcx.trait_def(trait_ref.def_id); let unsafe_attr = impl_.generics.params.iter().find(|p| p.pure_wrt_drop).map(|_| "may_dangle"); diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index ba856a11890e..a8000aa3c8a8 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1898,9 +1898,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { for id in tcx.hir().items() { if matches!(tcx.def_kind(id.owner_id), DefKind::Impl) { - if let Some(trait_ref) = - tcx.impl_trait_ref(id.owner_id).map(ty::EarlyBinder::subst_identity) - { + if let Some(trait_ref) = tcx.impl_trait_ref(id.owner_id) { + let trait_ref = trait_ref.subst_identity(); + let simplified_self_ty = fast_reject::simplify_type( self.tcx, trait_ref.self_ty(), diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 7cc4ad4ca46c..e9bd0e9866fd 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2187,8 +2187,10 @@ impl<'tcx> TyCtxt<'tcx> { ) -> Option { // If either trait impl references an error, they're allowed to overlap, // as one of them essentially doesn't exist. - if self.impl_trait_ref(def_id1).map_or(false, |tr| tr.skip_binder().references_error()) - || self.impl_trait_ref(def_id2).map_or(false, |tr| tr.skip_binder().references_error()) + if self.impl_trait_ref(def_id1).map_or(false, |tr| tr.subst_identity().references_error()) + || self + .impl_trait_ref(def_id2) + .map_or(false, |tr| tr.subst_identity().references_error()) { return Some(ImplOverlapKind::Permitted { marker: false }); } diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 3080248d5082..ec1de3056872 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -1351,9 +1351,9 @@ fn create_mono_items_for_default_impls<'tcx>( tcx.def_path_str(item.owner_id.to_def_id()) ); - if let Some(trait_ref) = - tcx.impl_trait_ref(item.owner_id).map(ty::EarlyBinder::subst_identity) - { + if let Some(trait_ref) = tcx.impl_trait_ref(item.owner_id) { + let trait_ref = trait_ref.subst_identity(); + let param_env = ty::ParamEnv::reveal_all(); let trait_ref = tcx.normalize_erasing_regions(param_env, trait_ref); let overridden_methods = tcx.impl_item_implementor_ids(item.owner_id); diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 185810ed3d8e..0edae34190c3 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -77,10 +77,10 @@ pub fn overlapping_impls( // a quick check via fast_reject to tell if the impl headers could possibly // unify. let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::AsInfer }; - let impl1_ref = tcx.impl_trait_ref(impl1_def_id).map(ty::EarlyBinder::subst_identity); - let impl2_ref = tcx.impl_trait_ref(impl2_def_id).map(ty::EarlyBinder::subst_identity); + let impl1_ref = tcx.impl_trait_ref(impl1_def_id); + let impl2_ref = tcx.impl_trait_ref(impl2_def_id); let may_overlap = match (impl1_ref, impl2_ref) { - (Some(a), Some(b)) => iter::zip(a.substs, b.substs) + (Some(a), Some(b)) => iter::zip(a.skip_binder().substs, b.skip_binder().substs) .all(|(arg1, arg2)| drcx.generic_args_may_unify(arg1, arg2)), (None, None) => { let self_ty1 = tcx.type_of(impl1_def_id); @@ -461,7 +461,7 @@ pub fn orphan_check(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Result<(), OrphanChe // We only except this routine to be invoked on implementations // of a trait, not inherent implementations. - let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().skip_binder(); + let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().subst_identity(); debug!("orphan_check: trait_ref={:?}", trait_ref); // If the *trait* is local to the crate, ok. 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 5d2e0bd5afa4..052db2cfe7b9 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1940,7 +1940,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { return None; } - let imp = self.tcx.impl_trait_ref(def_id).unwrap().subst_identity(); + let imp = self.tcx.impl_trait_ref(def_id).unwrap().skip_binder(); self.fuzzy_match_tys(trait_pred.skip_binder().self_ty(), imp.self_ty(), false) .map(|similarity| ImplCandidate { trait_ref: imp, similarity }) diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index 69b671b27bd5..3b796c623c0a 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs @@ -431,7 +431,7 @@ fn report_conflicting_impls<'tcx>( pub(crate) fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Option { use std::fmt::Write; - let trait_ref = tcx.impl_trait_ref(impl_def_id)?.skip_binder(); + let trait_ref = tcx.impl_trait_ref(impl_def_id)?.subst_identity(); let mut w = "impl".to_owned(); let substs = InternalSubsts::identity_for_item(tcx, impl_def_id); diff --git a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs index eb4815122c33..6411206a5a40 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs @@ -48,7 +48,7 @@ trait ChildrenExt<'tcx> { impl<'tcx> ChildrenExt<'tcx> for Children { /// Insert an impl into this set of children without comparing to any existing impls. fn insert_blindly(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) { - let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().subst_identity(); + let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().skip_binder(); if let Some(st) = fast_reject::simplify_type(tcx, trait_ref.self_ty(), TreatParams::AsInfer) { debug!("insert_blindly: impl_def_id={:?} st={:?}", impl_def_id, st); @@ -63,7 +63,7 @@ impl<'tcx> ChildrenExt<'tcx> for Children { /// an impl with a parent. The impl must be present in the list of /// children already. fn remove_existing(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) { - let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().subst_identity(); + let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().skip_binder(); let vec: &mut Vec; if let Some(st) = fast_reject::simplify_type(tcx, trait_ref.self_ty(), TreatParams::AsInfer) { @@ -275,7 +275,8 @@ impl<'tcx> GraphExt<'tcx> for Graph { ) -> Result>, OverlapError<'tcx>> { assert!(impl_def_id.is_local()); - let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().subst_identity(); + // FIXME: use `EarlyBinder` in `self.children` + let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().skip_binder(); let trait_def_id = trait_ref.def_id; debug!( @@ -388,7 +389,7 @@ pub(crate) fn assoc_def( impl_def_id: DefId, assoc_def_id: DefId, ) -> Result { - let trait_def_id = tcx.impl_trait_ref(impl_def_id).unwrap().skip_binder().def_id; + let trait_def_id = tcx.trait_id_of_impl(impl_def_id).unwrap(); let trait_def = tcx.trait_def(trait_def_id); // This function may be called while we are still building the diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs index 7a9c1d8ffe7d..7a24645803c9 100644 --- a/compiler/rustc_ty_utils/src/implied_bounds.rs +++ b/compiler/rustc_ty_utils/src/implied_bounds.rs @@ -22,9 +22,9 @@ fn assumed_wf_types(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::List> { tcx.intern_type_list(&assumed_wf_types) } DefKind::Impl => { - match tcx.impl_trait_ref(def_id).map(ty::EarlyBinder::subst_identity) { + match tcx.impl_trait_ref(def_id) { Some(trait_ref) => { - let types: Vec<_> = trait_ref.substs.types().collect(); + let types: Vec<_> = trait_ref.skip_binder().substs.types().collect(); tcx.intern_type_list(&types) } // Only the impl self type diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 62588040685f..075951312a63 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -786,7 +786,7 @@ fn trait_impls_for<'a>( tcx.find_map_relevant_impl(trait_, ty, |impl_| { let trait_ref = tcx.impl_trait_ref(impl_).expect("this is not an inherent impl"); // Check if these are the same type. - let impl_type = trait_ref.subst_identity().self_ty(); + let impl_type = trait_ref.skip_binder().self_ty(); trace!( "comparing type {} with kind {:?} against type {:?}", impl_type, From 2de9d679adcc2740f490e8f702b2d227be2de30a Mon Sep 17 00:00:00 2001 From: kadmin Date: Tue, 10 Jan 2023 06:08:18 +0000 Subject: [PATCH 082/105] Add note when `FnPtr` vs. `FnDef` impl trait I encountered an instance where an `FnPtr` implemented a trait, but I was passing an `FnDef`. To the end user, there is really no way to differentiate each of them, but it is necessary to cast to the generic function in order to compile. It is thus useful to suggest `as` in the help note, (even if the Fn output implements the trait). --- .../src/traits/error_reporting/mod.rs | 54 +++++++++++++------ tests/ui/traits/fn-trait-cast-diagnostic.rs | 26 +++++++++ .../ui/traits/fn-trait-cast-diagnostic.stderr | 43 +++++++++++++++ tests/ui/traits/issue-99875.stderr | 5 +- 4 files changed, 111 insertions(+), 17 deletions(-) create mode 100644 tests/ui/traits/fn-trait-cast-diagnostic.rs create mode 100644 tests/ui/traits/fn-trait-cast-diagnostic.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 0c7ffb056cc0..41a64a844ce4 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -374,6 +374,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { }) } } + impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { fn report_fulfillment_errors( &self, @@ -852,6 +853,29 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let mut suggested = self.suggest_dereferences(&obligation, &mut err, trait_predicate); suggested |= self.suggest_fn_call(&obligation, &mut err, trait_predicate); + let impl_candidates = self.find_similar_impl_candidates(trait_predicate); + suggested = if let &[cand] = &impl_candidates[..] { + let cand = cand.trait_ref; + if let (ty::FnPtr(_), ty::FnDef(..)) = + (cand.self_ty().kind(), trait_ref.self_ty().skip_binder().kind()) + { + err.span_suggestion( + span.shrink_to_hi(), + format!( + "the trait `{}` is implemented for fn pointer `{}`, try casting using `as`", + cand.print_only_trait_path(), + cand.self_ty(), + ), + format!(" as {}", cand.self_ty()), + Applicability::MaybeIncorrect, + ); + true + } else { + false + } + } else { + false + } || suggested; suggested |= self.suggest_remove_reference(&obligation, &mut err, trait_predicate); suggested |= self.suggest_semicolon_removal( @@ -1968,27 +1992,25 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { candidates.sort(); candidates.dedup(); let len = candidates.len(); - if candidates.len() == 0 { + if candidates.is_empty() { return false; } - if candidates.len() == 1 { - let ty_desc = match candidates[0].self_ty().kind() { - ty::FnPtr(_) => Some("fn pointer"), - _ => None, - }; - let the_desc = match ty_desc { - Some(desc) => format!(" implemented for {} `", desc), - None => " implemented for `".to_string(), - }; + if let &[cand] = &candidates[..] { + let (desc, mention_castable) = + match (cand.self_ty().kind(), trait_ref.self_ty().skip_binder().kind()) { + (ty::FnPtr(_), ty::FnDef(..)) => { + (" implemented for fn pointer `", ", cast using `as`") + } + (ty::FnPtr(_), _) => (" implemented for fn pointer `", ""), + _ => (" implemented for `", ""), + }; err.highlighted_help(vec![ - ( - format!("the trait `{}` ", candidates[0].print_only_trait_path()), - Style::NoStyle, - ), + (format!("the trait `{}` ", cand.print_only_trait_path()), Style::NoStyle), ("is".to_string(), Style::Highlight), - (the_desc, Style::NoStyle), - (candidates[0].self_ty().to_string(), Style::Highlight), + (desc.to_string(), Style::NoStyle), + (cand.self_ty().to_string(), Style::Highlight), ("`".to_string(), Style::NoStyle), + (mention_castable.to_string(), Style::NoStyle), ]); return true; } diff --git a/tests/ui/traits/fn-trait-cast-diagnostic.rs b/tests/ui/traits/fn-trait-cast-diagnostic.rs new file mode 100644 index 000000000000..e20aa210e58b --- /dev/null +++ b/tests/ui/traits/fn-trait-cast-diagnostic.rs @@ -0,0 +1,26 @@ +// There are two different instances to check that even if +// the trait is implemented for the output of a function, +// it will still be displayed if the function itself implements a trait. +trait Foo {} + +impl Foo for fn() -> bool {} +impl Foo for bool {} + +fn example() -> bool { + true +} + +trait NoOtherFoo {} + +impl NoOtherFoo for fn() -> bool {} + +fn do_on_foo(v: impl Foo) {} +fn do_on_single_foo(v: impl NoOtherFoo) {} + +fn main() { + do_on_foo(example); + //~^ ERROR the trait bound + + do_on_single_foo(example); + //~^ ERROR the trait bound +} diff --git a/tests/ui/traits/fn-trait-cast-diagnostic.stderr b/tests/ui/traits/fn-trait-cast-diagnostic.stderr new file mode 100644 index 000000000000..6851dcdd504d --- /dev/null +++ b/tests/ui/traits/fn-trait-cast-diagnostic.stderr @@ -0,0 +1,43 @@ +error[E0277]: the trait bound `fn() -> bool {example}: Foo` is not satisfied + --> $DIR/fn-trait-cast-diagnostic.rs:21:15 + | +LL | do_on_foo(example); + | --------- ^^^^^^^ the trait `Foo` is not implemented for fn item `fn() -> bool {example}` + | | + | required by a bound introduced by this call + | +note: required by a bound in `do_on_foo` + --> $DIR/fn-trait-cast-diagnostic.rs:17:22 + | +LL | fn do_on_foo(v: impl Foo) {} + | ^^^ required by this bound in `do_on_foo` +help: use parentheses to call this function + | +LL | do_on_foo(example()); + | ++ +help: the trait `Foo` is implemented for fn pointer `fn() -> bool`, try casting using `as` + | +LL | do_on_foo(example as fn() -> bool); + | +++++++++++++++ + +error[E0277]: the trait bound `fn() -> bool {example}: NoOtherFoo` is not satisfied + --> $DIR/fn-trait-cast-diagnostic.rs:24:22 + | +LL | do_on_single_foo(example); + | ---------------- ^^^^^^^ the trait `NoOtherFoo` is not implemented for fn item `fn() -> bool {example}` + | | + | required by a bound introduced by this call + | +note: required by a bound in `do_on_single_foo` + --> $DIR/fn-trait-cast-diagnostic.rs:18:29 + | +LL | fn do_on_single_foo(v: impl NoOtherFoo) {} + | ^^^^^^^^^^ required by this bound in `do_on_single_foo` +help: the trait `NoOtherFoo` is implemented for fn pointer `fn() -> bool`, try casting using `as` + | +LL | do_on_single_foo(example as fn() -> bool); + | +++++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/issue-99875.stderr b/tests/ui/traits/issue-99875.stderr index 3ff8f12f1b8c..fb6eebbd254a 100644 --- a/tests/ui/traits/issue-99875.stderr +++ b/tests/ui/traits/issue-99875.stderr @@ -6,12 +6,15 @@ LL | takes(function); | | | required by a bound introduced by this call | - = help: the trait `Trait` is implemented for fn pointer `fn(Argument) -> Return` note: required by a bound in `takes` --> $DIR/issue-99875.rs:9:18 | LL | fn takes(_: impl Trait) {} | ^^^^^ required by this bound in `takes` +help: the trait `Trait` is implemented for fn pointer `fn(Argument) -> Return`, try casting using `as` + | +LL | takes(function as fn(Argument) -> Return); + | +++++++++++++++++++++++++ error[E0277]: the trait bound `[closure@$DIR/issue-99875.rs:14:11: 14:34]: Trait` is not satisfied --> $DIR/issue-99875.rs:14:11 From ecb1ad11d9df883f4070695276c0714c148c751b Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Sat, 14 Jan 2023 11:28:14 +0000 Subject: [PATCH 083/105] Make `LhsExpr::AlreadyParsed` a named struct --- compiler/rustc_parse/src/parser/expr.rs | 8 ++++---- compiler/rustc_parse/src/parser/stmt.rs | 10 ++++++++-- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index dd2b03988c3e..24821f1bd97c 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -83,7 +83,7 @@ macro_rules! maybe_whole_expr { pub(super) enum LhsExpr { NotYetParsed, AttributesParsed(AttrWrapper), - AlreadyParsed(P, bool), // (expr, starts_statement) + AlreadyParsed { expr: P, starts_statement: bool }, } impl From> for LhsExpr { @@ -97,11 +97,11 @@ impl From> for LhsExpr { } impl From> for LhsExpr { - /// Converts the `expr: P` into `LhsExpr::AlreadyParsed(expr)`. + /// Converts the `expr: P` into `LhsExpr::AlreadyParsed { expr, starts_statement: false }`. /// /// This conversion does not allocate. fn from(expr: P) -> Self { - LhsExpr::AlreadyParsed(expr, false) + LhsExpr::AlreadyParsed { expr, starts_statement: false } } } @@ -174,7 +174,7 @@ impl<'a> Parser<'a> { lhs: LhsExpr, ) -> PResult<'a, P> { let mut starts_stmt = false; - let mut lhs = if let LhsExpr::AlreadyParsed(expr, starts_statement) = lhs { + let mut lhs = if let LhsExpr::AlreadyParsed { expr, starts_statement } = lhs { starts_stmt = starts_statement; expr } else { diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 1e5c28349603..4ff9927aab51 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -164,7 +164,10 @@ impl<'a> Parser<'a> { // Perform this outside of the `collect_tokens_trailing_token` closure, // since our outer attributes do not apply to this part of the expression let expr = self.with_res(Restrictions::STMT_EXPR, |this| { - this.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(expr, true)) + this.parse_assoc_expr_with( + 0, + LhsExpr::AlreadyParsed { expr, starts_statement: true }, + ) })?; Ok(self.mk_stmt(lo.to(self.prev_token.span), StmtKind::Expr(expr))) } else { @@ -198,7 +201,10 @@ impl<'a> Parser<'a> { let e = self.mk_expr(lo.to(hi), ExprKind::MacCall(mac)); let e = self.maybe_recover_from_bad_qpath(e)?; let e = self.parse_dot_or_call_expr_with(e, lo, attrs)?; - let e = self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e, false))?; + let e = self.parse_assoc_expr_with( + 0, + LhsExpr::AlreadyParsed { expr: e, starts_statement: false }, + )?; StmtKind::Expr(e) }; Ok(self.mk_stmt(lo.to(hi), kind)) From f7850c5368de4d477b6484ecee2c3eedb9ba997e Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Sat, 14 Jan 2023 11:29:22 +0000 Subject: [PATCH 084/105] Improve comments in `parser/expr.rs` --- compiler/rustc_parse/src/parser/expr.rs | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 24821f1bd97c..645f86339410 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -562,17 +562,23 @@ impl<'a> Parser<'a> { // Note: when adding new unary operators, don't forget to adjust TokenKind::can_begin_expr() match this.token.uninterpolate().kind { - token::Not => make_it!(this, attrs, |this, _| this.parse_unary_expr(lo, UnOp::Not)), // `!expr` - token::Tilde => make_it!(this, attrs, |this, _| this.recover_tilde_expr(lo)), // `~expr` + // `!expr` + token::Not => make_it!(this, attrs, |this, _| this.parse_unary_expr(lo, UnOp::Not)), + // `~expr` + token::Tilde => make_it!(this, attrs, |this, _| this.recover_tilde_expr(lo)), + // `-expr` token::BinOp(token::Minus) => { make_it!(this, attrs, |this, _| this.parse_unary_expr(lo, UnOp::Neg)) - } // `-expr` + } + // `*expr` token::BinOp(token::Star) => { make_it!(this, attrs, |this, _| this.parse_unary_expr(lo, UnOp::Deref)) - } // `*expr` + } + // `&expr` and `&&expr` token::BinOp(token::And) | token::AndAnd => { make_it!(this, attrs, |this, _| this.parse_borrow_expr(lo)) } + // `+lit` token::BinOp(token::Plus) if this.look_ahead(1, |tok| tok.is_numeric_lit()) => { let mut err = LeadingPlusNotSupported { span: lo, remove_plus: None, add_parentheses: None }; @@ -587,7 +593,7 @@ impl<'a> Parser<'a> { this.bump(); this.parse_prefix_expr(None) - } // `+expr` + } // Recover from `++x`: token::BinOp(token::Plus) if this.look_ahead(1, |t| *t == token::BinOp(token::Plus)) => @@ -624,7 +630,7 @@ impl<'a> Parser<'a> { Ok((span, self.mk_unary(op, expr))) } - // Recover on `!` suggesting for bitwise negation instead. + /// Recover on `~expr` in favor of `!expr`. fn recover_tilde_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> { self.sess.emit_err(TildeAsUnaryOperator(lo)); @@ -651,7 +657,6 @@ impl<'a> Parser<'a> { /// Recover on `not expr` in favor of `!expr`. fn recover_not_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> { - // Emit the error... let negated_token = self.look_ahead(1, |t| t.clone()); let sub_diag = if negated_token.is_numeric_lit() { @@ -672,7 +677,6 @@ impl<'a> Parser<'a> { ), }); - // ...and recover! self.parse_unary_expr(lo, UnOp::Not) } @@ -1593,7 +1597,7 @@ impl<'a> Parser<'a> { vis.0 }; - // Suggestion involves adding a (as of time of writing this, unstable) labeled block. + // Suggestion involves adding a labeled block. // // If there are no breaks that may use this label, suggest removing the label and // recover to the unmodified expression. From ea13023b367d56ac3a8fcb72c9bbe636cf9ae1e7 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Sat, 14 Jan 2023 11:44:25 +0000 Subject: [PATCH 085/105] Allocate one less vec in `parser/expr.rs` --- compiler/rustc_parse/src/parser/expr.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index dd2b03988c3e..9995b2148617 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1471,9 +1471,8 @@ impl<'a> Parser<'a> { } else if self.eat(&token::Comma) { // Vector with two or more elements. let sep = SeqSep::trailing_allowed(token::Comma); - let (remaining_exprs, _) = self.parse_seq_to_end(close, sep, |p| p.parse_expr())?; - let mut exprs = vec![first_expr]; - exprs.extend(remaining_exprs); + let (mut exprs, _) = self.parse_seq_to_end(close, sep, |p| p.parse_expr())?; + exprs.insert(0, first_expr); ExprKind::Array(exprs) } else { // Vector with one element From dd96a44c7d69c60322161f19123bba9823e4ac8a Mon Sep 17 00:00:00 2001 From: Boxy Date: Sat, 14 Jan 2023 11:44:37 +0000 Subject: [PATCH 086/105] a --- triagebot.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/triagebot.toml b/triagebot.toml index 914b52cf041d..14bade6472fa 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -251,7 +251,7 @@ new_pr = true [autolabel."WG-trait-system-refactor"] trigger_files = [ - "compiler/rustc_trait_selection/solve" + "compiler/rustc_trait_selection/src/solve" ] [notify-zulip."I-prioritize"] From 1caec6fa1d09739f70b1f54766141cf204696503 Mon Sep 17 00:00:00 2001 From: Ethan Brierley Date: Fri, 23 Dec 2022 00:13:47 +0000 Subject: [PATCH 087/105] fix: misleading add `dyn` to derive macro suggestion --- .../rustc_hir_analysis/src/astconv/mod.rs | 8 ++++- tests/ui/traits/issue-106072.rs | 5 ++++ tests/ui/traits/issue-106072.stderr | 30 +++++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 tests/ui/traits/issue-106072.rs create mode 100644 tests/ui/traits/issue-106072.stderr diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 3521911b0552..398dd18f5121 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -3307,7 +3307,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let label = "add `dyn` keyword before this trait"; let mut diag = rustc_errors::struct_span_err!(tcx.sess, self_ty.span, E0782, "{}", msg); - diag.multipart_suggestion_verbose(label, sugg, Applicability::MachineApplicable); + if self_ty.span.can_be_used_for_suggestions() { + diag.multipart_suggestion_verbose( + label, + sugg, + Applicability::MachineApplicable, + ); + } // check if the impl trait that we are considering is a impl of a local trait self.maybe_lint_blanket_trait_impl(&self_ty, &mut diag); diag.emit(); diff --git a/tests/ui/traits/issue-106072.rs b/tests/ui/traits/issue-106072.rs new file mode 100644 index 000000000000..7064a39d21e7 --- /dev/null +++ b/tests/ui/traits/issue-106072.rs @@ -0,0 +1,5 @@ +#[derive(Clone)] //~ trait objects must include the `dyn` keyword + //~| trait objects must include the `dyn` keyword +struct Foo; +trait Foo {} //~ the name `Foo` is defined multiple times +fn main() {} diff --git a/tests/ui/traits/issue-106072.stderr b/tests/ui/traits/issue-106072.stderr new file mode 100644 index 000000000000..f9b7b814663f --- /dev/null +++ b/tests/ui/traits/issue-106072.stderr @@ -0,0 +1,30 @@ +error[E0428]: the name `Foo` is defined multiple times + --> $DIR/issue-106072.rs:4:1 + | +LL | struct Foo; + | ----------- previous definition of the type `Foo` here +LL | trait Foo {} + | ^^^^^^^^^ `Foo` redefined here + | + = note: `Foo` must be defined only once in the type namespace of this module + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/issue-106072.rs:1:10 + | +LL | #[derive(Clone)] + | ^^^^^ + | + = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/issue-106072.rs:1:10 + | +LL | #[derive(Clone)] + | ^^^^^ + | + = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0428, E0782. +For more information about an error, try `rustc --explain E0428`. From 6821adb65145463ffe51e044cbe37ea823059222 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Fri, 13 Jan 2023 01:27:58 +0100 Subject: [PATCH 088/105] Deprioritize fulfillment errors that come from expansions. --- .../src/traits/error_reporting/mod.rs | 8 +++++--- .../cannot-infer-partial-try-return.stderr | 2 -- .../inference/question-mark-type-infer.stderr | 9 +++++++-- tests/ui/issues/issue-69455.stderr | 18 ++++++++++-------- .../cannot_infer_local_or_vec_in_tuples.stderr | 2 +- 5 files changed, 23 insertions(+), 16 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 0c7ffb056cc0..c75842d18c62 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -453,9 +453,11 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } } - for (error, suppressed) in iter::zip(errors, is_suppressed) { - if !suppressed { - self.report_fulfillment_error(error, body_id); + for from_expansion in [false, true] { + for (error, suppressed) in iter::zip(errors, &is_suppressed) { + if !suppressed && error.obligation.cause.span.from_expansion() == from_expansion { + self.report_fulfillment_error(error, body_id); + } } } diff --git a/tests/ui/inference/cannot-infer-partial-try-return.stderr b/tests/ui/inference/cannot-infer-partial-try-return.stderr index 2a56aaa44fef..888c321bc479 100644 --- a/tests/ui/inference/cannot-infer-partial-try-return.stderr +++ b/tests/ui/inference/cannot-infer-partial-try-return.stderr @@ -1,8 +1,6 @@ error[E0282]: type annotations needed --> $DIR/cannot-infer-partial-try-return.rs:20:9 | -LL | infallible()?; - | ------------- type must be known at this point LL | Ok(()) | ^^ cannot infer type of the type parameter `E` declared on the enum `Result` | diff --git a/tests/ui/inference/question-mark-type-infer.stderr b/tests/ui/inference/question-mark-type-infer.stderr index 9b822714f828..a9cb7e5257c8 100644 --- a/tests/ui/inference/question-mark-type-infer.stderr +++ b/tests/ui/inference/question-mark-type-infer.stderr @@ -1,8 +1,13 @@ error[E0282]: type annotations needed - --> $DIR/question-mark-type-infer.rs:10:30 + --> $DIR/question-mark-type-infer.rs:10:21 | LL | l.iter().map(f).collect()? - | ^ cannot infer type + | ^^^^^^^ cannot infer type of the type parameter `B` declared on the associated function `collect` + | +help: consider specifying the generic argument + | +LL | l.iter().map(f).collect::>()? + | ++++++++++ error: aborting due to previous error diff --git a/tests/ui/issues/issue-69455.stderr b/tests/ui/issues/issue-69455.stderr index 9d11cf19ea77..fc343bb54aac 100644 --- a/tests/ui/issues/issue-69455.stderr +++ b/tests/ui/issues/issue-69455.stderr @@ -1,14 +1,16 @@ -error[E0282]: type annotations needed - --> $DIR/issue-69455.rs:29:20 +error[E0284]: type annotations needed + --> $DIR/issue-69455.rs:29:41 | LL | println!("{}", 23u64.test(xs.iter().sum())); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the associated function `new_display` + | ---- ^^^ cannot infer type of the type parameter `S` declared on the associated function `sum` + | | + | type must be known at this point | - = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: cannot satisfy `>::Output == _` help: consider specifying the generic argument | -LL | println!("{}", 23u64.test(xs.iter().sum())::); - | +++++ +LL | println!("{}", 23u64.test(xs.iter().sum::())); + | +++++ error[E0283]: type annotations needed --> $DIR/issue-69455.rs:29:41 @@ -33,5 +35,5 @@ LL | println!("{}", 23u64.test(xs.iter().sum::())); error: aborting due to 2 previous errors -Some errors have detailed explanations: E0282, E0283. -For more information about an error, try `rustc --explain E0282`. +Some errors have detailed explanations: E0283, E0284. +For more information about an error, try `rustc --explain E0283`. diff --git a/tests/ui/type/type-check/cannot_infer_local_or_vec_in_tuples.stderr b/tests/ui/type/type-check/cannot_infer_local_or_vec_in_tuples.stderr index be60cda68b9f..e544b3695154 100644 --- a/tests/ui/type/type-check/cannot_infer_local_or_vec_in_tuples.stderr +++ b/tests/ui/type/type-check/cannot_infer_local_or_vec_in_tuples.stderr @@ -2,7 +2,7 @@ error[E0282]: type annotations needed for `(Vec,)` --> $DIR/cannot_infer_local_or_vec_in_tuples.rs:2:9 | LL | let (x, ) = (vec![], ); - | ^^^^^ + | ^^^^^ ---------- type must be known at this point | help: consider giving this pattern a type, where the type for type parameter `T` is specified | From 4f64de83bc5731946c9acdd4f572e24bfbaef4b9 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Sat, 7 Jan 2023 15:41:32 +0000 Subject: [PATCH 089/105] Fix `unused_braces` on generic const expr macro call --- compiler/rustc_lint/src/unused.rs | 1 + tests/ui/const-generics/unused_braces.fixed | 7 +++++++ tests/ui/const-generics/unused_braces.rs | 7 +++++++ tests/ui/const-generics/unused_braces.stderr | 2 +- 4 files changed, 16 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index ac2b32b44e6a..f2ee9ab1a198 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -1105,6 +1105,7 @@ impl UnusedDelimLint for UnusedBraces { || matches!(expr.kind, ast::ExprKind::Lit(_))) && !cx.sess().source_map().is_multiline(value.span) && value.attrs.is_empty() + && !expr.span.from_expansion() && !value.span.from_expansion() && !inner.span.from_expansion() { diff --git a/tests/ui/const-generics/unused_braces.fixed b/tests/ui/const-generics/unused_braces.fixed index d080c210e6bd..4c1926387b92 100644 --- a/tests/ui/const-generics/unused_braces.fixed +++ b/tests/ui/const-generics/unused_braces.fixed @@ -2,10 +2,17 @@ // run-rustfix #![warn(unused_braces)] +macro_rules! make_1 { + () => { + 1 + } +} + struct A; fn main() { let _: A<7>; // ok let _: A<7>; //~ WARN unnecessary braces let _: A<{ 3 + 5 }>; // ok + let _: A<{make_1!()}>; // ok } diff --git a/tests/ui/const-generics/unused_braces.rs b/tests/ui/const-generics/unused_braces.rs index 47f0f8c1c96c..e9f15b401807 100644 --- a/tests/ui/const-generics/unused_braces.rs +++ b/tests/ui/const-generics/unused_braces.rs @@ -2,10 +2,17 @@ // run-rustfix #![warn(unused_braces)] +macro_rules! make_1 { + () => { + 1 + } +} + struct A; fn main() { let _: A<7>; // ok let _: A<{ 7 }>; //~ WARN unnecessary braces let _: A<{ 3 + 5 }>; // ok + let _: A<{make_1!()}>; // ok } diff --git a/tests/ui/const-generics/unused_braces.stderr b/tests/ui/const-generics/unused_braces.stderr index 553a3a0f88eb..2c8031c43002 100644 --- a/tests/ui/const-generics/unused_braces.stderr +++ b/tests/ui/const-generics/unused_braces.stderr @@ -1,5 +1,5 @@ warning: unnecessary braces around const expression - --> $DIR/unused_braces.rs:9:14 + --> $DIR/unused_braces.rs:15:14 | LL | let _: A<{ 7 }>; | ^^ ^^ From 0b35f448f8e9f39ed6fc1c494eeb331afba513bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Vennberg?= Date: Sat, 14 Jan 2023 16:33:11 +0100 Subject: [PATCH 090/105] Remove various double spaces in source comments. --- library/alloc/src/alloc.rs | 4 ++-- library/alloc/src/rc.rs | 2 +- library/alloc/src/sync.rs | 8 ++++---- library/alloc/src/vec/into_iter.rs | 6 +++--- library/alloc/src/vec/is_zero.rs | 2 +- library/alloc/src/vec/mod.rs | 4 ++-- library/alloc/tests/vec.rs | 2 +- library/core/src/array/iter.rs | 6 +++--- library/core/src/iter/range.rs | 2 +- library/core/src/num/int_macros.rs | 4 ++-- library/core/src/ptr/mod.rs | 2 +- library/core/src/slice/iter.rs | 4 ++-- library/core/src/slice/iter/macros.rs | 2 +- library/core/src/slice/mod.rs | 4 ++-- library/core/src/slice/sort.rs | 6 +++--- library/core/tests/slice.rs | 2 +- library/std/src/io/buffered/tests.rs | 4 ++-- library/std/src/os/fd/owned.rs | 2 +- library/std/src/panicking.rs | 4 ++-- library/std/src/path.rs | 2 +- library/std/src/sys/itron/thread.rs | 2 +- library/std/src/sys/unix/fs.rs | 4 ++-- library/std/src/sys/unix/kernel_copy.rs | 2 +- .../std/src/sys/unix/process/process_fuchsia.rs | 10 +++++----- library/std/src/sys/unix/process/process_unix.rs | 6 +++--- .../src/sys/unix/process/process_unix/tests.rs | 6 +++--- .../std/src/sys/unix/process/process_vxworks.rs | 6 +++--- library/std/src/sys/unix/thread.rs | 16 ++++++++-------- library/std/src/sys/windows/os.rs | 2 +- library/std/src/sys/windows/thread.rs | 2 +- library/test/src/lib.rs | 2 +- library/test/src/term/terminfo/searcher.rs | 2 +- 32 files changed, 66 insertions(+), 66 deletions(-) diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index fe6de1cf879b..3a797bd5ecaa 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -20,7 +20,7 @@ use core::marker::Destruct; mod tests; extern "Rust" { - // These are the magic symbols to call the global allocator. rustc generates + // These are the magic symbols to call the global allocator. rustc generates // them to call `__rg_alloc` etc. if there is a `#[global_allocator]` attribute // (the code expanding that attribute macro generates those functions), or to call // the default implementations in std (`__rdl_alloc` etc. in `library/std/src/alloc.rs`) @@ -353,7 +353,7 @@ pub(crate) const unsafe fn box_free !; diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index c1d853ed6521..c9aa23fc4af1 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -2179,7 +2179,7 @@ pub struct Weak { // This is a `NonNull` to allow optimizing the size of this type in enums, // but it is not necessarily a valid pointer. // `Weak::new` sets this to `usize::MAX` so that it doesn’t need - // to allocate space on the heap. That's not a value a real pointer + // to allocate space on the heap. That's not a value a real pointer // will ever have because RcBox has alignment at least 2. // This is only possible when `T: Sized`; unsized `T` never dangle. ptr: NonNull>, diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index d833d4d1dfbd..bab7f5f53657 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -295,7 +295,7 @@ pub struct Weak { // This is a `NonNull` to allow optimizing the size of this type in enums, // but it is not necessarily a valid pointer. // `Weak::new` sets this to `usize::MAX` so that it doesn’t need - // to allocate space on the heap. That's not a value a real pointer + // to allocate space on the heap. That's not a value a real pointer // will ever have because RcBox has alignment at least 2. // This is only possible when `T: Sized`; unsized `T` never dangle. ptr: NonNull>, @@ -1656,7 +1656,7 @@ impl Arc { // // The acquire label here ensures a happens-before relationship with any // writes to `strong` (in particular in `Weak::upgrade`) prior to decrements - // of the `weak` count (via `Weak::drop`, which uses release). If the upgraded + // of the `weak` count (via `Weak::drop`, which uses release). If the upgraded // weak ref was never dropped, the CAS here will fail so we do not care to synchronize. if self.inner().weak.compare_exchange(1, usize::MAX, Acquire, Relaxed).is_ok() { // This needs to be an `Acquire` to synchronize with the decrement of the `strong` @@ -1712,7 +1712,7 @@ unsafe impl<#[may_dangle] T: ?Sized> Drop for Arc { } // This fence is needed to prevent reordering of use of the data and - // deletion of the data. Because it is marked `Release`, the decreasing + // deletion of the data. Because it is marked `Release`, the decreasing // of the reference count synchronizes with this `Acquire` fence. This // means that use of the data happens before decreasing the reference // count, which happens before this fence, which happens before the @@ -2172,7 +2172,7 @@ impl Clone for Weak { } else { return Weak { ptr: self.ptr }; }; - // See comments in Arc::clone() for why this is relaxed. This can use a + // See comments in Arc::clone() for why this is relaxed. This can use a // fetch_add (ignoring the lock) because the weak count is only locked // where are *no other* weak pointers in existence. (So we can't be // running this code in that case). diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs index b207b3210f1a..37966007eb7e 100644 --- a/library/alloc/src/vec/into_iter.rs +++ b/library/alloc/src/vec/into_iter.rs @@ -40,7 +40,7 @@ pub struct IntoIter< // to avoid dropping the allocator twice we need to wrap it into ManuallyDrop pub(super) alloc: ManuallyDrop
, pub(super) ptr: *const T, - pub(super) end: *const T, // If T is a ZST, this is actually ptr+len. This encoding is picked so that + pub(super) end: *const T, // If T is a ZST, this is actually ptr+len. This encoding is picked so that // ptr == end is a quick test for the Iterator being empty, that works // for both ZST and non-ZST. } @@ -146,9 +146,9 @@ impl IntoIter { let mut this = ManuallyDrop::new(self); // SAFETY: This allocation originally came from a `Vec`, so it passes - // all those checks. We have `this.buf` ≤ `this.ptr` ≤ `this.end`, + // all those checks. We have `this.buf` ≤ `this.ptr` ≤ `this.end`, // so the `sub_ptr`s below cannot wrap, and will produce a well-formed - // range. `end` ≤ `buf + cap`, so the range will be in-bounds. + // range. `end` ≤ `buf + cap`, so the range will be in-bounds. // Taking `alloc` is ok because nothing else is going to look at it, // since our `Drop` impl isn't going to run so there's no more code. unsafe { diff --git a/library/alloc/src/vec/is_zero.rs b/library/alloc/src/vec/is_zero.rs index 8e652d676dc0..26120270c0cb 100644 --- a/library/alloc/src/vec/is_zero.rs +++ b/library/alloc/src/vec/is_zero.rs @@ -57,7 +57,7 @@ unsafe impl IsZero for [T; N] { #[inline] fn is_zero(&self) -> bool { // Because this is generated as a runtime check, it's not obvious that - // it's worth doing if the array is really long. The threshold here + // it's worth doing if the array is really long. The threshold here // is largely arbitrary, but was picked because as of 2022-07-01 LLVM // fails to const-fold the check in `vec![[1; 32]; n]` // See https://github.com/rust-lang/rust/pull/97581#issuecomment-1166628022 diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 36cfac8ee9e1..36b0b3c9e7cc 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -2429,7 +2429,7 @@ impl Vec { self.reserve(range.len()); // SAFETY: - // - `slice::range` guarantees that the given range is valid for indexing self + // - `slice::range` guarantees that the given range is valid for indexing self unsafe { self.spec_extend_from_within(range); } @@ -2686,7 +2686,7 @@ impl Clone for Vec { // HACK(japaric): with cfg(test) the inherent `[T]::to_vec` method, which is // required for this method definition, is not available. Instead use the - // `slice::to_vec` function which is only available with cfg(test) + // `slice::to_vec` function which is only available with cfg(test) // NB see the slice::hack module in slice.rs for more information #[cfg(test)] fn clone(&self) -> Self { diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs index 87adcead8f62..2f07c2911a50 100644 --- a/library/alloc/tests/vec.rs +++ b/library/alloc/tests/vec.rs @@ -1849,7 +1849,7 @@ fn test_stable_pointers() { } // Test that, if we reserved enough space, adding and removing elements does not - // invalidate references into the vector (such as `v0`). This test also + // invalidate references into the vector (such as `v0`). This test also // runs in Miri, which would detect such problems. // Note that this test does *not* constitute a stable guarantee that all these functions do not // reallocate! Only what is explicitly documented at diff --git a/library/core/src/array/iter.rs b/library/core/src/array/iter.rs index b91c630183d4..8259c087d22e 100644 --- a/library/core/src/array/iter.rs +++ b/library/core/src/array/iter.rs @@ -109,8 +109,8 @@ impl IntoIter { /// use std::array::IntoIter; /// use std::mem::MaybeUninit; /// - /// # // Hi! Thanks for reading the code. This is restricted to `Copy` because - /// # // otherwise it could leak. A fully-general version this would need a drop + /// # // Hi! Thanks for reading the code. This is restricted to `Copy` because + /// # // otherwise it could leak. A fully-general version this would need a drop /// # // guard to handle panics from the iterator, but this works for an example. /// fn next_chunk( /// it: &mut impl Iterator, @@ -211,7 +211,7 @@ impl IntoIter { let initialized = 0..0; // SAFETY: We're telling it that none of the elements are initialized, - // which is trivially true. And ∀N: usize, 0 <= N. + // which is trivially true. And ∀N: usize, 0 <= N. unsafe { Self::new_unchecked(buffer, initialized) } } diff --git a/library/core/src/iter/range.rs b/library/core/src/iter/range.rs index ac7b389b15b4..b5739f2f3c0b 100644 --- a/library/core/src/iter/range.rs +++ b/library/core/src/iter/range.rs @@ -756,7 +756,7 @@ impl Iterator for ops::Range { where Self: TrustedRandomAccessNoCoerce, { - // SAFETY: The TrustedRandomAccess contract requires that callers only pass an index + // SAFETY: The TrustedRandomAccess contract requires that callers only pass an index // that is in bounds. // Additionally Self: TrustedRandomAccess is only implemented for Copy types // which means even repeated reads of the same index would be safe. diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 21518a3f5518..7071a656d613 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -1538,7 +1538,7 @@ macro_rules! int_impl { /// /// ``` /// #![feature(bigint_helper_methods)] - /// // Only the most significant word is signed. + /// // Only the most significant word is signed. /// // #[doc = concat!("// 10 MAX (a = 10 × 2^", stringify!($BITS), " + 2^", stringify!($BITS), " - 1)")] #[doc = concat!("// + -5 9 (b = -5 × 2^", stringify!($BITS), " + 9)")] @@ -1646,7 +1646,7 @@ macro_rules! int_impl { /// /// ``` /// #![feature(bigint_helper_methods)] - /// // Only the most significant word is signed. + /// // Only the most significant word is signed. /// // #[doc = concat!("// 6 8 (a = 6 × 2^", stringify!($BITS), " + 8)")] #[doc = concat!("// - -5 9 (b = -5 × 2^", stringify!($BITS), " + 9)")] diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 5f30029eaa07..1ad9af1549a4 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -1701,7 +1701,7 @@ pub(crate) const unsafe fn align_offset(p: *const T, a: usize) -> usiz // offset is not a multiple of `stride`, the input pointer was misaligned and no pointer // offset will be able to produce a `p` aligned to the specified `a`. // - // The naive `-p (mod a)` equation inhibits LLVM's ability to select instructions + // The naive `-p (mod a)` equation inhibits LLVM's ability to select instructions // like `lea`. We compute `(round_up_to_next_alignment(p, a) - p)` instead. This // redistributes operations around the load-bearing, but pessimizing `and` instruction // sufficiently for LLVM to be able to utilize the various optimizations it knows about. diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs index 06228976719f..c3e7f2eb302c 100644 --- a/library/core/src/slice/iter.rs +++ b/library/core/src/slice/iter.rs @@ -65,7 +65,7 @@ fn size_from_ptr(_: *const T) -> usize { #[must_use = "iterators are lazy and do nothing unless consumed"] pub struct Iter<'a, T: 'a> { ptr: NonNull, - end: *const T, // If T is a ZST, this is actually ptr+len. This encoding is picked so that + end: *const T, // If T is a ZST, this is actually ptr+len. This encoding is picked so that // ptr == end is a quick test for the Iterator being empty, that works // for both ZST and non-ZST. _marker: PhantomData<&'a T>, @@ -186,7 +186,7 @@ impl AsRef<[T]> for Iter<'_, T> { #[must_use = "iterators are lazy and do nothing unless consumed"] pub struct IterMut<'a, T: 'a> { ptr: NonNull, - end: *mut T, // If T is a ZST, this is actually ptr+len. This encoding is picked so that + end: *mut T, // If T is a ZST, this is actually ptr+len. This encoding is picked so that // ptr == end is a quick test for the Iterator being empty, that works // for both ZST and non-ZST. _marker: PhantomData<&'a mut T>, diff --git a/library/core/src/slice/iter/macros.rs b/library/core/src/slice/iter/macros.rs index ce51d48e3e55..55af4cb61dcc 100644 --- a/library/core/src/slice/iter/macros.rs +++ b/library/core/src/slice/iter/macros.rs @@ -23,7 +23,7 @@ macro_rules! len { $self.end.addr().wrapping_sub(start.as_ptr().addr()) } else { // We know that `start <= end`, so can do better than `offset_from`, - // which needs to deal in signed. By setting appropriate flags here + // which needs to deal in signed. By setting appropriate flags here // we can tell LLVM this, which helps it remove bounds checks. // SAFETY: By the type invariant, `start <= end` let diff = unsafe { unchecked_sub($self.end.addr(), start.as_ptr().addr()) }; diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 2995cf0c6443..caca2d0031d3 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -703,7 +703,7 @@ impl [T] { // Because this function is first compiled in isolation, // this check tells LLVM that the indexing below is - // in-bounds. Then after inlining -- once the actual + // in-bounds. Then after inlining -- once the actual // lengths of the slices are known -- it's removed. let (a, b) = (&mut a[..n], &mut b[..n]); @@ -2476,7 +2476,7 @@ impl [T] { let mid = left + size / 2; // SAFETY: the while condition means `size` is strictly positive, so - // `size/2 < size`. Thus `left + size/2 < left + size`, which + // `size/2 < size`. Thus `left + size/2 < left + size`, which // coupled with the `left + size <= self.len()` invariant means // we have `left + size/2 < self.len()`, and this is in-bounds. let cmp = f(unsafe { self.get_unchecked(mid) }); diff --git a/library/core/src/slice/sort.rs b/library/core/src/slice/sort.rs index b8c0c3fd9493..4d2fcd917849 100644 --- a/library/core/src/slice/sort.rs +++ b/library/core/src/slice/sort.rs @@ -18,9 +18,9 @@ struct CopyOnDrop { impl Drop for CopyOnDrop { fn drop(&mut self) { - // SAFETY: This is a helper class. - // Please refer to its usage for correctness. - // Namely, one must be sure that `src` and `dst` does not overlap as required by `ptr::copy_nonoverlapping`. + // SAFETY: This is a helper class. + // Please refer to its usage for correctness. + // Namely, one must be sure that `src` and `dst` does not overlap as required by `ptr::copy_nonoverlapping`. unsafe { ptr::copy_nonoverlapping(self.src, self.dest, 1); } diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs index fd35d96c3fef..39559cdbb5ea 100644 --- a/library/core/tests/slice.rs +++ b/library/core/tests/slice.rs @@ -1488,7 +1488,7 @@ mod slice_index { // optional: // // one or more similar inputs for which data[input] succeeds, - // and the corresponding output as an array. This helps validate + // and the corresponding output as an array. This helps validate // "critical points" where an input range straddles the boundary // between valid and invalid. // (such as the input `len..len`, which is just barely valid) diff --git a/library/std/src/io/buffered/tests.rs b/library/std/src/io/buffered/tests.rs index f4e688eb926c..4c1b7d57684d 100644 --- a/library/std/src/io/buffered/tests.rs +++ b/library/std/src/io/buffered/tests.rs @@ -288,8 +288,8 @@ fn test_buffered_reader_seek_underflow_discard_buffer_between_seeks() { let mut reader = BufReader::with_capacity(5, ErrAfterFirstSeekReader { first_seek: true }); assert_eq!(reader.fill_buf().ok(), Some(&[0, 0, 0, 0, 0][..])); - // The following seek will require two underlying seeks. The first will - // succeed but the second will fail. This should still invalidate the + // The following seek will require two underlying seeks. The first will + // succeed but the second will fail. This should still invalidate the // buffer. assert!(reader.seek(SeekFrom::Current(i64::MIN)).is_err()); assert_eq!(reader.buffer().len(), 0); diff --git a/library/std/src/os/fd/owned.rs b/library/std/src/os/fd/owned.rs index c16518577f7c..c41e093a7e5c 100644 --- a/library/std/src/os/fd/owned.rs +++ b/library/std/src/os/fd/owned.rs @@ -100,7 +100,7 @@ impl BorrowedFd<'_> { // For ESP-IDF, F_DUPFD is used instead, because the CLOEXEC semantics // will never be supported, as this is a bare metal framework with - // no capabilities for multi-process execution. While F_DUPFD is also + // no capabilities for multi-process execution. While F_DUPFD is also // not supported yet, it might be (currently it returns ENOSYS). #[cfg(target_os = "espidf")] let cmd = libc::F_DUPFD; diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index b30dd8eecd84..b0db3112e22f 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -306,11 +306,11 @@ pub mod panic_count { // and after increase and decrease, but not necessarily during their execution. // // Additionally, the top bit of GLOBAL_PANIC_COUNT (GLOBAL_ALWAYS_ABORT_FLAG) - // records whether panic::always_abort() has been called. This can only be + // records whether panic::always_abort() has been called. This can only be // set, never cleared. // panic::always_abort() is usually called to prevent memory allocations done by // the panic handling in the child created by `libc::fork`. - // Memory allocations performed in a child created with `libc::fork` are undefined + // Memory allocations performed in a child created with `libc::fork` are undefined // behavior in most operating systems. // Accessing LOCAL_PANIC_COUNT in a child created by `libc::fork` would lead to a memory // allocation. Only GLOBAL_PANIC_COUNT can be accessed in this situation. This is diff --git a/library/std/src/path.rs b/library/std/src/path.rs index a2dcee0e2bdb..c3593264e520 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -607,7 +607,7 @@ pub struct Components<'a> { // true if path *physically* has a root separator; for most Windows // prefixes, it may have a "logical" root separator for the purposes of - // normalization, e.g., \\server\share == \\server\share\. + // normalization, e.g., \\server\share == \\server\share\. has_physical_root: bool, // The iterator is double-ended, and these two states keep track of what has diff --git a/library/std/src/sys/itron/thread.rs b/library/std/src/sys/itron/thread.rs index 535703be33f0..19350b83fab8 100644 --- a/library/std/src/sys/itron/thread.rs +++ b/library/std/src/sys/itron/thread.rs @@ -294,7 +294,7 @@ impl Drop for Thread { // Terminate and delete the task // Safety: `self.task` still represents a task we own (because // this method or `join_inner` is called only once for - // each `Thread`). The task indicated that it's safe to + // each `Thread`). The task indicated that it's safe to // delete by entering the `FINISHED` state. unsafe { terminate_and_delete_task(self.task) }; diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs index aea0c26ee8b6..3a43a007171b 100644 --- a/library/std/src/sys/unix/fs.rs +++ b/library/std/src/sys/unix/fs.rs @@ -600,13 +600,13 @@ impl Iterator for ReadDir { loop { // As of POSIX.1-2017, readdir() is not required to be thread safe; only // readdir_r() is. However, readdir_r() cannot correctly handle platforms - // with unlimited or variable NAME_MAX. Many modern platforms guarantee + // with unlimited or variable NAME_MAX. Many modern platforms guarantee // thread safety for readdir() as long an individual DIR* is not accessed // concurrently, which is sufficient for Rust. super::os::set_errno(0); let entry_ptr = readdir64(self.inner.dirp.0); if entry_ptr.is_null() { - // We either encountered an error, or reached the end. Either way, + // We either encountered an error, or reached the end. Either way, // the next call to next() should return None. self.end_of_stream = true; diff --git a/library/std/src/sys/unix/kernel_copy.rs b/library/std/src/sys/unix/kernel_copy.rs index 0f7107122b7e..73b9bef7e2ac 100644 --- a/library/std/src/sys/unix/kernel_copy.rs +++ b/library/std/src/sys/unix/kernel_copy.rs @@ -587,7 +587,7 @@ pub(super) fn copy_regular_files(reader: RawFd, writer: RawFd, max_len: u64) -> // - copy_file_range file is immutable or syscall is blocked by seccomp¹ (EPERM) // - copy_file_range cannot be used with pipes or device nodes (EINVAL) // - the writer fd was opened with O_APPEND (EBADF²) - // and no bytes were written successfully yet. (All these errnos should + // and no bytes were written successfully yet. (All these errnos should // not be returned if something was already written, but they happen in // the wild, see #91152.) // diff --git a/library/std/src/sys/unix/process/process_fuchsia.rs b/library/std/src/sys/unix/process/process_fuchsia.rs index 4c99d758c93a..d4c7e58b34d2 100644 --- a/library/std/src/sys/unix/process/process_fuchsia.rs +++ b/library/std/src/sys/unix/process/process_fuchsia.rs @@ -262,7 +262,7 @@ impl ExitStatus { // available on Fuchsia. // // It does not appear that Fuchsia is Unix-like enough to implement ExitStatus (or indeed many - // other things from std::os::unix) properly. This veneer is always going to be a bodge. So + // other things from std::os::unix) properly. This veneer is always going to be a bodge. So // while I don't know if these implementations are actually correct, I think they will do for // now at least. pub fn core_dumped(&self) -> bool { @@ -277,9 +277,9 @@ impl ExitStatus { pub fn into_raw(&self) -> c_int { // We don't know what someone who calls into_raw() will do with this value, but it should - // have the conventional Unix representation. Despite the fact that this is not + // have the conventional Unix representation. Despite the fact that this is not // standardised in SuS or POSIX, all Unix systems encode the signal and exit status the - // same way. (Ie the WIFEXITED, WEXITSTATUS etc. macros have identical behaviour on every + // same way. (Ie the WIFEXITED, WEXITSTATUS etc. macros have identical behaviour on every // Unix.) // // The caller of `std::os::unix::into_raw` is probably wanting a Unix exit status, and may @@ -287,14 +287,14 @@ impl ExitStatus { // different Unix variant. // // The other view would be to say that the caller on Fuchsia ought to know that `into_raw` - // will give a raw Fuchsia status (whatever that is - I don't know, personally). That is + // will give a raw Fuchsia status (whatever that is - I don't know, personally). That is // not possible here because we must return a c_int because that's what Unix (including // SuS and POSIX) say a wait status is, but Fuchsia apparently uses a u64, so it won't // necessarily fit. // // It seems to me that the right answer would be to provide std::os::fuchsia with its // own ExitStatusExt, rather that trying to provide a not very convincing imitation of - // Unix. Ie, std::os::unix::process:ExitStatusExt ought not to exist on Fuchsia. But + // Unix. Ie, std::os::unix::process:ExitStatusExt ought not to exist on Fuchsia. But // fixing this up that is beyond the scope of my efforts now. let exit_status_as_if_unix: u8 = self.0.try_into().expect("Fuchsia process return code bigger than 8 bits, but std::os::unix::ExitStatusExt::into_raw() was called to try to convert the value into a traditional Unix-style wait status, which cannot represent values greater than 255."); let wait_status_as_if_unix = (exit_status_as_if_unix as c_int) << 8; diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs index 39d1c8b1d8eb..c2c4aa1c9dfc 100644 --- a/library/std/src/sys/unix/process/process_unix.rs +++ b/library/std/src/sys/unix/process/process_unix.rs @@ -666,11 +666,11 @@ impl ExitStatus { } pub fn exit_ok(&self) -> Result<(), ExitStatusError> { - // This assumes that WIFEXITED(status) && WEXITSTATUS==0 corresponds to status==0. This is + // This assumes that WIFEXITED(status) && WEXITSTATUS==0 corresponds to status==0. This is // true on all actual versions of Unix, is widely assumed, and is specified in SuS - // https://pubs.opengroup.org/onlinepubs/9699919799/functions/wait.html . If it is not + // https://pubs.opengroup.org/onlinepubs/9699919799/functions/wait.html. If it is not // true for a platform pretending to be Unix, the tests (our doctests, and also - // procsss_unix/tests.rs) will spot it. `ExitStatusError::code` assumes this too. + // procsss_unix/tests.rs) will spot it. `ExitStatusError::code` assumes this too. match NonZero_c_int::try_from(self.0) { /* was nonzero */ Ok(failure) => Err(ExitStatusError(failure)), /* was zero, couldn't convert */ Err(_) => Ok(()), diff --git a/library/std/src/sys/unix/process/process_unix/tests.rs b/library/std/src/sys/unix/process/process_unix/tests.rs index 4c87f633a260..e5e1f956bc35 100644 --- a/library/std/src/sys/unix/process/process_unix/tests.rs +++ b/library/std/src/sys/unix/process/process_unix/tests.rs @@ -19,17 +19,17 @@ fn exitstatus_display_tests() { t(0x00000, "exit status: 0"); t(0x0ff00, "exit status: 255"); - // On MacOS, 0x0137f is WIFCONTINUED, not WIFSTOPPED. Probably *BSD is similar. + // On MacOS, 0x0137f is WIFCONTINUED, not WIFSTOPPED. Probably *BSD is similar. // https://github.com/rust-lang/rust/pull/82749#issuecomment-790525956 // The purpose of this test is to test our string formatting, not our understanding of the wait - // status magic numbers. So restrict these to Linux. + // status magic numbers. So restrict these to Linux. if cfg!(target_os = "linux") { t(0x0137f, "stopped (not terminated) by signal: 19 (SIGSTOP)"); t(0x0ffff, "continued (WIFCONTINUED)"); } // Testing "unrecognised wait status" is hard because the wait.h macros typically - // assume that the value came from wait and isn't mad. With the glibc I have here + // assume that the value came from wait and isn't mad. With the glibc I have here // this works: if cfg!(all(target_os = "linux", target_env = "gnu")) { t(0x000ff, "unrecognised wait status: 255 0xff"); diff --git a/library/std/src/sys/unix/process/process_vxworks.rs b/library/std/src/sys/unix/process/process_vxworks.rs index f549d37c3011..569a4b149125 100644 --- a/library/std/src/sys/unix/process/process_vxworks.rs +++ b/library/std/src/sys/unix/process/process_vxworks.rs @@ -195,11 +195,11 @@ impl ExitStatus { } pub fn exit_ok(&self) -> Result<(), ExitStatusError> { - // This assumes that WIFEXITED(status) && WEXITSTATUS==0 corresponds to status==0. This is + // This assumes that WIFEXITED(status) && WEXITSTATUS==0 corresponds to status==0. This is // true on all actual versions of Unix, is widely assumed, and is specified in SuS - // https://pubs.opengroup.org/onlinepubs/9699919799/functions/wait.html . If it is not + // https://pubs.opengroup.org/onlinepubs/9699919799/functions/wait.html. If it is not // true for a platform pretending to be Unix, the tests (our doctests, and also - // procsss_unix/tests.rs) will spot it. `ExitStatusError::code` assumes this too. + // procsss_unix/tests.rs) will spot it. `ExitStatusError::code` assumes this too. match NonZero_c_int::try_from(self.0) { Ok(failure) => Err(ExitStatusError(failure)), Err(_) => Ok(()), diff --git a/library/std/src/sys/unix/thread.rs b/library/std/src/sys/unix/thread.rs index b251949bda20..2a1830d060ed 100644 --- a/library/std/src/sys/unix/thread.rs +++ b/library/std/src/sys/unix/thread.rs @@ -73,7 +73,7 @@ impl Thread { n => { assert_eq!(n, libc::EINVAL); // EINVAL means |stack_size| is either too small or not a - // multiple of the system page size. Because it's definitely + // multiple of the system page size. Because it's definitely // >= PTHREAD_STACK_MIN, it must be an alignment issue. // Round up to the nearest page and try again. let page_size = os::page_size(); @@ -755,10 +755,10 @@ pub mod guard { if cfg!(all(target_os = "linux", not(target_env = "musl"))) { // Linux doesn't allocate the whole stack right away, and // the kernel has its own stack-guard mechanism to fault - // when growing too close to an existing mapping. If we map + // when growing too close to an existing mapping. If we map // our own guard, then the kernel starts enforcing a rather // large gap above that, rendering much of the possible - // stack space useless. See #43052. + // stack space useless. See #43052. // // Instead, we'll just note where we expect rlimit to start // faulting, so our handler can report "stack overflow", and @@ -774,14 +774,14 @@ pub mod guard { None } else if cfg!(target_os = "freebsd") { // FreeBSD's stack autogrows, and optionally includes a guard page - // at the bottom. If we try to remap the bottom of the stack - // ourselves, FreeBSD's guard page moves upwards. So we'll just use + // at the bottom. If we try to remap the bottom of the stack + // ourselves, FreeBSD's guard page moves upwards. So we'll just use // the builtin guard page. let stackptr = get_stack_start_aligned()?; let guardaddr = stackptr.addr(); // Technically the number of guard pages is tunable and controlled // by the security.bsd.stack_guard_page sysctl, but there are - // few reasons to change it from the default. The default value has + // few reasons to change it from the default. The default value has // been 1 ever since FreeBSD 11.1 and 10.4. const GUARD_PAGES: usize = 1; let guard = guardaddr..guardaddr + GUARD_PAGES * page_size; @@ -877,9 +877,9 @@ pub mod guard { } else if cfg!(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc"))) { // glibc used to include the guard area within the stack, as noted in the BUGS - // section of `man pthread_attr_getguardsize`. This has been corrected starting + // section of `man pthread_attr_getguardsize`. This has been corrected starting // with glibc 2.27, and in some distro backports, so the guard is now placed at the - // end (below) the stack. There's no easy way for us to know which we have at + // end (below) the stack. There's no easy way for us to know which we have at // runtime, so we'll just match any fault in the range right above or below the // stack base to call that fault a stack overflow. Some(stackaddr - guardsize..stackaddr + guardsize) diff --git a/library/std/src/sys/windows/os.rs b/library/std/src/sys/windows/os.rs index 352337ba3223..d7adeb266ed9 100644 --- a/library/std/src/sys/windows/os.rs +++ b/library/std/src/sys/windows/os.rs @@ -157,7 +157,7 @@ impl<'a> Iterator for SplitPaths<'a> { // Double quotes are used as a way of introducing literal semicolons // (since c:\some;dir is a valid Windows path). Double quotes are not // themselves permitted in path names, so there is no way to escape a - // double quote. Quoted regions can appear in arbitrary locations, so + // double quote. Quoted regions can appear in arbitrary locations, so // // c:\foo;c:\som"e;di"r;c:\bar // diff --git a/library/std/src/sys/windows/thread.rs b/library/std/src/sys/windows/thread.rs index c5c9e97e646f..1cb576c95947 100644 --- a/library/std/src/sys/windows/thread.rs +++ b/library/std/src/sys/windows/thread.rs @@ -26,7 +26,7 @@ impl Thread { // FIXME On UNIX, we guard against stack sizes that are too small but // that's because pthreads enforces that stacks are at least - // PTHREAD_STACK_MIN bytes big. Windows has no such lower limit, it's + // PTHREAD_STACK_MIN bytes big. Windows has no such lower limit, it's // just that below a certain threshold you can't do anything useful. // That threshold is application and architecture-specific, however. let ret = c::CreateThread( diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs index 30dc4ff85531..69fb529d7f56 100644 --- a/library/test/src/lib.rs +++ b/library/test/src/lib.rs @@ -116,7 +116,7 @@ pub fn test_main(args: &[String], tests: Vec, options: Option Option { } } else { // Found nothing in TERMINFO_DIRS, use the default paths: - // According to /etc/terminfo/README, after looking at + // According to /etc/terminfo/README, after looking at // ~/.terminfo, ncurses will search /etc/terminfo, then // /lib/terminfo, and eventually /usr/share/terminfo. // On Haiku the database can be found at /boot/system/data/terminfo From da3623abab0bb548b539a8a61ba5b813f5395db8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Vennberg?= Date: Sat, 14 Jan 2023 17:34:59 +0100 Subject: [PATCH 091/105] Removed various double spaces in compiler source comments. --- compiler/rustc_abi/src/lib.rs | 2 +- compiler/rustc_borrowck/src/places_conflict.rs | 2 +- compiler/rustc_hir_typeck/src/expr_use_visitor.rs | 2 +- compiler/rustc_hir_typeck/src/method/probe.rs | 2 +- compiler/rustc_session/src/config.rs | 2 +- compiler/rustc_trait_selection/src/traits/mod.rs | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 4582d3c6badf..b48654d1ac36 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -1100,7 +1100,7 @@ pub enum FieldsShape { /// named `inverse_memory_index`. /// // FIXME(eddyb) build a better abstraction for permutations, if possible. - // FIXME(camlorn) also consider small vector optimization here. + // FIXME(camlorn) also consider small vector optimization here. memory_index: Vec, }, } diff --git a/compiler/rustc_borrowck/src/places_conflict.rs b/compiler/rustc_borrowck/src/places_conflict.rs index 89ac0dfa4d6f..918fb2d69237 100644 --- a/compiler/rustc_borrowck/src/places_conflict.rs +++ b/compiler/rustc_borrowck/src/places_conflict.rs @@ -209,7 +209,7 @@ fn place_components_conflict<'tcx>( match (elem, &base_ty.kind(), access) { (_, _, Shallow(Some(ArtificialField::ArrayLength))) | (_, _, Shallow(Some(ArtificialField::ShallowBorrow))) => { - // The array length is like additional fields on the + // The array length is like additional fields on the // type; it does not overlap any existing data there. // Furthermore, if cannot actually be a prefix of any // borrowed place (at least in MIR as it is currently.) diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index 7774ffc9b979..c8cda0dc90c6 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -417,7 +417,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { // Named constants have to be equated with the value // being matched, so that's a read of the value being matched. // - // FIXME: We don't actually reads for ZSTs. + // FIXME: We don't actually reads for ZSTs. needs_to_be_read = true; } _ => { diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index dd827777df94..3a3080b2c967 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -232,7 +232,7 @@ pub type PickResult<'tcx> = Result, MethodError<'tcx>>; pub enum Mode { // An expression of the form `receiver.method_name(...)`. // Autoderefs are performed on `receiver`, lookup is done based on the - // `self` argument of the method, and static methods aren't considered. + // `self` argument of the method, and static methods aren't considered. MethodCall, // An expression of the form `Type::item` or `::item`. // No autoderefs are performed, lookup is done based on the type each diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 1ccfc59f7a9d..55576b4e0d19 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -2091,7 +2091,7 @@ fn parse_libs(matches: &getopts::Matches, error_format: ErrorOutputType) -> Vec< .map(|s| { // Parse string of the form "[KIND[:MODIFIERS]=]lib[:new_name]", // where KIND is one of "dylib", "framework", "static", "link-arg" and - // where MODIFIERS are a comma separated list of supported modifiers + // where MODIFIERS are a comma separated list of supported modifiers // (bundle, verbatim, whole-archive, as-needed). Each modifier is prefixed // with either + or - to indicate whether it is enabled or disabled. // The last value specified for a given modifier wins. diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 37b40a2f75ad..e5fbf981beda 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -308,7 +308,7 @@ pub fn normalize_param_env_or_error<'tcx>( // the `TypeOutlives` predicates first inside the unnormalized parameter environment, and // then we normalize the `TypeOutlives` bounds inside the normalized parameter environment. // - // This works fairly well because trait matching does not actually care about param-env + // This works fairly well because trait matching does not actually care about param-env // TypeOutlives predicates - these are normally used by regionck. let outlives_predicates: Vec<_> = predicates .drain_filter(|predicate| { From 0e65003c9e0ea97d7fcfbdb01cca181558b5fa15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Vennberg?= Date: Sat, 14 Jan 2023 18:23:40 +0100 Subject: [PATCH 092/105] Fix some missed double spaces. --- compiler/rustc_borrowck/src/region_infer/opaque_types.rs | 2 +- compiler/rustc_middle/src/ty/typeck_results.rs | 2 +- compiler/rustc_parse/src/parser/pat.rs | 2 +- compiler/rustc_target/src/asm/mod.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index 767f9fe39c68..c6e42336ef8c 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -235,7 +235,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { /// # Parameters /// /// - `def_id`, the `impl Trait` type - /// - `substs`, the substs used to instantiate this opaque type + /// - `substs`, the substs used to instantiate this opaque type /// - `instantiated_ty`, the inferred type C1 -- fully resolved, lifted version of /// `opaque_defn.concrete_ty` #[instrument(level = "debug", skip(self))] diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs index 028a03c0b2bd..b910bd888c07 100644 --- a/compiler/rustc_middle/src/ty/typeck_results.rs +++ b/compiler/rustc_middle/src/ty/typeck_results.rs @@ -193,7 +193,7 @@ pub struct TypeckResults<'tcx> { pub generator_interior_types: ty::Binder<'tcx, Vec>>, /// We sometimes treat byte string literals (which are of type `&[u8; N]`) - /// as `&[u8]`, depending on the pattern in which they are used. + /// as `&[u8]`, depending on the pattern in which they are used. /// This hashset records all instances where we behave /// like this to allow `const_to_pat` to reliably handle this situation. pub treat_byte_string_as_slice: ItemLocalSet, diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 0b057f2f577f..e73a17ced7de 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -469,7 +469,7 @@ impl<'a> Parser<'a> { /// Try to recover the more general form `intersect ::= $pat_lhs @ $pat_rhs`. /// /// Allowed binding patterns generated by `binding ::= ref? mut? $ident @ $pat_rhs` - /// should already have been parsed by now at this point, + /// should already have been parsed by now at this point, /// if the next token is `@` then we can try to parse the more general form. /// /// Consult `parse_pat_ident` for the `binding` grammar. diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs index 7f01f33d39c6..70cd883be09b 100644 --- a/compiler/rustc_target/src/asm/mod.rs +++ b/compiler/rustc_target/src/asm/mod.rs @@ -462,7 +462,7 @@ impl InlineAsmRegClass { } /// Returns a suggested template modifier to use for this type and an - /// example of a register named formatted with it. + /// example of a register named formatted with it. /// /// Such suggestions are useful if a type smaller than the full register /// size is used and a modifier can be used to point to the subregister of From 2fea03f5e69481606257a1d4dfeae2c717991e48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Vennberg?= Date: Sat, 14 Jan 2023 18:26:38 +0100 Subject: [PATCH 093/105] Fix some missed double spaces. --- library/core/src/num/dec2flt/fpu.rs | 2 +- library/core/src/pin.rs | 4 ++-- library/core/src/slice/mod.rs | 2 +- library/std/src/fs.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/library/core/src/num/dec2flt/fpu.rs b/library/core/src/num/dec2flt/fpu.rs index ec5fa45fdadd..3806977f70ee 100644 --- a/library/core/src/num/dec2flt/fpu.rs +++ b/library/core/src/num/dec2flt/fpu.rs @@ -26,7 +26,7 @@ mod fpu_precision { /// Developer's Manual (Volume 1). /// /// The only field which is relevant for the following code is PC, Precision Control. This - /// field determines the precision of the operations performed by the FPU. It can be set to: + /// field determines the precision of the operations performed by the FPU. It can be set to: /// - 0b00, single precision i.e., 32-bits /// - 0b10, double precision i.e., 64-bits /// - 0b11, double extended precision i.e., 80-bits (default state) diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index 2eb29d4f9c57..ec0c9984841e 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -753,7 +753,7 @@ impl Pin

{ impl<'a, T: ?Sized> Pin<&'a T> { /// Constructs a new pin by mapping the interior value. /// - /// For example, if you wanted to get a `Pin` of a field of something, + /// For example, if you wanted to get a `Pin` of a field of something, /// you could use this to get access to that field in one line of code. /// However, there are several gotchas with these "pinning projections"; /// see the [`pin` module] documentation for further details on that topic. @@ -856,7 +856,7 @@ impl<'a, T: ?Sized> Pin<&'a mut T> { /// Construct a new pin by mapping the interior value. /// - /// For example, if you wanted to get a `Pin` of a field of something, + /// For example, if you wanted to get a `Pin` of a field of something, /// you could use this to get access to that field in one line of code. /// However, there are several gotchas with these "pinning projections"; /// see the [`pin` module] documentation for further details on that topic. diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index caca2d0031d3..df7fe2bf76dc 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -1248,7 +1248,7 @@ impl [T] { ArrayChunksMut::new(self) } - /// Returns an iterator over overlapping windows of `N` elements of a slice, + /// Returns an iterator over overlapping windows of `N` elements of a slice, /// starting at the beginning of the slice. /// /// This is the const generic equivalent of [`windows`]. diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 5c5ef0b1125a..286ad68fd13e 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -1512,7 +1512,7 @@ impl FileType { } /// Tests whether this file type represents a regular file. - /// The result is mutually exclusive to the results of + /// The result is mutually exclusive to the results of /// [`is_dir`] and [`is_symlink`]; only zero or one of these /// tests may pass. /// From de34489a019b8e5319c09504ca158022df188d49 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 14 Jan 2023 18:30:33 +0100 Subject: [PATCH 094/105] Add explanation for GUI test --- tests/rustdoc-gui/scrape-examples-button-focus.goml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/rustdoc-gui/scrape-examples-button-focus.goml b/tests/rustdoc-gui/scrape-examples-button-focus.goml index 10651a3f6696..1b5c3a0d202a 100644 --- a/tests/rustdoc-gui/scrape-examples-button-focus.goml +++ b/tests/rustdoc-gui/scrape-examples-button-focus.goml @@ -1,3 +1,5 @@ +// This test ensures that the scraped examples buttons are working as expecting +// when 'Enter' key is pressed when they're focused. goto: "file://" + |DOC_PATH| + "/scrape_examples/fn.test.html" // The next/prev buttons vertically scroll the code viewport between examples From 287c65838cd08904c740b6b412a0ea194d16002c Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Sat, 14 Jan 2023 09:35:42 -0800 Subject: [PATCH 095/105] Fix the stability attributes for `std::os::fd`. As @bjorn3 pointed out [here], I used the wrong stability attribute in #98368 when making `std::os::fd` public. I set it to Rust 1.63, which was when io-safety was stabilized, but it should be Rust 1.66, which was when `std::os::fd` was stabilized. [here]: https://github.com/rust-lang/rust/pull/98368#discussion_r1063721420 --- library/std/src/os/fd/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/std/src/os/fd/mod.rs b/library/std/src/os/fd/mod.rs index c6aa7c77dbc4..35de4860fe24 100644 --- a/library/std/src/os/fd/mod.rs +++ b/library/std/src/os/fd/mod.rs @@ -3,7 +3,7 @@ //! This module is supported on Unix platforms and WASI, which both use a //! similar file descriptor system for referencing OS resources. -#![stable(feature = "io_safety", since = "1.63.0")] +#![stable(feature = "os_fd", since = "1.66.0")] #![deny(unsafe_op_in_unsafe_fn)] // `RawFd`, `AsRawFd`, etc. @@ -19,7 +19,7 @@ mod net; mod tests; // Export the types and traits for the public API. -#[unstable(feature = "os_fd", issue = "98699")] +#[stable(feature = "os_fd", since = "1.66.0")] pub use owned::*; -#[unstable(feature = "os_fd", issue = "98699")] +#[stable(feature = "os_fd", since = "1.66.0")] pub use raw::*; From aa51a0f19ae571497a18d2f75e409a3944d4b736 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Sun, 15 Jan 2023 05:47:24 +0900 Subject: [PATCH 096/105] Add regression test for #92157 Signed-off-by: Yuki Okushi --- tests/ui/borrowck/issue-92157.rs | 40 ++++++++++++++++++++++++++++ tests/ui/borrowck/issue-92157.stderr | 11 ++++++++ 2 files changed, 51 insertions(+) create mode 100644 tests/ui/borrowck/issue-92157.rs create mode 100644 tests/ui/borrowck/issue-92157.stderr diff --git a/tests/ui/borrowck/issue-92157.rs b/tests/ui/borrowck/issue-92157.rs new file mode 100644 index 000000000000..6ee2320a603a --- /dev/null +++ b/tests/ui/borrowck/issue-92157.rs @@ -0,0 +1,40 @@ +#![feature(no_core)] +#![feature(lang_items)] + +#![no_core] + +#[cfg(target_os = "linux")] +#[link(name = "c")] +extern {} + +#[lang = "start"] +fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8) -> isize { + //~^ ERROR: incorrect number of parameters for the `start` lang item + 40+2 +} + +#[lang = "sized"] +pub trait Sized {} +#[lang = "copy"] +pub trait Copy {} + +#[lang = "drop_in_place"] +#[allow(unconditional_recursion)] +pub unsafe fn drop_in_place(to_drop: *mut T) { + drop_in_place(to_drop) +} + +#[lang = "add"] +trait Add { + type Output; + fn add(self, other: RHS) -> Self::Output; +} + +impl Add for isize { + type Output = isize; + fn add(self, other: isize) -> isize { + self + other + } +} + +fn main() {} diff --git a/tests/ui/borrowck/issue-92157.stderr b/tests/ui/borrowck/issue-92157.stderr new file mode 100644 index 000000000000..a4010d73d057 --- /dev/null +++ b/tests/ui/borrowck/issue-92157.stderr @@ -0,0 +1,11 @@ +error: incorrect number of parameters for the `start` lang item + --> $DIR/issue-92157.rs:11:1 + | +LL | fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8) -> isize { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the `start` lang item should have four parameters, but found 3 + = note: the `start` lang item should have the signature `fn(fn() -> T, isize, *const *const u8, u8) -> isize` + +error: aborting due to previous error + From cf5be0c3ac9ee3f6fb95a75d3ce8c75b6e771728 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Sun, 15 Jan 2023 05:52:22 +0900 Subject: [PATCH 097/105] Add regression test for #42114 Signed-off-by: Yuki Okushi --- .../higher-rank-trait-bounds/issue-42114.rs | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 tests/ui/higher-rank-trait-bounds/issue-42114.rs diff --git a/tests/ui/higher-rank-trait-bounds/issue-42114.rs b/tests/ui/higher-rank-trait-bounds/issue-42114.rs new file mode 100644 index 000000000000..01515fdc9d2b --- /dev/null +++ b/tests/ui/higher-rank-trait-bounds/issue-42114.rs @@ -0,0 +1,20 @@ +// check-pass + +fn lifetime<'a>() +where + &'a (): 'a, +{ + /* do nothing */ +} + +fn doesnt_work() +where + for<'a> &'a (): 'a, +{ + /* do nothing */ +} + +fn main() { + lifetime(); + doesnt_work(); +} From 208b781bdaca4343a8538f01abd6083e925046e6 Mon Sep 17 00:00:00 2001 From: Trevor Spiteri Date: Sat, 14 Jan 2023 22:09:14 +0100 Subject: [PATCH 098/105] doc: fix typo --- library/core/src/num/int_macros.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 21518a3f5518..b3cbe862a78b 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -1625,7 +1625,7 @@ macro_rules! int_impl { /// overflow. /// /// Performs "ternary subtraction" by subtracting both an integer - /// operandand a borrow-in bit from `self`, and returns a tuple of the + /// operand and a borrow-in bit from `self`, and returns a tuple of the /// difference along with a boolean indicating whether an arithmetic /// overflow would occur. On overflow, the wrapped value is returned. /// From 130d02b62e65c5f2a434eaec63c4249e9d508487 Mon Sep 17 00:00:00 2001 From: Nick Lamb Date: Sat, 14 Jan 2023 14:51:17 +0000 Subject: [PATCH 099/105] Improve E0308: suggest user meant to use byte literal, w/ tests and fix suggested by Nilstrieb Co-authored-by: nils <48135649+Nilstrieb@users.noreply.github.com> --- .../src/infer/error_reporting/mod.rs | 16 +++++++ .../suggestions/type-mismatch-byte-literal.rs | 18 ++++++++ .../type-mismatch-byte-literal.stderr | 42 +++++++++++++++++++ 3 files changed, 76 insertions(+) create mode 100644 tests/ui/suggestions/type-mismatch-byte-literal.rs create mode 100644 tests/ui/suggestions/type-mismatch-byte-literal.stderr diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 533a3c768eb1..abd99fc74dac 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -1923,6 +1923,22 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { (ty::Tuple(fields), _) => { self.emit_tuple_wrap_err(&mut err, span, found, fields) } + // If a byte was expected and the found expression is a char literal + // containing a single ASCII character, perhaps the user meant to write `b'c'` to + // specify a byte literal + (ty::Uint(ty::UintTy::U8), ty::Char) => { + if let Ok(code) = self.tcx.sess().source_map().span_to_snippet(span) + && let Some(code) = code.strip_prefix('\'').and_then(|s| s.strip_suffix('\'')) + && code.chars().next().map_or(false, |c| c.is_ascii()) + { + err.span_suggestion( + span, + "if you meant to write a byte literal, prefix with `b`", + format!("b'{}'", escape_literal(code)), + Applicability::MachineApplicable, + ); + } + } // If a character was expected and the found expression is a string literal // containing a single character, perhaps the user meant to write `'c'` to // specify a character literal (issue #92479) diff --git a/tests/ui/suggestions/type-mismatch-byte-literal.rs b/tests/ui/suggestions/type-mismatch-byte-literal.rs new file mode 100644 index 000000000000..34199f8c37c1 --- /dev/null +++ b/tests/ui/suggestions/type-mismatch-byte-literal.rs @@ -0,0 +1,18 @@ +// Tests that a suggestion is issued for type mismatch errors when a +// u8 is expected and a char literal which is ASCII is supplied. + +fn foo(_t: u8) {} + +fn main() { + let _x: u8 = 'X'; + //~^ ERROR: mismatched types [E0308] + //~| HELP: if you meant to write a byte literal, prefix with `b` + + foo('#'); + //~^ ERROR: mismatched types [E0308] + //~| HELP: if you meant to write a byte literal, prefix with `b` + + // Do not issue the suggestion if the char literal isn't ASCII + let _t: u8 = '€'; + //~^ ERROR: mismatched types [E0308] +} diff --git a/tests/ui/suggestions/type-mismatch-byte-literal.stderr b/tests/ui/suggestions/type-mismatch-byte-literal.stderr new file mode 100644 index 000000000000..c9c2e7498d05 --- /dev/null +++ b/tests/ui/suggestions/type-mismatch-byte-literal.stderr @@ -0,0 +1,42 @@ +error[E0308]: mismatched types + --> $DIR/type-mismatch-byte-literal.rs:7:18 + | +LL | let _x: u8 = 'X'; + | -- ^^^ expected `u8`, found `char` + | | + | expected due to this + | +help: if you meant to write a byte literal, prefix with `b` + | +LL | let _x: u8 = b'X'; + | ~~~~ + +error[E0308]: mismatched types + --> $DIR/type-mismatch-byte-literal.rs:11:9 + | +LL | foo('#'); + | --- ^^^ expected `u8`, found `char` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/type-mismatch-byte-literal.rs:4:4 + | +LL | fn foo(_t: u8) {} + | ^^^ ------ +help: if you meant to write a byte literal, prefix with `b` + | +LL | foo(b'#'); + | ~~~~ + +error[E0308]: mismatched types + --> $DIR/type-mismatch-byte-literal.rs:16:18 + | +LL | let _t: u8 = '€'; + | -- ^^^ expected `u8`, found `char` + | | + | expected due to this + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. From 4fe167f83a90f3f193c3cb5dafb4c2862d0671e9 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 18 Dec 2022 09:40:23 -0800 Subject: [PATCH 100/105] Add test of leaking a binary_heap PeekMut --- .../src/collections/binary_heap/tests.rs | 19 +++++++++++++++++++ library/alloc/src/lib.rs | 1 + 2 files changed, 20 insertions(+) diff --git a/library/alloc/src/collections/binary_heap/tests.rs b/library/alloc/src/collections/binary_heap/tests.rs index 59c516374c0e..ffbb6c80ac01 100644 --- a/library/alloc/src/collections/binary_heap/tests.rs +++ b/library/alloc/src/collections/binary_heap/tests.rs @@ -1,6 +1,7 @@ use super::*; use crate::boxed::Box; use crate::testing::crash_test::{CrashTestDummy, Panic}; +use core::mem; use std::iter::TrustedLen; use std::panic::{catch_unwind, AssertUnwindSafe}; @@ -146,6 +147,24 @@ fn test_peek_mut() { assert_eq!(heap.peek(), Some(&9)); } +#[test] +fn test_peek_mut_leek() { + let data = vec![4, 2, 7]; + let mut heap = BinaryHeap::from(data); + let mut max = heap.peek_mut().unwrap(); + *max = -1; + + // The PeekMut object's Drop impl would have been responsible for moving the + // -1 out of the max position of the BinaryHeap, but we don't run it. + mem::forget(max); + + // Absent some mitigation like leak amplification, the -1 would incorrectly + // end up in the last position of the returned Vec, with the rest of the + // heap's original contents in front of it in sorted order. + let sorted_vec = heap.into_sorted_vec(); + assert!(sorted_vec.is_sorted(), "{:?}", sorted_vec); +} + #[test] fn test_peek_mut_pop() { let data = vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]; diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 4e812529c2cc..afc3a3dc6a8c 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -125,6 +125,7 @@ #![feature(hasher_prefixfree_extras)] #![feature(inline_const)] #![feature(inplace_iteration)] +#![cfg_attr(test, feature(is_sorted))] #![feature(iter_advance_by)] #![feature(iter_next_chunk)] #![feature(iter_repeat_n)] From aedb756020dffd4be1b4e055e989e8761103f93f Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 18 Dec 2022 09:40:36 -0800 Subject: [PATCH 101/105] Leak amplification for peek_mut() to ensure BinaryHeap's invariant is always met --- .../alloc/src/collections/binary_heap/mod.rs | 55 ++++++++++++++++--- 1 file changed, 46 insertions(+), 9 deletions(-) diff --git a/library/alloc/src/collections/binary_heap/mod.rs b/library/alloc/src/collections/binary_heap/mod.rs index 4583bc9a158e..e3fef96613bd 100644 --- a/library/alloc/src/collections/binary_heap/mod.rs +++ b/library/alloc/src/collections/binary_heap/mod.rs @@ -146,6 +146,7 @@ use core::fmt; use core::iter::{FromIterator, FusedIterator, InPlaceIterable, SourceIter, TrustedLen}; use core::mem::{self, swap, ManuallyDrop}; +use core::num::NonZeroUsize; use core::ops::{Deref, DerefMut}; use core::ptr; @@ -279,7 +280,9 @@ pub struct BinaryHeap { #[stable(feature = "binary_heap_peek_mut", since = "1.12.0")] pub struct PeekMut<'a, T: 'a + Ord> { heap: &'a mut BinaryHeap, - sift: bool, + // If a set_len + sift_down are required, this is Some. If a &mut T has not + // yet been exposed to peek_mut()'s caller, it's None. + original_len: Option, } #[stable(feature = "collection_debug", since = "1.17.0")] @@ -292,7 +295,14 @@ impl fmt::Debug for PeekMut<'_, T> { #[stable(feature = "binary_heap_peek_mut", since = "1.12.0")] impl Drop for PeekMut<'_, T> { fn drop(&mut self) { - if self.sift { + if let Some(original_len) = self.original_len { + // SAFETY: That's how many elements were in the Vec at the time of + // the PeekMut::deref_mut call, and therefore also at the time of + // the BinaryHeap::peek_mut call. Since the PeekMut did not end up + // getting leaked, we are now undoing the leak amplification that + // the DerefMut prepared for. + unsafe { self.heap.data.set_len(original_len.get()) }; + // SAFETY: PeekMut is only instantiated for non-empty heaps. unsafe { self.heap.sift_down(0) }; } @@ -313,7 +323,26 @@ impl Deref for PeekMut<'_, T> { impl DerefMut for PeekMut<'_, T> { fn deref_mut(&mut self) -> &mut T { debug_assert!(!self.heap.is_empty()); - self.sift = true; + + let len = self.heap.len(); + if len > 1 { + // Here we preemptively leak all the rest of the underlying vector + // after the currently max element. If the caller mutates the &mut T + // we're about to give them, and then leaks the PeekMut, all these + // elements will remain leaked. If they don't leak the PeekMut, then + // either Drop or PeekMut::pop will un-leak the vector elements. + // + // This is technique is described throughout several other places in + // the standard library as "leak amplification". + unsafe { + // SAFETY: len > 1 so len != 0. + self.original_len = Some(NonZeroUsize::new_unchecked(len)); + // SAFETY: len > 1 so all this does for now is leak elements, + // which is safe. + self.heap.data.set_len(1); + } + } + // SAFE: PeekMut is only instantiated for non-empty heaps unsafe { self.heap.data.get_unchecked_mut(0) } } @@ -323,9 +352,16 @@ impl<'a, T: Ord> PeekMut<'a, T> { /// Removes the peeked value from the heap and returns it. #[stable(feature = "binary_heap_peek_mut_pop", since = "1.18.0")] pub fn pop(mut this: PeekMut<'a, T>) -> T { - let value = this.heap.pop().unwrap(); - this.sift = false; - value + if let Some(original_len) = this.original_len.take() { + // SAFETY: This is how many elements were in the Vec at the time of + // the BinaryHeap::peek_mut call. + unsafe { this.heap.data.set_len(original_len.get()) }; + + // Unlike in Drop, here we don't also need to do a sift_down even if + // the caller could've mutated the element. It is removed from the + // heap on the next line and pop() is not sensitive to its value. + } + this.heap.pop().unwrap() } } @@ -398,8 +434,9 @@ impl BinaryHeap { /// Returns a mutable reference to the greatest item in the binary heap, or /// `None` if it is empty. /// - /// Note: If the `PeekMut` value is leaked, the heap may be in an - /// inconsistent state. + /// Note: If the `PeekMut` value is leaked, some heap elements might get + /// leaked along with it, but the remaining elements will remain a valid + /// heap. /// /// # Examples /// @@ -426,7 +463,7 @@ impl BinaryHeap { /// otherwise it's *O*(1). #[stable(feature = "binary_heap_peek_mut", since = "1.12.0")] pub fn peek_mut(&mut self) -> Option> { - if self.is_empty() { None } else { Some(PeekMut { heap: self, sift: false }) } + if self.is_empty() { None } else { Some(PeekMut { heap: self, original_len: None }) } } /// Removes the greatest item from the binary heap and returns it, or `None` if it From 23501703fb444a083155e8aa0b280d36be84c676 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 5 Jan 2023 00:04:59 -0800 Subject: [PATCH 102/105] Document guarantees about BinaryHeap invariant --- library/alloc/src/collections/binary_heap/mod.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/library/alloc/src/collections/binary_heap/mod.rs b/library/alloc/src/collections/binary_heap/mod.rs index e3fef96613bd..0b73b1af4eb3 100644 --- a/library/alloc/src/collections/binary_heap/mod.rs +++ b/library/alloc/src/collections/binary_heap/mod.rs @@ -166,12 +166,20 @@ mod tests; /// It is a logic error for an item to be modified in such a way that the /// item's ordering relative to any other item, as determined by the [`Ord`] /// trait, changes while it is in the heap. This is normally only possible -/// through [`Cell`], [`RefCell`], global state, I/O, or unsafe code. The +/// through interior mutability, global state, I/O, or unsafe code. The /// behavior resulting from such a logic error is not specified, but will /// be encapsulated to the `BinaryHeap` that observed the logic error and not /// result in undefined behavior. This could include panics, incorrect results, /// aborts, memory leaks, and non-termination. /// +/// As long as no elements change their relative order while being in the heap +/// as described above, the API of `BinaryHeap` guarantees that the heap +/// invariant remains intact i.e. its methods all behave as documented. For +/// example if a method is documented as iterating in sorted order, that's +/// guaranteed to work as long as elements in the heap have not changed order, +/// even in the presence of closures getting unwinded out of, iterators getting +/// leaked, and similar foolishness. +/// /// # Examples /// /// ``` From 0d3eaa848ce6b44a83502174eae16524c893dd28 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 15 Jan 2023 13:08:20 -0800 Subject: [PATCH 103/105] Add test showing broken behavior of BinaryHeap::retain --- .../alloc/src/collections/binary_heap/tests.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/library/alloc/src/collections/binary_heap/tests.rs b/library/alloc/src/collections/binary_heap/tests.rs index ffbb6c80ac01..835b2e5b7e91 100644 --- a/library/alloc/src/collections/binary_heap/tests.rs +++ b/library/alloc/src/collections/binary_heap/tests.rs @@ -474,6 +474,23 @@ fn test_retain() { assert!(a.is_empty()); } +#[test] +fn test_retain_catch_unwind() { + let mut heap = BinaryHeap::from(vec![3, 1, 2]); + + // Removes the 3, then unwinds out of retain. + let _ = catch_unwind(AssertUnwindSafe(|| { + heap.retain(|e| { + if *e == 1 { + panic!(); + } + false + }); + })); + + assert_eq!(heap.into_vec(), [1, 2]); // BAD!! +} + // old binaryheap failed this test // // Integrity means that all elements are present after a comparison panics, From fa2ff4d7e5a88bfda186f0f3f621402470745788 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 15 Jan 2023 13:14:33 -0800 Subject: [PATCH 104/105] Rebuild BinaryHeap on unwind from retain --- .../alloc/src/collections/binary_heap/mod.rs | 24 ++++++++++++++----- .../src/collections/binary_heap/tests.rs | 4 +++- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/library/alloc/src/collections/binary_heap/mod.rs b/library/alloc/src/collections/binary_heap/mod.rs index 0b73b1af4eb3..f1d0a305d999 100644 --- a/library/alloc/src/collections/binary_heap/mod.rs +++ b/library/alloc/src/collections/binary_heap/mod.rs @@ -851,18 +851,30 @@ impl BinaryHeap { where F: FnMut(&T) -> bool, { - let mut first_removed = self.len(); + struct RebuildOnDrop<'a, T: Ord> { + heap: &'a mut BinaryHeap, + first_removed: usize, + } + + let mut guard = RebuildOnDrop { first_removed: self.len(), heap: self }; + let mut i = 0; - self.data.retain(|e| { + guard.heap.data.retain(|e| { let keep = f(e); - if !keep && i < first_removed { - first_removed = i; + if !keep && i < guard.first_removed { + guard.first_removed = i; } i += 1; keep }); - // data[0..first_removed] is untouched, so we only need to rebuild the tail: - self.rebuild_tail(first_removed); + + impl<'a, T: Ord> Drop for RebuildOnDrop<'a, T> { + fn drop(&mut self) { + // data[..first_removed] is untouched, so we only need to + // rebuild the tail: + self.heap.rebuild_tail(self.first_removed); + } + } } } diff --git a/library/alloc/src/collections/binary_heap/tests.rs b/library/alloc/src/collections/binary_heap/tests.rs index 835b2e5b7e91..500caa35678a 100644 --- a/library/alloc/src/collections/binary_heap/tests.rs +++ b/library/alloc/src/collections/binary_heap/tests.rs @@ -488,7 +488,9 @@ fn test_retain_catch_unwind() { }); })); - assert_eq!(heap.into_vec(), [1, 2]); // BAD!! + // Naively this would be [1, 2] (an invalid heap) if BinaryHeap delegates to + // Vec's retain impl and then does not rebuild the heap after that unwinds. + assert_eq!(heap.into_vec(), [2, 1]); } // old binaryheap failed this test From ec5f8253e28a660034a3936a171f93a3c063a0cc Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 15 Jan 2023 16:45:54 -0500 Subject: [PATCH 105/105] Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index d42c0367b77d..c0dbb2e644c1 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -279f1c9d8c26a8d227ae8ab806d262bb784b251b +9e75dddf609c0201d03f9792e850f95d6a283d11