From 16e22e143d878bc614c03401e9d576a14a40c4bf Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 15 Oct 2022 14:33:20 +0000 Subject: [PATCH 1/6] Mark derived StructuralEq as automatically derived. --- .../rustc_builtin_macros/src/deriving/mod.rs | 16 +++-- .../ui/deriving/deriving-all-codegen.stdout | 72 ++++++++++++------- src/test/ui/single-use-lifetime/derive-eq.rs | 11 +++ 3 files changed, 70 insertions(+), 29 deletions(-) create mode 100644 src/test/ui/single-use-lifetime/derive-eq.rs diff --git a/compiler/rustc_builtin_macros/src/deriving/mod.rs b/compiler/rustc_builtin_macros/src/deriving/mod.rs index a65d0bad6de80..ee346047a0bc0 100644 --- a/compiler/rustc_builtin_macros/src/deriving/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/mod.rs @@ -131,6 +131,8 @@ fn inject_impl_of_structural_trait( // Create generics param list for where clauses and impl headers let mut generics = generics.clone(); + let ctxt = span.ctxt(); + // Create the type of `self`. // // in addition, remove defaults from generic params (impls cannot have them). @@ -138,16 +140,18 @@ fn inject_impl_of_structural_trait( .params .iter_mut() .map(|param| match &mut param.kind { - ast::GenericParamKind::Lifetime => { - ast::GenericArg::Lifetime(cx.lifetime(span, param.ident)) - } + ast::GenericParamKind::Lifetime => ast::GenericArg::Lifetime( + cx.lifetime(param.ident.span.with_ctxt(ctxt), param.ident), + ), ast::GenericParamKind::Type { default } => { *default = None; - ast::GenericArg::Type(cx.ty_ident(span, param.ident)) + ast::GenericArg::Type(cx.ty_ident(param.ident.span.with_ctxt(ctxt), param.ident)) } ast::GenericParamKind::Const { ty: _, kw_span: _, default } => { *default = None; - ast::GenericArg::Const(cx.const_ident(span, param.ident)) + ast::GenericArg::Const( + cx.const_ident(param.ident.span.with_ctxt(ctxt), param.ident), + ) } }) .collect(); @@ -174,6 +178,8 @@ fn inject_impl_of_structural_trait( }) .cloned(), ); + // Mark as `automatically_derived` to avoid some silly lints. + attrs.push(cx.attribute(cx.meta_word(span, sym::automatically_derived))); let newitem = cx.item( span, diff --git a/src/test/ui/deriving/deriving-all-codegen.stdout b/src/test/ui/deriving/deriving-all-codegen.stdout index 65f7dec840802..258ef8ba91dff 100644 --- a/src/test/ui/deriving/deriving-all-codegen.stdout +++ b/src/test/ui/deriving/deriving-all-codegen.stdout @@ -46,13 +46,15 @@ impl ::core::default::Default for Empty { impl ::core::hash::Hash for Empty { fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {} } -impl ::core::marker::StructuralPartialEq for Empty {} +#[automatically_derived] +impl ::core::marker::StructuralPartialEq for Empty { } #[automatically_derived] impl ::core::cmp::PartialEq for Empty { #[inline] fn eq(&self, other: &Empty) -> bool { true } } -impl ::core::marker::StructuralEq for Empty {} +#[automatically_derived] +impl ::core::marker::StructuralEq for Empty { } #[automatically_derived] impl ::core::cmp::Eq for Empty { #[inline] @@ -115,7 +117,8 @@ impl ::core::hash::Hash for Point { ::core::hash::Hash::hash(&self.y, state) } } -impl ::core::marker::StructuralPartialEq for Point {} +#[automatically_derived] +impl ::core::marker::StructuralPartialEq for Point { } #[automatically_derived] impl ::core::cmp::PartialEq for Point { #[inline] @@ -123,7 +126,8 @@ impl ::core::cmp::PartialEq for Point { self.x == other.x && self.y == other.y } } -impl ::core::marker::StructuralEq for Point {} +#[automatically_derived] +impl ::core::marker::StructuralEq for Point { } #[automatically_derived] impl ::core::cmp::Eq for Point { #[inline] @@ -225,7 +229,8 @@ impl ::core::hash::Hash for Big { ::core::hash::Hash::hash(&self.b8, state) } } -impl ::core::marker::StructuralPartialEq for Big {} +#[automatically_derived] +impl ::core::marker::StructuralPartialEq for Big { } #[automatically_derived] impl ::core::cmp::PartialEq for Big { #[inline] @@ -236,7 +241,8 @@ impl ::core::cmp::PartialEq for Big { self.b8 == other.b8 } } -impl ::core::marker::StructuralEq for Big {} +#[automatically_derived] +impl ::core::marker::StructuralEq for Big { } #[automatically_derived] impl ::core::cmp::Eq for Big { #[inline] @@ -345,13 +351,15 @@ impl ::core::hash::Hash for Unsized { ::core::hash::Hash::hash(&self.0, state) } } -impl ::core::marker::StructuralPartialEq for Unsized {} +#[automatically_derived] +impl ::core::marker::StructuralPartialEq for Unsized { } #[automatically_derived] impl ::core::cmp::PartialEq for Unsized { #[inline] fn eq(&self, other: &Unsized) -> bool { self.0 == other.0 } } -impl ::core::marker::StructuralEq for Unsized {} +#[automatically_derived] +impl ::core::marker::StructuralEq for Unsized { } #[automatically_derived] impl ::core::cmp::Eq for Unsized { #[inline] @@ -410,13 +418,15 @@ impl ::core::hash::Hash for PackedCopy { ::core::hash::Hash::hash(&{ self.0 }, state) } } -impl ::core::marker::StructuralPartialEq for PackedCopy {} +#[automatically_derived] +impl ::core::marker::StructuralPartialEq for PackedCopy { } #[automatically_derived] impl ::core::cmp::PartialEq for PackedCopy { #[inline] fn eq(&self, other: &PackedCopy) -> bool { { self.0 } == { other.0 } } } -impl ::core::marker::StructuralEq for PackedCopy {} +#[automatically_derived] +impl ::core::marker::StructuralEq for PackedCopy { } #[automatically_derived] impl ::core::cmp::Eq for PackedCopy { #[inline] @@ -479,7 +489,8 @@ impl ::core::hash::Hash for PackedNonCopy { ::core::hash::Hash::hash(__self_0_0, state) } } -impl ::core::marker::StructuralPartialEq for PackedNonCopy {} +#[automatically_derived] +impl ::core::marker::StructuralPartialEq for PackedNonCopy { } #[automatically_derived] impl ::core::cmp::PartialEq for PackedNonCopy { #[inline] @@ -489,7 +500,8 @@ impl ::core::cmp::PartialEq for PackedNonCopy { *__self_0_0 == *__self_1_0 } } -impl ::core::marker::StructuralEq for PackedNonCopy {} +#[automatically_derived] +impl ::core::marker::StructuralEq for PackedNonCopy { } #[automatically_derived] impl ::core::cmp::Eq for PackedNonCopy { #[inline] @@ -540,7 +552,8 @@ impl ::core::hash::Hash for Enum0 { unsafe { ::core::intrinsics::unreachable() } } } -impl ::core::marker::StructuralPartialEq for Enum0 {} +#[automatically_derived] +impl ::core::marker::StructuralPartialEq for Enum0 { } #[automatically_derived] impl ::core::cmp::PartialEq for Enum0 { #[inline] @@ -548,7 +561,8 @@ impl ::core::cmp::PartialEq for Enum0 { unsafe { ::core::intrinsics::unreachable() } } } -impl ::core::marker::StructuralEq for Enum0 {} +#[automatically_derived] +impl ::core::marker::StructuralEq for Enum0 { } #[automatically_derived] impl ::core::cmp::Eq for Enum0 { #[inline] @@ -607,7 +621,8 @@ impl ::core::hash::Hash for Enum1 { } } } -impl ::core::marker::StructuralPartialEq for Enum1 {} +#[automatically_derived] +impl ::core::marker::StructuralPartialEq for Enum1 { } #[automatically_derived] impl ::core::cmp::PartialEq for Enum1 { #[inline] @@ -618,7 +633,8 @@ impl ::core::cmp::PartialEq for Enum1 { } } } -impl ::core::marker::StructuralEq for Enum1 {} +#[automatically_derived] +impl ::core::marker::StructuralEq for Enum1 { } #[automatically_derived] impl ::core::cmp::Eq for Enum1 { #[inline] @@ -676,13 +692,15 @@ impl ::core::default::Default for Fieldless1 { impl ::core::hash::Hash for Fieldless1 { fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {} } -impl ::core::marker::StructuralPartialEq for Fieldless1 {} +#[automatically_derived] +impl ::core::marker::StructuralPartialEq for Fieldless1 { } #[automatically_derived] impl ::core::cmp::PartialEq for Fieldless1 { #[inline] fn eq(&self, other: &Fieldless1) -> bool { true } } -impl ::core::marker::StructuralEq for Fieldless1 {} +#[automatically_derived] +impl ::core::marker::StructuralEq for Fieldless1 { } #[automatically_derived] impl ::core::cmp::Eq for Fieldless1 { #[inline] @@ -743,7 +761,8 @@ impl ::core::hash::Hash for Fieldless { ::core::hash::Hash::hash(&__self_tag, state) } } -impl ::core::marker::StructuralPartialEq for Fieldless {} +#[automatically_derived] +impl ::core::marker::StructuralPartialEq for Fieldless { } #[automatically_derived] impl ::core::cmp::PartialEq for Fieldless { #[inline] @@ -753,7 +772,8 @@ impl ::core::cmp::PartialEq for Fieldless { __self_tag == __arg1_tag } } -impl ::core::marker::StructuralEq for Fieldless {} +#[automatically_derived] +impl ::core::marker::StructuralEq for Fieldless { } #[automatically_derived] impl ::core::cmp::Eq for Fieldless { #[inline] @@ -838,7 +858,8 @@ impl ::core::hash::Hash for Mixed { } } } -impl ::core::marker::StructuralPartialEq for Mixed {} +#[automatically_derived] +impl ::core::marker::StructuralPartialEq for Mixed { } #[automatically_derived] impl ::core::cmp::PartialEq for Mixed { #[inline] @@ -856,7 +877,8 @@ impl ::core::cmp::PartialEq for Mixed { } } } -impl ::core::marker::StructuralEq for Mixed {} +#[automatically_derived] +impl ::core::marker::StructuralEq for Mixed { } #[automatically_derived] impl ::core::cmp::Eq for Mixed { #[inline] @@ -963,7 +985,8 @@ impl ::core::hash::Hash for Fielded { } } } -impl ::core::marker::StructuralPartialEq for Fielded {} +#[automatically_derived] +impl ::core::marker::StructuralPartialEq for Fielded { } #[automatically_derived] impl ::core::cmp::PartialEq for Fielded { #[inline] @@ -982,7 +1005,8 @@ impl ::core::cmp::PartialEq for Fielded { } } } -impl ::core::marker::StructuralEq for Fielded {} +#[automatically_derived] +impl ::core::marker::StructuralEq for Fielded { } #[automatically_derived] impl ::core::cmp::Eq for Fielded { #[inline] diff --git a/src/test/ui/single-use-lifetime/derive-eq.rs b/src/test/ui/single-use-lifetime/derive-eq.rs new file mode 100644 index 0000000000000..e5bdfc55dd670 --- /dev/null +++ b/src/test/ui/single-use-lifetime/derive-eq.rs @@ -0,0 +1,11 @@ +// check-pass + +#![deny(single_use_lifetimes)] + +#[derive(PartialEq, Eq)] +struct Foo<'a, T> { + /// a reference to the underlying secret data that will be derefed + pub data: &'a mut T, +} + +fn main() {} From 4854e37dbce901db40cc94f078cce87985d7e0b1 Mon Sep 17 00:00:00 2001 From: philipp Date: Sat, 15 Oct 2022 14:59:27 +0200 Subject: [PATCH 2/6] Documentation BTreeMap::append's behavior for already existing keys --- library/alloc/src/collections/btree/map.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index 73bc1c21d5577..c4c75e46a2a3b 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -1093,6 +1093,9 @@ impl BTreeMap { /// Moves all elements from `other` into `self`, leaving `other` empty. /// + /// If a key from `other` is already present in `self`, the respective + /// value from `self` will be overwritten with the respective value from `other`. + /// /// # Examples /// /// ``` @@ -1101,10 +1104,10 @@ impl BTreeMap { /// let mut a = BTreeMap::new(); /// a.insert(1, "a"); /// a.insert(2, "b"); - /// a.insert(3, "c"); + /// a.insert(3, "c"); // Note: Key (3) also present in b. /// /// let mut b = BTreeMap::new(); - /// b.insert(3, "d"); + /// b.insert(3, "d"); // Note: Key (3) also present in a. /// b.insert(4, "e"); /// b.insert(5, "f"); /// @@ -1115,7 +1118,7 @@ impl BTreeMap { /// /// assert_eq!(a[&1], "a"); /// assert_eq!(a[&2], "b"); - /// assert_eq!(a[&3], "d"); + /// assert_eq!(a[&3], "d"); // Note: "c" has been overwritten. /// assert_eq!(a[&4], "e"); /// assert_eq!(a[&5], "f"); /// ``` From ddd5e983d19b9cc08fd4e587a3b0a03b5e68e26c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 16 Oct 2022 10:36:13 +0200 Subject: [PATCH 3/6] PhantomData: inline a macro that is used only once --- library/core/src/marker.rs | 112 ++++++++++++++++++------------------- 1 file changed, 53 insertions(+), 59 deletions(-) diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index d5ed52124e2ca..c43c4fff6ae77 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -483,64 +483,6 @@ impl !Sync for *const T {} #[stable(feature = "rust1", since = "1.0.0")] impl !Sync for *mut T {} -macro_rules! impls { - ($t: ident) => { - #[stable(feature = "rust1", since = "1.0.0")] - impl Hash for $t { - #[inline] - fn hash(&self, _: &mut H) {} - } - - #[stable(feature = "rust1", since = "1.0.0")] - impl cmp::PartialEq for $t { - fn eq(&self, _other: &$t) -> bool { - true - } - } - - #[stable(feature = "rust1", since = "1.0.0")] - impl cmp::Eq for $t {} - - #[stable(feature = "rust1", since = "1.0.0")] - impl cmp::PartialOrd for $t { - fn partial_cmp(&self, _other: &$t) -> Option { - Option::Some(cmp::Ordering::Equal) - } - } - - #[stable(feature = "rust1", since = "1.0.0")] - impl cmp::Ord for $t { - fn cmp(&self, _other: &$t) -> cmp::Ordering { - cmp::Ordering::Equal - } - } - - #[stable(feature = "rust1", since = "1.0.0")] - impl Copy for $t {} - - #[stable(feature = "rust1", since = "1.0.0")] - impl Clone for $t { - fn clone(&self) -> Self { - Self - } - } - - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_default_impls", issue = "87864")] - impl const Default for $t { - fn default() -> Self { - Self - } - } - - #[unstable(feature = "structural_match", issue = "31434")] - impl StructuralPartialEq for $t {} - - #[unstable(feature = "structural_match", issue = "31434")] - impl StructuralEq for $t {} - }; -} - /// Zero-sized type used to mark things that "act like" they own a `T`. /// /// Adding a `PhantomData` field to your type tells the compiler that your @@ -678,7 +620,59 @@ macro_rules! impls { #[stable(feature = "rust1", since = "1.0.0")] pub struct PhantomData; -impls! { PhantomData } +#[stable(feature = "rust1", since = "1.0.0")] +impl Hash for PhantomData { + #[inline] + fn hash(&self, _: &mut H) {} +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl cmp::PartialEq for PhantomData { + fn eq(&self, _other: &PhantomData) -> bool { + true + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl cmp::Eq for PhantomData {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl cmp::PartialOrd for PhantomData { + fn partial_cmp(&self, _other: &PhantomData) -> Option { + Option::Some(cmp::Ordering::Equal) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl cmp::Ord for PhantomData { + fn cmp(&self, _other: &PhantomData) -> cmp::Ordering { + cmp::Ordering::Equal + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Copy for PhantomData {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for PhantomData { + fn clone(&self) -> Self { + Self + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_unstable(feature = "const_default_impls", issue = "87864")] +impl const Default for PhantomData { + fn default() -> Self { + Self + } +} + +#[unstable(feature = "structural_match", issue = "31434")] +impl StructuralPartialEq for PhantomData {} + +#[unstable(feature = "structural_match", issue = "31434")] +impl StructuralEq for PhantomData {} mod impls { #[stable(feature = "rust1", since = "1.0.0")] From a6372525ce40611b21764b261cf27a288df2d825 Mon Sep 17 00:00:00 2001 From: Sky Date: Sat, 15 Oct 2022 21:41:45 -0400 Subject: [PATCH 4/6] Clarify the possible return values of len_utf16 --- library/core/src/char/methods.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index 224bc9effe61e..bb83599369c13 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -597,9 +597,14 @@ impl char { /// Returns the number of 16-bit code units this `char` would need if /// encoded in UTF-16. /// + /// That number of code units is always either 1 or 2, for unicode scalar values in + /// the [basic multilingual plane] or [supplementary planes] respectively. + /// /// See the documentation for [`len_utf8()`] for more explanation of this /// concept. This function is a mirror, but for UTF-16 instead of UTF-8. /// + /// [basic multilingual plane]: http://www.unicode.org/glossary/#basic_multilingual_plane + /// [supplementary planes]: http://www.unicode.org/glossary/#supplementary_planes /// [`len_utf8()`]: #method.len_utf8 /// /// # Examples From c65f3db2d947a616c9c50ee6ba72d40141a49e3e Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 16 Oct 2022 20:39:53 +0400 Subject: [PATCH 5/6] rustdoc: Do not expect `doc(primitive)` modules to always exist --- src/librustdoc/passes/collect_intra_doc_links.rs | 10 +++++----- src/test/rustdoc/intra-doc/no-doc-primitive.rs | 15 +++++++++++++++ 2 files changed, 20 insertions(+), 5 deletions(-) create mode 100644 src/test/rustdoc/intra-doc/no-doc-primitive.rs diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 3beda708bf2e1..3513c13d522f1 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -80,10 +80,10 @@ impl Res { } } - fn def_id(self, tcx: TyCtxt<'_>) -> DefId { + fn def_id(self, tcx: TyCtxt<'_>) -> Option { match self { - Res::Def(_, id) => id, - Res::Primitive(prim) => *PrimitiveType::primitive_locations(tcx).get(&prim).unwrap(), + Res::Def(_, id) => Some(id), + Res::Primitive(prim) => PrimitiveType::primitive_locations(tcx).get(&prim).copied(), } } @@ -1127,10 +1127,10 @@ impl LinkCollector<'_, '_> { } } - Some(ItemLink { + res.def_id(self.cx.tcx).map(|page_id| ItemLink { link: ori_link.link.clone(), link_text: link_text.clone(), - page_id: res.def_id(self.cx.tcx), + page_id, fragment, }) } diff --git a/src/test/rustdoc/intra-doc/no-doc-primitive.rs b/src/test/rustdoc/intra-doc/no-doc-primitive.rs new file mode 100644 index 0000000000000..e5eba1d8d48b4 --- /dev/null +++ b/src/test/rustdoc/intra-doc/no-doc-primitive.rs @@ -0,0 +1,15 @@ +// Crate tree without a `doc(primitive)` module for primitive type linked to by a doc link. + +#![deny(rustdoc::broken_intra_doc_links)] +#![feature(no_core, lang_items, rustc_attrs)] +#![no_core] +#![rustc_coherence_is_core] +#![crate_type = "rlib"] + +// @has no_doc_primitive/index.html +//! A [`char`] and its [`char::len_utf8`]. +impl char { + pub fn len_utf8(self) -> usize { + 42 + } +} From dd7411d84868e415a88f12e5401abc29c257f3a4 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 16 Oct 2022 21:51:13 +0400 Subject: [PATCH 6/6] rustdoc: Process extern impls in all loaded crates including those loaded through hacks. --- src/librustdoc/passes/collect_intra_doc_links/early.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/librustdoc/passes/collect_intra_doc_links/early.rs b/src/librustdoc/passes/collect_intra_doc_links/early.rs index 38cfd7a27ddb4..50dc26d768cd2 100644 --- a/src/librustdoc/passes/collect_intra_doc_links/early.rs +++ b/src/librustdoc/passes/collect_intra_doc_links/early.rs @@ -48,7 +48,6 @@ pub(crate) fn early_resolve_intra_doc_links( link_resolver.resolve_doc_links_local(&krate.attrs); link_resolver.process_module_children_or_reexports(CRATE_DEF_ID.to_def_id()); visit::walk_crate(&mut link_resolver, krate); - link_resolver.process_extern_impls(); // FIXME: somehow rustdoc is still missing crates even though we loaded all // the known necessary crates. Load them all unconditionally until we find a way to fix this. @@ -58,6 +57,8 @@ pub(crate) fn early_resolve_intra_doc_links( link_resolver.resolver.resolve_rustdoc_path(extern_name, TypeNS, parent_scope); } + link_resolver.process_extern_impls(); + ResolverCaches { markdown_links: Some(link_resolver.markdown_links), doc_link_resolutions: link_resolver.doc_link_resolutions,