Skip to content

Commit e1e3e2d

Browse files
committed
---
yaml --- r: 4941 b: refs/heads/master c: 63f9b43 h: refs/heads/master i: 4939: 15108e1 v: v3
1 parent dd269f9 commit e1e3e2d

File tree

2 files changed

+61
-6
lines changed

2 files changed

+61
-6
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
---
2-
refs/heads/master: 48c695300192a4475889009b41b8f0ff6dc596bb
2+
refs/heads/master: 63f9b43d36fe9d95d36c3d541c66df04c7c11618

trunk/doc/rust.texi

Lines changed: 60 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -642,6 +642,7 @@ The keywords are:
642642
@tab @code{syntax}
643643
@tab @code{mutable}
644644
@tab @code{native}
645+
@tab @code{unchecked}
645646
@item @code{mod}
646647
@tab @code{import}
647648
@tab @code{export}
@@ -679,7 +680,7 @@ The keywords are:
679680
@tab @code{with}
680681
@item @code{fn}
681682
@tab @code{iter}
682-
@tab @code{pred}
683+
@tab @code{pure}
683684
@tab @code{obj}
684685
@tab @code{resource}
685686
@item @code{if}
@@ -1867,7 +1868,7 @@ control).
18671868
Any pure boolean function is called a @emph{predicate}, and may be used
18681869
as part of the static typestate system. @xref{Ref.Typestate.Constr}. A
18691870
predicate declaration is identical to a function declaration, except that it
1870-
is declared with the keyword @code{pred} instead of @code{fn}. In addition,
1871+
is declared with the additional keyword @code{pure}. In addition,
18711872
the typechecker checks the body of a predicate with a restricted set of
18721873
typechecking rules. A predicate
18731874
@itemize
@@ -1878,11 +1879,65 @@ self-call expression; and
18781879

18791880
An example of a predicate:
18801881
@example
1881-
pred lt_42(int x) -> bool @{
1882+
pure fn lt_42(x: int) -> bool @{
18821883
ret (x < 42);
18831884
@}
18841885
@end example
18851886

1887+
A non-boolean function may also be declared with @code{pure fn}. This allows
1888+
predicates to call non-boolean functions as long as they are pure. For example:
1889+
@example
1890+
pure fn pure_length<@@T>(ls: &list<T>) -> uint @{ /* ... */ @}
1891+
1892+
pure fn nonempty_list<@@T>(ls: &list<T>) -> bool @{ pure_length(ls) > 0u @}
1893+
@end example
1894+
1895+
In this example, @code{nonempty_list} is a predicate---it can be used in a
1896+
typestate constraint---but the auxiliary function @code{pure_length}@ is
1897+
not.
1898+
1899+
@emph{ToDo:} should actually define referential transparency.
1900+
1901+
The effect checking rules previously enumerated are a restricted set of
1902+
typechecking rules meant to approximate the universe of observably
1903+
referentially transparent Rust procedures conservatively. Sometimes, these
1904+
rules are @emph{too} restrictive. Rust allows programmers to violate these
1905+
rules by writing predicates that the compiler cannot prove to be referentially
1906+
transparent, using an escape-hatch feature called ``unchecked blocks''. When
1907+
writing code that uses unchecked blocks, programmers should always be aware
1908+
that they have an obligation to show that the code @emph{behaves} referentially
1909+
transparently at all times, even if the compiler cannot @emph{prove}
1910+
automatically that the code is referentially transparent. In the presence of
1911+
unchecked blocks, the compiler provides no static guarantee that the code will
1912+
behave as expected at runtime. Rather, the programmer has an independent
1913+
obligation to verify the semantics of the predicates they write.
1914+
1915+
@emph{ToDo:} last two sentences are vague.
1916+
1917+
An example of a predicate that uses an unchecked block:
1918+
@example
1919+
fn pure_foldl<@@T, @@U>(ls: &list<T>, u: &U, f: &block(&T, &U) -> U) -> U @{
1920+
alt ls @{
1921+
nil. @{ u @}
1922+
cons(hd, tl) @{ f(hd, pure_foldl(*tl, f(hd, u), f)) @}
1923+
@}
1924+
@}
1925+
1926+
pure fn pure_length<@@T>(ls: &list<T>) -> uint @{
1927+
fn count<T>(_t: &T, u: &uint) -> uint @{ u + 1u @}
1928+
unchecked @{
1929+
pure_foldl(ls, 0u, count)
1930+
@}
1931+
@}
1932+
@end example
1933+
1934+
Despite its name, @code{pure_foldl} is a @code{fn}, not a @code{pure fn},
1935+
because there is no way in Rust to specify that the higher-order function
1936+
argument @code{f} is a pure function. So, to use @code{foldl} in a pure list
1937+
length function that a predicate could then use, we must use an
1938+
@code{unchecked} block wrapped around the call to @code{pure_foldl} in the
1939+
definition of @code{pure_length}.
1940+
18861941
@node Ref.Item.Iter
18871942
@subsection Ref.Item.Iter
18881943
@c * Ref.Item.Iter:: Items defining iterators.
@@ -2684,7 +2739,7 @@ A @dfn{constraint} is a predicate applied to specific slots.
26842739
For example, consider the following code:
26852740

26862741
@example
2687-
pred is_less_than(int a, int b) -> bool @{
2742+
pure fn is_less_than(int a, int b) -> bool @{
26882743
ret a < b;
26892744
@}
26902745
@@ -3461,7 +3516,7 @@ and statically comparing implied states and their
34613516
specifications. @xref{Ref.Typestate}.
34623517

34633518
@example
3464-
pred even(x: &int) -> bool @{
3519+
pure fn even(x: &int) -> bool @{
34653520
ret x & 1 == 0;
34663521
@}
34673522

0 commit comments

Comments
 (0)