From 603fd426df04d133f803870a28cd9bd2434bb6ad Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 17 Jul 2023 14:56:14 +0000 Subject: [PATCH 1/6] Properly document lifetime_mapping in OpaqueTy --- compiler/rustc_ast_lowering/src/lib.rs | 24 +++++++++++-------- compiler/rustc_hir/src/hir.rs | 17 +++++++++---- .../src/collect/predicates_of.rs | 2 +- 3 files changed, 28 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 429e62c4a1c63..9e193402feb20 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1619,13 +1619,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { debug!(?hir_bounds); let lifetime_mapping = if in_trait { - self.arena.alloc_from_iter( - collected_lifetime_mapping - .iter() - .map(|(lifetime, def_id)| (**lifetime, *def_id)), + Some( + &*self.arena.alloc_from_iter( + collected_lifetime_mapping + .iter() + .map(|(lifetime, def_id)| (**lifetime, *def_id)), + ), ) } else { - &mut [] + None }; let opaque_ty_item = hir::OpaqueTy { @@ -2090,13 +2092,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { debug!("lower_async_fn_ret_ty: generic_params={:#?}", generic_params); let lifetime_mapping = if in_trait { - self.arena.alloc_from_iter( - collected_lifetime_mapping - .iter() - .map(|(lifetime, def_id)| (**lifetime, *def_id)), + Some( + &*self.arena.alloc_from_iter( + collected_lifetime_mapping + .iter() + .map(|(lifetime, def_id)| (**lifetime, *def_id)), + ), ) } else { - &mut [] + None }; let opaque_ty_item = hir::OpaqueTy { diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 35ef30114b712..68f1559ea220e 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2664,10 +2664,19 @@ pub struct OpaqueTy<'hir> { pub generics: &'hir Generics<'hir>, pub bounds: GenericBounds<'hir>, pub origin: OpaqueTyOrigin, - // Opaques have duplicated lifetimes, this mapping connects the original lifetime with the copy - // so we can later generate bidirectional outlives predicates to enforce that these lifetimes - // stay in sync. - pub lifetime_mapping: &'hir [(Lifetime, LocalDefId)], + /// Return-position impl traits (and async futures) must "reify" any late-bound + /// lifetimes that are captured from the function signature they originate from. + /// + /// This is done by generating a new early-bound lifetime parameter local to the + /// opaque which is substituted in the function signature with the late-bound + /// lifetime. + /// + /// This mapping associated a captured lifetime (first parameter) with the new + /// early-bound lifetime that was generated for the opaque. + pub lifetime_mapping: Option<&'hir [(Lifetime, LocalDefId)]>, + /// Whether the opaque is a return-position impl trait (or async future) + /// originating from a trait method. This makes it so that the opaque is + /// lowered as an associated type. pub in_trait: bool, } diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 1c9070600dbe3..979b101e7fe2d 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -66,7 +66,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen let opaque_ty_id = tcx.hir().local_def_id_to_hir_id(opaque_def_id.expect_local()); let opaque_ty_node = tcx.hir().get(opaque_ty_id); let Node::Item(&Item { - kind: ItemKind::OpaqueTy(OpaqueTy { lifetime_mapping, .. }), + kind: ItemKind::OpaqueTy(OpaqueTy { lifetime_mapping: Some(lifetime_mapping), .. }), .. }) = opaque_ty_node else { From 33bd453f3521ea3cfb67602eada912948b7aeb81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= Date: Tue, 18 Jul 2023 09:10:45 +0800 Subject: [PATCH 2/6] Fix removal span calculation of unused_qualifications suggestion --- compiler/rustc_lint/src/context.rs | 8 ++--- compiler/rustc_lint_defs/src/lib.rs | 6 ++-- compiler/rustc_resolve/src/late.rs | 6 ++-- tests/ui/lint/lint-qualification.fixed | 21 +++++++++++++ tests/ui/lint/lint-qualification.rs | 1 + tests/ui/lint/lint-qualification.stderr | 11 ++++--- ...lid-unused-qualifications-suggestion.fixed | 31 +++++++++++++++++++ ...nvalid-unused-qualifications-suggestion.rs | 31 +++++++++++++++++++ ...id-unused-qualifications-suggestion.stderr | 31 +++++++++++++++++++ .../unused-qualifications-suggestion.stderr | 14 +++++---- 10 files changed, 138 insertions(+), 22 deletions(-) create mode 100644 tests/ui/lint/lint-qualification.fixed create mode 100644 tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.fixed create mode 100644 tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.rs create mode 100644 tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.stderr diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 6522e449386c7..7c701fd4fe16e 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -956,11 +956,11 @@ pub trait LintContext: Sized { db.span_note(glob_reexport_span, format!("the name `{}` in the {} namespace is supposed to be publicly re-exported here", name, namespace)); db.span_note(private_item_span, "but the private item here shadows it".to_owned()); } - BuiltinLintDiagnostics::UnusedQualifications { path_span, unqualified_path } => { + BuiltinLintDiagnostics::UnusedQualifications { removal_span } => { db.span_suggestion_verbose( - path_span, - "replace it with the unqualified path", - unqualified_path, + removal_span, + "remove the unnecessary path segments", + "", Applicability::MachineApplicable ); } diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index f6ffd46b1fe08..10ebe29dfce69 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -551,10 +551,8 @@ pub enum BuiltinLintDiagnostics { private_item_span: Span, }, UnusedQualifications { - /// The span of the unnecessarily-qualified path. - path_span: Span, - /// The replacement unqualified path. - unqualified_path: Ident, + /// The span of the unnecessarily-qualified path to remove. + removal_span: Span, }, } diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 846a1ffe09b17..05128a51016a0 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -3911,8 +3911,9 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { && path[0].ident.name != kw::PathRoot && path[0].ident.name != kw::DollarCrate { + let last_segment = *path.last().unwrap(); let unqualified_result = { - match self.resolve_path(&[*path.last().unwrap()], Some(ns), None) { + match self.resolve_path(&[last_segment], Some(ns), None) { PathResult::NonModule(path_res) => path_res.expect_full_res(), PathResult::Module(ModuleOrUniformRoot::Module(module)) => { module.res().unwrap() @@ -3928,8 +3929,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { finalize.path_span, "unnecessary qualification", lint::BuiltinLintDiagnostics::UnusedQualifications { - path_span: finalize.path_span, - unqualified_path: path.last().unwrap().ident + removal_span: finalize.path_span.until(last_segment.ident.span), } ) } diff --git a/tests/ui/lint/lint-qualification.fixed b/tests/ui/lint/lint-qualification.fixed new file mode 100644 index 0000000000000..c144930136234 --- /dev/null +++ b/tests/ui/lint/lint-qualification.fixed @@ -0,0 +1,21 @@ +// run-rustfix +#![deny(unused_qualifications)] +#![allow(deprecated)] + +mod foo { + pub fn bar() {} +} + +fn main() { + use foo::bar; + bar(); //~ ERROR: unnecessary qualification + bar(); + + let _ = || -> Result<(), ()> { try!(Ok(())); Ok(()) }; // issue #37345 + + macro_rules! m { () => { + $crate::foo::bar(); // issue #37357 + ::foo::bar(); // issue #38682 + } } + m!(); +} diff --git a/tests/ui/lint/lint-qualification.rs b/tests/ui/lint/lint-qualification.rs index 0cace0ca0355a..80904303559d8 100644 --- a/tests/ui/lint/lint-qualification.rs +++ b/tests/ui/lint/lint-qualification.rs @@ -1,3 +1,4 @@ +// run-rustfix #![deny(unused_qualifications)] #![allow(deprecated)] diff --git a/tests/ui/lint/lint-qualification.stderr b/tests/ui/lint/lint-qualification.stderr index d09cb78c4f013..90a06bc6cbe5d 100644 --- a/tests/ui/lint/lint-qualification.stderr +++ b/tests/ui/lint/lint-qualification.stderr @@ -1,18 +1,19 @@ error: unnecessary qualification - --> $DIR/lint-qualification.rs:10:5 + --> $DIR/lint-qualification.rs:11:5 | LL | foo::bar(); | ^^^^^^^^ | note: the lint level is defined here - --> $DIR/lint-qualification.rs:1:9 + --> $DIR/lint-qualification.rs:2:9 | LL | #![deny(unused_qualifications)] | ^^^^^^^^^^^^^^^^^^^^^ -help: replace it with the unqualified path +help: remove the unnecessary path segments + | +LL - foo::bar(); +LL + bar(); | -LL | bar(); - | ~~~ error: aborting due to previous error diff --git a/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.fixed b/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.fixed new file mode 100644 index 0000000000000..e730f94660bbd --- /dev/null +++ b/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.fixed @@ -0,0 +1,31 @@ +// run-rustfix + +#![deny(unused_qualifications)] +#![feature(unsized_fn_params)] + +#[allow(unused_imports)] +use std::ops; +use std::ops::Index; + +pub struct A; + +impl Index for A { + //~^ ERROR unnecessary qualification + type Output = (); + fn index(&self, _: str) -> &Self::Output { + &() + } +} + +mod inner { + pub trait Trait {} +} + +// the import needs to be here for the lint to show up +#[allow(unused_imports)] +use inner::Trait; + +impl Trait for () {} +//~^ ERROR unnecessary qualification + +fn main() {} diff --git a/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.rs b/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.rs new file mode 100644 index 0000000000000..641c892e3de9a --- /dev/null +++ b/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.rs @@ -0,0 +1,31 @@ +// run-rustfix + +#![deny(unused_qualifications)] +#![feature(unsized_fn_params)] + +#[allow(unused_imports)] +use std::ops; +use std::ops::Index; + +pub struct A; + +impl ops::Index for A { + //~^ ERROR unnecessary qualification + type Output = (); + fn index(&self, _: str) -> &Self::Output { + &() + } +} + +mod inner { + pub trait Trait {} +} + +// the import needs to be here for the lint to show up +#[allow(unused_imports)] +use inner::Trait; + +impl inner::Trait for () {} +//~^ ERROR unnecessary qualification + +fn main() {} diff --git a/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.stderr b/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.stderr new file mode 100644 index 0000000000000..d9c7fd21871ba --- /dev/null +++ b/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.stderr @@ -0,0 +1,31 @@ +error: unnecessary qualification + --> $DIR/issue-113808-invalid-unused-qualifications-suggestion.rs:12:6 + | +LL | impl ops::Index for A { + | ^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/issue-113808-invalid-unused-qualifications-suggestion.rs:3:9 + | +LL | #![deny(unused_qualifications)] + | ^^^^^^^^^^^^^^^^^^^^^ +help: remove the unnecessary path segments + | +LL - impl ops::Index for A { +LL + impl Index for A { + | + +error: unnecessary qualification + --> $DIR/issue-113808-invalid-unused-qualifications-suggestion.rs:28:6 + | +LL | impl inner::Trait for () {} + | ^^^^^^^^^^^^^^^^ + | +help: remove the unnecessary path segments + | +LL - impl inner::Trait for () {} +LL + impl Trait for () {} + | + +error: aborting due to 2 previous errors + diff --git a/tests/ui/resolve/unused-qualifications-suggestion.stderr b/tests/ui/resolve/unused-qualifications-suggestion.stderr index c8e91e07295b6..e3dac37fc6e22 100644 --- a/tests/ui/resolve/unused-qualifications-suggestion.stderr +++ b/tests/ui/resolve/unused-qualifications-suggestion.stderr @@ -9,10 +9,11 @@ note: the lint level is defined here | LL | #![deny(unused_qualifications)] | ^^^^^^^^^^^^^^^^^^^^^ -help: replace it with the unqualified path +help: remove the unnecessary path segments + | +LL - foo::bar(); +LL + bar(); | -LL | bar(); - | ~~~ error: unnecessary qualification --> $DIR/unused-qualifications-suggestion.rs:21:5 @@ -20,10 +21,11 @@ error: unnecessary qualification LL | baz::qux::quux(); | ^^^^^^^^^^^^^^ | -help: replace it with the unqualified path +help: remove the unnecessary path segments + | +LL - baz::qux::quux(); +LL + quux(); | -LL | quux(); - | ~~~~ error: aborting due to 2 previous errors From 2779d1531717e97020a444ed04a957d074a91013 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Mon, 17 Jul 2023 21:53:19 -0500 Subject: [PATCH 3/6] docs(release): Remove nightly-only cargo item See rust-lang/cargo#12343 --- RELEASES.md | 1 - 1 file changed, 1 deletion(-) diff --git a/RELEASES.md b/RELEASES.md index 3205b02e5c452..e8c79c573f976 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -92,7 +92,6 @@ Cargo ----- - [Allow named debuginfo options in `Cargo.toml`.](https://github.com/rust-lang/cargo/pull/11958/) - [Add `workspace_default_members` to the output of `cargo metadata`.](https://github.com/rust-lang/cargo/pull/11978/) -- [`cargo add` now considers `rust-version` when selecting packages.](https://github.com/rust-lang/cargo/pull/12078/) - [Automatically inherit workspace fields when running `cargo new`/`cargo init`.](https://github.com/rust-lang/cargo/pull/12069/) From 6fb4ce9f88ee0651a7a05f512a155de21f395e11 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 16 Jul 2023 23:22:16 +0200 Subject: [PATCH 4/6] Fix invalid display of inlined re-export --- src/librustdoc/clean/mod.rs | 19 +++++++++++++++--- src/librustdoc/visit_ast.rs | 40 ++++++++++++++++++++++++------------- 2 files changed, 42 insertions(+), 17 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 2d00c53951fef..56545983d425e 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -90,6 +90,19 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext< } v })); + items.extend(doc.inlined_foreigns.values().flat_map(|(res, renamed, local_import_id)| { + let Some(def_id) = res.opt_def_id() else { return Vec::new() }; + let name = renamed.unwrap_or_else(|| cx.tcx.item_name(def_id)); + let import = cx.tcx.hir().expect_item(*local_import_id); + match import.kind { + hir::ItemKind::Use(path, kind) => { + let hir::UsePath { segments, span, .. } = *path; + let path = hir::Path { segments, res: *res, span }; + clean_use_statement_inner(import, name, &path, kind, cx, &mut Default::default()) + } + _ => unreachable!(), + } + })); items.extend(doc.items.values().flat_map(|(item, renamed, _)| { // Now we actually lower the imports, skipping everything else. if let hir::ItemKind::Use(path, hir::UseKind::Glob) = item.kind { @@ -2652,9 +2665,6 @@ fn clean_use_statement<'tcx>( let mut items = Vec::new(); let hir::UsePath { segments, ref res, span } = *path; for &res in res { - if let Res::Def(DefKind::Ctor(..), _) | Res::SelfCtor(..) = res { - continue; - } let path = hir::Path { segments, res, span }; items.append(&mut clean_use_statement_inner(import, name, &path, kind, cx, inlined_names)); } @@ -2669,6 +2679,9 @@ fn clean_use_statement_inner<'tcx>( cx: &mut DocContext<'tcx>, inlined_names: &mut FxHashSet<(ItemType, Symbol)>, ) -> Vec { + if let Res::Def(DefKind::Ctor(..), _) | Res::SelfCtor(..) = path.res { + return Vec::new(); + } // We need this comparison because some imports (for std types for example) // are "inserted" as well but directly by the compiler and they should not be // taken into account. diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 265123ddf6c8b..cee3995eff411 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -35,6 +35,9 @@ pub(crate) struct Module<'hir> { (LocalDefId, Option), (&'hir hir::Item<'hir>, Option, Option), >, + /// Same as for `items`. + pub(crate) inlined_foreigns: + FxIndexMap<(DefId, Option), (Res, Option, LocalDefId)>, pub(crate) foreigns: Vec<(&'hir hir::ForeignItem<'hir>, Option)>, } @@ -54,6 +57,7 @@ impl Module<'_> { import_id, mods: Vec::new(), items: FxIndexMap::default(), + inlined_foreigns: FxIndexMap::default(), foreigns: Vec::new(), } } @@ -272,21 +276,30 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { return false; } - // For cross-crate impl inlining we need to know whether items are - // reachable in documentation -- a previously unreachable item can be - // made reachable by cross-crate inlining which we're checking here. - // (this is done here because we need to know this upfront). - if !ori_res_did.is_local() && !is_no_inline { - crate::visit_lib::lib_embargo_visit_item(self.cx, ori_res_did); - return false; - } - + let is_hidden = !document_hidden && tcx.is_doc_hidden(ori_res_did); let Some(res_did) = ori_res_did.as_local() else { - return false; + // For cross-crate impl inlining we need to know whether items are + // reachable in documentation -- a previously unreachable item can be + // made reachable by cross-crate inlining which we're checking here. + // (this is done here because we need to know this upfront). + crate::visit_lib::lib_embargo_visit_item(self.cx, ori_res_did); + if is_hidden { + return false; + } + // We store inlined foreign items otherwise, it'd mean that the `use` item would be kept + // around. It's not a problem unless this `use` imports both a local AND a foreign item. + // If a local item is inlined, its `use` is not supposed to still be around in `clean`, + // which would make appear the `use` in the generated documentation like the local item + // was not inlined even though it actually was. + self.modules + .last_mut() + .unwrap() + .inlined_foreigns + .insert((ori_res_did, renamed), (res, renamed, def_id)); + return true; }; let is_private = !self.cx.cache.effective_visibilities.is_directly_public(tcx, ori_res_did); - let is_hidden = !document_hidden && tcx.is_doc_hidden(ori_res_did); let item = tcx.hir().get_by_def_id(res_did); if !please_inline { @@ -314,7 +327,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { return false; } - let inlined = match tcx.hir().get_by_def_id(res_did) { + let inlined = match item { // Bang macros are handled a bit on their because of how they are handled by the // compiler. If they have `#[doc(hidden)]` and the re-export doesn't have // `#[doc(inline)]`, then we don't inline it. @@ -346,7 +359,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { }; self.view_item_stack.remove(&res_did); if inlined { - self.cx.cache.inlined_items.insert(res_did.to_def_id()); + self.cx.cache.inlined_items.insert(ori_res_did); } inlined } @@ -483,7 +496,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { continue; } } - self.add_to_current_mod(item, renamed, import_id); } } From c845a53aa23c1252f1cc15528799d652512b877e Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 16 Jul 2023 15:54:23 +0200 Subject: [PATCH 5/6] Add regression test for #105735 --- .../issue-105735-overlapping-reexport-2.rs | 25 +++++++++++++++++++ .../issue-105735-overlapping-reexport.rs | 21 ++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 tests/rustdoc/issue-105735-overlapping-reexport-2.rs create mode 100644 tests/rustdoc/issue-105735-overlapping-reexport.rs diff --git a/tests/rustdoc/issue-105735-overlapping-reexport-2.rs b/tests/rustdoc/issue-105735-overlapping-reexport-2.rs new file mode 100644 index 0000000000000..9108248394894 --- /dev/null +++ b/tests/rustdoc/issue-105735-overlapping-reexport-2.rs @@ -0,0 +1,25 @@ +// Regression test to ensure that both `AtomicU8` items are displayed but not the re-export. + +#![crate_name = "foo"] +#![no_std] + +// @has 'foo/index.html' +// @has - '//*[@class="item-name"]/a[@class="type"]' 'AtomicU8' +// @has - '//*[@class="item-name"]/a[@class="constant"]' 'AtomicU8' +// We also ensure we don't have another item displayed. +// @count - '//*[@id="main-content"]/*[@class="small-section-header"]' 2 +// @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Type Definitions' +// @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Constants' + +mod other { + pub type AtomicU8 = (); +} + +mod thing { + pub use crate::other::AtomicU8; + + #[allow(non_upper_case_globals)] + pub const AtomicU8: () = (); +} + +pub use crate::thing::AtomicU8; diff --git a/tests/rustdoc/issue-105735-overlapping-reexport.rs b/tests/rustdoc/issue-105735-overlapping-reexport.rs new file mode 100644 index 0000000000000..50f2450b90a0b --- /dev/null +++ b/tests/rustdoc/issue-105735-overlapping-reexport.rs @@ -0,0 +1,21 @@ +// Regression test to ensure that both `AtomicU8` items are displayed but not the re-export. + +#![crate_name = "foo"] +#![no_std] + +// @has 'foo/index.html' +// @has - '//*[@class="item-name"]/a[@class="struct"]' 'AtomicU8' +// @has - '//*[@class="item-name"]/a[@class="constant"]' 'AtomicU8' +// We also ensure we don't have another item displayed. +// @count - '//*[@id="main-content"]/*[@class="small-section-header"]' 2 +// @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Structs' +// @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Constants' + +mod thing { + pub use core::sync::atomic::AtomicU8; + + #[allow(non_upper_case_globals)] + pub const AtomicU8: () = (); +} + +pub use crate::thing::AtomicU8; From afec6d242bf308139503e4051fc4251f785b377a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 17 Jul 2023 20:33:54 +0200 Subject: [PATCH 6/6] Remove unneeded `Option` in `foreign_items` --- src/librustdoc/clean/mod.rs | 2 +- src/librustdoc/visit_ast.rs | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 56545983d425e..d14953f1bb786 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -90,7 +90,7 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext< } v })); - items.extend(doc.inlined_foreigns.values().flat_map(|(res, renamed, local_import_id)| { + items.extend(doc.inlined_foreigns.iter().flat_map(|((_, renamed), (res, local_import_id))| { let Some(def_id) = res.opt_def_id() else { return Vec::new() }; let name = renamed.unwrap_or_else(|| cx.tcx.item_name(def_id)); let import = cx.tcx.hir().expect_item(*local_import_id); diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index cee3995eff411..66737a0152158 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -36,8 +36,7 @@ pub(crate) struct Module<'hir> { (&'hir hir::Item<'hir>, Option, Option), >, /// Same as for `items`. - pub(crate) inlined_foreigns: - FxIndexMap<(DefId, Option), (Res, Option, LocalDefId)>, + pub(crate) inlined_foreigns: FxIndexMap<(DefId, Option), (Res, LocalDefId)>, pub(crate) foreigns: Vec<(&'hir hir::ForeignItem<'hir>, Option)>, } @@ -295,7 +294,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { .last_mut() .unwrap() .inlined_foreigns - .insert((ori_res_did, renamed), (res, renamed, def_id)); + .insert((ori_res_did, renamed), (res, def_id)); return true; };