From 1df6ddd08c3155e64806cd54b878337814401b7e Mon Sep 17 00:00:00 2001 From: Lindsey Kuper Date: Wed, 20 Jun 2012 17:09:30 -0700 Subject: [PATCH] doc: add information about suffix inference to tutorial and manual. --- doc/rust.md | 22 ++++--- doc/tutorial.md | 57 +++++++++++++++++-- .../tutorial-suffix-inference-test.rs | 22 +++++++ 3 files changed, 88 insertions(+), 13 deletions(-) create mode 100644 src/test/compile-fail/tutorial-suffix-inference-test.rs diff --git a/doc/rust.md b/doc/rust.md index b30932ef5c5..3f4e39d95c8 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -330,24 +330,32 @@ An _integer literal_ has one of three forms: * A _binary literal_ starts with the character sequence `U+0030` `U+0062` (`0b`) and continues as any mixture binary digits and underscores. -By default, an integer literal is of type `int`. An integer literal may be -followed (immediately, without any spaces) by an _integer suffix_, which -changes the type of the literal. There are two kinds of integer literal -suffix: +An integer literal may be followed (immediately, without any spaces) by an +_integer suffix_, which changes the type of the literal. There are two kinds +of integer literal suffix: - * The `u` suffix gives the literal type `uint`. + * The `i` and `u` suffixes give the literal type `int` or `uint`, + respectively. * Each of the signed and unsigned machine types `u8`, `i8`, `u16`, `i16`, `u32`, `i32`, `u64` and `i64` give the literal the corresponding machine type. +The type of an _unsuffixed_ integer literal is determined by type inference. +If a integer type can be _uniquely_ determined from the surrounding program +context, the unsuffixed integer literal has that type. If the program context +underconstrains the type, the unsuffixed integer literal's type is `int`; if +the program context overconstrains the type, it is considered a static type +error. Examples of integer literals of various forms: ~~~~ -123; // type int +123; 0xff00; // type determined by program context; + // defaults to int in absence of type + // information + 123u; // type uint 123_u; // type uint -0xff00; // type int 0xff_u8; // type u8 0b1111_1111_1001_0000_i32; // type i32 ~~~~ diff --git a/doc/tutorial.md b/doc/tutorial.md index 1ef17c71166..f6c2aef30ea 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -396,15 +396,58 @@ synonym. ## Literals +### Numeric literals + Integers can be written in decimal (`144`), hexadecimal (`0x90`), and -binary (`0b10010000`) base. Without a suffix, an integer literal is -considered to be of type `int`. Add a `u` (`144u`) to make it a `uint` -instead. Literals of the fixed-size integer types can be created by -the literal with the type name (`255u8`, `50i64`, etc). +binary (`0b10010000`) base. + +If you write an integer literal without a suffix (`3`, `-500`, etc.), +the Rust compiler will try to infer its type based on type annotations +and function signatures in the surrounding program. For example, here +the type of `x` is inferred to be `u16` because it is passed to a +function that takes a `u16` argument: + +~~~~~ +let x = 3; + +fn identity_u16(n: u16) -> u16 { n } + +identity_u16(x); +~~~~ + +On the other hand, if the program gives conflicting information about +what the type of the unsuffixed literal should be, you'll get an error +message. + +~~~~~{.xfail-test} +let x = 3; +let y: i32 = 3; + +fn identity_u8(n: u8) -> u8 { n } +fn identity_u16(n: u16) -> u16 { n } + +identity_u8(x); // after this, `x` is assumed to have type `u8` +identity_u16(x); // raises a type error (expected `u16` but found `u8`) +identity_u16(y); // raises a type error (expected `u16` but found `i32`) +~~~~ + +In the absence of any type annotations at all, Rust will assume that +an unsuffixed integer literal has type `int`. + +~~~~ +let n = 50; +log(error, n); // n is an int +~~~~ + +It's also possible to avoid any type ambiguity by writing integer +literals with a suffix. The suffixes `i` and `u` are for the types +`int` and `uint`, respectively: the literal `-3i` has type `int`, +while `127u` has type `uint`. For the fixed-size integer types, just +suffix the literal with the type name: `255u8`, `50i64`, etc. Note that, in Rust, no implicit conversion between integer types -happens. If you are adding one to a variable of type `uint`, you must -type `v += 1u`—saying `+= 1` will give you a type error. +happens. If you are adding one to a variable of type `uint`, saying +`+= 1u8` will give you a type error. Floating point numbers are written `0.0`, `1e6`, or `2.1e-4`. Without a suffix, the literal is assumed to be of type `float`. Suffixes `f32` @@ -412,6 +455,8 @@ and `f64` can be used to create literals of a specific type. The suffix `f` can be used to write `float` literals without a dot or exponent: `3f`. +### Other literals + The nil literal is written just like the type: `()`. The keywords `true` and `false` produce the boolean literals. diff --git a/src/test/compile-fail/tutorial-suffix-inference-test.rs b/src/test/compile-fail/tutorial-suffix-inference-test.rs new file mode 100644 index 00000000000..fa07be952c1 --- /dev/null +++ b/src/test/compile-fail/tutorial-suffix-inference-test.rs @@ -0,0 +1,22 @@ +fn main() { + let x = 3; + let y: i32 = 3; + + fn identity_u8(n: u8) -> u8 { n } + fn identity_u16(n: u16) -> u16 { n } + + identity_u8(x); // after this, `x` is assumed to have type `u8` + identity_u16(x); + //!^ ERROR mismatched types: expected `u16` but found `u8` + identity_u16(y); + //!^ ERROR mismatched types: expected `u16` but found `i32` + + let a = 3i; + + fn identity_i(n: int) -> int { n } + + identity_i(a); // ok + identity_u16(a); + //!^ ERROR mismatched types: expected `u16` but found `int` + +} \ No newline at end of file