| [Number literals](#number-literals)`*` | Example | Exponentiation | Suffixes |
|----------------------------------------|---------|----------------|----------|
-| Decimal integer | `98_222i` | `N/A` | Integer suffixes |
-| Hex integer | `0xffi` | `N/A` | Integer suffixes |
-| Octal integer | `0o77i` | `N/A` | Integer suffixes |
-| Binary integer | `0b1111_0000i` | `N/A` | Integer suffixes |
+| Decimal integer | `98_222is` | `N/A` | Integer suffixes |
+| Hex integer | `0xffis` | `N/A` | Integer suffixes |
+| Octal integer | `0o77is` | `N/A` | Integer suffixes |
+| Binary integer | `0b1111_0000is` | `N/A` | Integer suffixes |
| Floating-point | `123.0E+77f64` | `Optional` | Floating-point suffixes |
`*` All number literals allow `_` as a visual separator: `1_234.0E+18f64`
##### Suffixes
| Integer | Floating-point |
|---------|----------------|
-| `i` (`int`), `u` (`uint`), `u8`, `i8`, `u16`, `i16`, `u32`, `i32`, `u64`, `i64` | `f32`, `f64` |
+| `is` (`isize`), `us` (`usize`), `u8`, `i8`, `u16`, `i16`, `u32`, `i32`, `u64`, `i64` | `f32`, `f64` |
#### Character and string literals
without any spaces) by an _integer suffix_, which forcibly sets the
type of the literal. There are 10 valid values for an integer suffix:
-* The `i` and `u` suffixes give the literal type `int` or `uint`,
+* The `is` and `us` suffixes give the literal type `isize` or `usize`,
respectively.
* Each of the signed and unsigned machine types `u8`, `i8`,
`u16`, `i16`, `u32`, `i32`, `u64` and `i64`
Examples of integer literals of various forms:
```
-123i; // type int
-123u; // type uint
-123_u; // type uint
+123is; // type isize
+123us; // type usize
+123_us; // type usize
0xff_u8; // type u8
0o70_i16; // type i16
0b1111_1111_1001_0000_i32; // type i32
# struct HashMap<K, V>;
# fn f() {
# fn id<T>(t: T) -> T { t }
-type T = HashMap<int,String>; // Type arguments used in a type expression
-let x = id::<int>(10); // Type arguments used in a call expression
+type T = HashMap<i32,String>; // Type arguments used in a type expression
+let x = id::<i32>(10); // Type arguments used in a call expression
# }
```
| '*' ] ] ?
| '{' path_item [ ',' path_item ] * '}' ;
-path_item : ident | "mod" ;
+path_item : ident | "self" ;
```
A _use declaration_ creates one or more local name bindings synonymous with
* Binding all paths matching a given prefix, using the asterisk wildcard syntax
`use a::b::*;`
* Simultaneously binding a list of paths differing only in their final element
- and their immediate parent module, using the `mod` keyword, such as
- `use a::b::{mod, c, d};`
+ and their immediate parent module, using the `self` keyword, such as
+ `use a::b::{self, c, d};`
An example of `use` declarations:
```
use std::iter::range_step;
use std::option::Option::{Some, None};
-use std::collections::hash_map::{mod, HashMap};
+use std::collections::hash_map::{self, HashMap};
fn foo<T>(_: T){}
-fn bar(map1: HashMap<String, uint>, map2: hash_map::HashMap<String, uint>){}
+fn bar(map1: HashMap<String, usize>, map2: hash_map::HashMap<String, usize>){}
fn main() {
- // Equivalent to 'std::iter::range_step(0u, 10u, 2u);'
- range_step(0u, 10u, 2u);
+ // Equivalent to 'std::iter::range_step(0us, 10, 2);'
+ range_step(0us, 10, 2);
// Equivalent to 'foo(vec![std::option::Option::Some(1.0f64),
// std::option::Option::None]);'
An example of a function:
```
-fn add(x: int, y: int) -> int {
+fn add(x: i32, y: i32) -> i32 {
return x + y;
}
```
pattern that is valid in a let binding is also valid as an argument.
```
-fn first((value, _): (int, int)) -> int { value }
+fn first((value, _): (i32, i32)) -> i32 { value }
```
When a generic function is referenced, its type is instantiated based on the
context of the reference. For example, calling the `iter` function defined
-above on `[1, 2]` will instantiate type parameter `T` with `int`, and require
-the closure parameter to have type `fn(int)`.
+above on `[1, 2]` will instantiate type parameter `T` with `isize`, and require
+the closure parameter to have type `fn(isize)`.
The type parameters can also be explicitly supplied in a trailing
[path](#paths) component after the function name. This might be necessary if
```
# fn my_err(s: &str) -> ! { panic!() }
-fn f(i: int) -> int {
+fn f(i: i32) -> i32 {
if i == 42 {
return 42;
}
```
This will not compile without the `!` annotation on `my_err`, since the `else`
-branch of the conditional in `f` does not return an `int`, as required by the
+branch of the conditional in `f` does not return an `i32`, as required by the
signature of `f`. Adding the `!` annotation to `my_err` informs the
typechecker that, should control ever enter `my_err`, no further type judgments
about `f` need to hold, since control will never resume in any context that
```
// Declares an extern fn, the ABI defaults to "C"
-extern fn new_int() -> int { 0 }
+extern fn new_i32() -> i32 { 0 }
// Declares an extern fn with "stdcall" ABI
-extern "stdcall" fn new_int_stdcall() -> int { 0 }
+extern "stdcall" fn new_i32_stdcall() -> i32 { 0 }
```
Unlike normal functions, extern fns have an `extern "ABI" fn()`. This is the
same type as the functions declared in an extern block.
```
-# extern fn new_int() -> int { 0 }
-let fptr: extern "C" fn() -> int = new_int;
+# extern fn new_i32() -> i32 { 0 }
+let fptr: extern "C" fn() -> i32 = new_i32;
```
Extern functions may be called directly from Rust code as Rust uses large,
An example of a `struct` item and its use:
```
-struct Point {x: int, y: int}
+struct Point {x: i32, y: i32}
let p = Point {x: 10, y: 11};
-let px: int = p.x;
+let px: i32 = p.x;
```
A _tuple structure_ is a nominal [tuple type](#tuple-types), also defined with
the keyword `struct`. For example:
```
-struct Point(int, int);
+struct Point(i32, i32);
let p = Point(10, 11);
-let px: int = match p { Point(x, _) => x };
+let px: i32 = match p { Point(x, _) => x };
```
A _unit-like struct_ is a structure without any fields, defined by leaving off
In this example, `Cat` is a _struct-like enum variant_,
whereas `Dog` is simply called an enum variant.
+Enums have a discriminant. You can assign them explicitly:
+
+```
+enum Foo {
+ Bar = 123,
+}
+```
+
+If a discriminant isn't assigned, they start at zero, and add one for each
+variant, in order.
+
+You can cast an enum to get this value:
+
+```
+# enum Foo { Bar = 123 }
+let x = Foo::Bar as u32; // x is now 123u32
+```
+
+This only works as long as none of the variants have data attached. If
+it were `Bar(i32)`, this is disallowed.
+
### Constant items
```{.ebnf .gram}
the `static` lifetime, fixed-size arrays, tuples, enum variants, and structs.
```
-const BIT1: uint = 1 << 0;
-const BIT2: uint = 1 << 1;
+const BIT1: u32 = 1 << 0;
+const BIT2: u32 = 1 << 1;
-const BITS: [uint; 2] = [BIT1, BIT2];
+const BITS: [u32; 2] = [BIT1, BIT2];
const STRING: &'static str = "bitstring";
struct BitsNStrings<'a> {
- mybits: [uint; 2],
+ mybits: [u32; 2],
mystring: &'a str
}
data are being stored, or single-address and mutability properties are required.
```
-use std::sync::atomic::{AtomicUint, Ordering, ATOMIC_UINT_INIT};;
+use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
-// Note that ATOMIC_UINT_INIT is a *const*, but it may be used to initialize a
+// Note that ATOMIC_USIZE_INIT is a *const*, but it may be used to initialize a
// static. This static can be modified, so it is not placed in read-only memory.
-static COUNTER: AtomicUint = ATOMIC_UINT_INIT;
+static COUNTER: AtomicUsize = ATOMIC_USIZE_INIT;
// This table is a candidate to be placed in read-only memory.
-static TABLE: &'static [uint] = &[1, 2, 3, /* ... */];
+static TABLE: &'static [usize] = &[1, 2, 3, /* ... */];
for slot in TABLE.iter() {
println!("{}", slot);
libraries and can also be bound from C libraries (in an `extern` block).
```
-# fn atomic_add(_: &mut uint, _: uint) -> uint { 2 }
+# fn atomic_add(_: &mut u32, _: u32) -> u32 { 2 }
-static mut LEVELS: uint = 0;
+static mut LEVELS: u32 = 0;
// This violates the idea of no shared state, and this doesn't internally
// protect against races, so this function is `unsafe`
-unsafe fn bump_levels_unsafe1() -> uint {
+unsafe fn bump_levels_unsafe1() -> u32 {
let ret = LEVELS;
LEVELS += 1;
return ret;
// Assuming that we have an atomic_add function which returns the old value,
// this function is "safe" but the meaning of the return value may not be what
// callers expect, so it's still marked as `unsafe`
-unsafe fn bump_levels_unsafe2() -> uint {
+unsafe fn bump_levels_unsafe2() -> u32 {
return atomic_add(&mut LEVELS, 1);
}
```
[implementations](#implementations).
```
-# type Surface = int;
-# type BoundingBox = int;
+# type Surface = i32;
+# type BoundingBox = i32;
trait Shape {
fn draw(&self, Surface);
fn bounding_box(&self) -> BoundingBox;
```
trait Seq<T> {
- fn len(&self) -> uint;
- fn elt_at(&self, n: uint) -> T;
+ fn len(&self) -> u32;
+ fn elt_at(&self, n: u32) -> T;
fn iter<F>(&self, F) where F: Fn(T);
}
```
called on values that have the parameter's type. For example:
```
-# type Surface = int;
+# type Surface = i32;
# trait Shape { fn draw(&self, Surface); }
fn draw_twice<T: Shape>(surface: Surface, sh: T) {
sh.draw(surface);
```
# trait Shape { }
-# impl Shape for int { }
-# let mycircle = 0i;
+# impl Shape for i32 { }
+# let mycircle = 0i32;
let myshape: Box<Shape> = Box::new(mycircle) as Box<Shape>;
```
```
trait Num {
- fn from_int(n: int) -> Self;
+ fn from_i32(n: i32) -> Self;
}
impl Num for f64 {
- fn from_int(n: int) -> f64 { n as f64 }
+ fn from_i32(n: i32) -> f64 { n as f64 }
}
-let x: f64 = Num::from_int(42);
+let x: f64 = Num::from_i32(42);
```
Traits may inherit from other traits. For example, in
```{.ignore}
# trait Shape { fn area(&self) -> f64; }
# trait Circle : Shape { fn radius(&self) -> f64; }
-# impl Shape for int { fn area(&self) -> f64 { 0.0 } }
-# impl Circle for int { fn radius(&self) -> f64 { 0.0 } }
-# let mycircle = 0;
+# impl Shape for i32 { fn area(&self) -> f64 { 0.0 } }
+# impl Circle for i32 { fn radius(&self) -> f64 { 0.0 } }
+# let mycircle = 0i32;
let mycircle = Box::new(mycircle) as Box<Circle>;
let nonsense = mycircle.radius() * mycircle.area();
```
```
# struct Point {x: f64, y: f64};
# impl Copy for Point {}
-# type Surface = int;
+# type Surface = i32;
# struct BoundingBox {x: f64, y: f64, width: f64, height: f64};
# trait Shape { fn draw(&self, Surface); fn bounding_box(&self) -> BoundingBox; }
# fn do_draw_circle(s: Surface, c: Circle) { }
in the same module or a sub-module as the `self` type:
```
-struct Point {x: int, y: int}
+struct Point {x: i32, y: i32}
impl Point {
fn log(&self) {
// Declare a public struct with a private field
pub struct Bar {
- field: int
+ field: i32
}
// Declare a public enum with two public variants
mod m1 {
// Missing documentation is ignored here
#[allow(missing_docs)]
- pub fn undocumented_one() -> int { 1 }
+ pub fn undocumented_one() -> i32 { 1 }
// Missing documentation signals a warning here
#[warn(missing_docs)]
- pub fn undocumented_too() -> int { 2 }
+ pub fn undocumented_too() -> i32 { 2 }
// Missing documentation signals an error here
#[deny(missing_docs)]
- pub fn undocumented_end() -> int { 3 }
+ pub fn undocumented_end() -> i32 { 3 }
}
```
#[allow(missing_docs)]
mod nested {
// Missing documentation is ignored here
- pub fn undocumented_one() -> int { 1 }
+ pub fn undocumented_one() -> i32 { 1 }
// Missing documentation signals a warning here,
// despite the allow above.
#[warn(missing_docs)]
- pub fn undocumented_two() -> int { 2 }
+ pub fn undocumented_two() -> i32 { 2 }
}
// Missing documentation signals a warning here
- pub fn undocumented_too() -> int { 3 }
+ pub fn undocumented_too() -> i32 { 3 }
}
```
// Attempting to toggle warning signals an error here
#[allow(missing_docs)]
/// Returns 2.
- pub fn undocumented_too() -> int { 2 }
+ pub fn undocumented_too() -> i32 { 2 }
}
```
: ___Needs filling in___
* `no_copy_bound`
: This type does not implement "copy", even if eligible.
-* `no_send_bound`
- : This type does not implement "send", even if eligible.
-* `no_sync_bound`
- : This type does not implement "sync", even if eligible.
* `eh_personality`
: ___Needs filling in___
* `exchange_free`
* `#[inline(always)]` asks the compiler to always perform an inline expansion.
* `#[inline(never)]` asks the compiler to never perform an inline expansion.
-### Derive
+### `derive`
The `derive` attribute allows certain traits to be automatically implemented
for data structures. For example, the following will create an `impl` for the
```
#[derive(PartialEq, Clone)]
struct Foo<T> {
- a: int,
+ a: i32,
b: T
}
```
The generated `impl` for `PartialEq` is equivalent to
```
-# struct Foo<T> { a: int, b: T }
+# struct Foo<T> { a: i32, b: T }
impl<T: PartialEq> PartialEq for Foo<T> {
fn eq(&self, other: &Foo<T>) -> bool {
self.a == other.a && self.b == other.b
```{.tuple}
(0,);
(0.0, 4.5);
-("a", 4u, true);
+("a", 4us, true);
```
### Unit expressions
```
# struct Point { x: f64, y: f64 }
# struct TuplePoint(f64, f64);
-# mod game { pub struct User<'a> { pub name: &'a str, pub age: uint, pub score: uint } }
+# mod game { pub struct User<'a> { pub name: &'a str, pub age: u32, pub score: uint } }
# struct Cookie; fn some_fn<T>(t: T) {}
Point {x: 10.0, y: 20.0};
TuplePoint(10.0, 20.0);
fields.
```
-# struct Point3d { x: int, y: int, z: int }
+# struct Point3d { x: i32, y: i32, z: i32 }
let base = Point3d {x: 1, y: 2, z: 3};
Point3d {y: 0, z: 10, .. base};
```
[literal](#literals) or a [static item](#static-items).
```
-[1i, 2, 3, 4];
+[1is, 2, 3, 4];
["a", "b", "c", "d"];
-[0i; 128]; // array with 128 zeros
+[0is; 128]; // array with 128 zeros
[0u8, 0u8, 0u8, 0u8];
```
```
# fn sum(v: &[f64]) -> f64 { 0.0 }
-# fn len(v: &[f64]) -> int { 0 }
+# fn len(v: &[f64]) -> i32 { 0 }
fn avg(v: &[f64]) -> f64 {
let sum: f64 = sum(v);
operand.
```
-# let mut x = 0i;
+# let mut x = 0is;
# let y = 0;
x = y;
An example of a parenthesized expression:
```
-let x: int = (2 + 3) * 4;
+let x: i32 = (2 + 3) * 4;
```
Some examples of call expressions:
```
-# fn add(x: int, y: int) -> int { 0 }
+# fn add(x: i32, y: i32) -> i32 { 0 }
-let x: int = add(1, 2);
+let x: i32 = add(1i32, 2i32);
let pi: Option<f32> = "3.14".parse();
```
function argument, and call it with a lambda expression as an argument:
```
-fn ten_times<F>(f: F) where F: Fn(int) {
- let mut i = 0;
+fn ten_times<F>(f: F) where F: Fn(i32) {
+ let mut i = 0i32;
while i < 10 {
f(i);
i += 1;
An example:
```
-let mut i = 0u;
+let mut i = 0us;
while i < 10 {
println!("hello");
An example of a for loop over the contents of an array:
```
-# type Foo = int;
+# type Foo = i32;
# fn bar(f: Foo) { }
# let a = 0;
# let b = 0;
An example of a for loop over a series of integers:
```
-# fn bar(b:uint) { }
-for i in range(0u, 256) {
+# fn bar(b:usize) { }
+for i in range(0us, 256) {
bar(i);
}
```
enum List<X> { Nil, Cons(X, Box<List<X>>) }
fn main() {
- let x: List<int> = List::Cons(10, box List::Cons(11, box List::Nil));
+ let x: List<i32> = List::Cons(10, box List::Cons(11, box List::Nil));
match x {
List::Cons(_, box List::Nil) => panic!("singleton list"),
`advanced_slice_patterns` feature gate is turned on. This wildcard can be used
at most once for a given array, which implies that it cannot be used to
specifically match elements that are at an unknown distance from both ends of a
-array, like `[.., 42, ..]`. If followed by a variable name, it will bind the
+array, like `[.., 42, ..]`. If preceded by a variable name, it will bind the
corresponding slice to the variable. Example:
```
# #![feature(advanced_slice_patterns)]
-fn is_symmetric(list: &[uint]) -> bool {
+fn is_symmetric(list: &[u32]) -> bool {
match list {
[] | [_] => true,
[x, inside.., y] if x == y => is_symmetric(inside),
```
#![feature(box_syntax)]
-# fn process_pair(a: int, b: int) { }
+# fn process_pair(a: i32, b: i32) { }
# fn process_ten() { }
enum List<X> { Nil, Cons(X, Box<List<X>>) }
fn main() {
- let x: List<int> = List::Cons(10, box List::Cons(11, box List::Nil));
+ let x: List<i32> = List::Cons(10, box List::Cons(11, box List::Nil));
match x {
List::Cons(a, box List::Cons(b, _)) => {
```
Patterns can also dereference pointers by using the `&`, `&mut` and `box`
-symbols, as appropriate. For example, these two matches on `x: &int` are
+symbols, as appropriate. For example, these two matches on `x: &isize` are
equivalent:
```
-# let x = &3i;
+# let x = &3is;
let y = match *x { 0 => "zero", _ => "some" };
let z = match x { &0 => "zero", _ => "some" };
may be specified with `...`. For example:
```
-# let x = 2i;
+# let x = 2is;
let message = match x {
0 | 1 => "not many",
```
# let maybe_digit = Some(0);
-# fn process_digit(i: int) { }
-# fn process_other(i: int) { }
+# fn process_digit(i: i32) { }
+# fn process_other(i: i32) { }
let message = match maybe_digit {
Some(x) if x < 10 => process_digit(x),
An example of a `return` expression:
```
-fn max(a: int, b: int) -> int {
+fn max(a: i32, b: i32) -> i32 {
if a > b {
return a;
}
#### Machine-dependent integer types
-The `uint` type is an unsigned integer type with the same number of bits as the
+The `usize` type is an unsigned integer type with the same number of bits as the
platform's pointer type. It can represent every memory address in the process.
-The `int` type is a signed integer type with the same number of bits as the
+The `isize` type is a signed integer type with the same number of bits as the
platform's pointer type. The theoretical upper bound on object and array size
-is the maximum `int` value. This ensures that `int` can be used to calculate
+is the maximum `isize` value. This ensures that `isize` can be used to calculate
differences between pointers into an object or array and can address every byte
within an object along with one byte past the end.
An example of a tuple type and its use:
```
-type Pair<'a> = (int, &'a str);
+type Pair<'a> = (i32, &'a str);
let p: Pair<'static> = (10, "hello");
let (a, b) = p;
assert!(b != "world");
An example of a `fn` type:
```
-fn add(x: int, y: int) -> int {
+fn add(x: i32, y: i32) -> i32 {
return x + y;
}
let mut x = add(5,7);
-type Binop = fn(int, int) -> int;
+type Binop = fn(i32, i32) -> i32;
let bo: Binop = add;
x = bo(5,7);
```
An example of creating and calling a closure:
```rust
-let captured_var = 10i;
+let captured_var = 10is;
let closure_no_args = |&:| println!("captured_var={}", captured_var);
-let closure_args = |&: arg: int| -> int {
+let closure_args = |&: arg: isize| -> isize {
println!("captured_var={}, arg={}", captured_var, arg);
arg // Note lack of semicolon after 'arg'
};
-fn call_closure<F: Fn(), G: Fn(int) -> int>(c1: F, c2: G) {
+fn call_closure<F: Fn(), G: Fn(isize) -> isize>(c1: F, c2: G) {
c1();
c2(2);
}
fn stringify(&self) -> String;
}
-impl Printable for int {
+impl Printable for isize {
fn stringify(&self) -> String { self.to_string() }
}
}
fn main() {
- print(Box::new(10i) as Box<Printable>);
+ print(Box::new(10is) as Box<Printable>);
}
```
Function parameters are immutable unless declared with `mut`. The `mut` keyword
applies only to the following parameter (so `|mut x, y|` and `fn f(mut x:
-Box<int>, y: Box<int>)` declare one mutable variable `x` and one immutable
+Box<i32>, y: Box<i32>)` declare one mutable variable `x` and one immutable
variable `y`).
Methods that take either `self` or `Box<Self>` can optionally place them in a
An example of a box type and value:
```
-let x: Box<int> = Box::new(10);
+let x: Box<i32> = Box::new(10);
```
Box values exist in 1:1 correspondence with their heap allocation, copying a
the source location cannot be used unless it is reinitialized.
```
-let x: Box<int> = Box::new(10);
+let x: Box<i32> = Box::new(10);
let y = x;
// attempting to use `x` will result in an error here
```