about summary refs log tree commit diff
path: root/library/alloc/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-03-30 12:28:50 +0000
committerbors <bors@rust-lang.org>2022-03-30 12:28:50 +0000
commit3e7514670db841a7f0d7656f3b13b1c8b2c11599 (patch)
treeea65f9f3d772de91ee27bf207de8cbf7ff997e8f /library/alloc/src
parente50ff9b4521234e56ff46f8ed0372d5cb5689654 (diff)
parent46340f20497fd9f30e08d5c30413f6f45164da89 (diff)
downloadrust-3e7514670db841a7f0d7656f3b13b1c8b2c11599.tar.gz
rust-3e7514670db841a7f0d7656f3b13b1c8b2c11599.zip
Auto merge of #94963 - lcnr:inherent-impls-std, r=oli-obk,m-ou-se
allow arbitrary inherent impls for builtin types in core

Part of https://github.com/rust-lang/compiler-team/issues/487. Slightly adjusted after some talks with `@m-ou-se` about the requirements of `t-libs-api`.

This adds a crate attribute `#![rustc_coherence_is_core]` which allows arbitrary impls for builtin types in core.

For other library crates impls for builtin types should be avoided if possible. We do have to allow the existing stable impls however. To prevent us from accidentally adding more of these in the future, there is a second attribute `#[rustc_allow_incoherent_impl]` which has to be added to **all impl items**. This only supports impls for builtin types but can easily be extended to additional types in a future PR.

This implementation does not check for overlaps in these impls. Perfectly checking that requires us to check the coherence of these incoherent impls in every crate, as two distinct dependencies may add overlapping methods. It should be easy enough to detect if it goes wrong and the attribute is only intended for use inside of std.

The first two commits are mostly unrelated cleanups.
Diffstat (limited to 'library/alloc/src')
-rw-r--r--library/alloc/src/slice.rs17
-rw-r--r--library/alloc/src/str.rs11
2 files changed, 25 insertions, 3 deletions
diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs
index 31365562ddb..89d85146963 100644
--- a/library/alloc/src/slice.rs
+++ b/library/alloc/src/slice.rs
@@ -237,7 +237,7 @@ mod hack {
     }
 }
 
