Skip to content

Commit a432e7e

Browse files
committed
---
yaml --- r: 29748 b: refs/heads/incoming c: 8d26d86 h: refs/heads/master v: v3
1 parent 1666d64 commit a432e7e

File tree

327 files changed

+3613
-6719
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

327 files changed

+3613
-6719
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ refs/heads/try: d324a424d8f84b1eb049b12cf34182bda91b0024
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b
88
refs/heads/try2: d0c6ce338884ee21843f4b40bf6bf18d222ce5df
9-
refs/heads/incoming: f9946f37aa14ae98f934c0f9cebffee97dc0d0da
9+
refs/heads/incoming: 8d26d86b708b4597e761034fe3a2cc8a7a08c85f
1010
refs/heads/dist-snap: 2f32a1581f522e524009138b33b1c7049ced668d
1111
refs/tags/release-0.2: c870d2dffb391e14efb05aa27898f1f6333a9596
1212
refs/tags/release-0.3: b5f0d0f648d9a6153664837026ba1be43d3e2503

branches/incoming/doc/rust.md

Lines changed: 55 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -899,51 +899,58 @@ express that `f` requires no explicit `return`, as if it returns
899899
control to the caller, it returns a value (true because it never returns
900900
control).
901901

902-
#### Pure functions
902+
#### Predicate functions
903903

