From 6b68921ca0d25690e9d7d3b5d6f442fb1bda1fcc Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 6 Aug 2022 18:04:52 +0300 Subject: [PATCH 1/7] Change implementation of `-Z gcc-ld` and `lld-wrapper` again --- compiler/rustc_codegen_ssa/src/back/link.rs | 32 ++++++++++--------- src/bootstrap/compile.rs | 4 ++- src/bootstrap/dist.rs | 7 +++-- src/bootstrap/lib.rs | 3 ++ src/tools/lld-wrapper/src/main.rs | 35 +++++++++++---------- 5 files changed, 48 insertions(+), 33 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 63207803e327f..085057c3bf3fa 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -2777,20 +2777,24 @@ fn add_gcc_ld_path(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) { if let LinkerFlavor::Gcc = flavor { match ld_impl { LdImpl::Lld => { - let tools_path = sess.get_tools_search_paths(false); - let gcc_ld_dir = tools_path - .into_iter() - .map(|p| p.join("gcc-ld")) - .find(|p| { - p.join(if sess.host.is_like_windows { "ld.exe" } else { "ld" }).exists() - }) - .unwrap_or_else(|| sess.fatal("rust-lld (as ld) not found")); - cmd.arg({ - let mut arg = OsString::from("-B"); - arg.push(gcc_ld_dir); - arg - }); - cmd.arg(format!("-Wl,-rustc-lld-flavor={}", sess.target.lld_flavor.as_str())); + // Implement the "self-contained" part of -Zgcc-ld + // by adding rustc distribution directories to the tool search path. + for path in sess.get_tools_search_paths(false) { + cmd.arg({ + let mut arg = OsString::from("-B"); + arg.push(path.join("gcc-ld")); + arg + }); + } + // Implement the "linker flavor" part of -Zgcc-ld + // by asking cc to use some kind of lld. + cmd.arg("-fuse-ld=lld"); + if sess.target.lld_flavor != LldFlavor::Ld { + // Tell clang to use a non-default LLD flavor. + // Gcc doesn't understand the target option, but we currently assume + // that gcc is not used for Apple and Wasm targets (#97402). + cmd.arg(format!("--target={}", sess.target.llvm_target)); + } } } } else { diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index dd2b9d59366ea..0d89e0a4f25c9 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -1276,7 +1276,9 @@ impl Step for Assemble { compiler: build_compiler, target: target_compiler.host, }); - builder.copy(&lld_wrapper_exe, &gcc_ld_dir.join(exe("ld", target_compiler.host))); + for name in crate::LLD_FILE_NAMES { + builder.copy(&lld_wrapper_exe, &gcc_ld_dir.join(exe(name, target_compiler.host))); + } } if builder.config.rust_codegen_backends.contains(&INTERNER.intern_str("llvm")) { diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 6291b204e485f..31f71759e249e 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -423,8 +423,11 @@ impl Step for Rustc { let gcc_lld_src_dir = src_dir.join("gcc-ld"); let gcc_lld_dst_dir = dst_dir.join("gcc-ld"); t!(fs::create_dir(&gcc_lld_dst_dir)); - let exe_name = exe("ld", compiler.host); - builder.copy(&gcc_lld_src_dir.join(&exe_name), &gcc_lld_dst_dir.join(&exe_name)); + for name in crate::LLD_FILE_NAMES { + let exe_name = exe(name, compiler.host); + builder + .copy(&gcc_lld_src_dir.join(&exe_name), &gcc_lld_dst_dir.join(&exe_name)); + } } // Man pages diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index f84de73297acb..797e846733176 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -186,6 +186,9 @@ const LLVM_TOOLS: &[&str] = &[ "opt", // used to optimize LLVM bytecode ]; +/// LLD file names for all flavors. +const LLD_FILE_NAMES: &[&str] = &["ld.lld", "ld64.lld", "lld-link", "wasm-ld"]; + pub const VERSION: usize = 2; /// Extra --check-cfg to add when building diff --git a/src/tools/lld-wrapper/src/main.rs b/src/tools/lld-wrapper/src/main.rs index 90bd24a75e064..1795f3d7fe5bc 100644 --- a/src/tools/lld-wrapper/src/main.rs +++ b/src/tools/lld-wrapper/src/main.rs @@ -8,8 +8,8 @@ //! make gcc/clang pass `-flavor ` as the first two arguments in the linker invocation //! and since Windows does not support symbolic links for files this wrapper is used in place of a //! symbolic link. It execs `../rust-lld -flavor ` by propagating the flavor argument -//! passed to the wrapper as the first two arguments. On Windows it spawns a `..\rust-lld.exe` -//! child process. +//! obtained from the wrapper's name as the first two arguments. +//! On Windows it spawns a `..\rust-lld.exe` child process. use std::fmt::Display; use std::path::{Path, PathBuf}; @@ -53,29 +53,32 @@ fn get_rust_lld_path(current_exe_path: &Path) -> PathBuf { rust_lld_path } +/// Extract LLD flavor name from the lld-wrapper executable name. +fn get_lld_flavor(current_exe_path: &Path) -> Result<&'static str, String> { + let stem = current_exe_path.file_stem(); + Ok(match stem.and_then(|s| s.to_str()) { + Some("ld.lld") => "gnu", + Some("ld64.lld") => "darwin", + Some("lld-link") => "link", + Some("wasm-ld") => "wasm", + _ => return Err(format!("{:?}", stem)), + }) +} + /// Returns the command for invoking rust-lld with the correct flavor. -/// LLD only accepts the flavor argument at the first two arguments, so move it there. +/// LLD only accepts the flavor argument at the first two arguments, so pass it there. /// /// Exits on error. fn get_rust_lld_command(current_exe_path: &Path) -> process::Command { let rust_lld_path = get_rust_lld_path(current_exe_path); let mut command = process::Command::new(rust_lld_path); - let mut flavor = None; - let args = env::args_os() - .skip(1) - .filter(|arg| match arg.to_str().and_then(|s| s.strip_prefix("-rustc-lld-flavor=")) { - Some(suffix) => { - flavor = Some(suffix.to_string()); - false - } - None => true, - }) - .collect::>(); + let flavor = + get_lld_flavor(current_exe_path).unwrap_or_exit_with("executable has unexpected name"); command.arg("-flavor"); - command.arg(flavor.unwrap_or_exit_with("-rustc-lld-flavor= is not passed")); - command.args(args); + command.arg(flavor); + command.args(env::args_os().skip(1)); command } From 81a583c21e74d600ef8c4b45a3d5088382300e17 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Wed, 3 Aug 2022 22:24:47 +0200 Subject: [PATCH 2/7] Try normalizing types without RevealAll in ParamEnv in mir validation Before, the MIR validator used RevealAll in its ParamEnv for type checking. This could cause false negatives in some cases due to RevealAll ParamEnvs not always use all predicates as expected here. Since some MIR passes like inlining use RevealAll as well, keep using it in the MIR validator too, but when it fails usign RevealAll, also try the check without it, to stop false negatives. --- .../src/transform/validate.rs | 28 +++++++++++++------ src/test/ui/mir/issue-99866.rs | 25 +++++++++++++++++ 2 files changed, 45 insertions(+), 8 deletions(-) create mode 100644 src/test/ui/mir/issue-99866.rs diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index 45a94972c1134..ddde9ff4c0281 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -181,16 +181,28 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { if (src, dest).has_opaque_types() { return true; } + + let try_equal_with_param_env = |param_env| { + let src = self.tcx.normalize_erasing_regions(param_env, src); + let dest = self.tcx.normalize_erasing_regions(param_env, dest); + // Type-changing assignments can happen when subtyping is used. While + // all normal lifetimes are erased, higher-ranked types with their + // late-bound lifetimes are still around and can lead to type + // differences. So we compare ignoring lifetimes. + equal_up_to_regions(self.tcx, param_env, src, dest) + }; + // Normalize projections and things like that. + // First, try with reveal_all. This might not work in some cases, as the predicates + // can be cleared in reveal_all mode. We try the reveal first anyways as it is used + // by some other passes like inlining as well. let param_env = self.param_env.with_reveal_all_normalized(self.tcx); - let src = self.tcx.normalize_erasing_regions(param_env, src); - let dest = self.tcx.normalize_erasing_regions(param_env, dest); - - // Type-changing assignments can happen when subtyping is used. While - // all normal lifetimes are erased, higher-ranked types with their - // late-bound lifetimes are still around and can lead to type - // differences. So we compare ignoring lifetimes. - equal_up_to_regions(self.tcx, param_env, src, dest) + if try_equal_with_param_env(param_env) { + true + } else { + // If this fails, we can try it without the reveal. + try_equal_with_param_env(self.param_env) + } } } diff --git a/src/test/ui/mir/issue-99866.rs b/src/test/ui/mir/issue-99866.rs new file mode 100644 index 0000000000000..d39ae6ebf1da2 --- /dev/null +++ b/src/test/ui/mir/issue-99866.rs @@ -0,0 +1,25 @@ +// check-pass +pub trait Backend { + type DescriptorSetLayout; +} + +pub struct Back; + +impl Backend for Back { + type DescriptorSetLayout = u32; +} + +pub struct HalSetLayouts { + vertex_layout: ::DescriptorSetLayout, +} + +impl HalSetLayouts { + pub fn iter(self) -> DSL + where + Back: Backend, + { + self.vertex_layout + } +} + +fn main() {} From 96d4137deed6c52c6db2dd19568c37d1c160f1e7 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sat, 6 Aug 2022 14:22:57 +0200 Subject: [PATCH 3/7] Only normalize once in mir validator typechecker Before, it called `normalize_erasing_regions` twice since `equal_up_to_regions` called it as well for both types. --- .../src/transform/validate.rs | 25 ++++++++----------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index ddde9ff4c0281..69113e57bdc5b 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -182,27 +182,22 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { return true; } - let try_equal_with_param_env = |param_env| { - let src = self.tcx.normalize_erasing_regions(param_env, src); - let dest = self.tcx.normalize_erasing_regions(param_env, dest); - // Type-changing assignments can happen when subtyping is used. While - // all normal lifetimes are erased, higher-ranked types with their - // late-bound lifetimes are still around and can lead to type - // differences. So we compare ignoring lifetimes. - equal_up_to_regions(self.tcx, param_env, src, dest) - }; - // Normalize projections and things like that. + // Type-changing assignments can happen when subtyping is used. While + // all normal lifetimes are erased, higher-ranked types with their + // late-bound lifetimes are still around and can lead to type + // differences. So we compare ignoring lifetimes. + // First, try with reveal_all. This might not work in some cases, as the predicates // can be cleared in reveal_all mode. We try the reveal first anyways as it is used // by some other passes like inlining as well. let param_env = self.param_env.with_reveal_all_normalized(self.tcx); - if try_equal_with_param_env(param_env) { - true - } else { - // If this fails, we can try it without the reveal. - try_equal_with_param_env(self.param_env) + if equal_up_to_regions(self.tcx, param_env, src, dest) { + return true; } + + // If this fails, we can try it without the reveal. + equal_up_to_regions(self.tcx, self.param_env, src, dest) } } From 630f831cd06d24732c9a422b8d3d3e2ce9e1a879 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Thu, 1 Sep 2022 04:17:36 +0100 Subject: [PATCH 4/7] Use `FILE_ATTRIBUTE_TAG_INFO` to get reparse tag This avoid unnecessarily getting the full reparse data when all we need is the tag. --- library/std/src/sys/windows/c.rs | 6 ++++++ library/std/src/sys/windows/fs.rs | 26 ++++++++++++++++++-------- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs index c99c8efe4367f..b4db77700aabd 100644 --- a/library/std/src/sys/windows/c.rs +++ b/library/std/src/sys/windows/c.rs @@ -454,6 +454,12 @@ pub enum FILE_INFO_BY_HANDLE_CLASS { MaximumFileInfoByHandlesClass, } +#[repr(C)] +pub struct FILE_ATTRIBUTE_TAG_INFO { + pub FileAttributes: DWORD, + pub ReparseTag: DWORD, +} + #[repr(C)] pub struct FILE_DISPOSITION_INFO { pub DeleteFile: BOOLEAN, diff --git a/library/std/src/sys/windows/fs.rs b/library/std/src/sys/windows/fs.rs index 98c8834d38403..c2ad592dfea73 100644 --- a/library/std/src/sys/windows/fs.rs +++ b/library/std/src/sys/windows/fs.rs @@ -326,10 +326,15 @@ impl File { cvt(c::GetFileInformationByHandle(self.handle.as_raw_handle(), &mut info))?; let mut reparse_tag = 0; if info.dwFileAttributes & c::FILE_ATTRIBUTE_REPARSE_POINT != 0 { - let mut b = - Align8([MaybeUninit::::uninit(); c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE]); - if let Ok((_, buf)) = self.reparse_point(&mut b) { - reparse_tag = (*buf).ReparseTag; + let mut attr_tag: c::FILE_ATTRIBUTE_TAG_INFO = mem::zeroed(); + cvt(c::GetFileInformationByHandleEx( + self.handle.as_raw_handle(), + c::FileAttributeTagInfo, + ptr::addr_of_mut!(attr_tag).cast(), + mem::size_of::().try_into().unwrap(), + ))?; + if attr_tag.FileAttributes & c::FILE_ATTRIBUTE_REPARSE_POINT != 0 { + reparse_tag = attr_tag.ReparseTag; } } Ok(FileAttr { @@ -390,10 +395,15 @@ impl File { attr.file_size = info.AllocationSize as u64; attr.number_of_links = Some(info.NumberOfLinks); if attr.file_type().is_reparse_point() { - let mut b = - Align8([MaybeUninit::::uninit(); c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE]); - if let Ok((_, buf)) = self.reparse_point(&mut b) { - attr.reparse_tag = (*buf).ReparseTag; + let mut attr_tag: c::FILE_ATTRIBUTE_TAG_INFO = mem::zeroed(); + cvt(c::GetFileInformationByHandleEx( + self.handle.as_raw_handle(), + c::FileAttributeTagInfo, + ptr::addr_of_mut!(attr_tag).cast(), + mem::size_of::().try_into().unwrap(), + ))?; + if attr_tag.FileAttributes & c::FILE_ATTRIBUTE_REPARSE_POINT != 0 { + reparse_tag = attr_tag.ReparseTag; } } Ok(attr) From 8e8220027711874f8bf176b14cb8e87b01342081 Mon Sep 17 00:00:00 2001 From: Gabriel Bustamante Date: Fri, 26 Aug 2022 13:08:58 -0500 Subject: [PATCH 5/7] Porting 'compiler/rustc_trait_selection' to translatable diagnostics - Part 1 --- .../locales/en-US/trait_selection.ftl | 26 +++++ compiler/rustc_error_messages/src/lib.rs | 1 + compiler/rustc_middle/src/ty/consts/kind.rs | 6 ++ compiler/rustc_middle/src/ty/sty.rs | 6 ++ compiler/rustc_session/src/session.rs | 6 ++ .../rustc_trait_selection/src/autoderef.rs | 19 +--- compiler/rustc_trait_selection/src/errors.rs | 102 ++++++++++++++++++ compiler/rustc_trait_selection/src/lib.rs | 1 + .../src/traits/auto_trait.rs | 8 +- .../rustc_trait_selection/src/traits/mod.rs | 8 +- .../src/traits/on_unimplemented.rs | 47 ++------ .../src/traits/specialize/mod.rs | 37 ++----- 12 files changed, 180 insertions(+), 87 deletions(-) create mode 100644 compiler/rustc_error_messages/locales/en-US/trait_selection.ftl create mode 100644 compiler/rustc_trait_selection/src/errors.rs diff --git a/compiler/rustc_error_messages/locales/en-US/trait_selection.ftl b/compiler/rustc_error_messages/locales/en-US/trait_selection.ftl new file mode 100644 index 0000000000000..004e0ab189694 --- /dev/null +++ b/compiler/rustc_error_messages/locales/en-US/trait_selection.ftl @@ -0,0 +1,26 @@ +trait_selection_dump_vtable_entries = vtable entries for `{$trait_ref}`: {$entries} + +trait_selection_unable_to_construct_constant_value = unable to construct a constant value for the unevaluated constant {$unevaluated} + +trait_selection_auto_deref_reached_recursion_limit = reached the recursion limit while auto-dereferencing `{$ty}` + .label = deref recursion limit reached + .help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]` attribute to your crate (`{$crate_name}`) + +trait_selection_empty_on_clause_in_rustc_on_unimplemented = empty `on`-clause in `#[rustc_on_unimplemented]` + .label = empty on-clause here + +trait_selection_invalid_on_clause_in_rustc_on_unimplemented = invalid `on`-clause in `#[rustc_on_unimplemented]` + .label = invalid on-clause here + +trait_selection_no_value_in_rustc_on_unimplemented = this attribute must have a valid value + .label = expected value here + .note = eg `#[rustc_on_unimplemented(message="foo")]` + +trait_selection_negative_positive_conflict = found both positive and negative implementation of trait `{$trait_desc}`{$self_desc -> + [none] {""} + *[default] {" "}for type `{$self_desc}` + }: + .negative_implementation_here = negative implementation here + .negative_implementation_in_crate = negative implementation in crate `{$negative_impl_cname}` + .positive_implementation_here = positive implementation here + .positive_implementation_in_crate = positive implementation in crate `{$positive_impl_cname}` diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index 8f47be25db917..5fe107fbc530a 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -51,6 +51,7 @@ fluent_messages! { plugin_impl => "../locales/en-US/plugin_impl.ftl", privacy => "../locales/en-US/privacy.ftl", query_system => "../locales/en-US/query_system.ftl", + trait_selection => "../locales/en-US/trait_selection.ftl", save_analysis => "../locales/en-US/save_analysis.ftl", ty_utils => "../locales/en-US/ty_utils.ftl", typeck => "../locales/en-US/typeck.ftl", diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs index cb0137d2e5e09..3840e79cebd84 100644 --- a/compiler/rustc_middle/src/ty/consts/kind.rs +++ b/compiler/rustc_middle/src/ty/consts/kind.rs @@ -20,6 +20,12 @@ pub struct Unevaluated<'tcx, P = Option> { pub promoted: P, } +impl rustc_errors::IntoDiagnosticArg for Unevaluated<'_> { + fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { + format!("{:?}", self).into_diagnostic_arg() + } +} + impl<'tcx> Unevaluated<'tcx> { #[inline] pub fn shrink(self) -> Unevaluated<'tcx, ()> { diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 80354a3f8a226..9fb91b5fe8700 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -849,6 +849,12 @@ impl<'tcx> PolyTraitRef<'tcx> { } } +impl rustc_errors::IntoDiagnosticArg for PolyTraitRef<'_> { + fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { + self.to_string().into_diagnostic_arg() + } +} + /// An existential reference to a trait, where `Self` is erased. /// For example, the trait object `Trait<'a, 'b, X, Y>` is: /// ```ignore (illustrative) diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index ec5e5170d3594..a49af23be2316 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -110,6 +110,12 @@ impl Mul for Limit { } } +impl rustc_errors::IntoDiagnosticArg for Limit { + fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { + self.to_string().into_diagnostic_arg() + } +} + #[derive(Clone, Copy, Debug, HashStable_Generic)] pub struct Limits { /// The maximum recursion limit for potentially infinitely recursive diff --git a/compiler/rustc_trait_selection/src/autoderef.rs b/compiler/rustc_trait_selection/src/autoderef.rs index 8b7e8984a8adb..36ab8f3bd8845 100644 --- a/compiler/rustc_trait_selection/src/autoderef.rs +++ b/compiler/rustc_trait_selection/src/autoderef.rs @@ -1,6 +1,6 @@ +use crate::errors::AutoDerefReachedRecursionLimit; use crate::traits::query::evaluate_obligation::InferCtxtExt; use crate::traits::{self, TraitEngine}; -use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_infer::infer::InferCtxt; use rustc_middle::ty::{self, TraitRef, Ty, TyCtxt}; @@ -222,19 +222,10 @@ pub fn report_autoderef_recursion_limit_error<'tcx>(tcx: TyCtxt<'tcx>, span: Spa Limit(0) => Limit(2), limit => limit * 2, }; - struct_span_err!( - tcx.sess, + tcx.sess.emit_err(AutoDerefReachedRecursionLimit { span, - E0055, - "reached the recursion limit while auto-dereferencing `{:?}`", - ty - ) - .span_label(span, "deref recursion limit reached") - .help(&format!( - "consider increasing the recursion limit by adding a \ - `#![recursion_limit = \"{}\"]` attribute to your crate (`{}`)", + ty, suggested_limit, - tcx.crate_name(LOCAL_CRATE), - )) - .emit(); + crate_name: tcx.crate_name(LOCAL_CRATE), + }); } diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs new file mode 100644 index 0000000000000..81977f25ca21f --- /dev/null +++ b/compiler/rustc_trait_selection/src/errors.rs @@ -0,0 +1,102 @@ +use rustc_errors::{fluent, ErrorGuaranteed}; +use rustc_macros::SessionDiagnostic; +use rustc_middle::ty::{PolyTraitRef, Ty, Unevaluated}; +use rustc_session::{parse::ParseSess, Limit, SessionDiagnostic}; +use rustc_span::{Span, Symbol}; + +#[derive(SessionDiagnostic)] +#[diag(trait_selection::dump_vtable_entries)] +pub struct DumpVTableEntries<'a> { + #[primary_span] + pub span: Span, + pub trait_ref: PolyTraitRef<'a>, + pub entries: String, +} + +#[derive(SessionDiagnostic)] +#[diag(trait_selection::unable_to_construct_constant_value)] +pub struct UnableToConstructConstantValue<'a> { + #[primary_span] + pub span: Span, + pub unevaluated: Unevaluated<'a>, +} + +#[derive(SessionDiagnostic)] +#[help] +#[diag(trait_selection::auto_deref_reached_recursion_limit, code = "E0055")] +pub struct AutoDerefReachedRecursionLimit<'a> { + #[primary_span] + #[label] + pub span: Span, + pub ty: Ty<'a>, + pub suggested_limit: Limit, + pub crate_name: Symbol, +} + +#[derive(SessionDiagnostic)] +#[diag(trait_selection::empty_on_clause_in_rustc_on_unimplemented, code = "E0232")] +pub struct EmptyOnClauseInOnUnimplemented { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(trait_selection::invalid_on_clause_in_rustc_on_unimplemented, code = "E0232")] +pub struct InvalidOnClauseInOnUnimplemented { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(trait_selection::no_value_in_rustc_on_unimplemented, code = "E0232")] +#[note] +pub struct NoValueInOnUnimplemented { + #[primary_span] + #[label] + pub span: Span, +} + +pub struct NegativePositiveConflict<'a> { + pub impl_span: Span, + pub trait_desc: &'a str, + pub self_desc: &'a Option, + pub negative_impl_span: Result, + pub positive_impl_span: Result, +} + +impl SessionDiagnostic<'_> for NegativePositiveConflict<'_> { + fn into_diagnostic( + self, + sess: &ParseSess, + ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> { + let mut diag = sess.struct_err(fluent::trait_selection::negative_positive_conflict); + diag.set_arg("trait_desc", self.trait_desc); + diag.set_arg( + "self_desc", + self.self_desc.clone().map_or_else(|| String::from("none"), |ty| ty), + ); + diag.set_span(self.impl_span); + diag.code(rustc_errors::error_code!(E0751)); + match self.negative_impl_span { + Ok(span) => { + diag.span_label(span, fluent::trait_selection::negative_implementation_here); + } + Err(cname) => { + diag.note(fluent::trait_selection::negative_implementation_in_crate); + diag.set_arg("negative_impl_cname", cname.to_string()); + } + } + match self.positive_impl_span { + Ok(span) => { + diag.span_label(span, fluent::trait_selection::positive_implementation_here); + } + Err(cname) => { + diag.note(fluent::trait_selection::positive_implementation_in_crate); + diag.set_arg("positive_impl_cname", cname.to_string()); + } + } + diag + } +} diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index 77cc2c164c34c..f039b1fca1817 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -37,5 +37,6 @@ extern crate rustc_middle; extern crate smallvec; pub mod autoderef; +pub mod errors; pub mod infer; pub mod traits; diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 4bab99355012e..1223c7ced7abc 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -3,6 +3,7 @@ use super::*; +use crate::errors::UnableToConstructConstantValue; use crate::infer::region_constraints::{Constraint, RegionConstraintData}; use crate::infer::InferCtxt; use crate::traits::project::ProjectAndUnifyResult; @@ -830,8 +831,11 @@ impl<'tcx> AutoTraitFinder<'tcx> { Ok(None) => { let tcx = self.tcx; let def_id = unevaluated.def.did; - let reported = tcx.sess.struct_span_err(tcx.def_span(def_id), &format!("unable to construct a constant value for the unevaluated constant {:?}", unevaluated)).emit(); - + let reported = + tcx.sess.emit_err(UnableToConstructConstantValue { + span: tcx.def_span(def_id), + unevaluated, + }); Err(ErrorHandled::Reported(reported)) } Err(err) => Err(err), diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index e11ea7751aa73..14e078096783e 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -23,6 +23,7 @@ mod structural_match; mod util; pub mod wf; +use crate::errors::DumpVTableEntries; use crate::infer::outlives::env::OutlivesEnvironment; use crate::infer::{InferCtxt, TyCtxtInferExt}; use crate::traits::error_reporting::InferCtxtExt as _; @@ -763,8 +764,11 @@ fn dump_vtable_entries<'tcx>( trait_ref: ty::PolyTraitRef<'tcx>, entries: &[VtblEntry<'tcx>], ) { - let msg = format!("vtable entries for `{}`: {:#?}", trait_ref, entries); - tcx.sess.struct_span_err(sp, &msg).emit(); + tcx.sess.emit_err(DumpVTableEntries { + span: sp, + trait_ref, + entries: format!("{:#?}", entries), + }); } fn own_existential_vtable_entries<'tcx>( diff --git a/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs index 9227bbf011dbf..3d8840e9e7421 100644 --- a/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs @@ -8,6 +8,10 @@ use rustc_parse_format::{ParseMode, Parser, Piece, Position}; use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::{Span, DUMMY_SP}; +use crate::errors::{ + EmptyOnClauseInOnUnimplemented, InvalidOnClauseInOnUnimplemented, NoValueInOnUnimplemented, +}; + #[derive(Clone, Debug)] pub struct OnUnimplementedFormatString(Symbol); @@ -35,21 +39,6 @@ pub struct OnUnimplementedNote { pub append_const_msg: Option>, } -fn parse_error( - tcx: TyCtxt<'_>, - span: Span, - message: &str, - label: &str, - note: Option<&str>, -) -> ErrorGuaranteed { - let mut diag = struct_span_err!(tcx.sess, span, E0232, "{}", message); - diag.span_label(span, label); - if let Some(note) = note { - diag.note(note); - } - diag.emit() -} - impl<'tcx> OnUnimplementedDirective { fn parse( tcx: TyCtxt<'tcx>, @@ -70,25 +59,9 @@ impl<'tcx> OnUnimplementedDirective { } else { let cond = item_iter .next() - .ok_or_else(|| { - parse_error( - tcx, - span, - "empty `on`-clause in `#[rustc_on_unimplemented]`", - "empty on-clause here", - None, - ) - })? + .ok_or_else(|| tcx.sess.emit_err(EmptyOnClauseInOnUnimplemented { span }))? .meta_item() - .ok_or_else(|| { - parse_error( - tcx, - span, - "invalid `on`-clause in `#[rustc_on_unimplemented]`", - "invalid on-clause here", - None, - ) - })?; + .ok_or_else(|| tcx.sess.emit_err(InvalidOnClauseInOnUnimplemented { span }))?; attr::eval_condition(cond, &tcx.sess.parse_sess, Some(tcx.features()), &mut |cfg| { if let Some(value) = cfg.value && let Err(guar) = parse_value(value) { errored = Some(guar); @@ -150,13 +123,7 @@ impl<'tcx> OnUnimplementedDirective { } // nothing found - parse_error( - tcx, - item.span(), - "this attribute must have a valid value", - "expected value here", - Some(r#"eg `#[rustc_on_unimplemented(message="foo")]`"#), - ); + tcx.sess.emit_err(NoValueInOnUnimplemented { span: item.span() }); } if let Some(reported) = errored { diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index 0f76fef0eee22..7d299e30ae041 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs @@ -12,6 +12,7 @@ pub mod specialization_graph; use specialization_graph::GraphExt; +use crate::errors::NegativePositiveConflict; use crate::infer::{InferCtxt, InferOk, TyCtxtInferExt}; use crate::traits::select::IntercrateAmbiguityCause; use crate::traits::{self, coherence, FutureCompatOverlapErrorKind, ObligationCause}; @@ -327,35 +328,13 @@ fn report_negative_positive_conflict( positive_impl_def_id: DefId, sg: &mut specialization_graph::Graph, ) { - let impl_span = tcx.def_span(local_impl_def_id); - - let mut err = struct_span_err!( - tcx.sess, - impl_span, - E0751, - "found both positive and negative implementation of trait `{}`{}:", - overlap.trait_desc, - overlap.self_desc.clone().map_or_else(String::new, |ty| format!(" for type `{}`", ty)) - ); - - match tcx.span_of_impl(negative_impl_def_id) { - Ok(span) => { - err.span_label(span, "negative implementation here"); - } - Err(cname) => { - err.note(&format!("negative implementation in crate `{}`", cname)); - } - } - - match tcx.span_of_impl(positive_impl_def_id) { - Ok(span) => { - err.span_label(span, "positive implementation here"); - } - Err(cname) => { - err.note(&format!("positive implementation in crate `{}`", cname)); - } - } - + let mut err = tcx.sess.create_err(NegativePositiveConflict { + impl_span: tcx.def_span(local_impl_def_id), + trait_desc: &overlap.trait_desc, + self_desc: &overlap.self_desc, + negative_impl_span: tcx.span_of_impl(negative_impl_def_id), + positive_impl_span: tcx.span_of_impl(positive_impl_def_id), + }); sg.has_errored = Some(err.emit()); } From 0c4ec5df58201a9215248d6cf68865431b4d3e35 Mon Sep 17 00:00:00 2001 From: est31 Date: Tue, 30 Aug 2022 23:05:51 +0200 Subject: [PATCH 6/7] Also replace the version placeholder in rustc_attr This fixes rustdoc not showing the current version as stabilization version for recently stabilized lang features. --- compiler/rustc_attr/src/builtin.rs | 12 ++++++++++++ compiler/rustc_passes/src/lib_features.rs | 2 +- src/tools/replace-version-placeholder/src/main.rs | 2 +- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index 65edab78ce74e..a8ed510866d89 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -15,6 +15,12 @@ use std::num::NonZeroU32; use crate::session_diagnostics::{self, IncorrectReprFormatGenericCause}; +/// The version placeholder that recently stabilized features contain inside the +/// `since` field of the `#[stable]` attribute. +/// +/// For more, see [this pull request](https://github.com/rust-lang/rust/pull/100591). +pub const VERSION_PLACEHOLDER: &str = "CURRENT_RUSTC_VERSION"; + pub fn is_builtin_attr(attr: &Attribute) -> bool { attr.is_doc_comment() || attr.ident().filter(|ident| is_builtin_attr_name(ident.name)).is_some() } @@ -483,6 +489,12 @@ where } } + if let Some(s) = since && s.as_str() == VERSION_PLACEHOLDER { + let version = option_env!("CFG_VERSION").unwrap_or(""); + let version = version.split(' ').next().unwrap(); + since = Some(Symbol::intern(&version)); + } + match (feature, since) { (Some(feature), Some(since)) => { let level = Stable { since, allowed_through_unstable_modules: false }; diff --git a/compiler/rustc_passes/src/lib_features.rs b/compiler/rustc_passes/src/lib_features.rs index 70b6bfd1e582d..5aac6943eef1e 100644 --- a/compiler/rustc_passes/src/lib_features.rs +++ b/compiler/rustc_passes/src/lib_features.rs @@ -5,6 +5,7 @@ //! collect them instead. use rustc_ast::{Attribute, MetaItemKind}; +use rustc_attr::VERSION_PLACEHOLDER; use rustc_errors::struct_span_err; use rustc_hir::intravisit::Visitor; use rustc_middle::hir::nested_filter; @@ -54,7 +55,6 @@ impl<'tcx> LibFeatureCollector<'tcx> { } } } - const VERSION_PLACEHOLDER: &str = "CURRENT_RUSTC_VERSION"; if let Some(s) = since && s.as_str() == VERSION_PLACEHOLDER { let version = option_env!("CFG_VERSION").unwrap_or(""); diff --git a/src/tools/replace-version-placeholder/src/main.rs b/src/tools/replace-version-placeholder/src/main.rs index 146e53f2e9a0f..33b35d0541576 100644 --- a/src/tools/replace-version-placeholder/src/main.rs +++ b/src/tools/replace-version-placeholder/src/main.rs @@ -14,7 +14,7 @@ fn main() { walk::filter_dirs(path) // We exempt these as they require the placeholder // for their operation - || path.ends_with("compiler/rustc_passes/src/lib_features.rs") + || path.ends_with("compiler/rustc_attr/src/builtin.rs") || path.ends_with("src/tools/tidy/src/features/version.rs") || path.ends_with("src/tools/replace-version-placeholder") }, From 017cfebcac9b04e34a782a2926af723026da3c03 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 2 Sep 2022 15:09:59 +0200 Subject: [PATCH 7/7] Remove unused .toggle-label CSS rule --- src/librustdoc/html/static/css/rustdoc.css | 6 ------ src/librustdoc/html/static/css/themes/ayu.css | 1 - src/librustdoc/html/static/css/themes/dark.css | 1 - src/librustdoc/html/static/css/themes/light.css | 1 - 4 files changed, 9 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index abbfecd849781..7409be2dbb9be 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -1242,12 +1242,6 @@ h3.variant { margin-left: 24px; } -.toggle-label { - display: inline-block; - margin-left: 4px; - margin-top: 3px; -} - :target > code, :target > .code-header { opacity: 1; } diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css index e301a793282eb..4f6dd645c2725 100644 --- a/src/librustdoc/html/static/css/themes/ayu.css +++ b/src/librustdoc/html/static/css/themes/ayu.css @@ -242,7 +242,6 @@ a.test-arrow:hover { color: #c5c5c5; } -.toggle-label, .code-attribute { color: #999; } diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css index d5cd47c3e19d5..a37bbac5306a4 100644 --- a/src/librustdoc/html/static/css/themes/dark.css +++ b/src/librustdoc/html/static/css/themes/dark.css @@ -197,7 +197,6 @@ a.test-arrow:hover{ background-color: #4e8bca; } -.toggle-label, .code-attribute { color: #999; } diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css index cff70268144f3..3d8e866fdc618 100644 --- a/src/librustdoc/html/static/css/themes/light.css +++ b/src/librustdoc/html/static/css/themes/light.css @@ -182,7 +182,6 @@ a.test-arrow:hover{ background-color: #4e8bca; } -.toggle-label, .code-attribute { color: #999; }