-#[lang = "slice_alloc"]
+#[cfg_attr(bootstrap, lang = "slice_alloc")]
 #[cfg(not(test))]
 impl<T> [T] {
     /// Sorts the slice.
@@ -267,6 +267,7 @@ impl<T> [T] {
     /// assert!(v == [-5, -3, 1, 2, 4]);
     /// ```
     #[cfg(not(no_global_oom_handling))]
+    #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn sort(&mut self)
@@ -322,6 +323,7 @@ impl<T> [T] {
     /// assert!(v == [5, 4, 3, 2, 1]);
     /// ```
     #[cfg(not(no_global_oom_handling))]
+    #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn sort_by<F>(&mut self, mut compare: F)
@@ -363,6 +365,7 @@ impl<T> [T] {
     /// assert!(v == [1, 2, -3, 4, -5]);
     /// ```
     #[cfg(not(no_global_oom_handling))]
+    #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)]
     #[stable(feature = "slice_sort_by_key", since = "1.7.0")]
     #[inline]
     pub fn sort_by_key<K, F>(&mut self, mut f: F)
@@ -409,6 +412,7 @@ impl<T> [T] {
     ///
     /// [pdqsort]: https://github.com/orlp/pdqsort
     #[cfg(not(no_global_oom_handling))]
+    #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)]
     #[stable(feature = "slice_sort_by_cached_key", since = "1.34.0")]
     #[inline]
     pub fn sort_by_cached_key<K, F>(&mut self, f: F)
@@ -467,6 +471,7 @@ impl<T> [T] {
     /// // Here, `s` and `x` can be modified independently.
     /// ```
     #[cfg(not(no_global_oom_handling))]
+    #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)]
     #[rustc_conversion_suggestion]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
@@ -491,6 +496,7 @@ impl<T> [T] {
     /// // Here, `s` and `x` can be modified independently.
     /// ```
     #[cfg(not(no_global_oom_handling))]
+    #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)]
     #[inline]
     #[unstable(feature = "allocator_api", issue = "32838")]
     pub fn to_vec_in<A: Allocator>(&self, alloc: A) -> Vec<T, A>
@@ -515,6 +521,7 @@ impl<T> [T] {
     ///
     /// assert_eq!(x, vec![10, 40, 30]);
     /// ```
+    #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn into_vec<A: Allocator>(self: Box<Self, A>) -> Vec<T, A> {
@@ -542,6 +549,7 @@ impl<T> [T] {
     /// // this will panic at runtime
     /// b"0123456789abcdef".repeat(usize::MAX);
     /// ```
+    #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)]
     #[cfg(not(no_global_oom_handling))]
     #[stable(feature = "repeat_generic_slice", since = "1.40.0")]
     pub fn repeat(&self, n: usize) -> Vec<T>
@@ -610,6 +618,7 @@ impl<T> [T] {
     /// assert_eq!(["hello", "world"].concat(), "helloworld");
     /// assert_eq!([[1, 2], [3, 4]].concat(), [1, 2, 3, 4]);
     /// ```
+    #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn concat<Item: ?Sized>(&self) -> <Self as Concat<Item>>::Output
     where
@@ -628,6 +637,7 @@ impl<T> [T] {
     /// assert_eq!([[1, 2], [3, 4]].join(&0), [1, 2, 0, 3, 4]);
     /// assert_eq!([[1, 2], [3, 4]].join(&[0, 0][..]), [1, 2, 0, 0, 3, 4]);
     /// ```
+    #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)]
     #[stable(feature = "rename_connect_to_join", since = "1.3.0")]
     pub fn join<Separator>(&self, sep: Separator) -> <Self as Join<Separator>>::Output
     where
@@ -646,6 +656,7 @@ impl<T> [T] {
     /// assert_eq!(["hello", "world"].connect(" "), "hello world");
     /// assert_eq!([[1, 2], [3, 4]].connect(&0), [1, 2, 0, 3, 4]);
     /// ```
+    #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_deprecated(since = "1.3.0", reason = "renamed to join")]
     pub fn connect<Separator>(&self, sep: Separator) -> <Self as Join<Separator>>::Output
@@ -656,7 +667,7 @@ impl<T> [T] {
     }
 }
 
-#[lang = "slice_u8_alloc"]
+#[cfg_attr(bootstrap, lang = "slice_u8_alloc")]
 #[cfg(not(test))]
 impl [u8] {
     /// Returns a vector containing a copy of this slice where each byte
@@ -669,6 +680,7 @@ impl [u8] {
     ///
     /// [`make_ascii_uppercase`]: slice::make_ascii_uppercase
     #[cfg(not(no_global_oom_handling))]
+    #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)]
     #[must_use = "this returns the uppercase bytes as a new Vec, \
                   without modifying the original"]
     #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
@@ -689,6 +701,7 @@ impl [u8] {
     ///
     /// [`make_ascii_lowercase`]: slice::make_ascii_lowercase
     #[cfg(not(no_global_oom_handling))]
+    #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)]
     #[must_use = "this returns the lowercase bytes as a new Vec, \
                   without modifying the original"]
     #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
diff --git a/library/alloc/src/str.rs b/library/alloc/src/str.rs
index 69495f31c32..a3c17612c3a 100644
--- a/library/alloc/src/str.rs
+++ b/library/alloc/src/str.rs
@@ -235,7 +235,7 @@ impl ToOwned for str {
 }
 
 /// Methods for string slices.
-#[lang = "str_alloc"]
+#[cfg_attr(bootstrap, lang = "str_alloc")]
 #[cfg(not(test))]
 impl str {
     /// Converts a `Box<str>` into a `Box<[u8]>` without copying or allocating.
@@ -250,6 +250,7 @@ impl str {
     /// let boxed_bytes = boxed_str.into_boxed_bytes();
     /// assert_eq!(*boxed_bytes, *s.as_bytes());
     /// ```
+    #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)]
     #[stable(feature = "str_box_extras", since = "1.20.0")]
     #[must_use = "`self` will be dropped if the result is not used"]
     #[inline]
@@ -280,6 +281,7 @@ impl str {
     /// assert_eq!(s, s.replace("cookie monster", "little lamb"));
     /// ```
     #[cfg(not(no_global_oom_handling))]
+    #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)]
     #[must_use = "this returns the replaced string as a new allocation, \
                   without modifying the original"]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -320,6 +322,7 @@ impl str {
     /// assert_eq!(s, s.replacen("cookie monster", "little lamb", 10));
     /// ```
     #[cfg(not(no_global_oom_handling))]
+    #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)]
     #[must_use = "this returns the replaced string as a new allocation, \
                   without modifying the original"]
     #[stable(feature = "str_replacen", since = "1.16.0")]
@@ -376,6 +379,7 @@ impl str {
     /// assert_eq!(new_year, new_year.to_lowercase());
     /// ```
     #[cfg(not(no_global_oom_handling))]
+    #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)]
     #[must_use = "this returns the lowercase string as a new String, \
                   without modifying the original"]
     #[stable(feature = "unicode_case_mapping", since = "1.2.0")]
@@ -458,6 +462,7 @@ impl str {
     /// assert_eq!("TSCHÜSS", s.to_uppercase());
     /// ```
     #[cfg(not(no_global_oom_handling))]
+    #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)]
     #[must_use = "this returns the uppercase string as a new String, \
                   without modifying the original"]
     #[stable(feature = "unicode_case_mapping", since = "1.2.0")]
@@ -493,6 +498,7 @@ impl str {
     /// assert_eq!(boxed_str.into_string(), string);
     /// ```
     #[stable(feature = "box_str", since = "1.4.0")]
+    #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)]
     #[must_use = "`self` will be dropped if the result is not used"]
     #[inline]
     pub fn into_string(self: Box<str>) -> String {
@@ -521,6 +527,7 @@ impl str {
     /// let huge = "0123456789abcdef".repeat(usize::MAX);
     /// ```
     #[cfg(not(no_global_oom_handling))]
+    #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)]
     #[must_use]
     #[stable(feature = "repeat_str", since = "1.16.0")]
     pub fn repeat(&self, n: usize) -> String {
@@ -549,6 +556,7 @@ impl str {
     /// [`make_ascii_uppercase`]: str::make_ascii_uppercase
     /// [`to_uppercase`]: #method.to_uppercase
     #[cfg(not(no_global_oom_handling))]
+    #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)]
     #[must_use = "to uppercase the value in-place, use `make_ascii_uppercase()`"]
     #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
     #[inline]
@@ -581,6 +589,7 @@ impl str {
     /// [`make_ascii_lowercase`]: str::make_ascii_lowercase
     /// [`to_lowercase`]: #method.to_lowercase
     #[cfg(not(no_global_oom_handling))]
+    #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)]
     #[must_use = "to lowercase the value in-place, use `make_ascii_lowercase()`"]
     #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
     #[inline]