From 6234a5694936cb0f7c9a3fb456ae4c0aeee69f11 Mon Sep 17 00:00:00 2001 From: Augie Fackler Date: Thu, 4 Nov 2021 17:16:16 -0400 Subject: [PATCH 01/11] rustc_llvm: update PassWrapper for recent LLVM Now AddressSanitizerOptions is a struct, but at least the change was tiny. r? nikic --- compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index ddbc3c5912836..94dce9f46fbc1 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -889,15 +889,18 @@ LLVMRustOptimizeWithNewPassManager( OptimizerLastEPCallbacks.push_back( [SanitizerOptions](ModulePassManager &MPM, OptimizationLevel Level) { MPM.addPass(RequireAnalysisPass()); - MPM.addPass(ModuleAddressSanitizerPass( - /*CompileKernel=*/false, SanitizerOptions->SanitizeAddressRecover)); #if LLVM_VERSION_GE(14, 0) - AddressSanitizerOptions opts(/*CompileKernel=*/false, - SanitizerOptions->SanitizeAddressRecover, - /*UseAfterScope=*/true, - AsanDetectStackUseAfterReturnMode::Runtime); + AddressSanitizerOptions opts = AddressSanitizerOptions{ + /*CompileKernel=*/false, + SanitizerOptions->SanitizeAddressRecover, + /*UseAfterScope=*/false, + AsanDetectStackUseAfterReturnMode::Runtime, + }; + MPM.addPass(ModuleAddressSanitizerPass(opts)); MPM.addPass(createModuleToFunctionPassAdaptor(AddressSanitizerPass(opts))); #else + MPM.addPass(ModuleAddressSanitizerPass( + /*CompileKernel=*/false, SanitizerOptions->SanitizeAddressRecover)); MPM.addPass(createModuleToFunctionPassAdaptor(AddressSanitizerPass( /*CompileKernel=*/false, SanitizerOptions->SanitizeAddressRecover, /*UseAfterScope=*/true))); From d440ce6a9f6d8cfa532007add77754d956038407 Mon Sep 17 00:00:00 2001 From: Augie Fackler Date: Thu, 4 Nov 2021 18:08:32 -0400 Subject: [PATCH 02/11] Didn't mean to invert this boolean. --- compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 94dce9f46fbc1..baeb17ed1cb6d 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -893,7 +893,7 @@ LLVMRustOptimizeWithNewPassManager( AddressSanitizerOptions opts = AddressSanitizerOptions{ /*CompileKernel=*/false, SanitizerOptions->SanitizeAddressRecover, - /*UseAfterScope=*/false, + /*UseAfterScope=*/true, AsanDetectStackUseAfterReturnMode::Runtime, }; MPM.addPass(ModuleAddressSanitizerPass(opts)); From eeaa2f16aa4487d3e5fdaef7097b488d45b986d2 Mon Sep 17 00:00:00 2001 From: est31 Date: Sat, 6 Nov 2021 05:56:09 +0100 Subject: [PATCH 03/11] Extend the const_swap feature This makes the inherent method ptr::swap unstably const, as well as slice::swap{,_unchecked}. --- library/core/src/ptr/mut_ptr.rs | 3 ++- library/core/src/slice/mod.rs | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index adc64cb2bd39a..5d5527dc8b46b 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -1092,8 +1092,9 @@ impl *mut T { /// /// [`ptr::swap`]: crate::ptr::swap() #[stable(feature = "pointer_methods", since = "1.26.0")] + #[rustc_const_unstable(feature = "const_swap", issue = "83163")] #[inline(always)] - pub unsafe fn swap(self, with: *mut T) + pub const unsafe fn swap(self, with: *mut T) where T: Sized, { diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 65ed72cb0cdbe..d876d944e7f0b 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -558,8 +558,9 @@ impl [T] { /// assert!(v == ["a", "b", "e", "d", "c"]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_swap", issue = "83163")] #[inline] - pub fn swap(&mut self, a: usize, b: usize) { + pub const fn swap(&mut self, a: usize, b: usize) { let _ = &self[a]; let _ = &self[b]; @@ -595,7 +596,8 @@ impl [T] { /// [`swap`]: slice::swap /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html #[unstable(feature = "slice_swap_unchecked", issue = "88539")] - pub unsafe fn swap_unchecked(&mut self, a: usize, b: usize) { + #[rustc_const_unstable(feature = "const_swap", issue = "83163")] + pub const unsafe fn swap_unchecked(&mut self, a: usize, b: usize) { #[cfg(debug_assertions)] { let _ = &self[a]; From 9f6ca7482ca885bca14ba6870ed39a783ab939b5 Mon Sep 17 00:00:00 2001 From: Marcel Hellwig Date: Wed, 10 Nov 2021 12:00:46 +0100 Subject: [PATCH 04/11] Shorten Span of unused macro lints The span has been recuded to the actual ident, instead of linting the *whole* macro. --- .../rustc_resolve/src/build_reduced_graph.rs | 14 +++----- compiler/rustc_resolve/src/lib.rs | 2 +- compiler/rustc_resolve/src/macros.rs | 9 +++-- src/test/ui/lint/unused/issue-70041.stderr | 11 +++--- .../ui/lint/unused/unused-macro-rules.stderr | 35 +++++++------------ src/test/ui/lint/unused/unused-macro.stderr | 30 +++++++--------- src/test/ui/proc-macro/issue-39889.rs | 2 +- 7 files changed, 41 insertions(+), 62 deletions(-) diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 4173e0fbf5668..3cf9d324a38da 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -1194,15 +1194,9 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { // Mark the given macro as unused unless its name starts with `_`. // Macro uses will remove items from this set, and the remaining // items will be reported as `unused_macros`. - fn insert_unused_macro( - &mut self, - ident: Ident, - def_id: LocalDefId, - node_id: NodeId, - span: Span, - ) { + fn insert_unused_macro(&mut self, ident: Ident, def_id: LocalDefId, node_id: NodeId) { if !ident.as_str().starts_with('_') { - self.r.unused_macros.insert(def_id, (node_id, span)); + self.r.unused_macros.insert(def_id, (node_id, ident)); } } @@ -1246,7 +1240,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { self.r.define(module, ident, MacroNS, (res, vis, span, expansion, IsMacroExport)); } else { self.r.check_reserved_macro_name(ident, res); - self.insert_unused_macro(ident, def_id, item.id, span); + self.insert_unused_macro(ident, def_id, item.id); } self.r.visibilities.insert(def_id, vis); self.r.arenas.alloc_macro_rules_scope(MacroRulesScope::Binding( @@ -1267,7 +1261,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { _ => self.resolve_visibility(&item.vis), }; if vis != ty::Visibility::Public { - self.insert_unused_macro(ident, def_id, item.id, span); + self.insert_unused_macro(ident, def_id, item.id); } self.r.define(module, ident, MacroNS, (res, vis, span, expansion)); self.r.visibilities.insert(def_id, vis); diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 5f3620b247e26..f5bea83bdcf65 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -988,7 +988,7 @@ pub struct Resolver<'a> { non_macro_attr: Lrc, local_macro_def_scopes: FxHashMap>, ast_transform_scopes: FxHashMap>, - unused_macros: FxHashMap, + unused_macros: FxHashMap, proc_macro_stubs: FxHashSet, /// Traces collected during macro resolution and validated when it's complete. single_segment_macro_resolutions: diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 4f6e23d8f84f0..31fd9b989e1c8 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -315,8 +315,13 @@ impl<'a> ResolverExpand for Resolver<'a> { } fn check_unused_macros(&mut self) { - for (_, &(node_id, span)) in self.unused_macros.iter() { - self.lint_buffer.buffer_lint(UNUSED_MACROS, node_id, span, "unused macro definition"); + for (_, &(node_id, ident)) in self.unused_macros.iter() { + self.lint_buffer.buffer_lint( + UNUSED_MACROS, + node_id, + ident.span, + &format!("unused macro definition: `{}`", ident.as_str()), + ); } } diff --git a/src/test/ui/lint/unused/issue-70041.stderr b/src/test/ui/lint/unused/issue-70041.stderr index ecd618eae8b07..b2e6d1aeb3f50 100644 --- a/src/test/ui/lint/unused/issue-70041.stderr +++ b/src/test/ui/lint/unused/issue-70041.stderr @@ -1,11 +1,8 @@ -warning: unused macro definition - --> $DIR/issue-70041.rs:4:1 +warning: unused macro definition: `regex` + --> $DIR/issue-70041.rs:4:14 | -LL | / macro_rules! regex { -LL | | -LL | | () => {}; -LL | | } - | |_^ +LL | macro_rules! regex { + | ^^^^^ | = note: `#[warn(unused_macros)]` on by default diff --git a/src/test/ui/lint/unused/unused-macro-rules.stderr b/src/test/ui/lint/unused/unused-macro-rules.stderr index 6812a1d8f631a..59db35b411183 100644 --- a/src/test/ui/lint/unused/unused-macro-rules.stderr +++ b/src/test/ui/lint/unused/unused-macro-rules.stderr @@ -1,10 +1,8 @@ -error: unused macro definition - --> $DIR/unused-macro-rules.rs:4:1 +error: unused macro definition: `unused` + --> $DIR/unused-macro-rules.rs:4:14 | -LL | / macro_rules! unused { -LL | | () => {}; -LL | | } - | |_^ +LL | macro_rules! unused { + | ^^^^^^ | note: the lint level is defined here --> $DIR/unused-macro-rules.rs:1:9 @@ -12,26 +10,17 @@ note: the lint level is defined here LL | #![deny(unused_macros)] | ^^^^^^^^^^^^^ -error: unused macro definition - --> $DIR/unused-macro-rules.rs:11:9 +error: unused macro definition: `m` + --> $DIR/unused-macro-rules.rs:11:22 | -LL | / macro_rules! m { -LL | | () => {}; -LL | | } - | |_________^ -... -LL | create_macro!(); - | --------------- in this macro invocation - | - = note: this error originates in the macro `create_macro` (in Nightly builds, run with -Z macro-backtrace for more info) +LL | macro_rules! m { + | ^ -error: unused macro definition - --> $DIR/unused-macro-rules.rs:24:5 +error: unused macro definition: `unused` + --> $DIR/unused-macro-rules.rs:24:18 | -LL | / macro_rules! unused { -LL | | () => {}; -LL | | } - | |_____^ +LL | macro_rules! unused { + | ^^^^^^ | note: the lint level is defined here --> $DIR/unused-macro-rules.rs:23:12 diff --git a/src/test/ui/lint/unused/unused-macro.stderr b/src/test/ui/lint/unused/unused-macro.stderr index f5eb76179bf4b..1a73279ed6dbd 100644 --- a/src/test/ui/lint/unused/unused-macro.stderr +++ b/src/test/ui/lint/unused/unused-macro.stderr @@ -1,10 +1,8 @@ -error: unused macro definition - --> $DIR/unused-macro.rs:5:1 +error: unused macro definition: `unused` + --> $DIR/unused-macro.rs:5:7 | -LL | / macro unused { -LL | | () => {} -LL | | } - | |_^ +LL | macro unused { + | ^^^^^^ | note: the lint level is defined here --> $DIR/unused-macro.rs:2:9 @@ -12,13 +10,11 @@ note: the lint level is defined here LL | #![deny(unused_macros)] | ^^^^^^^^^^^^^ -error: unused macro definition - --> $DIR/unused-macro.rs:15:5 +error: unused macro definition: `unused` + --> $DIR/unused-macro.rs:15:11 | -LL | / macro unused { -LL | | () => {} -LL | | } - | |_____^ +LL | macro unused { + | ^^^^^^ | note: the lint level is defined here --> $DIR/unused-macro.rs:14:12 @@ -26,13 +22,11 @@ note: the lint level is defined here LL | #[deny(unused_macros)] | ^^^^^^^^^^^^^ -error: unused macro definition - --> $DIR/unused-macro.rs:21:5 +error: unused macro definition: `unused` + --> $DIR/unused-macro.rs:21:22 | -LL | / pub(crate) macro unused { -LL | | () => {} -LL | | } - | |_____^ +LL | pub(crate) macro unused { + | ^^^^^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/proc-macro/issue-39889.rs b/src/test/ui/proc-macro/issue-39889.rs index ada125a215a5d..69bfb4f3cbfbc 100644 --- a/src/test/ui/proc-macro/issue-39889.rs +++ b/src/test/ui/proc-macro/issue-39889.rs @@ -1,6 +1,6 @@ // run-pass -#![allow(dead_code)] +#![allow(dead_code, unused_macros)] // aux-build:issue-39889.rs extern crate issue_39889; From b41b2e5a5cb9aa3d56dd2da23c2438d16fef9997 Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Thu, 11 Nov 2021 13:41:21 +0000 Subject: [PATCH 05/11] Document `unreachable!()` custom panic message The `unreachable!` docs previously did not mention that there was a second form, `unreachable!("message")` that could be used to specify a custom panic message, The docs now mention this in the same style as currently used for `unimplemented!`: https://doc.rust-lang.org/core/macro.unimplemented.html#panics --- library/core/src/macros/mod.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 5b3e988caa506..993ae72322966 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -554,7 +554,10 @@ macro_rules! writeln { /// /// # Panics /// -/// This will always [`panic!`]. +/// This will always [`panic!`] because `unreachable!` is just a shorthand for `panic!` with a +/// fixed, specific message. +/// +/// Like `panic!`, this macro has a second form for displaying custom values. /// /// # Examples /// @@ -581,7 +584,7 @@ macro_rules! writeln { /// if 3*i < i { panic!("u32 overflow"); } /// if x < 3*i { return i-1; } /// } -/// unreachable!(); +/// unreachable!("The loop should always return"); /// } /// ``` #[macro_export] From d9f2d5f0e9c55f440d043c3614b164d7c9fa70ce Mon Sep 17 00:00:00 2001 From: Krasimir Georgiev Date: Thu, 11 Nov 2021 09:03:23 -0500 Subject: [PATCH 06/11] PassWrapper: additional sanitizer update to match clang This happened later in the stream than the other changes, but the fix is overlapping. Fix taken from a55c4ec1cee7683d9095327d9d33e7137ec25292 in LLVM. --- compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index baeb17ed1cb6d..4f77db8a24dc4 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -897,7 +897,6 @@ LLVMRustOptimizeWithNewPassManager( AsanDetectStackUseAfterReturnMode::Runtime, }; MPM.addPass(ModuleAddressSanitizerPass(opts)); - MPM.addPass(createModuleToFunctionPassAdaptor(AddressSanitizerPass(opts))); #else MPM.addPass(ModuleAddressSanitizerPass( /*CompileKernel=*/false, SanitizerOptions->SanitizeAddressRecover)); From 79e52b3f1ea5038de95372b45ffcb523d6b462a2 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Mon, 8 Nov 2021 17:28:02 +0000 Subject: [PATCH 07/11] unix::ExitStatusExt: Correct reference to _exit system call As discussed here https://github.com/rust-lang/rust/pull/88300#issuecomment-936085371 exit is (conventionally) a library function, with _exit being the actual system call. I have checked the other references and they say "if the process terminated by calling `exti`". I think despite the slight imprecision (strictly, it should read iff ... `_exit`), this is clearer. Anyone who knows about the distinction between `exit` and `_exit` will not be confused. `_exit` is the correct traditional name for the system call, despite Linux calling it `exit_group` or `exit`: https://www.freebsd.org/cgi/man.cgi?query=_exit&sektion=2&n=1 Signed-off-by: Ian Jackson --- library/std/src/os/unix/process.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/os/unix/process.rs b/library/std/src/os/unix/process.rs index 286a7c3b386f9..f573216157535 100644 --- a/library/std/src/os/unix/process.rs +++ b/library/std/src/os/unix/process.rs @@ -207,7 +207,7 @@ impl CommandExt for process::Command { /// [`ExitStatusError`](process::ExitStatusError). /// /// On Unix, `ExitStatus` **does not necessarily represent an exit status**, as -/// passed to the `exit` system call or returned by +/// passed to the `_exit` system call or returned by /// [`ExitStatus::code()`](crate::process::ExitStatus::code). It represents **any wait status** /// as returned by one of the `wait` family of system /// calls. From d1df4715ec851f7e8b019b4ed0fca14bac1dacc9 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Mon, 8 Nov 2021 17:38:01 +0000 Subject: [PATCH 08/11] unix::ExitStatus: Add comment saying that it's a wait status With cross-reference. Signed-off-by: Ian Jackson --- library/std/src/sys/unix/process/process_unix.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs index 99013efb495d0..7e674910f8e61 100644 --- a/library/std/src/sys/unix/process/process_unix.rs +++ b/library/std/src/sys/unix/process/process_unix.rs @@ -616,6 +616,9 @@ impl Process { } /// Unix exit statuses +// +// This is not actually an "exit status" in Unix terminology. Rather, it is a "wait status". +// See the discussion in comments and doc comments for `std::process::ExitStatus`. #[derive(PartialEq, Eq, Clone, Copy)] pub struct ExitStatus(c_int); From fe39fb314973f16dcb73b1f6ed8395aaf29299ec Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Mon, 8 Nov 2021 17:38:53 +0000 Subject: [PATCH 09/11] process::ExitStatus: Discuss `exit` vs `_exit` in a comment. As discussed here https://github.com/rust-lang/rust/pull/88300#issuecomment-936097710 I felt this was the best place to put this (rather than next to ExitStatusExt). After all, it's a property of the ExitStatus type on Unix. Signed-off-by: Ian Jackson --- library/std/src/process.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/library/std/src/process.rs b/library/std/src/process.rs index 9cc7fc2f0352e..b4dab41f06632 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -1417,6 +1417,11 @@ impl From for Stdio { /// /// [`status`]: Command::status /// [`wait`]: Child::wait +// +// We speak slightly loosely (here and in various other places in the stdlib docs) about `exit` +// vs `_exit`. Naming of Unix system calls is not standardised across Unices, so terminology is a +// matter of convention and tradition. For clarity we usually speak of `exit`, even when we might +// mean an underlying system call such as `_exit`. #[derive(PartialEq, Eq, Clone, Copy, Debug)] #[stable(feature = "process", since = "1.0.0")] pub struct ExitStatus(imp::ExitStatus); From 66557270419400a2d104833f3ff6dd6a55210543 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 12 Nov 2021 20:15:14 +0800 Subject: [PATCH 10/11] rustc_feature: Convert `BuiltinAttribute` from tuple to a struct --- compiler/rustc_ast_passes/src/feature_gate.rs | 13 ++-- compiler/rustc_feature/src/builtin_attrs.rs | 65 ++++++++++++------- compiler/rustc_lint/src/builtin.rs | 11 ++-- compiler/rustc_parse/src/validate_attr.rs | 11 ++-- compiler/rustc_passes/src/check_attr.rs | 4 +- compiler/rustc_resolve/src/diagnostics.rs | 2 +- 6 files changed, 62 insertions(+), 44 deletions(-) diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index f45a79f026fb5..b011a2e8117af 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -3,7 +3,7 @@ use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor}; use rustc_ast::{AssocTyConstraint, AssocTyConstraintKind, NodeId}; use rustc_ast::{PatKind, RangeEnd, VariantData}; use rustc_errors::struct_span_err; -use rustc_feature::{AttributeGate, BUILTIN_ATTRIBUTE_MAP}; +use rustc_feature::{AttributeGate, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP}; use rustc_feature::{Features, GateIssue}; use rustc_session::parse::{feature_err, feature_err_issue}; use rustc_session::Session; @@ -301,11 +301,14 @@ impl<'a> PostExpansionVisitor<'a> { impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { fn visit_attribute(&mut self, attr: &ast::Attribute) { - let attr_info = - attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name)).map(|a| **a); + let attr_info = attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name)); // Check feature gates for built-in attributes. - if let Some((.., AttributeGate::Gated(_, name, descr, has_feature))) = attr_info { - gate_feature_fn!(self, has_feature, attr.span, name, descr); + if let Some(BuiltinAttribute { + gate: AttributeGate::Gated(_, name, descr, has_feature), + .. + }) = attr_info + { + gate_feature_fn!(self, has_feature, attr.span, *name, descr); } // Check unstable flavors of the `#[doc]` attribute. if attr.has_name(sym::doc) { diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 33188d375f5d5..7212bbf38c7f2 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -115,16 +115,26 @@ macro_rules! template { macro_rules! ungated { ($attr:ident, $typ:expr, $tpl:expr $(,)?) => { - (sym::$attr, $typ, $tpl, Ungated) + BuiltinAttribute { name: sym::$attr, type_: $typ, template: $tpl, gate: Ungated } }; } macro_rules! gated { ($attr:ident, $typ:expr, $tpl:expr, $gate:ident, $msg:expr $(,)?) => { - (sym::$attr, $typ, $tpl, Gated(Stability::Unstable, sym::$gate, $msg, cfg_fn!($gate))) + BuiltinAttribute { + name: sym::$attr, + type_: $typ, + template: $tpl, + gate: Gated(Stability::Unstable, sym::$gate, $msg, cfg_fn!($gate)), + } }; ($attr:ident, $typ:expr, $tpl:expr, $msg:expr $(,)?) => { - (sym::$attr, $typ, $tpl, Gated(Stability::Unstable, sym::$attr, $msg, cfg_fn!($attr))) + BuiltinAttribute { + name: sym::$attr, + type_: $typ, + template: $tpl, + gate: Gated(Stability::Unstable, sym::$attr, $msg, cfg_fn!($attr)), + } }; } @@ -143,12 +153,12 @@ macro_rules! rustc_attr { ) }; ($attr:ident, $typ:expr, $tpl:expr, $msg:expr $(,)?) => { - ( - sym::$attr, - $typ, - $tpl, - Gated(Stability::Unstable, sym::rustc_attrs, $msg, cfg_fn!(rustc_attrs)), - ) + BuiltinAttribute { + name: sym::$attr, + type_: $typ, + template: $tpl, + gate: Gated(Stability::Unstable, sym::rustc_attrs, $msg, cfg_fn!(rustc_attrs)), + } }; } @@ -161,7 +171,12 @@ macro_rules! experimental { const IMPL_DETAIL: &str = "internal implementation detail"; const INTERNAL_UNSTABLE: &str = "this is an internal attribute that will never be stable"; -pub type BuiltinAttribute = (Symbol, AttributeType, AttributeTemplate, AttributeGate); +pub struct BuiltinAttribute { + pub name: Symbol, + pub type_: AttributeType, + pub template: AttributeTemplate, + pub gate: AttributeGate, +} /// Attributes that have a special meaning to rustc or rustdoc. #[rustfmt::skip] @@ -290,9 +305,11 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ), // Plugins: - ( - sym::plugin, CrateLevel, template!(List: "name"), - Gated( + BuiltinAttribute { + name: sym::plugin, + type_: CrateLevel, + template: template!(List: "name"), + gate: Gated( Stability::Deprecated( "https://github.com/rust-lang/rust/pull/64675", Some("may be removed in a future compiler version"), @@ -300,8 +317,8 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ sym::plugin, "compiler plugins are deprecated", cfg_fn!(plugin) - ) - ), + ), + }, // Testing: gated!(allow_fail, Normal, template!(Word), experimental!(allow_fail)), @@ -497,17 +514,17 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ lang, Normal, template!(NameValueStr: "name"), lang_items, "language items are subject to change", ), - ( - sym::rustc_diagnostic_item, - Normal, - template!(NameValueStr: "name"), - Gated( + BuiltinAttribute { + name: sym::rustc_diagnostic_item, + type_: Normal, + template: template!(NameValueStr: "name"), + gate: Gated( Stability::Unstable, sym::rustc_attrs, "diagnostic items compiler internal support for linting", cfg_fn!(rustc_attrs), ), - ), + }, gated!( // Used in resolve: prelude_import, Normal, template!(Word), @@ -601,7 +618,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ]; pub fn deprecated_attributes() -> Vec<&'static BuiltinAttribute> { - BUILTIN_ATTRIBUTES.iter().filter(|(.., gate)| gate.is_deprecated()).collect() + BUILTIN_ATTRIBUTES.iter().filter(|attr| attr.gate.is_deprecated()).collect() } pub fn is_builtin_attr_name(name: Symbol) -> bool { @@ -612,8 +629,8 @@ pub static BUILTIN_ATTRIBUTE_MAP: SyncLazy> SyncLazy::new(|| { let mut map = FxHashMap::default(); for attr in BUILTIN_ATTRIBUTES.iter() { - if map.insert(attr.0, attr).is_some() { - panic!("duplicate builtin attribute `{}`", attr.0); + if map.insert(attr.name, attr).is_some() { + panic!("duplicate builtin attribute `{}`", attr.name); } } map diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 6548cdc0fdc52..f2e4e70a19779 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -32,8 +32,7 @@ use rustc_ast_pretty::pprust::{self, expr_to_string}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString}; -use rustc_feature::{deprecated_attributes, AttributeGate, AttributeTemplate, AttributeType}; -use rustc_feature::{GateIssue, Stability}; +use rustc_feature::{deprecated_attributes, AttributeGate, BuiltinAttribute, GateIssue, Stability}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdSet, CRATE_DEF_ID}; @@ -959,7 +958,7 @@ impl EarlyLintPass for AnonymousParameters { pub struct DeprecatedAttr { // This is not free to compute, so we want to keep it around, rather than // compute it for every attribute. - depr_attrs: Vec<&'static (Symbol, AttributeType, AttributeTemplate, AttributeGate)>, + depr_attrs: Vec<&'static BuiltinAttribute>, } impl_lint_pass!(DeprecatedAttr => []); @@ -990,14 +989,14 @@ fn lint_deprecated_attr( impl EarlyLintPass for DeprecatedAttr { fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &ast::Attribute) { - for &&(n, _, _, ref g) in &self.depr_attrs { - if attr.ident().map(|ident| ident.name) == Some(n) { + for BuiltinAttribute { name, gate, .. } in &self.depr_attrs { + if attr.ident().map(|ident| ident.name) == Some(*name) { if let &AttributeGate::Gated( Stability::Deprecated(link, suggestion), name, reason, _, - ) = g + ) = gate { let msg = format!("use of deprecated attribute `{}`: {}. See {}", name, reason, link); diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs index 2aa20d02c8830..4781813ee8e56 100644 --- a/compiler/rustc_parse/src/validate_attr.rs +++ b/compiler/rustc_parse/src/validate_attr.rs @@ -5,7 +5,7 @@ use crate::parse_in; use rustc_ast::tokenstream::{DelimSpan, TokenTree}; use rustc_ast::{self as ast, Attribute, MacArgs, MacDelimiter, MetaItem, MetaItemKind}; use rustc_errors::{Applicability, FatalError, PResult}; -use rustc_feature::{AttributeTemplate, BUILTIN_ATTRIBUTE_MAP}; +use rustc_feature::{AttributeTemplate, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP}; use rustc_session::lint::builtin::ILL_FORMED_ATTRIBUTE_INPUT; use rustc_session::parse::ParseSess; use rustc_span::{sym, Symbol}; @@ -15,14 +15,13 @@ pub fn check_meta(sess: &ParseSess, attr: &Attribute) { return; } - let attr_info = - attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name)).map(|a| **a); + let attr_info = attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name)); // Check input tokens for built-in and key-value attributes. match attr_info { // `rustc_dummy` doesn't have any restrictions specific to built-in attributes. - Some((name, _, template, _)) if name != sym::rustc_dummy => { - check_builtin_attribute(sess, attr, name, template) + Some(BuiltinAttribute { name, template, .. }) if *name != sym::rustc_dummy => { + check_builtin_attribute(sess, attr, *name, *template) } _ if let MacArgs::Eq(..) = attr.get_normal_item().args => { // All key-value attributes are restricted to meta-item syntax. @@ -168,7 +167,7 @@ pub fn emit_fatal_malformed_builtin_attribute( attr: &Attribute, name: Symbol, ) -> ! { - let template = BUILTIN_ATTRIBUTE_MAP.get(&name).expect("builtin attr defined").2; + let template = BUILTIN_ATTRIBUTE_MAP.get(&name).expect("builtin attr defined").template; emit_malformed_attribute(sess, attr, name, template); // This is fatal, otherwise it will likely cause a cascade of other errors // (and an error here is expected to be very rare). diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 596d13d2d9acb..129a9fdab8234 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -11,7 +11,7 @@ use rustc_middle::ty::TyCtxt; use rustc_ast::{ast, AttrStyle, Attribute, Lit, LitKind, NestedMetaItem}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{pluralize, struct_span_err, Applicability}; -use rustc_feature::{AttributeType, BUILTIN_ATTRIBUTE_MAP}; +use rustc_feature::{AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP}; use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; @@ -148,7 +148,7 @@ impl CheckAttrVisitor<'tcx> { } if hir_id != CRATE_HIR_ID { - if let Some((_, AttributeType::CrateLevel, ..)) = + if let Some(BuiltinAttribute { type_: AttributeType::CrateLevel, .. }) = attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name)) { self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| { diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 094a5ed7bfbfe..c46a18e51031a 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -731,7 +731,7 @@ impl<'a> Resolver<'a> { suggestions.extend( BUILTIN_ATTRIBUTES .iter() - .map(|(name, ..)| TypoSuggestion::typo_from_res(*name, res)), + .map(|attr| TypoSuggestion::typo_from_res(attr.name, res)), ); } } From 9c05335a0f82a07780c6c37b0e2b2c2c9f7fc9f5 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 11 Nov 2021 12:43:54 +0100 Subject: [PATCH 11/11] Add more comments to explain the code to generate the search index --- src/librustdoc/html/render/cache.rs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs index 79421c128bcf8..af0c9faca4c17 100644 --- a/src/librustdoc/html/render/cache.rs +++ b/src/librustdoc/html/render/cache.rs @@ -241,8 +241,10 @@ fn get_index_type_name(clean_type: &clean::Type, accept_generic: bool) -> Option /// The point of this function is to replace bounds with types. /// /// i.e. `[T, U]` when you have the following bounds: `T: Display, U: Option` will return -/// `[Display, Option]` (we just returns the list of the types, we don't care about the -/// wrapped types in here). +/// `[Display, Option]`. If a type parameter has no trait bound, it is discarded. +/// +/// Important note: It goes through generics recursively. So if you have +/// `T: Option>`, it'll go into `Option` and then into `Result`. crate fn get_real_types<'tcx>( generics: &Generics, arg: &Type, @@ -326,7 +328,10 @@ crate fn get_real_types<'tcx>( return; } + // If this argument is a type parameter and not a trait bound or a type, we need to look + // for its bounds. if let Type::Generic(arg_s) = *arg { + // First we check if the bounds are in a `where` predicate... if let Some(where_pred) = generics.where_predicates.iter().find(|g| match g { WherePredicate::BoundPredicate { ty, .. } => { ty.def_id_no_primitives() == arg.def_id_no_primitives() @@ -349,6 +354,7 @@ crate fn get_real_types<'tcx>( } insert_ty(res, tcx, arg.clone(), ty_generics); } + // Otherwise we check if the trait bounds are "inlined" like `T: Option`... if let Some(bound) = generics.params.iter().find(|g| g.is_type() && g.name == arg_s) { let mut ty_generics = Vec::new(); for bound in bound.get_bounds().unwrap_or(&[]) { @@ -360,6 +366,11 @@ crate fn get_real_types<'tcx>( insert_ty(res, tcx, arg.clone(), ty_generics); } } else { + // This is not a type parameter. So for example if we have `T, U: Option`, and we're + // looking at `Option`, we enter this "else" condition, otherwise if it's `T`, we don't. + // + // So in here, we can add it directly and look for its own type parameters (so for `Option`, + // we will look for them but not for `T`). let mut ty_generics = Vec::new(); if let Some(arg_generics) = arg.generics() { for gen in arg_generics.iter() {