Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement conversion traits for primitive integer types #28921

Merged
merged 1 commit into from Oct 15, 2015

Conversation

Projects
None yet
@petrochenkov
Copy link
Contributor

petrochenkov commented Oct 8, 2015

@petrochenkov petrochenkov force-pushed the petrochenkov:intconv branch from 48b66df to 47f0f2e Oct 9, 2015

impl_from! { u32, usize }
#[cfg(target_pointer_width = "64")]
impl_from! { u64, usize }
#[cfg(target_pointer_width = "16")]

This comment has been minimized.

@oli-obk

oli-obk Oct 9, 2015

Contributor

we have support for 16 bit?

This comment has been minimized.

@tbu-

tbu- Oct 9, 2015

Contributor

No, we don't.

This comment has been minimized.

@tbu-

This comment has been minimized.

Copy link
Contributor

tbu- commented Oct 9, 2015

Very cool. This makes it possible to get rid of lots of as casts for non-truncating casts.

@oli-obk

This comment has been minimized.

Copy link
Contributor

oli-obk commented Oct 9, 2015

Very cool. This makes it possible to get rid of lots of as casts for non-truncating casts.

this screams for a lint...

@petrochenkov

This comment has been minimized.

Copy link
Contributor Author

petrochenkov commented Oct 9, 2015

@oli-obk

this screams for a lint...

Yes, but not right now, because now we can write large + small as Large, but can't replace it with large + small.into() or large + small.into(): Large yet. Besides, the lint can give platform-dependent warnings (this is solved by cast() in the RFC linked above).

@japaric

This comment has been minimized.

Copy link
Member

japaric commented Oct 9, 2015

but can't replace it with large + small.into() or large + small.into(): Large yet.

But we can write large + Large::from(small) which is one character smaller than the type ascription version 😄.


Nice to see lossless int conversions land in std. I've been using my own From trait that does this + checked casts (return Option), but it would be nice to be able drop that dependency when I only need lossless int casts.

this screams for a lint...

I treat as the same as unsafe (i.e. must be audited) and try to minimize its use in my code; instead, I use lossless/checked usize::froms wherever possible. And, I usually do this by grepping my code for the as keyword because I'm too lazy to (learn how to) write a lint. So, I would very much welcome such a lint. (Then I can copy it and modify it for my needs 😈)

impl_from! { u32, u64 }
#[cfg(any(target_pointer_width = "64", target_pointer_width = "32"))]
impl_from! { u32, usize }
#[cfg(target_pointer_width = "64")]

This comment has been minimized.

@aturon

aturon Oct 9, 2015

Member

Hmm, I am a bit wary of taking this step: it makes it easy to silently/accidentally introduce arch-specific code. (Contrast this with the approach we took with OS-specific extensions, where you generally have to import a specific trait to "opt in" to platform specificity.)

cc @alexcrichton

This comment has been minimized.

@petrochenkov

petrochenkov Oct 9, 2015

Author Contributor

It was discussed in the RFC and tested on rustc Windows 64-bit / Linux 32-bit. Yes, porting to a new platform assumes changing some into into cast/as, but potential porting bugs are also uncovered.

This comment has been minimized.

@alexcrichton

alexcrichton Oct 9, 2015

Member

Yeah I would prefer to avoid usize and isize in these "always working" coercions for now. I'm not actually aware of any types which have some traits implemented on some platforms and not others, and that's a great boon for portability so it'd be nice to keep it that way!

This comment has been minimized.

@petrochenkov

petrochenkov Oct 9, 2015

Author Contributor

This is significant and important part of the RFC, it's motivated and tested in practice, I won't surrender it just like that. I'd argue that most of integer conversions actually involve usize.

Any comments from @japaric? Do your own conversion traits perform conversions to/from usize?

This comment has been minimized.

@petrochenkov

petrochenkov Oct 9, 2015

Author Contributor

Here's some old statistics: https://internals.rust-lang.org/t/the-operator-as-statistics-of-usage/1353
as usize is very popular, including indexing context v[a as usize].

This comment has been minimized.

