From 137f20c11265ea70e3ed3ed7798662b9abfbaad2 Mon Sep 17 00:00:00 2001 From: Nathan Stocks Date: Thu, 18 Aug 2022 15:51:47 -0600 Subject: [PATCH 01/24] rebased: convert rustc_monomorphize errors to SessionDiagnostic --- Cargo.lock | 10 ++- .../locales/en-US/monomorphize.ftl | 19 +++++ compiler/rustc_error_messages/src/lib.rs | 1 + compiler/rustc_monomorphize/Cargo.toml | 4 +- compiler/rustc_monomorphize/src/collector.rs | 65 ++++++++------- compiler/rustc_monomorphize/src/errors.rs | 81 +++++++++++++++++++ compiler/rustc_monomorphize/src/lib.rs | 3 + .../src/partitioning/mod.rs | 10 ++- .../rustc_monomorphize/src/polymorphize.rs | 16 +++- src/tools/cargo | 2 +- 10 files changed, 170 insertions(+), 41 deletions(-) create mode 100644 compiler/rustc_error_messages/locales/en-US/monomorphize.ftl create mode 100644 compiler/rustc_monomorphize/src/errors.rs diff --git a/Cargo.lock b/Cargo.lock index 9464c87fc728b..1c1869a470c4d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4253,8 +4253,10 @@ name = "rustc_monomorphize" version = "0.0.0" dependencies = [ "rustc_data_structures", + "rustc_errors", "rustc_hir", "rustc_index", + "rustc_macros", "rustc_middle", "rustc_session", "rustc_span", @@ -4995,9 +4997,9 @@ checksum = "da73c8f77aebc0e40c300b93f0a5f1bece7a248a36eee287d4e095f35c7b7d6e" [[package]] name = "snapbox" -version = "0.3.3" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d199ccf8f606592df2d145db26f2aa45344e23c64b074cc5a4047f1d99b0f7" +checksum = "767a1d5da232b6959cd1bd5c9e8db8a7cce09c3038e89deedb49a549a2aefd93" dependencies = [ "concolor", "content_inspector", @@ -5013,9 +5015,9 @@ dependencies = [ [[package]] name = "snapbox-macros" -version = "0.3.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a253e6f894cfa440cba00600a249fa90869d8e0ec45ab274a456e043a0ce8f2" +checksum = "c01dea7e04cbb27ef4c86e9922184608185f7cd95c1763bc30d727cda4a5e930" [[package]] name = "socket2" diff --git a/compiler/rustc_error_messages/locales/en-US/monomorphize.ftl b/compiler/rustc_error_messages/locales/en-US/monomorphize.ftl new file mode 100644 index 0000000000000..4c67c6f5cb46d --- /dev/null +++ b/compiler/rustc_error_messages/locales/en-US/monomorphize.ftl @@ -0,0 +1,19 @@ +monomorphize_recursion_limit = + reached the recursion limit while instantiating `{$shrunk}` + .note = `{$def_path_str}` defined here + +monomorphize_written_to_path = the full type name has been written to '{$path}' + +monomorphize_type_length_limit = reached the type-length limit while instantiating `{$shrunk}` + +monomorphize_consider_type_length_limit = + consider adding a `#![type_length_limit="{$type_length}"]` attribute to your crate + +monomorphize_fatal_error = {$error_message} + +monomorphize_unused_generic_params = item has unused generic parameters + +monomorphize_large_assignments = + moving {$size} bytes + .label = value moved from here + .note = The current maximum size is {$limit}, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]` diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index 2d001d445be02..3f3f99fa9c04d 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -39,6 +39,7 @@ fluent_messages! { expand => "../locales/en-US/expand.ftl", interface => "../locales/en-US/interface.ftl", lint => "../locales/en-US/lint.ftl", + monomorphize => "../locales/en-US/monomorphize.ftl", parser => "../locales/en-US/parser.ftl", passes => "../locales/en-US/passes.ftl", plugin_impl => "../locales/en-US/plugin_impl.ftl", diff --git a/compiler/rustc_monomorphize/Cargo.toml b/compiler/rustc_monomorphize/Cargo.toml index 41ba4d4b64a34..59ca04ec868d1 100644 --- a/compiler/rustc_monomorphize/Cargo.toml +++ b/compiler/rustc_monomorphize/Cargo.toml @@ -7,11 +7,13 @@ edition = "2021" doctest = false [dependencies] -smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } +smallvec = { version = "1.8.1", features = [ "union", "may_dangle" ] } tracing = "0.1" rustc_data_structures = { path = "../rustc_data_structures" } +rustc_errors = { path = "../rustc_errors" } rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } +rustc_macros = { path = "../rustc_macros" } rustc_middle = { path = "../rustc_middle" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 82ef16a7f72fc..8f0d98563af2c 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -207,6 +207,8 @@ use std::iter; use std::ops::Range; use std::path::PathBuf; +use crate::errors::{FatalError, LargeAssignmentsLint, RecursionLimit, TypeLengthLimit}; + #[derive(PartialEq)] pub enum MonoItemCollectionMode { Eager, @@ -604,17 +606,24 @@ fn check_recursion_limit<'tcx>( // more than the recursion limit is assumed to be causing an // infinite expansion. if !recursion_limit.value_within_limit(adjusted_recursion_depth) { + let def_span = tcx.def_span(def_id); + let def_path_str = tcx.def_path_str(def_id); let (shrunk, written_to_path) = shrunk_instance_name(tcx, &instance, 32, 32); - let error = format!("reached the recursion limit while instantiating `{}`", shrunk); - let mut err = tcx.sess.struct_span_fatal(span, &error); - err.span_note( - tcx.def_span(def_id), - &format!("`{}` defined here", tcx.def_path_str(def_id)), - ); - if let Some(path) = written_to_path { - err.note(&format!("the full type name has been written to '{}'", path.display())); - } - err.emit() + let mut path = PathBuf::new(); + let was_written = if written_to_path.is_some() { + path = written_to_path.unwrap(); + Some(()) + } else { + None + }; + tcx.sess.emit_fatal(RecursionLimit { + span, + shrunk, + def_span, + def_path_str, + was_written, + path, + }); } recursion_depths.insert(def_id, recursion_depth + 1); @@ -642,16 +651,15 @@ fn check_type_length_limit<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) { // Bail out in these cases to avoid that bad user experience. if !tcx.type_length_limit().value_within_limit(type_length) { let (shrunk, written_to_path) = shrunk_instance_name(tcx, &instance, 32, 32); - let msg = format!("reached the type-length limit while instantiating `{}`", shrunk); - let mut diag = tcx.sess.struct_span_fatal(tcx.def_span(instance.def_id()), &msg); - if let Some(path) = written_to_path { - diag.note(&format!("the full type name has been written to '{}'", path.display())); - } - diag.help(&format!( - "consider adding a `#![type_length_limit=\"{}\"]` attribute to your crate", - type_length - )); - diag.emit() + let span = tcx.def_span(instance.def_id()); + let mut path = PathBuf::new(); + let was_written = if written_to_path.is_some() { + path = written_to_path.unwrap(); + Some(()) + } else { + None + }; + tcx.sess.emit_fatal(TypeLengthLimit { span, shrunk, was_written, path, type_length }); } } @@ -914,17 +922,16 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { // but correct span? This would make the lint at least accept crate-level lint attributes. return; }; - self.tcx.struct_span_lint_hir( + self.tcx.emit_spanned_lint( LARGE_ASSIGNMENTS, lint_root, source_info.span, - |lint| { - let mut err = lint.build(&format!("moving {} bytes", layout.size.bytes())); - err.span_label(source_info.span, "value moved from here"); - err.note(&format!(r#"The current maximum size is {}, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`"#, limit.bytes())); - err.emit(); + LargeAssignmentsLint { + span: source_info.span, + size: layout.size.bytes(), + limit: limit.bytes(), }, - ); + ) } } } @@ -1321,7 +1328,9 @@ impl<'v> RootCollector<'_, 'v> { let start_def_id = match self.tcx.lang_items().require(LangItem::Start) { Ok(s) => s, - Err(err) => self.tcx.sess.fatal(&err), + Err(error_message) => { + self.tcx.sess.emit_fatal(FatalError { error_message: error_message.clone() }); + } }; let main_ret_ty = self.tcx.fn_sig(main_def_id).output(); diff --git a/compiler/rustc_monomorphize/src/errors.rs b/compiler/rustc_monomorphize/src/errors.rs new file mode 100644 index 0000000000000..62ebac97136ce --- /dev/null +++ b/compiler/rustc_monomorphize/src/errors.rs @@ -0,0 +1,81 @@ +use std::path::PathBuf; + +use rustc_errors::ErrorGuaranteed; +use rustc_macros::{LintDiagnostic, SessionDiagnostic}; +use rustc_session::SessionDiagnostic; +// use rustc_session::SessionDiagnostic; +use rustc_span::Span; + +#[derive(SessionDiagnostic)] +#[diag(monomorphize::recursion_limit)] +pub struct RecursionLimit { + #[primary_span] + pub span: Span, + pub shrunk: String, + #[note] + pub def_span: Span, + pub def_path_str: String, + #[note(monomorphize::written_to_path)] + pub was_written: Option<()>, + pub path: PathBuf, +} + +#[derive(SessionDiagnostic)] +#[diag(monomorphize::type_length_limit)] +#[help(monomorphize::consider_type_length_limit)] +pub struct TypeLengthLimit { + #[primary_span] + pub span: Span, + pub shrunk: String, + #[note(monomorphize::written_to_path)] + pub was_written: Option<()>, + pub path: PathBuf, + pub type_length: usize, +} + +#[derive(SessionDiagnostic)] +#[diag(monomorphize::fatal_error)] +pub struct FatalError { + pub error_message: String, +} + +#[derive(SessionDiagnostic)] +#[diag(monomorphize::fatal_error)] +pub struct SpanFatalError { + #[primary_span] + pub span: Span, + pub error_message: String, +} + +pub struct UnusedGenericParams { + pub span: Span, + pub param_spans: Vec, + pub param_names: Vec, +} + +impl SessionDiagnostic<'_> for UnusedGenericParams { + fn into_diagnostic( + self, + sess: &'_ rustc_session::parse::ParseSess, + ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> { + let mut diag = sess.struct_err(rustc_errors::fluent::monomorphize::unused_generic_params); + diag.set_span(self.span); + for (span, name) in self.param_spans.into_iter().zip(self.param_names) { + // FIXME: I can figure out how to do a label with a fluent string with a fixed message, + // or a label with a dynamic value in a hard-coded string, but I haven't figured out + // how to combine the two. šŸ˜¢ + diag.span_label(span, format!("generic parameter `{}` is unused", name)); + } + diag + } +} + +#[derive(LintDiagnostic)] +#[diag(monomorphize::large_assignments)] +#[note] +pub struct LargeAssignmentsLint { + #[label] + pub span: Span, + pub size: u64, + pub limit: u64, +} diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs index ef4560b5ec48e..d64de44705bb2 100644 --- a/compiler/rustc_monomorphize/src/lib.rs +++ b/compiler/rustc_monomorphize/src/lib.rs @@ -3,6 +3,8 @@ #![feature(let_else)] #![recursion_limit = "256"] #![allow(rustc::potential_query_instability)] +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate tracing; @@ -16,6 +18,7 @@ use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, Ty, TyCtxt}; mod collector; +mod errors; mod partitioning; mod polymorphize; mod util; diff --git a/compiler/rustc_monomorphize/src/partitioning/mod.rs b/compiler/rustc_monomorphize/src/partitioning/mod.rs index ff2d386932858..d88b7e0a81360 100644 --- a/compiler/rustc_monomorphize/src/partitioning/mod.rs +++ b/compiler/rustc_monomorphize/src/partitioning/mod.rs @@ -108,6 +108,7 @@ use rustc_span::symbol::Symbol; use crate::collector::InliningMap; use crate::collector::{self, MonoItemCollectionMode}; +use crate::errors::{FatalError, SpanFatalError}; pub struct PartitioningCx<'a, 'tcx> { tcx: TyCtxt<'tcx>, @@ -149,7 +150,10 @@ fn get_partitioner<'tcx>(tcx: TyCtxt<'tcx>) -> Box> { match strategy { "default" => Box::new(default::DefaultPartitioning), - _ => tcx.sess.fatal("unknown partitioning strategy"), + _ => { + let error_message = "unknown partitioning strategy".to_string(); + tcx.sess.emit_fatal(FatalError { error_message: error_message.clone() }); + } } } @@ -334,9 +338,9 @@ where let error_message = format!("symbol `{}` is already defined", sym1); if let Some(span) = span { - tcx.sess.span_fatal(span, &error_message) + tcx.sess.emit_fatal(SpanFatalError { span, error_message: error_message.clone() }); } else { - tcx.sess.fatal(&error_message) + tcx.sess.emit_fatal(FatalError { error_message: error_message.clone() }); } } } diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs index 394843e510d21..88f8e24fbd529 100644 --- a/compiler/rustc_monomorphize/src/polymorphize.rs +++ b/compiler/rustc_monomorphize/src/polymorphize.rs @@ -22,6 +22,8 @@ use rustc_span::symbol::sym; use std::convert::TryInto; use std::ops::ControlFlow; +use crate::errors::UnusedGenericParams; + /// Provide implementations of queries relating to polymorphization analysis. pub fn provide(providers: &mut Providers) { providers.unused_generic_params = unused_generic_params; @@ -206,22 +208,28 @@ fn emit_unused_generic_params_error<'tcx>( _ => tcx.def_span(def_id), }; - let mut err = tcx.sess.struct_span_err(fn_span, "item has unused generic parameters"); - + let mut param_spans = Vec::new(); + let mut param_names = Vec::new(); let mut next_generics = Some(generics); while let Some(generics) = next_generics { for param in &generics.params { if unused_parameters.contains(param.index).unwrap_or(false) { debug!(?param); let def_span = tcx.def_span(param.def_id); - err.span_label(def_span, &format!("generic parameter `{}` is unused", param.name)); + // šŸ¤” The docs say + // + // Any attribute applied to a Vec will be repeated for each element of the vector. + // + // But they don't say what template variable to use to substitute each value into the message!? + param_spans.push(def_span); + param_names.push(param.name.to_string()); } } next_generics = generics.parent.map(|did| tcx.generics_of(did)); } - err.emit(); + tcx.sess.emit_err(UnusedGenericParams { span: fn_span, param_spans, param_names }); } /// Visitor used to aggregate generic parameter uses. diff --git a/src/tools/cargo b/src/tools/cargo index 6da726708a440..9809f8ff33c2b 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 6da726708a4406f31f996d813790818dce837161 +Subproject commit 9809f8ff33c2b998919fd0432c626f0f7323697a From 40f44736e805d0576918bb7679e2737a704590f1 Mon Sep 17 00:00:00 2001 From: Nathan Stocks Date: Tue, 23 Aug 2022 11:20:01 -0600 Subject: [PATCH 02/24] replace some usages of [Span]FatalError with error-specific types --- .../locales/en-US/monomorphize.ftl | 4 ++++ compiler/rustc_monomorphize/src/errors.rs | 20 +++++++++++-------- .../src/partitioning/mod.rs | 13 +++--------- 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/monomorphize.ftl b/compiler/rustc_error_messages/locales/en-US/monomorphize.ftl index 4c67c6f5cb46d..48ddb54b79e79 100644 --- a/compiler/rustc_error_messages/locales/en-US/monomorphize.ftl +++ b/compiler/rustc_error_messages/locales/en-US/monomorphize.ftl @@ -11,6 +11,10 @@ monomorphize_consider_type_length_limit = monomorphize_fatal_error = {$error_message} +monomorphize_unknown_partition_strategy = unknown partitioning strategy + +monomorphize_symbol_already_defined = symbol `{$symbol}` is already defined + monomorphize_unused_generic_params = item has unused generic parameters monomorphize_large_assignments = diff --git a/compiler/rustc_monomorphize/src/errors.rs b/compiler/rustc_monomorphize/src/errors.rs index 62ebac97136ce..fa7655f262425 100644 --- a/compiler/rustc_monomorphize/src/errors.rs +++ b/compiler/rustc_monomorphize/src/errors.rs @@ -39,14 +39,6 @@ pub struct FatalError { pub error_message: String, } -#[derive(SessionDiagnostic)] -#[diag(monomorphize::fatal_error)] -pub struct SpanFatalError { - #[primary_span] - pub span: Span, - pub error_message: String, -} - pub struct UnusedGenericParams { pub span: Span, pub param_spans: Vec, @@ -79,3 +71,15 @@ pub struct LargeAssignmentsLint { pub size: u64, pub limit: u64, } + +#[derive(SessionDiagnostic)] +#[diag(monomorphize::unknown_partition_strategy)] +pub struct UnknownPartitionStrategy; + +#[derive(SessionDiagnostic)] +#[diag(monomorphize::symbol_already_defined)] +pub struct SymbolAlreadyDefined { + #[primary_span] + pub span: Option, + pub symbol: String, +} diff --git a/compiler/rustc_monomorphize/src/partitioning/mod.rs b/compiler/rustc_monomorphize/src/partitioning/mod.rs index d88b7e0a81360..3d9197c7549c7 100644 --- a/compiler/rustc_monomorphize/src/partitioning/mod.rs +++ b/compiler/rustc_monomorphize/src/partitioning/mod.rs @@ -108,7 +108,7 @@ use rustc_span::symbol::Symbol; use crate::collector::InliningMap; use crate::collector::{self, MonoItemCollectionMode}; -use crate::errors::{FatalError, SpanFatalError}; +use crate::errors::{SymbolAlreadyDefined, UnknownPartitionStrategy}; pub struct PartitioningCx<'a, 'tcx> { tcx: TyCtxt<'tcx>, @@ -151,8 +151,7 @@ fn get_partitioner<'tcx>(tcx: TyCtxt<'tcx>) -> Box> { match strategy { "default" => Box::new(default::DefaultPartitioning), _ => { - let error_message = "unknown partitioning strategy".to_string(); - tcx.sess.emit_fatal(FatalError { error_message: error_message.clone() }); + tcx.sess.emit_fatal(UnknownPartitionStrategy); } } } @@ -335,13 +334,7 @@ where (span1, span2) => span1.or(span2), }; - let error_message = format!("symbol `{}` is already defined", sym1); - - if let Some(span) = span { - tcx.sess.emit_fatal(SpanFatalError { span, error_message: error_message.clone() }); - } else { - tcx.sess.emit_fatal(FatalError { error_message: error_message.clone() }); - } + tcx.sess.emit_fatal(SymbolAlreadyDefined { span, symbol: sym1.to_string() }); } } } From 33cbbc2789304714f8c9da1370c5f2adb74addda Mon Sep 17 00:00:00 2001 From: Nathan Stocks Date: Tue, 23 Aug 2022 13:01:51 -0600 Subject: [PATCH 03/24] remove stray comment --- compiler/rustc_monomorphize/src/errors.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/compiler/rustc_monomorphize/src/errors.rs b/compiler/rustc_monomorphize/src/errors.rs index fa7655f262425..c53ef20c7f888 100644 --- a/compiler/rustc_monomorphize/src/errors.rs +++ b/compiler/rustc_monomorphize/src/errors.rs @@ -3,7 +3,6 @@ use std::path::PathBuf; use rustc_errors::ErrorGuaranteed; use rustc_macros::{LintDiagnostic, SessionDiagnostic}; use rustc_session::SessionDiagnostic; -// use rustc_session::SessionDiagnostic; use rustc_span::Span; #[derive(SessionDiagnostic)] From e9142473dfca7e274d24695e86f9100b020acab5 Mon Sep 17 00:00:00 2001 From: Nathan Stocks Date: Wed, 24 Aug 2022 15:27:39 -0600 Subject: [PATCH 04/24] bless the change in note/help order due to migrating to SessionDiagnostic --- src/test/ui/type_length_limit.stderr | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/ui/type_length_limit.stderr b/src/test/ui/type_length_limit.stderr index 1508b84c1b6e7..84ac48b1e77b4 100644 --- a/src/test/ui/type_length_limit.stderr +++ b/src/test/ui/type_length_limit.stderr @@ -4,8 +4,8 @@ error: reached the type-length limit while instantiating `std::mem::drop::(_x: T) {} | ^^^^^^^^^^^^^^^^^^^^^ | - = note: the full type name has been written to '$TEST_BUILD_DIR/type_length_limit/type_length_limit.long-type.txt' = help: consider adding a `#![type_length_limit="8"]` attribute to your crate + = note: the full type name has been written to '$TEST_BUILD_DIR/type_length_limit/type_length_limit.long-type.txt' error: reached the type-length limit while instantiating `<[closure@std::rt::lang_start<()...e<()>>::call_once - shim(vtable)` --> $SRC_DIR/core/src/ops/function.rs:LL:COL @@ -13,8 +13,8 @@ error: reached the type-length limit while instantiating `<[closure@std::rt::lan LL | extern "rust-call" fn call_once(self, args: Args) -> Self::Output; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: the full type name has been written to '$TEST_BUILD_DIR/type_length_limit/type_length_limit.long-type.txt' = help: consider adding a `#![type_length_limit="8"]` attribute to your crate + = note: the full type name has been written to '$TEST_BUILD_DIR/type_length_limit/type_length_limit.long-type.txt' error: aborting due to 2 previous errors From 30c750665517756484b0154b1b33a1256e614e6b Mon Sep 17 00:00:00 2001 From: Nathan Stocks Date: Wed, 24 Aug 2022 16:28:56 -0600 Subject: [PATCH 05/24] allow non-monomorphize modules to access hard-coded error message through new struct, use fluent message in monomorphize --- .../rustc_error_messages/locales/en-US/monomorphize.ftl | 3 +++ compiler/rustc_hir/src/errors.rs | 9 +++++++++ compiler/rustc_hir/src/lang_items.rs | 7 ++++--- compiler/rustc_hir/src/lib.rs | 1 + compiler/rustc_middle/src/middle/lang_items.rs | 6 +++--- compiler/rustc_monomorphize/src/collector.rs | 8 +++++--- compiler/rustc_monomorphize/src/errors.rs | 6 +++--- compiler/rustc_typeck/src/coherence/builtin.rs | 2 +- 8 files changed, 29 insertions(+), 13 deletions(-) create mode 100644 compiler/rustc_hir/src/errors.rs diff --git a/compiler/rustc_error_messages/locales/en-US/monomorphize.ftl b/compiler/rustc_error_messages/locales/en-US/monomorphize.ftl index 48ddb54b79e79..42c84fdd2d14b 100644 --- a/compiler/rustc_error_messages/locales/en-US/monomorphize.ftl +++ b/compiler/rustc_error_messages/locales/en-US/monomorphize.ftl @@ -21,3 +21,6 @@ monomorphize_large_assignments = moving {$size} bytes .label = value moved from here .note = The current maximum size is {$limit}, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]` + +monomorphize_requires_lang_item = + requires `{$lang_item}` lang_item diff --git a/compiler/rustc_hir/src/errors.rs b/compiler/rustc_hir/src/errors.rs new file mode 100644 index 0000000000000..7ed09d3f29366 --- /dev/null +++ b/compiler/rustc_hir/src/errors.rs @@ -0,0 +1,9 @@ +use crate::LangItem; + +pub struct LangItemError(pub LangItem); + +impl ToString for LangItemError { + fn to_string(&self) -> String { + format!("requires `{}` lang_item", self.0.name()) + } +} diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index c337be12ae492..0c01326d0032a 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -8,6 +8,7 @@ //! * Functions called by the compiler itself. use crate::def_id::DefId; +use crate::errors::LangItemError; use crate::{MethodKind, Target}; use rustc_ast as ast; @@ -115,9 +116,9 @@ macro_rules! language_item_table { /// Requires that a given `LangItem` was bound and returns the corresponding `DefId`. /// If it wasn't bound, e.g. due to a missing `#[lang = ""]`, - /// returns an error message as a string. - pub fn require(&self, it: LangItem) -> Result { - self.items[it as usize].ok_or_else(|| format!("requires `{}` lang_item", it.name())) + /// returns an error encapsulating the `LangItem`. + pub fn require(&self, it: LangItem) -> Result { + self.items[it as usize].ok_or_else(|| LangItemError(it)) } /// Returns the [`DefId`]s of all lang items in a group. diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs index 7097f998bebda..092029ef09ec8 100644 --- a/compiler/rustc_hir/src/lib.rs +++ b/compiler/rustc_hir/src/lib.rs @@ -27,6 +27,7 @@ pub mod def; pub mod def_path_hash_map; pub mod definitions; pub mod diagnostic_items; +pub mod errors; pub use rustc_span::def_id; mod hir; pub mod hir_id; diff --git a/compiler/rustc_middle/src/middle/lang_items.rs b/compiler/rustc_middle/src/middle/lang_items.rs index cc9706f2d867c..31c20fa14aaf5 100644 --- a/compiler/rustc_middle/src/middle/lang_items.rs +++ b/compiler/rustc_middle/src/middle/lang_items.rs @@ -18,11 +18,11 @@ impl<'tcx> TyCtxt<'tcx> { /// Returns the `DefId` for a given `LangItem`. /// If not found, fatally aborts compilation. pub fn require_lang_item(self, lang_item: LangItem, span: Option) -> DefId { - self.lang_items().require(lang_item).unwrap_or_else(|msg| { + self.lang_items().require(lang_item).unwrap_or_else(|err| { if let Some(span) = span { - self.sess.span_fatal(span, &msg) + self.sess.span_fatal(span, err.to_string()) } else { - self.sess.fatal(&msg) + self.sess.fatal(err.to_string()) } }) } diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 8f0d98563af2c..e0a14738b9548 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -207,7 +207,7 @@ use std::iter; use std::ops::Range; use std::path::PathBuf; -use crate::errors::{FatalError, LargeAssignmentsLint, RecursionLimit, TypeLengthLimit}; +use crate::errors::{LargeAssignmentsLint, RecursionLimit, RequiresLangItem, TypeLengthLimit}; #[derive(PartialEq)] pub enum MonoItemCollectionMode { @@ -1328,8 +1328,10 @@ impl<'v> RootCollector<'_, 'v> { let start_def_id = match self.tcx.lang_items().require(LangItem::Start) { Ok(s) => s, - Err(error_message) => { - self.tcx.sess.emit_fatal(FatalError { error_message: error_message.clone() }); + Err(lang_item_err) => { + self.tcx + .sess + .emit_fatal(RequiresLangItem { lang_item: lang_item_err.0.name().to_string() }); } }; let main_ret_ty = self.tcx.fn_sig(main_def_id).output(); diff --git a/compiler/rustc_monomorphize/src/errors.rs b/compiler/rustc_monomorphize/src/errors.rs index c53ef20c7f888..77b6cfa1f69f8 100644 --- a/compiler/rustc_monomorphize/src/errors.rs +++ b/compiler/rustc_monomorphize/src/errors.rs @@ -33,9 +33,9 @@ pub struct TypeLengthLimit { } #[derive(SessionDiagnostic)] -#[diag(monomorphize::fatal_error)] -pub struct FatalError { - pub error_message: String, +#[diag(monomorphize::requires_lang_item)] +pub struct RequiresLangItem { + pub lang_item: String, } pub struct UnusedGenericParams { diff --git a/compiler/rustc_typeck/src/coherence/builtin.rs b/compiler/rustc_typeck/src/coherence/builtin.rs index 2467a81638f75..d08c0d4dbb72a 100644 --- a/compiler/rustc_typeck/src/coherence/builtin.rs +++ b/compiler/rustc_typeck/src/coherence/builtin.rs @@ -359,7 +359,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn let coerce_unsized_trait = tcx.require_lang_item(LangItem::CoerceUnsized, Some(span)); let unsize_trait = tcx.lang_items().require(LangItem::Unsize).unwrap_or_else(|err| { - tcx.sess.fatal(&format!("`CoerceUnsized` implementation {}", err)); + tcx.sess.fatal(&format!("`CoerceUnsized` implementation {}", err.to_string())); }); let source = tcx.type_of(impl_did); From 6cdfdd02f65da9d11742e15cd3d1176bb2ab3858 Mon Sep 17 00:00:00 2001 From: Nathan Stocks Date: Wed, 24 Aug 2022 16:52:46 -0600 Subject: [PATCH 06/24] adjust to new error value --- compiler/rustc_codegen_cranelift/src/base.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index 44c34d6c8cb79..3a2875e5d27d5 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -925,8 +925,11 @@ pub(crate) fn codegen_panic_inner<'tcx>( args: &[Value], span: Span, ) { - let def_id = - fx.tcx.lang_items().require(lang_item).unwrap_or_else(|s| fx.tcx.sess.span_fatal(span, &s)); + let def_id = fx + .tcx + .lang_items() + .require(lang_item) + .unwrap_or_else(|e| fx.tcx.sess.span_fatal(span, e.to_string())); let instance = Instance::mono(fx.tcx, def_id).polymorphize(fx.tcx); let symbol_name = fx.tcx.symbol_name(instance).name; From 82d609c8dfab1b7a1a77de54c1ac27f73778cf10 Mon Sep 17 00:00:00 2001 From: Nathan Stocks Date: Wed, 24 Aug 2022 17:06:18 -0600 Subject: [PATCH 07/24] have LangItemError derive everything LangItem does --- compiler/rustc_hir/src/errors.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_hir/src/errors.rs b/compiler/rustc_hir/src/errors.rs index 7ed09d3f29366..e593ed1044a58 100644 --- a/compiler/rustc_hir/src/errors.rs +++ b/compiler/rustc_hir/src/errors.rs @@ -1,5 +1,6 @@ use crate::LangItem; +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Encodable, Decodable)] pub struct LangItemError(pub LangItem); impl ToString for LangItemError { From 706452eba74026c51e8d0fa30aee2497c69eafc0 Mon Sep 17 00:00:00 2001 From: Luis Cardoso <61982523+LuisCardosoOliveira@users.noreply.github.com> Date: Fri, 19 Aug 2022 15:34:13 +0200 Subject: [PATCH 08/24] translations(rustc_session): migrate the file cgu_reuse_tracker This commit migrates the errors that indicates an incorrect CGU type and the fatal error that indicates that a CGU has not been correctly recorded --- .../locales/en-US/session.ftl | 5 +++ compiler/rustc_error_messages/src/lib.rs | 1 + .../rustc_session/src/cgu_reuse_tracker.rs | 34 ++++++++++++++++--- compiler/rustc_session/src/errors.rs | 22 ++++++++++++ compiler/rustc_session/src/lib.rs | 3 ++ 5 files changed, 60 insertions(+), 5 deletions(-) create mode 100644 compiler/rustc_error_messages/locales/en-US/session.ftl create mode 100644 compiler/rustc_session/src/errors.rs diff --git a/compiler/rustc_error_messages/locales/en-US/session.ftl b/compiler/rustc_error_messages/locales/en-US/session.ftl new file mode 100644 index 0000000000000..71d3abc5e6b7c --- /dev/null +++ b/compiler/rustc_error_messages/locales/en-US/session.ftl @@ -0,0 +1,5 @@ +incorrect_cgu_reuse_type = + CGU-reuse for `{$cgu_user_name}` is `{$actual_reuse}` but should be `{$at_least}``${expected_reuse}` + +cgu_not_recorded = + CGU-reuse for `{$cgu_user_name}` is (mangled: `{$cgu_name}`) was not recorded` \ No newline at end of file diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index 2d001d445be02..2fde301d19dbc 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -37,6 +37,7 @@ fluent_messages! { builtin_macros => "../locales/en-US/builtin_macros.ftl", const_eval => "../locales/en-US/const_eval.ftl", expand => "../locales/en-US/expand.ftl", + session => "../locales/en-US/session.ftl", interface => "../locales/en-US/interface.ftl", lint => "../locales/en-US/lint.ftl", parser => "../locales/en-US/parser.ftl", diff --git a/compiler/rustc_session/src/cgu_reuse_tracker.rs b/compiler/rustc_session/src/cgu_reuse_tracker.rs index dd64e8ab71e7b..88fcbf7c1133a 100644 --- a/compiler/rustc_session/src/cgu_reuse_tracker.rs +++ b/compiler/rustc_session/src/cgu_reuse_tracker.rs @@ -2,8 +2,13 @@ //! compilation. This is used for incremental compilation tests and debug //! output. +use crate::errors::IncorrectCguReuseType; +// use crate::errors::{CguNotRecorded, IncorrectCguReuseType}; use rustc_data_structures::fx::FxHashMap; +use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg}; use rustc_span::{Span, Symbol}; +use std::borrow::Cow; +use std::fmt::{self}; use std::sync::{Arc, Mutex}; use tracing::debug; @@ -14,6 +19,22 @@ pub enum CguReuse { PostLto, } +impl fmt::Display for CguReuse { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match *self { + CguReuse::No => write!(f, "No"), + CguReuse::PreLto => write!(f, "PreLto "), + CguReuse::PostLto => write!(f, "PostLto "), + } + } +} + +impl IntoDiagnosticArg for CguReuse { + fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + DiagnosticArgValue::Str(Cow::Owned(self.to_string())) + } +} + #[derive(Copy, Clone, Debug, PartialEq)] pub enum ComparisonKind { Exact, @@ -99,11 +120,13 @@ impl CguReuseTracker { if error { let at_least = if at_least { "at least " } else { "" }; - let msg = format!( - "CGU-reuse for `{cgu_user_name}` is `{actual_reuse:?}` but \ - should be {at_least}`{expected_reuse:?}`" - ); - diag.span_err(error_span.0, &msg); + IncorrectCguReuseType { + span: error_span.0, + cgu_user_name: &cgu_user_name, + actual_reuse, + expected_reuse, + at_least, + }; } } else { let msg = format!( @@ -111,6 +134,7 @@ impl CguReuseTracker { not recorded" ); diag.span_fatal(error_span.0, &msg) + // CguNotRecorded { cgu_user_name, cgu_name }; } } } diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs new file mode 100644 index 0000000000000..ef78d1c98361b --- /dev/null +++ b/compiler/rustc_session/src/errors.rs @@ -0,0 +1,22 @@ +use crate as rustc_session; +use crate::cgu_reuse_tracker::CguReuse; +use rustc_macros::SessionDiagnostic; +use rustc_span::Span; + +#[derive(SessionDiagnostic)] +#[error(session::incorrect_cgu_reuse_type)] +pub struct IncorrectCguReuseType<'a> { + #[primary_span] + pub span: Span, + pub cgu_user_name: &'a str, + pub actual_reuse: CguReuse, + pub expected_reuse: CguReuse, + pub at_least: &'a str, +} + +// #[derive(SessionDiagnostic)] +// #[fatal(session::cgu_not_recorded)] +// pub struct CguNotRecorded<'a> { +// pub cgu_user_name: &'a str, +// pub cgu_name: &'a str, +// } diff --git a/compiler/rustc_session/src/lib.rs b/compiler/rustc_session/src/lib.rs index 0617bd5fae786..113bd85135eae 100644 --- a/compiler/rustc_session/src/lib.rs +++ b/compiler/rustc_session/src/lib.rs @@ -8,9 +8,12 @@ #![feature(map_many_mut)] #![recursion_limit = "256"] #![allow(rustc::potential_query_instability)] +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate rustc_macros; +pub mod errors; pub mod cgu_reuse_tracker; pub mod utils; From d5262a945246a624113faaadbbdae4ec5013c862 Mon Sep 17 00:00:00 2001 From: Luis Cardoso <61982523+LuisCardosoOliveira@users.noreply.github.com> Date: Mon, 22 Aug 2022 08:28:50 +0200 Subject: [PATCH 09/24] translations(rustc_session): migrate 80% of the file parse.rs This commit migrates around 80% of the parse file to use SsessionDiagnostic We still have to migrate struct_err and struct_warn. --- .../locales/en-US/session.ftl | 14 ++++++++-- .../rustc_session/src/cgu_reuse_tracker.rs | 4 ++- compiler/rustc_session/src/errors.rs | 28 +++++++++++++++++-- compiler/rustc_session/src/lib.rs | 2 -- compiler/rustc_session/src/parse.rs | 21 ++++++++++---- 5 files changed, 55 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/session.ftl b/compiler/rustc_error_messages/locales/en-US/session.ftl index 71d3abc5e6b7c..e94a7b2c1c8e9 100644 --- a/compiler/rustc_error_messages/locales/en-US/session.ftl +++ b/compiler/rustc_error_messages/locales/en-US/session.ftl @@ -1,5 +1,13 @@ -incorrect_cgu_reuse_type = +session_incorrect_cgu_reuse_type = CGU-reuse for `{$cgu_user_name}` is `{$actual_reuse}` but should be `{$at_least}``${expected_reuse}` -cgu_not_recorded = - CGU-reuse for `{$cgu_user_name}` is (mangled: `{$cgu_name}`) was not recorded` \ No newline at end of file +session_cgu_not_recorded = + CGU-reuse for `{$cgu_user_name}` is (mangled: `{$cgu_name}`) was not recorded` + +session_feature_gate_error = {$explain} + +session_feature_diagnostic_for_issue = + see issue #{$n} for more information + +session_feature_diagnostic_help = + add `#![feature({$feature})]` to the crate attributes to enable diff --git a/compiler/rustc_session/src/cgu_reuse_tracker.rs b/compiler/rustc_session/src/cgu_reuse_tracker.rs index 88fcbf7c1133a..0b75a89c4d8a1 100644 --- a/compiler/rustc_session/src/cgu_reuse_tracker.rs +++ b/compiler/rustc_session/src/cgu_reuse_tracker.rs @@ -3,7 +3,6 @@ //! output. use crate::errors::IncorrectCguReuseType; -// use crate::errors::{CguNotRecorded, IncorrectCguReuseType}; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg}; use rustc_span::{Span, Symbol}; @@ -129,11 +128,14 @@ impl CguReuseTracker { }; } } else { + //FIXME: Remove this once PR #100694 that implements `[fatal(..)]` is merged let msg = format!( "CGU-reuse for `{cgu_user_name}` (mangled: `{cgu_name}`) was \ not recorded" ); diag.span_fatal(error_span.0, &msg) + + //FIXME: Uncomment this once PR #100694 that implements `[fatal(..)]` is merged // CguNotRecorded { cgu_user_name, cgu_name }; } } diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index ef78d1c98361b..54e5fe82f5c4d 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -1,10 +1,13 @@ +use std::num::NonZeroU32; + use crate as rustc_session; use crate::cgu_reuse_tracker::CguReuse; +use rustc_errors::MultiSpan; use rustc_macros::SessionDiagnostic; -use rustc_span::Span; +use rustc_span::{Span, Symbol}; #[derive(SessionDiagnostic)] -#[error(session::incorrect_cgu_reuse_type)] +#[diag(session::incorrect_cgu_reuse_type)] pub struct IncorrectCguReuseType<'a> { #[primary_span] pub span: Span, @@ -14,9 +17,30 @@ pub struct IncorrectCguReuseType<'a> { pub at_least: &'a str, } +//FIXME: Uncomment this once PR #100694 that implements `[fatal(..)]` is merged // #[derive(SessionDiagnostic)] // #[fatal(session::cgu_not_recorded)] // pub struct CguNotRecorded<'a> { // pub cgu_user_name: &'a str, // pub cgu_name: &'a str, // } + +#[derive(SessionDiagnostic)] +#[diag(session::feature_gate_error, code = "E0658")] +pub struct FeatureGateError<'a> { + #[primary_span] + pub span: MultiSpan, + pub explain: &'a str, +} + +#[derive(SessionSubdiagnostic)] +#[note(session::feature_diagnostic_for_issue)] +pub struct FeatureDiagnosticForIssue { + pub n: NonZeroU32, +} + +#[derive(SessionSubdiagnostic)] +#[help(session::feature_diagnostic_help)] +pub struct FeatureDiagnosticHelp { + pub feature: Symbol, +} diff --git a/compiler/rustc_session/src/lib.rs b/compiler/rustc_session/src/lib.rs index 113bd85135eae..3f098078173f4 100644 --- a/compiler/rustc_session/src/lib.rs +++ b/compiler/rustc_session/src/lib.rs @@ -8,8 +8,6 @@ #![feature(map_many_mut)] #![recursion_limit = "256"] #![allow(rustc::potential_query_instability)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate rustc_macros; diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index 17866dc6bddcb..ebec754dcffb8 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -2,6 +2,7 @@ //! It also serves as an input to the parser itself. use crate::config::CheckCfg; +use crate::errors::{FeatureDiagnosticForIssue, FeatureDiagnosticHelp, FeatureGateError}; use crate::lint::{ builtin::UNSTABLE_SYNTAX_PRE_EXPANSION, BufferedEarlyLint, BuiltinLintDiagnostics, Lint, LintId, }; @@ -11,7 +12,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::{Lock, Lrc}; use rustc_errors::{emitter::SilentEmitter, ColorConfig, Handler}; use rustc_errors::{ - error_code, fallback_fluent_bundle, Applicability, Diagnostic, DiagnosticBuilder, DiagnosticId, + fallback_fluent_bundle, Applicability, Diagnostic, DiagnosticBuilder, DiagnosticId, DiagnosticMessage, EmissionGuarantee, ErrorGuaranteed, MultiSpan, StashKey, }; use rustc_feature::{find_feature_issue, GateIssue, UnstableFeatures}; @@ -112,7 +113,7 @@ pub fn feature_err_issue<'a>( .map(|err| err.cancel()); } - let mut err = sess.span_diagnostic.struct_span_err_with_code(span, explain, error_code!(E0658)); + let mut err = sess.create_err(FeatureGateError { span, explain }); add_feature_diagnostics_for_issue(&mut err, sess, feature, issue); err } @@ -130,6 +131,8 @@ pub fn feature_warn<'a>(sess: &'a ParseSess, feature: Symbol, span: Span, explai /// /// This variant allows you to control whether it is a library or language feature. /// Almost always, you want to use this for a language feature. If so, prefer `feature_warn`. +#[allow(rustc::diagnostic_outside_of_impl)] +#[allow(rustc::untranslatable_diagnostic)] pub fn feature_warn_issue<'a>( sess: &'a ParseSess, feature: Symbol, @@ -172,14 +175,12 @@ pub fn add_feature_diagnostics_for_issue<'a>( issue: GateIssue, ) { if let Some(n) = find_feature_issue(feature, issue) { - err.note(&format!( - "see issue #{n} for more information" - )); + err.subdiagnostic(FeatureDiagnosticForIssue { n }); } // #23973: do not suggest `#![feature(...)]` if we are in beta/stable if sess.unstable_features.is_nightly_build() { - err.help(&format!("add `#![feature({feature})]` to the crate attributes to enable")); + err.subdiagnostic(FeatureDiagnosticHelp { feature }); } } @@ -372,6 +373,8 @@ impl ParseSess { } #[rustc_lint_diagnostics] + #[allow(rustc::diagnostic_outside_of_impl)] + #[allow(rustc::untranslatable_diagnostic)] pub fn struct_err( &self, msg: impl Into, @@ -380,16 +383,22 @@ impl ParseSess { } #[rustc_lint_diagnostics] + #[allow(rustc::diagnostic_outside_of_impl)] + #[allow(rustc::untranslatable_diagnostic)] pub fn struct_warn(&self, msg: impl Into) -> DiagnosticBuilder<'_, ()> { self.span_diagnostic.struct_warn(msg) } #[rustc_lint_diagnostics] + #[allow(rustc::diagnostic_outside_of_impl)] + #[allow(rustc::untranslatable_diagnostic)] pub fn struct_fatal(&self, msg: impl Into) -> DiagnosticBuilder<'_, !> { self.span_diagnostic.struct_fatal(msg) } #[rustc_lint_diagnostics] + #[allow(rustc::diagnostic_outside_of_impl)] + #[allow(rustc::untranslatable_diagnostic)] pub fn struct_diagnostic( &self, msg: impl Into, From 2c77f3e9c5804edc0bb520c7b4774424cea6beb0 Mon Sep 17 00:00:00 2001 From: Luis Cardoso <61982523+LuisCardosoOliveira@users.noreply.github.com> Date: Wed, 24 Aug 2022 17:15:08 +0200 Subject: [PATCH 10/24] translations(rustc_session): migrate check_expected_reuse This commit migrates the errors in the function check_expected_reuse to use the new SessionDiagnostic. It also does some small refactor for the IncorrectCguReuseType to include the 'at least' word in the fluent translation file --- compiler/rustc_codegen_ssa/src/back/write.rs | 2 +- .../locales/en-US/session.ftl | 5 ++++- compiler/rustc_session/src/cgu_reuse_tracker.rs | 17 +++++------------ compiler/rustc_session/src/errors.rs | 15 +++++++-------- 4 files changed, 17 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 2930d09d71f1a..68f3b19b715ad 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -1892,7 +1892,7 @@ impl OngoingCodegen { } }); - sess.cgu_reuse_tracker.check_expected_reuse(sess.diagnostic()); + sess.cgu_reuse_tracker.check_expected_reuse(sess); sess.abort_if_errors(); diff --git a/compiler/rustc_error_messages/locales/en-US/session.ftl b/compiler/rustc_error_messages/locales/en-US/session.ftl index e94a7b2c1c8e9..983e5cee8237d 100644 --- a/compiler/rustc_error_messages/locales/en-US/session.ftl +++ b/compiler/rustc_error_messages/locales/en-US/session.ftl @@ -1,5 +1,8 @@ session_incorrect_cgu_reuse_type = - CGU-reuse for `{$cgu_user_name}` is `{$actual_reuse}` but should be `{$at_least}``${expected_reuse}` + CGU-reuse for `{$cgu_user_name}` is `{$actual_reuse}` but should be {$at_least -> + [one] {"at least "} + *[other] {""} + }`{$expected_reuse}` session_cgu_not_recorded = CGU-reuse for `{$cgu_user_name}` is (mangled: `{$cgu_name}`) was not recorded` diff --git a/compiler/rustc_session/src/cgu_reuse_tracker.rs b/compiler/rustc_session/src/cgu_reuse_tracker.rs index 0b75a89c4d8a1..2a4a772f61085 100644 --- a/compiler/rustc_session/src/cgu_reuse_tracker.rs +++ b/compiler/rustc_session/src/cgu_reuse_tracker.rs @@ -2,7 +2,8 @@ //! compilation. This is used for incremental compilation tests and debug //! output. -use crate::errors::IncorrectCguReuseType; +use crate::errors::{CguNotRecorded, IncorrectCguReuseType}; +use crate::Session; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg}; use rustc_span::{Span, Symbol}; @@ -104,7 +105,7 @@ impl CguReuseTracker { } } - pub fn check_expected_reuse(&self, diag: &rustc_errors::Handler) { + pub fn check_expected_reuse(&self, sess: &Session) { if let Some(ref data) = self.data { let data = data.lock().unwrap(); @@ -118,7 +119,7 @@ impl CguReuseTracker { }; if error { - let at_least = if at_least { "at least " } else { "" }; + let at_least = if at_least { 1 } else { 0 }; IncorrectCguReuseType { span: error_span.0, cgu_user_name: &cgu_user_name, @@ -128,15 +129,7 @@ impl CguReuseTracker { }; } } else { - //FIXME: Remove this once PR #100694 that implements `[fatal(..)]` is merged - let msg = format!( - "CGU-reuse for `{cgu_user_name}` (mangled: `{cgu_name}`) was \ - not recorded" - ); - diag.span_fatal(error_span.0, &msg) - - //FIXME: Uncomment this once PR #100694 that implements `[fatal(..)]` is merged - // CguNotRecorded { cgu_user_name, cgu_name }; + sess.emit_fatal(CguNotRecorded { cgu_user_name, cgu_name }); } } } diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index 54e5fe82f5c4d..7252f1799dac1 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -14,16 +14,15 @@ pub struct IncorrectCguReuseType<'a> { pub cgu_user_name: &'a str, pub actual_reuse: CguReuse, pub expected_reuse: CguReuse, - pub at_least: &'a str, + pub at_least: u8, } -//FIXME: Uncomment this once PR #100694 that implements `[fatal(..)]` is merged -// #[derive(SessionDiagnostic)] -// #[fatal(session::cgu_not_recorded)] -// pub struct CguNotRecorded<'a> { -// pub cgu_user_name: &'a str, -// pub cgu_name: &'a str, -// } +#[derive(SessionDiagnostic)] +#[diag(session::cgu_not_recorded)] +pub struct CguNotRecorded<'a> { + pub cgu_user_name: &'a str, + pub cgu_name: &'a str, +} #[derive(SessionDiagnostic)] #[diag(session::feature_gate_error, code = "E0658")] From a19139f9ff8a303e3a26ff6c441e9c8032f19568 Mon Sep 17 00:00:00 2001 From: Nathan Stocks Date: Fri, 26 Aug 2022 11:45:09 -0600 Subject: [PATCH 11/24] remove unnecessary comment --- compiler/rustc_monomorphize/src/polymorphize.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs index 88f8e24fbd529..6e4ab2a35c337 100644 --- a/compiler/rustc_monomorphize/src/polymorphize.rs +++ b/compiler/rustc_monomorphize/src/polymorphize.rs @@ -216,11 +216,6 @@ fn emit_unused_generic_params_error<'tcx>( if unused_parameters.contains(param.index).unwrap_or(false) { debug!(?param); let def_span = tcx.def_span(param.def_id); - // šŸ¤” The docs say - // - // Any attribute applied to a Vec will be repeated for each element of the vector. - // - // But they don't say what template variable to use to substitute each value into the message!? param_spans.push(def_span); param_names.push(param.name.to_string()); } From 845d56759c71391a23c73a328bea71b9342d7933 Mon Sep 17 00:00:00 2001 From: Nathan Stocks Date: Fri, 26 Aug 2022 15:17:20 -0600 Subject: [PATCH 12/24] revert src/tools/cargo submodule to where it ought to be from where we rebased --- Cargo.lock | 8 ++++---- src/tools/cargo | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1c1869a470c4d..178157830e979 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4997,9 +4997,9 @@ checksum = "da73c8f77aebc0e40c300b93f0a5f1bece7a248a36eee287d4e095f35c7b7d6e" [[package]] name = "snapbox" -version = "0.2.10" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "767a1d5da232b6959cd1bd5c9e8db8a7cce09c3038e89deedb49a549a2aefd93" +checksum = "44d199ccf8f606592df2d145db26f2aa45344e23c64b074cc5a4047f1d99b0f7" dependencies = [ "concolor", "content_inspector", @@ -5015,9 +5015,9 @@ dependencies = [ [[package]] name = "snapbox-macros" -version = "0.2.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c01dea7e04cbb27ef4c86e9922184608185f7cd95c1763bc30d727cda4a5e930" +checksum = "8a253e6f894cfa440cba00600a249fa90869d8e0ec45ab274a456e043a0ce8f2" [[package]] name = "socket2" diff --git a/src/tools/cargo b/src/tools/cargo index 9809f8ff33c2b..6da726708a440 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 9809f8ff33c2b998919fd0432c626f0f7323697a +Subproject commit 6da726708a4406f31f996d813790818dce837161 From 6099d17afe622c2784caa2c215b7970a4424f908 Mon Sep 17 00:00:00 2001 From: Nixon Enraght-Moony Date: Tue, 30 Aug 2022 15:29:41 +0100 Subject: [PATCH 13/24] rustdoc: Resugar async fn return type in `clean`, not `html` This way it also happens for json output. Fixes #101199 --- src/librustdoc/clean/mod.rs | 5 +++- src/librustdoc/html/format.rs | 17 +++-------- src/librustdoc/html/render/mod.rs | 2 +- src/librustdoc/html/render/print_item.rs | 2 +- src/test/rustdoc-json/fns/async_return.rs | 36 +++++++++++++++++++++++ 5 files changed, 46 insertions(+), 16 deletions(-) create mode 100644 src/test/rustdoc-json/fns/async_return.rs diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index c425de081a6a6..41f9eb3cdf6bd 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -886,7 +886,10 @@ fn clean_function<'tcx>( // NOTE: generics must be cleaned before args let generics = clean_generics(generics, cx); let args = clean_args_from_types_and_body_id(cx, sig.decl.inputs, body_id); - let decl = clean_fn_decl_with_args(cx, sig.decl, args); + let mut decl = clean_fn_decl_with_args(cx, sig.decl, args); + if sig.header.is_async() { + decl.output = decl.sugared_async_return_type(); + } (generics, decl) }); Box::new(Function { decl, generics }) diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index b023792e95a58..6f49f00f93e5e 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -1310,22 +1310,19 @@ impl clean::FnDecl { ///
Used to determine line-wrapping. /// * `indent`: The number of spaces to indent each successive line with, if line-wrapping is /// necessary. - /// * `asyncness`: Whether the function is async or not. pub(crate) fn full_print<'a, 'tcx: 'a>( &'a self, header_len: usize, indent: usize, - asyncness: hir::IsAsync, cx: &'a Context<'tcx>, ) -> impl fmt::Display + 'a + Captures<'tcx> { - display_fn(move |f| self.inner_full_print(header_len, indent, asyncness, f, cx)) + display_fn(move |f| self.inner_full_print(header_len, indent, f, cx)) } fn inner_full_print( &self, header_len: usize, indent: usize, - asyncness: hir::IsAsync, f: &mut fmt::Formatter<'_>, cx: &Context<'_>, ) -> fmt::Result { @@ -1390,15 +1387,9 @@ impl clean::FnDecl { args_plain.push_str(", ..."); } - let arrow_plain; - let arrow = if let hir::IsAsync::Async = asyncness { - let output = self.sugared_async_return_type(); - arrow_plain = format!("{:#}", output.print(cx)); - if f.alternate() { arrow_plain.clone() } else { format!("{}", output.print(cx)) } - } else { - arrow_plain = format!("{:#}", self.output.print(cx)); - if f.alternate() { arrow_plain.clone() } else { format!("{}", self.output.print(cx)) } - }; + let arrow_plain = format!("{:#}", self.output.print(cx)); + let arrow = + if f.alternate() { arrow_plain.clone() } else { format!("{}", self.output.print(cx)) }; let declaration_len = header_len + args_plain.len() + arrow_plain.len(); let output = if declaration_len > 80 { diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 6272f47f460ca..bc3d2d93da9bf 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -821,7 +821,7 @@ fn assoc_method( href = href, name = name, generics = g.print(cx), - decl = d.full_print(header_len, indent, header.asyncness, cx), + decl = d.full_print(header_len, indent, cx), notable_traits = notable_traits_decl(d, cx), where_clause = print_where_clause(g, cx, indent, end_newline), ) diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 710064a37d041..af8e27ce1a10f 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -530,7 +530,7 @@ fn item_function(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, f: &cle name = name, generics = f.generics.print(cx), where_clause = print_where_clause(&f.generics, cx, 0, Ending::Newline), - decl = f.decl.full_print(header_len, 0, header.asyncness, cx), + decl = f.decl.full_print(header_len, 0, cx), notable_traits = notable_traits_decl(&f.decl, cx), ); }); diff --git a/src/test/rustdoc-json/fns/async_return.rs b/src/test/rustdoc-json/fns/async_return.rs new file mode 100644 index 0000000000000..b89781ca92da6 --- /dev/null +++ b/src/test/rustdoc-json/fns/async_return.rs @@ -0,0 +1,36 @@ +// edition:2021 +// ignore-tidy-linelength + +// Regression test for + +use std::future::Future; + +// @is "$.index[*][?(@.name=='get_int')].inner.decl.output" '{"inner": "i32", "kind": "primitive"}' +// @is "$.index[*][?(@.name=='get_int')].inner.header.async" false +pub fn get_int() -> i32 { + 42 +} + +// @is "$.index[*][?(@.name=='get_int_async')].inner.decl.output" '{"inner": "i32", "kind": "primitive"}' +// @is "$.index[*][?(@.name=='get_int_async')].inner.header.async" true +pub async fn get_int_async() -> i32 { + 42 +} + +// @is "$.index[*][?(@.name=='get_int_future')].inner.decl.output.kind" '"impl_trait"' +// @is "$.index[*][?(@.name=='get_int_future')].inner.decl.output.inner[0].trait_bound.trait.name" '"Future"' +// @is "$.index[*][?(@.name=='get_int_future')].inner.decl.output.inner[0].trait_bound.trait.args.angle_bracketed.bindings[0].name" '"Output"' +// @is "$.index[*][?(@.name=='get_int_future')].inner.decl.output.inner[0].trait_bound.trait.args.angle_bracketed.bindings[0].binding.equality.type" '{"inner": "i32", "kind": "primitive"}' +// @is "$.index[*][?(@.name=='get_int_future')].inner.header.async" false +pub fn get_int_future() -> impl Future { + async { 42 } +} + +// @is "$.index[*][?(@.name=='get_int_future_async')].inner.decl.output.kind" '"impl_trait"' +// @is "$.index[*][?(@.name=='get_int_future_async')].inner.decl.output.inner[0].trait_bound.trait.name" '"Future"' +// @is "$.index[*][?(@.name=='get_int_future_async')].inner.decl.output.inner[0].trait_bound.trait.args.angle_bracketed.bindings[0].name" '"Output"' +// @is "$.index[*][?(@.name=='get_int_future_async')].inner.decl.output.inner[0].trait_bound.trait.args.angle_bracketed.bindings[0].binding.equality.type" '{"inner": "i32", "kind": "primitive"}' +// @is "$.index[*][?(@.name=='get_int_future_async')].inner.header.async" true +pub async fn get_int_future_async() -> impl Future { + async { 42 } +} From 6c585fcce52f96b3bd7c5ab69599c02387716d03 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 30 Aug 2022 17:11:07 +0200 Subject: [PATCH 14/24] Clean up render_assoc_items_inner a bit --- src/librustdoc/html/render/mod.rs | 106 +++++++++++++++--------------- 1 file changed, 52 insertions(+), 54 deletions(-) diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 6272f47f460ca..56e1c1fe5a7bc 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -613,7 +613,7 @@ fn short_item_info( // Render the list of items inside one of the sections "Trait Implementations", // "Auto Trait Implementations," "Blanket Trait Implementations" (on struct/enum pages). -fn render_impls( +pub(crate) fn render_impls( cx: &mut Context<'_>, w: &mut Buffer, impls: &[&&Impl], @@ -1025,6 +1025,47 @@ impl<'a> AssocItemLink<'a> { } } +fn write_impl_section_heading(w: &mut Buffer, title: &str, id: &str) { + write!( + w, + "

\ + {title}\ + \ +

" + ); +} + +pub(crate) fn render_all_impls( + w: &mut Buffer, + cx: &mut Context<'_>, + containing_item: &clean::Item, + concrete: &[&&Impl], + synthetic: &[&&Impl], + blanket_impl: &[&&Impl], +) { + let mut impls = Buffer::empty_from(w); + render_impls(cx, &mut impls, concrete, containing_item, true); + let impls = impls.into_inner(); + if !impls.is_empty() { + write_impl_section_heading(w, "Trait Implementations", "trait-implementations"); + write!(w, "
{}
", impls); + } + + if !synthetic.is_empty() { + write_impl_section_heading(w, "Auto Trait Implementations", "synthetic-implementations"); + w.write_str("
"); + render_impls(cx, w, synthetic, containing_item, false); + w.write_str("
"); + } + + if !blanket_impl.is_empty() { + write_impl_section_heading(w, "Blanket Implementations", "blanket-implementations"); + w.write_str("
"); + render_impls(cx, w, blanket_impl, containing_item, false); + w.write_str("
"); + } +} + fn render_assoc_items( w: &mut Buffer, cx: &mut Context<'_>, @@ -1054,12 +1095,7 @@ fn render_assoc_items_inner( let mut tmp_buf = Buffer::empty_from(w); let (render_mode, id) = match what { AssocItemRender::All => { - tmp_buf.write_str( - "

\ - Implementations\ - \ -

", - ); + write_impl_section_heading(&mut tmp_buf, "Implementations", "implementations"); (RenderMode::Normal, "implementations-list".to_owned()) } AssocItemRender::DerefFor { trait_, type_, deref_mut_ } => { @@ -1068,15 +1104,14 @@ fn render_assoc_items_inner( if let Some(def_id) = type_.def_id(cx.cache()) { cx.deref_id_map.insert(def_id, id.clone()); } - write!( - tmp_buf, - "

\ - Methods from {trait_}<Target = {type_}>\ - \ -

", - id = id, - trait_ = trait_.print(cx), - type_ = type_.print(cx), + write_impl_section_heading( + &mut tmp_buf, + &format!( + "Methods from {trait_}<Target = {type_}>", + trait_ = trait_.print(cx), + type_ = type_.print(cx), + ), + &id, ); (RenderMode::ForDeref { mut_: deref_mut_ }, cx.derive_id(id)) } @@ -1128,44 +1163,7 @@ fn render_assoc_items_inner( let (blanket_impl, concrete): (Vec<&&Impl>, _) = concrete.into_iter().partition(|t| t.inner_impl().kind.is_blanket()); - let mut impls = Buffer::empty_from(w); - render_impls(cx, &mut impls, &concrete, containing_item, true); - let impls = impls.into_inner(); - if !impls.is_empty() { - write!( - w, - "

\ - Trait Implementations\ - \ -

\ -
{}
", - impls - ); - } - - if !synthetic.is_empty() { - w.write_str( - "

\ - Auto Trait Implementations\ - \ -

\ -
", - ); - render_impls(cx, w, &synthetic, containing_item, false); - w.write_str("
"); - } - - if !blanket_impl.is_empty() { - w.write_str( - "

\ - Blanket Implementations\ - \ -

\ -
", - ); - render_impls(cx, w, &blanket_impl, containing_item, false); - w.write_str("
"); - } + render_all_impls(w, cx, containing_item, &concrete, &synthetic, &blanket_impl); } } From 86f8c4e8e3136ee1831ffaa9d6fbdac7267d35ea Mon Sep 17 00:00:00 2001 From: Jhonny Bill Mena Date: Sat, 27 Aug 2022 00:24:13 -0400 Subject: [PATCH 15/24] ADD - InvalidSymbolName to migrate symbol-name({}) error to new diagnostics infraestructure ADD - dependencies needed to port a module to new Diagnostics infra (rustc_macros, rustc_errors, errors file, and fluent file) --- Cargo.lock | 2 ++ .../locales/en-US/symbol_mangling.ftl | 1 + compiler/rustc_error_messages/src/lib.rs | 1 + compiler/rustc_symbol_mangling/Cargo.toml | 2 ++ compiler/rustc_symbol_mangling/src/errors.rs | 12 ++++++++++++ compiler/rustc_symbol_mangling/src/lib.rs | 1 + compiler/rustc_symbol_mangling/src/test.rs | 6 +++++- 7 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 compiler/rustc_error_messages/locales/en-US/symbol_mangling.ftl create mode 100644 compiler/rustc_symbol_mangling/src/errors.rs diff --git a/Cargo.lock b/Cargo.lock index 21d522cb9ff42..6cddbe9d2cd5f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4155,7 +4155,9 @@ dependencies = [ "punycode", "rustc-demangle", "rustc_data_structures", + "rustc_errors", "rustc_hir", + "rustc_macros", "rustc_middle", "rustc_session", "rustc_span", diff --git a/compiler/rustc_error_messages/locales/en-US/symbol_mangling.ftl b/compiler/rustc_error_messages/locales/en-US/symbol_mangling.ftl new file mode 100644 index 0000000000000..6c8166beab859 --- /dev/null +++ b/compiler/rustc_error_messages/locales/en-US/symbol_mangling.ftl @@ -0,0 +1 @@ +symbol_mangling_invalid_symbol_name = symbol-name({$mangled_formatted}) diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index d1ac326a72c6d..eabb9192029d5 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -52,6 +52,7 @@ fluent_messages! { ty_utils => "../locales/en-US/ty_utils.ftl", typeck => "../locales/en-US/typeck.ftl", mir_dataflow => "../locales/en-US/mir_dataflow.ftl", + symbol_mangling => "../locales/en-US/symbol_mangling.ftl", } pub use fluent_generated::{self as fluent, DEFAULT_LOCALE_RESOURCES}; diff --git a/compiler/rustc_symbol_mangling/Cargo.toml b/compiler/rustc_symbol_mangling/Cargo.toml index b104a40c23115..3db05225722e7 100644 --- a/compiler/rustc_symbol_mangling/Cargo.toml +++ b/compiler/rustc_symbol_mangling/Cargo.toml @@ -18,3 +18,5 @@ rustc_hir = { path = "../rustc_hir" } rustc_target = { path = "../rustc_target" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_session = { path = "../rustc_session" } +rustc_macros = { path = "../rustc_macros" } +rustc_errors = { path = "../rustc_errors" } diff --git a/compiler/rustc_symbol_mangling/src/errors.rs b/compiler/rustc_symbol_mangling/src/errors.rs new file mode 100644 index 0000000000000..38aa4345f0c9c --- /dev/null +++ b/compiler/rustc_symbol_mangling/src/errors.rs @@ -0,0 +1,12 @@ +//! Errors emitted by symbol_mangling. + +use rustc_macros::SessionDiagnostic; +use rustc_span::Span; + +#[derive(SessionDiagnostic)] +#[error(symbol_mangling::invalid_symbol_name)] +pub struct InvalidSymbolName<'a> { + #[primary_span] + pub span: Span, + pub mangled_formatted: &'a str, +} diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs index 5fc992023caa0..252726691a760 100644 --- a/compiler/rustc_symbol_mangling/src/lib.rs +++ b/compiler/rustc_symbol_mangling/src/lib.rs @@ -110,6 +110,7 @@ use tracing::debug; mod legacy; mod v0; +pub mod errors; pub mod test; pub mod typeid; diff --git a/compiler/rustc_symbol_mangling/src/test.rs b/compiler/rustc_symbol_mangling/src/test.rs index 7249ce04c155e..9c1d5d4292ca2 100644 --- a/compiler/rustc_symbol_mangling/src/test.rs +++ b/compiler/rustc_symbol_mangling/src/test.rs @@ -4,6 +4,7 @@ //! def-path. This is used for unit testing the code that generates //! paths etc in all kinds of annoying scenarios. +use crate::errors::InvalidSymbolName; use rustc_hir::def_id::LocalDefId; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{subst::InternalSubsts, Instance, TyCtxt}; @@ -59,7 +60,10 @@ impl SymbolNamesTest<'_> { tcx.erase_regions(InternalSubsts::identity_for_item(tcx, def_id)), ); let mangled = tcx.symbol_name(instance); - tcx.sess.span_err(attr.span, &format!("symbol-name({})", mangled)); + tcx.sess.emit_err(InvalidSymbolName { + span: attr.span, + mangled_formatted: &format!("{mangled}"), + }); if let Ok(demangling) = rustc_demangle::try_demangle(mangled.name) { tcx.sess.span_err(attr.span, &format!("demangling({})", demangling)); tcx.sess.span_err(attr.span, &format!("demangling-alt({:#})", demangling)); From 359002bbebb5a3879af4d957001b6526ae4c550e Mon Sep 17 00:00:00 2001 From: Jhonny Bill Mena Date: Sun, 21 Aug 2022 00:38:23 -0400 Subject: [PATCH 16/24] ADD - migrate InvalidTraitItem and AltInvalidTraitItem errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Thought of doing this by having a struct and an enum with Default and Alt cases, but not sure if we wanted to have the text in code instead of having ā€œdemangling()ā€ and ā€œdemangling-alt()ā€ in the ftl file. Donā€™t like the current way of having structs representing the same-ish and using long names to distinguish their expectations, instead of putting this in an enum and handling the different cases inside the type. I am fine with whichever option the team prefers; also understand having them as separate structs keeps it simple. --- .../locales/en-US/symbol_mangling.ftl | 4 ++++ compiler/rustc_symbol_mangling/src/errors.rs | 16 ++++++++++++++++ compiler/rustc_symbol_mangling/src/test.rs | 12 +++++++++--- 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/symbol_mangling.ftl b/compiler/rustc_error_messages/locales/en-US/symbol_mangling.ftl index 6c8166beab859..644c8f84c28ef 100644 --- a/compiler/rustc_error_messages/locales/en-US/symbol_mangling.ftl +++ b/compiler/rustc_error_messages/locales/en-US/symbol_mangling.ftl @@ -1 +1,5 @@ symbol_mangling_invalid_symbol_name = symbol-name({$mangled_formatted}) + +symbol_mangling_invalid_trait_item = demangling({$demangling_formatted}) + +symbol_mangling_alt_invalid_trait_item = demangling-alt({$alt_demangling_formatted}) diff --git a/compiler/rustc_symbol_mangling/src/errors.rs b/compiler/rustc_symbol_mangling/src/errors.rs index 38aa4345f0c9c..db8b3159a6ff5 100644 --- a/compiler/rustc_symbol_mangling/src/errors.rs +++ b/compiler/rustc_symbol_mangling/src/errors.rs @@ -10,3 +10,19 @@ pub struct InvalidSymbolName<'a> { pub span: Span, pub mangled_formatted: &'a str, } + +#[derive(SessionDiagnostic)] +#[error(symbol_mangling::invalid_trait_item)] +pub struct InvalidTraitItem<'a> { + #[primary_span] + pub span: Span, + pub demangling_formatted: &'a str, +} + +#[derive(SessionDiagnostic)] +#[error(symbol_mangling::alt_invalid_trait_item)] +pub struct AltInvalidTraitItem<'a> { + #[primary_span] + pub span: Span, + pub alt_demangling_formatted: &'a str, +} diff --git a/compiler/rustc_symbol_mangling/src/test.rs b/compiler/rustc_symbol_mangling/src/test.rs index 9c1d5d4292ca2..06efefb726ca7 100644 --- a/compiler/rustc_symbol_mangling/src/test.rs +++ b/compiler/rustc_symbol_mangling/src/test.rs @@ -4,7 +4,7 @@ //! def-path. This is used for unit testing the code that generates //! paths etc in all kinds of annoying scenarios. -use crate::errors::InvalidSymbolName; +use crate::errors::{AltInvalidTraitItem, InvalidSymbolName, InvalidTraitItem}; use rustc_hir::def_id::LocalDefId; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{subst::InternalSubsts, Instance, TyCtxt}; @@ -65,8 +65,14 @@ impl SymbolNamesTest<'_> { mangled_formatted: &format!("{mangled}"), }); if let Ok(demangling) = rustc_demangle::try_demangle(mangled.name) { - tcx.sess.span_err(attr.span, &format!("demangling({})", demangling)); - tcx.sess.span_err(attr.span, &format!("demangling-alt({:#})", demangling)); + tcx.sess.emit_err(InvalidTraitItem { + span: attr.span, + demangling_formatted: &format!("{demangling}"), + }); + tcx.sess.emit_err(AltInvalidTraitItem { + span: attr.span, + alt_demangling_formatted: &format!("{:#}", demangling), + }); } } From bd83bbc93adce97e34c1c4d5d8d74f7b19068326 Mon Sep 17 00:00:00 2001 From: Jhonny Bill Mena Date: Sun, 21 Aug 2022 00:42:59 -0400 Subject: [PATCH 17/24] UPDATE - accept String instead of unused 'str --- compiler/rustc_symbol_mangling/src/errors.rs | 12 ++++++------ compiler/rustc_symbol_mangling/src/test.rs | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_symbol_mangling/src/errors.rs b/compiler/rustc_symbol_mangling/src/errors.rs index db8b3159a6ff5..c0e49e07bfc59 100644 --- a/compiler/rustc_symbol_mangling/src/errors.rs +++ b/compiler/rustc_symbol_mangling/src/errors.rs @@ -5,24 +5,24 @@ use rustc_span::Span; #[derive(SessionDiagnostic)] #[error(symbol_mangling::invalid_symbol_name)] -pub struct InvalidSymbolName<'a> { +pub struct InvalidSymbolName { #[primary_span] pub span: Span, - pub mangled_formatted: &'a str, + pub mangled_formatted: String, } #[derive(SessionDiagnostic)] #[error(symbol_mangling::invalid_trait_item)] -pub struct InvalidTraitItem<'a> { +pub struct InvalidTraitItem { #[primary_span] pub span: Span, - pub demangling_formatted: &'a str, + pub demangling_formatted: String, } #[derive(SessionDiagnostic)] #[error(symbol_mangling::alt_invalid_trait_item)] -pub struct AltInvalidTraitItem<'a> { +pub struct AltInvalidTraitItem { #[primary_span] pub span: Span, - pub alt_demangling_formatted: &'a str, + pub alt_demangling_formatted: String, } diff --git a/compiler/rustc_symbol_mangling/src/test.rs b/compiler/rustc_symbol_mangling/src/test.rs index 06efefb726ca7..2ed1dea357dd5 100644 --- a/compiler/rustc_symbol_mangling/src/test.rs +++ b/compiler/rustc_symbol_mangling/src/test.rs @@ -62,16 +62,16 @@ impl SymbolNamesTest<'_> { let mangled = tcx.symbol_name(instance); tcx.sess.emit_err(InvalidSymbolName { span: attr.span, - mangled_formatted: &format!("{mangled}"), + mangled_formatted: format!("{mangled}"), }); if let Ok(demangling) = rustc_demangle::try_demangle(mangled.name) { tcx.sess.emit_err(InvalidTraitItem { span: attr.span, - demangling_formatted: &format!("{demangling}"), + demangling_formatted: format!("{demangling}"), }); tcx.sess.emit_err(AltInvalidTraitItem { span: attr.span, - alt_demangling_formatted: &format!("{:#}", demangling), + alt_demangling_formatted: format!("{:#}", demangling), }); } } From 8f5fada86df26aaccbf4f5e5851ac040b5ea5852 Mon Sep 17 00:00:00 2001 From: Jhonny Bill Mena Date: Sun, 21 Aug 2022 00:51:33 -0400 Subject: [PATCH 18/24] ADD - migrate InvalidDefPath to new diagnostics infra --- .../locales/en-US/symbol_mangling.ftl | 2 ++ compiler/rustc_symbol_mangling/src/errors.rs | 8 ++++++++ compiler/rustc_symbol_mangling/src/test.rs | 8 +++++--- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/symbol_mangling.ftl b/compiler/rustc_error_messages/locales/en-US/symbol_mangling.ftl index 644c8f84c28ef..55d6fbbf86f33 100644 --- a/compiler/rustc_error_messages/locales/en-US/symbol_mangling.ftl +++ b/compiler/rustc_error_messages/locales/en-US/symbol_mangling.ftl @@ -3,3 +3,5 @@ symbol_mangling_invalid_symbol_name = symbol-name({$mangled_formatted}) symbol_mangling_invalid_trait_item = demangling({$demangling_formatted}) symbol_mangling_alt_invalid_trait_item = demangling-alt({$alt_demangling_formatted}) + +symbol_mangling_invalid_def_path = def-path({$def_path}) diff --git a/compiler/rustc_symbol_mangling/src/errors.rs b/compiler/rustc_symbol_mangling/src/errors.rs index c0e49e07bfc59..4872dfa2653a6 100644 --- a/compiler/rustc_symbol_mangling/src/errors.rs +++ b/compiler/rustc_symbol_mangling/src/errors.rs @@ -26,3 +26,11 @@ pub struct AltInvalidTraitItem { pub span: Span, pub alt_demangling_formatted: String, } + +#[derive(SessionDiagnostic)] +#[error(symbol_mangling::invalid_def_path)] +pub struct InvalidDefPath { + #[primary_span] + pub span: Span, + pub def_path: String, +} diff --git a/compiler/rustc_symbol_mangling/src/test.rs b/compiler/rustc_symbol_mangling/src/test.rs index 2ed1dea357dd5..b1c4cab11eb8e 100644 --- a/compiler/rustc_symbol_mangling/src/test.rs +++ b/compiler/rustc_symbol_mangling/src/test.rs @@ -4,7 +4,7 @@ //! def-path. This is used for unit testing the code that generates //! paths etc in all kinds of annoying scenarios. -use crate::errors::{AltInvalidTraitItem, InvalidSymbolName, InvalidTraitItem}; +use crate::errors::{AltInvalidTraitItem, InvalidDefPath, InvalidSymbolName, InvalidTraitItem}; use rustc_hir::def_id::LocalDefId; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{subst::InternalSubsts, Instance, TyCtxt}; @@ -77,8 +77,10 @@ impl SymbolNamesTest<'_> { } for attr in tcx.get_attrs(def_id.to_def_id(), DEF_PATH) { - let path = with_no_trimmed_paths!(tcx.def_path_str(def_id.to_def_id())); - tcx.sess.span_err(attr.span, &format!("def-path({})", path)); + tcx.sess.emit_err(InvalidDefPath { + span: attr.span, + def_path: with_no_trimmed_paths!(tcx.def_path_str(def_id.to_def_id())), + }); } } } From ef2f6ab55eb1862fbf5a700d034ea4fd2fb23e80 Mon Sep 17 00:00:00 2001 From: Jhonny Bill Mena Date: Sun, 21 Aug 2022 00:57:52 -0400 Subject: [PATCH 19/24] ADD - diagnostics lints to symbol_mangling module --- compiler/rustc_symbol_mangling/src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs index 252726691a760..0c6489acb3483 100644 --- a/compiler/rustc_symbol_mangling/src/lib.rs +++ b/compiler/rustc_symbol_mangling/src/lib.rs @@ -91,6 +91,8 @@ #![feature(never_type)] #![recursion_limit = "256"] #![allow(rustc::potential_query_instability)] +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate rustc_middle; From 3ee69463164ac33af6eb483ccd2f64b06730c220 Mon Sep 17 00:00:00 2001 From: Jhonny Bill Mena Date: Sun, 21 Aug 2022 11:09:00 -0400 Subject: [PATCH 20/24] UPDATE - to support diag introduced in PR #100765 --- compiler/rustc_symbol_mangling/src/errors.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_symbol_mangling/src/errors.rs b/compiler/rustc_symbol_mangling/src/errors.rs index 4872dfa2653a6..242997365a892 100644 --- a/compiler/rustc_symbol_mangling/src/errors.rs +++ b/compiler/rustc_symbol_mangling/src/errors.rs @@ -4,7 +4,7 @@ use rustc_macros::SessionDiagnostic; use rustc_span::Span; #[derive(SessionDiagnostic)] -#[error(symbol_mangling::invalid_symbol_name)] +#[diag(symbol_mangling::invalid_symbol_name)] pub struct InvalidSymbolName { #[primary_span] pub span: Span, @@ -12,7 +12,7 @@ pub struct InvalidSymbolName { } #[derive(SessionDiagnostic)] -#[error(symbol_mangling::invalid_trait_item)] +#[diag(symbol_mangling::invalid_trait_item)] pub struct InvalidTraitItem { #[primary_span] pub span: Span, @@ -20,7 +20,7 @@ pub struct InvalidTraitItem { } #[derive(SessionDiagnostic)] -#[error(symbol_mangling::alt_invalid_trait_item)] +#[diag(symbol_mangling::alt_invalid_trait_item)] pub struct AltInvalidTraitItem { #[primary_span] pub span: Span, @@ -28,7 +28,7 @@ pub struct AltInvalidTraitItem { } #[derive(SessionDiagnostic)] -#[error(symbol_mangling::invalid_def_path)] +#[diag(symbol_mangling::invalid_def_path)] pub struct InvalidDefPath { #[primary_span] pub span: Span, From 8588374d29c67df66d128b4be9fea4ac2b9eb5f5 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 30 Aug 2022 14:54:37 -0700 Subject: [PATCH 21/24] Use in-page links for sanitizer docs. --- .../src/compiler-flags/sanitizer.md | 36 +++++++++++++------ 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/src/doc/unstable-book/src/compiler-flags/sanitizer.md b/src/doc/unstable-book/src/compiler-flags/sanitizer.md index 7f7549aaf5a96..b33405f18e90b 100644 --- a/src/doc/unstable-book/src/compiler-flags/sanitizer.md +++ b/src/doc/unstable-book/src/compiler-flags/sanitizer.md @@ -9,17 +9,17 @@ The tracking issues for this feature are: This feature allows for use of one of following sanitizers: -* [AddressSanitizer][clang-asan] a fast memory error detector. -* [ControlFlowIntegrity][clang-cfi] LLVM Control Flow Integrity (CFI) provides +* [AddressSanitizer](#addresssanitizer) a fast memory error detector. +* [ControlFlowIntegrity](#controlflowintegrity) LLVM Control Flow Integrity (CFI) provides forward-edge control flow protection. -* [HWAddressSanitizer][clang-hwasan] a memory error detector similar to +* [HWAddressSanitizer](#hwaddresssanitizer) a memory error detector similar to AddressSanitizer, but based on partial hardware assistance. -* [LeakSanitizer][clang-lsan] a run-time memory leak detector. -* [MemorySanitizer][clang-msan] a detector of uninitialized reads. -* [MemTagSanitizer][clang-memtag] fast memory error detector based on +* [LeakSanitizer](#leaksanitizer) a run-time memory leak detector. +* [MemorySanitizer](#memorysanitizer) a detector of uninitialized reads. +* [MemTagSanitizer](#memtagsanitizer) fast memory error detector based on Armv8.5-A Memory Tagging Extension. -* [ShadowCallStack][clang-scs] provides backward-edge control flow protection. -* [ThreadSanitizer][clang-tsan] a fast data race detector. +* [ShadowCallStack](#shadowcallstack) provides backward-edge control flow protection. +* [ThreadSanitizer](#threadsanitizer) a fast data race detector. To enable a sanitizer compile with `-Zsanitizer=address`,`-Zsanitizer=cfi`, `-Zsanitizer=hwaddress`, `-Zsanitizer=leak`, `-Zsanitizer=memory`, @@ -58,6 +58,8 @@ AddressSanitizer works with non-instrumented code although it will impede its ability to detect some bugs. It is not expected to produce false positive reports. +See the [Clang AddressSanitizer documentation][clang-asan] for more details. + ## Examples Stack buffer overflow: @@ -204,6 +206,8 @@ tracking issue [#89653](https://github.com/rust-lang/rust/issues/89653)). LLVM CFI can be enabled with -Zsanitizer=cfi and requires LTO (i.e., -Clto). +See the [Clang ControlFlowIntegrity documentation][clang-cfi] for more details. + ## Example ```text @@ -430,6 +434,8 @@ HWAddressSanitizer requires `tagged-globals` target feature to instrument globals. To enable this target feature compile with `-C target-feature=+tagged-globals` +See the [Clang HWAddressSanitizer documentation][clang-hwasan] for more details. + ## Example Heap buffer overflow: @@ -507,6 +513,8 @@ LeakSanitizer is supported on the following targets: * `x86_64-apple-darwin` * `x86_64-unknown-linux-gnu` +See the [Clang LeakSanitizer documentation][clang-lsan] for more details. + # MemorySanitizer MemorySanitizer is detector of uninitialized reads. @@ -521,6 +529,8 @@ MemorySanitizer requires all program code to be instrumented. C/C++ dependencies need to be recompiled using Clang with `-fsanitize=memory` option. Failing to achieve that will result in false positive reports. +See the [Clang MemorySanitizer documentation][clang-msan] for more details. + ## Example Detecting the use of uninitialized memory. The `-Zbuild-std` flag rebuilds and @@ -569,7 +579,7 @@ MemTagSanitizer is supported on the following targets: MemTagSanitizer requires hardware support and the `mte` target feature. To enable this target feature compile with `-C target-feature="+mte"`. -More information can be found in the associated [LLVM documentation](https://llvm.org/docs/MemTagSanitizer.html). +See the [LLVM MemTagSanitizer documentation][llvm-memtag] for more details. # ShadowCallStack @@ -581,7 +591,9 @@ ShadowCallStack can be enabled with `-Zsanitizer=shadow-call-stack` option and i * `aarch64-linux-android` -A runtime must be provided by the application or operating system. See the [LLVM documentation][clang-scs] for further details. +A runtime must be provided by the application or operating system. + +See the [Clang ShadowCallStack documentation][clang-scs] for more details. # ThreadSanitizer @@ -604,6 +616,8 @@ can lead to false positive reports. ThreadSanitizer does not support atomic fences `std::sync::atomic::fence`, nor synchronization performed using inline assembly code. +See the [Clang ThreadSanitizer documentation][clang-tsan] for more details. + ## Example ```rust @@ -673,6 +687,7 @@ Sanitizers produce symbolized stacktraces when llvm-symbolizer binary is in `PAT * [HWAddressSanitizer in Clang][clang-hwasan] * [LeakSanitizer in Clang][clang-lsan] * [MemorySanitizer in Clang][clang-msan] +* [MemTagSanitizer in LLVM][llvm-memtag] * [ThreadSanitizer in Clang][clang-tsan] [clang-asan]: https://clang.llvm.org/docs/AddressSanitizer.html @@ -682,3 +697,4 @@ Sanitizers produce symbolized stacktraces when llvm-symbolizer binary is in `PAT [clang-msan]: https://clang.llvm.org/docs/MemorySanitizer.html [clang-scs]: https://clang.llvm.org/docs/ShadowCallStack.html [clang-tsan]: https://clang.llvm.org/docs/ThreadSanitizer.html +[llvm-memtag]: https://llvm.org/docs/MemTagSanitizer.html From 900cda2043654f0bf0bb4dabfb696f643dd1a3a6 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 30 Aug 2022 20:21:56 +0200 Subject: [PATCH 22/24] Print only blanket implementations on reference primitive type --- src/librustdoc/html/render/mod.rs | 180 +++++++++++++++-------- src/librustdoc/html/render/print_item.rs | 20 ++- 2 files changed, 133 insertions(+), 67 deletions(-) diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 56e1c1fe5a7bc..cf43033d1d29a 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -616,7 +616,7 @@ fn short_item_info( pub(crate) fn render_impls( cx: &mut Context<'_>, w: &mut Buffer, - impls: &[&&Impl], + impls: &[&Impl], containing_item: &clean::Item, toggle_open_by_default: bool, ) { @@ -1039,9 +1039,9 @@ pub(crate) fn render_all_impls( w: &mut Buffer, cx: &mut Context<'_>, containing_item: &clean::Item, - concrete: &[&&Impl], - synthetic: &[&&Impl], - blanket_impl: &[&&Impl], + concrete: &[&Impl], + synthetic: &[&Impl], + blanket_impl: &[&Impl], ) { let mut impls = Buffer::empty_from(w); render_impls(cx, &mut impls, concrete, containing_item, true); @@ -1158,9 +1158,9 @@ fn render_assoc_items_inner( return; } - let (synthetic, concrete): (Vec<&&Impl>, Vec<&&Impl>) = - traits.iter().partition(|t| t.inner_impl().kind.is_auto()); - let (blanket_impl, concrete): (Vec<&&Impl>, _) = + let (synthetic, concrete): (Vec<&Impl>, Vec<&Impl>) = + traits.into_iter().partition(|t| t.inner_impl().kind.is_auto()); + let (blanket_impl, concrete): (Vec<&Impl>, _) = concrete.into_iter().partition(|t| t.inner_impl().kind.is_blanket()); render_all_impls(w, cx, containing_item, &concrete, &synthetic, &blanket_impl); @@ -1968,6 +1968,70 @@ fn small_url_encode(s: String) -> String { } } +pub(crate) fn sidebar_render_assoc_items( + cx: &Context<'_>, + out: &mut Buffer, + id_map: &mut IdMap, + concrete: Vec<&Impl>, + synthetic: Vec<&Impl>, + blanket_impl: Vec<&Impl>, +) { + let format_impls = |impls: Vec<&Impl>, id_map: &mut IdMap| { + let mut links = FxHashSet::default(); + + let mut ret = impls + .iter() + .filter_map(|it| { + let trait_ = it.inner_impl().trait_.as_ref()?; + let encoded = + id_map.derive(get_id_for_impl(&it.inner_impl().for_, Some(trait_), cx)); + + let i_display = format!("{:#}", trait_.print(cx)); + let out = Escape(&i_display); + let prefix = match it.inner_impl().polarity { + ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => "", + ty::ImplPolarity::Negative => "!", + }; + let generated = format!("{}{}", encoded, prefix, out); + if links.insert(generated.clone()) { Some(generated) } else { None } + }) + .collect::>(); + ret.sort(); + ret + }; + + let concrete_format = format_impls(concrete, id_map); + let synthetic_format = format_impls(synthetic, id_map); + let blanket_format = format_impls(blanket_impl, id_map); + + if !concrete_format.is_empty() { + print_sidebar_block( + out, + "trait-implementations", + "Trait Implementations", + concrete_format.iter(), + ); + } + + if !synthetic_format.is_empty() { + print_sidebar_block( + out, + "synthetic-implementations", + "Auto Trait Implementations", + synthetic_format.iter(), + ); + } + + if !blanket_format.is_empty() { + print_sidebar_block( + out, + "blanket-implementations", + "Blanket Implementations", + blanket_format.iter(), + ); + } +} + fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) { let did = it.item_id.expect_def_id(); let cache = cx.cache(); @@ -2016,65 +2080,12 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) { sidebar_deref_methods(cx, out, impl_, v, &mut derefs, &mut used_links); } - let format_impls = |impls: Vec<&Impl>, id_map: &mut IdMap| { - let mut links = FxHashSet::default(); - - let mut ret = impls - .iter() - .filter_map(|it| { - let trait_ = it.inner_impl().trait_.as_ref()?; - let encoded = - id_map.derive(get_id_for_impl(&it.inner_impl().for_, Some(trait_), cx)); - - let i_display = format!("{:#}", trait_.print(cx)); - let out = Escape(&i_display); - let prefix = match it.inner_impl().polarity { - ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => "", - ty::ImplPolarity::Negative => "!", - }; - let generated = format!("{}{}", encoded, prefix, out); - if links.insert(generated.clone()) { Some(generated) } else { None } - }) - .collect::>(); - ret.sort(); - ret - }; - let (synthetic, concrete): (Vec<&Impl>, Vec<&Impl>) = v.iter().partition::, _>(|i| i.inner_impl().kind.is_auto()); let (blanket_impl, concrete): (Vec<&Impl>, Vec<&Impl>) = concrete.into_iter().partition::, _>(|i| i.inner_impl().kind.is_blanket()); - let concrete_format = format_impls(concrete, &mut id_map); - let synthetic_format = format_impls(synthetic, &mut id_map); - let blanket_format = format_impls(blanket_impl, &mut id_map); - - if !concrete_format.is_empty() { - print_sidebar_block( - out, - "trait-implementations", - "Trait Implementations", - concrete_format.iter(), - ); - } - - if !synthetic_format.is_empty() { - print_sidebar_block( - out, - "synthetic-implementations", - "Auto Trait Implementations", - synthetic_format.iter(), - ); - } - - if !blanket_format.is_empty() { - print_sidebar_block( - out, - "blanket-implementations", - "Blanket Implementations", - blanket_format.iter(), - ); - } + sidebar_render_assoc_items(cx, out, &mut id_map, concrete, synthetic, blanket_impl); } } } @@ -2344,9 +2355,54 @@ fn sidebar_trait(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, t: &clean buf.push_str("") } +/// Returns the list of implementations for the primitive reference type, filtering out any +/// implementations that are on concrete or partially generic types, only keeping implementations +/// of the form `impl Trait for &T`. +pub(crate) fn get_filtered_impls_for_reference<'a>( + shared: &'a Rc>, + it: &clean::Item, +) -> (Vec<&'a Impl>, Vec<&'a Impl>, Vec<&'a Impl>) { + let def_id = it.item_id.expect_def_id(); + // If the reference primitive is somehow not defined, exit early. + let Some(v) = shared.cache.impls.get(&def_id) else { return (Vec::new(), Vec::new(), Vec::new()) }; + // Since there is no "direct implementation" on the reference primitive type, we filter out + // every implementation which isn't a trait implementation. + let traits: Vec<_> = v.iter().filter(|i| i.inner_impl().trait_.is_some()).collect(); + let (synthetic, concrete): (Vec<&Impl>, Vec<&Impl>) = + traits.into_iter().partition(|t| t.inner_impl().kind.is_auto()); + + let (blanket_impl, concrete): (Vec<&Impl>, _) = + concrete.into_iter().partition(|t| t.inner_impl().kind.is_blanket()); + // Now we keep only references over full generic types. + let concrete: Vec<_> = concrete + .into_iter() + .filter(|t| match t.inner_impl().for_ { + clean::Type::BorrowedRef { ref type_, .. } => type_.is_full_generic(), + _ => false, + }) + .collect(); + + (concrete, synthetic, blanket_impl) +} + fn sidebar_primitive(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item) { let mut sidebar = Buffer::new(); - sidebar_assoc_items(cx, &mut sidebar, it); + + if it.name.map(|n| n.as_str() != "reference").unwrap_or(false) { + sidebar_assoc_items(cx, &mut sidebar, it); + } else { + let shared = Rc::clone(&cx.shared); + let (concrete, synthetic, blanket_impl) = get_filtered_impls_for_reference(&shared, it); + + sidebar_render_assoc_items( + cx, + &mut sidebar, + &mut IdMap::new(), + concrete, + synthetic, + blanket_impl, + ); + } if !sidebar.is_empty() { write!(buf, "
{}
", sidebar.into_inner()); diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 710064a37d041..e3c9dbf502f82 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -16,10 +16,10 @@ use std::fmt; use std::rc::Rc; use super::{ - collect_paths_for_type, document, ensure_trailing_slash, item_ty_to_section, - notable_traits_decl, render_assoc_item, render_assoc_items, render_attributes_in_code, - render_attributes_in_pre, render_impl, render_rightside, render_stability_since_raw, - AssocItemLink, Context, ImplRenderingParameters, + collect_paths_for_type, document, ensure_trailing_slash, get_filtered_impls_for_reference, + item_ty_to_section, notable_traits_decl, render_all_impls, render_assoc_item, + render_assoc_items, render_attributes_in_code, render_attributes_in_pre, render_impl, + render_rightside, render_stability_since_raw, AssocItemLink, Context, ImplRenderingParameters, }; use crate::clean; use crate::config::ModuleSorting; @@ -1371,8 +1371,18 @@ fn item_proc_macro(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, m: &c } fn item_primitive(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item) { + let def_id = it.item_id.expect_def_id(); document(w, cx, it, None, HeadingOffset::H2); - render_assoc_items(w, cx, it, it.item_id.expect_def_id(), AssocItemRender::All) + if it.name.map(|n| n.as_str() != "reference").unwrap_or(false) { + render_assoc_items(w, cx, it, def_id, AssocItemRender::All); + } else { + // We handle the "reference" primitive type on its own because we only want to list + // implementations on generic types. + let shared = Rc::clone(&cx.shared); + let (concrete, synthetic, blanket_impl) = get_filtered_impls_for_reference(&shared, it); + + render_all_impls(w, cx, it, &concrete, &synthetic, &blanket_impl); + } } fn item_constant(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, c: &clean::Constant) { From 477b7ba1657986a31b60ccf149011c037ef649d1 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 30 Aug 2022 20:51:58 +0200 Subject: [PATCH 23/24] Add regression test for implementations displayed on reference primitive type --- src/test/rustdoc/primitive-reference.rs | 37 +++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 src/test/rustdoc/primitive-reference.rs diff --git a/src/test/rustdoc/primitive-reference.rs b/src/test/rustdoc/primitive-reference.rs new file mode 100644 index 0000000000000..5c11934060922 --- /dev/null +++ b/src/test/rustdoc/primitive-reference.rs @@ -0,0 +1,37 @@ +#![crate_name = "foo"] + +#![feature(rustdoc_internals)] + +// @has foo/index.html +// @has - '//h2[@id="primitives"]' 'Primitive Types' +// @has - '//a[@href="primitive.reference.html"]' 'reference' +// @has - '//div[@class="sidebar-elems"]//li/a' 'Primitive Types' +// @has - '//div[@class="sidebar-elems"]//li/a/@href' '#primitives' +// @has foo/primitive.reference.html +// @has - '//a[@class="primitive"]' 'reference' +// @has - '//span[@class="in-band"]' 'Primitive Type reference' +// @has - '//section[@id="main-content"]//div[@class="docblock"]//p' 'this is a test!' + +// There should be only one implementation listed. +// @count - '//*[@class="impl has-srclink"]' 1 +// @has - '//*[@id="impl-Foo%3C%26A%3E-for-%26B"]/*[@class="code-header in-band"]' \ +// 'impl Foo<&A> for &B' +#[doc(primitive = "reference")] +/// this is a test! +mod reference {} + +pub struct Bar; + +// This implementation should **not** show up. +impl From<&T> for Bar { + fn from(s: &T) -> Self { + Bar + } +} + +pub trait Foo { + fn stuff(&self, other: &T) {} +} + +// This implementation should show up. +impl Foo<&A> for &B {} From fe29ac9a4411836d9ec84947124411232e52b895 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 31 Aug 2022 14:21:35 +0200 Subject: [PATCH 24/24] fix into_iter on ZST --- library/alloc/src/vec/into_iter.rs | 2 +- library/alloc/tests/vec.rs | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs index ed049194dd068..b4157fd589541 100644 --- a/library/alloc/src/vec/into_iter.rs +++ b/library/alloc/src/vec/into_iter.rs @@ -266,7 +266,7 @@ impl DoubleEndedIterator for IntoIter { None } else if mem::size_of::() == 0 { // See above for why 'ptr.offset' isn't used - self.end = self.ptr.wrapping_byte_sub(1); + self.end = self.end.wrapping_byte_sub(1); // Make up a value of this ZST. Some(unsafe { mem::zeroed() }) diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs index 4c118455a3fc3..f140fc4143f3f 100644 --- a/library/alloc/tests/vec.rs +++ b/library/alloc/tests/vec.rs @@ -1104,6 +1104,12 @@ fn test_into_iter_drop_allocator() { assert_eq!(drop_count, 2); } +#[test] +fn test_into_iter_zst() { + for _ in vec![[0u64; 0]].into_iter() {} + for _ in vec![[0u64; 0]; 5].into_iter().rev() {} +} + #[test] fn test_from_iter_specialization() { let src: Vec = vec![0usize; 1];