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

RFC for removing integer inference fallback #115

Merged
merged 2 commits into from
Jun 18, 2014
Merged
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
75 changes: 75 additions & 0 deletions active/0000-rm-integer-fallback.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
- Start Date: 2014-06-11
- RFC PR #: (leave this empty)
- Rust Issue #: 6023

# Summary

Currently we use inference to find the current type of
otherwise-unannotated integer literals, and when that fails the type
defaults to `int`. This is often felt to be potentially error-prone
behavior.

This proposal removes the integer inference fallback and strengthens
the types required for several language features that interact with
integer inference.

# Motivation

With the integer fallback, small changes to code can change the
inferred type in unexpected ways. It's not clear how big a problem
this is, but previous experiments[1] indicate that removing
the fallback has a relatively small impact on existing code,
so it's reasonable to back off of this feature in favor of more
strict typing.

See also https://github.com/mozilla/rust/issues/6023.

[1]: https://gist.github.com/nikomatsakis/11179747

# Detailed design

The primary change here is that, when integer type inference fails,
the compiler will emit an error instead of assigning the value the
type `int`.

This change alone will cause a fair bit of existing code to be
unable to type check because of lack of constraints. To add more
constraints and increase likelihood of unification, we 'tighten'
up what kinds of integers are required in some situations:

* Array repeat counts must be uint (`[expr, .. count]`)
* << and >> require uint when shifting integral types

Finally, inference for `as` will be modified to track the types
a value is being cast *to* for cases where the value being cast
is unconstrained, like `0 as u8`.

Treatment of enum discriminants will need to change:

```
enum Color { Red = 0, Green = 1, Blue = 2 }
```

Currently, an unsuffixed integer defaults to `int`. Instead, we will
only require enum descriminants primitive integers of unspecified
type; assigning an integer to an enum will behave as if casting from
from the type of the integer to an unsigned integer with the size of
the enum discriminant.

# Drawbacks

This will force users to type hint somewhat more often. In particular,
ranges of unsigned ints may need to be type-hinted:

```
for _ in range(0u, 10) { }

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps default type parameters could be dual-purposed to provide a fallback type for this case (see rust-lang/rust#13702). I.e. the signature of range would become:

pub fn range<A: Add<A, A> + PartialOrd + Clone + One = uint>(start: A, stop: A) -> Range<A>

although it wasn't clear to me if the original issue was motivated by this very function defaulting to int too often.

```

# Alternatives

Do none of this.

# Unresolved questions

* If we're putting new restrictions on shift operators, should we
change the traits, or just make the primitives special?