Skip to content

Commit 5aca7d6

Browse files
committed
auto merge of #5137 : yjh0502/rust/empty_struct, r=nikomatsakis
The fix is straight-forward, but there are several changes while fixing the issue. 1) disallow `mut` keyword when making a new struct In code base, there are following code, ```rust struct Foo { mut a: int }; let a = Foo { mut a: 1 }; ``` This is because of structural record, which is deprecated corrently (see issue #3089) In structural record, `mut` keyword should be allowd to control mutability. But without structural record, we don't need to allow `mut` keyword while constructing struct. 2) disallow structural records in parser level This is related to 1). With structural records, there is an ambiguity between empty block and empty struct To solve the problem, I change parser to stop parsing structural records. I think this is not a problem, because structural records are not compiled already. Misc. issues There is an ambiguity between empty struct vs. empty match stmt. with following code, ```rust match x{} {} ``` Two interpretation is possible, which is listed blow ```rust match (x{}) {} // matching with newly-constructed empty struct (match x{}) {} // matching with empty enum(or struct) x // and then empty block ``` It seems that there is no such code in rust code base, but there is one test which uses empty match statement: https://github.com/mozilla/rust/blob/incoming/src/test/run-pass/issue-3037.rs All other cases could be distinguished with look-ahead, but this can't be. One possible solution is wrapping with parentheses when matching with an uninhabited type. ```rust enum what { } fn match_with_empty(x: what) -> ~str { match (x) { //use parentheses to remove the ambiguity } } ```
2 parents d3b94f6 + 95bc9ea commit 5aca7d6

25 files changed

+74
-335
lines changed

Diff for: doc/rust.md

+14-95
Original file line numberDiff line numberDiff line change
@@ -1299,19 +1299,22 @@ An _implementation_ is an item that implements a [trait](#traits) for a specific
12991299
Implementations are defined with the keyword `impl`.
13001300

13011301
~~~~
1302-
# type Point = {x: float, y: float};
1302+
# struct Point {x: float, y: float};
13031303
# type Surface = int;
1304-
# type BoundingBox = {x: float, y: float, width: float, height: float};
1304+
# struct BoundingBox {x: float, y: float, width: float, height: float};
13051305
# trait Shape { fn draw(Surface); fn bounding_box() -> BoundingBox; }
13061306
# fn do_draw_circle(s: Surface, c: Circle) { }
13071307
1308-
type Circle = {radius: float, center: Point};
1308+
struct Circle {
1309+
radius: float,
1310+
center: Point,
1311+
}
13091312
13101313
impl Shape for Circle {
13111314
fn draw(s: Surface) { do_draw_circle(s, self); }
13121315
fn bounding_box() -> BoundingBox {
13131316
let r = self.radius;
1314-
{x: self.center.x - r, y: self.center.y - r,
1317+
BoundingBox{x: self.center.x - r, y: self.center.y - r,
13151318
width: 2.0 * r, height: 2.0 * r}
13161319
}
13171320
}
@@ -1657,38 +1660,6 @@ rec_expr : '{' ident ':' expr
16571660
[ ".." expr ] '}'
16581661
~~~~~~~~
16591662

1660-
> **Note:** In future versions of Rust, record expressions and [record types](#record-types) will be removed.
1661-
1662-
A [_record_](#record-types) _expression_ is one or more comma-separated
1663-
name-value pairs enclosed by braces. A fieldname can be any identifier,
1664-
and is separated from its value expression by a
1665-
colon. To indicate that a field is mutable, the `mut` keyword is
1666-
written before its name.
1667-
1668-
~~~~
1669-
{x: 10f, y: 20f};
1670-
{name: "Joe", age: 35u, score: 100_000};
1671-
{ident: "X", mut count: 0u};
1672-
~~~~
1673-
1674-
The order of the fields in a record expression is significant, and
1675-
determines the type of the resulting value. `{a: u8, b: u8}` and `{b:
1676-
u8, a: u8}` are two different fields.
1677-
1678-
A record expression can terminate with the syntax `..` followed by an
1679-
expression to denote a functional update. The expression following
1680-
`..` (the base) must be of a record type that includes at least all the
1681-
fields mentioned in the record expression. A new record will be
1682-
created, of the same type as the base expression, with the given
1683-
values for the fields that were explicitly specified, and the values
1684-
in the base record for all other fields. The ordering of the fields in
1685-
such a record expression is not significant.
1686-
1687-
~~~~
1688-
let base = {x: 1, y: 2, z: 3};
1689-
{y: 0, z: 10, .. base};
1690-
~~~~
1691-
16921663
### Method-call expressions
16931664

16941665
~~~~~~~~{.ebnf .gram}
@@ -1709,7 +1680,7 @@ field_expr : expr '.' ident
17091680

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

17141685
~~~~~~~~ {.field}
17151686
myrecord.myfield;
@@ -1925,8 +1896,10 @@ An example of three different swap expressions:
19251896
# let mut x = &mut [0];
19261897
# let mut a = &mut [0];
19271898
# let i = 0;
1928-
# let y = {mut z: 0};
1929-
# let b = {mut c: 0};
1899+
# struct S1 { z: int };
1900+
# struct S2 { c: int };
1901+
# let mut y = S1{z: 0};
1902+
# let mut b = S2{c: 0};
19301903
19311904
x <-> a;
19321905
x[i] <-> a[i];
@@ -2350,42 +2323,6 @@ match x {
23502323
}
23512324
~~~~
23522325

2353-
Records and structures can also be pattern-matched and their fields bound to variables.
2354-
When matching fields of a record,
2355-
the fields being matched are specified first,
2356-
then a placeholder (`_`) represents the remaining fields.
2357-
2358-
~~~~
2359-
# type options = {choose: bool, size: ~str};
2360-
# type player = {player: ~str, stats: (), options: options};
2361-
# fn load_stats() { }
2362-
# fn choose_player(r: &player) { }
2363-
# fn next_player() { }
2364-
2365-
fn main() {
2366-
let r = {
2367-
player: ~"ralph",
2368-
stats: load_stats(),
2369-
options: {
2370-
choose: true,
2371-
size: ~"small"
2372-
}
2373-
};
2374-
2375-
match r {
2376-
{options: {choose: true, _}, _} => {
2377-
choose_player(&r)
2378-
}
2379-
{player: ref p, options: {size: ~"small", _}, _} => {
2380-
log(info, (copy *p) + ~" is small");
2381-
}
2382-
_ => {
2383-
next_player();
2384-
}
2385-
}
2386-
}
2387-
~~~~
2388-
23892326
Patterns that bind variables default to binding to a copy of the matched value. This can be made
23902327
explicit using the ```copy``` keyword, changed to bind to a borrowed pointer by using the ```ref```
23912328
keyword, or to a mutable borrowed pointer using ```ref mut```, or the value can be moved into
@@ -2717,25 +2654,6 @@ let a: List<int> = Cons(7, @Cons(13, @Nil));
27172654
~~~~
27182655

27192656

2720-
### Record types
2721-
2722-
> **Note:** Records are not nominal types, thus do not directly support recursion, visibility control,
2723-
> out-of-order field initialization, or coherent trait implementation.
2724-
> Records are therefore deprecated and will be removed in future versions of Rust.
2725-
> [Structure types](#structure-types) should be used instead.
2726-
2727-
The record type-constructor forms a new heterogeneous product of values.
2728-
Fields of a record type are accessed by name and are arranged in memory in the order specified by the record type.
2729-
2730-
An example of a record type and its use:
2731-
2732-
~~~~
2733-
type Point = {x: int, y: int};
2734-
let p: Point = {x: 10, y: 11};
2735-
let px: int = p.x;
2736-
~~~~
2737-
2738-
27392657
### Pointer types
27402658

27412659
All pointers in Rust are explicit first-class values.
@@ -3065,7 +2983,8 @@ Some operations (such as field selection) implicitly dereference boxes. An
30652983
example of an _implicit dereference_ operation performed on box values:
30662984

30672985
~~~~~~~~
3068-
let x = @{y: 10};
2986+
struct Foo { y: int }
2987+
let x = @Foo{y: 10};
30692988
assert x.y == 10;
30702989
~~~~~~~~
30712990

Diff for: doc/tutorial-borrowed-ptr.md

+6-5
Original file line numberDiff line numberDiff line change
@@ -166,9 +166,9 @@ operator. For example, I could write:
166166
# struct Point {x: float, y: float} // as before
167167
# struct Size {w: float, h: float} // as before
168168
# struct Rectangle {origin: Point, size: Size}
169-
# let rect_stack = &{origin: Point {x: 1f, y: 2f}, size: Size {w: 3f, h: 4f}};
170-
# let rect_managed = @{origin: Point {x: 3f, y: 4f}, size: Size {w: 3f, h: 4f}};
171-
# let rect_unique = ~{origin: Point {x: 5f, y: 6f}, size: Size {w: 3f, h: 4f}};
169+
# let rect_stack = &Rectangle {origin: Point {x: 1f, y: 2f}, size: Size {w: 3f, h: 4f}};
170+
# let rect_managed = @Rectangle {origin: Point {x: 3f, y: 4f}, size: Size {w: 3f, h: 4f}};
171+
# let rect_unique = ~Rectangle {origin: Point {x: 5f, y: 6f}, size: Size {w: 3f, h: 4f}};
172172
# fn compute_distance(p1: &Point, p2: &Point) -> float { 0f }
173173
compute_distance(&rect_stack.origin, &rect_managed.origin);
174174
~~~
@@ -274,13 +274,14 @@ the following function is legal:
274274

275275
~~~
276276
# fn some_condition() -> bool { true }
277+
# struct Foo { f: int }
277278
fn example3() -> int {
278-
let mut x = ~{f: 3};
279+
let mut x = ~Foo {f: 3};
279280
if some_condition() {
280281
let y = &x.f; // -+ L
281282
return *y; // |
282283
} // -+
283-
x = ~{f: 4};
284+
x = ~Foo {f: 4};
284285
...
285286
# return 0;
286287
}

Diff for: src/libcore/dvec.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
1+
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
22
// file at the top-level directory of this distribution and at
33
// http://rust-lang.org/COPYRIGHT.
44
//
@@ -62,17 +62,17 @@ pub struct DVec<A> {
6262

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

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

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

7878
/// Consumes the vector and returns its contents

Diff for: src/libcore/os.rs

+11-7
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
1+
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
22
// file at the top-level directory of this distribution and at
33
// http://rust-lang.org/COPYRIGHT.
44
//
@@ -321,8 +321,8 @@ pub struct Pipe { mut in: c_int, mut out: c_int }
321321
#[cfg(unix)]
322322
pub fn pipe() -> Pipe {
323323
unsafe {
324-
let mut fds = Pipe {mut in: 0 as c_int,
325-
mut out: 0 as c_int };
324+
let mut fds = Pipe {in: 0 as c_int,
325+
out: 0 as c_int };
326326
assert (libc::pipe(&mut fds.in) == (0 as c_int));
327327
return Pipe {in: fds.in, out: fds.out};
328328
}
@@ -338,8 +338,8 @@ pub fn pipe() -> Pipe {
338338
// fully understand. Here we explicitly make the pipe non-inheritable,
339339
// which means to pass it to a subprocess they need to be duplicated
340340
// first, as in rust_run_program.
341-
let mut fds = Pipe { mut in: 0 as c_int,
342-
mut out: 0 as c_int };
341+
let mut fds = Pipe {in: 0 as c_int,
342+
out: 0 as c_int };
343343
let res = libc::pipe(&mut fds.in, 1024 as c_uint,
344344
(libc::O_BINARY | libc::O_NOINHERIT) as c_int);
345345
assert (res == 0 as c_int);
@@ -565,13 +565,17 @@ pub fn path_exists(p: &Path) -> bool {
565565
*
566566
* If the given path is relative, return it prepended with the current working
567567
* directory. If the given path is already an absolute path, return it
568-
* as is. This is a shortcut for calling os::getcwd().unsafe_join(p)
568+
* as is.
569569
*/
570570
// NB: this is here rather than in path because it is a form of environment
571571
// querying; what it does depends on the process working directory, not just
572572
// the input paths.
573573
pub fn make_absolute(p: &Path) -> Path {
574-
getcwd().unsafe_join(p)
574+
if p.is_absolute {
575+
copy *p
576+
} else {
577+
getcwd().push_many(p.components)
578+
}
575579
}
576580

577581

Diff for: src/libcore/ptr.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
1+
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
22
// file at the top-level directory of this distribution and at
33
// http://rust-lang.org/COPYRIGHT.
44
//
@@ -300,15 +300,15 @@ impl<T:Ord> Ord for &const T {
300300
pub fn test() {
301301
unsafe {
302302
struct Pair {mut fst: int, mut snd: int};
303-
let mut p = Pair {mut fst: 10, mut snd: 20};
303+
let mut p = Pair {fst: 10, snd: 20};
304304
let pptr: *mut Pair = &mut p;
305305
let iptr: *mut int = cast::reinterpret_cast(&pptr);
306306
assert (*iptr == 10);;
307307
*iptr = 30;
308308
assert (*iptr == 30);
309309
assert (p.fst == 30);;
310310

311-
*pptr = Pair {mut fst: 50, mut snd: 60};
311+
*pptr = Pair {fst: 50, snd: 60};
312312
assert (*iptr == 50);
313313
assert (p.fst == 50);
314314
assert (p.snd == 60);

Diff for: src/libstd/ebml.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
1+
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
22
// file at the top-level directory of this distribution and at
33
// http://rust-lang.org/COPYRIGHT.
44
//
@@ -219,7 +219,7 @@ pub mod reader {
219219
}
220220

221221
pub fn Decoder(d: Doc) -> Decoder {
222-
Decoder { mut parent: d, mut pos: d.start }
222+
Decoder { parent: d, pos: d.start }
223223
}
224224

225225
priv impl Decoder {

Diff for: src/libstd/sync.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
1+
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
22
// file at the top-level directory of this distribution and at
33
// http://rust-lang.org/COPYRIGHT.
44
//
@@ -87,7 +87,7 @@ enum Sem<Q> = Exclusive<SemInner<Q>>;
8787
#[doc(hidden)]
8888
fn new_sem<Q:Owned>(count: int, q: Q) -> Sem<Q> {
8989
Sem(exclusive(SemInner {
90-
mut count: count, waiters: new_waitqueue(), blocked: q }))
90+
count: count, waiters: new_waitqueue(), blocked: q }))
9191
}
9292
#[doc(hidden)]
9393
fn new_sem_and_signal(count: int, num_condvars: uint)

Diff for: src/libsyntax/parse/parser.rs

+6-10
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
1+
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
22
// file at the top-level directory of this distribution and at
33
// http://rust-lang.org/COPYRIGHT.
44
//
@@ -1093,15 +1093,10 @@ pub impl Parser {
10931093
self.mk_expr(lo, hi, expr_tup(es))
10941094
}
10951095
} else if *self.token == token::LBRACE {
1096-
if self.looking_at_record_literal() {
1097-
ex = self.parse_record_literal();
1098-
hi = self.span.hi;
1099-
} else {
1100-
self.bump();
1101-
let blk = self.parse_block_tail(lo, default_blk);
1102-
return self.mk_expr(blk.span.lo, blk.span.hi,
1103-
expr_block(blk));
1104-
}
1096+
self.bump();
1097+
let blk = self.parse_block_tail(lo, default_blk);
1098+
return self.mk_expr(blk.span.lo, blk.span.hi,
1099+
expr_block(blk));
11051100
} else if token::is_bar(*self.token) {
11061101
return self.parse_lambda_expr();
11071102
} else if self.eat_keyword(~"if") {
@@ -1223,6 +1218,7 @@ pub impl Parser {
12231218
self.bump();
12241219
let mut fields = ~[];
12251220
let mut base = None;
1221+
12261222
fields.push(self.parse_field(token::COLON));
12271223
while *self.token != token::RBRACE {
12281224
if self.try_parse_obsolete_with() {

Diff for: src/libsyntax/print/pprust.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1209,7 +1209,7 @@ pub fn print_expr(s: @ps, &&expr: @ast::expr) {
12091209
print_expr(s, expr);
12101210
end(s);
12111211
}
1212-
_ => word(s.s, ~",")
1212+
_ => (word(s.s, ~","))
12131213
}
12141214
word(s.s, ~"}");
12151215
}

Diff for: src/test/compile-fail/autoderef-full-lval.rs

+11-6
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,23 @@
99
// except according to those terms.
1010

1111
// error-pattern: mismatched types
12-
type clam = {x: @int, y: @int};
12+
struct clam {
13+
x: @int,
14+
y: @int,
15+
}
1316

14-
type fish = {a: @int};
17+
struct fish {
18+
a: @int,
19+
}
1520

1621
fn main() {
17-
let a: clam = {x: @1, y: @2};
18-
let b: clam = {x: @10, y: @20};
22+
let a: clam = clam{x: @1, y: @2};
23+
let b: clam = clam{x: @10, y: @20};
1924
let z: int = a.x + b.y;
2025
log(debug, z);
2126
assert (z == 21);
22-
let forty: fish = {a: @40};
23-
let two: fish = {a: @2};
27+
let forty: fish = fish{a: @40};
28+
let two: fish = fish{a: @2};
2429
let answer: int = forty.a + two.a;
2530
log(debug, answer);
2631
assert (answer == 42);

0 commit comments

Comments
 (0)