diff --git a/compiler/rustc_error_codes/src/error_codes/E0118.md b/compiler/rustc_error_codes/src/error_codes/E0118.md index 345ec341c3f40..8033aa8384c2e 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0118.md +++ b/compiler/rustc_error_codes/src/error_codes/E0118.md @@ -4,7 +4,7 @@ enum, union, or trait object. Erroneous code example: ```compile_fail,E0118 -impl (u8, u8) { // error: no nominal type found for inherent implementation +impl fn(u8) { // error: no nominal type found for inherent implementation fn get_state(&self) -> String { // ... } @@ -20,8 +20,8 @@ trait LiveLongAndProsper { fn get_state(&self) -> String; } -// and now you can implement it on (u8, u8) -impl LiveLongAndProsper for (u8, u8) { +// and now you can implement it on fn(u8) +impl LiveLongAndProsper for fn(u8) { fn get_state(&self) -> String { "He's dead, Jim!".to_owned() } @@ -33,7 +33,7 @@ For example, `NewType` is a newtype over `Foo` in `struct NewType(Foo)`. Example: ``` -struct TypeWrapper((u8, u8)); +struct TypeWrapper(fn(u8)); impl TypeWrapper { fn get_state(&self) -> String { @@ -41,24 +41,3 @@ impl TypeWrapper { } } ``` - -Instead of defining an inherent implementation on a reference, you could also -move the reference inside the implementation: - -```compile_fail,E0118 -struct Foo; - -impl &Foo { // error: no nominal type found for inherent implementation - fn bar(self, other: Self) {} -} -``` - -becomes - -``` -struct Foo; - -impl Foo { - fn bar(&self, other: &Self) {} -} -``` diff --git a/compiler/rustc_error_codes/src/error_codes/E0390.md b/compiler/rustc_error_codes/src/error_codes/E0390.md index 7a13160d09858..26a9dd331ce11 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0390.md +++ b/compiler/rustc_error_codes/src/error_codes/E0390.md @@ -8,8 +8,7 @@ struct Foo { } impl *mut Foo {} -// error: only a single inherent implementation marked with -// `#[lang = "mut_ptr"]` is allowed for the `*mut T` primitive +// error: cannot define inherent `impl` for primitive types ``` This isn't allowed, but using a trait to implement a method or constant @@ -29,3 +28,24 @@ impl Bar for *mut Foo { fn bar() {} // ok! } ``` + +Instead of defining an inherent implementation on a reference, you could also +move the reference inside the implementation: + +```compile_fail,E0390 +struct Foo; + +impl &Foo { // error: no nominal type found for inherent implementation + fn bar(self, other: Self) {} +} +``` + +becomes + +``` +struct Foo; + +impl Foo { + fn bar(&self, other: &Self) {} +} +``` diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index e2f0b413ff379..7c53f839a92e4 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -636,6 +636,14 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ template!(Word), ErrorFollowing, "#[rustc_pass_by_value] is used to mark types that must be passed by value instead of reference." ), + rustc_attr!( + rustc_coherence_is_core, AttributeType::CrateLevel, template!(Word), ErrorFollowing, + "#![rustc_coherence_is_core] allows inherent methods on builtin types, only intended to be used in `core`." + ), + rustc_attr!( + rustc_allow_incoherent_impl, AttributeType::Normal, template!(Word), ErrorFollowing, + "#[rustc_allow_incoherent_impl] has to be added to all impl items of an incoherent inherent impl." + ), BuiltinAttribute { name: sym::rustc_diagnostic_item, type_: Normal, diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index 7c312e1b61d5a..b8df163214435 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -166,36 +166,6 @@ pub fn extract(attrs: &[ast::Attribute]) -> Option<(Symbol, Span)> { language_item_table! { // Variant name, Name, Method name, Target Generic requirements; - Bool, sym::bool, bool_impl, Target::Impl, GenericRequirement::None; - Char, sym::char, char_impl, Target::Impl, GenericRequirement::None; - Str, sym::str, str_impl, Target::Impl, GenericRequirement::None; - Array, sym::array, array_impl, Target::Impl, GenericRequirement::None; - Slice, sym::slice, slice_impl, Target::Impl, GenericRequirement::None; - SliceU8, sym::slice_u8, slice_u8_impl, Target::Impl, GenericRequirement::None; - StrAlloc, sym::str_alloc, str_alloc_impl, Target::Impl, GenericRequirement::None; - SliceAlloc, sym::slice_alloc, slice_alloc_impl, Target::Impl, GenericRequirement::None; - SliceU8Alloc, sym::slice_u8_alloc, slice_u8_alloc_impl, Target::Impl, GenericRequirement::None; - ConstPtr, sym::const_ptr, const_ptr_impl, Target::Impl, GenericRequirement::None; - MutPtr, sym::mut_ptr, mut_ptr_impl, Target::Impl, GenericRequirement::None; - ConstSlicePtr, sym::const_slice_ptr, const_slice_ptr_impl, Target::Impl, GenericRequirement::None; - MutSlicePtr, sym::mut_slice_ptr, mut_slice_ptr_impl, Target::Impl, GenericRequirement::None; - I8, sym::i8, i8_impl, Target::Impl, GenericRequirement::None; - I16, sym::i16, i16_impl, Target::Impl, GenericRequirement::None; - I32, sym::i32, i32_impl, Target::Impl, GenericRequirement::None; - I64, sym::i64, i64_impl, Target::Impl, GenericRequirement::None; - I128, sym::i128, i128_impl, Target::Impl, GenericRequirement::None; - Isize, sym::isize, isize_impl, Target::Impl, GenericRequirement::None; - U8, sym::u8, u8_impl, Target::Impl, GenericRequirement::None; - U16, sym::u16, u16_impl, Target::Impl, GenericRequirement::None; - U32, sym::u32, u32_impl, Target::Impl, GenericRequirement::None; - U64, sym::u64, u64_impl, Target::Impl, GenericRequirement::None; - U128, sym::u128, u128_impl, Target::Impl, GenericRequirement::None; - Usize, sym::usize, usize_impl, Target::Impl, GenericRequirement::None; - F32, sym::f32, f32_impl, Target::Impl, GenericRequirement::None; - F64, sym::f64, f64_impl, Target::Impl, GenericRequirement::None; - F32Runtime, sym::f32_runtime, f32_runtime_impl, Target::Impl, GenericRequirement::None; - F64Runtime, sym::f64_runtime, f64_runtime_impl, Target::Impl, GenericRequirement::None; - Sized, sym::sized, sized_trait, Target::Trait, GenericRequirement::Exact(0); Unsize, sym::unsize, unsize_trait, Target::Trait, GenericRequirement::Minimum(1); /// Trait injected by `#[derive(PartialEq)]`, (i.e. "Partial EQ"). diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 2e6ce7b7040f9..e88ef68c7224d 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -95,6 +95,11 @@ crate struct CrateMetadata { /// FIXME: Used only from queries and can use query cache, /// so pre-decoding can probably be avoided. trait_impls: FxHashMap<(u32, DefIndex), Lazy<[(DefIndex, Option)]>>, + /// Inherent impls which do not follow the normal coherence rules. + /// + /// These can be introduced using either `#![rustc_coherence_is_core]` + /// or `#[rustc_allow_incoherent_impl]`. + incoherent_impls: FxHashMap>, /// Proc macro descriptions for this crate, if it's a proc macro crate. raw_proc_macros: Option<&'static [ProcMacro]>, /// Source maps for code from the crate. @@ -1028,11 +1033,13 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } /// Iterates over the language items in the given crate. - fn get_lang_items(self) -> impl Iterator + 'a { - self.root - .lang_items - .decode(self) - .map(move |(def_index, index)| (self.local_def_id(def_index), index)) + fn get_lang_items(self, tcx: TyCtxt<'tcx>) -> &'tcx [(DefId, usize)] { + tcx.arena.alloc_from_iter( + self.root + .lang_items + .decode(self) + .map(move |(def_index, index)| (self.local_def_id(def_index), index)), + ) } /// Iterates over the diagnostic items in the given crate. @@ -1327,10 +1334,10 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { /// Decodes all trait impls in the crate (for rustdoc). fn get_trait_impls(self) -> impl Iterator)> + 'a { - self.cdata.trait_impls.iter().flat_map(move |((trait_cnum_raw, trait_index), impls)| { + self.cdata.trait_impls.iter().flat_map(move |(&(trait_cnum_raw, trait_index), impls)| { let trait_def_id = DefId { - krate: self.cnum_map[CrateNum::from_u32(*trait_cnum_raw)], - index: *trait_index, + krate: self.cnum_map[CrateNum::from_u32(trait_cnum_raw)], + index: trait_index, }; impls.decode(self).map(move |(impl_index, simplified_self_ty)| { (trait_def_id, self.local_def_id(impl_index), simplified_self_ty) @@ -1338,6 +1345,21 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { }) } + fn get_all_incoherent_impls(self) -> impl Iterator + 'a { + self.cdata + .incoherent_impls + .values() + .flat_map(move |impls| impls.decode(self).map(move |idx| self.local_def_id(idx))) + } + + fn get_incoherent_impls(self, tcx: TyCtxt<'tcx>, simp: SimplifiedType) -> &'tcx [DefId] { + if let Some(impls) = self.cdata.incoherent_impls.get(&simp) { + tcx.arena.alloc_from_iter(impls.decode(self).map(|idx| self.local_def_id(idx))) + } else { + &[] + } + } + fn get_implementations_of_trait( self, tcx: TyCtxt<'tcx>, @@ -1754,6 +1776,11 @@ impl CrateMetadata { .decode((&blob, sess)) .map(|trait_impls| (trait_impls.trait_id, trait_impls.impls)) .collect(); + let incoherent_impls = root + .incoherent_impls + .decode((&blob, sess)) + .map(|incoherent_impls| (incoherent_impls.self_ty, incoherent_impls.impls)) + .collect(); let alloc_decoding_state = AllocDecodingState::new(root.interpret_alloc_index.decode(&blob).collect()); let dependencies = Lock::new(cnum_map.iter().cloned().collect()); @@ -1766,6 +1793,7 @@ impl CrateMetadata { blob, root, trait_impls, + incoherent_impls, raw_proc_macros, source_map_import_info: OnceCell::new(), def_path_hash_map, diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 5ae965ff7fadb..70358ae0e22aa 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -81,30 +81,42 @@ macro_rules! provide { // small trait to work around different signature queries all being defined via // the macro above. trait IntoArgs { - fn into_args(self) -> (DefId, DefId); + type Other; + fn into_args(self) -> (DefId, Self::Other); } impl IntoArgs for DefId { - fn into_args(self) -> (DefId, DefId) { - (self, self) + type Other = (); + fn into_args(self) -> (DefId, ()) { + (self, ()) } } impl IntoArgs for CrateNum { - fn into_args(self) -> (DefId, DefId) { - (self.as_def_id(), self.as_def_id()) + type Other = (); + fn into_args(self) -> (DefId, ()) { + (self.as_def_id(), ()) } } impl IntoArgs for (CrateNum, DefId) { + type Other = DefId; fn into_args(self) -> (DefId, DefId) { (self.0.as_def_id(), self.1) } } impl<'tcx> IntoArgs for ty::InstanceDef<'tcx> { - fn into_args(self) -> (DefId, DefId) { - (self.def_id(), self.def_id()) + type Other = (); + fn into_args(self) -> (DefId, ()) { + (self.def_id(), ()) + } +} + +impl IntoArgs for (CrateNum, SimplifiedType) { + type Other = SimplifiedType; + fn into_args(self) -> (DefId, SimplifiedType) { + (self.0.as_def_id(), self.1) } } @@ -199,6 +211,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, traits_in_crate => { tcx.arena.alloc_from_iter(cdata.get_traits()) } implementations_of_trait => { cdata.get_implementations_of_trait(tcx, other) } + crate_incoherent_impls => { cdata.get_incoherent_impls(tcx, other) } dep_kind => { let r = *cdata.dep_kind.lock(); @@ -210,7 +223,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, tcx.arena.alloc_slice(&result) } defined_lib_features => { cdata.get_lib_features(tcx) } - defined_lang_items => { tcx.arena.alloc_from_iter(cdata.get_lang_items()) } + defined_lang_items => { cdata.get_lang_items(tcx) } diagnostic_items => { cdata.get_diagnostic_items() } missing_lang_items => { cdata.get_missing_lang_items(tcx) } @@ -371,7 +384,6 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) { .alloc_slice(&CStore::from_tcx(tcx).crate_dependencies_in_postorder(LOCAL_CRATE)) }, crates: |tcx, ()| tcx.arena.alloc_from_iter(CStore::from_tcx(tcx).crates_untracked()), - ..*providers }; } @@ -511,9 +523,12 @@ impl CStore { self.get_crate_data(cnum).get_inherent_impls() } - /// Decodes all lang items in the crate (for rustdoc). - pub fn lang_items_untracked(&self, cnum: CrateNum) -> impl Iterator + '_ { - self.get_crate_data(cnum).get_lang_items().map(|(def_id, _)| def_id) + /// Decodes all incoherent inherent impls in the crate (for rustdoc). + pub fn incoherent_impls_in_crate_untracked( + &self, + cnum: CrateNum, + ) -> impl Iterator + '_ { + self.get_crate_data(cnum).get_all_incoherent_impls() } } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 924e5f921039e..a219b9eb2be83 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -2,8 +2,9 @@ use crate::rmeta::def_path_hash_map::DefPathHashMapRef; use crate::rmeta::table::{FixedSizeEncoding, TableBuilder}; use crate::rmeta::*; +use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; -use rustc_data_structures::stable_hasher::StableHasher; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::{join, par_iter, Lrc, ParallelIterator}; use rustc_hir as hir; use rustc_hir::def::DefKind; @@ -578,6 +579,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } fn encode_crate_root(&mut self) -> Lazy> { + let tcx = self.tcx; let mut i = self.position(); // Encode the crate deps @@ -623,8 +625,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let impls = self.encode_impls(); let impls_bytes = self.position() - i; - let tcx = self.tcx; - + i = self.position(); + let incoherent_impls = self.encode_incoherent_impls(); + let incoherent_impls_bytes = self.position() - i; // Encode MIR. i = self.position(); self.encode_mir(); @@ -734,6 +737,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { source_map, traits, impls, + incoherent_impls, exported_symbols, interpret_alloc_index, tables, @@ -762,6 +766,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { eprintln!(" source_map bytes: {}", source_map_bytes); eprintln!(" traits bytes: {}", traits_bytes); eprintln!(" impls bytes: {}", impls_bytes); + eprintln!("incoherent_impls bytes: {}", incoherent_impls_bytes); eprintln!(" exp. symbols bytes: {}", exported_symbols_bytes); eprintln!(" def-path table bytes: {}", def_path_table_bytes); eprintln!(" def-path hashes bytes: {}", def_path_hash_map_bytes); @@ -1813,6 +1818,33 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.lazy(&all_impls) } + fn encode_incoherent_impls(&mut self) -> Lazy<[IncoherentImpls]> { + debug!("EncodeContext::encode_traits_and_impls()"); + empty_proc_macro!(self); + let tcx = self.tcx; + let mut ctx = tcx.create_stable_hashing_context(); + let mut all_impls: Vec<_> = tcx.crate_inherent_impls(()).incoherent_impls.iter().collect(); + all_impls.sort_by_cached_key(|&(&simp, _)| { + let mut hasher = StableHasher::new(); + simp.hash_stable(&mut ctx, &mut hasher); + hasher.finish::(); + }); + let all_impls: Vec<_> = all_impls + .into_iter() + .map(|(&simp, impls)| { + let mut impls: Vec<_> = + impls.into_iter().map(|def_id| def_id.local_def_index).collect(); + impls.sort_by_cached_key(|&local_def_index| { + tcx.hir().def_path_hash(LocalDefId { local_def_index }) + }); + + IncoherentImpls { self_ty: simp, impls: self.lazy(impls) } + }) + .collect(); + + self.lazy(&all_impls) + } + // Encodes all symbols exported from this crate into the metadata. // // This pass is seeded off the reachability list calculated in the diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index a30cc034c4a96..204284ffaa3f9 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -212,6 +212,7 @@ crate struct CrateRoot<'tcx> { foreign_modules: Lazy<[ForeignModule]>, traits: Lazy<[DefIndex]>, impls: Lazy<[TraitImpls]>, + incoherent_impls: Lazy<[IncoherentImpls]>, interpret_alloc_index: Lazy<[u32]>, proc_macro_data: Option, @@ -251,6 +252,12 @@ crate struct TraitImpls { impls: Lazy<[(DefIndex, Option)]>, } +#[derive(MetadataEncodable, MetadataDecodable)] +crate struct IncoherentImpls { + self_ty: SimplifiedType, + impls: Lazy<[DefIndex]>, +} + /// Define `LazyTables` and `TableBuilders` at the same time. macro_rules! define_tables { ($($name:ident: Table<$IDX:ty, $T:ty>),+ $(,)?) => { diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index ec20e888333da..8afa6e70e4183 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -579,6 +579,10 @@ impl<'hir> Map<'hir> { self.attrs(CRATE_HIR_ID) } + pub fn rustc_coherence_is_core(self) -> bool { + self.krate_attrs().iter().any(|attr| attr.has_name(sym::rustc_coherence_is_core)) + } + pub fn get_module(self, module: LocalDefId) -> (&'hir Mod<'hir>, Span, HirId) { let hir_id = HirId::make_owner(module); match self.tcx.hir_owner(module).map(|o| o.node) { diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 95260e9e9173f..6d7e7ef0cb072 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -684,6 +684,10 @@ rustc_queries! { separate_provide_extern } + query incoherent_impls(key: SimplifiedType) -> &'tcx [DefId] { + desc { |tcx| "collecting all inherent impls for `{:?}`", key } + } + /// The result of unsafety-checking this `LocalDefId`. query unsafety_check_result(key: LocalDefId) -> &'tcx mir::UnsafetyCheckResult { desc { |tcx| "unsafety-checking `{}`", tcx.def_path_str(key.to_def_id()) } @@ -1469,6 +1473,15 @@ rustc_queries! { separate_provide_extern } + /// Collects all incoherent impls for the given crate and type. + /// + /// Do not call this directly, but instead use the `incoherent_impls` query. + /// This query is only used to get the data necessary for that query. + query crate_incoherent_impls(key: (CrateNum, SimplifiedType)) -> &'tcx [DefId] { + desc { |tcx| "collecting all impls for a type in a crate" } + separate_provide_extern + } + query is_dllimport_foreign_item(def_id: DefId) -> bool { desc { |tcx| "is_dllimport_foreign_item({})", tcx.def_path_str(def_id) } } diff --git a/compiler/rustc_middle/src/ty/impls_ty.rs b/compiler/rustc_middle/src/ty/impls_ty.rs index 54a345daec8a5..2009364b24e60 100644 --- a/compiler/rustc_middle/src/ty/impls_ty.rs +++ b/compiler/rustc_middle/src/ty/impls_ty.rs @@ -4,6 +4,7 @@ use crate::middle::region; use crate::mir; use crate::ty; +use crate::ty::fast_reject::SimplifiedType; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::HashingControls; @@ -55,6 +56,18 @@ where } } +impl<'a> ToStableHashKey> for SimplifiedType { + type KeyType = Fingerprint; + + #[inline] + fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> Fingerprint { + let mut hasher = StableHasher::new(); + let mut hcx: StableHashingContext<'a> = hcx.clone(); + self.hash_stable(&mut hcx, &mut hasher); + hasher.finish() + } +} + impl<'a, 'tcx> HashStable> for ty::subst::GenericArg<'tcx> { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { self.unpack().hash_stable(hcx, hasher); diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 44c190e459c3d..dfc405b1195ee 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -25,6 +25,7 @@ use crate::middle::privacy::AccessLevels; use crate::mir::{Body, GeneratorLayout}; use crate::traits::{self, Reveal}; use crate::ty; +use crate::ty::fast_reject::SimplifiedType; use crate::ty::subst::{GenericArg, InternalSubsts, Subst, SubstsRef}; use crate::ty::util::Discr; use rustc_ast as ast; @@ -2335,6 +2336,7 @@ pub fn provide(providers: &mut ty::query::Providers) { super::middle::provide(providers); *providers = ty::query::Providers { trait_impls_of: trait_def::trait_impls_of_provider, + incoherent_impls: trait_def::incoherent_impls_provider, type_uninhabited_from: inhabitedness::type_uninhabited_from, const_param_default: consts::const_param_default, vtable_allocation: vtable::vtable_allocation_provider, @@ -2350,6 +2352,7 @@ pub fn provide(providers: &mut ty::query::Providers) { #[derive(Clone, Debug, Default, HashStable)] pub struct CrateInherentImpls { pub inherent_impls: LocalDefIdMap>, + pub incoherent_impls: FxHashMap>, } #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, HashStable)] diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 335ddeb66db05..5a13216846d54 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1889,10 +1889,7 @@ impl<'tcx> Ty<'tcx> { #[inline] pub fn is_slice(self) -> bool { - match self.kind() { - RawPtr(TypeAndMut { ty, .. }) | Ref(_, ty, _) => matches!(ty.kind(), Slice(_) | Str), - _ => false, - } + matches!(self.kind(), Slice(_)) } #[inline] diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs index 8ebeca50c4174..943f610cc0dd3 100644 --- a/compiler/rustc_middle/src/ty/trait_def.rs +++ b/compiler/rustc_middle/src/ty/trait_def.rs @@ -2,9 +2,11 @@ use crate::traits::specialization_graph; use crate::ty::fast_reject::{self, SimplifiedType, TreatParams}; use crate::ty::fold::TypeFoldable; use crate::ty::{Ident, Ty, TyCtxt}; +use hir::def_id::LOCAL_CRATE; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::definitions::DefPathHash; +use std::iter; use rustc_data_structures::fx::FxIndexMap; use rustc_errors::ErrorGuaranteed; @@ -257,3 +259,19 @@ pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> Trait impls } + +// Query provider for `incoherent_impls`. +#[instrument(level = "debug", skip(tcx))] +pub(super) fn incoherent_impls_provider(tcx: TyCtxt<'_>, simp: SimplifiedType) -> &[DefId] { + let mut impls = Vec::new(); + + for cnum in iter::once(LOCAL_CRATE).chain(tcx.crates(()).iter().copied()) { + for &impl_def_id in tcx.crate_incoherent_impls((cnum, simp)) { + impls.push(impl_def_id) + } + } + + debug!(?impls); + + tcx.arena.alloc_slice(&impls) +} diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 4f9e1d3fa3bca..8aa659fa6ac7c 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -120,6 +120,9 @@ impl CheckAttrVisitor<'_> { sym::must_not_suspend => self.check_must_not_suspend(&attr, span, target), sym::must_use => self.check_must_use(hir_id, &attr, span, target), sym::rustc_pass_by_value => self.check_pass_by_value(&attr, span, target), + sym::rustc_allow_incoherent_impl => { + self.check_allow_incoherent_impl(&attr, span, target) + } sym::rustc_const_unstable | sym::rustc_const_stable | sym::unstable @@ -1080,6 +1083,24 @@ impl CheckAttrVisitor<'_> { } } + /// Warns against some misuses of `#[pass_by_value]` + fn check_allow_incoherent_impl(&self, attr: &Attribute, span: Span, target: Target) -> bool { + match target { + Target::Method(MethodKind::Inherent) => true, + _ => { + self.tcx + .sess + .struct_span_err( + attr.span, + "`rustc_allow_incoherent_impl` attribute should be applied to impl items.", + ) + .span_label(span, "the only currently supported targets are inherent methods") + .emit(); + false + } + } + } + /// Warns against some misuses of `#[must_use]` fn check_must_use(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) -> bool { let node = self.tcx.hir().get(hir_id); diff --git a/compiler/rustc_query_impl/src/keys.rs b/compiler/rustc_query_impl/src/keys.rs index 84de31a194da0..f1f83a7299c4d 100644 --- a/compiler/rustc_query_impl/src/keys.rs +++ b/compiler/rustc_query_impl/src/keys.rs @@ -141,6 +141,16 @@ impl Key for ty::WithOptConstParam { } } +impl Key for SimplifiedType { + #[inline(always)] + fn query_crate_is_local(&self) -> bool { + true + } + fn default_span(&self, _: TyCtxt<'_>) -> Span { + DUMMY_SP + } +} + impl Key for (DefId, DefId) { #[inline(always)] fn query_crate_is_local(&self) -> bool { @@ -215,6 +225,16 @@ impl Key for (CrateNum, DefId) { } } +impl Key for (CrateNum, SimplifiedType) { + #[inline(always)] + fn query_crate_is_local(&self) -> bool { + self.0 == LOCAL_CRATE + } + fn default_span(&self, _: TyCtxt<'_>) -> Span { + DUMMY_SP + } +} + impl Key for (DefId, SimplifiedType) { #[inline(always)] fn query_crate_is_local(&self) -> bool { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 5cf362bfa7e98..84dbad846dd29 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -494,11 +494,9 @@ symbols! { const_panic, const_panic_fmt, const_precise_live_drops, - const_ptr, const_raw_ptr_deref, const_raw_ptr_to_usize_cast, const_refs_to_cell, - const_slice_ptr, const_trait_bound_opt_out, const_trait_impl, const_transmute, @@ -655,9 +653,7 @@ symbols! { f, f16c_target_feature, f32, - f32_runtime, f64, - f64_runtime, fabsf32, fabsf64, fadd_fast, @@ -913,8 +909,6 @@ symbols! { mul_with_overflow, must_not_suspend, must_use, - mut_ptr, - mut_slice_ptr, naked, naked_functions, name, @@ -1160,10 +1154,12 @@ symbols! { rustc_allocator, rustc_allocator_nounwind, rustc_allow_const_fn_unstable, + rustc_allow_incoherent_impl, rustc_attrs, rustc_builtin_macro, rustc_capture_analysis, rustc_clean, + rustc_coherence_is_core, rustc_const_stable, rustc_const_unstable, rustc_conversion_suggestion, @@ -1312,11 +1308,8 @@ symbols! { sized, skip, slice, - slice_alloc, slice_len_fn, slice_patterns, - slice_u8, - slice_u8_alloc, slicing_syntax, soft, specialization, @@ -1346,7 +1339,6 @@ symbols! { stop_after_dataflow, store, str, - str_alloc, str_split_whitespace, str_trim, str_trim_end, diff --git a/compiler/rustc_typeck/src/check/method/mod.rs b/compiler/rustc_typeck/src/check/method/mod.rs index 1ca9c1920961a..adc284785c294 100644 --- a/compiler/rustc_typeck/src/check/method/mod.rs +++ b/compiler/rustc_typeck/src/check/method/mod.rs @@ -78,28 +78,6 @@ pub struct NoMatchData<'tcx> { pub mode: probe::Mode, } -impl<'tcx> NoMatchData<'tcx> { - pub fn new( - static_candidates: Vec, - unsatisfied_predicates: Vec<( - ty::Predicate<'tcx>, - Option>, - Option>, - )>, - out_of_scope_traits: Vec, - lev_candidate: Option, - mode: probe::Mode, - ) -> Self { - NoMatchData { - static_candidates, - unsatisfied_predicates, - out_of_scope_traits, - lev_candidate, - mode, - } - } -} - // A pared down enum describing just the places from which a method // candidate can arise. Used for error reporting only. #[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] diff --git a/compiler/rustc_typeck/src/check/method/probe.rs b/compiler/rustc_typeck/src/check/method/probe.rs index abdce9f586638..5d91b3b46a176 100644 --- a/compiler/rustc_typeck/src/check/method/probe.rs +++ b/compiler/rustc_typeck/src/check/method/probe.rs @@ -18,6 +18,7 @@ use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKi use rustc_infer::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; use rustc_infer::infer::{self, InferOk, TyCtxtInferExt}; use rustc_middle::middle::stability; +use rustc_middle::ty::fast_reject::{simplify_type, TreatParams}; use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef}; use rustc_middle::ty::GenericParamDefKind; use rustc_middle::ty::{self, ParamEnvAnd, ToPredicate, Ty, TyCtxt, TypeFoldable}; @@ -427,13 +428,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .unwrap_or_else(|_| span_bug!(span, "instantiating {:?} failed?", ty)); let ty = self.structurally_resolved_type(span, ty.value); assert!(matches!(ty.kind(), ty::Error(_))); - return Err(MethodError::NoMatch(NoMatchData::new( - Vec::new(), - Vec::new(), - Vec::new(), - None, + return Err(MethodError::NoMatch(NoMatchData { + static_candidates: Vec::new(), + unsatisfied_predicates: Vec::new(), + out_of_scope_traits: Vec::new(), + lev_candidate: None, mode, - ))); + })); } } @@ -613,9 +614,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { fn assemble_probe(&mut self, self_ty: &Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>) { debug!("assemble_probe: self_ty={:?}", self_ty); - let lang_items = self.tcx.lang_items(); - - match *self_ty.value.value.kind() { + let raw_self_ty = self_ty.value.value; + match *raw_self_ty.kind() { ty::Dynamic(data, ..) if let Some(p) = data.principal() => { // Subtle: we can't use `instantiate_query_response` here: using it will // commit to all of the type equalities assumed by inference going through @@ -650,83 +650,27 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { ty::Param(p) => { self.assemble_inherent_candidates_from_param(p); } - ty::Bool => { - let lang_def_id = lang_items.bool_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); - } - ty::Char => { - let lang_def_id = lang_items.char_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); - } - ty::Str => { - let lang_def_id = lang_items.str_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); - - let lang_def_id = lang_items.str_alloc_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); - } - ty::Slice(_) => { - for lang_def_id in [ - lang_items.slice_impl(), - lang_items.slice_u8_impl(), - lang_items.slice_alloc_impl(), - lang_items.slice_u8_alloc_impl(), - ] { - self.assemble_inherent_impl_for_primitive(lang_def_id); - } - } - ty::Array(_, _) => { - let lang_def_id = lang_items.array_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); - } - ty::RawPtr(ty::TypeAndMut { ty: _, mutbl }) => { - let (lang_def_id1, lang_def_id2) = match mutbl { - hir::Mutability::Not => { - (lang_items.const_ptr_impl(), lang_items.const_slice_ptr_impl()) - } - hir::Mutability::Mut => { - (lang_items.mut_ptr_impl(), lang_items.mut_slice_ptr_impl()) - } - }; - self.assemble_inherent_impl_for_primitive(lang_def_id1); - self.assemble_inherent_impl_for_primitive(lang_def_id2); - } - ty::Int(i) => { - let lang_def_id = match i { - ty::IntTy::I8 => lang_items.i8_impl(), - ty::IntTy::I16 => lang_items.i16_impl(), - ty::IntTy::I32 => lang_items.i32_impl(), - ty::IntTy::I64 => lang_items.i64_impl(), - ty::IntTy::I128 => lang_items.i128_impl(), - ty::IntTy::Isize => lang_items.isize_impl(), - }; - self.assemble_inherent_impl_for_primitive(lang_def_id); - } - ty::Uint(i) => { - let lang_def_id = match i { - ty::UintTy::U8 => lang_items.u8_impl(), - ty::UintTy::U16 => lang_items.u16_impl(), - ty::UintTy::U32 => lang_items.u32_impl(), - ty::UintTy::U64 => lang_items.u64_impl(), - ty::UintTy::U128 => lang_items.u128_impl(), - ty::UintTy::Usize => lang_items.usize_impl(), - }; - self.assemble_inherent_impl_for_primitive(lang_def_id); - } - ty::Float(f) => { - let (lang_def_id1, lang_def_id2) = match f { - ty::FloatTy::F32 => (lang_items.f32_impl(), lang_items.f32_runtime_impl()), - ty::FloatTy::F64 => (lang_items.f64_impl(), lang_items.f64_runtime_impl()), - }; - self.assemble_inherent_impl_for_primitive(lang_def_id1); - self.assemble_inherent_impl_for_primitive(lang_def_id2); - } + ty::Bool + | ty::Char + | ty::Int(_) + | ty::Uint(_) + | ty::Float(_) + | ty::Str + | ty::Array(..) + | ty::Slice(_) + | ty::RawPtr(_) + | ty::Ref(..) + | ty::Never + | ty::Tuple(..) => self.assemble_inherent_candidates_for_incoherent_ty(raw_self_ty), _ => {} } } - fn assemble_inherent_impl_for_primitive(&mut self, lang_def_id: Option) { - if let Some(impl_def_id) = lang_def_id { + fn assemble_inherent_candidates_for_incoherent_ty(&mut self, self_ty: Ty<'tcx>) { + let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::AsPlaceholders) else { + bug!("unexpected incoherent type: {:?}", self_ty) + }; + for &impl_def_id in self.tcx.incoherent_impls(simp) { self.assemble_inherent_impl_probe(impl_def_id); } } @@ -765,7 +709,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { // fcx's fulfillment context after this probe is over. // Note: we only normalize `xform_self_ty` here since the normalization // of the return type can lead to inference results that prohibit - // valid canidates from being found, see issue #85671 + // valid candidates from being found, see issue #85671 // FIXME Postponing the normalization of the return type likely only hides a deeper bug, // which might be caused by the `param_env` itself. The clauses of the `param_env` // maybe shouldn't include `Param`s, but rather fresh variables or be canonicalized, @@ -1093,13 +1037,13 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } let lev_candidate = self.probe_for_lev_candidate()?; - Err(MethodError::NoMatch(NoMatchData::new( + Err(MethodError::NoMatch(NoMatchData { static_candidates, unsatisfied_predicates, out_of_scope_traits, lev_candidate, - self.mode, - ))) + mode: self.mode, + })) } fn pick_core(&mut self) -> Option> { diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index 9c3f2da56442f..e1d6b5d2bd425 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -281,25 +281,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // There are methods that are defined on the primitive types and won't be // found when exploring `all_traits`, but we also need them to be acurate on // our suggestions (#47759). - let fund_assoc = |opt_def_id: Option| { - opt_def_id.and_then(|id| self.associated_value(id, item_name)).is_some() + let found_assoc = |ty: Ty<'tcx>| { + simplify_type(tcx, ty, TreatParams::AsPlaceholders) + .and_then(|simp| { + tcx.incoherent_impls(simp) + .iter() + .find_map(|&id| self.associated_value(id, item_name)) + }) + .is_some() }; - let lang_items = tcx.lang_items(); let found_candidate = candidates.next().is_some() - || fund_assoc(lang_items.i8_impl()) - || fund_assoc(lang_items.i16_impl()) - || fund_assoc(lang_items.i32_impl()) - || fund_assoc(lang_items.i64_impl()) - || fund_assoc(lang_items.i128_impl()) - || fund_assoc(lang_items.u8_impl()) - || fund_assoc(lang_items.u16_impl()) - || fund_assoc(lang_items.u32_impl()) - || fund_assoc(lang_items.u64_impl()) - || fund_assoc(lang_items.u128_impl()) - || fund_assoc(lang_items.f32_impl()) - || fund_assoc(lang_items.f32_runtime_impl()) - || fund_assoc(lang_items.f64_impl()) - || fund_assoc(lang_items.f64_runtime_impl()); + || found_assoc(tcx.types.i8) + || found_assoc(tcx.types.i16) + || found_assoc(tcx.types.i32) + || found_assoc(tcx.types.i64) + || found_assoc(tcx.types.i128) + || found_assoc(tcx.types.u8) + || found_assoc(tcx.types.u16) + || found_assoc(tcx.types.u32) + || found_assoc(tcx.types.u64) + || found_assoc(tcx.types.u128) + || found_assoc(tcx.types.f32) + || found_assoc(tcx.types.f32); if let (true, false, SelfSource::MethodCall(expr), true) = ( actual.is_numeric(), actual.has_concrete_skeleton(), diff --git a/compiler/rustc_typeck/src/coherence/inherent_impls.rs b/compiler/rustc_typeck/src/coherence/inherent_impls.rs index 303ec910a9f09..e11bd9355ebf9 100644 --- a/compiler/rustc_typeck/src/coherence/inherent_impls.rs +++ b/compiler/rustc_typeck/src/coherence/inherent_impls.rs @@ -7,12 +7,13 @@ //! `tcx.inherent_impls(def_id)`). That value, however, //! is computed by selecting an idea from this table. -use rustc_errors::{pluralize, struct_span_err}; +use rustc_errors::struct_span_err; use rustc_hir as hir; -use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::def_id::{CrateNum, DefId, LocalDefId}; use rustc_hir::itemlikevisit::ItemLikeVisitor; -use rustc_middle::ty::{self, CrateInherentImpls, TyCtxt}; - +use rustc_middle::ty::fast_reject::{simplify_type, SimplifiedType, TreatParams}; +use rustc_middle::ty::{self, CrateInherentImpls, Ty, TyCtxt}; +use rustc_span::symbol::sym; use rustc_span::Span; /// On-demand query: yields a map containing all types mapped to their inherent impls. @@ -22,6 +23,13 @@ pub fn crate_inherent_impls(tcx: TyCtxt<'_>, (): ()) -> CrateInherentImpls { collect.impls_map } +pub fn crate_incoherent_impls(tcx: TyCtxt<'_>, (_, simp): (CrateNum, SimplifiedType)) -> &[DefId] { + let crate_map = tcx.crate_inherent_impls(()); + tcx.arena.alloc_from_iter( + crate_map.incoherent_impls.get(&simp).unwrap_or(&Vec::new()).iter().map(|d| d.to_def_id()), + ) +} + /// On-demand query: yields a vector of the inherent impls for a specific type. pub fn inherent_impls(tcx: TyCtxt<'_>, ty_def_id: DefId) -> &[DefId] { let ty_def_id = ty_def_id.expect_local(); @@ -40,12 +48,11 @@ struct InherentCollect<'tcx> { impl<'tcx> ItemLikeVisitor<'_> for InherentCollect<'tcx> { fn visit_item(&mut self, item: &hir::Item<'_>) { - let hir::ItemKind::Impl(hir::Impl { of_trait: None, self_ty: ty, items: assoc_items, .. }) = item.kind else { + let hir::ItemKind::Impl(hir::Impl { of_trait: None, self_ty: ty, ref items, .. }) = item.kind else { return; }; let self_ty = self.tcx.type_of(item.def_id); - let lang_items = self.tcx.lang_items(); match *self_ty.kind() { ty::Adt(def, _) => { self.check_def_id(item, def.did()); @@ -67,276 +74,19 @@ impl<'tcx> ItemLikeVisitor<'_> for InherentCollect<'tcx> { .note("define and implement a new trait or type instead") .emit(); } - ty::Bool => { - self.check_primitive_impl( - item.def_id, - lang_items.bool_impl(), - None, - "bool", - "bool", - item.span, - assoc_items, - ); - } - ty::Char => { - self.check_primitive_impl( - item.def_id, - lang_items.char_impl(), - None, - "char", - "char", - item.span, - assoc_items, - ); - } - ty::Str => { - self.check_primitive_impl( - item.def_id, - lang_items.str_impl(), - lang_items.str_alloc_impl(), - "str", - "str", - item.span, - assoc_items, - ); - } - ty::Slice(slice_item) if slice_item == self.tcx.types.u8 => { - self.check_primitive_impl( - item.def_id, - lang_items.slice_u8_impl(), - lang_items.slice_u8_alloc_impl(), - "slice_u8", - "[u8]", - item.span, - assoc_items, - ); - } - ty::Slice(_) => { - self.check_primitive_impl( - item.def_id, - lang_items.slice_impl(), - lang_items.slice_alloc_impl(), - "slice", - "[T]", - item.span, - assoc_items, - ); - } - ty::Array(_, _) => { - self.check_primitive_impl( - item.def_id, - lang_items.array_impl(), - None, - "array", - "[T; N]", - item.span, - assoc_items, - ); - } - ty::RawPtr(ty::TypeAndMut { ty: inner, mutbl: hir::Mutability::Not }) - if matches!(inner.kind(), ty::Slice(_)) => - { - self.check_primitive_impl( - item.def_id, - lang_items.const_slice_ptr_impl(), - None, - "const_slice_ptr", - "*const [T]", - item.span, - assoc_items, - ); - } - ty::RawPtr(ty::TypeAndMut { ty: inner, mutbl: hir::Mutability::Mut }) - if matches!(inner.kind(), ty::Slice(_)) => - { - self.check_primitive_impl( - item.def_id, - lang_items.mut_slice_ptr_impl(), - None, - "mut_slice_ptr", - "*mut [T]", - item.span, - assoc_items, - ); - } - ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::Mutability::Not }) => { - self.check_primitive_impl( - item.def_id, - lang_items.const_ptr_impl(), - None, - "const_ptr", - "*const T", - item.span, - assoc_items, - ); - } - ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::Mutability::Mut }) => { - self.check_primitive_impl( - item.def_id, - lang_items.mut_ptr_impl(), - None, - "mut_ptr", - "*mut T", - item.span, - assoc_items, - ); - } - ty::Int(ty::IntTy::I8) => { - self.check_primitive_impl( - item.def_id, - lang_items.i8_impl(), - None, - "i8", - "i8", - item.span, - assoc_items, - ); - } - ty::Int(ty::IntTy::I16) => { - self.check_primitive_impl( - item.def_id, - lang_items.i16_impl(), - None, - "i16", - "i16", - item.span, - assoc_items, - ); - } - ty::Int(ty::IntTy::I32) => { - self.check_primitive_impl( - item.def_id, - lang_items.i32_impl(), - None, - "i32", - "i32", - item.span, - assoc_items, - ); - } - ty::Int(ty::IntTy::I64) => { - self.check_primitive_impl( - item.def_id, - lang_items.i64_impl(), - None, - "i64", - "i64", - item.span, - assoc_items, - ); - } - ty::Int(ty::IntTy::I128) => { - self.check_primitive_impl( - item.def_id, - lang_items.i128_impl(), - None, - "i128", - "i128", - item.span, - assoc_items, - ); - } - ty::Int(ty::IntTy::Isize) => { - self.check_primitive_impl( - item.def_id, - lang_items.isize_impl(), - None, - "isize", - "isize", - item.span, - assoc_items, - ); - } - ty::Uint(ty::UintTy::U8) => { - self.check_primitive_impl( - item.def_id, - lang_items.u8_impl(), - None, - "u8", - "u8", - item.span, - assoc_items, - ); - } - ty::Uint(ty::UintTy::U16) => { - self.check_primitive_impl( - item.def_id, - lang_items.u16_impl(), - None, - "u16", - "u16", - item.span, - assoc_items, - ); - } - ty::Uint(ty::UintTy::U32) => { - self.check_primitive_impl( - item.def_id, - lang_items.u32_impl(), - None, - "u32", - "u32", - item.span, - assoc_items, - ); - } - ty::Uint(ty::UintTy::U64) => { - self.check_primitive_impl( - item.def_id, - lang_items.u64_impl(), - None, - "u64", - "u64", - item.span, - assoc_items, - ); - } - ty::Uint(ty::UintTy::U128) => { - self.check_primitive_impl( - item.def_id, - lang_items.u128_impl(), - None, - "u128", - "u128", - item.span, - assoc_items, - ); - } - ty::Uint(ty::UintTy::Usize) => { - self.check_primitive_impl( - item.def_id, - lang_items.usize_impl(), - None, - "usize", - "usize", - item.span, - assoc_items, - ); - } - ty::Float(ty::FloatTy::F32) => { - self.check_primitive_impl( - item.def_id, - lang_items.f32_impl(), - lang_items.f32_runtime_impl(), - "f32", - "f32", - item.span, - assoc_items, - ); - } - ty::Float(ty::FloatTy::F64) => { - self.check_primitive_impl( - item.def_id, - lang_items.f64_impl(), - lang_items.f64_runtime_impl(), - "f64", - "f64", - item.span, - assoc_items, - ); - } - ty::Error(_) => {} - _ => { + ty::Bool + | ty::Char + | ty::Int(_) + | ty::Uint(_) + | ty::Float(_) + | ty::Str + | ty::Array(..) + | ty::Slice(_) + | ty::RawPtr(_) + | ty::Ref(..) + | ty::Never + | ty::Tuple(..) => self.check_primitive_impl(item.def_id, self_ty, items, ty.span), + ty::FnPtr(_) | ty::Projection(..) | ty::Opaque(..) | ty::Param(_) => { let mut err = struct_span_err!( self.tcx.sess, ty.span, @@ -347,16 +97,18 @@ impl<'tcx> ItemLikeVisitor<'_> for InherentCollect<'tcx> { err.span_label(ty.span, "impl requires a nominal type") .note("either implement a trait on it or create a newtype to wrap it instead"); - if let ty::Ref(_, subty, _) = self_ty.kind() { - err.note(&format!( - "you could also try moving the reference to \ - uses of `{}` (such as `self`) within the implementation", - subty - )); - } - err.emit(); } + ty::FnDef(..) + | ty::Closure(..) + | ty::Generator(..) + | ty::GeneratorWitness(..) + | ty::Bound(..) + | ty::Placeholder(_) + | ty::Infer(_) => { + bug!("unexpected impl self type of impl: {:?} {:?}", item.def_id, self_ty); + } + ty::Error(_) => {} } } @@ -390,60 +142,58 @@ impl<'tcx> InherentCollect<'tcx> { } fn check_primitive_impl( - &self, + &mut self, impl_def_id: LocalDefId, - lang_def_id: Option, - lang_def_id2: Option, - lang: &str, - ty: &str, + ty: Ty<'tcx>, + items: &[hir::ImplItemRef], span: Span, - assoc_items: &[hir::ImplItemRef], ) { - match (lang_def_id, lang_def_id2) { - (Some(lang_def_id), _) if lang_def_id == impl_def_id.to_def_id() => { - // OK - } - (_, Some(lang_def_id)) if lang_def_id == impl_def_id.to_def_id() => { - // OK - } - _ => { - let to_implement = if assoc_items.is_empty() { - String::new() - } else { - let assoc_items_kind = { - let item_types = assoc_items.iter().map(|x| x.kind); - if item_types.clone().all(|x| x == hir::AssocItemKind::Const) { - "constant" - } else if item_types - .clone() - .all(|x| matches! {x, hir::AssocItemKind::Fn{ .. } }) - { - "method" - } else { - "associated item" - } - }; - - format!( - " to implement {} {}{}", - pluralize!("this", assoc_items.len()), - assoc_items_kind, - pluralize!(assoc_items.len()), - ) - }; - - struct_span_err!( + const INTO_CORE: &str = "consider moving this inherent impl into `core` if possible"; + const ADD_ATTR: &str = + "alternatively add `#[rustc_allow_incoherent_impl]` to the relevant impl items"; + if !self.tcx.hir().rustc_coherence_is_core() { + if self.tcx.features().rustc_attrs { + for item in items { + if !self + .tcx + .has_attr(item.id.def_id.to_def_id(), sym::rustc_allow_incoherent_impl) + { + struct_span_err!( + self.tcx.sess, + span, + E0390, + "cannot define inherent `impl` for primitive types outside of `core`", + ) + .help(INTO_CORE) + .span_help(item.span, ADD_ATTR) + .emit(); + return; + } + } + } else { + let mut err = struct_span_err!( self.tcx.sess, span, E0390, - "only a single inherent implementation marked with `#[lang = \ - \"{}\"]` is allowed for the `{}` primitive", - lang, - ty - ) - .help(&format!("consider using a trait{}", to_implement)) - .emit(); + "cannot define inherent `impl` for primitive types", + ); + err.help("consider using an extension trait instead"); + if let ty::Ref(_, subty, _) = ty.kind() { + err.note(&format!( + "you could also try moving the reference to \ + uses of `{}` (such as `self`) within the implementation", + subty + )); + } + err.emit(); + return; } } + + if let Some(simp) = simplify_type(self.tcx, ty, TreatParams::AsPlaceholders) { + self.impls_map.incoherent_impls.entry(simp).or_default().push(impl_def_id); + } else { + bug!("unexpected primitive type: {:?}", ty); + } } } diff --git a/compiler/rustc_typeck/src/coherence/mod.rs b/compiler/rustc_typeck/src/coherence/mod.rs index 055818f55f0c8..3f1b4828d1af3 100644 --- a/compiler/rustc_typeck/src/coherence/mod.rs +++ b/compiler/rustc_typeck/src/coherence/mod.rs @@ -144,13 +144,14 @@ fn enforce_empty_impls_for_marker_traits( pub fn provide(providers: &mut Providers) { use self::builtin::coerce_unsized_info; - use self::inherent_impls::{crate_inherent_impls, inherent_impls}; + use self::inherent_impls::{crate_incoherent_impls, crate_inherent_impls, inherent_impls}; use self::inherent_impls_overlap::crate_inherent_impls_overlap_check; use self::orphan::orphan_check_crate; *providers = Providers { coherent_trait, crate_inherent_impls, + crate_incoherent_impls, inherent_impls, crate_inherent_impls_overlap_check, coerce_unsized_info, diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs index 31365562ddb50..89d85146963cf 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] { /// Sorts the slice. @@ -267,6 +267,7 @@ impl [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] { /// 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(&mut self, mut compare: F) @@ -363,6 +365,7 @@ impl [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(&mut self, mut f: F) @@ -409,6 +412,7 @@ impl [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(&mut self, f: F) @@ -467,6 +471,7 @@ impl [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] { /// // 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(&self, alloc: A) -> Vec @@ -515,6 +521,7 @@ impl [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(self: Box) -> Vec { @@ -542,6 +549,7 @@ impl [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 @@ -610,6 +618,7 @@ impl [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(&self) -> >::Output where @@ -628,6 +637,7 @@ impl [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(&self, sep: Separator) -> >::Output where @@ -646,6 +656,7 @@ impl [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(&self, sep: Separator) -> >::Output @@ -656,7 +667,7 @@ impl [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 69495f31c32ca..a3c17612c3a0b 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` 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) -> 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] diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 20dfbc6347c4f..9e42ab5923aa0 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -395,7 +395,7 @@ macro_rules! array_impl_default { 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} -#[lang = "array"] +#[cfg_attr(bootstrap, lang = "array")] impl [T; N] { /// Returns an array of the same size as `self`, with function `f` applied to each element /// in order. diff --git a/library/core/src/bool.rs b/library/core/src/bool.rs index a13593a539d94..06aee3ccbaf9c 100644 --- a/library/core/src/bool.rs +++ b/library/core/src/bool.rs @@ -2,7 +2,7 @@ use crate::marker::Destruct; -#[lang = "bool"] +#[cfg_attr(bootstrap, lang = "bool")] impl bool { /// Returns `Some(t)` if the `bool` is [`true`](../std/keyword.true.html), /// or `None` otherwise. diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index f75cd74ee2de6..7deb3358c95d5 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -7,7 +7,7 @@ use crate::unicode::{self, conversions}; use super::*; -#[lang = "char"] +#[cfg_attr(bootstrap, lang = "char")] impl char { /// The highest valid code point a `char` can have, `'\u{10FFFF}'`. /// diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 5c16346cbd1d9..445a7ba6e2d66 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -84,6 +84,7 @@ target_has_atomic_load_store = "ptr", ))] #![no_core] +#![cfg_attr(not(bootstrap), rustc_coherence_is_core)] // // Lints: #![deny(rust_2021_incompatible_or_patterns)] diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index d8dcfdafa8df9..17ca854768546 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -370,7 +370,7 @@ pub mod consts { pub const LN_10: f32 = 2.30258509299404568401799145468436421_f32; } -#[lang = "f32"] +#[cfg_attr(bootstrap, lang = "f32")] #[cfg(not(test))] impl f32 { /// The radix or base of the internal representation of `f32`. diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index 7c2f51ff64639..350d8529de57a 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -370,7 +370,7 @@ pub mod consts { pub const LN_10: f64 = 2.30258509299404568401799145468436421_f64; } -#[lang = "f64"] +#[cfg_attr(bootstrap, lang = "f64")] #[cfg(not(test))] impl f64 { /// The radix or base of the internal representation of `f64`. diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index c09f642d9696c..f4f1d274d105b 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -193,26 +193,26 @@ macro_rules! widening_impl { }; } -#[lang = "i8"] +#[cfg_attr(bootstrap, lang = "i8")] impl i8 { int_impl! { i8, i8, u8, 8, 7, -128, 127, 2, "-0x7e", "0xa", "0x12", "0x12", "0x48", "[0x12]", "[0x12]", "", "" } } -#[lang = "i16"] +#[cfg_attr(bootstrap, lang = "i16")] impl i16 { int_impl! { i16, i16, u16, 16, 15, -32768, 32767, 4, "-0x5ffd", "0x3a", "0x1234", "0x3412", "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]", "", "" } } -#[lang = "i32"] +#[cfg_attr(bootstrap, lang = "i32")] impl i32 { int_impl! { i32, i32, u32, 32, 31, -2147483648, 2147483647, 8, "0x10000b3", "0xb301", "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", "", "" } } -#[lang = "i64"] +#[cfg_attr(bootstrap, lang = "i64")] impl i64 { int_impl! { i64, i64, u64, 64, 63, -9223372036854775808, 9223372036854775807, 12, "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412", @@ -220,7 +220,7 @@ impl i64 { "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", "", "" } } -#[lang = "i128"] +#[cfg_attr(bootstrap, lang = "i128")] impl i128 { int_impl! { i128, i128, u128, 128, 127, -170141183460469231731687303715884105728, 170141183460469231731687303715884105727, 16, @@ -233,7 +233,7 @@ impl i128 { } #[cfg(target_pointer_width = "16")] -#[lang = "isize"] +#[cfg_attr(bootstrap, lang = "isize")] impl isize { int_impl! { isize, i16, usize, 16, 15, -32768, 32767, 4, "-0x5ffd", "0x3a", "0x1234", "0x3412", "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]", @@ -241,7 +241,7 @@ impl isize { } #[cfg(target_pointer_width = "32")] -#[lang = "isize"] +#[cfg_attr(bootstrap, lang = "isize")] impl isize { int_impl! { isize, i32, usize, 32, 31, -2147483648, 2147483647, 8, "0x10000b3", "0xb301", "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", @@ -250,7 +250,7 @@ impl isize { } #[cfg(target_pointer_width = "64")] -#[lang = "isize"] +#[cfg_attr(bootstrap, lang = "isize")] impl isize { int_impl! { isize, i64, usize, 64, 63, -9223372036854775808, 9223372036854775807, 12, "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412", @@ -262,7 +262,7 @@ impl isize { /// If 6th bit set ascii is upper case. const ASCII_CASE_MASK: u8 = 0b0010_0000; -#[lang = "u8"] +#[cfg_attr(bootstrap, lang = "u8")] impl u8 { uint_impl! { u8, u8, i8, NonZeroU8, 8, 255, 2, "0x82", "0xa", "0x12", "0x12", "0x48", "[0x12]", "[0x12]", "", "" } @@ -816,7 +816,7 @@ impl u8 { } } -#[lang = "u16"] +#[cfg_attr(bootstrap, lang = "u16")] impl u16 { uint_impl! { u16, u16, i16, NonZeroU16, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]", "", "" } @@ -848,14 +848,14 @@ impl u16 { } } -#[lang = "u32"] +#[cfg_attr(bootstrap, lang = "u32")] impl u32 { uint_impl! { u32, u32, i32, NonZeroU32, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", "", "" } widening_impl! { u32, u64, 32, unsigned } } -#[lang = "u64"] +#[cfg_attr(bootstrap, lang = "u64")] impl u64 { uint_impl! { u64, u64, i64, NonZeroU64, 64, 18446744073709551615, 12, "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48", @@ -865,7 +865,7 @@ impl u64 { widening_impl! { u64, u128, 64, unsigned } } -#[lang = "u128"] +#[cfg_attr(bootstrap, lang = "u128")] impl u128 { uint_impl! { u128, u128, i128, NonZeroU128, 128, 340282366920938463463374607431768211455, 16, "0x13f40000000000000000000000004f76", "0x4f7613f4", "0x12345678901234567890123456789012", @@ -878,7 +878,7 @@ impl u128 { } #[cfg(target_pointer_width = "16")] -#[lang = "usize"] +#[cfg_attr(bootstrap, lang = "usize")] impl usize { uint_impl! { usize, u16, isize, NonZeroUsize, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]", @@ -886,7 +886,7 @@ impl usize { widening_impl! { usize, u32, 16, unsigned } } #[cfg(target_pointer_width = "32")] -#[lang = "usize"] +#[cfg_attr(bootstrap, lang = "usize")] impl usize { uint_impl! { usize, u32, isize, NonZeroUsize, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", @@ -895,7 +895,7 @@ impl usize { } #[cfg(target_pointer_width = "64")] -#[lang = "usize"] +#[cfg_attr(bootstrap, lang = "usize")] impl usize { uint_impl! { usize, u64, isize, NonZeroUsize, 64, 18446744073709551615, 12, "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48", diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 20ee128026421..209ea5cb0439b 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -4,7 +4,7 @@ use crate::intrinsics; use crate::mem; use crate::slice::{self, SliceIndex}; -#[lang = "const_ptr"] +#[cfg_attr(bootstrap, lang = "const_ptr")] impl *const T { /// Returns `true` if the pointer is null. /// @@ -1042,7 +1042,7 @@ impl *const T { } } -#[lang = "const_slice_ptr"] +#[cfg_attr(bootstrap, lang = "const_slice_ptr")] impl *const [T] { /// Returns the length of a raw slice. /// diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 547208025214a..bfc89625935d9 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -3,7 +3,7 @@ use crate::cmp::Ordering::{self, Equal, Greater, Less}; use crate::intrinsics; use crate::slice::{self, SliceIndex}; -#[lang = "mut_ptr"] +#[cfg_attr(bootstrap, lang = "mut_ptr")] impl *mut T { /// Returns `true` if the pointer is null. /// @@ -1313,7 +1313,7 @@ impl *mut T { } } -#[lang = "mut_slice_ptr"] +#[cfg_attr(bootstrap, lang = "mut_slice_ptr")] impl *mut [T] { /// Returns the length of a raw slice. /// diff --git a/library/core/src/slice/ascii.rs b/library/core/src/slice/ascii.rs index 6c9107401fda6..7c002130040ac 100644 --- a/library/core/src/slice/ascii.rs +++ b/library/core/src/slice/ascii.rs @@ -6,7 +6,7 @@ use crate::iter; use crate::mem; use crate::ops; -#[lang = "slice_u8"] +#[cfg_attr(bootstrap, lang = "slice_u8")] #[cfg(not(test))] impl [u8] { /// Checks if all bytes in this slice are within the ASCII range. diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 26d4fa15d0a7e..77bf5f9dc34e3 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -109,7 +109,7 @@ enum Direction { Back, } -#[lang = "slice"] +#[cfg_attr(bootstrap, lang = "slice")] #[cfg(not(test))] impl [T] { /// Returns the number of elements in the slice. diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index c603420f0f862..6bfa6a5e01519 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -130,7 +130,7 @@ fn slice_error_fail_rt(s: &str, begin: usize, end: usize) -> ! { ); } -#[lang = "str"] +#[cfg_attr(bootstrap, lang = "str")] #[cfg(not(test))] impl str { /// Returns the length of `self`. diff --git a/library/std/src/f32.rs b/library/std/src/f32.rs index d23f5244d88d4..70b5941c7c72b 100644 --- a/library/std/src/f32.rs +++ b/library/std/src/f32.rs @@ -28,7 +28,7 @@ pub use core::f32::{ }; #[cfg(not(test))] -#[lang = "f32_runtime"] +#[cfg_attr(bootstrap, lang = "f32_runtime")] impl f32 { /// Returns the largest integer less than or equal to a number. /// @@ -43,6 +43,7 @@ impl f32 { /// assert_eq!(g.floor(), 3.0); /// assert_eq!(h.floor(), -4.0); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -61,6 +62,7 @@ impl f32 { /// assert_eq!(f.ceil(), 4.0); /// assert_eq!(g.ceil(), 4.0); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -80,6 +82,7 @@ impl f32 { /// assert_eq!(f.round(), 3.0); /// assert_eq!(g.round(), -3.0); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -100,6 +103,7 @@ impl f32 { /// assert_eq!(g.trunc(), 3.0); /// assert_eq!(h.trunc(), -3.0); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -120,6 +124,7 @@ impl f32 { /// assert!(abs_difference_x <= f32::EPSILON); /// assert!(abs_difference_y <= f32::EPSILON); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -144,6 +149,7 @@ impl f32 { /// /// assert!(f32::NAN.abs().is_nan()); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -167,6 +173,7 @@ impl f32 { /// /// assert!(f32::NAN.signum().is_nan()); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -193,6 +200,7 @@ impl f32 { /// /// assert!(f32::NAN.copysign(1.0).is_nan()); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[inline] #[stable(feature = "copysign", since = "1.35.0")] @@ -220,6 +228,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -244,6 +253,7 @@ impl f32 { /// assert_eq!(a.div_euclid(-b), -1.0); // 7.0 >= -4.0 * -1.0 /// assert_eq!((-a).div_euclid(-b), 2.0); // -7.0 >= -4.0 * 2.0 /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[inline] #[stable(feature = "euclidean_division", since = "1.38.0")] @@ -278,6 +288,7 @@ impl f32 { /// // limitation due to round-off error /// assert!((-f32::EPSILON).rem_euclid(3.0) != 0.0); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[inline] #[stable(feature = "euclidean_division", since = "1.38.0")] @@ -298,6 +309,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -315,6 +327,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -339,6 +352,7 @@ impl f32 { /// assert!(negative.sqrt().is_nan()); /// assert!(negative_zero.sqrt() == negative_zero); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -360,6 +374,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -379,6 +394,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -400,6 +416,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -423,6 +440,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -442,6 +460,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -464,6 +483,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -488,6 +508,7 @@ impl f32 { /// assert!(abs_difference_x <= f32::EPSILON); /// assert!(abs_difference_y <= f32::EPSILON); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -517,6 +538,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -538,6 +560,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -556,6 +579,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -574,6 +598,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -591,6 +616,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -612,6 +638,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -633,6 +660,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -653,6 +681,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -686,6 +715,7 @@ impl f32 { /// assert!(abs_difference_1 <= f32::EPSILON); /// assert!(abs_difference_2 <= f32::EPSILON); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -708,6 +738,7 @@ impl f32 { /// assert!(abs_difference_0 <= f32::EPSILON); /// assert!(abs_difference_1 <= f32::EPSILON); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn sin_cos(self) -> (f32, f32) { @@ -728,6 +759,7 @@ impl f32 { /// /// assert!(abs_difference < 1e-10); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -749,6 +781,7 @@ impl f32 { /// /// assert!(abs_difference < 1e-10); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -771,6 +804,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -793,6 +827,7 @@ impl f32 { /// // Same result /// assert!(abs_difference <= f32::EPSILON); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -815,6 +850,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -834,6 +870,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -853,6 +890,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -872,6 +910,7 @@ impl f32 { /// /// assert!(abs_difference <= 1e-5); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] diff --git a/library/std/src/f64.rs b/library/std/src/f64.rs index 55e17b471905d..b90d068ec10d3 100644 --- a/library/std/src/f64.rs +++ b/library/std/src/f64.rs @@ -28,7 +28,7 @@ pub use core::f64::{ }; #[cfg(not(test))] -#[lang = "f64_runtime"] +#[cfg_attr(bootstrap, lang = "f64_runtime")] impl f64 { /// Returns the largest integer less than or equal to a number. /// @@ -43,6 +43,7 @@ impl f64 { /// assert_eq!(g.floor(), 3.0); /// assert_eq!(h.floor(), -4.0); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -61,6 +62,7 @@ impl f64 { /// assert_eq!(f.ceil(), 4.0); /// assert_eq!(g.ceil(), 4.0); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -80,6 +82,7 @@ impl f64 { /// assert_eq!(f.round(), 3.0); /// assert_eq!(g.round(), -3.0); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -100,6 +103,7 @@ impl f64 { /// assert_eq!(g.trunc(), 3.0); /// assert_eq!(h.trunc(), -3.0); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -120,6 +124,7 @@ impl f64 { /// assert!(abs_difference_x < 1e-10); /// assert!(abs_difference_y < 1e-10); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -144,6 +149,7 @@ impl f64 { /// /// assert!(f64::NAN.abs().is_nan()); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -167,6 +173,7 @@ impl f64 { /// /// assert!(f64::NAN.signum().is_nan()); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -193,6 +200,7 @@ impl f64 { /// /// assert!(f64::NAN.copysign(1.0).is_nan()); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "copysign", since = "1.35.0")] #[inline] @@ -220,6 +228,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -244,6 +253,7 @@ impl f64 { /// assert_eq!(a.div_euclid(-b), -1.0); // 7.0 >= -4.0 * -1.0 /// assert_eq!((-a).div_euclid(-b), 2.0); // -7.0 >= -4.0 * 2.0 /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[inline] #[stable(feature = "euclidean_division", since = "1.38.0")] @@ -278,6 +288,7 @@ impl f64 { /// // limitation due to round-off error /// assert!((-f64::EPSILON).rem_euclid(3.0) != 0.0); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[inline] #[stable(feature = "euclidean_division", since = "1.38.0")] @@ -298,6 +309,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -315,6 +327,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -339,6 +352,7 @@ impl f64 { /// assert!(negative.sqrt().is_nan()); /// assert!(negative_zero.sqrt() == negative_zero); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -360,6 +374,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -379,6 +394,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -400,6 +416,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -423,6 +440,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -442,6 +460,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -466,6 +485,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -490,6 +510,7 @@ impl f64 { /// assert!(abs_difference_x < 1e-10); /// assert!(abs_difference_y < 1e-10); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -519,6 +540,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -540,6 +562,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -558,6 +581,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -576,6 +600,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -593,6 +618,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-14); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -614,6 +640,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -635,6 +662,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -655,6 +683,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -688,6 +717,7 @@ impl f64 { /// assert!(abs_difference_1 < 1e-10); /// assert!(abs_difference_2 < 1e-10); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -710,6 +740,7 @@ impl f64 { /// assert!(abs_difference_0 < 1e-10); /// assert!(abs_difference_1 < 1e-10); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn sin_cos(self) -> (f64, f64) { @@ -730,6 +761,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-20); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -751,6 +783,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-20); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -773,6 +806,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -795,6 +829,7 @@ impl f64 { /// // Same result /// assert!(abs_difference < 1.0e-10); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -817,6 +852,7 @@ impl f64 { /// /// assert!(abs_difference < 1.0e-10); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -836,6 +872,7 @@ impl f64 { /// /// assert!(abs_difference < 1.0e-10); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -855,6 +892,7 @@ impl f64 { /// /// assert!(abs_difference < 1.0e-10); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -874,6 +912,7 @@ impl f64 { /// /// assert!(abs_difference < 1.0e-10); /// ``` + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -884,6 +923,7 @@ impl f64 { // Solaris/Illumos requires a wrapper around log, log2, and log10 functions // because of their non-standard behavior (e.g., log(-n) returns -Inf instead // of expected NaN). + #[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)] fn log_wrapper f64>(self, log_fn: F) -> f64 { if !cfg!(any(target_os = "solaris", target_os = "illumos")) { log_fn(self) diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 957faec30e1fc..3e60ed2f7c4e5 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1,6 +1,7 @@ use std::cell::RefCell; use std::default::Default; use std::hash::Hash; +use std::iter; use std::lazy::SyncOnceCell as OnceCell; use std::path::PathBuf; use std::rc::Rc; @@ -22,6 +23,7 @@ use rustc_hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE} use rustc_hir::lang_items::LangItem; use rustc_hir::{BodyId, Mutability}; use rustc_index::vec::IndexVec; +use rustc_middle::ty::fast_reject::SimplifiedType; use rustc_middle::ty::{self, TyCtxt}; use rustc_session::Session; use rustc_span::hygiene::MacroKind; @@ -1625,6 +1627,7 @@ crate enum PrimitiveType { Never, } +type SimplifiedTypes = FxHashMap>; impl PrimitiveType { crate fn from_hir(prim: hir::PrimTy) -> PrimitiveType { use ast::{FloatTy, IntTy, UintTy}; @@ -1680,68 +1683,68 @@ impl PrimitiveType { } } - crate fn impls(&self, tcx: TyCtxt<'_>) -> &'static ArrayVec { - Self::all_impls(tcx).get(self).expect("missing impl for primitive type") - } - - crate fn all_impls(tcx: TyCtxt<'_>) -> &'static FxHashMap> { - static CELL: OnceCell>> = OnceCell::new(); + crate fn simplified_types() -> &'static SimplifiedTypes { + use ty::fast_reject::SimplifiedTypeGen::*; + use ty::{FloatTy, IntTy, UintTy}; + use PrimitiveType::*; + static CELL: OnceCell = OnceCell::new(); + let single = |x| iter::once(x).collect(); CELL.get_or_init(move || { - use self::PrimitiveType::*; - - let single = |a: Option| a.into_iter().collect(); - let both = |a: Option, b: Option| -> ArrayVec<_, 4> { - a.into_iter().chain(b).collect() - }; - - let lang_items = tcx.lang_items(); map! { - Isize => single(lang_items.isize_impl()), - I8 => single(lang_items.i8_impl()), - I16 => single(lang_items.i16_impl()), - I32 => single(lang_items.i32_impl()), - I64 => single(lang_items.i64_impl()), - I128 => single(lang_items.i128_impl()), - Usize => single(lang_items.usize_impl()), - U8 => single(lang_items.u8_impl()), - U16 => single(lang_items.u16_impl()), - U32 => single(lang_items.u32_impl()), - U64 => single(lang_items.u64_impl()), - U128 => single(lang_items.u128_impl()), - F32 => both(lang_items.f32_impl(), lang_items.f32_runtime_impl()), - F64 => both(lang_items.f64_impl(), lang_items.f64_runtime_impl()), - Char => single(lang_items.char_impl()), - Bool => single(lang_items.bool_impl()), - Str => both(lang_items.str_impl(), lang_items.str_alloc_impl()), - Slice => { - lang_items - .slice_impl() - .into_iter() - .chain(lang_items.slice_u8_impl()) - .chain(lang_items.slice_alloc_impl()) - .chain(lang_items.slice_u8_alloc_impl()) - .collect() - }, - Array => single(lang_items.array_impl()), - Tuple => ArrayVec::new(), - Unit => ArrayVec::new(), - RawPointer => { - lang_items - .const_ptr_impl() - .into_iter() - .chain(lang_items.mut_ptr_impl()) - .chain(lang_items.const_slice_ptr_impl()) - .chain(lang_items.mut_slice_ptr_impl()) - .collect() - }, - Reference => ArrayVec::new(), + Isize => single(IntSimplifiedType(IntTy::Isize)), + I8 => single(IntSimplifiedType(IntTy::I8)), + I16 => single(IntSimplifiedType(IntTy::I16)), + I32 => single(IntSimplifiedType(IntTy::I32)), + I64 => single(IntSimplifiedType(IntTy::I64)), + I128 => single(IntSimplifiedType(IntTy::I128)), + Usize => single(UintSimplifiedType(UintTy::Usize)), + U8 => single(UintSimplifiedType(UintTy::U8)), + U16 => single(UintSimplifiedType(UintTy::U16)), + U32 => single(UintSimplifiedType(UintTy::U32)), + U64 => single(UintSimplifiedType(UintTy::U64)), + U128 => single(UintSimplifiedType(UintTy::U128)), + F32 => single(FloatSimplifiedType(FloatTy::F32)), + F64 => single(FloatSimplifiedType(FloatTy::F64)), + Str => single(StrSimplifiedType), + Bool => single(BoolSimplifiedType), + Char => single(CharSimplifiedType), + Array => single(ArraySimplifiedType), + Slice => single(SliceSimplifiedType), + // FIXME: If we ever add an inherent impl for tuples + // with different lengths, they won't show in rustdoc. + // + // Either manually update this arrayvec at this point + // or start with a more complex refactoring. + Tuple => [TupleSimplifiedType(2), TupleSimplifiedType(3)].into(), + Unit => single(TupleSimplifiedType(0)), + RawPointer => [PtrSimplifiedType(Mutability::Not), PtrSimplifiedType(Mutability::Mut)].into(), + Reference => [RefSimplifiedType(Mutability::Not), RefSimplifiedType(Mutability::Mut)].into(), + // FIXME: This will be wrong if we ever add inherent impls + // for function pointers. Fn => ArrayVec::new(), - Never => ArrayVec::new(), + Never => single(NeverSimplifiedType), } }) } + crate fn impls<'tcx>(&self, tcx: TyCtxt<'tcx>) -> impl Iterator + 'tcx { + Self::simplified_types() + .get(self) + .into_iter() + .flatten() + .flat_map(move |&simp| tcx.incoherent_impls(simp)) + .copied() + } + + crate fn all_impls(tcx: TyCtxt<'_>) -> impl Iterator + '_ { + Self::simplified_types() + .values() + .flatten() + .flat_map(move |&simp| tcx.incoherent_impls(simp)) + .copied() + } + crate fn as_sym(&self) -> Symbol { use PrimitiveType::*; match self { diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 656f28bfd28cf..00f512ded0e79 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -184,7 +184,7 @@ crate fn build_deref_target_impls(cx: &mut DocContext<'_>, items: &[Item], ret: if let Some(prim) = target.primitive_type() { let _prof_timer = cx.tcx.sess.prof.generic_activity("build_primitive_inherent_impls"); - for &did in prim.impls(tcx).iter().filter(|did| !did.is_local()) { + for did in prim.impls(tcx).filter(|did| !did.is_local()) { inline::build_impl(cx, None, did, None, ret); } } else if let Type::Path { path } = target { diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 5b14aca064e8a..8d66021fcaa90 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -467,7 +467,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { ) -> Option<(Res, ItemFragment)> { let tcx = self.cx.tcx; - prim_ty.impls(tcx).into_iter().find_map(|&impl_| { + prim_ty.impls(tcx).find_map(|impl_| { tcx.associated_items(impl_) .find_by_name_and_namespace(tcx, Ident::with_dummy_span(item_name), ns, impl_) .map(|item| { diff --git a/src/librustdoc/passes/collect_intra_doc_links/early.rs b/src/librustdoc/passes/collect_intra_doc_links/early.rs index 30636faf98c1f..75e952c5122b8 100644 --- a/src/librustdoc/passes/collect_intra_doc_links/early.rs +++ b/src/librustdoc/passes/collect_intra_doc_links/early.rs @@ -113,7 +113,8 @@ impl IntraLinkCrateLoader<'_, '_> { Vec::from_iter(self.resolver.cstore().trait_impls_in_crate_untracked(cnum)); let all_inherent_impls = Vec::from_iter(self.resolver.cstore().inherent_impls_in_crate_untracked(cnum)); - let all_lang_items = Vec::from_iter(self.resolver.cstore().lang_items_untracked(cnum)); + let all_incoherent_impls = + Vec::from_iter(self.resolver.cstore().incoherent_impls_in_crate_untracked(cnum)); // Querying traits in scope is expensive so we try to prune the impl and traits lists // using privacy, private traits and impls from other crates are never documented in @@ -137,7 +138,7 @@ impl IntraLinkCrateLoader<'_, '_> { self.add_traits_in_parent_scope(impl_def_id); } } - for def_id in all_lang_items { + for def_id in all_incoherent_impls { self.add_traits_in_parent_scope(def_id); } diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs index 53280b3df138b..2852c3b616df1 100644 --- a/src/librustdoc/passes/collect_trait_impls.rs +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -45,7 +45,7 @@ crate fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> Crate // Also try to inline primitive impls from other crates. cx.tcx.sess.prof.generic_activity("build_primitive_trait_impls").run(|| { - for &def_id in PrimitiveType::all_impls(cx.tcx).values().flatten() { + for def_id in PrimitiveType::all_impls(cx.tcx) { if !def_id.is_local() { inline::build_impl(cx, None, def_id, None, &mut new_items); diff --git a/src/test/rustdoc/intra-doc/auxiliary/extern-lang-item-impl-dep.rs b/src/test/rustdoc/intra-doc/auxiliary/extern-builtin-type-impl-dep.rs similarity index 84% rename from src/test/rustdoc/intra-doc/auxiliary/extern-lang-item-impl-dep.rs rename to src/test/rustdoc/intra-doc/auxiliary/extern-builtin-type-impl-dep.rs index 87ae2f096bb1f..d9a08cb41b82d 100644 --- a/src/test/rustdoc/intra-doc/auxiliary/extern-lang-item-impl-dep.rs +++ b/src/test/rustdoc/intra-doc/auxiliary/extern-builtin-type-impl-dep.rs @@ -1,7 +1,6 @@ // no-prefer-dynamic -#![feature(lang_items)] - +#![feature(lang_items, rustc_attrs)] #![crate_type = "rlib"] #![no_std] @@ -15,9 +14,9 @@ impl core::ops::Deref for DerefsToF64 { } mod inner { - #[lang = "f64_runtime"] impl f64 { /// [f64::clone] + #[rustc_allow_incoherent_impl] pub fn method() {} } } diff --git a/src/test/rustdoc/intra-doc/auxiliary/my-core.rs b/src/test/rustdoc/intra-doc/auxiliary/my-core.rs index bb70073fc6986..e22feb03ae6ac 100644 --- a/src/test/rustdoc/intra-doc/auxiliary/my-core.rs +++ b/src/test/rustdoc/intra-doc/auxiliary/my-core.rs @@ -1,12 +1,12 @@ -#![feature(no_core, lang_items, rustdoc_internals)] +#![feature(no_core, lang_items, rustdoc_internals, rustc_attrs)] #![no_core] +#![rustc_coherence_is_core] #![crate_type="rlib"] #[doc(primitive = "char")] /// Some char docs mod char {} -#[lang = "char"] impl char { pub fn len_utf8(self) -> usize { 42 diff --git a/src/test/rustdoc/intra-doc/extern-lang-item-impl.rs b/src/test/rustdoc/intra-doc/extern-builtin-type-impl.rs similarity index 62% rename from src/test/rustdoc/intra-doc/extern-lang-item-impl.rs rename to src/test/rustdoc/intra-doc/extern-builtin-type-impl.rs index f64f886f07641..7bb1ded3f3c2e 100644 --- a/src/test/rustdoc/intra-doc/extern-lang-item-impl.rs +++ b/src/test/rustdoc/intra-doc/extern-builtin-type-impl.rs @@ -2,10 +2,10 @@ // comments. The doc link points to an associated item, so we check that traits in scope for that // link are populated. -// aux-build:extern-lang-item-impl-dep.rs +// aux-build:extern-builtin-type-impl-dep.rs #![no_std] -extern crate extern_lang_item_impl_dep; +extern crate extern_builtin_type_impl_dep; -pub use extern_lang_item_impl_dep::DerefsToF64; +pub use extern_builtin_type_impl_dep::DerefsToF64; diff --git a/src/test/rustdoc/intra-doc/prim-methods-local.rs b/src/test/rustdoc/intra-doc/prim-methods-local.rs index fd0b1b97c6ef2..79d8df045158f 100644 --- a/src/test/rustdoc/intra-doc/prim-methods-local.rs +++ b/src/test/rustdoc/intra-doc/prim-methods-local.rs @@ -1,6 +1,7 @@ #![deny(rustdoc::broken_intra_doc_links)] -#![feature(no_core, lang_items, rustdoc_internals)] +#![feature(no_core, lang_items, rustc_attrs, rustdoc_internals)] #![no_core] +#![rustc_coherence_is_core] #![crate_type = "rlib"] // @has prim_methods_local/index.html @@ -12,7 +13,6 @@ #[doc(primitive = "char")] mod char {} -#[lang = "char"] impl char { pub fn len_utf8(self) -> usize { 42 diff --git a/src/test/rustdoc/intra-doc/prim-self.rs b/src/test/rustdoc/intra-doc/prim-self.rs index 7a65723d77b21..de053d70f0354 100644 --- a/src/test/rustdoc/intra-doc/prim-self.rs +++ b/src/test/rustdoc/intra-doc/prim-self.rs @@ -1,12 +1,12 @@ #![deny(rustdoc::broken_intra_doc_links)] +#![rustc_coherence_is_core] #![allow(incomplete_features)] // inherent_associated_types -#![feature(lang_items)] +#![feature(rustc_attrs)] #![feature(no_core)] #![feature(rustdoc_internals)] #![feature(inherent_associated_types)] #![no_core] -#[lang = "usize"] /// [Self::f] /// [Self::MAX] // @has prim_self/primitive.usize.html diff --git a/src/test/rustdoc/issue-23511.rs b/src/test/rustdoc/issue-23511.rs index 6d421f3c2531a..2d2a7908fb187 100644 --- a/src/test/rustdoc/issue-23511.rs +++ b/src/test/rustdoc/issue-23511.rs @@ -1,13 +1,13 @@ -#![feature(lang_items)] +#![feature(rustc_attrs)] #![feature(rustdoc_internals)] #![no_std] pub mod str { #![doc(primitive = "str")] - #[lang = "str_alloc"] impl str { // @has search-index.js foo + #[rustc_allow_incoherent_impl] pub fn foo(&self) {} } } diff --git a/src/test/ui/error-codes/E0117.rs b/src/test/ui/error-codes/E0117.rs index dbbac514801f7..22b48657385c6 100644 --- a/src/test/ui/error-codes/E0117.rs +++ b/src/test/ui/error-codes/E0117.rs @@ -1,5 +1,4 @@ impl Drop for u32 {} //~ ERROR E0117 //~| ERROR the `Drop` trait may only be implemented for structs, enums, and unions -fn main() { -} +fn main() {} diff --git a/src/test/ui/error-codes/E0118-2.rs b/src/test/ui/error-codes/E0118-2.rs deleted file mode 100644 index fe04190162af4..0000000000000 --- a/src/test/ui/error-codes/E0118-2.rs +++ /dev/null @@ -1,8 +0,0 @@ -struct Foo; - -impl &mut Foo { - //~^ ERROR E0118 - fn bar(self) {} -} - -fn main() {} diff --git a/src/test/ui/error-codes/E0118-2.stderr b/src/test/ui/error-codes/E0118-2.stderr deleted file mode 100644 index 2a1fe23111687..0000000000000 --- a/src/test/ui/error-codes/E0118-2.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0118]: no nominal type found for inherent implementation - --> $DIR/E0118-2.rs:3:6 - | -LL | impl &mut Foo { - | ^^^^^^^^ impl requires a nominal type - | - = note: either implement a trait on it or create a newtype to wrap it instead - = note: you could also try moving the reference to uses of `Foo` (such as `self`) within the implementation - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0118`. diff --git a/src/test/ui/error-codes/E0118.rs b/src/test/ui/error-codes/E0118.rs index 7bf36210f3a38..aaef8113b8ae2 100644 --- a/src/test/ui/error-codes/E0118.rs +++ b/src/test/ui/error-codes/E0118.rs @@ -1,8 +1,7 @@ -impl (u8, u8) { //~ ERROR E0118 +impl fn(u8) { //~ ERROR E0118 fn get_state(&self) -> String { - String::new() + String::new() } } -fn main() { -} +fn main() {} diff --git a/src/test/ui/error-codes/E0118.stderr b/src/test/ui/error-codes/E0118.stderr index 2693a93213a3b..296fb5d664a22 100644 --- a/src/test/ui/error-codes/E0118.stderr +++ b/src/test/ui/error-codes/E0118.stderr @@ -1,8 +1,8 @@ error[E0118]: no nominal type found for inherent implementation --> $DIR/E0118.rs:1:6 | -LL | impl (u8, u8) { - | ^^^^^^^^ impl requires a nominal type +LL | impl fn(u8) { + | ^^^^^^ impl requires a nominal type | = note: either implement a trait on it or create a newtype to wrap it instead diff --git a/src/test/ui/error-codes/E0120.rs b/src/test/ui/error-codes/E0120.rs index 287a4088183f4..a0a301a06e2ed 100644 --- a/src/test/ui/error-codes/E0120.rs +++ b/src/test/ui/error-codes/E0120.rs @@ -5,5 +5,4 @@ impl Drop for dyn MyTrait { fn drop(&mut self) {} } -fn main() { -} +fn main() {} diff --git a/src/test/ui/error-codes/E0390.stderr b/src/test/ui/error-codes/E0390.stderr index be47e93d19a9b..e635d4ec196a2 100644 --- a/src/test/ui/error-codes/E0390.stderr +++ b/src/test/ui/error-codes/E0390.stderr @@ -1,10 +1,10 @@ -error[E0390]: only a single inherent implementation marked with `#[lang = "mut_ptr"]` is allowed for the `*mut T` primitive - --> $DIR/E0390.rs:5:1 +error[E0390]: cannot define inherent `impl` for primitive types + --> $DIR/E0390.rs:5:6 | LL | impl *mut Foo {} - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^ | - = help: consider using a trait + = help: consider using an extension trait instead error: aborting due to previous error diff --git a/src/test/ui/kinds-of-primitive-impl.rs b/src/test/ui/kinds-of-primitive-impl.rs index b045b050d77a4..6a067a9a36092 100644 --- a/src/test/ui/kinds-of-primitive-impl.rs +++ b/src/test/ui/kinds-of-primitive-impl.rs @@ -1,20 +1,26 @@ impl u8 { -//~^ error: only a single inherent implementation marked with `#[lang = "u8"]` is allowed for the `u8` primitive +//~^ error: cannot define inherent `impl` for primitive types pub const B: u8 = 0; } impl str { -//~^ error: only a single inherent implementation marked with `#[lang = "str"]` is allowed for the `str` primitive +//~^ error: cannot define inherent `impl` for primitive types fn foo() {} fn bar(self) {} } impl char { -//~^ error: only a single inherent implementation marked with `#[lang = "char"]` is allowed for the `char` primitive +//~^ error: cannot define inherent `impl` for primitive types pub const B: u8 = 0; pub const C: u8 = 0; fn foo() {} fn bar(self) {} } +struct MyType; +impl &MyType { +//~^ error: cannot define inherent `impl` for primitive types + pub fn for_ref(self) {} +} + fn main() {} diff --git a/src/test/ui/kinds-of-primitive-impl.stderr b/src/test/ui/kinds-of-primitive-impl.stderr index f1fb295308352..f4dbd1c40e818 100644 --- a/src/test/ui/kinds-of-primitive-impl.stderr +++ b/src/test/ui/kinds-of-primitive-impl.stderr @@ -1,40 +1,36 @@ -error[E0390]: only a single inherent implementation marked with `#[lang = "u8"]` is allowed for the `u8` primitive - --> $DIR/kinds-of-primitive-impl.rs:1:1 +error[E0390]: cannot define inherent `impl` for primitive types + --> $DIR/kinds-of-primitive-impl.rs:1:6 | -LL | / impl u8 { -LL | | -LL | | pub const B: u8 = 0; -LL | | } - | |_^ +LL | impl u8 { + | ^^ | - = help: consider using a trait to implement this constant + = help: consider using an extension trait instead -error[E0390]: only a single inherent implementation marked with `#[lang = "str"]` is allowed for the `str` primitive - --> $DIR/kinds-of-primitive-impl.rs:6:1 +error[E0390]: cannot define inherent `impl` for primitive types + --> $DIR/kinds-of-primitive-impl.rs:6:6 | -LL | / impl str { -LL | | -LL | | fn foo() {} -LL | | fn bar(self) {} -LL | | } - | |_^ +LL | impl str { + | ^^^ | - = help: consider using a trait to implement these methods + = help: consider using an extension trait instead -error[E0390]: only a single inherent implementation marked with `#[lang = "char"]` is allowed for the `char` primitive - --> $DIR/kinds-of-primitive-impl.rs:12:1 - | -LL | / impl char { -LL | | -LL | | pub const B: u8 = 0; -LL | | pub const C: u8 = 0; -LL | | fn foo() {} -LL | | fn bar(self) {} -LL | | } - | |_^ - | - = help: consider using a trait to implement these associated items +error[E0390]: cannot define inherent `impl` for primitive types + --> $DIR/kinds-of-primitive-impl.rs:12:6 + | +LL | impl char { + | ^^^^ + | + = help: consider using an extension trait instead + +error[E0390]: cannot define inherent `impl` for primitive types + --> $DIR/kinds-of-primitive-impl.rs:21:6 + | +LL | impl &MyType { + | ^^^^^^^ + | + = help: consider using an extension trait instead + = note: you could also try moving the reference to uses of `MyType` (such as `self`) within the implementation -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0390`. diff --git a/src/test/ui/lang-items/lang-item-correct-generics.rs b/src/test/ui/lang-items/lang-item-correct-generics.rs deleted file mode 100644 index a3287db74e733..0000000000000 --- a/src/test/ui/lang-items/lang-item-correct-generics.rs +++ /dev/null @@ -1,28 +0,0 @@ -// build-pass - -#![feature(lang_items,no_core)] -#![no_core] -#![crate_type="lib"] - -#[lang = "sized"] -trait MySized {} - -#[lang = "copy"] -trait MyCopy {} - -#[lang = "drop"] -trait MyDrop {} - -struct S; - -impl MyDrop for S {} - -#[lang = "i32"] -impl<'a> i32 { - fn foo() {} -} - -fn bar() { - i32::foo(); - S; -} diff --git a/src/test/ui/single-primitive-inherent-impl.rs b/src/test/ui/single-primitive-inherent-impl.rs deleted file mode 100644 index 75c62feec32d0..0000000000000 --- a/src/test/ui/single-primitive-inherent-impl.rs +++ /dev/null @@ -1,11 +0,0 @@ -#![crate_type = "lib"] -#![feature(lang_items)] -#![no_std] - -// OK -#[lang = "str_alloc"] -impl str {} - -impl str { -//~^ error: only a single inherent implementation marked with `#[lang = "str"]` is allowed for the `str` primitive -} diff --git a/src/test/ui/single-primitive-inherent-impl.stderr b/src/test/ui/single-primitive-inherent-impl.stderr deleted file mode 100644 index 349a12eac05a0..0000000000000 --- a/src/test/ui/single-primitive-inherent-impl.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0390]: only a single inherent implementation marked with `#[lang = "str"]` is allowed for the `str` primitive - --> $DIR/single-primitive-inherent-impl.rs:9:1 - | -LL | / impl str { -LL | | -LL | | } - | |_^ - | - = help: consider using a trait - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0390`. diff --git a/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs b/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs index 6515975fbffdc..ae4158662d464 100644 --- a/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs +++ b/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs @@ -3,7 +3,7 @@ use clippy_utils::{higher, peel_blocks_with_stmt, SpanlessEq}; use if_chain::if_chain; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; -use rustc_hir::{lang_items::LangItem, BinOpKind, Expr, ExprKind, QPath}; +use rustc_hir::{BinOpKind, Expr, ExprKind, QPath}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -82,14 +82,6 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingSub { // Get the variable name let var_name = ares_path.segments[0].ident.name.as_str(); - const INT_TYPES: [LangItem; 5] = [ - LangItem::I8, - LangItem::I16, - LangItem::I32, - LangItem::I64, - LangItem::Isize - ]; - match cond_num_val.kind { ExprKind::Lit(ref cond_lit) => { // Check if the constant is zero @@ -105,8 +97,8 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingSub { if name.ident.as_str() == "MIN"; if let Some(const_id) = cx.typeck_results().type_dependent_def_id(cond_num_val.hir_id); if let Some(impl_id) = cx.tcx.impl_of_method(const_id); - let mut int_ids = INT_TYPES.iter().filter_map(|&ty| cx.tcx.lang_items().require(ty).ok()); - if int_ids.any(|int_id| int_id == impl_id); + if let None = cx.tcx.impl_trait_ref(impl_id); // An inherent impl + if cx.tcx.type_of(impl_id).is_integral(); then { print_lint_and_sugg(cx, var_name, expr) } @@ -118,8 +110,8 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingSub { if name.ident.as_str() == "min_value"; if let Some(func_id) = cx.typeck_results().type_dependent_def_id(func.hir_id); if let Some(impl_id) = cx.tcx.impl_of_method(func_id); - let mut int_ids = INT_TYPES.iter().filter_map(|&ty| cx.tcx.lang_items().require(ty).ok()); - if int_ids.any(|int_id| int_id == impl_id); + if let None = cx.tcx.impl_trait_ref(impl_id); // An inherent impl + if cx.tcx.type_of(impl_id).is_integral(); then { print_lint_and_sugg(cx, var_name, expr) } diff --git a/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs b/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs index 6e64e7f622207..c98cdfbca434e 100644 --- a/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs +++ b/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs @@ -49,10 +49,11 @@ pub fn is_clone_like(cx: &LateContext<'_>, method_name: &str, method_def_id: hir "to_owned" => is_diag_trait_item(cx, method_def_id, sym::ToOwned), "to_path_buf" => is_diag_item_method(cx, method_def_id, sym::Path), "to_vec" => { - cx.tcx - .impl_of_method(method_def_id) - .map(|impl_did| Some(impl_did) == cx.tcx.lang_items().slice_alloc_impl()) - == Some(true) + cx.tcx.impl_of_method(method_def_id) + .filter(|&impl_did| { + cx.tcx.type_of(impl_did).is_slice() && cx.tcx.impl_trait_ref(impl_did).is_none() + }) + .is_some() }, _ => false, } diff --git a/src/tools/clippy/clippy_lints/src/methods/suspicious_splitn.rs b/src/tools/clippy/clippy_lints/src/methods/suspicious_splitn.rs index 1c546a15bf62b..55567d8625e52 100644 --- a/src/tools/clippy/clippy_lints/src/methods/suspicious_splitn.rs +++ b/src/tools/clippy/clippy_lints/src/methods/suspicious_splitn.rs @@ -12,13 +12,13 @@ pub(super) fn check(cx: &LateContext<'_>, method_name: &str, expr: &Expr<'_>, se if count <= 1; if let Some(call_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id); if let Some(impl_id) = cx.tcx.impl_of_method(call_id); - let lang_items = cx.tcx.lang_items(); - if lang_items.slice_impl() == Some(impl_id) || lang_items.str_impl() == Some(impl_id); + if cx.tcx.impl_trait_ref(impl_id).is_none(); + let self_ty = cx.tcx.type_of(impl_id); + if self_ty.is_slice() || self_ty.is_str(); then { // Ignore empty slice and string literals when used with a literal count. if matches!(self_arg.kind, ExprKind::Array([])) || matches!(self_arg.kind, ExprKind::Lit(Spanned { node: LitKind::Str(s, _), .. }) if s.is_empty()) - { return; } @@ -28,7 +28,7 @@ pub(super) fn check(cx: &LateContext<'_>, method_name: &str, expr: &Expr<'_>, se "the resulting iterator will always return `None`") } else { (format!("`{}` called with `1` split", method_name), - if lang_items.slice_impl() == Some(impl_id) { + if self_ty.is_slice() { "the resulting iterator will always return the entire slice followed by `None`" } else { "the resulting iterator will always return the entire string followed by `None`" diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs index ba1997e70e131..9d4313827f7c6 100644 --- a/src/tools/clippy/clippy_lints/src/ptr.rs +++ b/src/tools/clippy/clippy_lints/src/ptr.rs @@ -16,7 +16,7 @@ use rustc_hir::{ }; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::nested_filter; -use rustc_middle::ty::{self, AssocItems, AssocKind, Ty}; +use rustc_middle::ty::{self, Ty}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; use rustc_span::symbol::Symbol; @@ -308,7 +308,6 @@ struct PtrArg<'tcx> { method_renames: &'static [(&'static str, &'static str)], ref_prefix: RefPrefix, deref_ty: DerefTy<'tcx>, - deref_assoc_items: Option<(DefId, &'tcx AssocItems<'tcx>)>, } impl PtrArg<'_> { fn build_msg(&self) -> String { @@ -411,7 +410,7 @@ fn check_fn_args<'cx, 'tcx: 'cx>( if params.get(i).map_or(true, |p| !is_lint_allowed(cx, PTR_ARG, p.hir_id)); then { - let (method_renames, deref_ty, deref_impl_id) = match cx.tcx.get_diagnostic_name(adt.did()) { + let (method_renames, deref_ty) = match cx.tcx.get_diagnostic_name(adt.did()) { Some(sym::Vec) => ( [("clone", ".to_owned()")].as_slice(), DerefTy::Slice( @@ -424,17 +423,14 @@ fn check_fn_args<'cx, 'tcx: 'cx>( }), substs.type_at(0), ), - cx.tcx.lang_items().slice_impl() ), Some(sym::String) => ( [("clone", ".to_owned()"), ("as_str", "")].as_slice(), DerefTy::Str, - cx.tcx.lang_items().str_impl() ), Some(sym::PathBuf) => ( [("clone", ".to_path_buf()"), ("as_path", "")].as_slice(), DerefTy::Path, - None, ), Some(sym::Cow) if mutability == Mutability::Not => { let ty_name = name.args @@ -470,7 +466,6 @@ fn check_fn_args<'cx, 'tcx: 'cx>( mutability, }, deref_ty, - deref_assoc_items: deref_impl_id.map(|id| (id, cx.tcx.associated_items(id))), }); } } @@ -607,14 +602,7 @@ fn check_ptr_arg_usage<'tcx>(cx: &LateContext<'tcx>, body: &'tcx Body<'_>, args: // If the types match check for methods which exist on both types. e.g. `Vec::len` and // `slice::len` ty::Adt(def, _) - if def.did() == args.ty_did - && (i != 0 - || self.cx.tcx.trait_of_item(id).is_some() - || !args.deref_assoc_items.map_or(false, |(id, items)| { - items - .find_by_name_and_kind(self.cx.tcx, name.ident, AssocKind::Fn, id) - .is_some() - })) => + if def.did() == args.ty_did => { set_skip_flag(); }, diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index cd20abd94ed25..62e144398012d 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -77,9 +77,9 @@ use rustc_hir::intravisit::{walk_expr, FnKind, Visitor}; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::LangItem::{OptionNone, ResultErr, ResultOk}; use rustc_hir::{ - def, lang_items, Arm, ArrayLen, BindingAnnotation, Block, BlockCheckMode, Body, Constness, Destination, Expr, + def, Arm, ArrayLen, BindingAnnotation, Block, BlockCheckMode, Body, Constness, Destination, Expr, ExprKind, FnDecl, ForeignItem, HirId, Impl, ImplItem, ImplItemKind, IsAsync, Item, ItemKind, LangItem, Local, - MatchSource, Mutability, Node, Param, Pat, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, Target, + MatchSource, Mutability, Node, Param, Pat, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitRef, TyKind, UnOp, }; use rustc_lint::{LateContext, Level, Lint, LintContext}; @@ -87,6 +87,8 @@ use rustc_middle::hir::place::PlaceBase; use rustc_middle::ty as rustc_ty; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow}; use rustc_middle::ty::binding::BindingMode; +use rustc_middle::ty::{IntTy, UintTy, FloatTy}; +use rustc_middle::ty::fast_reject::SimplifiedTypeGen::*; use rustc_middle::ty::{layout::IntegerExt, BorrowKind, DefIdTree, Ty, TyCtxt, TypeAndMut, TypeFoldable, UpvarCapture}; use rustc_semver::RustcVersion; use rustc_session::Session; @@ -455,14 +457,6 @@ pub fn path_def_id<'tcx>(cx: &LateContext<'_>, maybe_path: &impl MaybePath<'tcx> /// Resolves a def path like `std::vec::Vec`. /// This function is expensive and should be used sparingly. pub fn def_path_res(cx: &LateContext<'_>, path: &[&str]) -> Res { - macro_rules! try_res { - ($e:expr) => { - match $e { - Some(e) => e, - None => return Res::Err, - } - }; - } fn item_child_by_name(tcx: TyCtxt<'_>, def_id: DefId, name: &str) -> Option { match tcx.def_kind(def_id) { DefKind::Mod | DefKind::Enum | DefKind::Trait => tcx @@ -479,11 +473,35 @@ pub fn def_path_res(cx: &LateContext<'_>, path: &[&str]) -> Res { _ => None, } } - fn find_primitive(tcx: TyCtxt<'_>, name: &str) -> Option { - if let Some(&(index, Target::Impl)) = lang_items::ITEM_REFS.get(&Symbol::intern(name)) { - tcx.lang_items().items()[index] - } else { - None + fn find_primitive<'tcx>(tcx: TyCtxt<'tcx>, name: &str) -> impl Iterator + 'tcx { + let single = |ty| tcx.incoherent_impls(ty).iter().copied(); + let empty = || [].iter().copied(); + match name { + "bool" => single(BoolSimplifiedType), + "char" => single(CharSimplifiedType), + "str" => single(StrSimplifiedType), + "array" => single(ArraySimplifiedType), + "slice" => single(SliceSimplifiedType), + // FIXME: rustdoc documents these two using just `pointer`. + // + // Maybe this is something we should do here too. + "const_ptr" => single(PtrSimplifiedType(Mutability::Not)), + "mut_ptr" => single(PtrSimplifiedType(Mutability::Mut)), + "isize" => single(IntSimplifiedType(IntTy::Isize)), + "i8" => single(IntSimplifiedType(IntTy::I8)), + "i16" => single(IntSimplifiedType(IntTy::I16)), + "i32" => single(IntSimplifiedType(IntTy::I32)), + "i64" => single(IntSimplifiedType(IntTy::I64)), + "i128" => single(IntSimplifiedType(IntTy::I128)), + "usize" => single(UintSimplifiedType(UintTy::Usize)), + "u8" => single(UintSimplifiedType(UintTy::U8)), + "u16" => single(UintSimplifiedType(UintTy::U16)), + "u32" => single(UintSimplifiedType(UintTy::U32)), + "u64" => single(UintSimplifiedType(UintTy::U64)), + "u128" => single(UintSimplifiedType(UintTy::U128)), + "f32" => single(FloatSimplifiedType(FloatTy::F32)), + "f64" => single(FloatSimplifiedType(FloatTy::F64)), + _ => empty(), } } fn find_crate(tcx: TyCtxt<'_>, name: &str) -> Option { @@ -502,30 +520,35 @@ pub fn def_path_res(cx: &LateContext<'_>, path: &[&str]) -> Res { _ => return Res::Err, }; let tcx = cx.tcx; - let first = try_res!( - find_primitive(tcx, base) - .or_else(|| find_crate(tcx, base)) - .and_then(|id| item_child_by_name(tcx, id, first)) - ); + let starts = find_primitive(tcx, base) + .chain(find_crate(tcx, base)) + .flat_map(|id| item_child_by_name(tcx, id, first)); - let last = path - .iter() - .copied() - // for each segment, find the child item - .try_fold(first, |res, segment| { - let def_id = res.def_id(); - if let Some(item) = item_child_by_name(tcx, def_id, segment) { - Some(item) - } else if matches!(res, Res::Def(DefKind::Enum | DefKind::Struct, _)) { - // it is not a child item so check inherent impl items - tcx.inherent_impls(def_id) - .iter() - .find_map(|&impl_def_id| item_child_by_name(tcx, impl_def_id, segment)) - } else { - None - } - }); - try_res!(last).expect_non_local() + for first in starts { + let last = path + .iter() + .copied() + // for each segment, find the child item + .try_fold(first, |res, segment| { + let def_id = res.def_id(); + if let Some(item) = item_child_by_name(tcx, def_id, segment) { + Some(item) + } else if matches!(res, Res::Def(DefKind::Enum | DefKind::Struct, _)) { + // it is not a child item so check inherent impl items + tcx.inherent_impls(def_id) + .iter() + .find_map(|&impl_def_id| item_child_by_name(tcx, impl_def_id, segment)) + } else { + None + } + }); + + if let Some(last) = last { + return last; + } + } + + Res::Err } /// Convenience function to get the `DefId` of a trait by path.