Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,13 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
if !sp.contains(p_span) {
diag.span_label(p_span, format!("{expected}this type parameter"));
}
let parent = p_def_id.as_local().and_then(|id| {
let param_def_id = match *proj.self_ty().kind() {
ty::Param(param) => {
tcx.generics_of(body_owner_def_id).type_param(param, tcx).def_id
}
_ => p_def_id,
};
let parent = param_def_id.as_local().and_then(|id| {
let local_id = tcx.local_def_id_to_hir_id(id);
let generics = tcx.parent_hir_node(local_id).generics()?;
Some((id, generics))
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/ffi/c_double.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Equivalent to C's `double` type.

This type will almost always be [`f64`], which is guaranteed to be an [IEEE 754 double-precision float] in Rust. That said, the standard technically only guarantees that it be a floating-point number with at least the precision of a [`float`], and it may be `f32` or something entirely different from the IEEE-754 standard.
This type will almost always be [`f64`], which is guaranteed to be an [IEEE 754 double-precision float] in Rust. That said, the standard technically only guarantees that it be a floating-point number with at least the precision of a [`float`]; some 16-bit systems use [`f32`], for example. Esoteric systems could use something entirely different from the IEEE-754 standard.

[IEEE 754 double-precision float]: https://en.wikipedia.org/wiki/IEEE_754
[`float`]: c_float
30 changes: 24 additions & 6 deletions library/core/src/ffi/primitives.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,27 @@ macro_rules! type_alias {
}
}

type_alias! { "c_char.md", c_char = c_char_definition::c_char; #[doc(cfg(all()))] }
// `#[doc(cfg(true))]` is used to prevent rustdoc from displaying a "Available on ..." box.
// The implementation of these constants is target-specific, but every target does define them.

type_alias! { "c_char.md", c_char = c_char_definition::c_char; #[doc(cfg(true))] }

type_alias! { "c_schar.md", c_schar = i8; }
type_alias! { "c_uchar.md", c_uchar = u8; }
type_alias! { "c_short.md", c_short = i16; }
type_alias! { "c_ushort.md", c_ushort = u16; }

type_alias! { "c_int.md", c_int = c_int_definition::c_int; #[doc(cfg(all()))] }
type_alias! { "c_uint.md", c_uint = c_int_definition::c_uint; #[doc(cfg(all()))] }
type_alias! { "c_int.md", c_int = c_int_definition::c_int; #[doc(cfg(true))] }
type_alias! { "c_uint.md", c_uint = c_int_definition::c_uint; #[doc(cfg(true))] }

type_alias! { "c_long.md", c_long = c_long_definition::c_long; #[doc(cfg(all()))] }
type_alias! { "c_ulong.md", c_ulong = c_long_definition::c_ulong; #[doc(cfg(all()))] }
type_alias! { "c_long.md", c_long = c_long_definition::c_long; #[doc(cfg(true))] }
type_alias! { "c_ulong.md", c_ulong = c_long_definition::c_ulong; #[doc(cfg(true))] }

type_alias! { "c_longlong.md", c_longlong = i64; }
type_alias! { "c_ulonglong.md", c_ulonglong = u64; }

type_alias! { "c_float.md", c_float = f32; }
type_alias! { "c_double.md", c_double = f64; }
type_alias! { "c_double.md", c_double= c_double_definition::c_double; #[doc(cfg(true))] }

mod c_char_definition {
crate::cfg_select! {
Expand Down Expand Up @@ -183,3 +186,18 @@ mod c_int_definition {
}
}
}

mod c_double_definition {
crate::cfg_select! {
target_arch = "avr" => {
// avr:
// Per https://gcc.gnu.org/wiki/avr-gcc#Type_Layout. The table says `4,8` because
// in C the width of `double` can be changed with the `-mdouble=32/64` setting. But
// 32-bits is the default for the rust avr target.
pub(super) type c_double = f32;
}
_ => {
pub(super) type c_double = f64;
}
}
}
9 changes: 9 additions & 0 deletions library/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@
#![feature(offset_of_enum)]
#![feature(panic_internals)]
#![feature(pattern_type_macro)]
#![feature(sealed)]
#![feature(ub_checks)]
// tidy-alphabetical-end
//
Expand Down Expand Up @@ -216,6 +217,14 @@ pub mod from {
pub use crate::macros::builtin::From;
}

mod sealed {
/// This trait being unreachable from outside the crate
/// prevents outside implementations of our extension traits.
/// This allows adding more trait methods in the future.
#[unstable(feature = "sealed", issue = "none")]
pub trait Sealed {}
}

// We don't export this through #[macro_export] for now, to avoid breakage.
#[unstable(feature = "autodiff", issue = "124509")]
/// Unstable module containing the unstable `autodiff` macro.
Expand Down
84 changes: 84 additions & 0 deletions library/core/src/num/int_macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3944,5 +3944,89 @@ macro_rules! int_impl {
self
}
}

/// Truncate an integer to an integer of the same size or smaller, preserving the least
/// significant bits.
///
/// # Examples
///
/// ```
/// #![feature(integer_extend_truncate)]
#[doc = concat!("assert_eq!(120i8, 120", stringify!($SelfT), ".truncate());")]
#[doc = concat!("assert_eq!(-120i8, (-120", stringify!($SelfT), ").truncate());")]
/// assert_eq!(120i8, 376i32.truncate());
/// ```
#[must_use = "this returns the truncated value and does not modify the original"]
#[unstable(feature = "integer_extend_truncate", issue = "154330")]
#[rustc_const_unstable(feature = "integer_truncate_extend", issue = "154330")]
#[inline]
pub const fn truncate<Target>(self) -> Target
where Self: [const] traits::TruncateTarget<Target>
{
traits::TruncateTarget::internal_truncate(self)
}

/// Truncate an integer to an integer of the same size or smaller, saturating at numeric bounds
/// instead of truncating.
///
/// # Examples
///
/// ```
/// #![feature(integer_extend_truncate)]
#[doc = concat!("assert_eq!(120i8, 120", stringify!($SelfT), ".saturating_truncate());")]
#[doc = concat!("assert_eq!(-120i8, (-120", stringify!($SelfT), ").saturating_truncate());")]
/// assert_eq!(127i8, 376i32.saturating_truncate());
/// assert_eq!(-128i8, (-1000i32).saturating_truncate());
/// ```
#[must_use = "this returns the truncated value and does not modify the original"]
#[unstable(feature = "integer_extend_truncate", issue = "154330")]
#[rustc_const_unstable(feature = "integer_truncate_extend", issue = "154330")]
#[inline]
pub const fn saturating_truncate<Target>(self) -> Target
where Self: [const] traits::TruncateTarget<Target>
{
traits::TruncateTarget::internal_saturating_truncate(self)
}

/// Truncate an integer to an integer of the same size or smaller, returning `None` if the value
/// is outside the bounds of the smaller type.
///
/// # Examples
///
/// ```
/// #![feature(integer_extend_truncate)]
#[doc = concat!("assert_eq!(Some(120i8), 120", stringify!($SelfT), ".checked_truncate());")]
#[doc = concat!("assert_eq!(Some(-120i8), (-120", stringify!($SelfT), ").checked_truncate());")]
/// assert_eq!(None, 376i32.checked_truncate::<i8>());
/// assert_eq!(None, (-1000i32).checked_truncate::<i8>());
/// ```
#[must_use = "this returns the truncated value and does not modify the original"]
#[unstable(feature = "integer_extend_truncate", issue = "154330")]
#[rustc_const_unstable(feature = "integer_truncate_extend", issue = "154330")]
#[inline]
pub const fn checked_truncate<Target>(self) -> Option<Target>
where Self: [const] traits::TruncateTarget<Target>
{
traits::TruncateTarget::internal_checked_truncate(self)
}

/// Extend to an integer of the same size or larger, preserving its value.
///
/// # Examples
///
/// ```
/// #![feature(integer_extend_truncate)]
#[doc = concat!("assert_eq!(120i128, 120i8.extend());")]
#[doc = concat!("assert_eq!(-120i128, (-120i8).extend());")]
/// ```
#[must_use = "this returns the extended value and does not modify the original"]
#[unstable(feature = "integer_extend_truncate", issue = "154330")]
#[rustc_const_unstable(feature = "integer_truncate_extend", issue = "154330")]
#[inline]
pub const fn extend<Target>(self) -> Target
where Self: [const] traits::ExtendTarget<Target>
{
traits::ExtendTarget::internal_extend(self)
}
}
}
10 changes: 10 additions & 0 deletions library/core/src/num/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ mod error;
mod float_parse;
mod nonzero;
mod saturating;
mod traits;
mod wrapping;

/// 100% perma-unstable
Expand Down Expand Up @@ -1795,3 +1796,12 @@ macro_rules! from_str_int_impl {

from_str_int_impl! { signed isize i8 i16 i32 i64 i128 }
from_str_int_impl! { unsigned usize u8 u16 u32 u64 u128 }

macro_rules! impl_sealed {
($($t:ty)*) => {$(
/// Allows extension traits within `core`.
#[unstable(feature = "sealed", issue = "none")]
impl crate::sealed::Sealed for $t {}
)*}
}
impl_sealed! { isize i8 i16 i32 i64 i128 usize u8 u16 u32 u64 u128 }
129 changes: 129 additions & 0 deletions library/core/src/num/traits.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
/// Definitions of traits for numeric types
// Implementation based on `num_conv` by jhpratt, under (MIT OR Apache-2.0).

/// Trait for types that this type can be truncated to
#[unstable(feature = "num_internals", reason = "internal implementation detail", issue = "none")]
#[rustc_const_unstable(feature = "integer_truncate_extend", issue = "154330")]
pub const trait TruncateTarget<Target>: crate::sealed::Sealed {
#[doc(hidden)]
fn internal_truncate(self) -> Target;

#[doc(hidden)]
fn internal_saturating_truncate(self) -> Target;

#[doc(hidden)]
fn internal_checked_truncate(self) -> Option<Target>;
}

/// Trait for types that this type can be truncated to
#[unstable(feature = "num_internals", reason = "internal implementation detail", issue = "none")]
#[rustc_const_unstable(feature = "integer_truncate_extend", issue = "154330")]
pub const trait ExtendTarget<Target>: crate::sealed::Sealed {
#[doc(hidden)]
fn internal_extend(self) -> Target;
}

macro_rules! impl_truncate {
($($from:ty => $($to:ty),+;)*) => {$($(
const _: () = assert!(
size_of::<$from>() >= size_of::<$to>(),
concat!(
"cannot truncate ",
stringify!($from),
" to ",
stringify!($to),
" because ",
stringify!($from),
" is smaller than ",
stringify!($to)
)
);

#[unstable(feature = "num_internals", reason = "internal implementation detail", issue = "none")]
#[rustc_const_unstable(feature = "integer_truncate_extend", issue = "154330")]
impl const TruncateTarget<$to> for $from {
#[inline]
fn internal_truncate(self) -> $to {
self as _
}

#[inline]
fn internal_saturating_truncate(self) -> $to {
if self > <$to>::MAX as Self {
<$to>::MAX
} else if self < <$to>::MIN as Self {
<$to>::MIN
} else {
self as _
}
}

#[inline]
fn internal_checked_truncate(self) -> Option<$to> {
if self > <$to>::MAX as Self || self < <$to>::MIN as Self {
None
} else {
Some(self as _)
}
}
}
)+)*};
}

macro_rules! impl_extend {
($($from:ty => $($to:ty),+;)*) => {$($(
const _: () = assert!(
size_of::<$from>() <= size_of::<$to>(),
concat!(
"cannot extend ",
stringify!($from),
" to ",
stringify!($to),
" because ",
stringify!($from),
" is larger than ",
stringify!($to)
)
);

#[unstable(feature = "num_internals", reason = "internal implementation detail", issue = "none")]
#[rustc_const_unstable(feature = "integer_truncate_extend", issue = "154330")]
impl const ExtendTarget<$to> for $from {
fn internal_extend(self) -> $to {
self as _
}
}
)+)*};
}

impl_truncate! {
u8 => u8;
u16 => u16, u8;
u32 => u32, u16, u8;
u64 => u64, u32, u16, u8;
u128 => u128, u64, u32, u16, u8;
usize => usize, u16, u8;

i8 => i8;
i16 => i16, i8;
i32 => i32, i16, i8;
i64 => i64, i32, i16, i8;
i128 => i128, i64, i32, i16, i8;
isize => isize, i16, i8;
}

impl_extend! {
u8 => u8, u16, u32, u64, u128, usize;
u16 => u16, u32, u64, u128, usize;
u32 => u32, u64, u128;
u64 => u64, u128;
u128 => u128;
usize => usize;

i8 => i8, i16, i32, i64, i128, isize;
i16 => i16, i32, i64, i128, isize;
i32 => i32, i64, i128;
i64 => i64, i128;
i128 => i128;
isize => isize;
}
Loading
Loading