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

consider removing the fallback to int for integer inference #6023

Closed
thestinger opened this issue Apr 23, 2013 · 21 comments
Closed

consider removing the fallback to int for integer inference #6023

thestinger opened this issue Apr 23, 2013 · 21 comments
Labels
B-RFC-approved Blocker: Approved by a merged RFC but not yet implemented.
Milestone

Comments

@thestinger
Copy link
Contributor

I find it really easy to accidentally end up using int. It can be inferred as uint based on a function call, but if you delete a line of code you're back to int and possibly a bug. I don't think it's that much pain to tag one of them with i.

If #4169 is implemented, different strategies for overflow (expand to big integer, wrap, trap with a condition) can just be implemented as first-class library types. Haskell has a fallback to a big integer, but at least that's much less likely to cause a bug.

@pcwalton
Copy link
Contributor

I think this might be pretty annoying; e.g. println(1.to_str());

@pcwalton
Copy link
Contributor

Nominated for backwards-compatible milestone, but I suggest WONTFIX

@thestinger
Copy link
Contributor Author

I agree it would be annoying if you actually want int, but I think it would prevent a lot of mistakes. There are many counters that should really be unsigned, but Rust defaults them to int.

Especially if we end up with generic integers like Haskell, this would make overflow checked integers and big integers as first-class as the built-ins (excluding constant expressions).

@graydon
Copy link
Contributor

graydon commented May 23, 2013

accepted for backwards-compatible milestone

@catamorphism
Copy link
Contributor

Visiting for triage.

@brson
Copy link
Contributor

brson commented Sep 26, 2013

cc #4704

@nikomatsakis
Copy link
Contributor

I personally favor not guessing, or at least trying it

@1fish2
Copy link

1fish2 commented Oct 19, 2013

There are many counters that should really be unsigned ...

Using unsigned values for such purposes can cause bugs, e.g. when a loop counts down past 0. This is why the Google C++ Style Guide http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml?showone=Integer_Types#Integer_Types says:

... do not use unsigned types to say a number will never be negative. Instead, use assertions for this.
... Consider:

for (unsigned int i = foo.Length()-1; i >= 0; --i) ...

@huonw
Copy link
Member

huonw commented Oct 19, 2013

@1fish2 note that our range and range_step iterators handle counting down to zero like that correctly, even for unsigned types, so the advice for Rust is "writing your own counter loops is bad", not "using unsigned types is bad". (Admittedly there are other situations in which one should prefer a signed type to an unsigned type to avoid bugs, but I'm sure that loops are the most common one in C/C++.)

for i in range(0u, 10).invert() { print!("{} ", i) }

prints

9 8 7 6 5 4 3 2 1 0 

@1fish2
Copy link

1fish2 commented Oct 19, 2013

Agreed (esp. about writing your own loops). Perhaps a better way to put it is doing unsigned math doesn't save you from thinking about negative values, it just underflows them to large values.

Does range() always iterate downwards? I don't see any doc on that, e.g. http://static.rust-lang.org/doc/master/std/iter/fn.range.html

@thestinger
Copy link
Contributor Author

@1fish2: he was missing the invert call in the original snippet

@thestinger
Copy link
Contributor Author

@1fish2: well, I think we can agree that a pointer-sized integer with wrapping on overflow is a bad default for high-level application code whether or not we agree on the value of unsigned integers at API boundaries :)

@denispir
Copy link

I do agree int as default type is a bad point. My preferred solution is the standard type to be either uint or int depending on whether a literal value is signed or not. Meaning, one would write let n = +1; to get a signed int.

The solution of adding an explicit type suffix 'u' or 'i' (with or without precision of size) is also good and acceptable in my view. Then, seems an assignment without type name nor suffix should be a compile error?

@emberian
Copy link
Member

@denispir we already have said type suffixes.

I really want generic numeric literals. Neither int or uint are the right choice, usually, and when they are, type inference can take care of it (only need to specify the type once, somewhere).

@brson
Copy link
Contributor

brson commented Apr 15, 2014

Nominating for closing. I don't see a lot of momentum to change this and it's a huge change. Does anybody think we can or will?

@thestinger
Copy link
Contributor Author

I still think this is a language misfeature and will lead to real bugs. I expect that the process of adding i suffixes where necessary will reveal many bugs where a pointer-size integer was not appropriate, and was simply hidden by the compiler's guess of int.

In my opinion having generic integer literals is a mistake if they can unexpectedly fall back to int. Type inference is impossible to rely on when you can't trust it to give you an error if it is unable to infer the correct meaning. You have to add redundant u, u32, etc. suffixes instead because it simply can't be relied upon to do the right thing or report an error.

@nikomatsakis
Copy link
Contributor

I'd like to try 

Niko

-------- Original message --------
From: Brian Anderson [email protected]
Date:04/15/2014 15:31 (GMT-05:00)
To: mozilla/rust [email protected]
Cc: Niko Matsakis [email protected]
Subject: Re: [rust] consider removing the fallback to int for integer
inference (#6023)

Nominating for closing. I don't see a lot of momentum to change this and it's a huge change. Does anybody think we can or will?


Reply to this email directly or view it on GitHub.

@pnkfelix
Copy link
Member

Leaving on 1.0 milestone for now. Niko has been tasked with gathering statistics so that we can better understand the impact of making this change (or not doing so).

@nikomatsakis
Copy link
Contributor

Did some investigation: https://gist.github.com/nikomatsakis/11179747

It doesn't look like this would cause much trouble.

@emberian
Copy link
Member

As for range I think it's fine to have to write 0u or whatever. I usually
do anyway (because I'm not working with ints) and it's not that burdensome.

On Tue, Apr 22, 2014 at 5:55 PM, Niko Matsakis [email protected]:

Did some investigation: https://gist.github.com/nikomatsakis/11179747

It doesn't look like this would cause much trouble.


Reply to this email directly or view it on GitHubhttps://github.com//issues/6023#issuecomment-41100849
.

http://octayn.net/

@alexcrichton
Copy link
Member

The corresponding RFC for this issue has been approved: rust-lang/rfcs#115

nikomatsakis added a commit to pcwalton/rust that referenced this issue Jun 24, 2014
This breaks a fair amount of code. The typical patterns are:

* `for _ in range(0, 10)`: change to `for _ in range(0u, 10)`;

* `println!("{}", 3)`: change to `println!("{}", 3i)`;

* `[1, 2, 3].len()`: change to `[1i, 2, 3].len()`.

RFC rust-lang#30. Closes rust-lang#6023.

[breaking-change]
flip1995 pushed a commit to flip1995/rust that referenced this issue Sep 10, 2020
link to the Box docs in related lint documentation.

changelog: link to the box docs in lint docs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
B-RFC-approved Blocker: Approved by a merged RFC but not yet implemented.
Projects
None yet
Development

No branches or pull requests