Skip to content

Commit 0fb6e39

Browse files
committed
Auto merge of #51564 - SimonSapin:try-int, r=alexcrichton
Implement always-fallible TryFrom for usize/isize conversions that are infallible on some platforms This reverts commit 837d6c7 "Remove TryFrom impls that might become conditionally-infallible with a portability lint". This fixes #49415 by adding (restoring) missing `TryFrom` impls for integer conversions to or from `usize` or `isize`, by making them always fallible at the type system level (that is, with `Error=TryFromIntError`) even though they happen to be infallible on some platforms (for some values of `size_of::<usize>()`). They had been removed to allow the possibility to conditionally having some of them be infallible `From` impls instead, depending on the platforms, and have the [portability lint](rust-lang/rfcs#1868) warn when they are used in code that is not already opting into non-portability. For example `#[allow(some_lint)] usize::from(x: u64)` would be valid on code that only targets 64-bit platforms. This PR gives up on this possiblity for two reasons: * Based on discussion with @aturon, it seems that the portability lint is not happening any time soon. It’s better to have the conversions be available *at all* than keep blocking them for so long. Portability-lint-gated platform-specific APIs can always be added separately later. * For code that is fine with fallibility, the alternative would force it to opt into "non-portability" even though there would be no real portability issue.
2 parents 81d5c3e + e7c122c commit 0fb6e39

File tree

4 files changed

+191
-101
lines changed

4 files changed

+191
-101
lines changed

src/libcore/iter/range.rs

