Skip to content

Commit a0e010f

Browse files
committed
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 rust-lang/compiler-team#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.
2 parents f6fc9f8 + b85e916 commit a0e010f

File tree

16 files changed

+135
-33
lines changed

16 files changed

+135
-33
lines changed

alloc/src/slice.rs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ mod hack {
237237
}
238238
}
239239

240-
#[lang = "slice_alloc"]
240+
#[cfg_attr(bootstrap, lang = "slice_alloc")]
241241
#[cfg(not(test))]
242242
impl<T> [T] {
243243
/// Sorts the slice.
@@ -267,6 +267,7 @@ impl<T> [T] {
267267
/// assert!(v == [-5, -3, 1, 2, 4]);
268268
/// ```
269269
#[cfg(not(no_global_oom_handling))]
270+
#[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)]
270271
#[stable(feature = "rust1", since = "1.0.0")]
271272
#[inline]
272273
pub fn sort(&mut self)
@@ -322,6 +323,7 @@ impl<T> [T] {
322323
/// assert!(v == [5, 4, 3, 2, 1]);
323324
/// ```
324325
#[cfg(not(no_global_oom_handling))]
326+
#[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)]
325327
#[stable(feature = "rust1", since = "1.0.0")]
326328
#[inline]
327329
pub fn sort_by<F>(&mut self, mut compare: F)
@@ -363,6 +365,7 @@ impl<T> [T] {
363365
/// assert!(v == [1, 2, -3, 4, -5]);
364366
/// ```
365367
#[cfg(not(no_global_oom_handling))]
368+
#[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)]
366369
#[stable(feature = "slice_sort_by_key", since = "1.7.0")]
367370
#[inline]
368371
pub fn sort_by_key<K, F>(&mut self, mut f: F)
@@ -409,6 +412,7 @@ impl<T> [T] {
409412
///
410413
/// [pdqsort]: https://github.com/orlp/pdqsort
411414
#[cfg(not(no_global_oom_handling))]
415+
#[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)]
412416
#[stable(feature = "slice_sort_by_cached_key", since = "1.34.0")]
413417
#[inline]
414418
pub fn sort_by_cached_key<K, F>(&mut self, f: F)
@@ -467,6 +471,7 @@ impl<T> [T] {
467471
/// // Here, `s` and `x` can be modified independently.
468472
/// ```
469473
#[cfg(not(no_global_oom_handling))]
474+
#[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)]
470475
#[rustc_conversion_suggestion]
471476
#[stable(feature = "rust1", since = "1.0.0")]
472477
#[inline]
@@ -491,6 +496,7 @@ impl<T> [T] {
491496
/// // Here, `s` and `x` can be modified independently.
492497
/// ```
493498
#[cfg(not(no_global_oom_handling))]
499+
#[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)]
494500
#[inline]
495501
#[unstable(feature = "allocator_api", issue = "32838")]
496502
pub fn to_vec_in<A: Allocator>(&self, alloc: A) -> Vec<T, A>
@@ -515,6 +521,7 @@ impl<T> [T] {
515521
///
516522
/// assert_eq!(x, vec![10, 40, 30]);
517523
/// ```
524+
#[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)]
518525
#[stable(feature = "rust1", since = "1.0.0")]
519526
#[inline]
520527
pub fn into_vec<A: Allocator>(self: Box<Self, A>) -> Vec<T, A> {
@@ -542,6 +549,7 @@ impl<T> [T] {
542549
/// // this will panic at runtime
543550
/// b"0123456789abcdef".repeat(usize::MAX);
544551
/// ```
552+
#[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)]
545553
#[cfg(not(no_global_oom_handling))]
546554
#[stable(feature = "repeat_generic_slice", since = "1.40.0")]
547555
pub fn repeat(&self, n: usize) -> Vec<T>
@@ -610,6 +618,7 @@ impl<T> [T] {
610618
/// assert_eq!(["hello", "world"].concat(), "helloworld");
611619
/// assert_eq!([[1, 2], [3, 4]].concat(), [1, 2, 3, 4]);
612620
/// ```
621+
#[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)]
613622
#[stable(feature = "rust1", since = "1.0.0")]
614623
pub fn concat<Item: ?Sized>(&self) -> <Self as Concat<Item>>::Output
615624
where
@@ -628,6 +637,7 @@ impl<T> [T] {
628637
/// assert_eq!([[1, 2], [3, 4]].join(&0), [1, 2, 0, 3, 4]);
629638
/// assert_eq!([[1, 2], [3, 4]].join(&[0, 0][..]), [1, 2, 0, 0, 3, 4]);
630639
/// ```
640+
#[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)]
631641
#[stable(feature = "rename_connect_to_join", since = "1.3.0")]
632642
pub fn join<Separator>(&self, sep: Separator) -> <Self as Join<Separator>>::Output
633643
where
@@ -646,6 +656,7 @@ impl<T> [T] {
646656
/// assert_eq!(["hello", "world"].connect(" "), "hello world");
647657
/// assert_eq!([[1, 2], [3, 4]].connect(&0), [1, 2, 0, 3, 4]);
648658
/// ```
659+
#[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)]
649660
#[stable(feature = "rust1", since = "1.0.0")]
650661
#[rustc_deprecated(since = "1.3.0", reason = "renamed to join")]
651662
pub fn connect<Separator>(&self, sep: Separator) -> <Self as Join<Separator>>::Output
@@ -656,7 +667,7 @@ impl<T> [T] {
656667
}
657668
}
658669

659-
#[lang = "slice_u8_alloc"]
670+
#[cfg_attr(bootstrap, lang = "slice_u8_alloc")]
660671
#[cfg(not(test))]
661672
impl [u8] {
662673
/// Returns a vector containing a copy of this slice where each byte
@@ -669,6 +680,7 @@ impl [u8] {
669680
///
670681
/// [`make_ascii_uppercase`]: slice::make_ascii_uppercase
671682
#[cfg(not(no_global_oom_handling))]
683+
#[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)]
672684
#[must_use = "this returns the uppercase bytes as a new Vec, \
673685
without modifying the original"]
674686
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
@@ -689,6 +701,7 @@ impl [u8] {
689701
///
690702
/// [`make_ascii_lowercase`]: slice::make_ascii_lowercase
691703
#[cfg(not(no_global_oom_handling))]
704+
#[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)]
692705
#[must_use = "this returns the lowercase bytes as a new Vec, \
693706
without modifying the original"]
694707
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]

alloc/src/str.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ impl ToOwned for str {
235235
}
236236

237237
/// Methods for string slices.
238-
#[lang = "str_alloc"]
238+
#[cfg_attr(bootstrap, lang = "str_alloc")]
239239
#[cfg(not(test))]
240240
impl str {
241241
/// Converts a `Box<str>` into a `Box<[u8]>` without copying or allocating.
@@ -250,6 +250,7 @@ impl str {
250250
/// let boxed_bytes = boxed_str.into_boxed_bytes();
251251
/// assert_eq!(*boxed_bytes, *s.as_bytes());
252252
/// ```
253+
#[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)]
253254
#[stable(feature = "str_box_extras", since = "1.20.0")]
254255
#[must_use = "`self` will be dropped if the result is not used"]
255256
#[inline]
@@ -280,6 +281,7 @@ impl str {
280281
/// assert_eq!(s, s.replace("cookie monster", "little lamb"));
281282
/// ```
282283
#[cfg(not(no_global_oom_handling))]
284+
#[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)]
283285
#[must_use = "this returns the replaced string as a new allocation, \
284286
without modifying the original"]
285287
#[stable(feature = "rust1", since = "1.0.0")]
@@ -320,6 +322,7 @@ impl str {
320322
/// assert_eq!(s, s.replacen("cookie monster", "little lamb", 10));
321323
/// ```
322324
#[cfg(not(no_global_oom_handling))]
325+
#[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)]
323326
#[must_use = "this returns the replaced string as a new allocation, \
324327
without modifying the original"]
325328
#[stable(feature = "str_replacen", since = "1.16.0")]
@@ -376,6 +379,7 @@ impl str {
376379
/// assert_eq!(new_year, new_year.to_lowercase());
377380
/// ```
378381
#[cfg(not(no_global_oom_handling))]
382+
#[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)]
379383
#[must_use = "this returns the lowercase string as a new String, \
380384
without modifying the original"]
381385
#[stable(feature = "unicode_case_mapping", since = "1.2.0")]
@@ -458,6 +462,7 @@ impl str {
458462
/// assert_eq!("TSCHÜSS", s.to_uppercase());
459463
/// ```
460464
#[cfg(not(no_global_oom_handling))]
465+
#[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)]
461466
#[must_use = "this returns the uppercase string as a new String, \
462467
without modifying the original"]
463468
#[stable(feature = "unicode_case_mapping", since = "1.2.0")]
@@ -493,6 +498,7 @@ impl str {
493498
/// assert_eq!(boxed_str.into_string(), string);
494499
/// ```
495500
#[stable(feature = "box_str", since = "1.4.0")]
501+
#[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)]
496502
#[must_use = "`self` will be dropped if the result is not used"]
497503
#[inline]
498504
pub fn into_string(self: Box<str>) -> String {
@@ -521,6 +527,7 @@ impl str {
521527
/// let huge = "0123456789abcdef".repeat(usize::MAX);
522528
/// ```
523529
#[cfg(not(no_global_oom_handling))]
530+
#[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)]
524531
#[must_use]
525532
#[stable(feature = "repeat_str", since = "1.16.0")]
526533
pub fn repeat(&self, n: usize) -> String {
@@ -549,6 +556,7 @@ impl str {
549556
/// [`make_ascii_uppercase`]: str::make_ascii_uppercase
550557
/// [`to_uppercase`]: #method.to_uppercase
551558
#[cfg(not(no_global_oom_handling))]
559+
#[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)]
552560
#[must_use = "to uppercase the value in-place, use `make_ascii_uppercase()`"]
553561
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
554562
#[inline]
@@ -581,6 +589,7 @@ impl str {
581589
/// [`make_ascii_lowercase`]: str::make_ascii_lowercase
582590
/// [`to_lowercase`]: #method.to_lowercase
583591
#[cfg(not(no_global_oom_handling))]
592+
#[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)]
584593
#[must_use = "to lowercase the value in-place, use `make_ascii_lowercase()`"]
585594
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
586595
#[inline]

core/src/array/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,7 @@ macro_rules! array_impl_default {
395395

396396
array_impl_default! {32, T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T}
397397

398-
#[lang = "array"]
398+
#[cfg_attr(bootstrap, lang = "array")]
399399
impl<T, const N: usize> [T; N] {
400400
/// Returns an array of the same size as `self`, with function `f` applied to each element
401401
/// in order.

core/src/bool.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
use crate::marker::Destruct;
44

5-
#[lang = "bool"]
5+
#[cfg_attr(bootstrap, lang = "bool")]
66
impl bool {
77
/// Returns `Some(t)` if the `bool` is [`true`](../std/keyword.true.html),
88
/// or `None` otherwise.

core/src/char/methods.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::unicode::{self, conversions};
77

88
use super::*;
99

10-
#[lang = "char"]
10+
#[cfg_attr(bootstrap, lang = "char")]
1111
impl char {
1212
/// The highest valid code point a `char` can have, `'\u{10FFFF}'`.
1313
///

core/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@
8484
target_has_atomic_load_store = "ptr",
8585
))]
8686
#![no_core]
87+
#![cfg_attr(not(bootstrap), rustc_coherence_is_core)]
8788
//
8889
// Lints:
8990
#![deny(rust_2021_incompatible_or_patterns)]

core/src/num/f32.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,7 @@ pub mod consts {
370370
pub const LN_10: f32 = 2.30258509299404568401799145468436421_f32;
371371
}
372372

373-
#[lang = "f32"]
373+
#[cfg_attr(bootstrap, lang = "f32")]
374374
#[cfg(not(test))]
375375
impl f32 {
376376
/// The radix or base of the internal representation of `f32`.

core/src/num/f64.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,7 @@ pub mod consts {
370370
pub const LN_10: f64 = 2.30258509299404568401799145468436421_f64;
371371
}
372372

373-
#[lang = "f64"]
373+
#[cfg_attr(bootstrap, lang = "f64")]
374374
#[cfg(not(test))]
375375
impl f64 {
376376
/// The radix or base of the internal representation of `f64`.

core/src/num/mod.rs

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -193,34 +193,34 @@ macro_rules! widening_impl {
193193
};
194194
}
195195

196-
#[lang = "i8"]
196+
#[cfg_attr(bootstrap, lang = "i8")]
197197
impl i8 {
198198
int_impl! { i8, i8, u8, 8, 7, -128, 127, 2, "-0x7e", "0xa", "0x12", "0x12", "0x48",
199199
"[0x12]", "[0x12]", "", "" }
200200
}
201201

202-
#[lang = "i16"]
202+
#[cfg_attr(bootstrap, lang = "i16")]
203203
impl i16 {
204204
int_impl! { i16, i16, u16, 16, 15, -32768, 32767, 4, "-0x5ffd", "0x3a", "0x1234", "0x3412",
205205
"0x2c48", "[0x34, 0x12]", "[0x12, 0x34]", "", "" }
206206
}
207207

208-
#[lang = "i32"]
208+
#[cfg_attr(bootstrap, lang = "i32")]
209209
impl i32 {
210210
int_impl! { i32, i32, u32, 32, 31, -2147483648, 2147483647, 8, "0x10000b3", "0xb301",
211211
"0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]",
212212
"[0x12, 0x34, 0x56, 0x78]", "", "" }
213213
}
214214

215-
#[lang = "i64"]
215+
#[cfg_attr(bootstrap, lang = "i64")]
216216
impl i64 {
217217
int_impl! { i64, i64, u64, 64, 63, -9223372036854775808, 9223372036854775807, 12,
218218
"0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412",
219219
"0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
220220
"[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", "", "" }
221221
}
222222

223-
#[lang = "i128"]
223+
#[cfg_attr(bootstrap, lang = "i128")]
224224
impl i128 {
225225
int_impl! { i128, i128, u128, 128, 127, -170141183460469231731687303715884105728,
226226
170141183460469231731687303715884105727, 16,
@@ -233,15 +233,15 @@ impl i128 {
233233
}
234234

235235
#[cfg(target_pointer_width = "16")]
236-
#[lang = "isize"]
236+
#[cfg_attr(bootstrap, lang = "isize")]
237237
impl isize {
238238
int_impl! { isize, i16, usize, 16, 15, -32768, 32767, 4, "-0x5ffd", "0x3a", "0x1234",
239239
"0x3412", "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]",
240240
usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
241241
}
242242

243243
#[cfg(target_pointer_width = "32")]
244-
#[lang = "isize"]
244+
#[cfg_attr(bootstrap, lang = "isize")]
245245
impl isize {
246246
int_impl! { isize, i32, usize, 32, 31, -2147483648, 2147483647, 8, "0x10000b3", "0xb301",
247247
"0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]",
@@ -250,7 +250,7 @@ impl isize {
250250
}
251251

252252
#[cfg(target_pointer_width = "64")]
253-
#[lang = "isize"]
253+
#[cfg_attr(bootstrap, lang = "isize")]
254254
impl isize {
255255
int_impl! { isize, i64, usize, 64, 63, -9223372036854775808, 9223372036854775807,
256256
12, "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412",
@@ -262,7 +262,7 @@ impl isize {
262262
/// If 6th bit set ascii is upper case.
263263
const ASCII_CASE_MASK: u8 = 0b0010_0000;
264264

265-
#[lang = "u8"]
265+
#[cfg_attr(bootstrap, lang = "u8")]
266266
impl u8 {
267267
uint_impl! { u8, u8, i8, NonZeroU8, 8, 255, 2, "0x82", "0xa", "0x12", "0x12", "0x48", "[0x12]",
268268
"[0x12]", "", "" }
@@ -816,7 +816,7 @@ impl u8 {
816816
}
817817
}
818818

819-
#[lang = "u16"]
819+
#[cfg_attr(bootstrap, lang = "u16")]
820820
impl u16 {
821821
uint_impl! { u16, u16, i16, NonZeroU16, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48",
822822
"[0x34, 0x12]", "[0x12, 0x34]", "", "" }
@@ -848,14 +848,14 @@ impl u16 {
848848
}
849849
}
850850

851-
#[lang = "u32"]
851+
#[cfg_attr(bootstrap, lang = "u32")]
852852
impl u32 {
853853
uint_impl! { u32, u32, i32, NonZeroU32, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678",
854854
"0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", "", "" }
855855
widening_impl! { u32, u64, 32, unsigned }
856856
}
857857

858-
#[lang = "u64"]
858+
#[cfg_attr(bootstrap, lang = "u64")]
859859
impl u64 {
860860
uint_impl! { u64, u64, i64, NonZeroU64, 64, 18446744073709551615, 12, "0xaa00000000006e1", "0x6e10aa",
861861
"0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48",
@@ -865,7 +865,7 @@ impl u64 {
865865
widening_impl! { u64, u128, 64, unsigned }
866866
}
867867

868-
#[lang = "u128"]
868+
#[cfg_attr(bootstrap, lang = "u128")]
869869
impl u128 {
870870
uint_impl! { u128, u128, i128, NonZeroU128, 128, 340282366920938463463374607431768211455, 16,
871871
"0x13f40000000000000000000000004f76", "0x4f7613f4", "0x12345678901234567890123456789012",
@@ -878,15 +878,15 @@ impl u128 {
878878
}
879879

880880
#[cfg(target_pointer_width = "16")]
881-
#[lang = "usize"]
881+
#[cfg_attr(bootstrap, lang = "usize")]
882882
impl usize {
883883
uint_impl! { usize, u16, isize, NonZeroUsize, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48",
884884
"[0x34, 0x12]", "[0x12, 0x34]",
885885
usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
886886
widening_impl! { usize, u32, 16, unsigned }
887887
}
888888
#[cfg(target_pointer_width = "32")]
889-
#[lang = "usize"]
889+
#[cfg_attr(bootstrap, lang = "usize")]
890890
impl usize {
891891
uint_impl! { usize, u32, isize, NonZeroUsize, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678",
892892
"0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]",
@@ -895,7 +895,7 @@ impl usize {
895895
}
896896

897897
#[cfg(target_pointer_width = "64")]
898-
#[lang = "usize"]
898+
#[cfg_attr(bootstrap, lang = "usize")]
899899
impl usize {
900900
uint_impl! { usize, u64, isize, NonZeroUsize, 64, 18446744073709551615, 12, "0xaa00000000006e1", "0x6e10aa",
901901
"0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48",

0 commit comments

Comments
 (0)