@@ -642,6 +642,7 @@ The keywords are:
642
642
@tab @code {syntax }
643
643
@tab @code {mutable }
644
644
@tab @code {native }
645
+ @tab @code {unchecked }
645
646
@item @code {mod }
646
647
@tab @code {import }
647
648
@tab @code {export }
@@ -679,7 +680,7 @@ The keywords are:
679
680
@tab @code {with }
680
681
@item @code {fn }
681
682
@tab @code {iter }
682
- @tab @code {pred }
683
+ @tab @code {pure }
683
684
@tab @code {obj }
684
685
@tab @code {resource }
685
686
@item @code {if }
@@ -1867,7 +1868,7 @@ control).
1867
1868
Any pure boolean function is called a @emph {predicate }, and may be used
1868
1869
as part of the static typestate system. @xref {Ref.Typestate.Constr }. A
1869
1870
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,
1871
1872
the typechecker checks the body of a predicate with a restricted set of
1872
1873
typechecking rules. A predicate
1873
1874
@itemize
@@ -1878,11 +1879,65 @@ self-call expression; and
1878
1879
1879
1880
An example of a predicate:
1880
1881
@example
1881
- pred lt_42(int x ) -> bool @{
1882
+ pure fn lt_42(x: int ) -> bool @{
1882
1883
ret (x < 42);
1883
1884
@}
1884
1885
@end example
1885
1886
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
+
1886
1941
@node Ref.Item.Iter
1887
1942
@subsection Ref.Item.Iter
1888
1943
@c * Ref.Item.Iter:: Items defining iterators.
@@ -2684,7 +2739,7 @@ A @dfn{constraint} is a predicate applied to specific slots.
2684
2739
For example, consider the following code:
2685
2740
2686
2741
@example
2687
- pred is_less_than(int a, int b) -> bool @{
2742
+ pure fn is_less_than(int a, int b) -> bool @{
2688
2743
ret a < b;
2689
2744
@}
2690
2745
@@ -3461,7 +3516,7 @@ and statically comparing implied states and their
3461
3516
specifications. @xref {Ref.Typestate }.
3462
3517
3463
3518
@example
3464
- pred even(x: &int) -> bool @{
3519
+ pure fn even(x: &int) -> bool @{
3465
3520
ret x & 1 == 0;
3466
3521
@}
3467
3522
0 commit comments