From 2326e0bb35f428483b2db9085386d013a75a8be1 Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Fri, 7 Nov 2014 02:44:06 +0100 Subject: [PATCH 1/6] Change integer fallback RFC to suggest `i32` instead of `int`. --- text/0212-restore-int-fallback.md | 59 +++++++++++++++---------------- text/0401-coercions.md | 0 2 files changed, 28 insertions(+), 31 deletions(-) mode change 100755 => 100644 text/0401-coercions.md diff --git a/text/0212-restore-int-fallback.md b/text/0212-restore-int-fallback.md index 55b389bc6af..9f142ce6db7 100644 --- a/text/0212-restore-int-fallback.md +++ b/text/0212-restore-int-fallback.md @@ -5,7 +5,8 @@ # Summary Restore the integer inference fallback that was removed. Integer -literals whose type is unconstrained will default to `int`, as before. +literals whose type is unconstrained will default to `i32`, unlike +before when it defaulted to `int`. Floating point literals will default to `f64`. # Motivation @@ -102,7 +103,7 @@ To our knowledge, there has not been a single bug exposed by removing the fallback to the `int` type. Moreover, such bugs seem to be extremely unlikely. -The primary reason for this is that, in production code, the `int` +The primary reason for this is that, in production code, the `i32` fallback is very rarely used. In a sense, the same [measurements][m] that were used to justify removing the `int` fallback also justify keeping it. As the measurements showed, the vast, vast majority of @@ -111,25 +112,18 @@ used to print out and do assertions with. Specifically, any integer that is passed as a parameter, returned from a function, or stored in a struct or array, must wind up with a specific type. -Another secondary reason is that the lint which checks that literals -are suitable for their assigned type will catch cases where very large -literals were used that overflow the `int` type (for example, -`INT_MAX`+1). (Note that the overflow lint constraints `int` literals -to 32 bits for better portability.) - -In almost all of common cases we described above, there exists *some* -large constant representing a bound. If this constant exceeds the -range of the chosen fallback type, then a `type_overflow` lint warning -would be triggered. For example, in the accumulator, if the -accumulated result `i` is compared using a call like `assert_eq(i, -22)`, then the constant `22` will be linted. Similarly, when invoking -range with unconstrained arguments, the arguments to range are linted. -And so on. - -The only common case where the lint does not apply is when an -accumulator result is only being printed to the screen or otherwise -consumed by some generic function which never stores it to memory. -This is a very narrow case. +## Rationale for the choice of defaulting to `i32` + +Unlike in the first revision of the RFC, the fallback type suggested is +`i32`. This is, for one, to that a case analysis showed that there does +not exist a compelling reason for having a signed pointer-sized integer +type as the default. + +The reasons for using `i32` instead is that it's familiar to programmers +from the C programming language (where the default int type is 32-bit in +the major calling conventions), it's faster than 64-bit integers in +arithmetic today, and is superior in memory usage while still providing +a reasonable range of possible values. ## Future-proofing for overloaded literals @@ -141,12 +135,12 @@ be necessary for those literals to have some sort of fallback type. # Detailed design -Integeral literals are currently type-checked by creating a special +Integral literals are currently type-checked by creating a special class of type variable. These variables are subject to unification as normal, but can only unify with integral types. This RFC proposes that, at the end of type inference, when all constraints are known, we will identify all integral type variables that have not yet been bound -to anything and bind them to `int`. Similarly, floating point literals +to anything and bind them to `i32`. Similarly, floating point literals will fallback to `f64`. For those who wish to be very careful about which integral types they @@ -156,21 +150,19 @@ integer or floating point literal is unconstrained. # Downsides -Although we give a detailed argument for why bugs are unlikely, it is -nonetheless possible that this choice will lead to bugs in some code, -since another choice (most likely `uint`) may have been more suitable. +Although there seems to be little motivation for `int` to be the +default, there might be use cases where `int` is a more correct fallback +than `i32`. -Given that the size of `int` is platform dependent, it is possible -that a porting hazard is created. This is mitigated by the fact that -the `type_overflow` lint constraints `int` literals to 32 bits. # Alternatives - **No fallback.** Status quo. - **Fallback to something else.** We could potentially fallback to - `i32` or some other integral type rather than `int`. - + `int` like the original RFC suggested or some other integral type + rather than `i32`. + - **Fallback in a more narrow range of cases.** We could attempt to identify integers that are "only printed" or "only compared". There is no concrete proposal in this direction and it seems to lead to an @@ -182,5 +174,10 @@ the `type_overflow` lint constraints `int` literals to 32 bits. like `range(0, 10)` to work even without integral fallback, because the `range` function itself could specify a fallback type. However, this does not help with many other examples. + +# History + +2014-11-07: Changed the suggested fallback from `int` to `i32`, add +rationale. [m]: https://gist.github.com/nikomatsakis/11179747 diff --git a/text/0401-coercions.md b/text/0401-coercions.md old mode 100755 new mode 100644 From 2a2b6c17d2178411182ce06c653ea5bc99ee1c10 Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Fri, 7 Nov 2014 02:53:36 +0100 Subject: [PATCH 2/6] Int fallback restoration: Clarify the default name argument --- text/0212-restore-int-fallback.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/text/0212-restore-int-fallback.md b/text/0212-restore-int-fallback.md index 9f142ce6db7..e725073c940 100644 --- a/text/0212-restore-int-fallback.md +++ b/text/0212-restore-int-fallback.md @@ -154,6 +154,10 @@ Although there seems to be little motivation for `int` to be the default, there might be use cases where `int` is a more correct fallback than `i32`. +Additionally, it might seem weird to some that `i32` is a default, when +`int` looks like the default from other languages. The name of `int` +however is not in the scope of this RFC. + # Alternatives From cd464e9b487024a4ac3e98239f1bd9a67cfb0bea Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Fri, 7 Nov 2014 03:12:42 +0100 Subject: [PATCH 3/6] Int fallback restoration: Add case analysis --- text/0212-restore-int-fallback.md | 32 +++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/text/0212-restore-int-fallback.md b/text/0212-restore-int-fallback.md index e725073c940..c2ab81c8c8b 100644 --- a/text/0212-restore-int-fallback.md +++ b/text/0212-restore-int-fallback.md @@ -125,6 +125,38 @@ the major calling conventions), it's faster than 64-bit integers in arithmetic today, and is superior in memory usage while still providing a reasonable range of possible values. +## Case analysis + +This is an analysis of cases where `int` inference might be thought of +as useful: + +**Indexing into an array with unconstrained integer literal**: + +``` +let array = [0u8, 1, 2, 3]; +let index = 3; +array[index] +``` + +In this case, `index` is already automatically inferred to be a `uint`. + +**Using a default integer for tests, tutorials, etc.**: Examples of this +include "The Guide", the Rust API docs and the Rust standard library +unit tests. This is better served by a smaller, faster and platform +independent type as default. + +**Using an integer for an upper bound or for simply printing it**: This +is also served very well by `i32`. + +**Counting of loop iterations**: This is a part where `int` is as badly +suited as `i32`, so at least the move to `i32` doesn't create new +hazards (note that the number of elements of a vector might not +necessarily fit into an `int`). + +In addition to all the points above, having a platform-independent type +obviously results in less differences between the platforms in which the +programmer "doesn't care" about the integer type they are using. + ## Future-proofing for overloaded literals It is possible that, in the future, we will wish to allow vector and From 37f05a450d05aa21bc44cc9129c6ccab263b3e1e Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Fri, 7 Nov 2014 11:53:12 +0100 Subject: [PATCH 4/6] Int fallback restoration: Formatting --- text/0212-restore-int-fallback.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/text/0212-restore-int-fallback.md b/text/0212-restore-int-fallback.md index c2ab81c8c8b..5d674d8fe5c 100644 --- a/text/0212-restore-int-fallback.md +++ b/text/0212-restore-int-fallback.md @@ -5,8 +5,8 @@ # Summary Restore the integer inference fallback that was removed. Integer -literals whose type is unconstrained will default to `i32`, unlike -before when it defaulted to `int`. +literals whose type is unconstrained will default to `i32`, unlike the previous +fallback to `int`. Floating point literals will default to `f64`. # Motivation @@ -114,12 +114,12 @@ a struct or array, must wind up with a specific type. ## Rationale for the choice of defaulting to `i32` -Unlike in the first revision of the RFC, the fallback type suggested is -`i32`. This is, for one, to that a case analysis showed that there does -not exist a compelling reason for having a signed pointer-sized integer -type as the default. +In contrast to the first revision of the RFC, the fallback type +suggested is `i32`. This is justified by a case analysis which showed +that there does not exist a compelling reason for having a signed +pointer-sized integer type as the default. -The reasons for using `i32` instead is that it's familiar to programmers +There are reasons *for* using `i32` instead: It's familiar to programmers from the C programming language (where the default int type is 32-bit in the major calling conventions), it's faster than 64-bit integers in arithmetic today, and is superior in memory usage while still providing @@ -130,7 +130,7 @@ a reasonable range of possible values. This is an analysis of cases where `int` inference might be thought of as useful: -**Indexing into an array with unconstrained integer literal**: +**Indexing into an array with unconstrained integer literal:** ``` let array = [0u8, 1, 2, 3]; @@ -140,15 +140,15 @@ array[index] In this case, `index` is already automatically inferred to be a `uint`. -**Using a default integer for tests, tutorials, etc.**: Examples of this +**Using a default integer for tests, tutorials, etc.:** Examples of this include "The Guide", the Rust API docs and the Rust standard library unit tests. This is better served by a smaller, faster and platform independent type as default. -**Using an integer for an upper bound or for simply printing it**: This +**Using an integer for an upper bound or for simply printing it:** This is also served very well by `i32`. -**Counting of loop iterations**: This is a part where `int` is as badly +**Counting of loop iterations:** This is a part where `int` is as badly suited as `i32`, so at least the move to `i32` doesn't create new hazards (note that the number of elements of a vector might not necessarily fit into an `int`). From 960661bea5b5066371286c8f025b0dcb0372a37d Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Fri, 7 Nov 2014 23:56:14 +0100 Subject: [PATCH 5/6] Int fallback restoration: Expand on the perf argument --- text/0212-restore-int-fallback.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/text/0212-restore-int-fallback.md b/text/0212-restore-int-fallback.md index 5d674d8fe5c..874c86dc875 100644 --- a/text/0212-restore-int-fallback.md +++ b/text/0212-restore-int-fallback.md @@ -5,8 +5,8 @@ # Summary Restore the integer inference fallback that was removed. Integer -literals whose type is unconstrained will default to `i32`, unlike the previous -fallback to `int`. +literals whose type is unconstrained will default to `i32`, unlike the +previous fallback to `int`. Floating point literals will default to `f64`. # Motivation @@ -125,6 +125,12 @@ the major calling conventions), it's faster than 64-bit integers in arithmetic today, and is superior in memory usage while still providing a reasonable range of possible values. +To expand on the perfomance argument: `i32` obviously uses half of the +memory of `i64` meaning half the memory bandwidth used, half as much +cache consumption and twice as much vectorization – additionally +arithmetic (like multiplication and division) is faster on some of the +modern CPUs. + ## Case analysis This is an analysis of cases where `int` inference might be thought of From e66e34edc0a83f3db5f434a4ea59c88efd589027 Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Mon, 17 Nov 2014 19:24:49 +0100 Subject: [PATCH 6/6] Int fallback restoration: Remove unrelated mode change --- text/0401-coercions.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 text/0401-coercions.md diff --git a/text/0401-coercions.md b/text/0401-coercions.md old mode 100644 new mode 100755