+2-73
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ macro_rules! step_impl_unsigned {
9191
#[inline]
9292
#[allow(unreachable_patterns)]
9393
fn add_usize(&self, n: usize) -> Option<Self> {
94-
match <$t>::private_try_from(n) {
94+
match <$t>::try_from(n) {
9595
Ok(n_as_t) => self.checked_add(n_as_t),
9696
Err(_) => None,
9797
}
@@ -123,7 +123,7 @@ macro_rules! step_impl_signed {
123123
#[inline]
124124
#[allow(unreachable_patterns)]
125125
fn add_usize(&self, n: usize) -> Option<Self> {
126-
match <$unsigned>::private_try_from(n) {
126+
match <$unsigned>::try_from(n) {
127127
Ok(n_as_unsigned) => {
128128
// Wrapping in unsigned space handles cases like
129129
// `-120_i8.add_usize(200) == Some(80_i8)`,
@@ -461,74 +461,3 @@ impl<A: Step> DoubleEndedIterator for ops::RangeInclusive<A> {
461461

462462
#[stable(feature = "fused", since = "1.26.0")]
463463
impl<A: Step> FusedIterator for ops::RangeInclusive<A> {}
464-
465-
/// Compensate removal of some impls per
466-
/// https://github.com/rust-lang/rust/pull/49305#issuecomment-376293243
467-
trait PrivateTryFromUsize: Sized {
468-
fn private_try_from(n: usize) -> Result<Self, ()>;
469-
}
470-
471-
impl<T> PrivateTryFromUsize for T where T: TryFrom<usize> {
472-
#[inline]
473-
fn private_try_from(n: usize) -> Result<Self, ()> {
474-
T::try_from(n).map_err(|_| ())
475-
}
476-
}
477-
478-
// no possible bounds violation
479-
macro_rules! try_from_unbounded {
480-
($($target:ty),*) => {$(
481-
impl PrivateTryFromUsize for $target {
482-
#[inline]
483-
fn private_try_from(value: usize) -> Result<Self, ()> {
484-
Ok(value as $target)
485-
}
486-
}
487-
)*}
488-
}
489-
490-
// unsigned to signed (only positive bound)
491-
#[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))]
492-
macro_rules! try_from_upper_bounded {
493-
($($target:ty),*) => {$(
494-
impl PrivateTryFromUsize for $target {
495-
#[inline]
496-
fn private_try_from(u: usize) -> Result<$target, ()> {
497-
if u > (<$target>::max_value() as usize) {
498-
Err(())
499-
} else {
500-
Ok(u as $target)
501-
}
502-
}
503-
}
504-
)*}
505-
}
506-
507-
508-
#[cfg(target_pointer_width = "16")]
509-
mod ptr_try_from_impls {
510-
use super::PrivateTryFromUsize;
511-
512-
try_from_unbounded!(u16, u32, u64, u128);
513-
try_from_unbounded!(i32, i64, i128);
514-
}
515-
516-
#[cfg(target_pointer_width = "32")]
517-
mod ptr_try_from_impls {
518-
use super::PrivateTryFromUsize;
519-
520-
try_from_upper_bounded!(u16);
521-
try_from_unbounded!(u32, u64, u128);
522-
try_from_upper_bounded!(i32);
523-
try_from_unbounded!(i64, i128);
524-
}
525-
526-
#[cfg(target_pointer_width = "64")]
527-
mod ptr_try_from_impls {
528-
use super::PrivateTryFromUsize;
529-
530-
try_from_upper_bounded!(u16, u32);
531-
try_from_unbounded!(u64, u128);
532-
try_from_upper_bounded!(i32, i64);
533-
try_from_unbounded!(i128);
534-
}

src/libcore/num/mod.rs

+60-10
Original file line numberDiff line numberDiff line change
@@ -4213,6 +4213,21 @@ impl From<!> for TryFromIntError {
42134213
}
42144214
}
42154215

4216+
// no possible bounds violation
4217+
macro_rules! try_from_unbounded {
4218+
($source:ty, $($target:ty),*) => {$(
4219+
#[unstable(feature = "try_from", issue = "33417")]
4220+
impl TryFrom<$source> for $target {
4221+
type Error = TryFromIntError;
4222+
4223+
#[inline]
4224+
fn try_from(value: $source) -> Result<Self, Self::Error> {
4225+
Ok(value as $target)
4226+
}
4227+
}
4228+
)*}
4229+
}
4230+
42164231
// only negative bounds
42174232
macro_rules! try_from_lower_bounded {
42184233
($source:ty, $($target:ty),*) => {$(
@@ -4311,44 +4326,79 @@ try_from_both_bounded!(i128, u64, u32, u16, u8);
43114326
try_from_upper_bounded!(usize, isize);
43124327
try_from_lower_bounded!(isize, usize);
43134328

4314-
try_from_upper_bounded!(usize, u8);
4315-
try_from_upper_bounded!(usize, i8, i16);
4316-
try_from_both_bounded!(isize, u8);
4317-
try_from_both_bounded!(isize, i8);
4318-
43194329
#[cfg(target_pointer_width = "16")]
43204330
mod ptr_try_from_impls {
43214331
use super::TryFromIntError;
43224332
use convert::TryFrom;
43234333

4324-
// Fallible across platfoms, only implementation differs
4334+
try_from_upper_bounded!(usize, u8);
4335+
try_from_unbounded!(usize, u16, u32, u64, u128);
4336+
try_from_upper_bounded!(usize, i8, i16);
4337+
try_from_unbounded!(usize, i32, i64, i128);
4338+
4339+
try_from_both_bounded!(isize, u8);
43254340
try_from_lower_bounded!(isize, u16, u32, u64, u128);
4341+
try_from_both_bounded!(isize, i8);
4342+
try_from_unbounded!(isize, i16, i32, i64, i128);
4343+
4344+
rev!(try_from_upper_bounded, usize, u32, u64, u128);
43264345
rev!(try_from_lower_bounded, usize, i8, i16);
43274346
rev!(try_from_both_bounded, usize, i32, i64, i128);
4347+
4348+
rev!(try_from_upper_bounded, isize, u16, u32, u64, u128);
4349+
rev!(try_from_both_bounded, isize, i32, i64, i128);
43284350
}
43294351

43304352
#[cfg(target_pointer_width = "32")]
43314353
mod ptr_try_from_impls {
43324354
use super::TryFromIntError;
43334355
use convert::TryFrom;
43344356

4335-
// Fallible across platfoms, only implementation differs
4336-
try_from_both_bounded!(isize, u16);
4357+
try_from_upper_bounded!(usize, u8, u16);
4358+
try_from_unbounded!(usize, u32, u64, u128);
4359+
try_from_upper_bounded!(usize, i8, i16, i32);
4360+
try_from_unbounded!(usize, i64, i128);
4361+
4362+
try_from_both_bounded!(isize, u8, u16);
43374363
try_from_lower_bounded!(isize, u32, u64, u128);
4364+
try_from_both_bounded!(isize, i8, i16);
4365+
try_from_unbounded!(isize, i32, i64, i128);
4366+
4367+
rev!(try_from_unbounded, usize, u32);
4368+
rev!(try_from_upper_bounded, usize, u64, u128);
43384369
rev!(try_from_lower_bounded, usize, i8, i16, i32);
43394370
rev!(try_from_both_bounded, usize, i64, i128);
4371+
4372+
rev!(try_from_unbounded, isize, u16);
4373+
rev!(try_from_upper_bounded, isize, u32, u64, u128);
4374+
rev!(try_from_unbounded, isize, i32);
4375+
rev!(try_from_both_bounded, isize, i64, i128);
43404376
}
43414377

43424378
#[cfg(target_pointer_width = "64")]
43434379
mod ptr_try_from_impls {
43444380
use super::TryFromIntError;
43454381
use convert::TryFrom;
43464382

4347-
// Fallible across platfoms, only implementation differs
4348-
try_from_both_bounded!(isize, u16, u32);
4383+
try_from_upper_bounded!(usize, u8, u16, u32);
4384+
try_from_unbounded!(usize, u64, u128);
4385+
try_from_upper_bounded!(usize, i8, i16, i32, i64);
4386+
try_from_unbounded!(usize, i128);
4387+
4388+
try_from_both_bounded!(isize, u8, u16, u32);
43494389
try_from_lower_bounded!(isize, u64, u128);
4390+
try_from_both_bounded!(isize, i8, i16, i32);
4391+
try_from_unbounded!(isize, i64, i128);
4392+
4393+
rev!(try_from_unbounded, usize, u32, u64);
4394+
rev!(try_from_upper_bounded, usize, u128);
43504395
rev!(try_from_lower_bounded, usize, i8, i16, i32, i64);
43514396
rev!(try_from_both_bounded, usize, i128);
4397+
4398+
rev!(try_from_unbounded, isize, u16, u32);
4399+
rev!(try_from_upper_bounded, isize, u64, u128);
4400+
rev!(try_from_unbounded, isize, i32, i64);
4401+
rev!(try_from_both_bounded, isize, i128);
43524402
}
43534403

43544404
#[doc(hidden)]

src/libcore/tests/num/mod.rs

+127
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,15 @@ mod flt2dec;
3737
mod dec2flt;
3838
mod bignum;
3939

40+
41+
/// Adds the attribute to all items in the block.
42+
macro_rules! cfg_block {
43+
($(#[$attr:meta]{$($it:item)*})*) => {$($(
44+
#[$attr]
45+
$it
46+
)*)*}
47+
}
48+
4049
/// Groups items that assume the pointer width is either 16/32/64, and has to be altered if
4150
/// support for larger/smaller pointer widths are added in the future.
4251
macro_rules! assume_usize_width {
@@ -330,6 +339,42 @@ assume_usize_width! {
330339

331340
test_impl_try_from_always_ok! { test_try_u16usize, u16, usize }
332341
test_impl_try_from_always_ok! { test_try_i16isize, i16, isize }
342+
343+
test_impl_try_from_always_ok! { test_try_usizeu64, usize, u64 }
344+
test_impl_try_from_always_ok! { test_try_usizeu128, usize, u128 }
345+
test_impl_try_from_always_ok! { test_try_usizei128, usize, i128 }
346+
347+
test_impl_try_from_always_ok! { test_try_isizei64, isize, i64 }
348+
test_impl_try_from_always_ok! { test_try_isizei128, isize, i128 }
349+
350+
cfg_block!(
351+
#[cfg(target_pointer_width = "16")] {
352+
test_impl_try_from_always_ok! { test_try_usizeu16, usize, u16 }
353+
test_impl_try_from_always_ok! { test_try_isizei16, isize, i16 }
354+
test_impl_try_from_always_ok! { test_try_usizeu32, usize, u32 }
355+
test_impl_try_from_always_ok! { test_try_usizei32, usize, i32 }
356+
test_impl_try_from_always_ok! { test_try_isizei32, isize, i32 }
357+
test_impl_try_from_always_ok! { test_try_usizei64, usize, i64 }
358+
}
359+
360+
#[cfg(target_pointer_width = "32")] {
361+
test_impl_try_from_always_ok! { test_try_u16isize, u16, isize }
362+
test_impl_try_from_always_ok! { test_try_usizeu32, usize, u32 }
363+
test_impl_try_from_always_ok! { test_try_isizei32, isize, i32 }
364+
test_impl_try_from_always_ok! { test_try_u32usize, u32, usize }
365+
test_impl_try_from_always_ok! { test_try_i32isize, i32, isize }
366+
test_impl_try_from_always_ok! { test_try_usizei64, usize, i64 }
367+
}
368+
369+
#[cfg(target_pointer_width = "64")] {
370+
test_impl_try_from_always_ok! { test_try_u16isize, u16, isize }
371+
test_impl_try_from_always_ok! { test_try_u32usize, u32, usize }
372+
test_impl_try_from_always_ok! { test_try_u32isize, u32, isize }
373+
test_impl_try_from_always_ok! { test_try_i32isize, i32, isize }
374+
test_impl_try_from_always_ok! { test_try_u64usize, u64, usize }
375+
test_impl_try_from_always_ok! { test_try_i64isize, i64, isize }
376+
}
377+
);
333378
}
334379

335380
/// Conversions where max of $source can be represented as $target,
@@ -378,6 +423,24 @@ assume_usize_width! {
378423
test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_isizeu64, isize, u64 }
379424
test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_isizeu128, isize, u128 }
380425
test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_isizeusize, isize, usize }
426+
427+
cfg_block!(
428+
#[cfg(target_pointer_width = "16")] {
429+
test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_isizeu16, isize, u16 }
430+
test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_isizeu32, isize, u32 }
431+
}
432+
433+
#[cfg(target_pointer_width = "32")] {
434+
test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_isizeu32, isize, u32 }
435+
436+
test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i32usize, i32, usize }
437+
}
438+
439+
#[cfg(target_pointer_width = "64")] {
440+
test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i32usize, i32, usize }
441+
test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i64usize, i64, usize }
442+
}
443+
);
381444
}
382445

