5
5
# Summary
6
6
7
7
Restore the integer inference fallback that was removed. Integer
8
- literals whose type is unconstrained will default to ` int ` , as before.
8
+ literals whose type is unconstrained will default to ` i32 ` , unlike the
9
+ previous fallback to ` int ` .
9
10
Floating point literals will default to ` f64 ` .
10
11
11
12
# Motivation
@@ -102,7 +103,7 @@ To our knowledge, there has not been a single bug exposed by removing
102
103
the fallback to the ` int ` type. Moreover, such bugs seem to be
103
104
extremely unlikely.
104
105
105
- The primary reason for this is that, in production code, the ` int `
106
+ The primary reason for this is that, in production code, the ` i32 `
106
107
fallback is very rarely used. In a sense, the same [ measurements] [ m ]
107
108
that were used to justify removing the ` int ` fallback also justify
108
109
keeping it. As the measurements showed, the vast, vast majority of
@@ -111,25 +112,56 @@ used to print out and do assertions with. Specifically, any integer
111
112
that is passed as a parameter, returned from a function, or stored in
112
113
a struct or array, must wind up with a specific type.
113
114
114
- Another secondary reason is that the lint which checks that literals
115
- are suitable for their assigned type will catch cases where very large
116
- literals were used that overflow the ` int ` type (for example,
117
- ` INT_MAX ` +1). (Note that the overflow lint constraints ` int ` literals
118
- to 32 bits for better portability.)
119
-
120
- In almost all of common cases we described above, there exists * some*
121
- large constant representing a bound. If this constant exceeds the
122
- range of the chosen fallback type, then a ` type_overflow ` lint warning
123
- would be triggered. For example, in the accumulator, if the
124
- accumulated result ` i ` is compared using a call like `assert_eq(i,
125
- 22)` , then the constant ` 22` will be linted. Similarly, when invoking
126
- range with unconstrained arguments, the arguments to range are linted.
127
- And so on.
128
-
129
- The only common case where the lint does not apply is when an
130
- accumulator result is only being printed to the screen or otherwise
131
- consumed by some generic function which never stores it to memory.
132
- This is a very narrow case.
115
+ ## Rationale for the choice of defaulting to ` i32 `
116
+
117
+ In contrast to the first revision of the RFC, the fallback type
118
+ suggested is ` i32 ` . This is justified by a case analysis which showed
119
+ that there does not exist a compelling reason for having a signed
120
+ pointer-sized integer type as the default.
121
+
122
+ There are reasons * for* using ` i32 ` instead: It's familiar to programmers
123
+ from the C programming language (where the default int type is 32-bit in
124
+ the major calling conventions), it's faster than 64-bit integers in
125
+ arithmetic today, and is superior in memory usage while still providing
126
+ a reasonable range of possible values.
127
+
128
+ To expand on the perfomance argument: ` i32 ` obviously uses half of the
129
+ memory of ` i64 ` meaning half the memory bandwidth used, half as much
130
+ cache consumption and twice as much vectorization – additionally
131
+ arithmetic (like multiplication and division) is faster on some of the
132
+ modern CPUs.
133
+
134
+ ## Case analysis
135
+
136
+ This is an analysis of cases where ` int ` inference might be thought of
137
+ as useful:
138
+
139
+ ** Indexing into an array with unconstrained integer literal:**
140
+
141
+ ```
142
+ let array = [0u8, 1, 2, 3];
143
+ let index = 3;
144
+ array[index]
145
+ ```
146
+
147
+ In this case, ` index ` is already automatically inferred to be a ` uint ` .
148
+
149
+ ** Using a default integer for tests, tutorials, etc.:** Examples of this
150
+ include "The Guide", the Rust API docs and the Rust standard library
151
+ unit tests. This is better served by a smaller, faster and platform
152
+ independent type as default.
153
+
154
+ ** Using an integer for an upper bound or for simply printing it:** This
155
+ is also served very well by ` i32 ` .
156
+
157
+ ** Counting of loop iterations:** This is a part where ` int ` is as badly
158
+ suited as ` i32 ` , so at least the move to ` i32 ` doesn't create new
159
+ hazards (note that the number of elements of a vector might not
160
+ necessarily fit into an ` int ` ).
161
+
162
+ In addition to all the points above, having a platform-independent type
163
+ obviously results in less differences between the platforms in which the
164
+ programmer "doesn't care" about the integer type they are using.
133
165
134
166
## Future-proofing for overloaded literals
135
167
@@ -141,12 +173,12 @@ be necessary for those literals to have some sort of fallback type.
141
173
142
174
# Detailed design
143
175
144
- Integeral literals are currently type-checked by creating a special
176
+ Integral literals are currently type-checked by creating a special
145
177
class of type variable. These variables are subject to unification as
146
178
normal, but can only unify with integral types. This RFC proposes
147
179
that, at the end of type inference, when all constraints are known, we
148
180
will identify all integral type variables that have not yet been bound
149
- to anything and bind them to ` int ` . Similarly, floating point literals
181
+ to anything and bind them to ` i32 ` . Similarly, floating point literals
150
182
will fallback to ` f64 ` .
151
183
152
184
For those who wish to be very careful about which integral types they
@@ -156,21 +188,23 @@ integer or floating point literal is unconstrained.
156
188
157
189
# Downsides
158
190
159
- Although we give a detailed argument for why bugs are unlikely, it is
160
- nonetheless possible that this choice will lead to bugs in some code,
161
- since another choice (most likely ` uint ` ) may have been more suitable.
191
+ Although there seems to be little motivation for ` int ` to be the
192
+ default, there might be use cases where ` int ` is a more correct fallback
193
+ than ` i32 ` .
194
+
195
+ Additionally, it might seem weird to some that ` i32 ` is a default, when
196
+ ` int ` looks like the default from other languages. The name of ` int `
197
+ however is not in the scope of this RFC.
162
198
163
- Given that the size of ` int ` is platform dependent, it is possible
164
- that a porting hazard is created. This is mitigated by the fact that
165
- the ` type_overflow ` lint constraints ` int ` literals to 32 bits.
166
199
167
200
# Alternatives
168
201
169
202
- ** No fallback.** Status quo.
170
203
171
204
- ** Fallback to something else.** We could potentially fallback to
172
- ` i32 ` or some other integral type rather than ` int ` .
173
-
205
+ ` int ` like the original RFC suggested or some other integral type
206
+ rather than ` i32 ` .
207
+
174
208
- ** Fallback in a more narrow range of cases.** We could attempt to
175
209
identify integers that are "only printed" or "only compared". There
176
210
is no concrete proposal in this direction and it seems to lead to an
@@ -182,5 +216,10 @@ the `type_overflow` lint constraints `int` literals to 32 bits.
182
216
like ` range(0, 10) ` to work even without integral fallback, because
183
217
the ` range ` function itself could specify a fallback type. However,
184
218
this does not help with many other examples.
219
+
220
+ # History
221
+
222
+ 2014-11-07: Changed the suggested fallback from ` int ` to ` i32 ` , add
223
+ rationale.
185
224
186
225
[ m ] : https://gist.github.com/nikomatsakis/11179747
0 commit comments