make_dir $h/test/perf
make_dir $h/test/pretty
make_dir $h/test/doc-tutorial
+ make_dir $h/test/doc-tutorial-ffi
+ make_dir $h/test/doc-tutorial-macros
+ make_dir $h/test/doc-tutorial-borrowed-ptr
make_dir $h/test/doc-ref
done
point, but allocated in a different place:
~~~
+# type point = {x: float, y: float};
let on_the_stack : point = {x: 3.0, y: 4.0};
let shared_box : @point = @{x: 5.0, y: 1.0};
let unique_box : ~point = ~{x: 7.0, y: 9.0};
borrowed pointers to do this:
~~~
+# type point = {x: float, y: float};
+# fn sqrt(f: float) -> float { 0f }
fn compute_distance(p1: &point, p2: &point) -> float {
let x_d = p1.x - p2.x;
let y_d = p1.y - p2.y;
Now we can call `compute_distance()` in various ways:
-~~~
+~~~ {.xfail-test}
+# type point = {x: float, y: float};
+# let on_the_stack : point = {x: 3.0, y: 4.0};
+# let shared_box : @point = @{x: 5.0, y: 1.0};
+# let unique_box : ~point = ~{x: 7.0, y: 9.0};
+# fn compute_distance(p1: &point, p2: &point) -> float { 0f }
compute_distance(&on_the_stack, shared_box)
compute_distance(shared_box, unique_box)
~~~
In the previous example, the value `on_the_stack` was defined like so:
~~~
+# type point = {x: float, y: float};
let on_the_stack : point = {x: 3.0, y: 4.0};
~~~
operator into the definition of `on_the_stack`:
~~~
+# type point = {x: float, y: float};
let on_the_stack2 : &point = &{x: 3.0, y: 4.0};
~~~
shorthand for creating a temporary and taking its address:
~~~
+# type point = {x: float, y: float};
let tmp = {x: 3.0, y: 4.0};
let on_the_stack2 : &point = &tmp;
~~~
In each case I can use the `&` operator to extact out individual
subcomponents. For example, I could write:
-~~~
+~~~ {.xfail-test}
+# type point = {x: float, y: float};
+# type size = {w: float, h: float}; // as before
+# type rectangle = {origin: point, size: size};
+# let rect_stack = &{origin: {x: 1, y: 2}, size: {w: 3, h: 4}};
+# let rect_shared = @{origin: {x: 3, y: 4}, size: {w: 3, h: 4}};
+# let rect_unique = ~{origin: {x: 5, y: 6}, size: {w: 3, h: 4}};
+# fn compute_distance(p1: &point, p2: &point) -> float { 0f }
compute_distance(&rect_stack.origin, &rect_shared.origin);
~~~
the following function is legal:
~~~
+# fn some_condition() -> bool { true }
fn example3() -> int {
let mut x = ~{f: 3};
- if some_condition {
+ if some_condition() {
let y = &x.f; // -+ L
- ret *y; // |
+ return *y; // |
} // -+
x = ~{f: 4};
...
+# return 0;
}
~~~
scope_. Therefore, a program like this is illegal (and would be
rejected by the compiler):
-~~~
+~~~ {.xfail-test}
fn example3() -> int {
let mut x = ~{f: 3};
let y = &x.f;
additional unique pointers and records, and the compiler will still be
able to detect possible mutations:
-~~~
+~~~ {.xfail-test}
fn example3() -> int {
let mut x = ~{mut f: ~{g: 3}};
let y = &x.f.g;
stack frame (or when the compiler doesn’t know who the owner
is). Consider a program like this:
-~~~
-fn example5a(x: @{mut f: ~{g: int}}, ...) -> int {
+~~~ {.xfail-test}
+fn example5a(x: @{mut f: ~{g: int}} ...) -> int {
let y = &x.f.g; // Error reported here.
...
}
unique fields, as in the following example:
~~~
-fn example5b(x: @{f: ~{g: int}}, ...) -> int {
+fn example5b(x: @{f: ~{g: int}}) -> int {
let y = &x.f.g;
...
+# return 0;
}
~~~
it, one option is to use the swap operator to bring that unique box
onto your stack:
-~~~
-fn example5c(x: @{mut f: ~int}, ...) -> int {
+~~~ {.xfail-test}
+fn example5c(x: @{mut f: ~int}) -> int {
let mut v = ~0;
v <-> x.f; // Swap v and x.f
let y = &v;
...
x.f <- v; // Replace x.f
+ ...
+# return 0;
}
~~~
copying them.
~~~
+# type point = {x: float, y: float}; // as before
+# type size = {w: float, h: float}; // as before
+# enum shape {
+# circle(point, float), // origin, radius
+# rectangle(point, size) // upper-left, dimensions
+# }
+# const tau: float = 6.28f;
fn compute_area(shape: &shape) -> float {
- alt *shape {
+ match *shape {
circle(_, radius) => 0.5 * tau * radius * radius,
rectangle(_, ref size) => size.w * size.h
}
For example, we could write a subroutine like this:
-~~~
+~~~ {.xfail-test}
type point = {x: float, y: float};
fn get_x(p: &point) -> &float { &p.x }
~~~
To drill in this point, let’s look at a variation on the example, this
time one which does not compile:
-~~~
+~~~ {.xfail-test}
type point = {x: float, y: float};
fn get_x_sh(p: @point) -> &float {
&p.x // Error reported here
useful to be able to group those parameters by lifetime. For example,
consider this function:
-~~~
+~~~ {.xfail-test}
+# type point = {x: float, y: float}; // as before
+# type size = {w: float, h: float}; // as before
+# enum shape {
+# circle(point, float), // origin, radius
+# rectangle(point, size) // upper-left, dimensions
+# }
+# fn compute_area(shape: &shape) -> float { 0f }
fn select<T>(shape: &shape, threshold: float,
a: &T, b: &T) -> &T {
if compute_area(shape) > threshold {a} else {b}
lifetime of the three region parameters. This may be overloy
conservative, as in this example:
-~~~
+~~~ {.xfail-test}
+# type point = {x: float, y: float}; // as before
+# type size = {w: float, h: float}; // as before
+# enum shape {
+# circle(point, float), // origin, radius
+# rectangle(point, size) // upper-left, dimensions
+# }
+# fn compute_area(shape: &shape) -> float { 0f }
+# fn select<T>(shape: &shape, threshold: float,
+# a: &T, b: &T) -> &T {
+# if compute_area(shape) > threshold {a} else {b}
+# }
+
// -+ L
fn select_based_on_unit_circle<T>( // |-+ B
threshold: float, a: &T, b: &T) -> &T { // | |
do not need to be declared, you just use them. Here is how the new
`select()` might look:
-~~~
+~~~ {.xfail-test}
+# type point = {x: float, y: float}; // as before
+# type size = {w: float, h: float}; // as before
+# enum shape {
+# circle(point, float), // origin, radius
+# rectangle(point, size) // upper-left, dimensions
+# }
+# fn compute_area(shape: &shape) -> float { 0f }
fn select<T>(shape: &tmp/shape, threshold: float,
a: &T, b: &T) -> &T {
if compute_area(shape) > threshold {a} else {b}
You could also write `select()` using all named lifetime parameters,
which might look like:
-~~~
+~~~ {.xfail-test}
+# type point = {x: float, y: float}; // as before
+# type size = {w: float, h: float}; // as before
+# enum shape {
+# circle(point, float), // origin, radius
+# rectangle(point, size) // upper-left, dimensions
+# }
+# fn compute_area(shape: &shape) -> float { 0f }
fn select<T>(shape: &tmp/shape, threshold: float,
a: &r/T, b: &r/T) -> &r/T {
if compute_area(shape) > threshold {a} else {b}
replaced the `...` with some specific code:
~~~
-fn example5a(x: @{mut f: ~{g: int}}, ...) -> int {
+fn example5a(x: @{mut f: ~{g: int}} ...) -> int {
let y = &x.f.g; // Unsafe
*y + 1
}
We can now update `example5a()` to use `add_one()`:
-~~~
-fn example5a(x: @{mut f: ~{g: int}}, ...) -> int {
+~~~ {.xfail-test}
+# fn add_one(x: &int) -> int { *x + 1 }
+fn example5a(x: @{mut f: ~{g: int}} ...) -> int {
let y = &x.f.g;
add_one(y) // Error reported here
}
fn sha1(data: ~str) -> ~str unsafe {
let bytes = str::to_bytes(data);
- let hash = crypto::SHA1(vec::unsafe::to_ptr(bytes),
+ let hash = crypto::SHA1(vec::raw::to_ptr(bytes),
vec::len(bytes) as c_uint, ptr::null());
- return as_hex(vec::unsafe::from_buf(hash, 20u));
+ return as_hex(vec::raw::from_buf(hash, 20u));
}
fn main(args: ~[~str]) {
fn sha1(data: ~str) -> ~str {
unsafe {
let bytes = str::to_bytes(data);
- let hash = crypto::SHA1(vec::unsafe::to_ptr(bytes),
+ let hash = crypto::SHA1(vec::raw::to_ptr(bytes),
vec::len(bytes), ptr::null());
- return as_hex(vec::unsafe::from_buf(hash, 20u));
+ return as_hex(vec::raw::from_buf(hash, 20u));
}
}
~~~~
# fn x(data: ~str) -> ~str {
# unsafe {
let bytes = str::to_bytes(data);
-let hash = crypto::SHA1(vec::unsafe::to_ptr(bytes),
+let hash = crypto::SHA1(vec::raw::to_ptr(bytes),
vec::len(bytes), ptr::null());
-return as_hex(vec::unsafe::from_buf(hash, 20u));
+return as_hex(vec::raw::from_buf(hash, 20u));
# }
# }
~~~~
The `str::to_bytes` function is perfectly safe: it converts a string to
-a `[u8]`. This byte array is then fed to `vec::unsafe::to_ptr`, which
+a `[u8]`. This byte array is then fed to `vec::raw::to_ptr`, which
returns an unsafe pointer to its contents.
This pointer will become invalid as soon as the vector it points into
like that—they can take the right form depending on the type that they
are expected to return).
-Finally, `vec::unsafe::from_buf` builds up a new `[u8]` from the
+Finally, `vec::raw::from_buf` builds up a new `[u8]` from the
unsafe pointer that was returned by `SHA1`. SHA1 digests are always
twenty bytes long, so we can pass `20u` for the length of the new
vector.
$$(Q)rm -f $(1)/test/doc-tutorial/*.rs
$$(Q)$$(EXTRACT_TESTS) $$(S)doc/tutorial.md $(1)/test/doc-tutorial
+doc-tutorial-ffi-extract$(1):
+ @$$(call E, extract: tutorial-ffi tests)
+ $$(Q)rm -f $(1)/test/doc-tutorial-ffi/*.rs
+ $$(Q)$$(EXTRACT_TESTS) $$(S)doc/tutorial-ffi.md $(1)/test/doc-tutorial-ffi
+
+doc-tutorial-macros-extract$(1):
+ @$$(call E, extract: tutorial-macros tests)
+ $$(Q)rm -f $(1)/test/doc-tutorial-macros/*.rs
+ $$(Q)$$(EXTRACT_TESTS) $$(S)doc/tutorial-macros.md $(1)/test/doc-tutorial-macros
+
+doc-tutorial-borrowed-ptr-extract$(1):
+ @$$(call E, extract: tutorial-borrowed-ptr tests)
+ $$(Q)rm -f $(1)/test/doc-tutorial-borrowed-ptr/*.rs
+ $$(Q)$$(EXTRACT_TESTS) $$(S)doc/tutorial-borrowed-ptr.md $(1)/test/doc-tutorial-borrowed-ptr
+
doc-ref-extract$(1):
@$$(call E, extract: ref tests)
$$(Q)rm -f $(1)/test/doc-ref/*.rs
check-stage$(1)-T-$(2)-H-$(3)-rustdoc \
check-stage$(1)-T-$(2)-H-$(3)-cargo \
check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial \
+ check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial-ffi \
+ check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial-macros \
+ check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial-borrowed-ptr \
check-stage$(1)-T-$(2)-H-$(3)-doc-ref
check-stage$(1)-T-$(2)-H-$(3)-core: \
check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial: \
check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial-dummy
+check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial-ffi: \
+ check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial-ffi-dummy
+
+check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial-macros: \
+ check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial-macros-dummy
+
+check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial-borrowed-ptr: \
+ check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial-borrowed-ptr-dummy
+
check-stage$(1)-T-$(2)-H-$(3)-doc-ref: \
check-stage$(1)-T-$(2)-H-$(3)-doc-ref-dummy
--build-base $(3)/test/doc-tutorial/ \
--mode run-pass
+DOC_TUTORIAL_FFI_ARGS$(1)-T-$(2)-H-$(3) := \
+ $$(CTEST_COMMON_ARGS$(1)-T-$(2)-H-$(3)) \
+ --src-base $(3)/test/doc-tutorial-ffi/ \
+ --build-base $(3)/test/doc-tutorial-ffi/ \
+ --mode run-pass
+
+DOC_TUTORIAL_MACROS_ARGS$(1)-T-$(2)-H-$(3) := \
+ $$(CTEST_COMMON_ARGS$(1)-T-$(2)-H-$(3)) \
+ --src-base $(3)/test/doc-tutorial-macros/ \
+ --build-base $(3)/test/doc-tutorial-macros/ \
+ --mode run-pass
+
+DOC_TUTORIAL_BORROWED_PTR_ARGS$(1)-T-$(2)-H-$(3) := \
+ $$(CTEST_COMMON_ARGS$(1)-T-$(2)-H-$(3)) \
+ --src-base $(3)/test/doc-tutorial-borrowed-ptr/ \
+ --build-base $(3)/test/doc-tutorial-borrowed-ptr/ \
+ --mode run-pass
+
DOC_REF_ARGS$(1)-T-$(2)-H-$(3) := \
$$(CTEST_COMMON_ARGS$(1)-T-$(2)-H-$(3)) \
--src-base $(3)/test/doc-ref/ \
$$(DOC_TUTORIAL_ARGS$(1)-T-$(2)-H-$(3)) \
--logfile tmp/check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial.log
+check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial-ffi-dummy: \
+ $$(TEST_SREQ$(1)_T_$(2)_H_$(3)) \
+ doc-tutorial-ffi-extract$(3)
+ @$$(call E, run doc-tutorial-ffi: $$<)
+ $$(Q)$$(call CFG_RUN_CTEST,$(1),$$<,$(3)) \
+ $$(DOC_TUTORIAL_FFI_ARGS$(1)-T-$(2)-H-$(3)) \
+ --logfile tmp/check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial-ffi.log
+
+check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial-macros-dummy: \
+ $$(TEST_SREQ$(1)_T_$(2)_H_$(3)) \
+ doc-tutorial-macros-extract$(3)
+ @$$(call E, run doc-tutorial-macros: $$<)
+ $$(Q)$$(call CFG_RUN_CTEST,$(1),$$<,$(3)) \
+ $$(DOC_TUTORIAL_MACROS_ARGS$(1)-T-$(2)-H-$(3)) \
+ --logfile tmp/check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial-macros.log
+
+check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial-borrowed-ptr-dummy: \
+ $$(TEST_SREQ$(1)_T_$(2)_H_$(3)) \
+ doc-tutorial-borrowed-ptr-extract$(3)
+ @$$(call E, run doc-tutorial-borrowed-ptr: $$<)
+ $$(Q)$$(call CFG_RUN_CTEST,$(1),$$<,$(3)) \
+ $$(DOC_TUTORIAL_BORROWED_PTR_ARGS$(1)-T-$(2)-H-$(3)) \
+ --logfile tmp/check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial-borrowed-ptr.log
+
check-stage$(1)-T-$(2)-H-$(3)-doc-ref-dummy: \
$$(TEST_SREQ$(1)_T_$(2)_H_$(3)) \
doc-ref-extract$(3)
check-stage$(1)-H-$(2)-doc-tutorial: \
$$(foreach target,$$(CFG_TARGET_TRIPLES), \
check-stage$(1)-T-$$(target)-H-$(2)-doc-tutorial)
+check-stage$(1)-H-$(2)-doc-tutorial-ffi: \
+ $$(foreach target,$$(CFG_TARGET_TRIPLES), \
+ check-stage$(1)-T-$$(target)-H-$(2)-doc-tutorial-ffi)
+check-stage$(1)-H-$(2)-doc-tutorial-macros: \
+ $$(foreach target,$$(CFG_TARGET_TRIPLES), \
+ check-stage$(1)-T-$$(target)-H-$(2)-doc-tutorial-macros)
+check-stage$(1)-H-$(2)-doc-tutorial-borrowed-ptr: \
+ $$(foreach target,$$(CFG_TARGET_TRIPLES), \
+ check-stage$(1)-T-$$(target)-H-$(2)-doc-tutorial-borrowed-ptr)
check-stage$(1)-H-$(2)-doc-ref: \
$$(foreach target,$$(CFG_TARGET_TRIPLES), \
check-stage$(1)-T-$$(target)-H-$(2)-doc-ref)
check-stage$(1)-rustdoc: check-stage$(1)-H-$$(CFG_HOST_TRIPLE)-rustdoc
check-stage$(1)-cargo: check-stage$(1)-H-$$(CFG_HOST_TRIPLE)-cargo
check-stage$(1)-doc-tutorial: check-stage$(1)-H-$$(CFG_HOST_TRIPLE)-doc-tutorial
+check-stage$(1)-doc-tutorial-ffi: check-stage$(1)-H-$$(CFG_HOST_TRIPLE)-doc-tutorial-ffi
+check-stage$(1)-doc-tutorial-macros: check-stage$(1)-H-$$(CFG_HOST_TRIPLE)-doc-tutorial-macros
+check-stage$(1)-doc-tutorial-borrowed-ptr: check-stage$(1)-H-$$(CFG_HOST_TRIPLE)-doc-tutorial-borrowed-ptr
check-stage$(1)-doc-ref: check-stage$(1)-H-$$(CFG_HOST_TRIPLE)-doc-ref
endef
if re.match("~~~", line):
break
else:
- block += re.sub("^# ", "", line)
+ # Lines beginning with '# ' are turned into valid code
+ line = re.sub("^# ", "", line)
+ # Allow elipses in code snippets
+ line = re.sub("\.\.\.", "/*...*/", line)
+ block += line
if not ignore:
if not re.search(r"\bfn main\b", block):
block = "fn main() {\n" + block + "\n}\n"