@petrochenkov

petrochenkov Oct 9, 2015

Author Contributor

Too bad implemented trait methods can't be marked with a warning message attribute, a lint.
Something like "you use a method making you code non-portable between 32-bit and 64-bit".
If user isn't interested in this kind of portability (or the types are different on different platforms so the conversion is always lossless even if it would not be lossless if the types were the same, but the lint doesn't know that) he could explicitly silence the warning.

This comment has been minimized.

@petrochenkov

petrochenkov Oct 9, 2015

Author Contributor

Hmm, how do you think, if I write a specialized built-in portability lint for this, would it be a good idea? (This lint could detect other 32<->64 portability problems eventually).

This comment has been minimized.

@aturon

aturon Oct 9, 2015

Member

Linting sounds like a reasonable way to approach this problem, for sure; it's an idea that's been tossed around not just for this portability issue, but also to make things like implicit widening part of the language but allow people to "opt out" via a lint.

It'd be awesome if this infrastructure could be used in e.g. the stability lint, which currently is not sensitive to the stability of trait impls. I'm not sure how much work that would be involved.

This comment has been minimized.

@petrochenkov

petrochenkov Oct 9, 2015

Author Contributor

Okay, so I'm going to comment out the impls problematic for 32<->64 portability for now to merge this PR and will return later with a lint.

This comment has been minimized.

@petrochenkov

petrochenkov Oct 9, 2015

Author Contributor

@aturon
Done.

