From bef6f3e895beede5bfd5ba4bb12898615c156d59 Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 15 Mar 2022 16:30:30 +0100 Subject: [PATCH] rework implementation for inherent impls for builtin types --- compiler/rustc_feature/src/builtin_attrs.rs | 8 + compiler/rustc_metadata/src/rmeta/decoder.rs | 25 +- .../src/rmeta/decoder/cstore_impl.rs | 28 +- compiler/rustc_metadata/src/rmeta/encoder.rs | 38 +- compiler/rustc_metadata/src/rmeta/mod.rs | 7 + compiler/rustc_middle/src/hir/map/mod.rs | 4 + compiler/rustc_middle/src/query/mod.rs | 13 + compiler/rustc_middle/src/ty/impls_ty.rs | 13 + compiler/rustc_middle/src/ty/mod.rs | 3 + compiler/rustc_middle/src/ty/trait_def.rs | 18 + compiler/rustc_passes/src/check_attr.rs | 21 + compiler/rustc_query_impl/src/keys.rs | 20 + compiler/rustc_span/src/symbol.rs | 2 + .../rustc_typeck/src/check/method/probe.rs | 96 +---- .../src/coherence/inherent_impls.rs | 376 +++--------------- compiler/rustc_typeck/src/coherence/mod.rs | 3 +- library/alloc/src/slice.rs | 13 + library/alloc/src/str.rs | 9 + library/core/src/lib.rs | 1 + library/std/src/f32.rs | 39 ++ library/std/src/f64.rs | 40 ++ 21 files changed, 364 insertions(+), 413 deletions(-) diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index e2f0b413ff37..7c53f839a92e 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_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 2e6ce7b7040f..de8c0800ac12 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 introduces 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. @@ -1327,10 +1332,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 +1343,14 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { }) } + 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 +1767,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 +1784,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 5ae965ff7fad..7fac668f0727 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(); @@ -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 }; } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 924e5f921039..a219b9eb2be8 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 a30cc034c4a9..204284ffaa3f 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 ec20e888333d..8afa6e70e418 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 95260e9e9173..6d7e7ef0cb07 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 54a345daec8a..2009364b24e6 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 44c190e459c3..dfc405b1195e 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/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs index 8ebeca50c417..943f610cc0dd 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 4f9e1d3fa3bc..8aa659fa6ac7 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 84de31a194da..f1f83a7299c4 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 5cf362bfa7e9..6dd9b8e44dd4 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1160,10 +1160,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, diff --git a/compiler/rustc_typeck/src/check/method/probe.rs b/compiler/rustc_typeck/src/check/method/probe.rs index ed20e5a48690..5d91b3b46a17 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}; @@ -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); } } diff --git a/compiler/rustc_typeck/src/coherence/inherent_impls.rs b/compiler/rustc_typeck/src/coherence/inherent_impls.rs index 303ec910a9f0..573d072da4b1 100644 --- a/compiler/rustc_typeck/src/coherence/inherent_impls.rs +++ b/compiler/rustc_typeck/src/coherence/inherent_impls.rs @@ -9,10 +9,11 @@ use rustc_errors::{pluralize, 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,274 +74,18 @@ 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::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::Error(_) => {} _ => { let mut err = struct_span_err!( @@ -390,60 +141,41 @@ 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" - } - }; + 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() { + for item in items { + if !self.tcx.has_attr(item.id.def_id.to_def_id(), sym::rustc_allow_incoherent_impl) + { + let mut err = struct_span_err!( + self.tcx.sess, + span, + E0390, + "cannot define inherent `impl` for primitive types", + ); - format!( - " to implement {} {}{}", - pluralize!("this", assoc_items.len()), - assoc_items_kind, - pluralize!(assoc_items.len()), - ) - }; - - 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(); + if self.tcx.features().rustc_attrs { + err.help(INTO_CORE).span_help(item.span, ADD_ATTR); + } else { + err.help("consider using a trait instead"); + } + err.emit(); + return; + } } } + + let Some(simp) = simplify_type(self.tcx, ty, TreatParams::AsPlaceholders) else { + bug!("unexpected primitive type: {:?}", ty); + }; + self.impls_map.incoherent_impls.entry(simp).or_default().push(impl_def_id); + return; } } diff --git a/compiler/rustc_typeck/src/coherence/mod.rs b/compiler/rustc_typeck/src/coherence/mod.rs index 055818f55f0c..3f1b4828d1af 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 f52871c73d9f..111c57e884b5 100644 --- a/library/alloc/src/slice.rs +++ b/library/alloc/src/slice.rs @@ -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 @@ -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 69495f31c32c..bf70363258c9 100644 --- a/library/alloc/src/str.rs +++ b/library/alloc/src/str.rs @@ -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/lib.rs b/library/core/src/lib.rs index 5c16346cbd1d..445a7ba6e2d6 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/std/src/f32.rs b/library/std/src/f32.rs index d23f5244d88d..1faf57e13db8 100644 --- a/library/std/src/f32.rs +++ b/library/std/src/f32.rs @@ -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 55e17b471905..22d58ab84cf7 100644 --- a/library/std/src/f64.rs +++ b/library/std/src/f64.rs @@ -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)