From 00a7bfc99294d57bb4ee58a3382f22c30600ef44 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 25 Sep 2022 22:23:36 +0000 Subject: [PATCH 01/20] Elaborate supertrait bounds when triggering unused_must_use on impl Trait --- compiler/rustc_lint/src/unused.rs | 8 ++++++-- src/test/ui/lint/unused/unused-supertrait.rs | 11 +++++++++++ src/test/ui/lint/unused/unused-supertrait.stderr | 15 +++++++++++++++ 3 files changed, 32 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/lint/unused/unused-supertrait.rs create mode 100644 src/test/ui/lint/unused/unused-supertrait.stderr diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 3d426ecbfcb05..dca61e3768152 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -7,6 +7,7 @@ use rustc_errors::{fluent, pluralize, Applicability, MultiSpan}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; +use rustc_infer::traits::util::elaborate_predicates_with_span; use rustc_middle::ty::adjustment; use rustc_middle::ty::{self, Ty}; use rustc_span::symbol::Symbol; @@ -206,10 +207,13 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { ty::Adt(def, _) => check_must_use_def(cx, def.did(), span, descr_pre, descr_post), ty::Opaque(def, _) => { let mut has_emitted = false; - for &(predicate, _) in cx.tcx.explicit_item_bounds(def) { + for obligation in elaborate_predicates_with_span( + cx.tcx, + cx.tcx.explicit_item_bounds(def).iter().cloned(), + ) { // We only look at the `DefId`, so it is safe to skip the binder here. if let ty::PredicateKind::Trait(ref poly_trait_predicate) = - predicate.kind().skip_binder() + obligation.predicate.kind().skip_binder() { let def_id = poly_trait_predicate.trait_ref.def_id; let descr_pre = diff --git a/src/test/ui/lint/unused/unused-supertrait.rs b/src/test/ui/lint/unused/unused-supertrait.rs new file mode 100644 index 0000000000000..64a8e5204579c --- /dev/null +++ b/src/test/ui/lint/unused/unused-supertrait.rs @@ -0,0 +1,11 @@ +#![deny(unused_must_use)] + +fn it() -> impl ExactSizeIterator { + let x: Box> = todo!(); + x +} + +fn main() { + it(); + //~^ ERROR unused implementer of `Iterator` that must be used +} diff --git a/src/test/ui/lint/unused/unused-supertrait.stderr b/src/test/ui/lint/unused/unused-supertrait.stderr new file mode 100644 index 0000000000000..0a3eca314d47a --- /dev/null +++ b/src/test/ui/lint/unused/unused-supertrait.stderr @@ -0,0 +1,15 @@ +error: unused implementer of `Iterator` that must be used + --> $DIR/unused-supertrait.rs:9:5 + | +LL | it(); + | ^^^^^ + | +note: the lint level is defined here + --> $DIR/unused-supertrait.rs:1:9 + | +LL | #![deny(unused_must_use)] + | ^^^^^^^^^^^^^^^ + = note: iterators are lazy and do nothing unless consumed + +error: aborting due to previous error + From afe29e48bc4d57c1bb73228ba8d70dc8f42436fc Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Wed, 5 Oct 2022 11:23:57 +0200 Subject: [PATCH 02/20] split steps for generating the standalone docs and the shared assets Before this commit, the step to generate the standalone docs (which included the index page and other HTML files at the root of the documentation) was bundled with the code copying files needed by multiple pieces of documentation. This means it wasn't possible to avoid generating the standalone docs. This commit splits the step into two, allowing the standalone docs generation to be excluded while still building the rest of the docs. --- src/bootstrap/doc.rs | 61 ++++++++++++++++++++++++++++++++------------ 1 file changed, 45 insertions(+), 16 deletions(-) diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 819af6587484d..b286c79a30307 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -227,7 +227,7 @@ impl Step for TheBook { } // build the version info page and CSS - builder.ensure(Standalone { compiler, target }); + let shared_assets = builder.ensure(SharedAssets { target }); // build the redirect pages builder.info(&format!("Documenting book redirect pages ({})", target)); @@ -236,7 +236,7 @@ impl Step for TheBook { let path = file.path(); let path = path.to_str().unwrap(); - invoke_rustdoc(builder, compiler, target, path); + invoke_rustdoc(builder, compiler, &shared_assets, target, path); } if builder.was_invoked_explicitly::(Kind::Doc) { @@ -250,6 +250,7 @@ impl Step for TheBook { fn invoke_rustdoc( builder: &Builder<'_>, compiler: Compiler, + shared_assets: &SharedAssetsPaths, target: TargetSelection, markdown: &str, ) { @@ -259,7 +260,6 @@ fn invoke_rustdoc( let header = builder.src.join("src/doc/redirect.inc"); let footer = builder.src.join("src/doc/footer.inc"); - let version_info = out.join("version_info.html"); let mut cmd = builder.rustdoc_cmd(compiler); @@ -268,7 +268,7 @@ fn invoke_rustdoc( cmd.arg("--html-after-content") .arg(&footer) .arg("--html-before-content") - .arg(&version_info) + .arg(&shared_assets.version_info) .arg("--html-in-header") .arg(&header) .arg("--markdown-no-toc") @@ -324,21 +324,11 @@ impl Step for Standalone { let out = builder.doc_out(target); t!(fs::create_dir_all(&out)); + let version_info = builder.ensure(SharedAssets { target: self.target }).version_info; + let favicon = builder.src.join("src/doc/favicon.inc"); let footer = builder.src.join("src/doc/footer.inc"); let full_toc = builder.src.join("src/doc/full-toc.inc"); - t!(fs::copy(builder.src.join("src/doc/rust.css"), out.join("rust.css"))); - - let version_input = builder.src.join("src/doc/version_info.html.template"); - let version_info = out.join("version_info.html"); - - if !builder.config.dry_run && !up_to_date(&version_input, &version_info) { - let info = t!(fs::read_to_string(&version_input)) - .replace("VERSION", &builder.rust_release()) - .replace("SHORT_HASH", builder.rust_info.sha_short().unwrap_or("")) - .replace("STAMP", builder.rust_info.sha().unwrap_or("")); - t!(fs::write(&version_info, &info)); - } for file in t!(fs::read_dir(builder.src.join("src/doc"))) { let file = t!(file); @@ -400,6 +390,45 @@ impl Step for Standalone { } } +#[derive(Debug, Clone)] +pub struct SharedAssetsPaths { + pub version_info: PathBuf, +} + +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct SharedAssets { + target: TargetSelection, +} + +impl Step for SharedAssets { + type Output = SharedAssetsPaths; + const DEFAULT: bool = false; + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + // Other tasks depend on this, no need to execute it on its own + run.never() + } + + // Generate shared resources used by other pieces of documentation. + fn run(self, builder: &Builder<'_>) -> Self::Output { + let out = builder.doc_out(self.target); + + let version_input = builder.src.join("src").join("doc").join("version_info.html.template"); + let version_info = out.join("version_info.html"); + if !builder.config.dry_run && !up_to_date(&version_input, &version_info) { + let info = t!(fs::read_to_string(&version_input)) + .replace("VERSION", &builder.rust_release()) + .replace("SHORT_HASH", builder.rust_info.sha_short().unwrap_or("")) + .replace("STAMP", builder.rust_info.sha().unwrap_or("")); + t!(fs::write(&version_info, &info)); + } + + builder.copy(&builder.src.join("src").join("doc").join("rust.css"), &out.join("rust.css")); + + SharedAssetsPaths { version_info } + } +} + #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct Std { pub stage: u32, From 004b8b98d626a89b5d4cdc630ff337c0f4ea919f Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Wed, 5 Oct 2022 12:45:52 +0200 Subject: [PATCH 03/20] add a "standalone" path for doc::Standalone to be able to exclude it Before this commit, the path for the doc::Standalone step was "src/doc", which is accurate as the standalone docs source files live at the root of the "src/doc" directory tree. Unfortunately, that caused bad interactions when trying to exclude it with `--exclude src/doc`. When an exclusion is passed to bootstrap, it will exclude all steps whose path *ends with* the exclusion, which results in the Cargo book (src/tools/cargo/src/doc) to also be excluded. To work around this problem, this commit adds the "standalone" path as an alternate path for doc::Standalone, allowing `--exclude standalone` to work without side effects. --- src/bootstrap/doc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index b286c79a30307..a8524fea1b2a0 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -299,7 +299,7 @@ impl Step for Standalone { fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { let builder = run.builder; - run.path("src/doc").default_condition(builder.config.docs) + run.path("src/doc").path("standalone").default_condition(builder.config.docs) } fn make_run(run: RunConfig<'_>) { From 76bec177bca25a35aa55a364bb8d2d66e0d5d45e Mon Sep 17 00:00:00 2001 From: Tomoaki Kawada Date: Thu, 13 Oct 2022 14:16:12 +0900 Subject: [PATCH 04/20] kmc-solid: Handle errors returned by `SOLID_FS_ReadDir` --- library/std/src/sys/solid/fs.rs | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/library/std/src/sys/solid/fs.rs b/library/std/src/sys/solid/fs.rs index 9692222534eaa..6c66b93a3e1a3 100644 --- a/library/std/src/sys/solid/fs.rs +++ b/library/std/src/sys/solid/fs.rs @@ -175,15 +175,19 @@ impl Iterator for ReadDir { type Item = io::Result; fn next(&mut self) -> Option> { - unsafe { - let mut out_dirent = MaybeUninit::uninit(); - error::SolidError::err_if_negative(abi::SOLID_FS_ReadDir( + let entry = unsafe { + let mut out_entry = MaybeUninit::uninit(); + match error::SolidError::err_if_negative(abi::SOLID_FS_ReadDir( self.inner.dirp, - out_dirent.as_mut_ptr(), - )) - .ok()?; - Some(Ok(DirEntry { entry: out_dirent.assume_init(), inner: Arc::clone(&self.inner) })) - } + out_entry.as_mut_ptr(), + )) { + Ok(_) => out_entry.assume_init(), + Err(e) if e.as_raw() == abi::SOLID_ERR_NOTFOUND => return None, + Err(e) => return Some(Err(e.as_io_error())), + } + }; + + (entry.d_name[0] != 0).then(|| Ok(DirEntry { entry, inner: Arc::clone(&self.inner) })) } } From 7fbaf2769634ac1800449a6d2d818615cef7eace Mon Sep 17 00:00:00 2001 From: David Wood Date: Fri, 14 Oct 2022 11:00:46 +0100 Subject: [PATCH 05/20] macros: support doc comments in diag derives Documentation comments shouldn't affect the diagnostic derive in any way, but explicit support has to be added for ignoring the `doc` attribute. Signed-off-by: David Wood --- .../src/diagnostics/diagnostic_builder.rs | 35 +++++++++++++++---- .../src/diagnostics/subdiagnostic.rs | 22 +++++++++--- .../rustc_macros/src/diagnostics/utils.rs | 17 +++++++-- .../session-diagnostic/diagnostic-derive.rs | 9 +++++ .../subdiagnostic-derive.rs | 21 +++++++++++ 5 files changed, 90 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs index dcbe89251cb36..9f7d2661a3e8b 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs @@ -5,7 +5,7 @@ use crate::diagnostics::error::{ DiagnosticDeriveError, }; use crate::diagnostics::utils::{ - build_field_mapping, report_error_if_not_applied_to_span, report_type_error, + build_field_mapping, is_doc_comment, report_error_if_not_applied_to_span, report_type_error, should_generate_set_arg, type_is_unit, type_matches_path, FieldInfo, FieldInnerTy, FieldMap, HasFieldMap, SetOnce, SpannedOption, SubdiagnosticKind, }; @@ -152,8 +152,12 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { fn parse_subdiag_attribute( &self, attr: &Attribute, - ) -> Result<(SubdiagnosticKind, Path), DiagnosticDeriveError> { - let (subdiag, slug) = SubdiagnosticKind::from_attr(attr, self)?; + ) -> Result, DiagnosticDeriveError> { + let Some((subdiag, slug)) = SubdiagnosticKind::from_attr(attr, self)? else { + // Some attributes aren't errors - like documentation comments - but also aren't + // subdiagnostics. + return Ok(None); + }; if let SubdiagnosticKind::MultipartSuggestion { .. } = subdiag { let meta = attr.parse_meta()?; @@ -170,7 +174,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { SubdiagnosticKind::MultipartSuggestion { .. } => unreachable!(), }); - Ok((subdiag, slug)) + Ok(Some((subdiag, slug))) } /// Establishes state in the `DiagnosticDeriveBuilder` resulting from the struct @@ -182,6 +186,11 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { ) -> Result { let diag = &self.parent.diag; + // Always allow documentation comments. + if is_doc_comment(attr) { + return Ok(quote! {}); + } + let name = attr.path.segments.last().unwrap().ident.to_string(); let name = name.as_str(); let meta = attr.parse_meta()?; @@ -250,7 +259,11 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { return Ok(tokens); } - let (subdiag, slug) = self.parse_subdiag_attribute(attr)?; + let Some((subdiag, slug)) = self.parse_subdiag_attribute(attr)? else { + // Some attributes aren't errors - like documentation comments - but also aren't + // subdiagnostics. + return Ok(quote! {}); + }; let fn_ident = format_ident!("{}", subdiag); match subdiag { SubdiagnosticKind::Note | SubdiagnosticKind::Help | SubdiagnosticKind::Warn => { @@ -291,6 +304,11 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { .attrs .iter() .map(move |attr| { + // Always allow documentation comments. + if is_doc_comment(attr) { + return quote! {}; + } + let name = attr.path.segments.last().unwrap().ident.to_string(); let needs_clone = name == "primary_span" && matches!(inner_ty, FieldInnerTy::Vec(_)); @@ -397,8 +415,11 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { _ => (), } - let (subdiag, slug) = self.parse_subdiag_attribute(attr)?; - + let Some((subdiag, slug)) = self.parse_subdiag_attribute(attr)? else { + // Some attributes aren't errors - like documentation comments - but also aren't + // subdiagnostics. + return Ok(quote! {}); + }; let fn_ident = format_ident!("{}", subdiag); match subdiag { SubdiagnosticKind::Label => { diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index 3d4c3ab9fd7c9..4fe02e8160797 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -5,9 +5,9 @@ use crate::diagnostics::error::{ DiagnosticDeriveError, }; use crate::diagnostics::utils::{ - build_field_mapping, new_code_ident, report_error_if_not_applied_to_applicability, - report_error_if_not_applied_to_span, FieldInfo, FieldInnerTy, FieldMap, HasFieldMap, SetOnce, - SpannedOption, SubdiagnosticKind, + build_field_mapping, is_doc_comment, new_code_ident, + report_error_if_not_applied_to_applicability, report_error_if_not_applied_to_span, FieldInfo, + FieldInnerTy, FieldMap, HasFieldMap, SetOnce, SpannedOption, SubdiagnosticKind, }; use proc_macro2::TokenStream; use quote::{format_ident, quote}; @@ -43,6 +43,11 @@ impl SubdiagnosticDeriveBuilder { if matches!(ast.data, syn::Data::Enum(..)) { for attr in &ast.attrs { + // Always allow documentation comments. + if is_doc_comment(attr) { + continue; + } + span_err( attr.span().unwrap(), "unsupported type attribute for subdiagnostic enum", @@ -173,7 +178,11 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { let mut kind_slugs = vec![]; for attr in self.variant.ast().attrs { - let (kind, slug) = SubdiagnosticKind::from_attr(attr, self)?; + let Some((kind, slug)) = SubdiagnosticKind::from_attr(attr, self)? else { + // Some attributes aren't errors - like documentation comments - but also aren't + // subdiagnostics. + continue; + }; let Some(slug) = slug else { let name = attr.path.segments.last().unwrap().ident.to_string(); @@ -227,6 +236,11 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { ast.attrs .iter() .map(|attr| { + // Always allow documentation comments. + if is_doc_comment(attr) { + return quote! {}; + } + let info = FieldInfo { binding, ty: inner_ty.inner_type().unwrap_or(&ast.ty), diff --git a/compiler/rustc_macros/src/diagnostics/utils.rs b/compiler/rustc_macros/src/diagnostics/utils.rs index 4fd4adc511267..61d5007fc30f0 100644 --- a/compiler/rustc_macros/src/diagnostics/utils.rs +++ b/compiler/rustc_macros/src/diagnostics/utils.rs @@ -477,7 +477,12 @@ impl SubdiagnosticKind { pub(super) fn from_attr( attr: &Attribute, fields: &impl HasFieldMap, - ) -> Result<(SubdiagnosticKind, Option), DiagnosticDeriveError> { + ) -> Result)>, DiagnosticDeriveError> { + // Always allow documentation comments. + if is_doc_comment(attr) { + return Ok(None); + } + let span = attr.span().unwrap(); let name = attr.path.segments.last().unwrap().ident.to_string(); @@ -526,7 +531,9 @@ impl SubdiagnosticKind { | SubdiagnosticKind::Note | SubdiagnosticKind::Help | SubdiagnosticKind::Warn - | SubdiagnosticKind::MultipartSuggestion { .. } => return Ok((kind, None)), + | SubdiagnosticKind::MultipartSuggestion { .. } => { + return Ok(Some((kind, None))); + } SubdiagnosticKind::Suggestion { .. } => { throw_span_err!(span, "suggestion without `code = \"...\"`") } @@ -626,7 +633,7 @@ impl SubdiagnosticKind { | SubdiagnosticKind::MultipartSuggestion { .. } => {} } - Ok((kind, slug)) + Ok(Some((kind, slug))) } } @@ -654,3 +661,7 @@ impl quote::IdentFragment for SubdiagnosticKind { pub(super) fn should_generate_set_arg(field: &Field) -> bool { field.attrs.is_empty() } + +pub(super) fn is_doc_comment(attr: &Attribute) -> bool { + attr.path.segments.last().unwrap().ident.to_string() == "doc" +} diff --git a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs index e873c36e0b39a..b8deb48d49add 100644 --- a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs +++ b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs @@ -749,3 +749,12 @@ struct SubdiagnosticEagerSuggestion { #[subdiagnostic(eager)] sub: SubdiagnosticWithSuggestion, } + +/// with a doc comment on the type.. +#[derive(Diagnostic)] +#[diag(compiletest::example, code = "E0123")] +struct WithDocComment { + /// ..and the field + #[primary_span] + span: Span, +} diff --git a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs index 84ee5af42dea5..31aae7ba12d42 100644 --- a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs +++ b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs @@ -641,3 +641,24 @@ struct BJ { span: Span, r#type: String, } + +/// with a doc comment on the type.. +#[derive(Subdiagnostic)] +#[label(parser::add_paren)] +struct BK { + /// ..and the field + #[primary_span] + span: Span, +} + +/// with a doc comment on the type.. +#[derive(Subdiagnostic)] +enum BL { + /// ..and the variant.. + #[label(parser::add_paren)] + Foo { + /// ..and the field + #[primary_span] + span: Span, + } +} From 1045e69e7331734d59ac85391443db9bd29fd2be Mon Sep 17 00:00:00 2001 From: David Wood Date: Fri, 14 Oct 2022 11:09:52 +0100 Subject: [PATCH 06/20] macros: allow subdiagnostic-kind-less variants Sometimes it is convenient to return a subdiagnostic enum where one or more of the variants don't add anything to the diagnostic. Signed-off-by: David Wood --- .../src/diagnostics/subdiagnostic.rs | 21 ++++- .../subdiagnostic-derive.rs | 1 - .../subdiagnostic-derive.stderr | 92 +++++++++---------- 3 files changed, 59 insertions(+), 55 deletions(-) diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index 4fe02e8160797..0b82cb5097eb3 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -41,7 +41,8 @@ impl SubdiagnosticDeriveBuilder { } } - if matches!(ast.data, syn::Data::Enum(..)) { + let is_enum = matches!(ast.data, syn::Data::Enum(..)); + if is_enum { for attr in &ast.attrs { // Always allow documentation comments. if is_doc_comment(attr) { @@ -67,6 +68,7 @@ impl SubdiagnosticDeriveBuilder { span_field: None, applicability: None, has_suggestion_parts: false, + is_enum, }; builder.into_tokens().unwrap_or_else(|v| v.to_compile_error()) }); @@ -127,6 +129,9 @@ struct SubdiagnosticDeriveVariantBuilder<'parent, 'a> { /// Set to true when a `#[suggestion_part]` field is encountered, used to generate an error /// during finalization if still `false`. has_suggestion_parts: bool, + + /// Set to true when this variant is an enum variant rather than just the body of a struct. + is_enum: bool, } impl<'parent, 'a> HasFieldMap for SubdiagnosticDeriveVariantBuilder<'parent, 'a> { @@ -457,10 +462,16 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { pub fn into_tokens(&mut self) -> Result { let kind_slugs = self.identify_kind()?; if kind_slugs.is_empty() { - throw_span_err!( - self.variant.ast().ident.span().unwrap(), - "subdiagnostic kind not specified" - ); + if self.is_enum { + // It's okay for a variant to not be a subdiagnostic at all.. + return Ok(quote! {}); + } else { + // ..but structs should always be _something_. + throw_span_err!( + self.variant.ast().ident.span().unwrap(), + "subdiagnostic kind not specified" + ); + } }; let kind_stats: KindsStatistics = kind_slugs.iter().map(|(kind, _slug)| kind).collect(); diff --git a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs index 31aae7ba12d42..2fe93d46d0ac0 100644 --- a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs +++ b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs @@ -237,7 +237,6 @@ enum V { var: String, }, B { - //~^ ERROR subdiagnostic kind not specified #[primary_span] span: Span, var: String, diff --git a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr index 171b89e657d81..1173d24248bc4 100644 --- a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr +++ b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr @@ -134,20 +134,14 @@ error: diagnostic slug must be first argument of a `#[label(...)]` attribute LL | #[label(code = "...")] | ^^^^^^^^^^^^^^^^^^^^^^ -error: subdiagnostic kind not specified - --> $DIR/subdiagnostic-derive.rs:239:5 - | -LL | B { - | ^ - error: the `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan` - --> $DIR/subdiagnostic-derive.rs:251:5 + --> $DIR/subdiagnostic-derive.rs:250:5 | LL | #[primary_span] | ^^^^^^^^^^^^^^^ error: label without `#[primary_span]` field - --> $DIR/subdiagnostic-derive.rs:248:1 + --> $DIR/subdiagnostic-derive.rs:247:1 | LL | / #[label(parser::add_paren)] LL | | @@ -159,13 +153,13 @@ LL | | } | |_^ error: `#[applicability]` is only valid on suggestions - --> $DIR/subdiagnostic-derive.rs:261:5 + --> $DIR/subdiagnostic-derive.rs:260:5 | LL | #[applicability] | ^^^^^^^^^^^^^^^^ error: `#[bar]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:271:5 + --> $DIR/subdiagnostic-derive.rs:270:5 | LL | #[bar] | ^^^^^^ @@ -173,13 +167,13 @@ LL | #[bar] = help: only `primary_span`, `applicability` and `skip_arg` are valid field attributes error: `#[bar = ...]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:282:5 + --> $DIR/subdiagnostic-derive.rs:281:5 | LL | #[bar = "..."] | ^^^^^^^^^^^^^^ error: `#[bar(...)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:293:5 + --> $DIR/subdiagnostic-derive.rs:292:5 | LL | #[bar("...")] | ^^^^^^^^^^^^^ @@ -187,7 +181,7 @@ LL | #[bar("...")] = help: only `primary_span`, `applicability` and `skip_arg` are valid field attributes error: unexpected unsupported untagged union - --> $DIR/subdiagnostic-derive.rs:309:1 + --> $DIR/subdiagnostic-derive.rs:308:1 | LL | / union AC { LL | | @@ -197,7 +191,7 @@ LL | | } | |_^ error: `#[label(parser::add_paren)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:324:28 + --> $DIR/subdiagnostic-derive.rs:323:28 | LL | #[label(parser::add_paren, parser::add_paren)] | ^^^^^^^^^^^^^^^^^ @@ -205,67 +199,67 @@ LL | #[label(parser::add_paren, parser::add_paren)] = help: a diagnostic slug must be the first argument to the attribute error: specified multiple times - --> $DIR/subdiagnostic-derive.rs:337:5 + --> $DIR/subdiagnostic-derive.rs:336:5 | LL | #[primary_span] | ^^^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/subdiagnostic-derive.rs:334:5 + --> $DIR/subdiagnostic-derive.rs:333:5 | LL | #[primary_span] | ^^^^^^^^^^^^^^^ error: subdiagnostic kind not specified - --> $DIR/subdiagnostic-derive.rs:343:8 + --> $DIR/subdiagnostic-derive.rs:342:8 | LL | struct AG { | ^^ error: specified multiple times - --> $DIR/subdiagnostic-derive.rs:380:47 + --> $DIR/subdiagnostic-derive.rs:379:47 | LL | #[suggestion(parser::add_paren, code = "...", code = "...")] | ^^^^^^^^^^^^ | note: previously specified here - --> $DIR/subdiagnostic-derive.rs:380:33 + --> $DIR/subdiagnostic-derive.rs:379:33 | LL | #[suggestion(parser::add_paren, code = "...", code = "...")] | ^^^^^^^^^^^^ error: specified multiple times - --> $DIR/subdiagnostic-derive.rs:398:5 + --> $DIR/subdiagnostic-derive.rs:397:5 | LL | #[applicability] | ^^^^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/subdiagnostic-derive.rs:395:5 + --> $DIR/subdiagnostic-derive.rs:394:5 | LL | #[applicability] | ^^^^^^^^^^^^^^^^ error: the `#[applicability]` attribute can only be applied to fields of type `Applicability` - --> $DIR/subdiagnostic-derive.rs:408:5 + --> $DIR/subdiagnostic-derive.rs:407:5 | LL | #[applicability] | ^^^^^^^^^^^^^^^^ error: suggestion without `code = "..."` - --> $DIR/subdiagnostic-derive.rs:421:1 + --> $DIR/subdiagnostic-derive.rs:420:1 | LL | #[suggestion(parser::add_paren)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: invalid applicability - --> $DIR/subdiagnostic-derive.rs:431:46 + --> $DIR/subdiagnostic-derive.rs:430:46 | LL | #[suggestion(parser::add_paren, code ="...", applicability = "foo")] | ^^^^^^^^^^^^^^^^^^^^^ error: suggestion without `#[primary_span]` field - --> $DIR/subdiagnostic-derive.rs:449:1 + --> $DIR/subdiagnostic-derive.rs:448:1 | LL | / #[suggestion(parser::add_paren, code = "...")] LL | | @@ -275,25 +269,25 @@ LL | | } | |_^ error: unsupported type attribute for subdiagnostic enum - --> $DIR/subdiagnostic-derive.rs:463:1 + --> $DIR/subdiagnostic-derive.rs:462:1 | LL | #[label] | ^^^^^^^^ error: `var` doesn't refer to a field on this type - --> $DIR/subdiagnostic-derive.rs:483:39 + --> $DIR/subdiagnostic-derive.rs:482:39 | LL | #[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")] | ^^^^^^^ error: `var` doesn't refer to a field on this type - --> $DIR/subdiagnostic-derive.rs:502:43 + --> $DIR/subdiagnostic-derive.rs:501:43 | LL | #[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")] | ^^^^^^^ error: `#[suggestion_part]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:525:5 + --> $DIR/subdiagnostic-derive.rs:524:5 | LL | #[suggestion_part] | ^^^^^^^^^^^^^^^^^^ @@ -301,7 +295,7 @@ LL | #[suggestion_part] = help: `#[suggestion_part(...)]` is only valid in multipart suggestions, use `#[primary_span]` instead error: `#[suggestion_part(...)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:528:5 + --> $DIR/subdiagnostic-derive.rs:527:5 | LL | #[suggestion_part(code = "...")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -309,7 +303,7 @@ LL | #[suggestion_part(code = "...")] = help: `#[suggestion_part(...)]` is only valid in multipart suggestions error: suggestion without `#[primary_span]` field - --> $DIR/subdiagnostic-derive.rs:522:1 + --> $DIR/subdiagnostic-derive.rs:521:1 | LL | / #[suggestion(parser::add_paren, code = "...")] LL | | @@ -321,7 +315,7 @@ LL | | } | |_^ error: `#[multipart_suggestion(code = ...)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:537:43 + --> $DIR/subdiagnostic-derive.rs:536:43 | LL | #[multipart_suggestion(parser::add_paren, code = "...", applicability = "machine-applicable")] | ^^^^^^^^^^^^ @@ -329,7 +323,7 @@ LL | #[multipart_suggestion(parser::add_paren, code = "...", applicability = "ma = help: only `applicability` is a valid nested attributes error: multipart suggestion without any `#[suggestion_part(...)]` fields - --> $DIR/subdiagnostic-derive.rs:537:1 + --> $DIR/subdiagnostic-derive.rs:536:1 | LL | / #[multipart_suggestion(parser::add_paren, code = "...", applicability = "machine-applicable")] LL | | @@ -340,19 +334,19 @@ LL | | } | |_^ error: `#[suggestion_part(...)]` attribute without `code = "..."` - --> $DIR/subdiagnostic-derive.rs:547:5 + --> $DIR/subdiagnostic-derive.rs:546:5 | LL | #[suggestion_part] | ^^^^^^^^^^^^^^^^^^ error: `#[suggestion_part(...)]` attribute without `code = "..."` - --> $DIR/subdiagnostic-derive.rs:555:5 + --> $DIR/subdiagnostic-derive.rs:554:5 | LL | #[suggestion_part()] | ^^^^^^^^^^^^^^^^^^^^ error: `#[primary_span]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:564:5 + --> $DIR/subdiagnostic-derive.rs:563:5 | LL | #[primary_span] | ^^^^^^^^^^^^^^^ @@ -360,7 +354,7 @@ LL | #[primary_span] = help: multipart suggestions use one or more `#[suggestion_part]`s rather than one `#[primary_span]` error: multipart suggestion without any `#[suggestion_part(...)]` fields - --> $DIR/subdiagnostic-derive.rs:561:1 + --> $DIR/subdiagnostic-derive.rs:560:1 | LL | / #[multipart_suggestion(parser::add_paren)] LL | | @@ -372,19 +366,19 @@ LL | | } | |_^ error: `#[suggestion_part(...)]` attribute without `code = "..."` - --> $DIR/subdiagnostic-derive.rs:572:5 + --> $DIR/subdiagnostic-derive.rs:571:5 | LL | #[suggestion_part] | ^^^^^^^^^^^^^^^^^^ error: `#[suggestion_part(...)]` attribute without `code = "..."` - --> $DIR/subdiagnostic-derive.rs:575:5 + --> $DIR/subdiagnostic-derive.rs:574:5 | LL | #[suggestion_part()] | ^^^^^^^^^^^^^^^^^^^^ error: `#[suggestion_part(foo = ...)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:578:23 + --> $DIR/subdiagnostic-derive.rs:577:23 | LL | #[suggestion_part(foo = "bar")] | ^^^^^^^^^^^ @@ -392,31 +386,31 @@ LL | #[suggestion_part(foo = "bar")] = help: `code` is the only valid nested attribute error: the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan` - --> $DIR/subdiagnostic-derive.rs:581:5 + --> $DIR/subdiagnostic-derive.rs:580:5 | LL | #[suggestion_part(code = "...")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan` - --> $DIR/subdiagnostic-derive.rs:584:5 + --> $DIR/subdiagnostic-derive.rs:583:5 | LL | #[suggestion_part()] | ^^^^^^^^^^^^^^^^^^^^ error: specified multiple times - --> $DIR/subdiagnostic-derive.rs:592:37 + --> $DIR/subdiagnostic-derive.rs:591:37 | LL | #[suggestion_part(code = "...", code = ",,,")] | ^^^^^^^^^^^^ | note: previously specified here - --> $DIR/subdiagnostic-derive.rs:592:23 + --> $DIR/subdiagnostic-derive.rs:591:23 | LL | #[suggestion_part(code = "...", code = ",,,")] | ^^^^^^^^^^^^ error: `#[applicability]` has no effect if all `#[suggestion]`/`#[multipart_suggestion]` attributes have a static `applicability = "..."` - --> $DIR/subdiagnostic-derive.rs:621:5 + --> $DIR/subdiagnostic-derive.rs:620:5 | LL | #[applicability] | ^^^^^^^^^^^^^^^^ @@ -458,19 +452,19 @@ LL | #[bar("...")] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:271:7 + --> $DIR/subdiagnostic-derive.rs:270:7 | LL | #[bar] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:282:7 + --> $DIR/subdiagnostic-derive.rs:281:7 | LL | #[bar = "..."] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:293:7 + --> $DIR/subdiagnostic-derive.rs:292:7 | LL | #[bar("...")] | ^^^ @@ -481,6 +475,6 @@ error[E0425]: cannot find value `slug` in module `rustc_errors::fluent` LL | #[label(slug)] | ^^^^ not found in `rustc_errors::fluent` -error: aborting due to 68 previous errors +error: aborting due to 67 previous errors For more information about this error, try `rustc --explain E0425`. From feeeb11d89d4f379085d5ee1374b3660e46815e3 Mon Sep 17 00:00:00 2001 From: David Wood Date: Fri, 14 Oct 2022 11:12:13 +0100 Subject: [PATCH 07/20] macros: fully specify path to `Fn` Signed-off-by: David Wood --- compiler/rustc_macros/src/diagnostics/subdiagnostic.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index 0b82cb5097eb3..5a42a2cd12dd6 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -86,7 +86,7 @@ impl SubdiagnosticDeriveBuilder { gen impl rustc_errors::AddToDiagnostic for @Self { fn add_to_diagnostic_with<__F>(self, #diag: &mut rustc_errors::Diagnostic, #f: __F) where - __F: Fn( + __F: core::ops::Fn( &mut rustc_errors::Diagnostic, rustc_errors::SubdiagnosticMessage ) -> rustc_errors::SubdiagnosticMessage, From 2a4b587a68e6fef52b478b516d18be4621c4b64b Mon Sep 17 00:00:00 2001 From: David Wood Date: Fri, 14 Oct 2022 13:10:49 +0100 Subject: [PATCH 08/20] ast_lowering: use derive more Signed-off-by: David Wood --- compiler/rustc_ast_lowering/src/errors.rs | 59 +++++++---------------- 1 file changed, 18 insertions(+), 41 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs index c6c85ffa84dd7..17ca1aa7fe170 100644 --- a/compiler/rustc_ast_lowering/src/errors.rs +++ b/compiler/rustc_ast_lowering/src/errors.rs @@ -1,7 +1,4 @@ -use rustc_errors::{ - fluent, AddToDiagnostic, Applicability, Diagnostic, DiagnosticArgFromDisplay, - SubdiagnosticMessage, -}; +use rustc_errors::DiagnosticArgFromDisplay; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{symbol::Ident, Span, Symbol}; @@ -15,25 +12,15 @@ pub struct GenericTypeWithParentheses { pub sub: Option, } -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Subdiagnostic)] +#[multipart_suggestion(ast_lowering::use_angle_brackets, applicability = "maybe-incorrect")] pub struct UseAngleBrackets { + #[suggestion_part(code = "<")] pub open_param: Span, + #[suggestion_part(code = ">")] pub close_param: Span, } -impl AddToDiagnostic for UseAngleBrackets { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { - diag.multipart_suggestion( - fluent::ast_lowering::use_angle_brackets, - vec![(self.open_param, String::from("<")), (self.close_param, String::from(">"))], - Applicability::MaybeIncorrect, - ); - } -} - #[derive(Diagnostic)] #[diag(ast_lowering::invalid_abi, code = "E0703")] #[note] @@ -68,30 +55,20 @@ pub struct AssocTyParentheses { pub sub: AssocTyParenthesesSub, } -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Subdiagnostic)] pub enum AssocTyParenthesesSub { - Empty { parentheses_span: Span }, - NotEmpty { open_param: Span, close_param: Span }, -} - -impl AddToDiagnostic for AssocTyParenthesesSub { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { - match self { - Self::Empty { parentheses_span } => diag.multipart_suggestion( - fluent::ast_lowering::remove_parentheses, - vec![(parentheses_span, String::new())], - Applicability::MaybeIncorrect, - ), - Self::NotEmpty { open_param, close_param } => diag.multipart_suggestion( - fluent::ast_lowering::use_angle_brackets, - vec![(open_param, String::from("<")), (close_param, String::from(">"))], - Applicability::MaybeIncorrect, - ), - }; - } + #[multipart_suggestion(ast_lowering::remove_parentheses)] + Empty { + #[suggestion_part(code = "")] + parentheses_span: Span, + }, + #[multipart_suggestion(ast_lowering::use_angle_brackets)] + NotEmpty { + #[suggestion_part(code = "<")] + open_param: Span, + #[suggestion_part(code = ">")] + close_param: Span, + }, } #[derive(Diagnostic)] From ea5d258a7560c0cb5b6080258ccae4a7e4d6277e Mon Sep 17 00:00:00 2001 From: David Wood Date: Fri, 14 Oct 2022 13:11:21 +0100 Subject: [PATCH 09/20] ast_passes: use derive more Signed-off-by: David Wood --- compiler/rustc_ast_passes/src/ast_validation.rs | 9 ++++++--- compiler/rustc_ast_passes/src/errors.rs | 17 ----------------- 2 files changed, 6 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 1a4c60087c385..1dc8b85d7e6e7 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -14,6 +14,7 @@ use rustc_ast::*; use rustc_ast_pretty::pprust::{self, State}; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{error_code, fluent, pluralize, struct_span_err, Applicability}; +use rustc_macros::Subdiagnostic; use rustc_parse::validate_attr; use rustc_session::lint::builtin::{ DEPRECATED_WHERE_CLAUSE_LOCATION, MISSING_ABI, PATTERNS_IN_FNS_WITHOUT_BODY, @@ -1782,15 +1783,17 @@ pub fn check_crate(session: &Session, krate: &Crate, lints: &mut LintBuffer) -> } /// Used to forbid `let` expressions in certain syntactic locations. -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Subdiagnostic)] pub(crate) enum ForbiddenLetReason { /// `let` is not valid and the source environment is not important GenericForbidden, /// A let chain with the `||` operator - NotSupportedOr(Span), + #[note(ast_passes::not_supported_or)] + NotSupportedOr(#[primary_span] Span), /// A let chain with invalid parentheses /// /// For example, `let 1 = 1 && (expr && expr)` is allowed /// but `(let 1 = 1 && (let 1 = 1 && (let 1 = 1))) && let a = 1` is not - NotSupportedParentheses(Span), + #[note(ast_passes::not_supported_parentheses)] + NotSupportedParentheses(#[primary_span] Span), } diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index ba2ed24fc08fc..8319352bd24bd 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -16,23 +16,6 @@ pub struct ForbiddenLet { pub(crate) reason: ForbiddenLetReason, } -impl AddToDiagnostic for ForbiddenLetReason { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { - match self { - Self::GenericForbidden => {} - Self::NotSupportedOr(span) => { - diag.span_note(span, fluent::ast_passes::not_supported_or); - } - Self::NotSupportedParentheses(span) => { - diag.span_note(span, fluent::ast_passes::not_supported_parentheses); - } - } - } -} - #[derive(Diagnostic)] #[diag(ast_passes::forbidden_let_stable)] #[note] From 21d3bbd8b611725456e5ebefb6704b263bee819e Mon Sep 17 00:00:00 2001 From: David Wood Date: Fri, 14 Oct 2022 13:25:12 +0100 Subject: [PATCH 10/20] lint: use derive more Signed-off-by: David Wood --- compiler/rustc_errors/src/diagnostic_impls.rs | 21 +++++++++++++--- compiler/rustc_lint/src/errors.rs | 25 ++----------------- 2 files changed, 20 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index 860f24871bcdc..571b7dbfd1b04 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -1,14 +1,14 @@ use crate::{ fluent, DiagnosticArgValue, DiagnosticBuilder, Handler, IntoDiagnostic, IntoDiagnosticArg, }; -use rustc_target::abi::TargetDataLayoutErrors; -use rustc_target::spec::{PanicStrategy, SplitDebuginfo, StackProtector, TargetTriple}; - use rustc_ast as ast; use rustc_ast_pretty::pprust; use rustc_hir as hir; +use rustc_lint_defs::Level; use rustc_span::edition::Edition; use rustc_span::symbol::{Ident, MacroRulesNormalizedIdent, Symbol}; +use rustc_target::abi::TargetDataLayoutErrors; +use rustc_target::spec::{PanicStrategy, SplitDebuginfo, StackProtector, TargetTriple}; use std::borrow::Cow; use std::fmt; use std::num::ParseIntError; @@ -155,6 +155,21 @@ impl IntoDiagnosticArg for ast::token::TokenKind { } } +impl IntoDiagnosticArg for Level { + fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + DiagnosticArgValue::Str(Cow::Borrowed(match self { + Level::Allow => "-A", + Level::Warn => "-W", + Level::ForceWarn(_) => "--force-warn", + Level::Deny => "-D", + Level::Forbid => "-F", + Level::Expect(_) => { + unreachable!("lints with the level of `expect` should not run this code"); + } + })) + } +} + impl IntoDiagnostic<'_, !> for TargetDataLayoutErrors<'_> { fn into_diagnostic(self, handler: &Handler) -> DiagnosticBuilder<'_, !> { let mut diag; diff --git a/compiler/rustc_lint/src/errors.rs b/compiler/rustc_lint/src/errors.rs index 97d012fb611d0..34b70030a5828 100644 --- a/compiler/rustc_lint/src/errors.rs +++ b/compiler/rustc_lint/src/errors.rs @@ -88,34 +88,13 @@ pub struct BuiltinEllpisisInclusiveRangePatterns { pub replace: String, } +#[derive(Subdiagnostic)] +#[note(lint::requested_level)] pub struct RequestedLevel { pub level: Level, pub lint_name: String, } -impl AddToDiagnostic for RequestedLevel { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { - diag.note(fluent::lint::requested_level); - diag.set_arg( - "level", - match self.level { - Level::Allow => "-A", - Level::Warn => "-W", - Level::ForceWarn(_) => "--force-warn", - Level::Deny => "-D", - Level::Forbid => "-F", - Level::Expect(_) => { - unreachable!("lints with the level of `expect` should not run this code"); - } - }, - ); - diag.set_arg("lint_name", self.lint_name); - } -} - #[derive(Diagnostic)] #[diag(lint::unsupported_group, code = "E0602")] pub struct UnsupportedGroup { From f8b628bce4fb3f71e660fb7d80e4bc5fdcaaee62 Mon Sep 17 00:00:00 2001 From: David Wood Date: Fri, 14 Oct 2022 13:25:43 +0100 Subject: [PATCH 11/20] session: use derive more Signed-off-by: David Wood --- .../locales/en-US/session.ftl | 4 ++ compiler/rustc_session/src/errors.rs | 41 ++++++++++++------- compiler/rustc_session/src/session.rs | 33 ++++++++------- 3 files changed, 46 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/session.ftl b/compiler/rustc_error_messages/locales/en-US/session.ftl index 47127ea8e9ce8..e2277923072f9 100644 --- a/compiler/rustc_error_messages/locales/en-US/session.ftl +++ b/compiler/rustc_error_messages/locales/en-US/session.ftl @@ -54,3 +54,7 @@ session_crate_name_empty = crate name must not be empty session_invalid_character_in_create_name = invalid character `{$character}` in crate name: `{$crate_name}` session_expr_parentheses_needed = parentheses are required to parse this as an expression + +session_skipping_const_checks = skipping const checks +session_unleashed_feature_help_named = skipping check for `{$gate}` feature +session_unleashed_feature_help_unnamed = skipping check that does not even have a feature gate diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index d12796f289e96..500ab4a584cab 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -1,9 +1,7 @@ use std::num::NonZeroU32; use crate::cgu_reuse_tracker::CguReuse; -use rustc_errors::{ - fluent, DiagnosticBuilder, ErrorGuaranteed, Handler, IntoDiagnostic, MultiSpan, -}; +use rustc_errors::MultiSpan; use rustc_macros::Diagnostic; use rustc_span::{Span, Symbol}; use rustc_target::spec::{SplitDebuginfo, StackProtector, TargetTriple}; @@ -148,24 +146,15 @@ pub struct CrateNameEmpty { pub span: Option, } +#[derive(Diagnostic)] +#[diag(session::invalid_character_in_create_name)] pub struct InvalidCharacterInCrateName<'a> { + #[primary_span] pub span: Option, pub character: char, pub crate_name: &'a str, } -impl IntoDiagnostic<'_> for InvalidCharacterInCrateName<'_> { - fn into_diagnostic(self, sess: &Handler) -> DiagnosticBuilder<'_, ErrorGuaranteed> { - let mut diag = sess.struct_err(fluent::session::invalid_character_in_create_name); - if let Some(sp) = self.span { - diag.set_span(sp); - } - diag.set_arg("character", self.character); - diag.set_arg("crate_name", self.crate_name); - diag - } -} - #[derive(Subdiagnostic)] #[multipart_suggestion(session::expr_parentheses_needed, applicability = "machine-applicable")] pub struct ExprParenthesesNeeded { @@ -180,3 +169,25 @@ impl ExprParenthesesNeeded { ExprParenthesesNeeded { left: s.shrink_to_lo(), right: s.shrink_to_hi() } } } + +#[derive(Diagnostic)] +#[diag(session::skipping_const_checks)] +pub struct SkippingConstChecks { + #[subdiagnostic(eager)] + pub unleashed_features: Vec, +} + +#[derive(Subdiagnostic)] +pub enum UnleashedFeatureHelp { + #[help(session::unleashed_feature_help_named)] + Named { + #[primary_span] + span: Span, + gate: Symbol, + }, + #[help(session::unleashed_feature_help_unnamed)] + Unnamed { + #[primary_span] + span: Span, + }, +} diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index beb22ab3eb951..73cc79692d7b3 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -5,9 +5,10 @@ use crate::config::{self, CrateType, InstrumentCoverage, OptLevel, OutputType, S use crate::errors::{ CannotEnableCrtStaticLinux, CannotMixAndMatchSanitizers, LinkerPluginToWindowsNotSupported, NotCircumventFeature, ProfileSampleUseFileDoesNotExist, ProfileUseFileDoesNotExist, - SanitizerCfiEnabled, SanitizerNotSupported, SanitizersNotSupported, + SanitizerCfiEnabled, SanitizerNotSupported, SanitizersNotSupported, SkippingConstChecks, SplitDebugInfoUnstablePlatform, StackProtectorNotSupportedForTarget, - TargetRequiresUnwindTables, UnstableVirtualFunctionElimination, UnsupportedDwarfVersion, + TargetRequiresUnwindTables, UnleashedFeatureHelp, UnstableVirtualFunctionElimination, + UnsupportedDwarfVersion, }; use crate::parse::{add_feature_diagnostics, ParseSess}; use crate::search_paths::{PathKind, SearchPath}; @@ -233,21 +234,19 @@ impl Session { if !unleashed_features.is_empty() { let mut must_err = false; // Create a diagnostic pointing at where things got unleashed. - // FIXME(#100717): needs eager translation/lists - #[allow(rustc::untranslatable_diagnostic)] - #[allow(rustc::diagnostic_outside_of_impl)] - let mut diag = self.struct_warn("skipping const checks"); - for &(span, feature_gate) in unleashed_features.iter() { - // FIXME: `span_label` doesn't do anything, so we use "help" as a hack. - if let Some(gate) = feature_gate { - diag.span_help(span, &format!("skipping check for `{gate}` feature")); - // The unleash flag must *not* be used to just "hack around" feature gates. - must_err = true; - } else { - diag.span_help(span, "skipping check that does not even have a feature gate"); - } - } - diag.emit(); + self.emit_warning(SkippingConstChecks { + unleashed_features: unleashed_features + .iter() + .map(|(span, gate)| { + gate.map(|gate| { + must_err = true; + UnleashedFeatureHelp::Named { span: *span, gate } + }) + .unwrap_or(UnleashedFeatureHelp::Unnamed { span: *span }) + }) + .collect(), + }); + // If we should err, make sure we did. if must_err && self.has_errors().is_none() { // We have skipped a feature gate, and not run into other errors... reject. From 913f5974026334dbd2eeb4f39b0e4ea767e1b28d Mon Sep 17 00:00:00 2001 From: David Wood Date: Fri, 14 Oct 2022 13:25:59 +0100 Subject: [PATCH 12/20] infer: use derive more Signed-off-by: David Wood --- .../locales/en-US/infer.ftl | 4 +- compiler/rustc_infer/src/errors/mod.rs | 71 ++++++++----------- .../mismatched_static_lifetime.rs | 18 +++-- .../src/diagnostics/subdiagnostic.rs | 2 + 4 files changed, 46 insertions(+), 49 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/infer.ftl b/compiler/rustc_error_messages/locales/en-US/infer.ftl index 65371a285911e..18b3408b06ab4 100644 --- a/compiler/rustc_error_messages/locales/en-US/infer.ftl +++ b/compiler/rustc_error_messages/locales/en-US/infer.ftl @@ -164,7 +164,9 @@ infer_region_explanation = {$pref_kind -> } infer_mismatched_static_lifetime = incompatible lifetime on type -infer_msl_impl_note = ...does not necessarily outlive the static lifetime introduced by the compatible `impl` +infer_does_not_outlive_static_from_impl = ...does not necessarily outlive the static lifetime introduced by the compatible `impl` +infer_implicit_static_lifetime_note = this has an implicit `'static` lifetime requirement +infer_implicit_static_lifetime_suggestion = consider relaxing the implicit `'static` requirement infer_msl_introduces_static = introduces a `'static` lifetime requirement infer_msl_unmet_req = because this has an unmet lifetime requirement infer_msl_trait_note = this has an implicit `'static` lifetime requirement diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs index 500900d3d4a74..25e8630bf6bd7 100644 --- a/compiler/rustc_infer/src/errors/mod.rs +++ b/compiler/rustc_infer/src/errors/mod.rs @@ -459,47 +459,34 @@ impl AddToDiagnostic for IntroducesStaticBecauseUnmetLifetimeReq { } } -pub struct ImplNote { - pub impl_span: Option, -} - -impl AddToDiagnostic for ImplNote { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { - match self.impl_span { - Some(span) => diag.span_note(span, fluent::infer::msl_impl_note), - None => diag.note(fluent::infer::msl_impl_note), - }; - } -} - -pub enum TraitSubdiag { - Note { span: Span }, - Sugg { span: Span }, +// FIXME(#100717): replace with a `Option` when subdiagnostic supports that +#[derive(Subdiagnostic)] +pub enum DoesNotOutliveStaticFromImpl { + #[note(infer::does_not_outlive_static_from_impl)] + Spanned { + #[primary_span] + span: Span, + }, + #[note(infer::does_not_outlive_static_from_impl)] + Unspanned, } -// FIXME(#100717) used in `Vec` so requires eager translation/list support -impl AddToDiagnostic for TraitSubdiag { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { - match self { - TraitSubdiag::Note { span } => { - diag.span_note(span, "this has an implicit `'static` lifetime requirement"); - } - TraitSubdiag::Sugg { span } => { - diag.span_suggestion_verbose( - span, - "consider relaxing the implicit `'static` requirement", - " + '_".to_owned(), - rustc_errors::Applicability::MaybeIncorrect, - ); - } - } - } +#[derive(Subdiagnostic)] +pub enum ImplicitStaticLifetimeSubdiag { + #[note(infer::implicit_static_lifetime_note)] + Note { + #[primary_span] + span: Span, + }, + #[suggestion_verbose( + infer::implicit_static_lifetime_suggestion, + code = " + '_", + applicability = "maybe-incorrect" + )] + Sugg { + #[primary_span] + span: Span, + }, } #[derive(Diagnostic)] @@ -512,7 +499,7 @@ pub struct MismatchedStaticLifetime<'a> { #[subdiagnostic] pub expl: Option>, #[subdiagnostic] - pub impl_note: ImplNote, - #[subdiagnostic] - pub trait_subdiags: Vec, + pub does_not_outlive_static_from_impl: DoesNotOutliveStaticFromImpl, + #[subdiagnostic(eager)] + pub implicit_static_lifetimes: Vec, } diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs index 1410e2b63b0b8..c5f2a1a3f7dce 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs @@ -2,7 +2,9 @@ //! to hold. use crate::errors::{note_and_explain, IntroducesStaticBecauseUnmetLifetimeReq}; -use crate::errors::{ImplNote, MismatchedStaticLifetime, TraitSubdiag}; +use crate::errors::{ + DoesNotOutliveStaticFromImpl, ImplicitStaticLifetimeSubdiag, MismatchedStaticLifetime, +}; use crate::infer::error_reporting::nice_region_error::NiceRegionError; use crate::infer::lexical_region_resolve::RegionResolutionError; use crate::infer::{SubregionOrigin, TypeTrace}; @@ -56,7 +58,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { note_and_explain::SuffixKind::Continues, ); let mut impl_span = None; - let mut trait_subdiags = Vec::new(); + let mut implicit_static_lifetimes = Vec::new(); if let Some(impl_node) = self.tcx().hir().get_if_local(*impl_def_id) { // If an impl is local, then maybe this isn't what they want. Try to // be as helpful as possible with implicit lifetimes. @@ -90,10 +92,12 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { // Otherwise, point at all implicit static lifetimes for span in &traits { - trait_subdiags.push(TraitSubdiag::Note { span: *span }); + implicit_static_lifetimes + .push(ImplicitStaticLifetimeSubdiag::Note { span: *span }); // It would be nice to put this immediately under the above note, but they get // pushed to the end. - trait_subdiags.push(TraitSubdiag::Sugg { span: span.shrink_to_hi() }); + implicit_static_lifetimes + .push(ImplicitStaticLifetimeSubdiag::Sugg { span: span.shrink_to_hi() }); } } } else { @@ -105,8 +109,10 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { cause_span: cause.span, unmet_lifetime_reqs: multispan_subdiag, expl, - impl_note: ImplNote { impl_span }, - trait_subdiags, + does_not_outlive_static_from_impl: impl_span + .map(|span| DoesNotOutliveStaticFromImpl::Spanned { span }) + .unwrap_or(DoesNotOutliveStaticFromImpl::Unspanned), + implicit_static_lifetimes, }; let reported = self.tcx().sess.emit_err(err); Some(reported) diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index 5a42a2cd12dd6..d1acb71384220 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -309,6 +309,8 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { report_error_if_not_applied_to_span(attr, &info)?; let binding = info.binding.binding.clone(); + // FIXME(#100717): support `Option` on `primary_span` like in the + // diagnostic derive self.span_field.set_once(binding, span); } From f134370b916b107cc2c07a563430e99d3c102188 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Tue, 18 Oct 2022 16:47:35 +0200 Subject: [PATCH 13/20] apply joshua's suggestion Co-authored-by: Joshua Nelson --- src/bootstrap/doc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index a8524fea1b2a0..939e169ec00e5 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -299,7 +299,7 @@ impl Step for Standalone { fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { let builder = run.builder; - run.path("src/doc").path("standalone").default_condition(builder.config.docs) + run.path("src/doc").alias("standalone").default_condition(builder.config.docs) } fn make_run(run: RunConfig<'_>) { From 0b2716415f1bd26e80887c2d8459fd436fc8e9b3 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Wed, 19 Oct 2022 11:17:46 +0900 Subject: [PATCH 14/20] fix `SelfVisitor::is_self_ty` ICE --- compiler/rustc_resolve/src/late.rs | 6 +++--- src/test/ui/resolve/issue-103202.rs | 7 +++++++ src/test/ui/resolve/issue-103202.stderr | 9 +++++++++ 3 files changed, 19 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/resolve/issue-103202.rs create mode 100644 src/test/ui/resolve/issue-103202.stderr diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index cc877e2fd30ca..5b99cd1e26436 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1928,11 +1928,11 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { match ty.kind { TyKind::ImplicitSelf => true, TyKind::Path(None, _) => { - let path_res = self.r.partial_res_map[&ty.id].expect_full_res(); - if let Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } = path_res { + let path_res = self.r.partial_res_map[&ty.id].full_res(); + if let Some(Res::SelfTyParam { .. } | Res::SelfTyAlias { .. }) = path_res { return true; } - Some(path_res) == self.impl_self + path_res == self.impl_self } _ => false, } diff --git a/src/test/ui/resolve/issue-103202.rs b/src/test/ui/resolve/issue-103202.rs new file mode 100644 index 0000000000000..469d9d7c860ca --- /dev/null +++ b/src/test/ui/resolve/issue-103202.rs @@ -0,0 +1,7 @@ +struct S {} + +impl S { + fn f(self: &S::x) {} //~ ERROR ambiguous associated type +} + +fn main() {} diff --git a/src/test/ui/resolve/issue-103202.stderr b/src/test/ui/resolve/issue-103202.stderr new file mode 100644 index 0000000000000..880389371ef70 --- /dev/null +++ b/src/test/ui/resolve/issue-103202.stderr @@ -0,0 +1,9 @@ +error[E0223]: ambiguous associated type + --> $DIR/issue-103202.rs:4:17 + | +LL | fn f(self: &S::x) {} + | ^^^^ help: use fully-qualified syntax: `::x` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0223`. From 2cc4a0aad72752a4d485ced76bab677620f088b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Tue, 18 Oct 2022 15:34:41 +0200 Subject: [PATCH 15/20] rustdoc: render bounds of cross-crate GAT params --- src/librustdoc/clean/mod.rs | 44 +++++++++++++------ .../assoc_item_trait_bounds.out0.html | 1 + .../assoc_item_trait_bounds.out2.html | 1 + ...html => assoc_item_trait_bounds.out9.html} | 0 ...bindings.rs => assoc_item_trait_bounds.rs} | 15 ++++--- ..._item_trait_bounds_with_bindings.out0.html | 1 - ...bindings.rs => assoc_item_trait_bounds.rs} | 1 + 7 files changed, 41 insertions(+), 22 deletions(-) create mode 100644 src/test/rustdoc/inline_cross/assoc_item_trait_bounds.out0.html create mode 100644 src/test/rustdoc/inline_cross/assoc_item_trait_bounds.out2.html rename src/test/rustdoc/inline_cross/{assoc_item_trait_bounds_with_bindings.out9.html => assoc_item_trait_bounds.out9.html} (100%) rename src/test/rustdoc/inline_cross/{assoc_item_trait_bounds_with_bindings.rs => assoc_item_trait_bounds.rs} (79%) delete mode 100644 src/test/rustdoc/inline_cross/assoc_item_trait_bounds_with_bindings.out0.html rename src/test/rustdoc/inline_cross/auxiliary/{assoc_item_trait_bounds_with_bindings.rs => assoc_item_trait_bounds.rs} (96%) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 5f674ed7441ba..13d63ffa0ee3c 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1201,21 +1201,19 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( } if let ty::TraitContainer = assoc_item.container { - // FIXME(fmease): `tcx.explicit_item_bounds` does not contain the bounds of GATs, - // e.g. the bounds `Copy`, `Display` & (implicitly) `Sized` in - // `type Assoc where T: Display`. This also means that we - // later incorrectly render `where T: ?Sized`. - // - // The result of `tcx.explicit_predicates_of` *does* contain them but - // it does not contain the other bounds / predicates we need. - // Either merge those two interned lists somehow or refactor - // `clean_ty_generics` to call `explicit_item_bounds` by itself. let bounds = tcx.explicit_item_bounds(assoc_item.def_id); - let predicates = ty::GenericPredicates { parent: None, predicates: bounds }; - let mut generics = - clean_ty_generics(cx, tcx.generics_of(assoc_item.def_id), predicates); - // Filter out the bounds that are (likely?) directly attached to the associated type, - // as opposed to being located in the where clause. + let predicates = tcx.explicit_predicates_of(assoc_item.def_id).predicates; + let predicates = + tcx.arena.alloc_from_iter(bounds.into_iter().chain(predicates).copied()); + let mut generics = clean_ty_generics( + cx, + tcx.generics_of(assoc_item.def_id), + ty::GenericPredicates { parent: None, predicates }, + ); + // Move bounds that are (likely) directly attached to the associated type + // from the where clause to the associated type. + // There is no guarantee that this is what the user actually wrote but we have + // no way of knowing. let mut bounds = generics .where_predicates .drain_filter(|pred| match *pred { @@ -1273,6 +1271,24 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( } None => bounds.push(GenericBound::maybe_sized(cx)), } + // Move bounds that are (likely) directly attached to the parameters of the + // (generic) associated type from the where clause to the respective parameter. + // There is no guarantee that this is what the user actually wrote but we have + // no way of knowing. + let mut where_predicates = Vec::new(); + for mut pred in generics.where_predicates { + if let WherePredicate::BoundPredicate { ty: Generic(arg), bounds, .. } = &mut pred + && let Some(GenericParamDef { + kind: GenericParamDefKind::Type { bounds: param_bounds, .. }, + .. + }) = generics.params.iter_mut().find(|param| ¶m.name == arg) + { + param_bounds.extend(mem::take(bounds)); + } else { + where_predicates.push(pred); + } + } + generics.where_predicates = where_predicates; if tcx.impl_defaultness(assoc_item.def_id).has_value() { AssocTypeItem( diff --git a/src/test/rustdoc/inline_cross/assoc_item_trait_bounds.out0.html b/src/test/rustdoc/inline_cross/assoc_item_trait_bounds.out0.html new file mode 100644 index 0000000000000..8934bc1ee339c --- /dev/null +++ b/src/test/rustdoc/inline_cross/assoc_item_trait_bounds.out0.html @@ -0,0 +1 @@ +

type Out0: Support<Item = ()>

\ No newline at end of file diff --git a/src/test/rustdoc/inline_cross/assoc_item_trait_bounds.out2.html b/src/test/rustdoc/inline_cross/assoc_item_trait_bounds.out2.html new file mode 100644 index 0000000000000..bf330670ed0fa --- /dev/null +++ b/src/test/rustdoc/inline_cross/assoc_item_trait_bounds.out2.html @@ -0,0 +1 @@ +

type Out2<T>: Support<Item = T>

\ No newline at end of file diff --git a/src/test/rustdoc/inline_cross/assoc_item_trait_bounds_with_bindings.out9.html b/src/test/rustdoc/inline_cross/assoc_item_trait_bounds.out9.html similarity index 100% rename from src/test/rustdoc/inline_cross/assoc_item_trait_bounds_with_bindings.out9.html rename to src/test/rustdoc/inline_cross/assoc_item_trait_bounds.out9.html diff --git a/src/test/rustdoc/inline_cross/assoc_item_trait_bounds_with_bindings.rs b/src/test/rustdoc/inline_cross/assoc_item_trait_bounds.rs similarity index 79% rename from src/test/rustdoc/inline_cross/assoc_item_trait_bounds_with_bindings.rs rename to src/test/rustdoc/inline_cross/assoc_item_trait_bounds.rs index 00976aa74420f..5f4712aab5b19 100644 --- a/src/test/rustdoc/inline_cross/assoc_item_trait_bounds_with_bindings.rs +++ b/src/test/rustdoc/inline_cross/assoc_item_trait_bounds.rs @@ -1,13 +1,10 @@ // Regression test for issues #77763, #84579 and #102142. #![crate_name = "main"] -// aux-build:assoc_item_trait_bounds_with_bindings.rs +// aux-build:assoc_item_trait_bounds.rs // build-aux-docs // ignore-cross-compile -extern crate assoc_item_trait_bounds_with_bindings as aux; - -// FIXME(fmease): Don't render an incorrect `T: ?Sized` where-clause for parameters -// of GATs like `Main::Out{2,4}`. Add a snapshot test once it's fixed. +extern crate assoc_item_trait_bounds as aux; // @has main/trait.Main.html // @has - '//*[@id="associatedtype.Out0"]' 'type Out0: Support' @@ -24,11 +21,15 @@ extern crate assoc_item_trait_bounds_with_bindings as aux; // @has - '//*[@id="associatedtype.Out11"]' "type Out11: for<'r, 's> Helper = &'s (), B<'r> = ()>" // @has - '//*[@id="associatedtype.Out12"]' "type Out12: for<'w> Helper = Cow<'w, str>, A<'w> = bool>" // @has - '//*[@id="associatedtype.Out13"]' "type Out13: for<'fst, 'snd> Aid<'snd, Result<'fst> = &'fst mut str>" +// @has - '//*[@id="associatedtype.Out14"]' "type Out14" // -// Snapshots: Check that we do not render any where-clauses for those associated types since all of -// the trait bounds contained within were moved to the bounds of the respective item. +// Snapshots: +// Check that we don't render any where-clauses for the following associated types since +// all corresponding projection equality predicates should have already been re-sugared +// to associated type bindings: // // @snapshot out0 - '//*[@id="associatedtype.Out0"]/*[@class="code-header"]' +// @snapshot out2 - '//*[@id="associatedtype.Out2"]/*[@class="code-header"]' // @snapshot out9 - '//*[@id="associatedtype.Out9"]/*[@class="code-header"]' // // @has - '//*[@id="tymethod.make"]' \ diff --git a/src/test/rustdoc/inline_cross/assoc_item_trait_bounds_with_bindings.out0.html b/src/test/rustdoc/inline_cross/assoc_item_trait_bounds_with_bindings.out0.html deleted file mode 100644 index 927a1a42a1f78..0000000000000 --- a/src/test/rustdoc/inline_cross/assoc_item_trait_bounds_with_bindings.out0.html +++ /dev/null @@ -1 +0,0 @@ -

type Out0: Support<Item = ()>

\ No newline at end of file diff --git a/src/test/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds_with_bindings.rs b/src/test/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds.rs similarity index 96% rename from src/test/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds_with_bindings.rs rename to src/test/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds.rs index f451b1a0e9920..d326e61daea26 100644 --- a/src/test/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds_with_bindings.rs +++ b/src/test/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds.rs @@ -15,6 +15,7 @@ pub trait Main { type Out11: for<'r, 's> Helper = &'s (), B<'r> = ()>; type Out12: for<'w> Helper = std::borrow::Cow<'w, str>, A<'w> = bool>; type Out13: for<'fst, 'snd> Aid<'snd, Result<'fst> = &'fst mut str>; + type Out14; fn make(_: F, _: impl FnMut(&str) -> bool) where From a3ccb193be29ebf5580d4759a9f2b48df069c365 Mon Sep 17 00:00:00 2001 From: John Higgins Date: Wed, 19 Oct 2022 21:49:29 -0700 Subject: [PATCH 16/20] Fixed docs typo in `library/std/src/time.rs` --- library/std/src/time.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/time.rs b/library/std/src/time.rs index 759a59e1f98d2..d4a1b9d9b50c8 100644 --- a/library/std/src/time.rs +++ b/library/std/src/time.rs @@ -356,7 +356,7 @@ impl Instant { /// /// # Panics /// - /// Previous rust versions panicked when self was earlier than the current time. Currently this + /// Previous rust versions panicked when the current time was earlier than self. Currently this /// method returns a Duration of zero in that case. Future versions may reintroduce the panic. /// See [Monotonicity]. /// From 9a9e2fe15fd0a730e929db88fcf73b0cb3a99ddc Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Thu, 20 Oct 2022 14:10:52 +0900 Subject: [PATCH 17/20] check if impl_self is `Some` --- compiler/rustc_resolve/src/late.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 5b99cd1e26436..c6607eff90dcc 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1932,7 +1932,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { if let Some(Res::SelfTyParam { .. } | Res::SelfTyAlias { .. }) = path_res { return true; } - path_res == self.impl_self + self.impl_self.is_some() && path_res == self.impl_self } _ => false, } From d3c37b1dfa62f8de2690e09c8e31ac8fbbd0dd2e Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 20 Oct 2022 11:33:31 +0200 Subject: [PATCH 18/20] +/- shortcut now only expand/collapse, not both --- src/librustdoc/html/static/js/main.js | 59 ++++++++++++++------------- 1 file changed, 30 insertions(+), 29 deletions(-) diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index d8f4bc2db22e1..0b816eace64b1 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -409,9 +409,12 @@ function loadCss(cssFileName) { break; case "+": + ev.preventDefault(); + expandAllDocs(); + break; case "-": ev.preventDefault(); - toggleAllDocs(); + collapseAllDocs(); break; case "?": @@ -614,15 +617,31 @@ function loadCss(cssFileName) { sidebarElems.appendChild(ul); } + function expandAllDocs() { + const innerToggle = document.getElementById(toggleAllDocsId); + removeClass(innerToggle, "will-expand"); + onEachLazy(document.getElementsByClassName("rustdoc-toggle"), e => { + if (!hasClass(e, "type-contents-toggle")) { + e.open = true; + } + }); + innerToggle.title = "collapse all docs"; + innerToggle.children[0].innerText = "\u2212"; // "\u2212" is "−" minus sign + } - function labelForToggleButton(sectionIsCollapsed) { - if (sectionIsCollapsed) { - // button will expand the section - return "+"; - } - // button will collapse the section - // note that this text is also set in the HTML template in ../render/mod.rs - return "\u2212"; // "\u2212" is "−" minus sign + function collapseAllDocs() { + const innerToggle = document.getElementById(toggleAllDocsId); + addClass(innerToggle, "will-expand"); + onEachLazy(document.getElementsByClassName("rustdoc-toggle"), e => { + if (e.parentNode.id !== "implementations-list" || + (!hasClass(e, "implementors-toggle") && + !hasClass(e, "type-contents-toggle")) + ) { + e.open = false; + } + }); + innerToggle.title = "expand all docs"; + innerToggle.children[0].innerText = "+"; } function toggleAllDocs() { @@ -630,29 +649,11 @@ function loadCss(cssFileName) { if (!innerToggle) { return; } - let sectionIsCollapsed = false; if (hasClass(innerToggle, "will-expand")) { - removeClass(innerToggle, "will-expand"); - onEachLazy(document.getElementsByClassName("rustdoc-toggle"), e => { - if (!hasClass(e, "type-contents-toggle")) { - e.open = true; - } - }); - innerToggle.title = "collapse all docs"; + expandAllDocs(); } else { - addClass(innerToggle, "will-expand"); - onEachLazy(document.getElementsByClassName("rustdoc-toggle"), e => { - if (e.parentNode.id !== "implementations-list" || - (!hasClass(e, "implementors-toggle") && - !hasClass(e, "type-contents-toggle")) - ) { - e.open = false; - } - }); - sectionIsCollapsed = true; - innerToggle.title = "expand all docs"; + collapseAllDocs(); } - innerToggle.children[0].innerText = labelForToggleButton(sectionIsCollapsed); } (function() { From 8e3b89140e621c5f7450bd5a023fbad65fedfa3c Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 20 Oct 2022 11:34:40 +0200 Subject: [PATCH 19/20] Add GUI tests for collapse/expand actions --- src/test/rustdoc-gui/shortcuts.goml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/test/rustdoc-gui/shortcuts.goml b/src/test/rustdoc-gui/shortcuts.goml index ea6f55272ffc9..9068680d640c1 100644 --- a/src/test/rustdoc-gui/shortcuts.goml +++ b/src/test/rustdoc-gui/shortcuts.goml @@ -11,3 +11,21 @@ press-key: "?" assert-css: ("#help-button .popover", {"display": "block"}) press-key: "Escape" assert-css: ("#help-button .popover", {"display": "none"}) +// Checking doc collapse and expand. +// It should be displaying a "-": +assert-text: ("#toggle-all-docs", "[\u2212]") +press-key: "-" +wait-for-text: ("#toggle-all-docs", "[+]") +assert-attribute: ("#toggle-all-docs", {"class": "will-expand"}) +// Pressing it again shouldn't do anything. +press-key: "-" +assert-text: ("#toggle-all-docs", "[+]") +assert-attribute: ("#toggle-all-docs", {"class": "will-expand"}) +// Expanding now. +press-key: "+" +wait-for-text: ("#toggle-all-docs", "[\u2212]") +assert-attribute: ("#toggle-all-docs", {"class": ""}) +// Pressing it again shouldn't do anything. +press-key: "+" +assert-text: ("#toggle-all-docs", "[\u2212]") +assert-attribute: ("#toggle-all-docs", {"class": ""}) From ed1f02bcb5294d8449fcd189f25a30ea29727172 Mon Sep 17 00:00:00 2001 From: cui fliter Date: Thu, 20 Oct 2022 18:00:36 +0800 Subject: [PATCH 20/20] fix typo --- .../rustc/src/platform-support/armeb-unknown-linux-gnueabi.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc/src/platform-support/armeb-unknown-linux-gnueabi.md b/src/doc/rustc/src/platform-support/armeb-unknown-linux-gnueabi.md index 507631cdc540a..432e0cfc960e3 100644 --- a/src/doc/rustc/src/platform-support/armeb-unknown-linux-gnueabi.md +++ b/src/doc/rustc/src/platform-support/armeb-unknown-linux-gnueabi.md @@ -1,7 +1,7 @@ # armeb-unknown-linux-gnueabi **Tier: 3** -Target for cross-compiling Linux user-mode applications targetting the ARM BE8 architecture. +Target for cross-compiling Linux user-mode applications targeting the ARM BE8 architecture. ## Overview BE8 architecture retains the same little-endian ordered code-stream used by conventional little endian ARM systems, however the data accesses are in big-endian. BE8 is used primarily in high-performance networking applications where the ability to read packets in their native "Network Byte Order" is important (many network protocols transmit data in big-endian byte order for their wire formats).