904-
A pure function declaration is identical to a function declaration, except that
905-
it is declared with the additional keyword `pure`. In addition, the typechecker
906-
checks the body of a pure function with a restricted set of typechecking rules.
907-
A pure function
904+
Any pure boolean function is called a *predicate function*, and may be used in
905+
a [constraint](#constraints), as part of the static [typestate
906+
system](#typestate-system). A predicate declaration is identical to a function
907+
declaration, except that it is declared with the additional keyword `pure`. In
908+
addition, the typechecker checks the body of a predicate with a restricted set
909+
of typechecking rules. A predicate
908910

909911
* may not contain an assignment or self-call expression; and
910-
* may only call other pure functions, not general functions.
912+
* may only call other predicates, not general functions.
911913

912-
An example of a pure function:
914+
An example of a predicate:
913915

914916
~~~~
915917
pure fn lt_42(x: int) -> bool {
916918
return (x < 42);
917919
}
918920
~~~~
919921

920-
Pure functions may call other pure functions:
922+
A non-boolean function may also be declared with `pure fn`. This allows
923+
predicates to call non-boolean functions as long as they are pure. For example:
921924

922925
~~~~{.xfail-test}
923926
pure fn pure_length<T>(ls: list<T>) -> uint { /* ... */ }
924927
925928
pure fn nonempty_list<T>(ls: list<T>) -> bool { pure_length(ls) > 0u }
926929
~~~~
927930

931+
In this example, `nonempty_list` is a predicate---it can be used in a
932+
typestate constraint---but the auxiliary function `pure_length` is
933+
not.
934+
928935
*TODO:* should actually define referential transparency.
929936

930937
The effect checking rules previously enumerated are a restricted set of
931938
typechecking rules meant to approximate the universe of observably
932939
referentially transparent Rust procedures conservatively. Sometimes, these
933940
rules are *too* restrictive. Rust allows programmers to violate these rules by
934-
writing pure functions that the compiler cannot prove to be referentially
941+
writing predicates that the compiler cannot prove to be referentially
935942
transparent, using an escape-hatch feature called "unchecked blocks". When
936943
writing code that uses unchecked blocks, programmers should always be aware
937944
that they have an obligation to show that the code *behaves* referentially
938945
transparently at all times, even if the compiler cannot *prove* automatically
939946
that the code is referentially transparent. In the presence of unchecked
940947
blocks, the compiler provides no static guarantee that the code will behave as
941948
expected at runtime. Rather, the programmer has an independent obligation to
942-
verify the semantics of the pure functions they write.
949+
verify the semantics of the predicates they write.
943950

944951
*TODO:* last two sentences are vague.
945952

946-
An example of a pure function that uses an unchecked block:
953+
An example of a predicate that uses an unchecked block:
947954

948955
~~~~
949956
# import std::list::*;
@@ -965,7 +972,7 @@ pure fn pure_length<T>(ls: list<T>) -> uint {
965972

966973
Despite its name, `pure_foldl` is a `fn`, not a `pure fn`, because there is no
967974
way in Rust to specify that the higher-order function argument `f` is a pure
968-
function. So, to use `foldl` in a pure list length function that a pure function
975+
function. So, to use `foldl` in a pure list length function that a predicate
969976
could then use, we must use an `unchecked` block wrapped around the call to
970977
`pure_foldl` in the definition of `pure_length`.
971978

@@ -1129,8 +1136,8 @@ looks like:
11291136

11301137
The only exception is that the body of the class constructor begins
11311138
with all the class's fields uninitialized, and is allowed to -- in
1132-
fact, must -- initialize all the fields. The compiler enforces this
1133-
invariant.
1139+
fact, must -- initialize all the fields. A special case in the
1140+
typestate pass enforces this invariant.
11341141

11351142
Usually, the class constructor stores its argument or arguments in the
11361143
class's named fields. In this case, the `file_descriptor`'s data field
@@ -1299,7 +1306,7 @@ type.
12991306

13001307
~~~~
13011308
# trait shape { }
1302-
# impl int: shape { }
1309+
# impl of shape for int { }
13031310
# let mycircle = 0;
13041311
13051312
let myshape: shape = mycircle as shape;
@@ -1325,7 +1332,7 @@ An _implementation item_ provides an implementation of a
13251332
13261333
type circle = {radius: float, center: point};
13271334
1328-
impl circle: shape {
1335+
impl circle_shape of shape for circle {
13291336
fn draw(s: surface) { do_draw_circle(s, self); }
13301337
fn bounding_box() -> bounding_box {
13311338
let r = self.radius;
@@ -1363,10 +1370,10 @@ specified, after the `impl` keyword.
13631370
~~~~
13641371
# trait seq<T> { }
13651372
1366-
impl<T> ~[T]: seq<T> {
1373+
impl <T> of seq<T> for ~[T] {
13671374
/* ... */
13681375
}
1369-
impl u32: seq<bool> {
1376+
impl of seq<bool> for u32 {
13701377
/* Treat the integer as a sequence of bits */
13711378
}
13721379
~~~~
@@ -1927,15 +1934,13 @@ x <- copy y;
19271934

19281935
The former is just more terse and familiar.
19291936

1930-
#### Compound assignment expressions
1937+
#### Operator-assignment expressions
19311938

19321939
The `+`, `-`, `*`, `/`, `%`, `&`, `|`, `^`, `<<`, `>>`, and `>>>`
19331940
operators may be composed with the `=` operator. The expression `lval
19341941
OP= val` is equivalent to `lval = lval OP val`. For example, `x = x +
19351942
1` may be written as `x += 1`.
19361943

1937-
Any such expression always has the [`nil`](#primitive-types) type.
1938-
19391944
#### Operator precedence
19401945

19411946
The precedence of Rust binary operators is ordered as follows, going
@@ -2069,6 +2074,31 @@ A `loop` expression denotes an infinite loop:
20692074
loop_expr : "loop" '{' block '}';
20702075
~~~~~~~~
20712076

2077+
For a block `b`, the expression `loop b` is semantically equivalent to
2078+
`while true b`. However, `loop`s differ from `while` loops in that the
2079+
typestate analysis pass takes into account that `loop`s are infinite.
2080+
2081+
For example, the following (contrived) function uses a `loop` with a
2082+
`return` expression:
2083+
2084+
~~~~
2085+
fn count() -> bool {
2086+
let mut i = 0;
2087+
loop {
2088+
i += 1;
2089+
if i == 20 { return true; }
2090+
}
2091+
}
2092+
~~~~
2093+
2094+
This function compiles, because typestate recognizes that the `loop`
2095+
never terminates (except non-locally, with `return`), thus there is no
2096+
need to insert a spurious `fail` or `return` after the `loop`. If `loop`
2097+
were replaced with `while true`, the function would be rejected
2098+
because from the compiler's perspective, there would be a control path
2099+
along which `count` does not return a value (that is, if the loop
2100+
condition is always false).
2101+
20722102
### Break expressions
20732103

20742104
~~~~~~~~{.ebnf .gram}
@@ -2510,7 +2540,7 @@ macro-generated and user-written code can cause unintentional capture.
25102540
Future versions of Rust will address these issues.
25112541

25122542

2513-
# Type system
2543+
# Types and typestates
25142544

25152545
## Types
25162546

@@ -2728,7 +2758,7 @@ trait printable {
27282758
fn to_str() -> ~str;
27292759
}
27302760
2731-
impl ~str: printable {
2761+
impl of printable for ~str {
27322762
fn to_str() -> ~str { self }
27332763
}
27342764
@@ -2775,7 +2805,7 @@ trait printable {
27752805
fn to_str() -> ~str;
27762806
}
27772807
2778-
impl ~str: printable {
2808+
impl of printable for ~str {
27792809
fn to_str() -> ~str { self }
27802810
}
27812811
~~~~~~
@@ -2936,7 +2966,7 @@ Local variables are not initialized when allocated; the entire frame worth of
29362966
local variables are allocated at once, on frame-entry, in an uninitialized
29372967
state. Subsequent statements within a function may or may not initialize the
29382968
local variables. Local variables can be used only after they have been
2939-
initialized; this is enforced by the compiler.
2969+
initialized; this condition is guaranteed by the typestate system.
29402970

29412971
References are created for function arguments. If the compiler can not prove
29422972
that the referred-to value will outlive the reference, it will try to set

0 commit comments

Comments
 (0)