383446
/// Conversions where max of $source can not be represented as $target,
@@ -419,9 +482,29 @@ test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u128i64, u128, i64 }
419482
test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u128i128, u128, i128 }
420483

421484
assume_usize_width! {
485+
test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u64isize, u64, isize }
486+
test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u128isize, u128, isize }
487+
422488
test_impl_try_from_unsigned_to_signed_upper_err! { test_try_usizei8, usize, i8 }
423489
test_impl_try_from_unsigned_to_signed_upper_err! { test_try_usizei16, usize, i16 }
424490
test_impl_try_from_unsigned_to_signed_upper_err! { test_try_usizeisize, usize, isize }
491+
492+
cfg_block!(
493+
#[cfg(target_pointer_width = "16")] {
494+
test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u16isize, u16, isize }
495+
test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u32isize, u32, isize }
496+
}
497+
498+
#[cfg(target_pointer_width = "32")] {
499+
test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u32isize, u32, isize }
500+
test_impl_try_from_unsigned_to_signed_upper_err! { test_try_usizei32, usize, i32 }
501+
}
502+
503+
#[cfg(target_pointer_width = "64")] {
504+
test_impl_try_from_unsigned_to_signed_upper_err! { test_try_usizei32, usize, i32 }
505+
test_impl_try_from_unsigned_to_signed_upper_err! { test_try_usizei64, usize, i64 }
506+
}
507+
);
425508
}
426509

