Auto merge of #94963 - lcnr:inherent-impls-std, r=oli-obk,m-ou-se
allow arbitrary inherent impls for builtin types in core Part of https://github.com/rust-lang/compiler-team/issues/487. Slightly adjusted after some talks with `@m-ou-se` about the requirements of `t-libs-api`. This adds a crate attribute `#![rustc_coherence_is_core]` which allows arbitrary impls for builtin types in core. For other library crates impls for builtin types should be avoided if possible. We do have to allow the existing stable impls however. To prevent us from accidentally adding more of these in the future, there is a second attribute `#[rustc_allow_incoherent_impl]` which has to be added to **all impl items**. This only supports impls for builtin types but can easily be extended to additional types in a future PR. This implementation does not check for overlaps in these impls. Perfectly checking that requires us to check the coherence of these incoherent impls in every crate, as two distinct dependencies may add overlapping methods. It should be easy enough to detect if it goes wrong and the attribute is only intended for use inside of std. The first two commits are mostly unrelated cleanups.
This commit is contained in:
commit
3e7514670d
66 changed files with 701 additions and 849 deletions
|
@ -4,7 +4,7 @@ enum, union, or trait object.
|
||||||
Erroneous code example:
|
Erroneous code example:
|
||||||
|
|
||||||
```compile_fail,E0118
|
```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 {
|
fn get_state(&self) -> String {
|
||||||
// ...
|
// ...
|
||||||
}
|
}
|
||||||
|
@ -20,8 +20,8 @@ trait LiveLongAndProsper {
|
||||||
fn get_state(&self) -> String;
|
fn get_state(&self) -> String;
|
||||||
}
|
}
|
||||||
|
|
||||||
// and now you can implement it on (u8, u8)
|
// and now you can implement it on fn(u8)
|
||||||
impl LiveLongAndProsper for (u8, u8) {
|
impl LiveLongAndProsper for fn(u8) {
|
||||||
fn get_state(&self) -> String {
|
fn get_state(&self) -> String {
|
||||||
"He's dead, Jim!".to_owned()
|
"He's dead, Jim!".to_owned()
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ For example, `NewType` is a newtype over `Foo` in `struct NewType(Foo)`.
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
```
|
```
|
||||||
struct TypeWrapper((u8, u8));
|
struct TypeWrapper(fn(u8));
|
||||||
|
|
||||||
impl TypeWrapper {
|
impl TypeWrapper {
|
||||||
fn get_state(&self) -> String {
|
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) {}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
|
@ -8,8 +8,7 @@ struct Foo {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl *mut Foo {}
|
impl *mut Foo {}
|
||||||
// error: only a single inherent implementation marked with
|
// error: cannot define inherent `impl` for primitive types
|
||||||
// `#[lang = "mut_ptr"]` is allowed for the `*mut T` primitive
|
|
||||||
```
|
```
|
||||||
|
|
||||||
This isn't allowed, but using a trait to implement a method or constant
|
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!
|
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) {}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
|
@ -636,6 +636,14 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
||||||
template!(Word), ErrorFollowing,
|
template!(Word), ErrorFollowing,
|
||||||
"#[rustc_pass_by_value] is used to mark types that must be passed by value instead of reference."
|
"#[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 {
|
BuiltinAttribute {
|
||||||
name: sym::rustc_diagnostic_item,
|
name: sym::rustc_diagnostic_item,
|
||||||
type_: Normal,
|
type_: Normal,
|
||||||
|
|
|
@ -166,36 +166,6 @@ pub fn extract(attrs: &[ast::Attribute]) -> Option<(Symbol, Span)> {
|
||||||
|
|
||||||
language_item_table! {
|
language_item_table! {
|
||||||
// Variant name, Name, Method name, Target Generic requirements;
|
// 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);
|
Sized, sym::sized, sized_trait, Target::Trait, GenericRequirement::Exact(0);
|
||||||
Unsize, sym::unsize, unsize_trait, Target::Trait, GenericRequirement::Minimum(1);
|
Unsize, sym::unsize, unsize_trait, Target::Trait, GenericRequirement::Minimum(1);
|
||||||
/// Trait injected by `#[derive(PartialEq)]`, (i.e. "Partial EQ").
|
/// Trait injected by `#[derive(PartialEq)]`, (i.e. "Partial EQ").
|
||||||
|
|
|
@ -95,6 +95,11 @@ crate struct CrateMetadata {
|
||||||
/// FIXME: Used only from queries and can use query cache,
|
/// FIXME: Used only from queries and can use query cache,
|
||||||
/// so pre-decoding can probably be avoided.
|
/// so pre-decoding can probably be avoided.
|
||||||
trait_impls: FxHashMap<(u32, DefIndex), Lazy<[(DefIndex, Option<SimplifiedType>)]>>,
|
trait_impls: FxHashMap<(u32, DefIndex), Lazy<[(DefIndex, Option<SimplifiedType>)]>>,
|
||||||
|
/// 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<SimplifiedType, Lazy<[DefIndex]>>,
|
||||||
/// Proc macro descriptions for this crate, if it's a proc macro crate.
|
/// Proc macro descriptions for this crate, if it's a proc macro crate.
|
||||||
raw_proc_macros: Option<&'static [ProcMacro]>,
|
raw_proc_macros: Option<&'static [ProcMacro]>,
|
||||||
/// Source maps for code from the crate.
|
/// 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.
|
/// Iterates over the language items in the given crate.
|
||||||
fn get_lang_items(self) -> impl Iterator<Item = (DefId, usize)> + 'a {
|
fn get_lang_items(self, tcx: TyCtxt<'tcx>) -> &'tcx [(DefId, usize)] {
|
||||||
self.root
|
tcx.arena.alloc_from_iter(
|
||||||
.lang_items
|
self.root
|
||||||
.decode(self)
|
.lang_items
|
||||||
.map(move |(def_index, index)| (self.local_def_id(def_index), index))
|
.decode(self)
|
||||||
|
.map(move |(def_index, index)| (self.local_def_id(def_index), index)),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Iterates over the diagnostic items in the given crate.
|
/// 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).
|
/// Decodes all trait impls in the crate (for rustdoc).
|
||||||
fn get_trait_impls(self) -> impl Iterator<Item = (DefId, DefId, Option<SimplifiedType>)> + 'a {
|
fn get_trait_impls(self) -> impl Iterator<Item = (DefId, DefId, Option<SimplifiedType>)> + '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 {
|
let trait_def_id = DefId {
|
||||||
krate: self.cnum_map[CrateNum::from_u32(*trait_cnum_raw)],
|
krate: self.cnum_map[CrateNum::from_u32(trait_cnum_raw)],
|
||||||
index: *trait_index,
|
index: trait_index,
|
||||||
};
|
};
|
||||||
impls.decode(self).map(move |(impl_index, simplified_self_ty)| {
|
impls.decode(self).map(move |(impl_index, simplified_self_ty)| {
|
||||||
(trait_def_id, self.local_def_id(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<Item = DefId> + '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(
|
fn get_implementations_of_trait(
|
||||||
self,
|
self,
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
|
@ -1754,6 +1776,11 @@ impl CrateMetadata {
|
||||||
.decode((&blob, sess))
|
.decode((&blob, sess))
|
||||||
.map(|trait_impls| (trait_impls.trait_id, trait_impls.impls))
|
.map(|trait_impls| (trait_impls.trait_id, trait_impls.impls))
|
||||||
.collect();
|
.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 =
|
let alloc_decoding_state =
|
||||||
AllocDecodingState::new(root.interpret_alloc_index.decode(&blob).collect());
|
AllocDecodingState::new(root.interpret_alloc_index.decode(&blob).collect());
|
||||||
let dependencies = Lock::new(cnum_map.iter().cloned().collect());
|
let dependencies = Lock::new(cnum_map.iter().cloned().collect());
|
||||||
|
@ -1766,6 +1793,7 @@ impl CrateMetadata {
|
||||||
blob,
|
blob,
|
||||||
root,
|
root,
|
||||||
trait_impls,
|
trait_impls,
|
||||||
|
incoherent_impls,
|
||||||
raw_proc_macros,
|
raw_proc_macros,
|
||||||
source_map_import_info: OnceCell::new(),
|
source_map_import_info: OnceCell::new(),
|
||||||
def_path_hash_map,
|
def_path_hash_map,
|
||||||
|
|
|
@ -81,30 +81,42 @@ macro_rules! provide {
|
||||||
// small trait to work around different signature queries all being defined via
|
// small trait to work around different signature queries all being defined via
|
||||||
// the macro above.
|
// the macro above.
|
||||||
trait IntoArgs {
|
trait IntoArgs {
|
||||||
fn into_args(self) -> (DefId, DefId);
|
type Other;
|
||||||
|
fn into_args(self) -> (DefId, Self::Other);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IntoArgs for DefId {
|
impl IntoArgs for DefId {
|
||||||
fn into_args(self) -> (DefId, DefId) {
|
type Other = ();
|
||||||
(self, self)
|
fn into_args(self) -> (DefId, ()) {
|
||||||
|
(self, ())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IntoArgs for CrateNum {
|
impl IntoArgs for CrateNum {
|
||||||
fn into_args(self) -> (DefId, DefId) {
|
type Other = ();
|
||||||
(self.as_def_id(), self.as_def_id())
|
fn into_args(self) -> (DefId, ()) {
|
||||||
|
(self.as_def_id(), ())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IntoArgs for (CrateNum, DefId) {
|
impl IntoArgs for (CrateNum, DefId) {
|
||||||
|
type Other = DefId;
|
||||||
fn into_args(self) -> (DefId, DefId) {
|
fn into_args(self) -> (DefId, DefId) {
|
||||||
(self.0.as_def_id(), self.1)
|
(self.0.as_def_id(), self.1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> IntoArgs for ty::InstanceDef<'tcx> {
|
impl<'tcx> IntoArgs for ty::InstanceDef<'tcx> {
|
||||||
fn into_args(self) -> (DefId, DefId) {
|
type Other = ();
|
||||||
(self.def_id(), self.def_id())
|
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()) }
|
traits_in_crate => { tcx.arena.alloc_from_iter(cdata.get_traits()) }
|
||||||
implementations_of_trait => { cdata.get_implementations_of_trait(tcx, other) }
|
implementations_of_trait => { cdata.get_implementations_of_trait(tcx, other) }
|
||||||
|
crate_incoherent_impls => { cdata.get_incoherent_impls(tcx, other) }
|
||||||
|
|
||||||
dep_kind => {
|
dep_kind => {
|
||||||
let r = *cdata.dep_kind.lock();
|
let r = *cdata.dep_kind.lock();
|
||||||
|
@ -210,7 +223,7 @@ provide! { <'tcx> tcx, def_id, other, cdata,
|
||||||
tcx.arena.alloc_slice(&result)
|
tcx.arena.alloc_slice(&result)
|
||||||
}
|
}
|
||||||
defined_lib_features => { cdata.get_lib_features(tcx) }
|
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() }
|
diagnostic_items => { cdata.get_diagnostic_items() }
|
||||||
missing_lang_items => { cdata.get_missing_lang_items(tcx) }
|
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))
|
.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()),
|
crates: |tcx, ()| tcx.arena.alloc_from_iter(CStore::from_tcx(tcx).crates_untracked()),
|
||||||
|
|
||||||
..*providers
|
..*providers
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -511,9 +523,12 @@ impl CStore {
|
||||||
self.get_crate_data(cnum).get_inherent_impls()
|
self.get_crate_data(cnum).get_inherent_impls()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Decodes all lang items in the crate (for rustdoc).
|
/// Decodes all incoherent inherent impls in the crate (for rustdoc).
|
||||||
pub fn lang_items_untracked(&self, cnum: CrateNum) -> impl Iterator<Item = DefId> + '_ {
|
pub fn incoherent_impls_in_crate_untracked(
|
||||||
self.get_crate_data(cnum).get_lang_items().map(|(def_id, _)| def_id)
|
&self,
|
||||||
|
cnum: CrateNum,
|
||||||
|
) -> impl Iterator<Item = DefId> + '_ {
|
||||||
|
self.get_crate_data(cnum).get_all_incoherent_impls()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,9 @@ use crate::rmeta::def_path_hash_map::DefPathHashMapRef;
|
||||||
use crate::rmeta::table::{FixedSizeEncoding, TableBuilder};
|
use crate::rmeta::table::{FixedSizeEncoding, TableBuilder};
|
||||||
use crate::rmeta::*;
|
use crate::rmeta::*;
|
||||||
|
|
||||||
|
use rustc_data_structures::fingerprint::Fingerprint;
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
|
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_data_structures::sync::{join, par_iter, Lrc, ParallelIterator};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::DefKind;
|
use rustc_hir::def::DefKind;
|
||||||
|
@ -578,6 +579,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encode_crate_root(&mut self) -> Lazy<CrateRoot<'tcx>> {
|
fn encode_crate_root(&mut self) -> Lazy<CrateRoot<'tcx>> {
|
||||||
|
let tcx = self.tcx;
|
||||||
let mut i = self.position();
|
let mut i = self.position();
|
||||||
|
|
||||||
// Encode the crate deps
|
// Encode the crate deps
|
||||||
|
@ -623,8 +625,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||||
let impls = self.encode_impls();
|
let impls = self.encode_impls();
|
||||||
let impls_bytes = self.position() - i;
|
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.
|
// Encode MIR.
|
||||||
i = self.position();
|
i = self.position();
|
||||||
self.encode_mir();
|
self.encode_mir();
|
||||||
|
@ -734,6 +737,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||||
source_map,
|
source_map,
|
||||||
traits,
|
traits,
|
||||||
impls,
|
impls,
|
||||||
|
incoherent_impls,
|
||||||
exported_symbols,
|
exported_symbols,
|
||||||
interpret_alloc_index,
|
interpret_alloc_index,
|
||||||
tables,
|
tables,
|
||||||
|
@ -762,6 +766,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||||
eprintln!(" source_map bytes: {}", source_map_bytes);
|
eprintln!(" source_map bytes: {}", source_map_bytes);
|
||||||
eprintln!(" traits bytes: {}", traits_bytes);
|
eprintln!(" traits bytes: {}", traits_bytes);
|
||||||
eprintln!(" impls bytes: {}", impls_bytes);
|
eprintln!(" impls bytes: {}", impls_bytes);
|
||||||
|
eprintln!("incoherent_impls bytes: {}", incoherent_impls_bytes);
|
||||||
eprintln!(" exp. symbols bytes: {}", exported_symbols_bytes);
|
eprintln!(" exp. symbols bytes: {}", exported_symbols_bytes);
|
||||||
eprintln!(" def-path table bytes: {}", def_path_table_bytes);
|
eprintln!(" def-path table bytes: {}", def_path_table_bytes);
|
||||||
eprintln!(" def-path hashes bytes: {}", def_path_hash_map_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)
|
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::<Fingerprint>();
|
||||||
|
});
|
||||||
|
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.
|
// Encodes all symbols exported from this crate into the metadata.
|
||||||
//
|
//
|
||||||
// This pass is seeded off the reachability list calculated in the
|
// This pass is seeded off the reachability list calculated in the
|
||||||
|
|
|
@ -212,6 +212,7 @@ crate struct CrateRoot<'tcx> {
|
||||||
foreign_modules: Lazy<[ForeignModule]>,
|
foreign_modules: Lazy<[ForeignModule]>,
|
||||||
traits: Lazy<[DefIndex]>,
|
traits: Lazy<[DefIndex]>,
|
||||||
impls: Lazy<[TraitImpls]>,
|
impls: Lazy<[TraitImpls]>,
|
||||||
|
incoherent_impls: Lazy<[IncoherentImpls]>,
|
||||||
interpret_alloc_index: Lazy<[u32]>,
|
interpret_alloc_index: Lazy<[u32]>,
|
||||||
proc_macro_data: Option<ProcMacroData>,
|
proc_macro_data: Option<ProcMacroData>,
|
||||||
|
|
||||||
|
@ -251,6 +252,12 @@ crate struct TraitImpls {
|
||||||
impls: Lazy<[(DefIndex, Option<SimplifiedType>)]>,
|
impls: Lazy<[(DefIndex, Option<SimplifiedType>)]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(MetadataEncodable, MetadataDecodable)]
|
||||||
|
crate struct IncoherentImpls {
|
||||||
|
self_ty: SimplifiedType,
|
||||||
|
impls: Lazy<[DefIndex]>,
|
||||||
|
}
|
||||||
|
|
||||||
/// Define `LazyTables` and `TableBuilders` at the same time.
|
/// Define `LazyTables` and `TableBuilders` at the same time.
|
||||||
macro_rules! define_tables {
|
macro_rules! define_tables {
|
||||||
($($name:ident: Table<$IDX:ty, $T:ty>),+ $(,)?) => {
|
($($name:ident: Table<$IDX:ty, $T:ty>),+ $(,)?) => {
|
||||||
|
|
|
@ -579,6 +579,10 @@ impl<'hir> Map<'hir> {
|
||||||
self.attrs(CRATE_HIR_ID)
|
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) {
|
pub fn get_module(self, module: LocalDefId) -> (&'hir Mod<'hir>, Span, HirId) {
|
||||||
let hir_id = HirId::make_owner(module);
|
let hir_id = HirId::make_owner(module);
|
||||||
match self.tcx.hir_owner(module).map(|o| o.node) {
|
match self.tcx.hir_owner(module).map(|o| o.node) {
|
||||||
|
|
|
@ -684,6 +684,10 @@ rustc_queries! {
|
||||||
separate_provide_extern
|
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`.
|
/// The result of unsafety-checking this `LocalDefId`.
|
||||||
query unsafety_check_result(key: LocalDefId) -> &'tcx mir::UnsafetyCheckResult {
|
query unsafety_check_result(key: LocalDefId) -> &'tcx mir::UnsafetyCheckResult {
|
||||||
desc { |tcx| "unsafety-checking `{}`", tcx.def_path_str(key.to_def_id()) }
|
desc { |tcx| "unsafety-checking `{}`", tcx.def_path_str(key.to_def_id()) }
|
||||||
|
@ -1469,6 +1473,15 @@ rustc_queries! {
|
||||||
separate_provide_extern
|
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 {
|
query is_dllimport_foreign_item(def_id: DefId) -> bool {
|
||||||
desc { |tcx| "is_dllimport_foreign_item({})", tcx.def_path_str(def_id) }
|
desc { |tcx| "is_dllimport_foreign_item({})", tcx.def_path_str(def_id) }
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
use crate::middle::region;
|
use crate::middle::region;
|
||||||
use crate::mir;
|
use crate::mir;
|
||||||
use crate::ty;
|
use crate::ty;
|
||||||
|
use crate::ty::fast_reject::SimplifiedType;
|
||||||
use rustc_data_structures::fingerprint::Fingerprint;
|
use rustc_data_structures::fingerprint::Fingerprint;
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_data_structures::stable_hasher::HashingControls;
|
use rustc_data_structures::stable_hasher::HashingControls;
|
||||||
|
@ -55,6 +56,18 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> ToStableHashKey<StableHashingContext<'a>> 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<StableHashingContext<'a>> for ty::subst::GenericArg<'tcx> {
|
impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ty::subst::GenericArg<'tcx> {
|
||||||
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
|
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
|
||||||
self.unpack().hash_stable(hcx, hasher);
|
self.unpack().hash_stable(hcx, hasher);
|
||||||
|
|
|
@ -25,6 +25,7 @@ use crate::middle::privacy::AccessLevels;
|
||||||
use crate::mir::{Body, GeneratorLayout};
|
use crate::mir::{Body, GeneratorLayout};
|
||||||
use crate::traits::{self, Reveal};
|
use crate::traits::{self, Reveal};
|
||||||
use crate::ty;
|
use crate::ty;
|
||||||
|
use crate::ty::fast_reject::SimplifiedType;
|
||||||
use crate::ty::subst::{GenericArg, InternalSubsts, Subst, SubstsRef};
|
use crate::ty::subst::{GenericArg, InternalSubsts, Subst, SubstsRef};
|
||||||
use crate::ty::util::Discr;
|
use crate::ty::util::Discr;
|
||||||
use rustc_ast as ast;
|
use rustc_ast as ast;
|
||||||
|
@ -2335,6 +2336,7 @@ pub fn provide(providers: &mut ty::query::Providers) {
|
||||||
super::middle::provide(providers);
|
super::middle::provide(providers);
|
||||||
*providers = ty::query::Providers {
|
*providers = ty::query::Providers {
|
||||||
trait_impls_of: trait_def::trait_impls_of_provider,
|
trait_impls_of: trait_def::trait_impls_of_provider,
|
||||||
|
incoherent_impls: trait_def::incoherent_impls_provider,
|
||||||
type_uninhabited_from: inhabitedness::type_uninhabited_from,
|
type_uninhabited_from: inhabitedness::type_uninhabited_from,
|
||||||
const_param_default: consts::const_param_default,
|
const_param_default: consts::const_param_default,
|
||||||
vtable_allocation: vtable::vtable_allocation_provider,
|
vtable_allocation: vtable::vtable_allocation_provider,
|
||||||
|
@ -2350,6 +2352,7 @@ pub fn provide(providers: &mut ty::query::Providers) {
|
||||||
#[derive(Clone, Debug, Default, HashStable)]
|
#[derive(Clone, Debug, Default, HashStable)]
|
||||||
pub struct CrateInherentImpls {
|
pub struct CrateInherentImpls {
|
||||||
pub inherent_impls: LocalDefIdMap<Vec<DefId>>,
|
pub inherent_impls: LocalDefIdMap<Vec<DefId>>,
|
||||||
|
pub incoherent_impls: FxHashMap<SimplifiedType, Vec<LocalDefId>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, HashStable)]
|
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, HashStable)]
|
||||||
|
|
|
@ -1889,10 +1889,7 @@ impl<'tcx> Ty<'tcx> {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_slice(self) -> bool {
|
pub fn is_slice(self) -> bool {
|
||||||
match self.kind() {
|
matches!(self.kind(), Slice(_))
|
||||||
RawPtr(TypeAndMut { ty, .. }) | Ref(_, ty, _) => matches!(ty.kind(), Slice(_) | Str),
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -2,9 +2,11 @@ use crate::traits::specialization_graph;
|
||||||
use crate::ty::fast_reject::{self, SimplifiedType, TreatParams};
|
use crate::ty::fast_reject::{self, SimplifiedType, TreatParams};
|
||||||
use crate::ty::fold::TypeFoldable;
|
use crate::ty::fold::TypeFoldable;
|
||||||
use crate::ty::{Ident, Ty, TyCtxt};
|
use crate::ty::{Ident, Ty, TyCtxt};
|
||||||
|
use hir::def_id::LOCAL_CRATE;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_hir::definitions::DefPathHash;
|
use rustc_hir::definitions::DefPathHash;
|
||||||
|
use std::iter;
|
||||||
|
|
||||||
use rustc_data_structures::fx::FxIndexMap;
|
use rustc_data_structures::fx::FxIndexMap;
|
||||||
use rustc_errors::ErrorGuaranteed;
|
use rustc_errors::ErrorGuaranteed;
|
||||||
|
@ -257,3 +259,19 @@ pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> Trait
|
||||||
|
|
||||||
impls
|
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)
|
||||||
|
}
|
||||||
|
|
|
@ -120,6 +120,9 @@ impl CheckAttrVisitor<'_> {
|
||||||
sym::must_not_suspend => self.check_must_not_suspend(&attr, span, target),
|
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::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_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_unstable
|
||||||
| sym::rustc_const_stable
|
| sym::rustc_const_stable
|
||||||
| sym::unstable
|
| 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]`
|
/// Warns against some misuses of `#[must_use]`
|
||||||
fn check_must_use(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) -> bool {
|
fn check_must_use(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) -> bool {
|
||||||
let node = self.tcx.hir().get(hir_id);
|
let node = self.tcx.hir().get(hir_id);
|
||||||
|
|
|
@ -141,6 +141,16 @@ impl Key for ty::WithOptConstParam<LocalDefId> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
impl Key for (DefId, DefId) {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn query_crate_is_local(&self) -> bool {
|
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) {
|
impl Key for (DefId, SimplifiedType) {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn query_crate_is_local(&self) -> bool {
|
fn query_crate_is_local(&self) -> bool {
|
||||||
|
|
|
@ -494,11 +494,9 @@ symbols! {
|
||||||
const_panic,
|
const_panic,
|
||||||
const_panic_fmt,
|
const_panic_fmt,
|
||||||
const_precise_live_drops,
|
const_precise_live_drops,
|
||||||
const_ptr,
|
|
||||||
const_raw_ptr_deref,
|
const_raw_ptr_deref,
|
||||||
const_raw_ptr_to_usize_cast,
|
const_raw_ptr_to_usize_cast,
|
||||||
const_refs_to_cell,
|
const_refs_to_cell,
|
||||||
const_slice_ptr,
|
|
||||||
const_trait_bound_opt_out,
|
const_trait_bound_opt_out,
|
||||||
const_trait_impl,
|
const_trait_impl,
|
||||||
const_transmute,
|
const_transmute,
|
||||||
|
@ -655,9 +653,7 @@ symbols! {
|
||||||
f,
|
f,
|
||||||
f16c_target_feature,
|
f16c_target_feature,
|
||||||
f32,
|
f32,
|
||||||
f32_runtime,
|
|
||||||
f64,
|
f64,
|
||||||
f64_runtime,
|
|
||||||
fabsf32,
|
fabsf32,
|
||||||
fabsf64,
|
fabsf64,
|
||||||
fadd_fast,
|
fadd_fast,
|
||||||
|
@ -913,8 +909,6 @@ symbols! {
|
||||||
mul_with_overflow,
|
mul_with_overflow,
|
||||||
must_not_suspend,
|
must_not_suspend,
|
||||||
must_use,
|
must_use,
|
||||||
mut_ptr,
|
|
||||||
mut_slice_ptr,
|
|
||||||
naked,
|
naked,
|
||||||
naked_functions,
|
naked_functions,
|
||||||
name,
|
name,
|
||||||
|
@ -1160,10 +1154,12 @@ symbols! {
|
||||||
rustc_allocator,
|
rustc_allocator,
|
||||||
rustc_allocator_nounwind,
|
rustc_allocator_nounwind,
|
||||||
rustc_allow_const_fn_unstable,
|
rustc_allow_const_fn_unstable,
|
||||||
|
rustc_allow_incoherent_impl,
|
||||||
rustc_attrs,
|
rustc_attrs,
|
||||||
rustc_builtin_macro,
|
rustc_builtin_macro,
|
||||||
rustc_capture_analysis,
|
rustc_capture_analysis,
|
||||||
rustc_clean,
|
rustc_clean,
|
||||||
|
rustc_coherence_is_core,
|
||||||
rustc_const_stable,
|
rustc_const_stable,
|
||||||
rustc_const_unstable,
|
rustc_const_unstable,
|
||||||
rustc_conversion_suggestion,
|
rustc_conversion_suggestion,
|
||||||
|
@ -1312,11 +1308,8 @@ symbols! {
|
||||||
sized,
|
sized,
|
||||||
skip,
|
skip,
|
||||||
slice,
|
slice,
|
||||||
slice_alloc,
|
|
||||||
slice_len_fn,
|
slice_len_fn,
|
||||||
slice_patterns,
|
slice_patterns,
|
||||||
slice_u8,
|
|
||||||
slice_u8_alloc,
|
|
||||||
slicing_syntax,
|
slicing_syntax,
|
||||||
soft,
|
soft,
|
||||||
specialization,
|
specialization,
|
||||||
|
@ -1346,7 +1339,6 @@ symbols! {
|
||||||
stop_after_dataflow,
|
stop_after_dataflow,
|
||||||
store,
|
store,
|
||||||
str,
|
str,
|
||||||
str_alloc,
|
|
||||||
str_split_whitespace,
|
str_split_whitespace,
|
||||||
str_trim,
|
str_trim,
|
||||||
str_trim_end,
|
str_trim_end,
|
||||||
|
|
|
@ -78,28 +78,6 @@ pub struct NoMatchData<'tcx> {
|
||||||
pub mode: probe::Mode,
|
pub mode: probe::Mode,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> NoMatchData<'tcx> {
|
|
||||||
pub fn new(
|
|
||||||
static_candidates: Vec<CandidateSource>,
|
|
||||||
unsatisfied_predicates: Vec<(
|
|
||||||
ty::Predicate<'tcx>,
|
|
||||||
Option<ty::Predicate<'tcx>>,
|
|
||||||
Option<ObligationCause<'tcx>>,
|
|
||||||
)>,
|
|
||||||
out_of_scope_traits: Vec<DefId>,
|
|
||||||
lev_candidate: Option<ty::AssocItem>,
|
|
||||||
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
|
// A pared down enum describing just the places from which a method
|
||||||
// candidate can arise. Used for error reporting only.
|
// candidate can arise. Used for error reporting only.
|
||||||
#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
|
#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
|
||||||
|
|
|
@ -18,6 +18,7 @@ use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKi
|
||||||
use rustc_infer::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
|
use rustc_infer::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
|
||||||
use rustc_infer::infer::{self, InferOk, TyCtxtInferExt};
|
use rustc_infer::infer::{self, InferOk, TyCtxtInferExt};
|
||||||
use rustc_middle::middle::stability;
|
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::subst::{InternalSubsts, Subst, SubstsRef};
|
||||||
use rustc_middle::ty::GenericParamDefKind;
|
use rustc_middle::ty::GenericParamDefKind;
|
||||||
use rustc_middle::ty::{self, ParamEnvAnd, ToPredicate, Ty, TyCtxt, TypeFoldable};
|
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));
|
.unwrap_or_else(|_| span_bug!(span, "instantiating {:?} failed?", ty));
|
||||||
let ty = self.structurally_resolved_type(span, ty.value);
|
let ty = self.structurally_resolved_type(span, ty.value);
|
||||||
assert!(matches!(ty.kind(), ty::Error(_)));
|
assert!(matches!(ty.kind(), ty::Error(_)));
|
||||||
return Err(MethodError::NoMatch(NoMatchData::new(
|
return Err(MethodError::NoMatch(NoMatchData {
|
||||||
Vec::new(),
|
static_candidates: Vec::new(),
|
||||||
Vec::new(),
|
unsatisfied_predicates: Vec::new(),
|
||||||
Vec::new(),
|
out_of_scope_traits: Vec::new(),
|
||||||
None,
|
lev_candidate: None,
|
||||||
mode,
|
mode,
|
||||||
)));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -613,9 +614,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
||||||
|
|
||||||
fn assemble_probe(&mut self, self_ty: &Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>) {
|
fn assemble_probe(&mut self, self_ty: &Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>) {
|
||||||
debug!("assemble_probe: self_ty={:?}", self_ty);
|
debug!("assemble_probe: self_ty={:?}", self_ty);
|
||||||
let lang_items = self.tcx.lang_items();
|
let raw_self_ty = self_ty.value.value;
|
||||||
|
match *raw_self_ty.kind() {
|
||||||
match *self_ty.value.value.kind() {
|
|
||||||
ty::Dynamic(data, ..) if let Some(p) = data.principal() => {
|
ty::Dynamic(data, ..) if let Some(p) = data.principal() => {
|
||||||
// Subtle: we can't use `instantiate_query_response` here: using it will
|
// Subtle: we can't use `instantiate_query_response` here: using it will
|
||||||
// commit to all of the type equalities assumed by inference going through
|
// 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) => {
|
ty::Param(p) => {
|
||||||
self.assemble_inherent_candidates_from_param(p);
|
self.assemble_inherent_candidates_from_param(p);
|
||||||
}
|
}
|
||||||
ty::Bool => {
|
ty::Bool
|
||||||
let lang_def_id = lang_items.bool_impl();
|
| ty::Char
|
||||||
self.assemble_inherent_impl_for_primitive(lang_def_id);
|
| ty::Int(_)
|
||||||
}
|
| ty::Uint(_)
|
||||||
ty::Char => {
|
| ty::Float(_)
|
||||||
let lang_def_id = lang_items.char_impl();
|
| ty::Str
|
||||||
self.assemble_inherent_impl_for_primitive(lang_def_id);
|
| ty::Array(..)
|
||||||
}
|
| ty::Slice(_)
|
||||||
ty::Str => {
|
| ty::RawPtr(_)
|
||||||
let lang_def_id = lang_items.str_impl();
|
| ty::Ref(..)
|
||||||
self.assemble_inherent_impl_for_primitive(lang_def_id);
|
| ty::Never
|
||||||
|
| ty::Tuple(..) => self.assemble_inherent_candidates_for_incoherent_ty(raw_self_ty),
|
||||||
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);
|
|
||||||
}
|
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn assemble_inherent_impl_for_primitive(&mut self, lang_def_id: Option<DefId>) {
|
fn assemble_inherent_candidates_for_incoherent_ty(&mut self, self_ty: Ty<'tcx>) {
|
||||||
if let Some(impl_def_id) = lang_def_id {
|
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);
|
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.
|
// fcx's fulfillment context after this probe is over.
|
||||||
// Note: we only normalize `xform_self_ty` here since the normalization
|
// Note: we only normalize `xform_self_ty` here since the normalization
|
||||||
// of the return type can lead to inference results that prohibit
|
// 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,
|
// 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`
|
// 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,
|
// 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()?;
|
let lev_candidate = self.probe_for_lev_candidate()?;
|
||||||
|
|
||||||
Err(MethodError::NoMatch(NoMatchData::new(
|
Err(MethodError::NoMatch(NoMatchData {
|
||||||
static_candidates,
|
static_candidates,
|
||||||
unsatisfied_predicates,
|
unsatisfied_predicates,
|
||||||
out_of_scope_traits,
|
out_of_scope_traits,
|
||||||
lev_candidate,
|
lev_candidate,
|
||||||
self.mode,
|
mode: self.mode,
|
||||||
)))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pick_core(&mut self) -> Option<PickResult<'tcx>> {
|
fn pick_core(&mut self) -> Option<PickResult<'tcx>> {
|
||||||
|
|
|
@ -281,25 +281,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
// There are methods that are defined on the primitive types and won't be
|
// 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
|
// found when exploring `all_traits`, but we also need them to be acurate on
|
||||||
// our suggestions (#47759).
|
// our suggestions (#47759).
|
||||||
let fund_assoc = |opt_def_id: Option<DefId>| {
|
let found_assoc = |ty: Ty<'tcx>| {
|
||||||
opt_def_id.and_then(|id| self.associated_value(id, item_name)).is_some()
|
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()
|
let found_candidate = candidates.next().is_some()
|
||||||
|| fund_assoc(lang_items.i8_impl())
|
|| found_assoc(tcx.types.i8)
|
||||||
|| fund_assoc(lang_items.i16_impl())
|
|| found_assoc(tcx.types.i16)
|
||||||
|| fund_assoc(lang_items.i32_impl())
|
|| found_assoc(tcx.types.i32)
|
||||||
|| fund_assoc(lang_items.i64_impl())
|
|| found_assoc(tcx.types.i64)
|
||||||
|| fund_assoc(lang_items.i128_impl())
|
|| found_assoc(tcx.types.i128)
|
||||||
|| fund_assoc(lang_items.u8_impl())
|
|| found_assoc(tcx.types.u8)
|
||||||
|| fund_assoc(lang_items.u16_impl())
|
|| found_assoc(tcx.types.u16)
|
||||||
|| fund_assoc(lang_items.u32_impl())
|
|| found_assoc(tcx.types.u32)
|
||||||
|| fund_assoc(lang_items.u64_impl())
|
|| found_assoc(tcx.types.u64)
|
||||||
|| fund_assoc(lang_items.u128_impl())
|
|| found_assoc(tcx.types.u128)
|
||||||
|| fund_assoc(lang_items.f32_impl())
|
|| found_assoc(tcx.types.f32)
|
||||||
|| fund_assoc(lang_items.f32_runtime_impl())
|
|| found_assoc(tcx.types.f32);
|
||||||
|| fund_assoc(lang_items.f64_impl())
|
|
||||||
|| fund_assoc(lang_items.f64_runtime_impl());
|
|
||||||
if let (true, false, SelfSource::MethodCall(expr), true) = (
|
if let (true, false, SelfSource::MethodCall(expr), true) = (
|
||||||
actual.is_numeric(),
|
actual.is_numeric(),
|
||||||
actual.has_concrete_skeleton(),
|
actual.has_concrete_skeleton(),
|
||||||
|
|
|
@ -7,12 +7,13 @@
|
||||||
//! `tcx.inherent_impls(def_id)`). That value, however,
|
//! `tcx.inherent_impls(def_id)`). That value, however,
|
||||||
//! is computed by selecting an idea from this table.
|
//! 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 as hir;
|
||||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId};
|
||||||
use rustc_hir::itemlikevisit::ItemLikeVisitor;
|
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;
|
use rustc_span::Span;
|
||||||
|
|
||||||
/// On-demand query: yields a map containing all types mapped to their inherent impls.
|
/// 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
|
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.
|
/// 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] {
|
pub fn inherent_impls(tcx: TyCtxt<'_>, ty_def_id: DefId) -> &[DefId] {
|
||||||
let ty_def_id = ty_def_id.expect_local();
|
let ty_def_id = ty_def_id.expect_local();
|
||||||
|
@ -40,12 +48,11 @@ struct InherentCollect<'tcx> {
|
||||||
|
|
||||||
impl<'tcx> ItemLikeVisitor<'_> for InherentCollect<'tcx> {
|
impl<'tcx> ItemLikeVisitor<'_> for InherentCollect<'tcx> {
|
||||||
fn visit_item(&mut self, item: &hir::Item<'_>) {
|
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;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
let self_ty = self.tcx.type_of(item.def_id);
|
let self_ty = self.tcx.type_of(item.def_id);
|
||||||
let lang_items = self.tcx.lang_items();
|
|
||||||
match *self_ty.kind() {
|
match *self_ty.kind() {
|
||||||
ty::Adt(def, _) => {
|
ty::Adt(def, _) => {
|
||||||
self.check_def_id(item, def.did());
|
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")
|
.note("define and implement a new trait or type instead")
|
||||||
.emit();
|
.emit();
|
||||||
}
|
}
|
||||||
ty::Bool => {
|
ty::Bool
|
||||||
self.check_primitive_impl(
|
| ty::Char
|
||||||
item.def_id,
|
| ty::Int(_)
|
||||||
lang_items.bool_impl(),
|
| ty::Uint(_)
|
||||||
None,
|
| ty::Float(_)
|
||||||
"bool",
|
| ty::Str
|
||||||
"bool",
|
| ty::Array(..)
|
||||||
item.span,
|
| ty::Slice(_)
|
||||||
assoc_items,
|
| ty::RawPtr(_)
|
||||||
);
|
| ty::Ref(..)
|
||||||
}
|
| ty::Never
|
||||||
ty::Char => {
|
| ty::Tuple(..) => self.check_primitive_impl(item.def_id, self_ty, items, ty.span),
|
||||||
self.check_primitive_impl(
|
ty::FnPtr(_) | ty::Projection(..) | ty::Opaque(..) | ty::Param(_) => {
|
||||||
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(_) => {}
|
|
||||||
_ => {
|
|
||||||
let mut err = struct_span_err!(
|
let mut err = struct_span_err!(
|
||||||
self.tcx.sess,
|
self.tcx.sess,
|
||||||
ty.span,
|
ty.span,
|
||||||
|
@ -347,16 +97,18 @@ impl<'tcx> ItemLikeVisitor<'_> for InherentCollect<'tcx> {
|
||||||
err.span_label(ty.span, "impl requires a nominal type")
|
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");
|
.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();
|
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(
|
fn check_primitive_impl(
|
||||||
&self,
|
&mut self,
|
||||||
impl_def_id: LocalDefId,
|
impl_def_id: LocalDefId,
|
||||||
lang_def_id: Option<DefId>,
|
ty: Ty<'tcx>,
|
||||||
lang_def_id2: Option<DefId>,
|
items: &[hir::ImplItemRef],
|
||||||
lang: &str,
|
|
||||||
ty: &str,
|
|
||||||
span: Span,
|
span: Span,
|
||||||
assoc_items: &[hir::ImplItemRef],
|
|
||||||
) {
|
) {
|
||||||
match (lang_def_id, lang_def_id2) {
|
const INTO_CORE: &str = "consider moving this inherent impl into `core` if possible";
|
||||||
(Some(lang_def_id), _) if lang_def_id == impl_def_id.to_def_id() => {
|
const ADD_ATTR: &str =
|
||||||
// OK
|
"alternatively add `#[rustc_allow_incoherent_impl]` to the relevant impl items";
|
||||||
}
|
if !self.tcx.hir().rustc_coherence_is_core() {
|
||||||
(_, Some(lang_def_id)) if lang_def_id == impl_def_id.to_def_id() => {
|
if self.tcx.features().rustc_attrs {
|
||||||
// OK
|
for item in items {
|
||||||
}
|
if !self
|
||||||
_ => {
|
.tcx
|
||||||
let to_implement = if assoc_items.is_empty() {
|
.has_attr(item.id.def_id.to_def_id(), sym::rustc_allow_incoherent_impl)
|
||||||
String::new()
|
{
|
||||||
} else {
|
struct_span_err!(
|
||||||
let assoc_items_kind = {
|
self.tcx.sess,
|
||||||
let item_types = assoc_items.iter().map(|x| x.kind);
|
span,
|
||||||
if item_types.clone().all(|x| x == hir::AssocItemKind::Const) {
|
E0390,
|
||||||
"constant"
|
"cannot define inherent `impl` for primitive types outside of `core`",
|
||||||
} else if item_types
|
)
|
||||||
.clone()
|
.help(INTO_CORE)
|
||||||
.all(|x| matches! {x, hir::AssocItemKind::Fn{ .. } })
|
.span_help(item.span, ADD_ATTR)
|
||||||
{
|
.emit();
|
||||||
"method"
|
return;
|
||||||
} else {
|
}
|
||||||
"associated item"
|
}
|
||||||
}
|
} else {
|
||||||
};
|
let mut err = struct_span_err!(
|
||||||
|
|
||||||
format!(
|
|
||||||
" to implement {} {}{}",
|
|
||||||
pluralize!("this", assoc_items.len()),
|
|
||||||
assoc_items_kind,
|
|
||||||
pluralize!(assoc_items.len()),
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
struct_span_err!(
|
|
||||||
self.tcx.sess,
|
self.tcx.sess,
|
||||||
span,
|
span,
|
||||||
E0390,
|
E0390,
|
||||||
"only a single inherent implementation marked with `#[lang = \
|
"cannot define inherent `impl` for primitive types",
|
||||||
\"{}\"]` is allowed for the `{}` primitive",
|
);
|
||||||
lang,
|
err.help("consider using an extension trait instead");
|
||||||
ty
|
if let ty::Ref(_, subty, _) = ty.kind() {
|
||||||
)
|
err.note(&format!(
|
||||||
.help(&format!("consider using a trait{}", to_implement))
|
"you could also try moving the reference to \
|
||||||
.emit();
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -144,13 +144,14 @@ fn enforce_empty_impls_for_marker_traits(
|
||||||
|
|
||||||
pub fn provide(providers: &mut Providers) {
|
pub fn provide(providers: &mut Providers) {
|
||||||
use self::builtin::coerce_unsized_info;
|
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::inherent_impls_overlap::crate_inherent_impls_overlap_check;
|
||||||
use self::orphan::orphan_check_crate;
|
use self::orphan::orphan_check_crate;
|
||||||
|
|
||||||
*providers = Providers {
|
*providers = Providers {
|
||||||
coherent_trait,
|
coherent_trait,
|
||||||
crate_inherent_impls,
|
crate_inherent_impls,
|
||||||
|
crate_incoherent_impls,
|
||||||
inherent_impls,
|
inherent_impls,
|
||||||
crate_inherent_impls_overlap_check,
|
crate_inherent_impls_overlap_check,
|
||||||
coerce_unsized_info,
|
coerce_unsized_info,
|
||||||
|
|
|
@ -237,7 +237,7 @@ mod hack {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[lang = "slice_alloc"]
|
#[cfg_attr(bootstrap, lang = "slice_alloc")]
|
||||||
#[cfg(not(test))]
|
#[cfg(not(test))]
|
||||||
impl<T> [T] {
|
impl<T> [T] {
|
||||||
/// Sorts the slice.
|
/// Sorts the slice.
|
||||||
|
@ -267,6 +267,7 @@ impl<T> [T] {
|
||||||
/// assert!(v == [-5, -3, 1, 2, 4]);
|
/// assert!(v == [-5, -3, 1, 2, 4]);
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg(not(no_global_oom_handling))]
|
#[cfg(not(no_global_oom_handling))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn sort(&mut self)
|
pub fn sort(&mut self)
|
||||||
|
@ -322,6 +323,7 @@ impl<T> [T] {
|
||||||
/// assert!(v == [5, 4, 3, 2, 1]);
|
/// assert!(v == [5, 4, 3, 2, 1]);
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg(not(no_global_oom_handling))]
|
#[cfg(not(no_global_oom_handling))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn sort_by<F>(&mut self, mut compare: F)
|
pub fn sort_by<F>(&mut self, mut compare: F)
|
||||||
|
@ -363,6 +365,7 @@ impl<T> [T] {
|
||||||
/// assert!(v == [1, 2, -3, 4, -5]);
|
/// assert!(v == [1, 2, -3, 4, -5]);
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg(not(no_global_oom_handling))]
|
#[cfg(not(no_global_oom_handling))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)]
|
||||||
#[stable(feature = "slice_sort_by_key", since = "1.7.0")]
|
#[stable(feature = "slice_sort_by_key", since = "1.7.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn sort_by_key<K, F>(&mut self, mut f: F)
|
pub fn sort_by_key<K, F>(&mut self, mut f: F)
|
||||||
|
@ -409,6 +412,7 @@ impl<T> [T] {
|
||||||
///
|
///
|
||||||
/// [pdqsort]: https://github.com/orlp/pdqsort
|
/// [pdqsort]: https://github.com/orlp/pdqsort
|
||||||
#[cfg(not(no_global_oom_handling))]
|
#[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")]
|
#[stable(feature = "slice_sort_by_cached_key", since = "1.34.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn sort_by_cached_key<K, F>(&mut self, f: F)
|
pub fn sort_by_cached_key<K, F>(&mut self, f: F)
|
||||||
|
@ -467,6 +471,7 @@ impl<T> [T] {
|
||||||
/// // Here, `s` and `x` can be modified independently.
|
/// // Here, `s` and `x` can be modified independently.
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg(not(no_global_oom_handling))]
|
#[cfg(not(no_global_oom_handling))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)]
|
||||||
#[rustc_conversion_suggestion]
|
#[rustc_conversion_suggestion]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -491,6 +496,7 @@ impl<T> [T] {
|
||||||
/// // Here, `s` and `x` can be modified independently.
|
/// // Here, `s` and `x` can be modified independently.
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg(not(no_global_oom_handling))]
|
#[cfg(not(no_global_oom_handling))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)]
|
||||||
#[inline]
|
#[inline]
|
||||||
#[unstable(feature = "allocator_api", issue = "32838")]
|
#[unstable(feature = "allocator_api", issue = "32838")]
|
||||||
pub fn to_vec_in<A: Allocator>(&self, alloc: A) -> Vec<T, A>
|
pub fn to_vec_in<A: Allocator>(&self, alloc: A) -> Vec<T, A>
|
||||||
|
@ -515,6 +521,7 @@ impl<T> [T] {
|
||||||
///
|
///
|
||||||
/// assert_eq!(x, vec![10, 40, 30]);
|
/// assert_eq!(x, vec![10, 40, 30]);
|
||||||
/// ```
|
/// ```
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn into_vec<A: Allocator>(self: Box<Self, A>) -> Vec<T, A> {
|
pub fn into_vec<A: Allocator>(self: Box<Self, A>) -> Vec<T, A> {
|
||||||
|
@ -542,6 +549,7 @@ impl<T> [T] {
|
||||||
/// // this will panic at runtime
|
/// // this will panic at runtime
|
||||||
/// b"0123456789abcdef".repeat(usize::MAX);
|
/// b"0123456789abcdef".repeat(usize::MAX);
|
||||||
/// ```
|
/// ```
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)]
|
||||||
#[cfg(not(no_global_oom_handling))]
|
#[cfg(not(no_global_oom_handling))]
|
||||||
#[stable(feature = "repeat_generic_slice", since = "1.40.0")]
|
#[stable(feature = "repeat_generic_slice", since = "1.40.0")]
|
||||||
pub fn repeat(&self, n: usize) -> Vec<T>
|
pub fn repeat(&self, n: usize) -> Vec<T>
|
||||||
|
@ -610,6 +618,7 @@ impl<T> [T] {
|
||||||
/// assert_eq!(["hello", "world"].concat(), "helloworld");
|
/// assert_eq!(["hello", "world"].concat(), "helloworld");
|
||||||
/// assert_eq!([[1, 2], [3, 4]].concat(), [1, 2, 3, 4]);
|
/// 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")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn concat<Item: ?Sized>(&self) -> <Self as Concat<Item>>::Output
|
pub fn concat<Item: ?Sized>(&self) -> <Self as Concat<Item>>::Output
|
||||||
where
|
where
|
||||||
|
@ -628,6 +637,7 @@ impl<T> [T] {
|
||||||
/// assert_eq!([[1, 2], [3, 4]].join(&0), [1, 2, 0, 3, 4]);
|
/// assert_eq!([[1, 2], [3, 4]].join(&0), [1, 2, 0, 3, 4]);
|
||||||
/// assert_eq!([[1, 2], [3, 4]].join(&[0, 0][..]), [1, 2, 0, 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")]
|
#[stable(feature = "rename_connect_to_join", since = "1.3.0")]
|
||||||
pub fn join<Separator>(&self, sep: Separator) -> <Self as Join<Separator>>::Output
|
pub fn join<Separator>(&self, sep: Separator) -> <Self as Join<Separator>>::Output
|
||||||
where
|
where
|
||||||
|
@ -646,6 +656,7 @@ impl<T> [T] {
|
||||||
/// assert_eq!(["hello", "world"].connect(" "), "hello world");
|
/// assert_eq!(["hello", "world"].connect(" "), "hello world");
|
||||||
/// assert_eq!([[1, 2], [3, 4]].connect(&0), [1, 2, 0, 3, 4]);
|
/// 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")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[rustc_deprecated(since = "1.3.0", reason = "renamed to join")]
|
#[rustc_deprecated(since = "1.3.0", reason = "renamed to join")]
|
||||||
pub fn connect<Separator>(&self, sep: Separator) -> <Self as Join<Separator>>::Output
|
pub fn connect<Separator>(&self, sep: Separator) -> <Self as Join<Separator>>::Output
|
||||||
|
@ -656,7 +667,7 @@ impl<T> [T] {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[lang = "slice_u8_alloc"]
|
#[cfg_attr(bootstrap, lang = "slice_u8_alloc")]
|
||||||
#[cfg(not(test))]
|
#[cfg(not(test))]
|
||||||
impl [u8] {
|
impl [u8] {
|
||||||
/// Returns a vector containing a copy of this slice where each byte
|
/// 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
|
/// [`make_ascii_uppercase`]: slice::make_ascii_uppercase
|
||||||
#[cfg(not(no_global_oom_handling))]
|
#[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, \
|
#[must_use = "this returns the uppercase bytes as a new Vec, \
|
||||||
without modifying the original"]
|
without modifying the original"]
|
||||||
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
|
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
|
||||||
|
@ -689,6 +701,7 @@ impl [u8] {
|
||||||
///
|
///
|
||||||
/// [`make_ascii_lowercase`]: slice::make_ascii_lowercase
|
/// [`make_ascii_lowercase`]: slice::make_ascii_lowercase
|
||||||
#[cfg(not(no_global_oom_handling))]
|
#[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, \
|
#[must_use = "this returns the lowercase bytes as a new Vec, \
|
||||||
without modifying the original"]
|
without modifying the original"]
|
||||||
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
|
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
|
||||||
|
|
|
@ -235,7 +235,7 @@ impl ToOwned for str {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Methods for string slices.
|
/// Methods for string slices.
|
||||||
#[lang = "str_alloc"]
|
#[cfg_attr(bootstrap, lang = "str_alloc")]
|
||||||
#[cfg(not(test))]
|
#[cfg(not(test))]
|
||||||
impl str {
|
impl str {
|
||||||
/// Converts a `Box<str>` into a `Box<[u8]>` without copying or allocating.
|
/// Converts a `Box<str>` into a `Box<[u8]>` without copying or allocating.
|
||||||
|
@ -250,6 +250,7 @@ impl str {
|
||||||
/// let boxed_bytes = boxed_str.into_boxed_bytes();
|
/// let boxed_bytes = boxed_str.into_boxed_bytes();
|
||||||
/// assert_eq!(*boxed_bytes, *s.as_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")]
|
#[stable(feature = "str_box_extras", since = "1.20.0")]
|
||||||
#[must_use = "`self` will be dropped if the result is not used"]
|
#[must_use = "`self` will be dropped if the result is not used"]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -280,6 +281,7 @@ impl str {
|
||||||
/// assert_eq!(s, s.replace("cookie monster", "little lamb"));
|
/// assert_eq!(s, s.replace("cookie monster", "little lamb"));
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg(not(no_global_oom_handling))]
|
#[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, \
|
#[must_use = "this returns the replaced string as a new allocation, \
|
||||||
without modifying the original"]
|
without modifying the original"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
@ -320,6 +322,7 @@ impl str {
|
||||||
/// assert_eq!(s, s.replacen("cookie monster", "little lamb", 10));
|
/// assert_eq!(s, s.replacen("cookie monster", "little lamb", 10));
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg(not(no_global_oom_handling))]
|
#[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, \
|
#[must_use = "this returns the replaced string as a new allocation, \
|
||||||
without modifying the original"]
|
without modifying the original"]
|
||||||
#[stable(feature = "str_replacen", since = "1.16.0")]
|
#[stable(feature = "str_replacen", since = "1.16.0")]
|
||||||
|
@ -376,6 +379,7 @@ impl str {
|
||||||
/// assert_eq!(new_year, new_year.to_lowercase());
|
/// assert_eq!(new_year, new_year.to_lowercase());
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg(not(no_global_oom_handling))]
|
#[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, \
|
#[must_use = "this returns the lowercase string as a new String, \
|
||||||
without modifying the original"]
|
without modifying the original"]
|
||||||
#[stable(feature = "unicode_case_mapping", since = "1.2.0")]
|
#[stable(feature = "unicode_case_mapping", since = "1.2.0")]
|
||||||
|
@ -458,6 +462,7 @@ impl str {
|
||||||
/// assert_eq!("TSCHÜSS", s.to_uppercase());
|
/// assert_eq!("TSCHÜSS", s.to_uppercase());
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg(not(no_global_oom_handling))]
|
#[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, \
|
#[must_use = "this returns the uppercase string as a new String, \
|
||||||
without modifying the original"]
|
without modifying the original"]
|
||||||
#[stable(feature = "unicode_case_mapping", since = "1.2.0")]
|
#[stable(feature = "unicode_case_mapping", since = "1.2.0")]
|
||||||
|
@ -493,6 +498,7 @@ impl str {
|
||||||
/// assert_eq!(boxed_str.into_string(), string);
|
/// assert_eq!(boxed_str.into_string(), string);
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "box_str", since = "1.4.0")]
|
#[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"]
|
#[must_use = "`self` will be dropped if the result is not used"]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn into_string(self: Box<str>) -> String {
|
pub fn into_string(self: Box<str>) -> String {
|
||||||
|
@ -521,6 +527,7 @@ impl str {
|
||||||
/// let huge = "0123456789abcdef".repeat(usize::MAX);
|
/// let huge = "0123456789abcdef".repeat(usize::MAX);
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg(not(no_global_oom_handling))]
|
#[cfg(not(no_global_oom_handling))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[stable(feature = "repeat_str", since = "1.16.0")]
|
#[stable(feature = "repeat_str", since = "1.16.0")]
|
||||||
pub fn repeat(&self, n: usize) -> String {
|
pub fn repeat(&self, n: usize) -> String {
|
||||||
|
@ -549,6 +556,7 @@ impl str {
|
||||||
/// [`make_ascii_uppercase`]: str::make_ascii_uppercase
|
/// [`make_ascii_uppercase`]: str::make_ascii_uppercase
|
||||||
/// [`to_uppercase`]: #method.to_uppercase
|
/// [`to_uppercase`]: #method.to_uppercase
|
||||||
#[cfg(not(no_global_oom_handling))]
|
#[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()`"]
|
#[must_use = "to uppercase the value in-place, use `make_ascii_uppercase()`"]
|
||||||
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
|
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -581,6 +589,7 @@ impl str {
|
||||||
/// [`make_ascii_lowercase`]: str::make_ascii_lowercase
|
/// [`make_ascii_lowercase`]: str::make_ascii_lowercase
|
||||||
/// [`to_lowercase`]: #method.to_lowercase
|
/// [`to_lowercase`]: #method.to_lowercase
|
||||||
#[cfg(not(no_global_oom_handling))]
|
#[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()`"]
|
#[must_use = "to lowercase the value in-place, use `make_ascii_lowercase()`"]
|
||||||
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
|
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -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}
|
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, const N: usize> [T; N] {
|
impl<T, const N: usize> [T; N] {
|
||||||
/// Returns an array of the same size as `self`, with function `f` applied to each element
|
/// Returns an array of the same size as `self`, with function `f` applied to each element
|
||||||
/// in order.
|
/// in order.
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
use crate::marker::Destruct;
|
use crate::marker::Destruct;
|
||||||
|
|
||||||
#[lang = "bool"]
|
#[cfg_attr(bootstrap, lang = "bool")]
|
||||||
impl bool {
|
impl bool {
|
||||||
/// Returns `Some(t)` if the `bool` is [`true`](../std/keyword.true.html),
|
/// Returns `Some(t)` if the `bool` is [`true`](../std/keyword.true.html),
|
||||||
/// or `None` otherwise.
|
/// or `None` otherwise.
|
||||||
|
|
|
@ -7,7 +7,7 @@ use crate::unicode::{self, conversions};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[lang = "char"]
|
#[cfg_attr(bootstrap, lang = "char")]
|
||||||
impl char {
|
impl char {
|
||||||
/// The highest valid code point a `char` can have, `'\u{10FFFF}'`.
|
/// The highest valid code point a `char` can have, `'\u{10FFFF}'`.
|
||||||
///
|
///
|
||||||
|
|
|
@ -84,6 +84,7 @@
|
||||||
target_has_atomic_load_store = "ptr",
|
target_has_atomic_load_store = "ptr",
|
||||||
))]
|
))]
|
||||||
#![no_core]
|
#![no_core]
|
||||||
|
#![cfg_attr(not(bootstrap), rustc_coherence_is_core)]
|
||||||
//
|
//
|
||||||
// Lints:
|
// Lints:
|
||||||
#![deny(rust_2021_incompatible_or_patterns)]
|
#![deny(rust_2021_incompatible_or_patterns)]
|
||||||
|
|
|
@ -370,7 +370,7 @@ pub mod consts {
|
||||||
pub const LN_10: f32 = 2.30258509299404568401799145468436421_f32;
|
pub const LN_10: f32 = 2.30258509299404568401799145468436421_f32;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[lang = "f32"]
|
#[cfg_attr(bootstrap, lang = "f32")]
|
||||||
#[cfg(not(test))]
|
#[cfg(not(test))]
|
||||||
impl f32 {
|
impl f32 {
|
||||||
/// The radix or base of the internal representation of `f32`.
|
/// The radix or base of the internal representation of `f32`.
|
||||||
|
|
|
@ -370,7 +370,7 @@ pub mod consts {
|
||||||
pub const LN_10: f64 = 2.30258509299404568401799145468436421_f64;
|
pub const LN_10: f64 = 2.30258509299404568401799145468436421_f64;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[lang = "f64"]
|
#[cfg_attr(bootstrap, lang = "f64")]
|
||||||
#[cfg(not(test))]
|
#[cfg(not(test))]
|
||||||
impl f64 {
|
impl f64 {
|
||||||
/// The radix or base of the internal representation of `f64`.
|
/// The radix or base of the internal representation of `f64`.
|
||||||
|
|
|
@ -193,26 +193,26 @@ macro_rules! widening_impl {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[lang = "i8"]
|
#[cfg_attr(bootstrap, lang = "i8")]
|
||||||
impl i8 {
|
impl i8 {
|
||||||
int_impl! { i8, i8, u8, 8, 7, -128, 127, 2, "-0x7e", "0xa", "0x12", "0x12", "0x48",
|
int_impl! { i8, i8, u8, 8, 7, -128, 127, 2, "-0x7e", "0xa", "0x12", "0x12", "0x48",
|
||||||
"[0x12]", "[0x12]", "", "" }
|
"[0x12]", "[0x12]", "", "" }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[lang = "i16"]
|
#[cfg_attr(bootstrap, lang = "i16")]
|
||||||
impl i16 {
|
impl i16 {
|
||||||
int_impl! { i16, i16, u16, 16, 15, -32768, 32767, 4, "-0x5ffd", "0x3a", "0x1234", "0x3412",
|
int_impl! { i16, i16, u16, 16, 15, -32768, 32767, 4, "-0x5ffd", "0x3a", "0x1234", "0x3412",
|
||||||
"0x2c48", "[0x34, 0x12]", "[0x12, 0x34]", "", "" }
|
"0x2c48", "[0x34, 0x12]", "[0x12, 0x34]", "", "" }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[lang = "i32"]
|
#[cfg_attr(bootstrap, lang = "i32")]
|
||||||
impl i32 {
|
impl i32 {
|
||||||
int_impl! { i32, i32, u32, 32, 31, -2147483648, 2147483647, 8, "0x10000b3", "0xb301",
|
int_impl! { i32, i32, u32, 32, 31, -2147483648, 2147483647, 8, "0x10000b3", "0xb301",
|
||||||
"0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]",
|
"0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]",
|
||||||
"[0x12, 0x34, 0x56, 0x78]", "", "" }
|
"[0x12, 0x34, 0x56, 0x78]", "", "" }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[lang = "i64"]
|
#[cfg_attr(bootstrap, lang = "i64")]
|
||||||
impl i64 {
|
impl i64 {
|
||||||
int_impl! { i64, i64, u64, 64, 63, -9223372036854775808, 9223372036854775807, 12,
|
int_impl! { i64, i64, u64, 64, 63, -9223372036854775808, 9223372036854775807, 12,
|
||||||
"0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412",
|
"0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412",
|
||||||
|
@ -220,7 +220,7 @@ impl i64 {
|
||||||
"[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", "", "" }
|
"[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", "", "" }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[lang = "i128"]
|
#[cfg_attr(bootstrap, lang = "i128")]
|
||||||
impl i128 {
|
impl i128 {
|
||||||
int_impl! { i128, i128, u128, 128, 127, -170141183460469231731687303715884105728,
|
int_impl! { i128, i128, u128, 128, 127, -170141183460469231731687303715884105728,
|
||||||
170141183460469231731687303715884105727, 16,
|
170141183460469231731687303715884105727, 16,
|
||||||
|
@ -233,7 +233,7 @@ impl i128 {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_pointer_width = "16")]
|
#[cfg(target_pointer_width = "16")]
|
||||||
#[lang = "isize"]
|
#[cfg_attr(bootstrap, lang = "isize")]
|
||||||
impl isize {
|
impl isize {
|
||||||
int_impl! { isize, i16, usize, 16, 15, -32768, 32767, 4, "-0x5ffd", "0x3a", "0x1234",
|
int_impl! { isize, i16, usize, 16, 15, -32768, 32767, 4, "-0x5ffd", "0x3a", "0x1234",
|
||||||
"0x3412", "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]",
|
"0x3412", "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]",
|
||||||
|
@ -241,7 +241,7 @@ impl isize {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_pointer_width = "32")]
|
#[cfg(target_pointer_width = "32")]
|
||||||
#[lang = "isize"]
|
#[cfg_attr(bootstrap, lang = "isize")]
|
||||||
impl isize {
|
impl isize {
|
||||||
int_impl! { isize, i32, usize, 32, 31, -2147483648, 2147483647, 8, "0x10000b3", "0xb301",
|
int_impl! { isize, i32, usize, 32, 31, -2147483648, 2147483647, 8, "0x10000b3", "0xb301",
|
||||||
"0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]",
|
"0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]",
|
||||||
|
@ -250,7 +250,7 @@ impl isize {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_pointer_width = "64")]
|
#[cfg(target_pointer_width = "64")]
|
||||||
#[lang = "isize"]
|
#[cfg_attr(bootstrap, lang = "isize")]
|
||||||
impl isize {
|
impl isize {
|
||||||
int_impl! { isize, i64, usize, 64, 63, -9223372036854775808, 9223372036854775807,
|
int_impl! { isize, i64, usize, 64, 63, -9223372036854775808, 9223372036854775807,
|
||||||
12, "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412",
|
12, "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412",
|
||||||
|
@ -262,7 +262,7 @@ impl isize {
|
||||||
/// If 6th bit set ascii is upper case.
|
/// If 6th bit set ascii is upper case.
|
||||||
const ASCII_CASE_MASK: u8 = 0b0010_0000;
|
const ASCII_CASE_MASK: u8 = 0b0010_0000;
|
||||||
|
|
||||||
#[lang = "u8"]
|
#[cfg_attr(bootstrap, lang = "u8")]
|
||||||
impl u8 {
|
impl u8 {
|
||||||
uint_impl! { u8, u8, i8, NonZeroU8, 8, 255, 2, "0x82", "0xa", "0x12", "0x12", "0x48", "[0x12]",
|
uint_impl! { u8, u8, i8, NonZeroU8, 8, 255, 2, "0x82", "0xa", "0x12", "0x12", "0x48", "[0x12]",
|
||||||
"[0x12]", "", "" }
|
"[0x12]", "", "" }
|
||||||
|
@ -816,7 +816,7 @@ impl u8 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[lang = "u16"]
|
#[cfg_attr(bootstrap, lang = "u16")]
|
||||||
impl u16 {
|
impl u16 {
|
||||||
uint_impl! { u16, u16, i16, NonZeroU16, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48",
|
uint_impl! { u16, u16, i16, NonZeroU16, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48",
|
||||||
"[0x34, 0x12]", "[0x12, 0x34]", "", "" }
|
"[0x34, 0x12]", "[0x12, 0x34]", "", "" }
|
||||||
|
@ -848,14 +848,14 @@ impl u16 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[lang = "u32"]
|
#[cfg_attr(bootstrap, lang = "u32")]
|
||||||
impl u32 {
|
impl u32 {
|
||||||
uint_impl! { u32, u32, i32, NonZeroU32, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678",
|
uint_impl! { u32, u32, i32, NonZeroU32, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678",
|
||||||
"0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", "", "" }
|
"0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", "", "" }
|
||||||
widening_impl! { u32, u64, 32, unsigned }
|
widening_impl! { u32, u64, 32, unsigned }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[lang = "u64"]
|
#[cfg_attr(bootstrap, lang = "u64")]
|
||||||
impl u64 {
|
impl u64 {
|
||||||
uint_impl! { u64, u64, i64, NonZeroU64, 64, 18446744073709551615, 12, "0xaa00000000006e1", "0x6e10aa",
|
uint_impl! { u64, u64, i64, NonZeroU64, 64, 18446744073709551615, 12, "0xaa00000000006e1", "0x6e10aa",
|
||||||
"0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48",
|
"0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48",
|
||||||
|
@ -865,7 +865,7 @@ impl u64 {
|
||||||
widening_impl! { u64, u128, 64, unsigned }
|
widening_impl! { u64, u128, 64, unsigned }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[lang = "u128"]
|
#[cfg_attr(bootstrap, lang = "u128")]
|
||||||
impl u128 {
|
impl u128 {
|
||||||
uint_impl! { u128, u128, i128, NonZeroU128, 128, 340282366920938463463374607431768211455, 16,
|
uint_impl! { u128, u128, i128, NonZeroU128, 128, 340282366920938463463374607431768211455, 16,
|
||||||
"0x13f40000000000000000000000004f76", "0x4f7613f4", "0x12345678901234567890123456789012",
|
"0x13f40000000000000000000000004f76", "0x4f7613f4", "0x12345678901234567890123456789012",
|
||||||
|
@ -878,7 +878,7 @@ impl u128 {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_pointer_width = "16")]
|
#[cfg(target_pointer_width = "16")]
|
||||||
#[lang = "usize"]
|
#[cfg_attr(bootstrap, lang = "usize")]
|
||||||
impl usize {
|
impl usize {
|
||||||
uint_impl! { usize, u16, isize, NonZeroUsize, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48",
|
uint_impl! { usize, u16, isize, NonZeroUsize, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48",
|
||||||
"[0x34, 0x12]", "[0x12, 0x34]",
|
"[0x34, 0x12]", "[0x12, 0x34]",
|
||||||
|
@ -886,7 +886,7 @@ impl usize {
|
||||||
widening_impl! { usize, u32, 16, unsigned }
|
widening_impl! { usize, u32, 16, unsigned }
|
||||||
}
|
}
|
||||||
#[cfg(target_pointer_width = "32")]
|
#[cfg(target_pointer_width = "32")]
|
||||||
#[lang = "usize"]
|
#[cfg_attr(bootstrap, lang = "usize")]
|
||||||
impl usize {
|
impl usize {
|
||||||
uint_impl! { usize, u32, isize, NonZeroUsize, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678",
|
uint_impl! { usize, u32, isize, NonZeroUsize, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678",
|
||||||
"0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]",
|
"0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]",
|
||||||
|
@ -895,7 +895,7 @@ impl usize {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_pointer_width = "64")]
|
#[cfg(target_pointer_width = "64")]
|
||||||
#[lang = "usize"]
|
#[cfg_attr(bootstrap, lang = "usize")]
|
||||||
impl usize {
|
impl usize {
|
||||||
uint_impl! { usize, u64, isize, NonZeroUsize, 64, 18446744073709551615, 12, "0xaa00000000006e1", "0x6e10aa",
|
uint_impl! { usize, u64, isize, NonZeroUsize, 64, 18446744073709551615, 12, "0xaa00000000006e1", "0x6e10aa",
|
||||||
"0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48",
|
"0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48",
|
||||||
|
|
|
@ -4,7 +4,7 @@ use crate::intrinsics;
|
||||||
use crate::mem;
|
use crate::mem;
|
||||||
use crate::slice::{self, SliceIndex};
|
use crate::slice::{self, SliceIndex};
|
||||||
|
|
||||||
#[lang = "const_ptr"]
|
#[cfg_attr(bootstrap, lang = "const_ptr")]
|
||||||
impl<T: ?Sized> *const T {
|
impl<T: ?Sized> *const T {
|
||||||
/// Returns `true` if the pointer is null.
|
/// Returns `true` if the pointer is null.
|
||||||
///
|
///
|
||||||
|
@ -1042,7 +1042,7 @@ impl<T: ?Sized> *const T {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[lang = "const_slice_ptr"]
|
#[cfg_attr(bootstrap, lang = "const_slice_ptr")]
|
||||||
impl<T> *const [T] {
|
impl<T> *const [T] {
|
||||||
/// Returns the length of a raw slice.
|
/// Returns the length of a raw slice.
|
||||||
///
|
///
|
||||||
|
|
|
@ -3,7 +3,7 @@ use crate::cmp::Ordering::{self, Equal, Greater, Less};
|
||||||
use crate::intrinsics;
|
use crate::intrinsics;
|
||||||
use crate::slice::{self, SliceIndex};
|
use crate::slice::{self, SliceIndex};
|
||||||
|
|
||||||
#[lang = "mut_ptr"]
|
#[cfg_attr(bootstrap, lang = "mut_ptr")]
|
||||||
impl<T: ?Sized> *mut T {
|
impl<T: ?Sized> *mut T {
|
||||||
/// Returns `true` if the pointer is null.
|
/// Returns `true` if the pointer is null.
|
||||||
///
|
///
|
||||||
|
@ -1313,7 +1313,7 @@ impl<T: ?Sized> *mut T {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[lang = "mut_slice_ptr"]
|
#[cfg_attr(bootstrap, lang = "mut_slice_ptr")]
|
||||||
impl<T> *mut [T] {
|
impl<T> *mut [T] {
|
||||||
/// Returns the length of a raw slice.
|
/// Returns the length of a raw slice.
|
||||||
///
|
///
|
||||||
|
|
|
@ -6,7 +6,7 @@ use crate::iter;
|
||||||
use crate::mem;
|
use crate::mem;
|
||||||
use crate::ops;
|
use crate::ops;
|
||||||
|
|
||||||
#[lang = "slice_u8"]
|
#[cfg_attr(bootstrap, lang = "slice_u8")]
|
||||||
#[cfg(not(test))]
|
#[cfg(not(test))]
|
||||||
impl [u8] {
|
impl [u8] {
|
||||||
/// Checks if all bytes in this slice are within the ASCII range.
|
/// Checks if all bytes in this slice are within the ASCII range.
|
||||||
|
|
|
@ -109,7 +109,7 @@ enum Direction {
|
||||||
Back,
|
Back,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[lang = "slice"]
|
#[cfg_attr(bootstrap, lang = "slice")]
|
||||||
#[cfg(not(test))]
|
#[cfg(not(test))]
|
||||||
impl<T> [T] {
|
impl<T> [T] {
|
||||||
/// Returns the number of elements in the slice.
|
/// Returns the number of elements in the slice.
|
||||||
|
|
|
@ -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))]
|
#[cfg(not(test))]
|
||||||
impl str {
|
impl str {
|
||||||
/// Returns the length of `self`.
|
/// Returns the length of `self`.
|
||||||
|
|
|
@ -28,7 +28,7 @@ pub use core::f32::{
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(not(test))]
|
#[cfg(not(test))]
|
||||||
#[lang = "f32_runtime"]
|
#[cfg_attr(bootstrap, lang = "f32_runtime")]
|
||||||
impl f32 {
|
impl f32 {
|
||||||
/// Returns the largest integer less than or equal to a number.
|
/// 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!(g.floor(), 3.0);
|
||||||
/// assert_eq!(h.floor(), -4.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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -61,6 +62,7 @@ impl f32 {
|
||||||
/// assert_eq!(f.ceil(), 4.0);
|
/// assert_eq!(f.ceil(), 4.0);
|
||||||
/// assert_eq!(g.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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -80,6 +82,7 @@ impl f32 {
|
||||||
/// assert_eq!(f.round(), 3.0);
|
/// assert_eq!(f.round(), 3.0);
|
||||||
/// assert_eq!(g.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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -100,6 +103,7 @@ impl f32 {
|
||||||
/// assert_eq!(g.trunc(), 3.0);
|
/// assert_eq!(g.trunc(), 3.0);
|
||||||
/// assert_eq!(h.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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -120,6 +124,7 @@ impl f32 {
|
||||||
/// assert!(abs_difference_x <= f32::EPSILON);
|
/// assert!(abs_difference_x <= f32::EPSILON);
|
||||||
/// assert!(abs_difference_y <= 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -144,6 +149,7 @@ impl f32 {
|
||||||
///
|
///
|
||||||
/// assert!(f32::NAN.abs().is_nan());
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -167,6 +173,7 @@ impl f32 {
|
||||||
///
|
///
|
||||||
/// assert!(f32::NAN.signum().is_nan());
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -193,6 +200,7 @@ impl f32 {
|
||||||
///
|
///
|
||||||
/// assert!(f32::NAN.copysign(1.0).is_nan());
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "copysign", since = "1.35.0")]
|
#[stable(feature = "copysign", since = "1.35.0")]
|
||||||
|
@ -220,6 +228,7 @@ impl f32 {
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference <= f32::EPSILON);
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[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), -1.0); // 7.0 >= -4.0 * -1.0
|
||||||
/// assert_eq!((-a).div_euclid(-b), 2.0); // -7.0 >= -4.0 * 2.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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "euclidean_division", since = "1.38.0")]
|
#[stable(feature = "euclidean_division", since = "1.38.0")]
|
||||||
|
@ -278,6 +288,7 @@ impl f32 {
|
||||||
/// // limitation due to round-off error
|
/// // limitation due to round-off error
|
||||||
/// assert!((-f32::EPSILON).rem_euclid(3.0) != 0.0);
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "euclidean_division", since = "1.38.0")]
|
#[stable(feature = "euclidean_division", since = "1.38.0")]
|
||||||
|
@ -298,6 +309,7 @@ impl f32 {
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference <= f32::EPSILON);
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -315,6 +327,7 @@ impl f32 {
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference <= f32::EPSILON);
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -339,6 +352,7 @@ impl f32 {
|
||||||
/// assert!(negative.sqrt().is_nan());
|
/// assert!(negative.sqrt().is_nan());
|
||||||
/// assert!(negative_zero.sqrt() == negative_zero);
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -360,6 +374,7 @@ impl f32 {
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference <= f32::EPSILON);
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -379,6 +394,7 @@ impl f32 {
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference <= f32::EPSILON);
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -400,6 +416,7 @@ impl f32 {
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference <= f32::EPSILON);
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -423,6 +440,7 @@ impl f32 {
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference <= f32::EPSILON);
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -442,6 +460,7 @@ impl f32 {
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference <= f32::EPSILON);
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -464,6 +483,7 @@ impl f32 {
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference <= f32::EPSILON);
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -488,6 +508,7 @@ impl f32 {
|
||||||
/// assert!(abs_difference_x <= f32::EPSILON);
|
/// assert!(abs_difference_x <= f32::EPSILON);
|
||||||
/// assert!(abs_difference_y <= 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -517,6 +538,7 @@ impl f32 {
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference <= f32::EPSILON);
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -538,6 +560,7 @@ impl f32 {
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference <= f32::EPSILON);
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -556,6 +579,7 @@ impl f32 {
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference <= f32::EPSILON);
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -574,6 +598,7 @@ impl f32 {
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference <= f32::EPSILON);
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -591,6 +616,7 @@ impl f32 {
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference <= f32::EPSILON);
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -612,6 +638,7 @@ impl f32 {
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference <= f32::EPSILON);
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -633,6 +660,7 @@ impl f32 {
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference <= f32::EPSILON);
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -653,6 +681,7 @@ impl f32 {
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference <= f32::EPSILON);
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -686,6 +715,7 @@ impl f32 {
|
||||||
/// assert!(abs_difference_1 <= f32::EPSILON);
|
/// assert!(abs_difference_1 <= f32::EPSILON);
|
||||||
/// assert!(abs_difference_2 <= 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -708,6 +738,7 @@ impl f32 {
|
||||||
/// assert!(abs_difference_0 <= f32::EPSILON);
|
/// assert!(abs_difference_0 <= f32::EPSILON);
|
||||||
/// assert!(abs_difference_1 <= f32::EPSILON);
|
/// assert!(abs_difference_1 <= f32::EPSILON);
|
||||||
/// ```
|
/// ```
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn sin_cos(self) -> (f32, f32) {
|
pub fn sin_cos(self) -> (f32, f32) {
|
||||||
|
@ -728,6 +759,7 @@ impl f32 {
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference < 1e-10);
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -749,6 +781,7 @@ impl f32 {
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference < 1e-10);
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -771,6 +804,7 @@ impl f32 {
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference <= f32::EPSILON);
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -793,6 +827,7 @@ impl f32 {
|
||||||
/// // Same result
|
/// // Same result
|
||||||
/// assert!(abs_difference <= f32::EPSILON);
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -815,6 +850,7 @@ impl f32 {
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference <= f32::EPSILON);
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -834,6 +870,7 @@ impl f32 {
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference <= f32::EPSILON);
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -853,6 +890,7 @@ impl f32 {
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference <= f32::EPSILON);
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -872,6 +910,7 @@ impl f32 {
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference <= 1e-5);
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -28,7 +28,7 @@ pub use core::f64::{
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(not(test))]
|
#[cfg(not(test))]
|
||||||
#[lang = "f64_runtime"]
|
#[cfg_attr(bootstrap, lang = "f64_runtime")]
|
||||||
impl f64 {
|
impl f64 {
|
||||||
/// Returns the largest integer less than or equal to a number.
|
/// 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!(g.floor(), 3.0);
|
||||||
/// assert_eq!(h.floor(), -4.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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -61,6 +62,7 @@ impl f64 {
|
||||||
/// assert_eq!(f.ceil(), 4.0);
|
/// assert_eq!(f.ceil(), 4.0);
|
||||||
/// assert_eq!(g.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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -80,6 +82,7 @@ impl f64 {
|
||||||
/// assert_eq!(f.round(), 3.0);
|
/// assert_eq!(f.round(), 3.0);
|
||||||
/// assert_eq!(g.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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -100,6 +103,7 @@ impl f64 {
|
||||||
/// assert_eq!(g.trunc(), 3.0);
|
/// assert_eq!(g.trunc(), 3.0);
|
||||||
/// assert_eq!(h.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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -120,6 +124,7 @@ impl f64 {
|
||||||
/// assert!(abs_difference_x < 1e-10);
|
/// assert!(abs_difference_x < 1e-10);
|
||||||
/// assert!(abs_difference_y < 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -144,6 +149,7 @@ impl f64 {
|
||||||
///
|
///
|
||||||
/// assert!(f64::NAN.abs().is_nan());
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -167,6 +173,7 @@ impl f64 {
|
||||||
///
|
///
|
||||||
/// assert!(f64::NAN.signum().is_nan());
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -193,6 +200,7 @@ impl f64 {
|
||||||
///
|
///
|
||||||
/// assert!(f64::NAN.copysign(1.0).is_nan());
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "copysign", since = "1.35.0")]
|
#[stable(feature = "copysign", since = "1.35.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -220,6 +228,7 @@ impl f64 {
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference < 1e-10);
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[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), -1.0); // 7.0 >= -4.0 * -1.0
|
||||||
/// assert_eq!((-a).div_euclid(-b), 2.0); // -7.0 >= -4.0 * 2.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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "euclidean_division", since = "1.38.0")]
|
#[stable(feature = "euclidean_division", since = "1.38.0")]
|
||||||
|
@ -278,6 +288,7 @@ impl f64 {
|
||||||
/// // limitation due to round-off error
|
/// // limitation due to round-off error
|
||||||
/// assert!((-f64::EPSILON).rem_euclid(3.0) != 0.0);
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "euclidean_division", since = "1.38.0")]
|
#[stable(feature = "euclidean_division", since = "1.38.0")]
|
||||||
|
@ -298,6 +309,7 @@ impl f64 {
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference < 1e-10);
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -315,6 +327,7 @@ impl f64 {
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference < 1e-10);
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -339,6 +352,7 @@ impl f64 {
|
||||||
/// assert!(negative.sqrt().is_nan());
|
/// assert!(negative.sqrt().is_nan());
|
||||||
/// assert!(negative_zero.sqrt() == negative_zero);
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -360,6 +374,7 @@ impl f64 {
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference < 1e-10);
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -379,6 +394,7 @@ impl f64 {
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference < 1e-10);
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -400,6 +416,7 @@ impl f64 {
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference < 1e-10);
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -423,6 +440,7 @@ impl f64 {
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference < 1e-10);
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -442,6 +460,7 @@ impl f64 {
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference < 1e-10);
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -466,6 +485,7 @@ impl f64 {
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference < 1e-10);
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -490,6 +510,7 @@ impl f64 {
|
||||||
/// assert!(abs_difference_x < 1e-10);
|
/// assert!(abs_difference_x < 1e-10);
|
||||||
/// assert!(abs_difference_y < 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -519,6 +540,7 @@ impl f64 {
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference < 1e-10);
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -540,6 +562,7 @@ impl f64 {
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference < 1e-10);
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -558,6 +581,7 @@ impl f64 {
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference < 1e-10);
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -576,6 +600,7 @@ impl f64 {
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference < 1e-10);
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -593,6 +618,7 @@ impl f64 {
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference < 1e-14);
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -614,6 +640,7 @@ impl f64 {
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference < 1e-10);
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -635,6 +662,7 @@ impl f64 {
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference < 1e-10);
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -655,6 +683,7 @@ impl f64 {
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference < 1e-10);
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -688,6 +717,7 @@ impl f64 {
|
||||||
/// assert!(abs_difference_1 < 1e-10);
|
/// assert!(abs_difference_1 < 1e-10);
|
||||||
/// assert!(abs_difference_2 < 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -710,6 +740,7 @@ impl f64 {
|
||||||
/// assert!(abs_difference_0 < 1e-10);
|
/// assert!(abs_difference_0 < 1e-10);
|
||||||
/// assert!(abs_difference_1 < 1e-10);
|
/// assert!(abs_difference_1 < 1e-10);
|
||||||
/// ```
|
/// ```
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn sin_cos(self) -> (f64, f64) {
|
pub fn sin_cos(self) -> (f64, f64) {
|
||||||
|
@ -730,6 +761,7 @@ impl f64 {
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference < 1e-20);
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -751,6 +783,7 @@ impl f64 {
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference < 1e-20);
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -773,6 +806,7 @@ impl f64 {
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference < 1e-10);
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -795,6 +829,7 @@ impl f64 {
|
||||||
/// // Same result
|
/// // Same result
|
||||||
/// assert!(abs_difference < 1.0e-10);
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -817,6 +852,7 @@ impl f64 {
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference < 1.0e-10);
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -836,6 +872,7 @@ impl f64 {
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference < 1.0e-10);
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -855,6 +892,7 @@ impl f64 {
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference < 1.0e-10);
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -874,6 +912,7 @@ impl f64 {
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference < 1.0e-10);
|
/// 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"]
|
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -884,6 +923,7 @@ impl f64 {
|
||||||
// Solaris/Illumos requires a wrapper around log, log2, and log10 functions
|
// Solaris/Illumos requires a wrapper around log, log2, and log10 functions
|
||||||
// because of their non-standard behavior (e.g., log(-n) returns -Inf instead
|
// because of their non-standard behavior (e.g., log(-n) returns -Inf instead
|
||||||
// of expected NaN).
|
// of expected NaN).
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_allow_incoherent_impl)]
|
||||||
fn log_wrapper<F: Fn(f64) -> f64>(self, log_fn: F) -> f64 {
|
fn log_wrapper<F: Fn(f64) -> f64>(self, log_fn: F) -> f64 {
|
||||||
if !cfg!(any(target_os = "solaris", target_os = "illumos")) {
|
if !cfg!(any(target_os = "solaris", target_os = "illumos")) {
|
||||||
log_fn(self)
|
log_fn(self)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::default::Default;
|
use std::default::Default;
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
|
use std::iter;
|
||||||
use std::lazy::SyncOnceCell as OnceCell;
|
use std::lazy::SyncOnceCell as OnceCell;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::rc::Rc;
|
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::lang_items::LangItem;
|
||||||
use rustc_hir::{BodyId, Mutability};
|
use rustc_hir::{BodyId, Mutability};
|
||||||
use rustc_index::vec::IndexVec;
|
use rustc_index::vec::IndexVec;
|
||||||
|
use rustc_middle::ty::fast_reject::SimplifiedType;
|
||||||
use rustc_middle::ty::{self, TyCtxt};
|
use rustc_middle::ty::{self, TyCtxt};
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
use rustc_span::hygiene::MacroKind;
|
use rustc_span::hygiene::MacroKind;
|
||||||
|
@ -1625,6 +1627,7 @@ crate enum PrimitiveType {
|
||||||
Never,
|
Never,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SimplifiedTypes = FxHashMap<PrimitiveType, ArrayVec<SimplifiedType, 2>>;
|
||||||
impl PrimitiveType {
|
impl PrimitiveType {
|
||||||
crate fn from_hir(prim: hir::PrimTy) -> PrimitiveType {
|
crate fn from_hir(prim: hir::PrimTy) -> PrimitiveType {
|
||||||
use ast::{FloatTy, IntTy, UintTy};
|
use ast::{FloatTy, IntTy, UintTy};
|
||||||
|
@ -1680,68 +1683,68 @@ impl PrimitiveType {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn impls(&self, tcx: TyCtxt<'_>) -> &'static ArrayVec<DefId, 4> {
|
crate fn simplified_types() -> &'static SimplifiedTypes {
|
||||||
Self::all_impls(tcx).get(self).expect("missing impl for primitive type")
|
use ty::fast_reject::SimplifiedTypeGen::*;
|
||||||
}
|
use ty::{FloatTy, IntTy, UintTy};
|
||||||
|
use PrimitiveType::*;
|
||||||
crate fn all_impls(tcx: TyCtxt<'_>) -> &'static FxHashMap<PrimitiveType, ArrayVec<DefId, 4>> {
|
static CELL: OnceCell<SimplifiedTypes> = OnceCell::new();
|
||||||
static CELL: OnceCell<FxHashMap<PrimitiveType, ArrayVec<DefId, 4>>> = OnceCell::new();
|
|
||||||
|
|
||||||
|
let single = |x| iter::once(x).collect();
|
||||||
CELL.get_or_init(move || {
|
CELL.get_or_init(move || {
|
||||||
use self::PrimitiveType::*;
|
|
||||||
|
|
||||||
let single = |a: Option<DefId>| a.into_iter().collect();
|
|
||||||
let both = |a: Option<DefId>, b: Option<DefId>| -> ArrayVec<_, 4> {
|
|
||||||
a.into_iter().chain(b).collect()
|
|
||||||
};
|
|
||||||
|
|
||||||
let lang_items = tcx.lang_items();
|
|
||||||
map! {
|
map! {
|
||||||
Isize => single(lang_items.isize_impl()),
|
Isize => single(IntSimplifiedType(IntTy::Isize)),
|
||||||
I8 => single(lang_items.i8_impl()),
|
I8 => single(IntSimplifiedType(IntTy::I8)),
|
||||||
I16 => single(lang_items.i16_impl()),
|
I16 => single(IntSimplifiedType(IntTy::I16)),
|
||||||
I32 => single(lang_items.i32_impl()),
|
I32 => single(IntSimplifiedType(IntTy::I32)),
|
||||||
I64 => single(lang_items.i64_impl()),
|
I64 => single(IntSimplifiedType(IntTy::I64)),
|
||||||
I128 => single(lang_items.i128_impl()),
|
I128 => single(IntSimplifiedType(IntTy::I128)),
|
||||||
Usize => single(lang_items.usize_impl()),
|
Usize => single(UintSimplifiedType(UintTy::Usize)),
|
||||||
U8 => single(lang_items.u8_impl()),
|
U8 => single(UintSimplifiedType(UintTy::U8)),
|
||||||
U16 => single(lang_items.u16_impl()),
|
U16 => single(UintSimplifiedType(UintTy::U16)),
|
||||||
U32 => single(lang_items.u32_impl()),
|
U32 => single(UintSimplifiedType(UintTy::U32)),
|
||||||
U64 => single(lang_items.u64_impl()),
|
U64 => single(UintSimplifiedType(UintTy::U64)),
|
||||||
U128 => single(lang_items.u128_impl()),
|
U128 => single(UintSimplifiedType(UintTy::U128)),
|
||||||
F32 => both(lang_items.f32_impl(), lang_items.f32_runtime_impl()),
|
F32 => single(FloatSimplifiedType(FloatTy::F32)),
|
||||||
F64 => both(lang_items.f64_impl(), lang_items.f64_runtime_impl()),
|
F64 => single(FloatSimplifiedType(FloatTy::F64)),
|
||||||
Char => single(lang_items.char_impl()),
|
Str => single(StrSimplifiedType),
|
||||||
Bool => single(lang_items.bool_impl()),
|
Bool => single(BoolSimplifiedType),
|
||||||
Str => both(lang_items.str_impl(), lang_items.str_alloc_impl()),
|
Char => single(CharSimplifiedType),
|
||||||
Slice => {
|
Array => single(ArraySimplifiedType),
|
||||||
lang_items
|
Slice => single(SliceSimplifiedType),
|
||||||
.slice_impl()
|
// FIXME: If we ever add an inherent impl for tuples
|
||||||
.into_iter()
|
// with different lengths, they won't show in rustdoc.
|
||||||
.chain(lang_items.slice_u8_impl())
|
//
|
||||||
.chain(lang_items.slice_alloc_impl())
|
// Either manually update this arrayvec at this point
|
||||||
.chain(lang_items.slice_u8_alloc_impl())
|
// or start with a more complex refactoring.
|
||||||
.collect()
|
Tuple => [TupleSimplifiedType(2), TupleSimplifiedType(3)].into(),
|
||||||
},
|
Unit => single(TupleSimplifiedType(0)),
|
||||||
Array => single(lang_items.array_impl()),
|
RawPointer => [PtrSimplifiedType(Mutability::Not), PtrSimplifiedType(Mutability::Mut)].into(),
|
||||||
Tuple => ArrayVec::new(),
|
Reference => [RefSimplifiedType(Mutability::Not), RefSimplifiedType(Mutability::Mut)].into(),
|
||||||
Unit => ArrayVec::new(),
|
// FIXME: This will be wrong if we ever add inherent impls
|
||||||
RawPointer => {
|
// for function pointers.
|
||||||
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(),
|
|
||||||
Fn => ArrayVec::new(),
|
Fn => ArrayVec::new(),
|
||||||
Never => ArrayVec::new(),
|
Never => single(NeverSimplifiedType),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
crate fn impls<'tcx>(&self, tcx: TyCtxt<'tcx>) -> impl Iterator<Item = DefId> + '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<Item = DefId> + '_ {
|
||||||
|
Self::simplified_types()
|
||||||
|
.values()
|
||||||
|
.flatten()
|
||||||
|
.flat_map(move |&simp| tcx.incoherent_impls(simp))
|
||||||
|
.copied()
|
||||||
|
}
|
||||||
|
|
||||||
crate fn as_sym(&self) -> Symbol {
|
crate fn as_sym(&self) -> Symbol {
|
||||||
use PrimitiveType::*;
|
use PrimitiveType::*;
|
||||||
match self {
|
match self {
|
||||||
|
|
|
@ -184,7 +184,7 @@ crate fn build_deref_target_impls(cx: &mut DocContext<'_>, items: &[Item], ret:
|
||||||
|
|
||||||
if let Some(prim) = target.primitive_type() {
|
if let Some(prim) = target.primitive_type() {
|
||||||
let _prof_timer = cx.tcx.sess.prof.generic_activity("build_primitive_inherent_impls");
|
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);
|
inline::build_impl(cx, None, did, None, ret);
|
||||||
}
|
}
|
||||||
} else if let Type::Path { path } = target {
|
} else if let Type::Path { path } = target {
|
||||||
|
|
|
@ -467,7 +467,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
|
||||||
) -> Option<(Res, ItemFragment)> {
|
) -> Option<(Res, ItemFragment)> {
|
||||||
let tcx = self.cx.tcx;
|
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_)
|
tcx.associated_items(impl_)
|
||||||
.find_by_name_and_namespace(tcx, Ident::with_dummy_span(item_name), ns, impl_)
|
.find_by_name_and_namespace(tcx, Ident::with_dummy_span(item_name), ns, impl_)
|
||||||
.map(|item| {
|
.map(|item| {
|
||||||
|
|
|
@ -113,7 +113,8 @@ impl IntraLinkCrateLoader<'_, '_> {
|
||||||
Vec::from_iter(self.resolver.cstore().trait_impls_in_crate_untracked(cnum));
|
Vec::from_iter(self.resolver.cstore().trait_impls_in_crate_untracked(cnum));
|
||||||
let all_inherent_impls =
|
let all_inherent_impls =
|
||||||
Vec::from_iter(self.resolver.cstore().inherent_impls_in_crate_untracked(cnum));
|
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
|
// 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
|
// 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);
|
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);
|
self.add_traits_in_parent_scope(def_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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.
|
// Also try to inline primitive impls from other crates.
|
||||||
cx.tcx.sess.prof.generic_activity("build_primitive_trait_impls").run(|| {
|
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() {
|
if !def_id.is_local() {
|
||||||
inline::build_impl(cx, None, def_id, None, &mut new_items);
|
inline::build_impl(cx, None, def_id, None, &mut new_items);
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
// no-prefer-dynamic
|
// no-prefer-dynamic
|
||||||
|
|
||||||
#![feature(lang_items)]
|
#![feature(lang_items, rustc_attrs)]
|
||||||
|
|
||||||
#![crate_type = "rlib"]
|
#![crate_type = "rlib"]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
|
@ -15,9 +14,9 @@ impl core::ops::Deref for DerefsToF64 {
|
||||||
}
|
}
|
||||||
|
|
||||||
mod inner {
|
mod inner {
|
||||||
#[lang = "f64_runtime"]
|
|
||||||
impl f64 {
|
impl f64 {
|
||||||
/// [f64::clone]
|
/// [f64::clone]
|
||||||
|
#[rustc_allow_incoherent_impl]
|
||||||
pub fn method() {}
|
pub fn method() {}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,12 +1,12 @@
|
||||||
#![feature(no_core, lang_items, rustdoc_internals)]
|
#![feature(no_core, lang_items, rustdoc_internals, rustc_attrs)]
|
||||||
#![no_core]
|
#![no_core]
|
||||||
|
#![rustc_coherence_is_core]
|
||||||
#![crate_type="rlib"]
|
#![crate_type="rlib"]
|
||||||
|
|
||||||
#[doc(primitive = "char")]
|
#[doc(primitive = "char")]
|
||||||
/// Some char docs
|
/// Some char docs
|
||||||
mod char {}
|
mod char {}
|
||||||
|
|
||||||
#[lang = "char"]
|
|
||||||
impl char {
|
impl char {
|
||||||
pub fn len_utf8(self) -> usize {
|
pub fn len_utf8(self) -> usize {
|
||||||
42
|
42
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
// comments. The doc link points to an associated item, so we check that traits in scope for that
|
// comments. The doc link points to an associated item, so we check that traits in scope for that
|
||||||
// link are populated.
|
// link are populated.
|
||||||
|
|
||||||
// aux-build:extern-lang-item-impl-dep.rs
|
// aux-build:extern-builtin-type-impl-dep.rs
|
||||||
|
|
||||||
#![no_std]
|
#![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;
|
|
@ -1,6 +1,7 @@
|
||||||
#![deny(rustdoc::broken_intra_doc_links)]
|
#![deny(rustdoc::broken_intra_doc_links)]
|
||||||
#![feature(no_core, lang_items, rustdoc_internals)]
|
#![feature(no_core, lang_items, rustc_attrs, rustdoc_internals)]
|
||||||
#![no_core]
|
#![no_core]
|
||||||
|
#![rustc_coherence_is_core]
|
||||||
#![crate_type = "rlib"]
|
#![crate_type = "rlib"]
|
||||||
|
|
||||||
// @has prim_methods_local/index.html
|
// @has prim_methods_local/index.html
|
||||||
|
@ -12,7 +13,6 @@
|
||||||
#[doc(primitive = "char")]
|
#[doc(primitive = "char")]
|
||||||
mod char {}
|
mod char {}
|
||||||
|
|
||||||
#[lang = "char"]
|
|
||||||
impl char {
|
impl char {
|
||||||
pub fn len_utf8(self) -> usize {
|
pub fn len_utf8(self) -> usize {
|
||||||
42
|
42
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
#![deny(rustdoc::broken_intra_doc_links)]
|
#![deny(rustdoc::broken_intra_doc_links)]
|
||||||
|
#![rustc_coherence_is_core]
|
||||||
#![allow(incomplete_features)] // inherent_associated_types
|
#![allow(incomplete_features)] // inherent_associated_types
|
||||||
#![feature(lang_items)]
|
#![feature(rustc_attrs)]
|
||||||
#![feature(no_core)]
|
#![feature(no_core)]
|
||||||
#![feature(rustdoc_internals)]
|
#![feature(rustdoc_internals)]
|
||||||
#![feature(inherent_associated_types)]
|
#![feature(inherent_associated_types)]
|
||||||
#![no_core]
|
#![no_core]
|
||||||
|
|
||||||
#[lang = "usize"]
|
|
||||||
/// [Self::f]
|
/// [Self::f]
|
||||||
/// [Self::MAX]
|
/// [Self::MAX]
|
||||||
// @has prim_self/primitive.usize.html
|
// @has prim_self/primitive.usize.html
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
#![feature(lang_items)]
|
#![feature(rustc_attrs)]
|
||||||
#![feature(rustdoc_internals)]
|
#![feature(rustdoc_internals)]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
pub mod str {
|
pub mod str {
|
||||||
#![doc(primitive = "str")]
|
#![doc(primitive = "str")]
|
||||||
|
|
||||||
#[lang = "str_alloc"]
|
|
||||||
impl str {
|
impl str {
|
||||||
// @has search-index.js foo
|
// @has search-index.js foo
|
||||||
|
#[rustc_allow_incoherent_impl]
|
||||||
pub fn foo(&self) {}
|
pub fn foo(&self) {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
impl Drop for u32 {} //~ ERROR E0117
|
impl Drop for u32 {} //~ ERROR E0117
|
||||||
//~| ERROR the `Drop` trait may only be implemented for structs, enums, and unions
|
//~| ERROR the `Drop` trait may only be implemented for structs, enums, and unions
|
||||||
|
|
||||||
fn main() {
|
fn main() {}
|
||||||
}
|
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
struct Foo;
|
|
||||||
|
|
||||||
impl &mut Foo {
|
|
||||||
//~^ ERROR E0118
|
|
||||||
fn bar(self) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {}
|
|
|
@ -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`.
|
|
|
@ -1,8 +1,7 @@
|
||||||
impl (u8, u8) { //~ ERROR E0118
|
impl fn(u8) { //~ ERROR E0118
|
||||||
fn get_state(&self) -> String {
|
fn get_state(&self) -> String {
|
||||||
String::new()
|
String::new()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {}
|
||||||
}
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
error[E0118]: no nominal type found for inherent implementation
|
error[E0118]: no nominal type found for inherent implementation
|
||||||
--> $DIR/E0118.rs:1:6
|
--> $DIR/E0118.rs:1:6
|
||||||
|
|
|
|
||||||
LL | impl (u8, u8) {
|
LL | impl fn(u8) {
|
||||||
| ^^^^^^^^ impl requires a nominal type
|
| ^^^^^^ impl requires a nominal type
|
||||||
|
|
|
|
||||||
= note: either implement a trait on it or create a newtype to wrap it instead
|
= note: either implement a trait on it or create a newtype to wrap it instead
|
||||||
|
|
||||||
|
|
|
@ -5,5 +5,4 @@ impl Drop for dyn MyTrait {
|
||||||
fn drop(&mut self) {}
|
fn drop(&mut self) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {}
|
||||||
}
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
error[E0390]: only a single inherent implementation marked with `#[lang = "mut_ptr"]` is allowed for the `*mut T` primitive
|
error[E0390]: cannot define inherent `impl` for primitive types
|
||||||
--> $DIR/E0390.rs:5:1
|
--> $DIR/E0390.rs:5:6
|
||||||
|
|
|
|
||||||
LL | impl *mut Foo {}
|
LL | impl *mut Foo {}
|
||||||
| ^^^^^^^^^^^^^^^^
|
| ^^^^^^^^
|
||||||
|
|
|
|
||||||
= help: consider using a trait
|
= help: consider using an extension trait instead
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -1,20 +1,26 @@
|
||||||
impl u8 {
|
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;
|
pub const B: u8 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl str {
|
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 foo() {}
|
||||||
fn bar(self) {}
|
fn bar(self) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl char {
|
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 B: u8 = 0;
|
||||||
pub const C: u8 = 0;
|
pub const C: u8 = 0;
|
||||||
fn foo() {}
|
fn foo() {}
|
||||||
fn bar(self) {}
|
fn bar(self) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct MyType;
|
||||||
|
impl &MyType {
|
||||||
|
//~^ error: cannot define inherent `impl` for primitive types
|
||||||
|
pub fn for_ref(self) {}
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -1,40 +1,36 @@
|
||||||
error[E0390]: only a single inherent implementation marked with `#[lang = "u8"]` is allowed for the `u8` primitive
|
error[E0390]: cannot define inherent `impl` for primitive types
|
||||||
--> $DIR/kinds-of-primitive-impl.rs:1:1
|
--> $DIR/kinds-of-primitive-impl.rs:1:6
|
||||||
|
|
|
|
||||||
LL | / impl u8 {
|
LL | impl u8 {
|
||||||
LL | |
|
| ^^
|
||||||
LL | | pub const B: u8 = 0;
|
|
||||||
LL | | }
|
|
||||||
| |_^
|
|
||||||
|
|
|
|
||||||
= 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
|
error[E0390]: cannot define inherent `impl` for primitive types
|
||||||
--> $DIR/kinds-of-primitive-impl.rs:6:1
|
--> $DIR/kinds-of-primitive-impl.rs:6:6
|
||||||
|
|
|
|
||||||
LL | / impl str {
|
LL | impl str {
|
||||||
LL | |
|
| ^^^
|
||||||
LL | | fn foo() {}
|
|
||||||
LL | | fn bar(self) {}
|
|
||||||
LL | | }
|
|
||||||
| |_^
|
|
||||||
|
|
|
|
||||||
= 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
|
error[E0390]: cannot define inherent `impl` for primitive types
|
||||||
--> $DIR/kinds-of-primitive-impl.rs:12:1
|
--> $DIR/kinds-of-primitive-impl.rs:12:6
|
||||||
|
|
|
|
||||||
LL | / impl char {
|
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
|
= help: consider using an extension trait instead
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
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 4 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0390`.
|
For more information about this error, try `rustc --explain E0390`.
|
||||||
|
|
|
@ -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<T> {}
|
|
||||||
|
|
||||||
struct S;
|
|
||||||
|
|
||||||
impl<T> MyDrop<T> for S {}
|
|
||||||
|
|
||||||
#[lang = "i32"]
|
|
||||||
impl<'a> i32 {
|
|
||||||
fn foo() {}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn bar() {
|
|
||||||
i32::foo();
|
|
||||||
S;
|
|
||||||
}
|
|
|
@ -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
|
|
||||||
}
|
|
|
@ -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`.
|
|
|
@ -3,7 +3,7 @@ use clippy_utils::{higher, peel_blocks_with_stmt, SpanlessEq};
|
||||||
use if_chain::if_chain;
|
use if_chain::if_chain;
|
||||||
use rustc_ast::ast::LitKind;
|
use rustc_ast::ast::LitKind;
|
||||||
use rustc_errors::Applicability;
|
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_lint::{LateContext, LateLintPass};
|
||||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||||
|
|
||||||
|
@ -82,14 +82,6 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingSub {
|
||||||
|
|
||||||
// Get the variable name
|
// Get the variable name
|
||||||
let var_name = ares_path.segments[0].ident.name.as_str();
|
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 {
|
match cond_num_val.kind {
|
||||||
ExprKind::Lit(ref cond_lit) => {
|
ExprKind::Lit(ref cond_lit) => {
|
||||||
// Check if the constant is zero
|
// Check if the constant is zero
|
||||||
|
@ -105,8 +97,8 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingSub {
|
||||||
if name.ident.as_str() == "MIN";
|
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(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);
|
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 let None = cx.tcx.impl_trait_ref(impl_id); // An inherent impl
|
||||||
if int_ids.any(|int_id| int_id == impl_id);
|
if cx.tcx.type_of(impl_id).is_integral();
|
||||||
then {
|
then {
|
||||||
print_lint_and_sugg(cx, var_name, expr)
|
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 name.ident.as_str() == "min_value";
|
||||||
if let Some(func_id) = cx.typeck_results().type_dependent_def_id(func.hir_id);
|
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);
|
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 let None = cx.tcx.impl_trait_ref(impl_id); // An inherent impl
|
||||||
if int_ids.any(|int_id| int_id == impl_id);
|
if cx.tcx.type_of(impl_id).is_integral();
|
||||||
then {
|
then {
|
||||||
print_lint_and_sugg(cx, var_name, expr)
|
print_lint_and_sugg(cx, var_name, expr)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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_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_path_buf" => is_diag_item_method(cx, method_def_id, sym::Path),
|
||||||
"to_vec" => {
|
"to_vec" => {
|
||||||
cx.tcx
|
cx.tcx.impl_of_method(method_def_id)
|
||||||
.impl_of_method(method_def_id)
|
.filter(|&impl_did| {
|
||||||
.map(|impl_did| Some(impl_did) == cx.tcx.lang_items().slice_alloc_impl())
|
cx.tcx.type_of(impl_did).is_slice() && cx.tcx.impl_trait_ref(impl_did).is_none()
|
||||||
== Some(true)
|
})
|
||||||
|
.is_some()
|
||||||
},
|
},
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,13 +12,13 @@ pub(super) fn check(cx: &LateContext<'_>, method_name: &str, expr: &Expr<'_>, se
|
||||||
if count <= 1;
|
if count <= 1;
|
||||||
if let Some(call_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
|
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);
|
if let Some(impl_id) = cx.tcx.impl_of_method(call_id);
|
||||||
let lang_items = cx.tcx.lang_items();
|
if cx.tcx.impl_trait_ref(impl_id).is_none();
|
||||||
if lang_items.slice_impl() == Some(impl_id) || lang_items.str_impl() == Some(impl_id);
|
let self_ty = cx.tcx.type_of(impl_id);
|
||||||
|
if self_ty.is_slice() || self_ty.is_str();
|
||||||
then {
|
then {
|
||||||
// Ignore empty slice and string literals when used with a literal count.
|
// Ignore empty slice and string literals when used with a literal count.
|
||||||
if matches!(self_arg.kind, ExprKind::Array([]))
|
if matches!(self_arg.kind, ExprKind::Array([]))
|
||||||
|| matches!(self_arg.kind, ExprKind::Lit(Spanned { node: LitKind::Str(s, _), .. }) if s.is_empty())
|
|| matches!(self_arg.kind, ExprKind::Lit(Spanned { node: LitKind::Str(s, _), .. }) if s.is_empty())
|
||||||
|
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ pub(super) fn check(cx: &LateContext<'_>, method_name: &str, expr: &Expr<'_>, se
|
||||||
"the resulting iterator will always return `None`")
|
"the resulting iterator will always return `None`")
|
||||||
} else {
|
} else {
|
||||||
(format!("`{}` called with `1` split", method_name),
|
(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`"
|
"the resulting iterator will always return the entire slice followed by `None`"
|
||||||
} else {
|
} else {
|
||||||
"the resulting iterator will always return the entire string followed by `None`"
|
"the resulting iterator will always return the entire string followed by `None`"
|
||||||
|
|
|
@ -16,7 +16,7 @@ use rustc_hir::{
|
||||||
};
|
};
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
use rustc_middle::hir::nested_filter;
|
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_session::{declare_lint_pass, declare_tool_lint};
|
||||||
use rustc_span::source_map::Span;
|
use rustc_span::source_map::Span;
|
||||||
use rustc_span::symbol::Symbol;
|
use rustc_span::symbol::Symbol;
|
||||||
|
@ -308,7 +308,6 @@ struct PtrArg<'tcx> {
|
||||||
method_renames: &'static [(&'static str, &'static str)],
|
method_renames: &'static [(&'static str, &'static str)],
|
||||||
ref_prefix: RefPrefix,
|
ref_prefix: RefPrefix,
|
||||||
deref_ty: DerefTy<'tcx>,
|
deref_ty: DerefTy<'tcx>,
|
||||||
deref_assoc_items: Option<(DefId, &'tcx AssocItems<'tcx>)>,
|
|
||||||
}
|
}
|
||||||
impl PtrArg<'_> {
|
impl PtrArg<'_> {
|
||||||
fn build_msg(&self) -> String {
|
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));
|
if params.get(i).map_or(true, |p| !is_lint_allowed(cx, PTR_ARG, p.hir_id));
|
||||||
|
|
||||||
then {
|
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) => (
|
Some(sym::Vec) => (
|
||||||
[("clone", ".to_owned()")].as_slice(),
|
[("clone", ".to_owned()")].as_slice(),
|
||||||
DerefTy::Slice(
|
DerefTy::Slice(
|
||||||
|
@ -424,17 +423,14 @@ fn check_fn_args<'cx, 'tcx: 'cx>(
|
||||||
}),
|
}),
|
||||||
substs.type_at(0),
|
substs.type_at(0),
|
||||||
),
|
),
|
||||||
cx.tcx.lang_items().slice_impl()
|
|
||||||
),
|
),
|
||||||
Some(sym::String) => (
|
Some(sym::String) => (
|
||||||
[("clone", ".to_owned()"), ("as_str", "")].as_slice(),
|
[("clone", ".to_owned()"), ("as_str", "")].as_slice(),
|
||||||
DerefTy::Str,
|
DerefTy::Str,
|
||||||
cx.tcx.lang_items().str_impl()
|
|
||||||
),
|
),
|
||||||
Some(sym::PathBuf) => (
|
Some(sym::PathBuf) => (
|
||||||
[("clone", ".to_path_buf()"), ("as_path", "")].as_slice(),
|
[("clone", ".to_path_buf()"), ("as_path", "")].as_slice(),
|
||||||
DerefTy::Path,
|
DerefTy::Path,
|
||||||
None,
|
|
||||||
),
|
),
|
||||||
Some(sym::Cow) if mutability == Mutability::Not => {
|
Some(sym::Cow) if mutability == Mutability::Not => {
|
||||||
let ty_name = name.args
|
let ty_name = name.args
|
||||||
|
@ -470,7 +466,6 @@ fn check_fn_args<'cx, 'tcx: 'cx>(
|
||||||
mutability,
|
mutability,
|
||||||
},
|
},
|
||||||
deref_ty,
|
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
|
// If the types match check for methods which exist on both types. e.g. `Vec::len` and
|
||||||
// `slice::len`
|
// `slice::len`
|
||||||
ty::Adt(def, _)
|
ty::Adt(def, _)
|
||||||
if def.did() == args.ty_did
|
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()
|
|
||||||
})) =>
|
|
||||||
{
|
{
|
||||||
set_skip_flag();
|
set_skip_flag();
|
||||||
},
|
},
|
||||||
|
|
|
@ -77,9 +77,9 @@ use rustc_hir::intravisit::{walk_expr, FnKind, Visitor};
|
||||||
use rustc_hir::itemlikevisit::ItemLikeVisitor;
|
use rustc_hir::itemlikevisit::ItemLikeVisitor;
|
||||||
use rustc_hir::LangItem::{OptionNone, ResultErr, ResultOk};
|
use rustc_hir::LangItem::{OptionNone, ResultErr, ResultOk};
|
||||||
use rustc_hir::{
|
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,
|
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,
|
TraitItem, TraitItemKind, TraitRef, TyKind, UnOp,
|
||||||
};
|
};
|
||||||
use rustc_lint::{LateContext, Level, Lint, LintContext};
|
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 as rustc_ty;
|
||||||
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow};
|
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow};
|
||||||
use rustc_middle::ty::binding::BindingMode;
|
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_middle::ty::{layout::IntegerExt, BorrowKind, DefIdTree, Ty, TyCtxt, TypeAndMut, TypeFoldable, UpvarCapture};
|
||||||
use rustc_semver::RustcVersion;
|
use rustc_semver::RustcVersion;
|
||||||
use rustc_session::Session;
|
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`.
|
/// Resolves a def path like `std::vec::Vec`.
|
||||||
/// This function is expensive and should be used sparingly.
|
/// This function is expensive and should be used sparingly.
|
||||||
pub fn def_path_res(cx: &LateContext<'_>, path: &[&str]) -> Res {
|
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<Res> {
|
fn item_child_by_name(tcx: TyCtxt<'_>, def_id: DefId, name: &str) -> Option<Res> {
|
||||||
match tcx.def_kind(def_id) {
|
match tcx.def_kind(def_id) {
|
||||||
DefKind::Mod | DefKind::Enum | DefKind::Trait => tcx
|
DefKind::Mod | DefKind::Enum | DefKind::Trait => tcx
|
||||||
|
@ -479,11 +473,35 @@ pub fn def_path_res(cx: &LateContext<'_>, path: &[&str]) -> Res {
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn find_primitive(tcx: TyCtxt<'_>, name: &str) -> Option<DefId> {
|
fn find_primitive<'tcx>(tcx: TyCtxt<'tcx>, name: &str) -> impl Iterator<Item = DefId> + 'tcx {
|
||||||
if let Some(&(index, Target::Impl)) = lang_items::ITEM_REFS.get(&Symbol::intern(name)) {
|
let single = |ty| tcx.incoherent_impls(ty).iter().copied();
|
||||||
tcx.lang_items().items()[index]
|
let empty = || [].iter().copied();
|
||||||
} else {
|
match name {
|
||||||
None
|
"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<DefId> {
|
fn find_crate(tcx: TyCtxt<'_>, name: &str) -> Option<DefId> {
|
||||||
|
@ -502,30 +520,35 @@ pub fn def_path_res(cx: &LateContext<'_>, path: &[&str]) -> Res {
|
||||||
_ => return Res::Err,
|
_ => return Res::Err,
|
||||||
};
|
};
|
||||||
let tcx = cx.tcx;
|
let tcx = cx.tcx;
|
||||||
let first = try_res!(
|
let starts = find_primitive(tcx, base)
|
||||||
find_primitive(tcx, base)
|
.chain(find_crate(tcx, base))
|
||||||
.or_else(|| find_crate(tcx, base))
|
.flat_map(|id| item_child_by_name(tcx, id, first));
|
||||||
.and_then(|id| item_child_by_name(tcx, id, first))
|
|
||||||
);
|
|
||||||
|
|
||||||
let last = path
|
for first in starts {
|
||||||
.iter()
|
let last = path
|
||||||
.copied()
|
.iter()
|
||||||
// for each segment, find the child item
|
.copied()
|
||||||
.try_fold(first, |res, segment| {
|
// for each segment, find the child item
|
||||||
let def_id = res.def_id();
|
.try_fold(first, |res, segment| {
|
||||||
if let Some(item) = item_child_by_name(tcx, def_id, segment) {
|
let def_id = res.def_id();
|
||||||
Some(item)
|
if let Some(item) = item_child_by_name(tcx, def_id, segment) {
|
||||||
} else if matches!(res, Res::Def(DefKind::Enum | DefKind::Struct, _)) {
|
Some(item)
|
||||||
// it is not a child item so check inherent impl items
|
} else if matches!(res, Res::Def(DefKind::Enum | DefKind::Struct, _)) {
|
||||||
tcx.inherent_impls(def_id)
|
// it is not a child item so check inherent impl items
|
||||||
.iter()
|
tcx.inherent_impls(def_id)
|
||||||
.find_map(|&impl_def_id| item_child_by_name(tcx, impl_def_id, segment))
|
.iter()
|
||||||
} else {
|
.find_map(|&impl_def_id| item_child_by_name(tcx, impl_def_id, segment))
|
||||||
None
|
} else {
|
||||||
}
|
None
|
||||||
});
|
}
|
||||||
try_res!(last).expect_non_local()
|
});
|
||||||
|
|
||||||
|
if let Some(last) = last {
|
||||||
|
return last;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Res::Err
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convenience function to get the `DefId` of a trait by path.
|
/// Convenience function to get the `DefId` of a trait by path.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue