Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add empty structure/Remove structural records #5137

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 14 additions & 95 deletions doc/rust.md
Original file line number Diff line number Diff line change
Expand Up @@ -1285,19 +1285,22 @@ An _implementation_ is an item that implements a [trait](#traits) for a specific
Implementations are defined with the keyword `impl`.

~~~~
# type Point = {x: float, y: float};
# struct Point {x: float, y: float};
# type Surface = int;
# type BoundingBox = {x: float, y: float, width: float, height: float};
# struct BoundingBox {x: float, y: float, width: float, height: float};
# trait Shape { fn draw(Surface); fn bounding_box() -> BoundingBox; }
# fn do_draw_circle(s: Surface, c: Circle) { }

type Circle = {radius: float, center: Point};
struct Circle {
radius: float,
center: Point,
}

impl Shape for Circle {
fn draw(s: Surface) { do_draw_circle(s, self); }
fn bounding_box() -> BoundingBox {
let r = self.radius;
{x: self.center.x - r, y: self.center.y - r,
BoundingBox{x: self.center.x - r, y: self.center.y - r,
width: 2.0 * r, height: 2.0 * r}
}
}
Expand Down Expand Up @@ -1637,38 +1640,6 @@ rec_expr : '{' ident ':' expr
[ ".." expr ] '}'
~~~~~~~~

> **Note:** In future versions of Rust, record expressions and [record types](#record-types) will be removed.

A [_record_](#record-types) _expression_ is one or more comma-separated
name-value pairs enclosed by braces. A fieldname can be any identifier,
and is separated from its value expression by a
colon. To indicate that a field is mutable, the `mut` keyword is
written before its name.

~~~~
{x: 10f, y: 20f};
{name: "Joe", age: 35u, score: 100_000};
{ident: "X", mut count: 0u};
~~~~

The order of the fields in a record expression is significant, and
determines the type of the resulting value. `{a: u8, b: u8}` and `{b:
u8, a: u8}` are two different fields.

A record expression can terminate with the syntax `..` followed by an
expression to denote a functional update. The expression following
`..` (the base) must be of a record type that includes at least all the
fields mentioned in the record expression. A new record will be
created, of the same type as the base expression, with the given
values for the fields that were explicitly specified, and the values
in the base record for all other fields. The ordering of the fields in
such a record expression is not significant.

~~~~
let base = {x: 1, y: 2, z: 3};
{y: 0, z: 10, .. base};
~~~~

### Method-call expressions

~~~~~~~~{.ebnf .gram}
Expand All @@ -1689,7 +1660,7 @@ field_expr : expr '.' ident

A _field expression_ consists of an expression followed by a single dot and an identifier,
when not immediately followed by a parenthesized expression-list (the latter is a [method call expression](#method-call-expressions)).
A field expression denotes a field of a [structure](#structure-types) or [record](#record-types).
A field expression denotes a field of a [structure](#structure-types).

~~~~~~~~ {.field}
myrecord.myfield;
Expand Down Expand Up @@ -1905,8 +1876,10 @@ An example of three different swap expressions:
# let mut x = &mut [0];
# let mut a = &mut [0];
# let i = 0;
# let y = {mut z: 0};
# let b = {mut c: 0};
# struct S1 { z: int };
# struct S2 { c: int };
# let mut y = S1{z: 0};
# let mut b = S2{c: 0};

x <-> a;
x[i] <-> a[i];
Expand Down Expand Up @@ -2328,42 +2301,6 @@ match x {
}
~~~~

Records and structures can also be pattern-matched and their fields bound to variables.
When matching fields of a record,
the fields being matched are specified first,
then a placeholder (`_`) represents the remaining fields.

~~~~
# type options = {choose: bool, size: ~str};
# type player = {player: ~str, stats: (), options: options};
# fn load_stats() { }
# fn choose_player(r: &player) { }
# fn next_player() { }

fn main() {
let r = {
player: ~"ralph",
stats: load_stats(),
options: {
choose: true,
size: ~"small"
}
};

match r {
{options: {choose: true, _}, _} => {
choose_player(&r)
}
{player: ref p, options: {size: ~"small", _}, _} => {
log(info, (copy *p) + ~" is small");
}
_ => {
next_player();
}
}
}
~~~~

Patterns that bind variables default to binding to a copy of the matched value. This can be made
explicit using the ```copy``` keyword, changed to bind to a borrowed pointer by using the ```ref```
keyword, or to a mutable borrowed pointer using ```ref mut```, or the value can be moved into
Expand Down Expand Up @@ -2692,25 +2629,6 @@ let a: List<int> = Cons(7, @Cons(13, @Nil));
~~~~


### Record types

> **Note:** Records are not nominal types, thus do not directly support recursion, visibility control,
> out-of-order field initialization, or coherent trait implementation.
> Records are therefore deprecated and will be removed in future versions of Rust.
> [Structure types](#structure-types) should be used instead.

The record type-constructor forms a new heterogeneous product of values.
Fields of a record type are accessed by name and are arranged in memory in the order specified by the record type.

An example of a record type and its use:

~~~~
type Point = {x: int, y: int};
let p: Point = {x: 10, y: 11};
let px: int = p.x;
~~~~


### Pointer types

All pointers in Rust are explicit first-class values.
Expand Down Expand Up @@ -3040,7 +2958,8 @@ Some operations (such as field selection) implicitly dereference boxes. An
example of an _implicit dereference_ operation performed on box values:

~~~~~~~~
let x = @{y: 10};
struct Foo { y: int }
let x = @Foo{y: 10};
assert x.y == 10;
~~~~~~~~

Expand Down
11 changes: 6 additions & 5 deletions doc/tutorial-borrowed-ptr.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,9 +166,9 @@ operator. For example, I could write:
# struct Point {x: float, y: float} // as before
# struct Size {w: float, h: float} // as before
# struct Rectangle {origin: Point, size: Size}
# let rect_stack = &{origin: Point {x: 1f, y: 2f}, size: Size {w: 3f, h: 4f}};
# let rect_managed = @{origin: Point {x: 3f, y: 4f}, size: Size {w: 3f, h: 4f}};
# let rect_unique = ~{origin: Point {x: 5f, y: 6f}, size: Size {w: 3f, h: 4f}};
# let rect_stack = &Rectangle {origin: Point {x: 1f, y: 2f}, size: Size {w: 3f, h: 4f}};
# let rect_managed = @Rectangle {origin: Point {x: 3f, y: 4f}, size: Size {w: 3f, h: 4f}};
# let rect_unique = ~Rectangle {origin: Point {x: 5f, y: 6f}, size: Size {w: 3f, h: 4f}};
# fn compute_distance(p1: &Point, p2: &Point) -> float { 0f }
compute_distance(&rect_stack.origin, &rect_managed.origin);
~~~
Expand Down Expand Up @@ -274,13 +274,14 @@ the following function is legal:

~~~
# fn some_condition() -> bool { true }
# struct Foo { f: int }
fn example3() -> int {
let mut x = ~{f: 3};
let mut x = ~Foo {f: 3};
if some_condition() {
let y = &x.f; // -+ L
return *y; // |
} // -+
x = ~{f: 4};
x = ~Foo {f: 4};
...
# return 0;
}
Expand Down
8 changes: 4 additions & 4 deletions src/libcore/dvec.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
Expand Down Expand Up @@ -62,17 +62,17 @@ pub struct DVec<A> {

/// Creates a new, empty dvec
pub pure fn DVec<A>() -> DVec<A> {
DVec {mut data: ~[]}
DVec {data: ~[]}
}

/// Creates a new dvec with a single element
pub pure fn from_elem<A>(e: A) -> DVec<A> {
DVec {mut data: ~[e]}
DVec {data: ~[e]}
}

/// Creates a new dvec with the contents of a vector
pub pure fn from_vec<A>(v: ~[A]) -> DVec<A> {
DVec {mut data: v}
DVec {data: v}
}

/// Consumes the vector and returns its contents
Expand Down
18 changes: 11 additions & 7 deletions src/libcore/os.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
Expand Down Expand Up @@ -322,8 +322,8 @@ pub struct Pipe { mut in: c_int, mut out: c_int }
#[cfg(unix)]
pub fn pipe() -> Pipe {
unsafe {
let mut fds = Pipe {mut in: 0 as c_int,
mut out: 0 as c_int };
let mut fds = Pipe {in: 0 as c_int,
out: 0 as c_int };
assert (libc::pipe(&mut fds.in) == (0 as c_int));
return Pipe {in: fds.in, out: fds.out};
}
Expand All @@ -339,8 +339,8 @@ pub fn pipe() -> Pipe {
// fully understand. Here we explicitly make the pipe non-inheritable,
// which means to pass it to a subprocess they need to be duplicated
// first, as in rust_run_program.
let mut fds = Pipe { mut in: 0 as c_int,
mut out: 0 as c_int };
let mut fds = Pipe {in: 0 as c_int,
out: 0 as c_int };
let res = libc::pipe(&mut fds.in, 1024 as c_uint,
(libc::O_BINARY | libc::O_NOINHERIT) as c_int);
assert (res == 0 as c_int);
Expand Down Expand Up @@ -566,13 +566,17 @@ pub fn path_exists(p: &Path) -> bool {
*
* If the given path is relative, return it prepended with the current working
* directory. If the given path is already an absolute path, return it
* as is. This is a shortcut for calling os::getcwd().unsafe_join(p)
* as is.
*/
// NB: this is here rather than in path because it is a form of environment
// querying; what it does depends on the process working directory, not just
// the input paths.
pub fn make_absolute(p: &Path) -> Path {
getcwd().unsafe_join(p)
if p.is_absolute {
copy *p
} else {
getcwd().push_many(p.components)
}
}


Expand Down
6 changes: 3 additions & 3 deletions src/libcore/ptr.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
Expand Down Expand Up @@ -300,15 +300,15 @@ impl<T:Ord> Ord for &const T {
pub fn test() {
unsafe {
struct Pair {mut fst: int, mut snd: int};
let mut p = Pair {mut fst: 10, mut snd: 20};
let mut p = Pair {fst: 10, snd: 20};
let pptr: *mut Pair = &mut p;
let iptr: *mut int = cast::reinterpret_cast(&pptr);
assert (*iptr == 10);;
*iptr = 30;
assert (*iptr == 30);
assert (p.fst == 30);;

*pptr = Pair {mut fst: 50, mut snd: 60};
*pptr = Pair {fst: 50, snd: 60};
assert (*iptr == 50);
assert (p.fst == 50);
assert (p.snd == 60);
Expand Down
4 changes: 2 additions & 2 deletions src/libstd/ebml.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
Expand Down Expand Up @@ -219,7 +219,7 @@ pub mod reader {
}

pub fn Decoder(d: Doc) -> Decoder {
Decoder { mut parent: d, mut pos: d.start }
Decoder { parent: d, pos: d.start }
}

priv impl Decoder {
Expand Down
4 changes: 2 additions & 2 deletions src/libstd/sync.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
Expand Down Expand Up @@ -87,7 +87,7 @@ enum Sem<Q> = Exclusive<SemInner<Q>>;
#[doc(hidden)]
fn new_sem<Q:Owned>(count: int, q: Q) -> Sem<Q> {
Sem(exclusive(SemInner {
mut count: count, waiters: new_waitqueue(), blocked: q }))
count: count, waiters: new_waitqueue(), blocked: q }))
}
#[doc(hidden)]
fn new_sem_and_signal(count: int, num_condvars: uint)
Expand Down
16 changes: 6 additions & 10 deletions src/libsyntax/parse/parser.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
Expand Down Expand Up @@ -1093,15 +1093,10 @@ pub impl Parser {
self.mk_expr(lo, hi, expr_tup(es))
}
} else if *self.token == token::LBRACE {
if self.looking_at_record_literal() {
ex = self.parse_record_literal();
hi = self.span.hi;
} else {
self.bump();
let blk = self.parse_block_tail(lo, default_blk);
return self.mk_expr(blk.span.lo, blk.span.hi,
expr_block(blk));
}
self.bump();
let blk = self.parse_block_tail(lo, default_blk);
return self.mk_expr(blk.span.lo, blk.span.hi,
expr_block(blk));
} else if token::is_bar(*self.token) {
return self.parse_lambda_expr();
} else if self.eat_keyword(~"if") {
Expand Down Expand Up @@ -1223,6 +1218,7 @@ pub impl Parser {
self.bump();
let mut fields = ~[];
let mut base = None;

fields.push(self.parse_field(token::COLON));
while *self.token != token::RBRACE {
if self.try_parse_obsolete_with() {
Expand Down
2 changes: 1 addition & 1 deletion src/libsyntax/print/pprust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1213,7 +1213,7 @@ pub fn print_expr(s: @ps, &&expr: @ast::expr) {
print_expr(s, expr);
end(s);
}
_ => word(s.s, ~",")
_ => (word(s.s, ~","))
}
word(s.s, ~"}");
}
Expand Down
17 changes: 11 additions & 6 deletions src/test/compile-fail/autoderef-full-lval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,23 @@
// except according to those terms.

// error-pattern: mismatched types
type clam = {x: @int, y: @int};
struct clam {
x: @int,
y: @int,
}

type fish = {a: @int};
struct fish {
a: @int,
}

fn main() {
let a: clam = {x: @1, y: @2};
let b: clam = {x: @10, y: @20};
let a: clam = clam{x: @1, y: @2};
let b: clam = clam{x: @10, y: @20};
let z: int = a.x + b.y;
log(debug, z);
assert (z == 21);
let forty: fish = {a: @40};
let two: fish = {a: @2};
let forty: fish = fish{a: @40};
let two: fish = fish{a: @2};
let answer: int = forty.a + two.a;
log(debug, answer);
assert (answer == 42);
Expand Down
Loading