427510
/// Conversions where min/max of $source can not be represented as $target.
@@ -481,6 +564,34 @@ test_impl_try_from_same_sign_err! { test_try_i128i64, i128, i64 }
481564

482565
assume_usize_width! {
483566
test_impl_try_from_same_sign_err! { test_try_usizeu8, usize, u8 }
567+
test_impl_try_from_same_sign_err! { test_try_u128usize, u128, usize }
568+
test_impl_try_from_same_sign_err! { test_try_i128isize, i128, isize }
569+
570+
cfg_block!(
571+
#[cfg(target_pointer_width = "16")] {
572+
test_impl_try_from_same_sign_err! { test_try_u32usize, u32, usize }
573+
test_impl_try_from_same_sign_err! { test_try_u64usize, u64, usize }
574+
575+
test_impl_try_from_same_sign_err! { test_try_i32isize, i32, isize }
576+
test_impl_try_from_same_sign_err! { test_try_i64isize, i64, isize }
577+
}
578+
579+
#[cfg(target_pointer_width = "32")] {
580+
test_impl_try_from_same_sign_err! { test_try_u64usize, u64, usize }
581+
test_impl_try_from_same_sign_err! { test_try_usizeu16, usize, u16 }
582+
583+
test_impl_try_from_same_sign_err! { test_try_i64isize, i64, isize }
584+
test_impl_try_from_same_sign_err! { test_try_isizei16, isize, i16 }
585+
}
586+
587+
#[cfg(target_pointer_width = "64")] {
588+
test_impl_try_from_same_sign_err! { test_try_usizeu16, usize, u16 }
589+
test_impl_try_from_same_sign_err! { test_try_usizeu32, usize, u32 }
590+
591+
test_impl_try_from_same_sign_err! { test_try_isizei16, isize, i16 }
592+
test_impl_try_from_same_sign_err! { test_try_isizei32, isize, i32 }
593+
}
594+
);
484595
}
485596

