Over on my new blog I have a post on running rustfmt on the Rust repo and how you can help with the process, if you would like to:
http://www.ncameron.org/blog/rustfmt-ing-rust/
http://www.ncameron.org/blog/rustfmt-ing-rust/
I'm a research engineer at Mozilla working on the Rust compiler. I have history with Firefox layout and graphics, and programming language theory and type systems (mostly of the OO, Featherweight flavour, thus the title of the blog). http://www.ncameron.org @nick_r_cameron
Box<Node> as our
pointer type (as we might do for tree-like data structures or linked lists).struct Foo<'a> {
f: &'a int,
}
fn main() {
let x = Foo { f: &42 };
}
struct Bar {
f: *const int,
}
fn main() {
let x = Bar { f: &42 };
}
fn foo() {
let x = 7i;
let y = x; // x is copied
println!("x is {}", x); // OK
let x = box 7i;
let y = x; // x is moved
//println!("x is {}", x); // error: use of moved value: `x`
}
enum Enum1 {
Var1,
Var2,
Var3
}
fn foo(x: &Enum1) {
match *x { // Option 1: deref here.
Var1 => {}
Var2 => {}
Var3 => {}
}
match x {
// Option 2: 'deref' in every arm.
&Var1 => {}
&Var2 => {}
&Var3 => {}
}
}
enum Enum2 {
// Box has a destructor so Enum2 has move semantics.
Var1(Box<int>),
Var2,
Var3
}
fn foo(x: &Enum2) {
match *x {
// We're ignoring nested data, so this is OK
Var1(..) => {}
// No change to the other arms.
Var2 => {}
Var3 => {}
}
match x {
// We're ignoring nested data, so this is OK
&Var1(..) => {}
// No change to the other arms.
&Var2 => {}
&Var3 => {}
}
}
match *x {
Var1(y) => {}
_ => {}
}
match x {
&Var1(y) => {}
_ => {}
}
fn bar(x: &Enum2, y: &Enum2) {
// Error: x and y are being moved.
// match (*x, *y) {
// (Var2, _) => {}
// _ => {}
// }
// OK.
match (x, y) {
(&Var2, _) => {}
_ => {}
}
}
fn baz(x: Enum2) {
match x {
Var1(y) => {}
_ => {}
}
}
fn foo(pair: (int, int)) {
let (x, y) = pair;
// we can now use x and y anywhere in foo
match pair {
(x, y) => {
// x and y can only be used in this scope
}
}
}
fn foo((x, y): (int, int)) {
}
struct St {
f1: int,
f2: f32
}
enum En {
Var1,
Var2,
Var3(int),
Var4(int, St, int)
}
fn foo(x: &En) {
match x {
&Var1 => println!("first variant"),
&Var3(5) => println!("third variant with number 5"),
&Var3(x) => println!("third variant with number {} (not 5)", x),
&Var4(3, St{ f1: 3, f2: x }, 45) => {
println!("destructuring an embedded struct, found {} in f2", x)
}
&Var4(_, x, _) => {
println!("Some other Var4 with {} in f1 and {} in f2", x.f1, x.f2)
}
_ => println!("other (Var2)")
}
}
fn foo(x: En) {
match x {
Var1 => println!("first variant"),
Var2 => println!("second variant"),
Var3(..) => println!("third variant"),
Var4(..) => println!("fourth variant")
}
}
struct Big {
field1: int,
field2: int,
field3: int,
field4: int,
field5: int,
field6: int,
field7: int,
field8: int,
field9: int,
}
fn foo(b: Big) {
let Big { field6: x, field3: y, ..} = b;
println!("pulled out {} and {}", x, y);
}
fn foo(b: Big) {
let Big { field6, field3, ..} = b;
println!("pulled out {} and {}", field3, field6);
}
struct Foo {
field: &'static int
}
fn foo(x: Foo) {
let Foo { field: &y } = x;
}
fn foo(b: Big) {
let Big { field3: ref x, ref field6, ..} = b;
println!("pulled out {} and {}", *x, *field6);
}
struct S {
field1: int,
field2: SomeOtherStruct
}
fn foo(s1: S, s2: &S) {
let f = s1.field1;
if f == s2.field1 {
println!("field1 matches!");
}
}
fn foo(sos: SomeOtherStruct) {
let x = S { field1: 45, field2: sos }; // initialise x with a struct literal
println!("x.field1 = {}", x.field1);
}
struct R {
r: Option<Box<R>>
}
struct Empty;
fn foo() {
let e = Empty;
}
// foo takes a struct and returns a tuple
fn foo(x: SomeOtherStruct) -> (i32, f32, S) {
(23, 45.82, S { field1: 54, field2: x })
}
Tuples can be used by destructuring using a `let` expression, e.g.,
fn bar(x: (int, int)) {
let (a, b) = x;
println!("x was ({}, {})", a, b);
}
struct IntPoint (int, int);
fn foo(x: IntPoint) {
let IntPoint(a, b) = x; // Note that we need the name of the tuple
// struct to destructure.
println!("x was ({}, {})", a, b);
}
enum E1 {
Var1,
Var2,
Var3
}
fn foo() {
let x: E1 = Var2;
match x {
Var2 => println!("var2"),
_ => {}
}
}
enum Expr {
Add(int, int),
Or(bool, bool),
Lit(int)
}
fn foo() {
let x = Or(true, false); // x has type Expr
}
fn bar(e: Expr) {
match e {
Add(x, y) => println!("An `Add` variant: {} + {}", x, y),
Or(..) => println!("An `Or` variant"),
_ => println!("Something else (in this case, a `Lit`)"),
}
}
use std::rc::Rc;
struct Node {
parent: Option<Rc<Node>>,
value: int
}
fn is_root(node: Node) -> bool {
match node.parent {
Some(_) => false,
None => true
}
}
struct S1 {
field1: int,
field2: S2
}
struct S2 {
field: int
}
fn main() {
let s = S1 { field1: 45, field2: S2 { field: 23 } };
// s is deeply immutable, the following mutations are forbidden
// s.field1 = 46;
// s.field2.field = 24;
let mut s = S1 { field1: 45, field2: S2 { field: 23 } };
// s is mutable, these are OK
s.field1 = 46;
s.field2.field = 24;
}
struct S1 {
f: int
}
struct S2<'a> {
f: &'a mut S1 // mutable reference field
}
struct S3<'a> {
f: &'a S1 // immutable reference field
}
fn main() {
let mut s1 = S1{f:56};
let s2 = S2 { f: &mut s1};
s2.f.f = 45; // legal even though s2 is immutable
// s2.f = &mut s1; // illegal - s2 is not mutable
let s1 = S1{f:56};
let mut s3 = S3 { f: &s1};
s3.f = &s1; // legal - s3 is mutable
// s3.f.f = 45; // illegal - s3.f is immutable
}
use std::rc::Rc;
use std::cell::RefCell;
Struct S {
field: int
}
fn foo(x: Rc<RefCell<S>>) {
{
let s = x.borrow();
println!("the field, twice {} {}", s.f, x.borrow().field);
// let s = x.borrow_mut(); // Error - we've already borrowed the contents of x
}
let s = x.borrow_mut(); // O, the earlier borrows are out of scope
s.f = 45;
// println!("The field {}", x.borrow().field); // Error - can't mut and immut borrow
println!("The field {}", s.f);
}