From 982a1a47830ae0419db620374ffe2f0e018843cf Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 12 Sep 2011 14:24:12 +0200 Subject: [PATCH] Rename alias to reference in docs and error messages Update docs to reflect new approach to aliases --- doc/rust.texi | 71 +++++++++---------- src/comp/middle/alias.rs | 9 +-- src/comp/middle/mut.rs | 8 +-- src/test/compile-fail/unsafe-alias-2.rs | 2 +- src/test/compile-fail/unsafe-alt.rs | 2 +- src/test/compile-fail/unsafe-for.rs | 2 +- src/test/compile-fail/unsafe-mutable-alias.rs | 2 +- 7 files changed, 45 insertions(+), 51 deletions(-) diff --git a/doc/rust.texi b/doc/rust.texi index bc86c130c5ce..175552bc42ff 100644 --- a/doc/rust.texi +++ b/doc/rust.texi @@ -253,21 +253,21 @@ way. To allocate such values in the heap, they must be explicitly value, its @emph{content}. Boxes may be either shared or unique, depending on which sort of storage management is desired. -Boxing and unboxing in Rust is explicit, though in many cases (arithmetic -operations, name-component dereferencing) Rust will automatically ``reach -through'' the box to access its content. Box values can be passed and assigned +Boxing and unboxing in Rust is explicit, though in many cases (such as +name-component dereferencing) Rust will automatically ``reach through'' the +box to access its content. Box values can be passed and assigned independently, like pointers in C; the difference is that in Rust they always point to live contents, and are not subject to pointer arithmetic. -In addition to boxes, Rust supports a kind of pass-by-reference slot called an -alias. Forming or releasing an alias does not perform reference-count -operations; aliases can only be formed on referents that will provably outlive -the alias, and are therefore only used for passing arguments to -functions. Aliases are not ``general values'', in the sense that they cannot -be independently manipulated. They are more like C++ references, except that -like boxes, aliases are safe: they always point to live values. +In addition to boxes, Rust supports a kind of pass-by-pointer slot called a +reference. Forming or releasing a reference does not perform reference-count +operations; references can only be formed on values that will provably outlive +the reference. References are not ``general values'', in the sense that they +cannot be independently manipulated. They are a lot like C++'s references, +except that they are safe: the compiler ensures that they always point to live +values. -In addition, every slot (stack-local allocation or alias) has a static +In addition, every slot (stack-local allocation or reference) has a static initialization state that is calculated by the typestate system. This permits late initialization of slots in functions with complex control-flow, while still guaranteeing that every use of a slot occurs after it has been @@ -1283,7 +1283,7 @@ references to any boxes. @cindex Stack @cindex Slot @cindex Local slot -@cindex Alias slot +@cindex Reference slot A task's stack contains slots. @@ -1293,10 +1293,9 @@ an @emph{alias}. A @dfn{local} slot (or @emph{stack-local} allocation) holds a value directly, allocated within the stack's memory. The value is a part of the stack frame. -An @dfn{alias} references a value outside the frame. An alias may refer to a +A @dfn{reference} references a value outside the frame. It may refer to a value allocated in another frame @emph{or} a boxed value in the heap. The -alias-formation rules ensure that the referent of an alias will outlive the -alias. +reference-formation rules ensure that the referent will outlive the reference. Local slots are always implicitly mutable. @@ -1306,24 +1305,18 @@ state. Subsequent statements within a function may or may not initialize the local slots. Local slots can only be used after they have been initialized; this condition is guaranteed by the typestate system. -Aliases can @emph{only} be declared as arguments in a function or iterator -signature, bound to the lifetime of a stack frame. Aliases are not general -values and cannot be held in boxed allocations or other general data types. +References are created for function arguments. If the compiler can not prove +that the referred-to value will outlive the reference, it will try to set +aside a copy of that value to refer to. If this is not sematically safe (for +example, if the referred-to value contains mutable fields), it reject the +program. If the compiler deems copying the value expensive, it will warn. -Alias slots are indicated by the @emph{ampersand} sigil @code{&}. +A function can be declared to take an argument by mutable reference. This +allows the function to write to the slot that the reference refers to. -An example function that accepts an alias parameter: +An example function that accepts an value by mutable reference: @example -type point3d = @{x: int, y: int, z: int@}; - -fn extract_z(p: &point3d) -> int @{ - ret p.z; -@} -@end example - -An example function that accepts an alias to a mutable value: -@example -fn incr(i: &mutable int) @{ +fn incr(&i: int) @{ i = i + 1; @} @end example @@ -1912,9 +1905,9 @@ pure fn lt_42(x: int) -> bool @{ A non-boolean function may also be declared with @code{pure fn}. This allows predicates to call non-boolean functions as long as they are pure. For example: @example -pure fn pure_length<@@T>(ls: &list) -> uint @{ /* ... */ @} +pure fn pure_length<@@T>(ls: list) -> uint @{ /* ... */ @} -pure fn nonempty_list<@@T>(ls: &list) -> bool @{ pure_length(ls) > 0u @} +pure fn nonempty_list<@@T>(ls: list) -> bool @{ pure_length(ls) > 0u @} @end example In this example, @code{nonempty_list} is a predicate---it can be used in a @@ -1941,15 +1934,15 @@ obligation to verify the semantics of the predicates they write. An example of a predicate that uses an unchecked block: @example -fn pure_foldl<@@T, @@U>(ls: &list, u: &U, f: &block(&T, &U) -> U) -> U @{ +fn pure_foldl<@@T, @@U>(ls: list, u: U, f: block(&T, &U) -> U) -> U @{ alt ls @{ nil. @{ u @} cons(hd, tl) @{ f(hd, pure_foldl(*tl, f(hd, u), f)) @} @} @} -pure fn pure_length<@@T>(ls: &list) -> uint @{ - fn count(_t: &T, u: &uint) -> uint @{ u + 1u @} +pure fn pure_length<@@T>(ls: list) -> uint @{ + fn count(_t: T, u: uint) -> uint @{ u + 1u @} unchecked @{ pure_foldl(ls, 0u, count) @} @@ -2280,7 +2273,7 @@ The primitive types are the following: @item The ``nil'' type @code{()}, having the single ``nil'' value @code{()}.@footnote{The ``nil'' value @code{()} is @emph{not} a sentinel -``null pointer'' value for alias slots; the ``nil'' type is the implicit +``null pointer'' value for reference slots; the ``nil'' type is the implicit return type from functions otherwise lacking a return type, and can be used in other contexts (such as message-sending or type-parametric code) as a zero-size type.} @@ -3062,7 +3055,7 @@ x.y = z + 2; @cindex Function calls A @dfn{call expression} invokes a function, providing a tuple of input slots -and an alias slot to serve as the function's output, bound to the @var{lval} +and an reference slot to serve as the function's output, bound to the @var{lval} on the right hand side of the call. If the function eventually returns, then the expression completes. @@ -3247,7 +3240,7 @@ diagnostic buffer. An example of a @code{note} expression: @example -fn read_file_lines(path: &str) -> [str] @{ +fn read_file_lines(path: str) -> [str] @{ note path; let r: [str]; let f: file = open_read(path); @@ -3541,7 +3534,7 @@ and statically comparing implied states and their specifications. @xref{Ref.Typestate}. @example -pure fn even(x: &int) -> bool @{ +pure fn even(x: int) -> bool @{ ret x & 1 == 0; @} diff --git a/src/comp/middle/alias.rs b/src/comp/middle/alias.rs index cfffa6e89c6c..602554cb0d0a 100644 --- a/src/comp/middle/alias.rs +++ b/src/comp/middle/alias.rs @@ -266,9 +266,10 @@ fn check_call(cx: ctx, f: @ast::expr, args: [@ast::expr], sc: scope) -> alt r.root_var { some(root) { if node == root && cant_copy(cx, r) { - cx.tcx.sess.span_err(args[arg].span, - "passing a mutable alias to a \ - variable that roots another alias"); + cx.tcx.sess.span_err + (args[arg].span, + "passing a mutable reference to a \ + variable that roots another reference"); break; } } @@ -415,7 +416,7 @@ fn test_scope(cx: ctx, sc: scope, r: restrict, p: ast::path) { } }; cx.tcx.sess.span_err(msg.span, - msg.msg + " will invalidate alias " + + msg.msg + " will invalidate reference " + ast_util::path_name(p) + ", which is still used"); } diff --git a/src/comp/middle/mut.rs b/src/comp/middle/mut.rs index b6a866537022..2aa3ddc66c8b 100644 --- a/src/comp/middle/mut.rs +++ b/src/comp/middle/mut.rs @@ -130,15 +130,15 @@ fn check_crate(tcx: ty::ctxt, crate: @crate) -> mut_map { ret cx.mut_map; } -tag msg { msg_assign; msg_move_out; msg_mut_alias; } +tag msg { msg_assign; msg_move_out; msg_mut_ref; } fn mk_err(cx: @ctx, span: syntax::codemap::span, msg: msg, name: str) { cx.tcx.sess.span_err(span, alt msg { msg_assign. { "assigning to " + name } msg_move_out. { "moving out of " + name } - msg_mut_alias. { - "passing " + name + " by mutable alias" + msg_mut_ref. { + "passing " + name + " by mutable reference" } }); } @@ -234,7 +234,7 @@ fn check_call(cx: @ctx, f: @expr, args: [@expr]) { ty::type_autoderef(cx.tcx, ty::expr_ty(cx.tcx, f))); let i = 0u; for arg_t: ty::arg in arg_ts { - if arg_t.mode != by_ref { check_lval(cx, args[i], msg_mut_alias); } + if arg_t.mode != by_ref { check_lval(cx, args[i], msg_mut_ref); } i += 1u; } } diff --git a/src/test/compile-fail/unsafe-alias-2.rs b/src/test/compile-fail/unsafe-alias-2.rs index ad7296ef1b44..9f28c6190efb 100644 --- a/src/test/compile-fail/unsafe-alias-2.rs +++ b/src/test/compile-fail/unsafe-alias-2.rs @@ -1,4 +1,4 @@ -// error-pattern:invalidate alias x +// error-pattern:invalidate reference x fn whoknows(x: @mutable int) { *x = 10; } diff --git a/src/test/compile-fail/unsafe-alt.rs b/src/test/compile-fail/unsafe-alt.rs index fb42b188a7cf..b83147715614 100644 --- a/src/test/compile-fail/unsafe-alt.rs +++ b/src/test/compile-fail/unsafe-alt.rs @@ -1,4 +1,4 @@ -// error-pattern:invalidate alias i +// error-pattern:invalidate reference i tag foo { left(int); right(bool); } diff --git a/src/test/compile-fail/unsafe-for.rs b/src/test/compile-fail/unsafe-for.rs index 22d5396c1cbc..cac88b410c75 100644 --- a/src/test/compile-fail/unsafe-for.rs +++ b/src/test/compile-fail/unsafe-for.rs @@ -1,4 +1,4 @@ -// error-pattern:invalidate alias x +// error-pattern:invalidate reference x fn main() { let v: [mutable int] = [mutable 1, 2, 3]; diff --git a/src/test/compile-fail/unsafe-mutable-alias.rs b/src/test/compile-fail/unsafe-mutable-alias.rs index 142e90a46a88..f6b52bef34b4 100644 --- a/src/test/compile-fail/unsafe-mutable-alias.rs +++ b/src/test/compile-fail/unsafe-mutable-alias.rs @@ -1,4 +1,4 @@ -// error-pattern:mutable alias to a variable that roots another alias +// error-pattern:mutable reference to a variable that roots another reference fn f(a: {mutable x: int}, &b: {mutable x: int}) -> int { b.x += 1;