486597
/// Conversions where neither the min nor the max of $source can be represented by
@@ -525,6 +636,22 @@ test_impl_try_from_signed_to_unsigned_err! { test_try_i128u64, i128, u64 }
525636
assume_usize_width! {
526637
test_impl_try_from_signed_to_unsigned_err! { test_try_isizeu8, isize, u8 }
527638
test_impl_try_from_signed_to_unsigned_err! { test_try_i128usize, i128, usize }
639+
640+
cfg_block! {
641+
#[cfg(target_pointer_width = "16")] {
642+
test_impl_try_from_signed_to_unsigned_err! { test_try_i32usize, i32, usize }
643+
test_impl_try_from_signed_to_unsigned_err! { test_try_i64usize, i64, usize }
644+
}
645+
#[cfg(target_pointer_width = "32")] {
646+
test_impl_try_from_signed_to_unsigned_err! { test_try_i64usize, i64, usize }
647+
648+
test_impl_try_from_signed_to_unsigned_err! { test_try_isizeu16, isize, u16 }
649+
}
650+
#[cfg(target_pointer_width = "64")] {
651+
test_impl_try_from_signed_to_unsigned_err! { test_try_isizeu16, isize, u16 }
652+
test_impl_try_from_signed_to_unsigned_err! { test_try_isizeu32, isize, u32 }
653+
}
654+
}
528655
}
529656

530657
macro_rules! test_float {

0 commit comments

Comments
 (0)