@@ -1486,7 +1486,7 @@ shr_assign_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize }
#[lang = "index"]
#[rustc_on_unimplemented = "the type `{Self}` cannot be indexed by `{Idx}`"]
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Index<Idx: ?Sized> {
pub trait Index<Idx: ?Sized = usize> {

This comment has been minimized.

@aturon

aturon Oct 9, 2015

Member

Can you elaborate on the necessity of this step? I'm slightly wary of changing the global default here, and in principle inference should be able to depend on the impls provided for a particular type.

This comment has been minimized.

@petrochenkov

petrochenkov Oct 9, 2015

Author Contributor

Type inference is not good enough to infer

let a: u16 = 10;
let b = vector[a.into()];

But... I've just tested it and it turns out the inference is not good enough to infer it even with trait Index<Idx: ?Sized = usize> and #![feature(default_type_parameter_fallback)]! So, this change can be reverted for now.

This comment has been minimized.

@petrochenkov

petrochenkov Oct 9, 2015

Author Contributor

Reverted Index changes.

@aturon

This comment has been minimized.

Copy link
Member

aturon commented Oct 9, 2015

cc @rust-lang/libs When we discussed this RFC briefly this week, we didn't talk in detail about how usize should be treated. I'd appreciate additional input on this aspect of the design.

@petrochenkov petrochenkov force-pushed the petrochenkov:intconv branch from 47f0f2e to 5ece8ce Oct 9, 2015

@tbu-

This comment has been minimized.

Copy link
Contributor

tbu- commented Oct 11, 2015

With the controversial parts removed, this should be fine to land, right?

@aturon

This comment has been minimized.

Copy link
Member

aturon commented Oct 13, 2015

@tbu- Most likely, though I would like to get broader feedback on the 32bit -> usize conversion. I'm going to flag this for a libs team decision at the meeting tomorrow.

@Gankro

This comment has been minimized.

Copy link
Contributor

Gankro commented Oct 13, 2015

(fwiw we've long held that 16-bit isn't supported. I can't recall any specific past decisions that legitimately preclude it, but I feel like they exist)

@alexcrichton

This comment has been minimized.

Copy link
Member

alexcrichton commented Oct 15, 2015

The libs team talked about this today and our conclusion was that at this time we'd like to avoid any #[cfg] impl blocks entirely. Along those lines we also think that implementations for isize and usize should be avoided at this time. We can always add them later, but it's less obvious that we want to add them right now.

It sounded like one of the main use cases of From and Into with usize/isize were around indexing, but @sfackler brought up a good point where we could certainly implement Index<u64> for vectors and slices today, it's just have extra checks on 32-bit platforms to test if it's out of bounds.

@petrochenkov could you perhaps elaborate a bit on the use cases you're thinking of for isize and usize? Perhaps they can fit into patterns like Index above with slices?

@petrochenkov petrochenkov force-pushed the petrochenkov:intconv branch from f8cac27 to 6f3e84d Oct 15, 2015

@petrochenkov

This comment has been minimized.

Copy link
Contributor Author

petrochenkov commented Oct 15, 2015

@alexcrichton
Updated with completely platform independent version.

could you perhaps elaborate a bit on the use cases you're thinking of for isize and usize?

We can always argue later, but it's less obvious that we want to do it right now

we could certainly implement Index<u64> for vectors and slices

Please, no

@alexcrichton

This comment has been minimized.

Copy link
Member

alexcrichton commented Oct 15, 2015

@bors: r+ 6f3e84d

Thanks!

bors added a commit that referenced this pull request Oct 15, 2015

@bors

This comment has been minimized.

Copy link
Contributor

bors commented Oct 15, 2015

⌛️ Testing commit 6f3e84d with merge fa9a421...

@bors bors merged commit 6f3e84d into rust-lang:master Oct 15, 2015

1 of 2 checks passed

continuous-integration/travis-ci/pr The Travis CI build is in progress
Details
homu Test successful
Details
@briansmith

This comment has been minimized.

Copy link

briansmith commented on src/libcore/num/mod.rs in 6f3e84d Oct 20, 2015

NIT: I suggest ending these two sentences with a period.

More substantially, it would be nice to document more clearly/precisely what the portability concerns are. Is the goal to support platforms where usize and isize are only 8 bits? 16 bits? Or is there some other issue?

This comment has been minimized.

Copy link
Owner Author

petrochenkov replied Oct 20, 2015

Personally, I have no concerns, besides maybe a lint for 32<->64 portability. According to rust-lang#28921 (comment) libs team has some vague concerns, not clearly articulated, so it's probably not my responsibility to document them.

@briansmith

This comment has been minimized.

Copy link

briansmith commented Oct 20, 2015

@petrochenkov could you perhaps elaborate a bit on the use cases you're thinking of for isize and usize? Perhaps they can fit into patterns like Index above with slices?

I am not @petrochenkov. But, in some cases in my code I have static size values of type u8 or u16 (to keep structures small) that I later need to do usize arithmetic and/or indexing on. Therefore, it would be very useful to have u8 and u16 implicitly convertible to usize.

fwiw we've long held that 16-bit isn't supported

If so, could we please add the u16 -> usize/isize, u32 -> usize, and i32 -> isize conversions that were not added?

@briansmith

This comment has been minimized.

Copy link

briansmith commented Oct 22, 2015

If so, could we please add the u16 -> usize/isize, u32 -> usize, and i32 -> isize conversions that were not added?

My PR #29220 adds conversions from u16 to usize, i16 to isize, and u8 to isize. I did not add any conversions from i32 or u32 because there actually is work underway to port Rust to AVR, which uses a 16-bit address space; see https://internals.rust-lang.org/t/adding-16-bit-pointer-support/2484.

@briansmith

This comment has been minimized.

Copy link

briansmith commented Oct 22, 2015

we could certainly implement Index for vectors and slices
Please, no

I agree. In particular, that shouldn't be added if it means having a runtime check for 32-bit-and-smaller platforms.

@malbarbo

This comment has been minimized.

Copy link
Contributor

malbarbo commented on src/libcore/num/mod.rs in 6f3e84d Oct 29, 2015

What are the concerns about u16 -> usize and u32 -> usize? Are these conversions always save? The smallest size of usize is u32?

bors added a commit that referenced this pull request Oct 29, 2015

Auto merge of #29129 - cuviper:impl-from-for-floats, r=alexcrichton
This is a spiritual successor to #28921, completing the "upcast" idea from rust-num/num#97.

@petrochenkov petrochenkov deleted the petrochenkov:intconv branch Nov 22, 2015

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.