Alex Rønne Petersen <alex@lycus.org>
Alexander Stavonin <a.stavonin@gmail.com>
Andreas Gal <gal@mozilla.com>
+Andrew Paseltiner <apaseltiner@gmail.com>
Arkaitz Jimenez <arkaitzj@gmail.com>
Armin Ronacher <armin.ronacher@active-4.com>
Austin Seipp <mad.one@gmail.com>
+auREAX <mark@xn--hwg34fba.ws>
Ben Blum <bblum@andrew.cmu.edu>
Ben Striegel <ben.striegel@gmail.com>
Benjamin Herr <ben@0x539.de>
Francisco Souza <f@souza.cc>
Gareth Daniel Smith <garethdanielsmith@gmail.com>
Glenn Willen <gwillen@nerdnet.org>
+Gonçalo Cabrita <_@gmcabrita.com>
Graham Fawcett <fawcett@uwindsor.ca>
Grahame Bowland <grahame@angrygoats.net>
Haitao Li <lihaitao@gmail.com>
Tycho Sci <tychosci@gmail.com>
Vincent Belliard <vincent@famillebelliard.fr>
Wade Mealing <wmealing@gmail.com>
+Yasuhiro Fujii <y-fujii@mimosa-pudica.net>
Zack Corr <zackcorr95@gmail.com>
opt mingw-cross 0 "cross-compile for win32 using mingw"
opt clang 0 "prefer clang to gcc for building the runtime"
opt local-rust 0 "use an installed rustc rather than downloading a snapshot"
+opt pax-flags 0 "apply PaX flags to rustc binaries (required for GRSecurity/PaX-patched kernels)"
valopt prefix "/usr/local" "set installation prefix"
valopt local-rust-root "/usr/local" "set prefix for local rust binary"
valopt llvm-root "" "set LLVM root"
probe CFG_XETEX xetex
probe CFG_LUATEX luatex
probe CFG_NODE nodejs node
+if [ "$CFG_OSTYPE" = "unknown-linux-gnu" ]
+then
+ probe CFG_PAXCTL paxctl /sbin/paxctl
+ probe CFG_ZCAT zcat
+fi
if [ ! -z "$CFG_PANDOC" ]
then
fi
fi
+if [ "$CFG_OSTYPE" = "unknown-linux-gnu" ]
+then
+ if [ ! -z "$CFG_ENABLE_PAX_FLAGS" -a -z "$CFG_PAXCTL" ]
+ then
+ err "enabled PaX markings but no paxctl binary found"
+ fi
+
+ if [ -z "$CFG_DISABLE_PAX_FLAGS" ]
+ then
+ # GRSecurity/PaX detection. This can be very flaky.
+ GRSEC_DETECTED=
+
+ # /dev/grsec only exists if CONFIG_GRKERNSEC_NO_RBAC is not set.
+ # /proc/sys/kernel/grsecurity is not available if ÇONFIG_GRKERNSEC_SYSCTL is not set.
+ if [ -e /dev/grsec -o -d /proc/sys/kernel/grsecurity ]
+ then
+ GRSEC_DETECTED=1
+ # /proc/config.gz is normally only available to root, and only if CONFIG_IKCONFIG_PROC has been set.
+ elif [ -r /proc/config.gz -a ! -z "$CFG_ZCAT" ]
+ then
+ if "$CFG_ZCAT" /proc/config.gz | grep --quiet "CONFIG_GRKERNSEC=y"
+ then
+ GRSEC_DETECTED=1
+ fi
+ # Flaky.
+ elif grep --quiet grsec /proc/version
+ then
+ GRSEC_DETECTED=1
+ fi
+
+ if [ ! -z "$GRSEC_DETECTED" ]
+ then
+ step_msg "GRSecurity: yes"
+ if [ ! -z "$CFG_PAXCTL" ]
+ then
+ CFG_ENABLE_PAX_FLAGS=1
+ else
+ warn "GRSecurity kernel detected but no paxctl binary found: not setting CFG_ENABLE_PAX_FLAGS"
+ fi
+ else
+ step_msg "GRSecurity: no"
+ fi
+ fi
+fi
+
if [ ! -z "$CFG_ENABLE_LOCAL_RUST" ]
then
if [ ! -f ${CFG_LOCAL_RUST_ROOT}/bin/rustc ]
msg "git: submodule sync"
"${CFG_GIT}" submodule --quiet sync
+ msg "git: submodule update"
+ "${CFG_GIT}" submodule --quiet update --init
+ need_ok "git failed"
+
+ msg "git: submodule foreach sync"
+ "${CFG_GIT}" submodule --quiet foreach --recursive git submodule sync
+ need_ok "git failed"
+
+ msg "git: submodule foreach update"
+ "${CFG_GIT}" submodule --quiet update --init --recursive
+ need_ok "git failed"
+
# NB: this is just for the sake of getting the submodule SHA1 values
# and status written into the build log.
msg "git: submodule status"
"${CFG_GIT}" submodule status --recursive
- msg "git: submodule update"
- "${CFG_GIT}" submodule --quiet update --init --recursive
- need_ok "git failed"
-
msg "git: submodule clobber"
"${CFG_GIT}" submodule --quiet foreach --recursive git clean -dxf
need_ok "git failed"
putvar CFG_LIBDIR
putvar CFG_DISABLE_MANAGE_SUBMODULES
+if [ ! -z "$CFG_ENABLE_PAX_FLAGS" ]
+then
+ putvar CFG_ENABLE_PAX_FLAGS
+ putvar CFG_PAXCTL
+fi
+
if [ ! -z $BAD_PANDOC ]
then
CFG_PANDOC=
var html = '<pre class="cm-s-default">', curstr = "", curstyle = null;
function add(str, style) {
if (style != curstyle) {
- if (curstyle) html += '<span class="cm-' + curstyle + '">' + curstr
- + "</span>";
- else if (curstr) html += curstr;
+ if (curstyle) html +=
+ '<span class="cm-' + CodeMirror.htmlEscape(curstyle) + '">' +
+ CodeMirror.htmlEscape(curstr) + "</span>";
+ else if (curstr) html += CodeMirror.htmlEscape(curstr);
curstr = str; curstyle = style;
} else curstr += str;
}
but simply changes the visibility of other items. There are several kinds of
view item:
- * [extern mod declarations](#extern-mod-declarations)
- * [use declarations](#use-declarations)
+ * [`extern mod` declarations](#extern-mod-declarations)
+ * [`use` declarations](#use-declarations)
##### Extern mod declarations
link_attr : ident '=' literal ;
~~~~~~~~
-An _extern mod declaration_ specifies a dependency on an external crate.
+An _`extern mod` declaration_ specifies a dependency on an external crate.
The external crate is then bound into the declaring scope as the `ident` provided in the `extern_mod_decl`.
The external crate is resolved to a specific `soname` at compile time, and a
pure fn nonempty_list<T>(ls: List<T>) -> bool { pure_length(ls) > 0u }
~~~~
-*TODO:* should actually define referential transparency.
-
-The effect checking rules previously enumerated are a restricted set
-of typechecking rules meant to approximate the universe of observably
-referentially transparent Rust procedures conservatively. Sometimes,
-these rules are *too* restrictive. Rust allows programmers to violate
-these rules by writing pure functions that the compiler cannot prove
-to be referentially transparent, using "unsafe blocks". When writing
-code that uses unsafe blocks, programmers should always be aware that
-they have an obligation to show that the code *behaves* referentially
-transparently at all times, even if the compiler cannot *prove*
-automatically that the code is referentially transparent. In the
-presence of unsafe blocks, the compiler provides no static guarantee
-that the code will behave as expected at runtime. Rather, the
-programmer has an independent obligation to verify the semantics of
-the pure functions they write.
-
-*TODO:* last two sentences are vague.
+These purity-checking rules approximate the concept of referential transparency:
+that a call-expression could be rewritten with the literal-expression of its return value, without changing the meaning of the program.
+Since they are an approximation, sometimes these rules are *too* restrictive.
+Rust allows programmers to violate these rules using [`unsafe` blocks](#unsafe-blocks).
+As with any `unsafe` block, those that violate static purity carry transfer the burden of safety-proof from the compiler to the programmer.
+Programmers should exercise caution when breaking such rules.
An example of a pure function that uses an unsafe block:
parameters to allow methods with that trait to be called on values
of that type.
+#### Unsafe functions
+
+Unsafe functions are those containing unsafe operations that are not contained in an [`unsafe` block](#unsafe-blocks).
+
+Unsafe operations are those that potentially violate the memory-safety guarantees of Rust's static semantics.
+Specifically, the following operations are considered unsafe:
+
+ - Dereferencing a [raw pointer](#pointer-types)
+ - Casting a [raw pointer](#pointer-types) to a safe pointer type
+ - Breaking the [purity-checking rules](#pure-functions)
+ - Calling an unsafe function
+
+##### Unsafe blocks
+
+A block of code can also be prefixed with the `unsafe` keyword,
+to permit a sequence of unsafe operations in an otherwise-safe function.
+This facility exists because the static semantics of a Rust are a necessary approximation of the dynamic semantics.
+When a programmer has sufficient conviction that a sequence of unsafe operations is actually safe,
+they can encapsulate that sequence (taken as a whole) within an `unsafe` block.
+The compiler will consider uses of such code "safe", to the surrounding context.
+
+
#### Extern functions
Extern functions are part of Rust's foreign function interface, providing
~~~
Extern functions may not be called from Rust code, but their value
-may be taken as an unsafe `u8` pointer.
+may be taken as a raw `u8` pointer.
~~~
# extern fn new_vec() -> ~[int] { ~[] }
sequence of block, statement, expression, and block can repeatedly nest to an
arbitrary depth.
+#### Lvalues, rvalues and temporaries
+
+Expressions are divided into two main categories: _lvalues_ and _rvalues_.
+Likewise within each expression, sub-expressions may occur in _lvalue context_ or _rvalue context_.
+The evaluation of an expression depends both on its own category and the context it occurs within.
+
+Path, field and index expressions are lvalues.
+All other expressions are rvalues.
+
+The left operand of an assignment expression and the operand of the borrow operator are lvalue contexts.
+All other expression contexts are rvalue contexts.
+
+When an lvalue is evaluated in an _lvalue context_, it denotes a memory location;
+when evaluated in an _rvalue context_, it denotes the value held _in_ that memory location.
+
+When an rvalue is used in lvalue context, a temporary un-named lvalue is created and used instead.
+A temporary's lifetime equals the largest lifetime of any borrowed pointer that points to it.
+
+
### Literal expressions
A _literal expression_ consists of one of the [literal](#literals)
Executing an `as` expression casts the value on the left-hand side to the type
on the right-hand side.
-A numeric value can be cast to any numeric type. An unsafe pointer value can
-be cast to or from any integral type or unsafe pointer type. Any other cast
-is unsupported and will fail to compile.
+A numeric value can be cast to any numeric type.
+A raw pointer value can be cast to or from any integral type or raw pointer type.
+Any other cast is unsupported and will fail to compile.
An example of an `as` expression:
// Full version, logging a value.
log(core::error, ~"file not found: " + filename);
-// Log-level abbreviated, since core::* is imported by default.
+// Log-level abbreviated, since core::* is used by default.
log(error, ~"file not found: " + filename);
-// Formatting the message using a format-string and #fmt
+// Formatting the message using a format-string and fmt!
log(error, fmt!("file not found: %s", filename));
-// Using the #error macro, that expands to the previous call.
+// Using the error! macro, that expands to the previous call.
error!("file not found: %s", filename);
~~~~
-A `log` expression is *not evaluated* when logging at the specified
-logging-level, module or task is disabled at runtime. This makes inactive
-`log` expressions very cheap; they should be used extensively in Rust
-code, as diagnostic aids, as they add little overhead beyond a single
-integer-compare and branch at runtime.
+A `log` expression is *not evaluated* when logging at the specified logging-level, module or task is disabled at runtime.
+This makes inactive `log` expressions very cheap;
+they should be used extensively in Rust code, as diagnostic aids,
+as they add little overhead beyond a single integer-compare and branch at runtime.
-Logging is presently implemented as a language built-in feature, as it makes
-use of compiler-provided logic for allocating the associated per-module
-logging-control structures visible to the runtime, and lazily evaluating
-arguments. In the future, as more of the supporting compiler-provided logic is
-moved into libraries, logging is likely to move to a component of the core
-library. It is best to use the macro forms of logging (*#error*,
-*#debug*, etc.) to minimize disruption to code using the logging facility
-when it is changed.
+Logging is presently implemented as a language built-in feature,
+as it makes use of compiler-provided, per-module data tables and flags.
+In the future, logging will move into a library, and will no longer be a core expression type.
+It is therefore recommended to use the macro forms of logging (`error!`, `debug!`, etc.) to minimize disruption in code that uses logging.
### Assert expressions
Enumerated types cannot be denoted *structurally* as types, but must be
denoted by named reference to an [*enumeration* item](#enumerations).
-### Box types
-
-Box types are represented as pointers. There are three flavours of
-pointers:
-
-Shared boxes (`@`)
- : These are reference-counted boxes. Their type is written
- `@content`, for example `@int` means a shared box containing an
- integer. Copying a value of such a type means copying the pointer
- and increasing the reference count.
-
-Unique boxes (`~`)
- : Unique boxes have only a single owner, and are freed when their
- owner releases them. They are written `~content`. Copying a
- unique box involves copying the contents into a new box.
-
-Unsafe pointers (`*`)
- : Unsafe pointers are pointers without safety guarantees or
- language-enforced semantics. Their type is written `*content`.
- They can be copied and dropped freely. Dereferencing an unsafe
- pointer is part of the unsafe sub-dialect of Rust.
+### Pointer types
+
+All pointers in Rust are explicit first-class values.
+They can be copied, stored into data structures, and returned from functions.
+There are four varieties of pointer in Rust:
+
+Managed pointers (`@`)
+ : These point to managed heap allocations (or "boxes") in the task-local, managed heap.
+ Managed pointers are written `@content`,
+ for example `@int` means a managed pointer to a managed box containing an integer.
+ Copying a managed pointer is a "shallow" operation:
+ it involves only copying the pointer itself
+ (as well as any reference-count or GC-barriers required by the managed heap).
+ Dropping a managed pointer does not necessarily release the box it points to;
+ the lifecycles of managed boxes are subject to an unspecified garbage collection algorithm.
+
+Owning pointers (`~`)
+ : These point to owned heap allocations (or "boxes") in the shared, inter-task heap.
+ Each owned box has a single owning pointer; pointer and pointee retain a 1:1 relationship at all times.
+ Owning pointers are written `~content`,
+ for example `~int` means an owning pointer to an owned box containing an integer.
+ Copying an owned box is a "deep" operation:
+ it involves allocating a new owned box and copying the contents of the old box into the new box.
+ Releasing an owning pointer immediately releases its corresponding owned box.
+
+Borrowed pointers (`&`)
+ : These point to memory _owned by some other value_.
+ Borrowed pointers arise by (automatic) conversion from owning pointers, managed pointers,
+ or by applying the borrowing operator `&` to some other value,
+ including [lvalues, rvalues or temporaries](#lvalues-rvalues-and-temporaries).
+ Borrowed pointers are written `&content`, or in some cases `&f/content` for some lifetime-variable `f`,
+ for example `&int` means a borrowed pointer to an integer.
+ Copying a borrowed pointer is a "shallow" operation:
+ it involves only copying the pointer itself.
+ Releasing a borrowed pointer typically has no effect on the value it points to,
+ with the exception of temporary values,
+ which are released when the last borrowed pointer to them is released.
+
+Raw pointers (`*`)
+ : Raw pointers are pointers without safety or liveness guarantees.
+ Raw pointers are written `*content`,
+ for example `*int` means a raw pointer to an integer.
+ Copying or dropping a raw pointer is has no effect on the lifecycle of any other value.
+ Dereferencing a raw pointer or converting it to any other pointer type is an [`unsafe` operation](#unsafe-functions).
+ Raw pointers are generally discouraged in Rust code;
+ they exist to support interoperability with foreign code,
+ and writing performance-critical or low-level functions.
### Function types
and out of frames, or stored in the heap, heap allocations may outlive the
frame they are allocated within.
-
### Memory ownership
A task owns all memory it can *safely* reach through local variables,
-shared or unique boxes, and/or references. Sharing memory between tasks can
-only be accomplished using *unsafe* constructs, such as raw pointer
-operations or calling C code.
+as well as managed, owning and borrowed pointers.
-When a task sends a value that has the `send` trait over a channel, it
-loses ownership of the value sent and can no longer refer to it. This is
-statically guaranteed by the combined use of "move semantics" and the
-compiler-checked _meaning_ of the `send` trait: it is only instantiated
-for (transitively) unique kinds of data constructor and pointers, never shared
-pointers.
+When a task sends a value that has the `Send` trait to another task,
+it loses ownership of the value sent and can no longer refer to it.
+This is statically guaranteed by the combined use of "move semantics",
+and the compiler-checked _meaning_ of the `Send` trait:
+it is only instantiated for (transitively) sendable kinds of data constructor and pointers,
+never including managed or borrowed pointers.
When a stack frame is exited, its local allocations are all released, and its
references to boxes (both shared and owned) are dropped.
example, if the referred-to value contains mutable fields), it will reject the
program. If the compiler deems copying the value expensive, it will warn.
-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 value by mutable reference:
+A function with an argument of type `&mut T`, for some type `T`, can write to
+the slot that its argument refers to. An example of such a function is:
~~~~~~~~
-fn incr(&i: int) {
- i = i + 1;
+fn incr(i: &mut int) {
+ *i = *i + 1;
}
~~~~~~~~
### Communication between tasks
-With the exception of *unsafe* blocks, Rust tasks are isolated from
-interfering with one another's memory directly. Instead of manipulating shared
-storage, Rust tasks communicate with one another using a typed, asynchronous,
-simplex message-passing system.
-
-A _port_ is a communication endpoint that can *receive* messages. Ports
-receive messages from channels.
-
-A _channel_ is a communication endpoint that can *send* messages. Channels
-send messages to ports.
-
-Each port is implicitly boxed and mutable; as such a port has a unique
-per-task identity and cannot be replicated or transmitted. If a port value is
-copied, both copies refer to the *same* port. New ports can be
-constructed dynamically and stored in data structures.
-
-Each channel is bound to a port when the channel is constructed, so the
-destination port for a channel must exist before the channel itself. A channel
-cannot be rebound to a different port from the one it was constructed with.
-
-Channels are weak: a channel does not keep the port it is bound to
-alive. Ports are owned by their allocating task and cannot be sent over
-channels; if a task dies its ports die with it, and all channels bound to
-those ports no longer function. Messages sent to a channel connected to a dead
-port will be dropped.
-
-Channels are immutable types with meaning known to the runtime; channels can
-be sent over channels.
-
-Many channels can be bound to the same port, but each channel is bound to a
-single port. In other words, channels and ports exist in an N:1 relationship,
-N channels to 1 port. ^[It may help to remember nautical terminology
-when differentiating channels from ports. Many different waterways --
-channels -- may lead to the same port.]
-
-Each port and channel can carry only one type of message. The message type is
-encoded as a parameter of the channel or port type. The message type of a
-channel is equal to the message type of the port it is bound to. The types of
-messages must satisfy the `send` built-in trait.
+Rust tasks are isolated and generally unable to interfere with one another's memory directly,
+except through [`unsafe` code](#unsafe-functions).
+All contact between tasks is mediated by safe forms of ownership transfer,
+and data races on memory are prohibited by the type system.
-Messages are generally sent asynchronously, with optional
-rate-limiting on the transmit side. Each port contains a message
-queue and sending a message over a channel merely means inserting it
-into the associated port's queue; message receipt is the
-responsibility of the receiving task.
+Inter-task communication and co-ordination facilities are provided in the standard library.
+These include:
+ - synchronous and asynchronous communication channels with various communication topologies
+ - read-only and read-write shared variables with various safe mutual exclusion patterns
+ - simple locks and semaphores
-Messages are sent on channels and received on ports using standard library
-functions.
+When such facilities carry values, the values are restricted to the [`Send` type-kind](#type-kinds).
+Restricting communication interfaces to this kind ensures that no borrowed or managed pointers move between tasks.
+Thus access to an entire data structure can be mediated through its owning "root" value;
+no further locking or copying is required to avoid data races within the substructure of such a value.
### Task lifecycle
state. In this state it executes the statements of its entry function, and any
functions called by the entry function.
-A task may transition from the *running* state to the *blocked* state any time
-it makes a blocking receive call on a port, or attempts a rate-limited
-blocking send on a channel. When the communication expression can be completed
--- when a message arrives at a sender, or a queue drains sufficiently to
-complete a rate-limited send -- then the blocked task will unblock and
-transition back to *running*.
+A task may transition from the *running* state to the *blocked*
+state any time it makes a blocking communication call. When the
+call can be completed -- when a message arrives at a sender, or a
+buffer opens to receive a message -- then the blocked task will
+unblock and transition back to *running*.
A task may transition to the *failing* state at any time, due being
killed by some external event or internally, from the evaluation of a
~~~~
let po = comm::Port();
-let ch = comm::Chan(po);
+let ch = comm::Chan(&po);
do task::spawn {
// let task run, do other things
~~~~
let po = comm::Port();
-let ch = comm::Chan(po);
+let ch = comm::Chan(&po);
comm::send(ch, ~"hello, world");
~~~~
~~~~~~~~
# let po = comm::Port();
-# let ch = comm::Chan(po);
+# let ch = comm::Chan(&po);
# comm::send(ch, ~"");
let s = comm::recv(po);
~~~~~~~~
To take as an argument a fragment of Rust code, write `$` followed by a name
(for use on the right-hand side), followed by a `:`, followed by the sort of
fragment to match (the most common ones are `ident`, `expr`, `ty`, `pat`, and
-`block`). Anything not preceeded by a `$` is taken literally. The standard
+`block`). Anything not preceded by a `$` is taken literally. The standard
rules of tokenization apply,
So `($x:ident => (($e:expr)))`, though excessively fancy, would create a macro
Going back to the motivating example, suppose that we wanted each invocation
of `early_return` to potentially accept multiple "special" identifiers. The
-syntax `$(...)*` accepts zero or more occurences of its contents, much like
+syntax `$(...)*` accepts zero or more occurrences of its contents, much like
the Kleene star operator in regular expressions. It also supports a separator
token (a comma-separated list could be written `$(...),*`), and `+` instead of
`*` to mean "at least one".
a message passing interface to Rust code: `core::comm` and `core::pipes`.
`core::comm` is an older, less efficient system that is being phased out
in favor of `pipes`. At some point the existing `core::comm` API will
-be romoved and the user-facing portions of `core::pipes` will be moved
+be removed and the user-facing portions of `core::pipes` will be moved
to `core::comm`. In this tutorial we will discuss `pipes` and ignore
the `comm` API.
* [`core::comm`] - The deprecated message passing API
* [`core::pipes`] - The new message passing infrastructure and API
* [`std::comm`] - Higher level messaging types based on `core::pipes`
-* [`std::sync`] - More exotic synchronization tools, including locks
+* [`std::sync`] - More exotic synchronization tools, including locks
* [`std::arc`] - The ARC type, for safely sharing immutable data
* [`std::par`] - Some basic tools for implementing parallel algorithms
The simplest way to create a pipe is to use the `pipes::stream`
function to create a `(Chan, Port)` pair. In Rust parlance a 'channel'
-is a sending endpoint of a pipe, and a 'port' is the recieving
+is a sending endpoint of a pipe, and a 'port' is the receiving
endpoint. Consider the following example of performing two calculations
concurrently.
~~~~
The channel will be used by the child task to send data to the parent task,
-which will wait to recieve the data on the port. The next statement
+which will wait to receive the data on the port. The next statement
spawns the child task.
~~~~
to "catch" the exception.
All tasks are, by default, _linked_ to each other, meaning their fate
-is interwined, and if one fails so do all of them.
+is intertwined, and if one fails so do all of them.
~~~
# use task::spawn;
then compile it, you'll see an error message like this:
~~~~ {.notrust}
-hello.rs:2:4: 2:16 error: unresolved name: io::print_it
-hello.rs:2 io::print_it("hello? yes, this is rust");
- ^~~~~~~~~~~~
+hello.rs:2:4: 2:16 error: unresolved name: io::print_with_unicorns
+hello.rs:2 io::print_with_unicorns("hello? yes, this is rust");
+ ^~~~~~~~~~~~~~~~~~~~~~~
~~~~
In its simplest form, a Rust program is a `.rs` file with some types
compiled to an executable. Rust does not allow code that's not a
declaration to appear at the top level of the file—all statements must
live inside a function. Rust programs can also be compiled as
-libraries, and included in other programs. The `extern mod std`
-directive that appears at the top of many examples imports the
-[standard library][std], described in more detail [later
-on](#modules-and-crates).
-
-[std]: http://doc.rust-lang.org/doc/std
+libraries, and included in other programs.
## Editing Rust code
24, then using emacs's internal package manager to install `rust-mode`
is the easiest way to keep it up to date. There is also a package for
Sublime Text 2, available both [standalone][sublime] and through
-[Sublime Package Control][sublime-pkg].
+[Sublime Package Control][sublime-pkg], and support for Kate
+under `src/etc/kate`.
-Other editors are not provided for yet. If you end up writing a Rust
+There is ctags support via `src/etc/ctags.rust`, but many other
+tools and editors are not provided for yet. If you end up writing a Rust
mode for your favorite editor, let us know so that we can link to it.
[sublime]: http://github.com/dbp/sublime-rust
Assuming you've programmed in any C-family language (C++, Java,
JavaScript, C#, or PHP), Rust will feel familiar. Code is arranged
in blocks delineated by curly braces; there are control structures
-for branching and looping, like the familiar `if` and `when`; function
+for branching and looping, like the familiar `if` and `while`; function
calls are written `myfunc(arg1, arg2)`; operators are written the same
and mostly have the same precedence as in C; comments are again like C.
}
~~~~
-Although Rust can almost always infer the types of local variables, it
-can help readability to specify a variable's type by following it with
-a colon, then the type name.
+Although Rust can almost always infer the types of local variables, you
+can specify a variable's type by following it with a colon, then the type
+name.
~~~~
-let my_favorite_value: float = 57.8;
-let my_favorite_value: int = my_favorite_value as int;
+let monster_size: float = 57.8;
+let imaginary_size = monster_size * 10.0;
+let monster_size: int = 50;
~~~~
Local variables may shadow earlier declarations, as in the previous
-example in which `my_favorite_value` is first declared as a `float`
-then a second `my_favorite_value` is declared as an int.
+example in which `monster_size` is first declared as a `float`
+then a second `monster_size` is declared as an int. If you were to actually
+compile this example though, the compiler will see that the second
+`monster_size` is unused, assume that you have made a mistake, and issue
+a warning. For occasions where unused variables are intentional, their
+name may be prefixed with an underscore to silence the warning, like
+`let _monster_size = 50;`.
Rust identifiers follow the same rules as C; they start with an alphabetic
character or an underscore, and after that may contain any sequence of
~~~
let my_variable = 100;
-type MyType = int; // built-in types though are _not_ camel case
+type MyType = int; // some built-in types are _not_ camel case
~~~
## Expression syntax
Though it isn't apparent in all code, there is a fundamental
-difference between Rust's syntax and its predecessors in this family
-of languages. Many constructs that are statements in C are expressions
+difference between Rust's syntax and predecessors like C.
+Many constructs that are statements in C are expressions
in Rust, allowing code to be more concise. For example, you might
write a piece of code like this:
~~~~
# let item = "salad";
-let price = if item == "salad" {
- 3.50
-} else if item == "muffin" {
- 2.25
-} else {
- 2.00
-};
+let price =
+ if item == "salad" {
+ 3.50
+ } else if item == "muffin" {
+ 2.25
+ } else {
+ 2.00
+ };
~~~~
Both pieces of code are exactly equivalent—they assign a value to
-`price` depending on the condition that holds. Note that the
-semicolons are omitted from the blocks in the second snippet. This is
+`price` depending on the condition that holds. Note that there
+are not semicolons in the blocks of the second snippet. This is
important; the lack of a semicolon after the last statement in a
braced block gives the whole block the value of that last expression.
Put another way, the semicolon in Rust *ignores the value of an expression*.
Thus, if the branches of the `if` had looked like `{ 4; }`, the above example
-would simply assign nil (void) to `price`. But without the semicolon, each
+would simply assign `()` (nil or void) to `price`. But without the semicolon, each
branch has a different value, and `price` gets the value of the branch that
was taken.
# fn foo() -> bool { true }
# fn bar() -> bool { true }
# fn baz() -> bool { true }
-
// `let` is not an expression, so it is semi-colon terminated;
let x = foo();
let y = if x { foo() } else { bar() };
~~~
-This may sound a bit intricate, but it is super-useful, and it will
-grow on you (hopefully).
+This may sound intricate, but it is super-useful and will grow on you.
## Types
-The basic types include the usual boolean, integral, and floating point types.
+The basic types include the usual boolean, integral, and floating-point types.
------------------------- -----------------------------------------------
`()` Nil, the type that has only a single value
`i8`, `i16`, `i32`, `i64` Signed integers with a specific size (in bits)
`u8`, `u16`, `u32`, `u64` Unsigned integers with a specific size
`float` The largest floating-point type efficiently supported on the target machine
-`f32`, `f64` Floating-point types with a specific size.
-`char` A Unicode character (32 bits).
+`f32`, `f64` Floating-point types with a specific size
+`char` A Unicode character (32 bits)
------------------------- -----------------------------------------------
These can be combined in composite types, which will be described in
-more detail later on (the `T`s here stand for any other type):
+more detail later on (the `T`s here stand for any other type,
+while N should be a literal number):
------------------------- -----------------------------------------------
`[T * N]` Vector (like an array in other languages) with N elements
`[mut T * N]` Mutable vector with N elements
-`(T1, T2)` Tuple type. Any arity above 1 is supported
+`(T1, T2)` Tuple type; any arity above 1 is supported
`&T`, `~T`, `@T` [Pointer types](#boxes-and-pointers)
------------------------- -----------------------------------------------
optionally write `-> ()`, but usually the return annotation is simply
left off, as in `fn main() { ... }`.
-Types can be given names with `type` declarations:
+Types can be given names or aliases with `type` declarations:
~~~~
type MonsterSize = uint;
This will provide a synonym, `MonsterSize`, for unsigned integers. It will not
actually create a new, incompatible type—`MonsterSize` and `uint` can be used
interchangeably, and using one where the other is expected is not a type
-error. Read about [single-variant enums](#single_variant_enum)
-further on if you need to create a type name that's not just a
-synonym.
+error.
+
+To create data types which are not synonyms, `struct` and `enum`
+can be used. They're described in more detail below, but they look like this:
+
+~~~~
+enum HidingPlaces {
+ Closet(uint),
+ UnderTheBed(uint)
+}
+
+struct HeroicBabysitter {
+ bedtime_stories: uint,
+ sharpened_stakes: uint
+}
+
+struct BabysitterSize(uint); // a single-variant struct
+enum MonsterSize = uint; // a single-variant enum
+~~~~
## Literals
Character literals are written between single quotes, as in `'x'`. Just as in
C, Rust understands a number of character escapes, using the backslash
-character, `\n`, `\r`, and `\t` being the most common. String literals,
+character, such as `\n`, `\r`, and `\t`. String literals,
written between double quotes, allow the same escape sequences. Rust strings
may contain newlines.
+## Constants
+
+Compile-time constants are declared with `const`. All scalar types,
+like integers and floats, may be declared `const`, as well as fixed
+length vectors, static strings (more on this later), and structs.
+Constants may be declared in any scope and may refer to other
+constants. Constant declarations are not type inferred, so must always
+have a type annotation. By convention they are written in all capital
+letters.
+
+~~~
+// Scalars can be constants
+const MY_PASSWORD: int = 12345;
+
+// Scalar constants can be combined with other constants
+const MY_DOGGIES_PASSWORD: int = MY_PASSWORD + 1;
+
+// Fixed-length vectors
+const MY_VECTORY_PASSWORD: [int * 5] = [1, 2, 3, 4, 5];
+
+// Static strings
+const MY_STRINGY_PASSWORD: &static/str = "12345";
+
+// Structs
+struct Password { value: int }
+const MY_STRUCTY_PASSWORD: Password = Password { value: MY_PASSWORD };
+~~~
+
## Operators
Rust's set of operators contains very few surprises. Arithmetic is done with
The main difference with C is that `++` and `--` are missing, and that
the logical bitwise operators have higher precedence — in C, `x & 2 > 0`
-comes out as `x & (2 > 0)`, in Rust, it means `(x & 2) > 0`, which is
-more likely to be what you expect (unless you are a C veteran).
+means `x & (2 > 0)`, but in Rust, it means `(x & 2) > 0`, which is
+more likely what a novice expects.
## Syntax extensions
The patterns in an match arm are followed by a fat arrow, `=>`, then an
expression to evaluate. Each case is separated by commas. It's often
-convenient to use a block expression for a case, in which case the
+convenient to use a block expression for each case, in which case the
commas are optional.
~~~
# let my_number = 1;
match my_number {
- 0 => {
- io::println("zero")
- }
- _ => {
- io::println("something else")
- }
+ 0 => { io::println("zero") }
+ _ => { io::println("something else") }
}
~~~
Structs can be destructured in `match` patterns. The basic syntax is
`Name {fieldname: pattern, ...}`:
+
~~~~
# struct Point { x: float, y: float }
# let mypoint = Point { x: 0.0, y: 0.0 };
match mypoint {
- Point { x: 0.0, y: y } => { io::println(y.to_str()); }
- Point { x: x, y: y } => { io::println(x.to_str() + " " + y.to_str()); }
+ Point { x: 0.0, y: yy } => { io::println(yy.to_str()); }
+ Point { x: xx, y: yy } => { io::println(xx.to_str() + " " + yy.to_str()); }
}
~~~~
order they appear in the type. When you are not interested in all
the fields of a struct, a struct pattern may end with `, _` (as in
`Name {field1, _}`) to indicate that you're ignoring all other fields.
+Additionally, struct fields have a shorthand matching form that simply
+reuses the field name as the binding name.
+
+~~~
+# struct Point { x: float, y: float }
+# let mypoint = Point { x: 0.0, y: 0.0 };
+match mypoint {
+ Point { x, _ } => { io::println(x.to_str()) }
+}
+~~~
+
+Structs are the only type in Rust that may have user-defined destructors,
+using `drop` blocks, inside of which the struct's value may be referred
+to with the name `self`.
+
+~~~
+struct TimeBomb {
+ explosivity: uint,
+
+ drop {
+ for iter::repeat(self.explosivity) {
+ io::println(fmt!("blam!"));
+ }
+ }
+}
+~~~
+
+> ***Note***: This destructor syntax is temporary. Eventually destructors
+> will be defined for any type using [traits](#traits).
## Enums
~~~~
# enum GizmoId = int;
-let my_gizmo_id = GizmoId(10);
+let my_gizmo_id: GizmoId = GizmoId(10);
let id_int: int = *my_gizmo_id;
~~~~
the return type follows the arrow.
~~~~
-fn repeat(string: &str, count: int) -> ~str {
- let mut result = ~"";
- for count.times {
- result += string;
- }
- return result;
+fn line(a: int, b: int, x: int) -> int {
+ return a * x + b;
}
~~~~
expression.
~~~~
-# const copernicus: int = 0;
-fn int_to_str(i: int) -> ~str {
- if i == copernicus {
- return ~"tube sock";
- } else {
- return ~"violin";
- }
-}
-~~~~
-
-~~~~
-# const copernicus: int = 0;
-fn int_to_str(i: int) -> ~str {
- if i == copernicus { ~"tube sock" }
- else { ~"violin" }
+fn line(a: int, b: int, x: int) -> int {
+ a * x + b
}
~~~~
fn do_nothing_the_easy_way() { }
~~~~
+Ending the function with a semicolon like so is equivalent to returning `()`.
+
+~~~~
+fn line(a: int, b: int, x: int) -> int { a * x + b }
+fn oops(a: int, b: int, x: int) -> () { a * x + b; }
+
+assert 8 == line(5, 3, 1);
+assert () == oops(5, 3, 1);
+~~~~
+
Methods are like functions, except that they are defined for a specific
'self' type (like 'this' in C++). Calling a method is done with
dot notation, as in `my_vec.len()`. Methods may be defined on most
additional benefit that garbage collection must only be done
per-heap. Rust never "stops the world" to reclaim memory.
-Complete isolation of heaps between tasks implies that any data
+Complete isolation of heaps between tasks would, however, mean that any data
transferred between tasks must be copied. While this is a fine and
useful way to implement communication between tasks, it is also very
inefficient for large data structures. Because of this, Rust also
~~~~
let x = ~10;
let y = copy x;
+
+let z = *x + *y;
+assert z == 20;
~~~~
This is where the 'move' operator comes in. It is similar to
single owner (if you used assignment instead of the move operator, the
box would, in principle, be copied).
-~~~~
+~~~~ {.xfail-test}
let x = ~10;
let y = move x;
+
+let z = *x + *y; // would cause an error: use of moved variable: `x`
~~~~
Owned boxes, when they do not contain any managed boxes, can be sent
[borrowtut]: tutorial-borrowed-ptr.html
+## Dereferencing pointers
+
+Rust uses the unary star operator (`*`) to access the contents of a
+box or pointer, similarly to C.
+
+~~~
+let managed = @10;
+let owned = ~20;
+let borrowed = &30;
+
+let sum = *managed + *owned + *borrowed;
+~~~
+
+Dereferenced mutable pointers may appear on the left hand side of
+assignments, in which case the value they point to is modified.
+
+~~~
+let managed = @mut 10;
+let owned = ~mut 20;
+
+let mut value = 30;
+let borrowed = &mut value;
+
+*managed = *owned + 10;
+*owned = *borrowed + 100;
+*borrowed = *managed + 1000;
+~~~
+
+Pointers have high operator precedence, but lower precedence than the
+dot operator used for field and method access. This can lead to some
+awkward code filled with parenthesis.
+
+~~~
+# struct Point { x: float, y: float }
+# enum Shape { Rectangle(Point, Point) }
+# impl Shape { fn area() -> int { 0 } }
+let start = @Point { x: 10f, y: 20f };
+let end = ~Point { x: (*start).x + 100f, y: (*start).y + 100f };
+let rect = &Rectangle(*start, *end);
+let area = (*rect).area();
+~~~
+
+To combat this ugliness the dot operator performs _automatic pointer
+dereferencing_ on the receiver (the value on the left hand side of the
+dot), so in most cases dereferencing the receiver is not necessary.
+
+~~~
+# struct Point { x: float, y: float }
+# enum Shape { Rectangle(Point, Point) }
+# impl Shape { fn area() -> int { 0 } }
+let start = @Point { x: 10f, y: 20f };
+let end = ~Point { x: start.x + 100f, y: start.y + 100f };
+let rect = &Rectangle(*start, *end);
+let area = rect.area();
+~~~
+
+Auto-dereferencing is performed through any number of pointers. If you
+felt inclined you could write something silly like
+
+~~~
+# struct Point { x: float, y: float }
+let point = &@~Point { x: 10f, y: 20f };
+io::println(fmt!("%f", point.x));
+~~~
+
+The indexing operator (`[]`) is also auto-dereferencing.
+
# Vectors and strings
Vectors are a contiguous section of memory containing zero or more
enum Crayon {
Almond, AntiqueBrass, Apricot,
Aquamarine, Asparagus, AtomicTangerine,
- BananaMania, Beaver, Bittersweet
+ BananaMania, Beaver, Bittersweet,
+ Black, BlizzardBlue, Blue
}
// A fixed-size stack vector
let stack_crayons: [Crayon * 3] = [Almond, AntiqueBrass, Apricot];
// A borrowed pointer to stack allocated vector
-let stack_crayons: &[Crayon] = &[Almond, AntiqueBrass, Apricot];
+let stack_crayons: &[Crayon] = &[Aquamarine, Asparagus, AtomicTangerine];
// A local heap (managed) vector of crayons
-let local_crayons: @[Crayon] = @[Aquamarine, Asparagus, AtomicTangerine];
+let local_crayons: @[Crayon] = @[BananaMania, Beaver, Bittersweet];
// An exchange heap (owned) vector of crayons
-let exchange_crayons: ~[Crayon] = ~[BananaMania, Beaver, Bittersweet];
+let exchange_crayons: ~[Crayon] = ~[Black, BlizzardBlue, Blue];
~~~
-Vector literals are enclosed in square brackets and dereferencing is
-also done with square brackets (zero-based):
+The `+` operator means concatenation when applied to vector types.
~~~~
# enum Crayon { Almond, AntiqueBrass, Apricot,
# Aquamarine, Asparagus, AtomicTangerine,
# BananaMania, Beaver, Bittersweet };
-# fn draw_scene(c: Crayon) { }
-let crayons = [BananaMania, Beaver, Bittersweet];
-match crayons[0] {
- Bittersweet => draw_scene(crayons[0]),
- _ => ()
-}
+let my_crayons = ~[Almond, AntiqueBrass, Apricot];
+let your_crayons = ~[BananaMania, Beaver, Bittersweet];
+
+// Add two vectors to create a new one
+let our_crayons = my_crayons + your_crayons;
+
+// += will append to a vector, provided it leves
+// in a mutable slot
+let mut my_crayons = move my_crayons;
+my_crayons += your_crayons;
~~~~
-By default, vectors are immutable—you can not replace their elements.
-The type written as `[mut T]` is a vector with mutable
-elements. Mutable vector literals are written `[mut]` (empty) or `[mut
-1, 2, 3]` (with elements).
+> ***Note:*** The above examples of vector addition use owned
+> vectors. Some operations on slices and stack vectors are
+> not well supported yet, owned vectors are often the most
+> usable.
+
+Indexing into vectors is done with square brackets:
~~~~
# enum Crayon { Almond, AntiqueBrass, Apricot,
# Aquamarine, Asparagus, AtomicTangerine,
# BananaMania, Beaver, Bittersweet };
-
-let crayons = [mut BananaMania, Beaver, Bittersweet];
-crayons[0] = AtomicTangerine;
+# fn draw_scene(c: Crayon) { }
+let crayons: [Crayon * 3] = [BananaMania, Beaver, Bittersweet];
+match crayons[0] {
+ Bittersweet => draw_scene(crayons[0]),
+ _ => ()
+}
~~~~
-The `+` operator means concatenation when applied to vector types.
+The elements of a vector _inherit the mutability of the vector_,
+and as such individual elements may not be reassigned when the
+vector lives in an immutable slot.
-~~~~
+~~~ {.xfail-test}
# enum Crayon { Almond, AntiqueBrass, Apricot,
# Aquamarine, Asparagus, AtomicTangerine,
# BananaMania, Beaver, Bittersweet };
+let crayons: ~[Crayon] = ~[BananaMania, Beaver, Bittersweet];
-let my_crayons = ~[Almond, AntiqueBrass, Apricot];
-let your_crayons = ~[BananaMania, Beaver, Bittersweet];
-
-let our_crayons = my_crayons + your_crayons;
-~~~~
+crayons[0] = Apricot; // ERROR: Can't assign to immutable vector
+~~~
-The `+=` operator also works as expected, provided the assignee
-lives in a mutable slot.
+Moving it into a mutable slot makes the elements assignable.
-~~~~
+~~~
# enum Crayon { Almond, AntiqueBrass, Apricot,
# Aquamarine, Asparagus, AtomicTangerine,
# BananaMania, Beaver, Bittersweet };
+let crayons: ~[Crayon] = ~[BananaMania, Beaver, Bittersweet];
-let mut my_crayons = ~[Almond, AntiqueBrass, Apricot];
-let your_crayons = ~[BananaMania, Beaver, Bittersweet];
+// Put the vector into a mutable slot
+let mut mutable_crayons = move crayons;
-my_crayons += your_crayons;
-~~~~
+// Now it's mutable to the bone
+mutable_crayons[0] = Apricot;
+~~~
-> ***Note:*** The above examples of vector addition use owned
-> vectors. Some operations on slices and stack vectors are
-> not well supported yet, owned vectors are often the most
-> usable.
+This is a simple example of Rust's _dual-mode data structures_, also
+referred to as _freezing and thawing_.
-Strings are simply vectors of `[u8]`, though they have a distinct
-type. They support most of the same allocation aptions as
+Strings are implemented with vectors of `u8`, though they have a distinct
+type. They support most of the same allocation options as
vectors, though the string literal without a storage sigil, e.g.
`"foo"` is treated differently than a comparable vector (`[foo]`).
-Where
+Whereas plain vectors are stack-allocated fixed-length vectors,
+plain strings are region pointers to read-only memory. Strings
+are always immutable.
~~~
// A plain string is a slice to read-only (static) memory
let stack_crayons: &str = "Almond, AntiqueBrass, Apricot";
-// The same thing, but without
-let stack_crayons: &str = &"Almond, AntiqueBrass, Apricot";
+// The same thing, but with the `&`
+let stack_crayons: &str = &"Aquamarine, Asparagus, AtomicTangerine";
// A local heap (managed) string
-let local_crayons: @str = @"Aquamarine, Asparagus, AtomicTangerine";
+let local_crayons: @str = @"BananMania, Beaver, Bittersweet";
// An exchange heap (owned) string
-let exchange_crayons: ~str = ~"BananaMania, Beaver, Bittersweet";
+let exchange_crayons: ~str = ~"Black, BlizzardBlue, Blue";
~~~
Both vectors and strings support a number of useful
-[methods](#implementation). While we haven't covered methods yet,
-most vector functionality is provided by methods, so let's have a
-brief look at a few common ones.
+[methods](#functions-and-methods), defined in [`core::vec`]
+and [`core::str`]. Here are some examples.
+
+[`core::vec`]: core/vec.html
+[`core::str`]: core/str.html
~~~
# use io::println;
~~~~
let mut max = 0;
-(~[1, 2, 3]).map(|x| if *x > max { max = *x });
+[1, 2, 3].map(|x| if *x > max { max = *x });
~~~~
Stack closures are very efficient because their environment is
returns it from a function, and then calls it:
~~~~
-extern mod std;
-
+# extern mod std;
fn mk_appender(suffix: ~str) -> fn@(~str) -> ~str {
return fn@(s: ~str) -> ~str { s + suffix };
}
call_twice(|| { ~"I am an inferred stack closure"; } );
call_twice(fn&() { ~"I am also a stack closure"; } );
call_twice(fn@() { ~"I am a managed closure"; });
-call_twice(fn~() { ~"I am a owned closure"; });
+call_twice(fn~() { ~"I am an owned closure"; });
fn bare_function() { ~"I am a plain function"; }
call_twice(bare_function);
~~~~
## Do syntax
-Closures in Rust are frequently used in combination with higher-order
-functions to simulate control structures like `if` and
-`loop`. Consider this function that iterates over a vector of
+The `do` expression is syntactic sugar for use with functions which
+take a closure as a final argument, because closures in Rust
+are so frequently used in combination with higher-order
+functions.
+
+Consider this function which iterates over a vector of
integers, passing in a pointer to each integer in the vector:
~~~~
The call is prefixed with the keyword `do` and, instead of writing the
final closure inside the argument list it is moved outside of the
parenthesis where it looks visually more like a typical block of
-code. The `do` expression is purely syntactic sugar for a call that
-takes a final closure argument.
+code.
`do` is often used for task spawning.
`for` syntax only works with stack closures.
+> ***Note:*** This is, essentially, a special loop protocol:
+> the keywords `break`, `loop`, and `return` work, in varying degree,
+> with `while`, `loop`, `do`, and `for` constructs.
+
# Generics
Throughout this tutorial, we've been defining functions that act only on
and `poultry::turkey`. You can also provide a `poultry.rs` to add
content to the `poultry` module itself.
+The compiler then builds the crate as a platform-specific shared library or
+executable which can be distributed.
+
## Using other crates
Having compiled a crate that contains the `#[crate_type = "lib"]`
This library is documented [here][core].
-[core]: http://doc.rust-lang.org/doc/core
+[core]: core/index.html
## A minimal example
these two files:
~~~~
-// mylib.rs
-#[link(name = "mylib", vers = "1.0")];
-fn world() -> ~str { ~"world" }
+// world.rs
+#[link(name = "world", vers = "1.0")];
+fn explore() -> ~str { ~"world" }
~~~~
~~~~ {.ignore}
// main.rs
-extern mod mylib;
-fn main() { io::println(~"hello " + mylib::world()); }
+extern mod world;
+fn main() { io::println(~"hello " + world::explore()); }
~~~~
Now compile and run like this (adjust to your platform if necessary):
~~~~ {.notrust}
-> rustc --lib mylib.rs
-> rustc main.rs -L .
+> rustc --lib world.rs # compiles libworld-94839cbfe144198-1.0.so
+> rustc main.rs -L . # compiles main
> ./main
"hello world"
~~~~
}
~~~~
+
It is also possible to import just the name of a module (`use
std::list;`, then use `list::find`), to import all identifiers exported
by a given module (`use io::*`), or to import a specific set
of identifiers (`use math::{min, max, pi}`).
-You can rename an identifier when importing using the `=` operator:
+Rust uses different namespaces for modules, types, and values. You
+can also rename an identifier when importing using the `=` operator:
~~~~
use prnt = io::println;
module can refer to the `enc::encrypt` and `enc::decrypt` identifiers
just fine, but it does not have access to `enc::super_secret_number`.
-## Namespaces
-
-Rust uses three different namespaces: one for modules, one for types,
-and one for values. This means that this code is valid:
-
-~~~~
-#[legacy_exports]
-mod buffalo {
- type buffalo = int;
- fn buffalo<buffalo>(+buffalo: buffalo) -> buffalo { buffalo }
-}
-fn main() {
- let buffalo: buffalo::buffalo = 1;
- buffalo::buffalo::<buffalo::buffalo>(buffalo::buffalo(buffalo));
-}
-~~~~
-
-You don't want to write things like that, but it *is* very practical
-to not have to worry about name clashes between types, values, and
-modules.
-
## Resolution
The resolution process in Rust simply goes up the chain of contexts,
type MyType = ~str;
fn main() {
type MyType = int;
- let x: MyType;
+ let x: MyType = 17;
}
~~~~
identifiers are actually found. Consider this example:
~~~~
-mod foo { fn bar() {} }
-fn baz() {
- let bar = 10u;
+mod foo {
+ fn bar() {}
+}
+
+fn main() {
+ let bar = 10;
{
use foo::bar;
let quux = bar;
+ assert quux == 10;
}
}
~~~~
$(Q)$(S)src/etc/local_stage0.sh $(CFG_HOST_TRIPLE) $(CFG_LOCAL_RUST_ROOT)
else
$(Q)$(S)src/etc/get-snapshot.py $(CFG_HOST_TRIPLE) $(SNAPSHOT_FILE)
+ifdef CFG_ENABLE_PAX_FLAGS
+ @$(call E, apply PaX flags: $@)
+ @"$(CFG_PAXCTL)" -cm "$@"
+endif
endif
$(Q)touch $@
$$(TLIBRUSTC_DEFAULT$(1)_T_$(2)_H_$(3))
@$$(call E, compile_and_link: $$@)
$$(STAGE$(1)_T_$(2)_H_$(3)) -o $$@ $$<
+ifdef CFG_ENABLE_PAX_FLAGS
+ @$$(call E, apply PaX flags: $$@)
+ @"$(CFG_PAXCTL)" -cm "$$@"
+endif
$$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_LIBRUSTC): \
$$(COMPILER_CRATE) $$(COMPILER_INPUTS) \
-This is preliminary version of the Rust compiler, libraries and tools
+This is a preliminary version of the Rust compiler, libraries and tools
Source layout:
set-method Change the method for a source.");
}
-fn main(argv: ~[~str]) {
+fn main() {
+ let argv = os::args();
let o = build_cargo_options(argv);
if vec::len(o.free) < 2u {
use common::mode;
use util::logv;
-fn main(++args: ~[~str]) {
+fn main() {
+ let args = os::args();
let config = parse_config(args);
log_config(config);
run_tests(config);
run_pass = os.path.join(src_dir, "src", "test", "run-pass")
run_pass = os.path.abspath(run_pass)
stage2_tests = []
-take_args = {}
for t in os.listdir(run_pass):
if t.endswith(".rs") and not (
"xfail-fast" in s or
"xfail-win32" in s):
stage2_tests.append(t)
- if "fn main(args:" in s or "fn main(++args:" in s:
- take_args[t] = True
f.close()
stage2_tests.sort()
p = os.path.join("test", "run-pass", t)
p = p.replace("\\", "\\\\")
d.write(" out.write_str(~\"run-pass [stage2]: %s\\n\");\n" % p)
- if t in take_args:
- d.write(" t_%d::main(~[~\"arg0\"]);\n" % i)
- else:
- d.write(" t_%d::main();\n" % i)
+ d.write(" t_%d::main();\n" % i)
i += 1
d.write("}\n")
}
}
-fn main(args: ~[~str]) {
+fn main() {
+ let args = os::args();
if vec::len(args) != 2u {
error!("usage: %s <testdir>", args[0]);
return;
//! Managed vectors
// NB: transitionary, de-mode-ing.
-// tjc: re-forbid deprecated modes after snapshot
+#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
use cast::transmute;
#[abi = "rust-intrinsic"]
extern mod rusti {
#[legacy_exports];
- fn move_val_init<T>(&dst: T, -src: T);
+ fn move_val_init<T>(dst: &mut T, -src: T);
}
/// Returns the number of elements the vector can hold without reallocating
push_slow(v, move initval);
}
}
- // This doesn't bother to make sure we have space.
+
#[inline(always)] // really pretty please
pub unsafe fn push_fast<T>(v: &mut @[const T], initval: T) {
let repr: **VecRepr = ::cast::reinterpret_cast(&v);
(**repr).unboxed.fill += sys::size_of::<T>();
let p = addr_of(&((**repr).unboxed.data));
let p = ptr::offset(p, fill) as *mut T;
- rusti::move_val_init(*p, move initval);
+ rusti::move_val_init(&mut(*p), move initval);
}
pub unsafe fn push_slow<T>(v: &mut @[const T], initval: T) {
//! Unsafe operations
+#[forbid(deprecated_mode)]
#[abi = "rust-intrinsic"]
extern mod rusti {
* The forget function will take ownership of the provided value but neglect
* to run any required cleanup or memory-management operations on it. This
* can be used for various acts of magick, particularly when using
- * reinterpret_cast on managed pointer types.
+ * reinterpret_cast on pointer types.
*/
#[inline(always)]
pub unsafe fn forget<T>(thing: T) { rusti::forget(move thing); }
#[link_name="fmax"] pure fn fmax(a: c_double, b: c_double) -> c_double;
#[link_name="fmin"] pure fn fmin(a: c_double, b: c_double) -> c_double;
pure fn nextafter(x: c_double, y: c_double) -> c_double;
- pure fn frexp(n: c_double, &value: c_int) -> c_double;
+ pure fn frexp(n: c_double, value: &mut c_int) -> c_double;
pure fn hypot(x: c_double, y: c_double) -> c_double;
pure fn ldexp(x: c_double, n: c_int) -> c_double;
#[cfg(unix)]
#[link_name="lgamma_r"] pure fn lgamma(n: c_double,
- &sign: c_int) -> c_double;
+ sign: &mut c_int) -> c_double;
#[cfg(windows)]
#[link_name="__lgamma_r"] pure fn lgamma(n: c_double,
- &sign: c_int) -> c_double;
+ sign: &mut c_int) -> c_double;
// renamed: log is a reserved keyword; ln seems more natural, too
#[link_name="log"] pure fn ln(n: c_double) -> c_double;
// renamed: "logb" /often/ is confused for log2 by beginners
pure fn log10(n: c_double) -> c_double;
pure fn log2(n: c_double) -> c_double;
#[link_name="ilogb"] pure fn ilog_radix(n: c_double) -> c_int;
- pure fn modf(n: c_double, &iptr: c_double) -> c_double;
+ pure fn modf(n: c_double, iptr: &mut c_double) -> c_double;
pure fn pow(n: c_double, e: c_double) -> c_double;
// FIXME (#1379): enable when rounding modes become available
// pure fn rint(n: c_double) -> c_double;
#[link_name="fdimf"] pure fn abs_sub(a: c_float, b: c_float) -> c_float;
#[link_name="floorf"] pure fn floor(n: c_float) -> c_float;
#[link_name="frexpf"] pure fn frexp(n: c_float,
- &value: c_int) -> c_float;
+ value: &mut c_int) -> c_float;
#[link_name="fmaf"] pure fn mul_add(a: c_float,
b: c_float, c: c_float) -> c_float;
#[link_name="fmaxf"] pure fn fmax(a: c_float, b: c_float) -> c_float;
#[cfg(unix)]
#[link_name="lgammaf_r"] pure fn lgamma(n: c_float,
- &sign: c_int) -> c_float;
+ sign: &mut c_int) -> c_float;
#[cfg(windows)]
#[link_name="__lgammaf_r"] pure fn lgamma(n: c_float,
- &sign: c_int) -> c_float;
+ sign: &mut c_int) -> c_float;
#[link_name="logf"] pure fn ln(n: c_float) -> c_float;
#[link_name="logbf"] pure fn log_radix(n: c_float) -> c_float;
#[link_name="log10f"] pure fn log10(n: c_float) -> c_float;
#[link_name="ilogbf"] pure fn ilog_radix(n: c_float) -> c_int;
#[link_name="modff"] pure fn modf(n: c_float,
- &iptr: c_float) -> c_float;
+ iptr: &mut c_float) -> c_float;
#[link_name="powf"] pure fn pow(n: c_float, e: c_float) -> c_float;
// FIXME (#1379): enable when rounding modes become available
// #[link_name="rintf"] pure fn rint(n: c_float) -> c_float;
*/
-// NB: transitionary, de-mode-ing
-// tjc: re-forbid deprecated modes after snapshot
+// NB: transitionary, de-mode-ing.
+#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
use either::Either;
impl<T: Send> Port<T> {
- fn chan() -> Chan<T> { Chan(self) }
+ fn chan() -> Chan<T> { Chan(&self) }
fn send(v: T) { self.chan().send(move v) }
fn recv() -> T { recv(self) }
fn peek() -> bool { peek(self) }
* Constructs a channel. The channel is bound to the port used to
* construct it.
*/
-pub fn Chan<T: Send>(&&p: Port<T>) -> Chan<T> {
+pub fn Chan<T: Send>(p: &Port<T>) -> Chan<T> {
Chan_(rustrt::get_port_id((**p).po))
}
#[test]
-fn create_port_and_chan() { let p = Port::<int>(); Chan(p); }
+fn create_port_and_chan() { let p = Port::<int>(); Chan(&p); }
#[test]
fn send_int() {
let p = Port::<int>();
- let c = Chan(p);
+ let c = Chan(&p);
send(c, 22);
}
#[test]
fn send_recv_fn() {
let p = Port::<int>();
- let c = Chan::<int>(p);
+ let c = Chan::<int>(&p);
send(c, 42);
assert (recv(p) == 42);
}
#[test]
fn send_recv_fn_infer() {
let p = Port();
- let c = Chan(p);
+ let c = Chan(&p);
send(c, 42);
assert (recv(p) == 42);
}
#[test]
fn chan_chan_infer() {
let p = Port(), p2 = Port::<int>();
- let c = Chan(p);
- send(c, Chan(p2));
+ let c = Chan(&p);
+ send(c, Chan(&p2));
recv(p);
}
#[test]
fn chan_chan() {
let p = Port::<Chan<int>>(), p2 = Port::<int>();
- let c = Chan(p);
- send(c, Chan(p2));
+ let c = Chan(&p);
+ send(c, Chan(&p2));
recv(p);
}
#[test]
fn test_peek() {
let po = Port();
- let ch = Chan(po);
+ let ch = Chan(&po);
assert !peek(po);
send(ch, ());
assert peek(po);
fn test_select2_available() {
let po_a = Port();
let po_b = Port();
- let ch_a = Chan(po_a);
- let ch_b = Chan(po_b);
+ let ch_a = Chan(&po_a);
+ let ch_b = Chan(&po_b);
send(ch_a, ~"a");
fn test_select2_rendezvous() {
let po_a = Port();
let po_b = Port();
- let ch_a = Chan(po_a);
- let ch_b = Chan(po_b);
+ let ch_a = Chan(&po_a);
+ let ch_b = Chan(&po_b);
for iter::repeat(10) {
do task::spawn {
fn test_select2_stress() {
let po_a = Port();
let po_b = Port();
- let ch_a = Chan(po_a);
- let ch_b = Chan(po_b);
+ let ch_a = Chan(&po_a);
+ let ch_b = Chan(&po_b);
let msgs = 100;
let times = 4u;
#[test]
fn test_recv_chan() {
let po = Port();
- let ch = Chan(po);
+ let ch = Chan(&po);
send(ch, ~"flower");
assert recv_chan(ch) == ~"flower";
}
#[should_fail]
#[ignore(cfg(windows))]
fn test_recv_chan_dead() {
- let ch = Chan(Port());
+ let ch = Chan(&Port());
send(ch, ~"flower");
recv_chan(ch);
}
#[ignore(cfg(windows))]
fn test_recv_chan_wrong_task() {
let po = Port();
- let ch = Chan(po);
+ let ch = Chan(&po);
send(ch, ~"flower");
assert result::is_err(&task::try(||
recv_chan(ch)
// Don't link to core. We are core.
#[no_core];
-#[legacy_exports];
-
#[warn(deprecated_mode)];
#[warn(deprecated_pattern)];
#[warn(vecs_implicitly_copyable)];
#[deny(non_camel_case_types)];
-export int, i8, i16, i32, i64;
-export uint, u8, u16, u32, u64;
-export float, f32, f64;
-export box, char, str, ptr, vec, at_vec, bool;
-export either, option, result, iter;
-export gc, io, libc, os, run, rand, sys, cast, logging;
-export comm, task, future, pipes;
-export extfmt;
-// The test harness links against core, so don't include runtime in tests.
-// FIXME (#2861): Uncomment this after snapshot gets updated.
-//#[cfg(notest)]
-export rt;
-export tuple;
-export to_str, to_bytes;
-export from_str;
-export util;
-export dvec, dvec_iter;
-export dlist, dlist_iter;
-export send_map;
-export hash;
-export cmp;
-export num;
-export path;
-export mutable;
-export flate;
-export unit;
-export uniq;
-export repr;
-export cleanup;
-export reflect;
-
-// NDM seems to be necessary for resolve to work
-export option_iter;
-
-// This creates some APIs that I do not want to commit to, but it must be
-// exported from core in order for uv to remain in std (see #2648).
-export private;
-
-
// Built-in-type support modules
/// Operations and constants for `int`
#[path = "int-template"]
-mod int {
+pub mod int {
pub use inst::{ pow };
#[path = "int.rs"]
- mod inst;
+ pub mod inst;
}
/// Operations and constants for `i8`
#[path = "int-template"]
-mod i8 {
+pub mod i8 {
#[path = "i8.rs"]
- mod inst;
+ pub mod inst;
}
/// Operations and constants for `i16`
#[path = "int-template"]
-mod i16 {
+pub mod i16 {
#[path = "i16.rs"]
- mod inst;
+ pub mod inst;
}
/// Operations and constants for `i32`
#[path = "int-template"]
-mod i32 {
+pub mod i32 {
#[path = "i32.rs"]
- mod inst;
+ pub mod inst;
}
/// Operations and constants for `i64`
#[path = "int-template"]
-mod i64 {
+pub mod i64 {
#[path = "i64.rs"]
- mod inst;
+ pub mod inst;
}
/// Operations and constants for `uint`
#[path = "uint-template"]
-mod uint {
+pub mod uint {
pub use inst::{
div_ceil, div_round, div_floor, iterate,
next_power_of_two
};
#[path = "uint.rs"]
- mod inst;
+ pub mod inst;
}
/// Operations and constants for `u8`
#[path = "uint-template"]
-mod u8 {
+pub mod u8 {
pub use inst::is_ascii;
#[path = "u8.rs"]
- mod inst;
+ pub mod inst;
}
/// Operations and constants for `u16`
#[path = "uint-template"]
-mod u16 {
+pub mod u16 {
#[path = "u16.rs"]
- mod inst;
+ pub mod inst;
}
/// Operations and constants for `u32`
#[path = "uint-template"]
-mod u32 {
+pub mod u32 {
#[path = "u32.rs"]
- mod inst;
+ pub mod inst;
}
/// Operations and constants for `u64`
#[path = "uint-template"]
-mod u64 {
+pub mod u64 {
#[path = "u64.rs"]
- mod inst;
+ pub mod inst;
}
-mod box;
-mod char;
-mod float;
-mod f32;
-mod f64;
-mod str;
-mod ptr;
-mod vec;
-mod at_vec;
-mod bool;
-mod tuple;
-mod unit;
-mod uniq;
+pub mod box;
+pub mod char;
+pub mod float;
+pub mod f32;
+pub mod f64;
+pub mod str;
+pub mod ptr;
+pub mod vec;
+pub mod at_vec;
+pub mod bool;
+pub mod tuple;
+pub mod unit;
+pub mod uniq;
// Ubiquitous-utility-type modules
#[cfg(notest)]
-mod ops;
-mod cmp;
-mod num;
-mod hash;
-mod either;
-mod iter;
-mod logging;
-mod option;
+pub mod ops;
+pub mod cmp;
+pub mod num;
+pub mod hash;
+pub mod either;
+pub mod iter;
+pub mod logging;
+pub mod option;
#[path="iter-trait"]
-mod option_iter {
+pub mod option_iter {
#[path = "option.rs"]
- mod inst;
+ pub mod inst;
}
-mod result;
-mod to_str;
-mod to_bytes;
-mod from_str;
-mod util;
+pub mod result;
+pub mod to_str;
+pub mod to_bytes;
+pub mod from_str;
+pub mod util;
// Data structure modules
-mod dvec;
+pub mod dvec;
#[path="iter-trait"]
-mod dvec_iter {
+pub mod dvec_iter {
#[path = "dvec.rs"]
- mod inst;
+ pub mod inst;
}
-mod dlist;
+pub mod dlist;
#[path="iter-trait"]
-mod dlist_iter {
+pub mod dlist_iter {
#[path ="dlist.rs"]
- mod inst;
+ pub mod inst;
}
-mod send_map;
+pub mod send_map;
// Concurrency
-mod comm;
-mod task {
+pub mod comm;
+pub mod task {
pub mod local_data;
mod local_data_priv;
pub mod spawn;
pub mod rt;
}
-mod future;
-mod pipes;
+pub mod future;
+pub mod pipes;
// Runtime and language-primitive support
-mod gc;
-mod io;
-mod libc;
-mod os;
-mod path;
-mod rand;
-mod run;
-mod sys;
-mod cast;
-mod mutable;
-mod flate;
-mod repr;
-mod cleanup;
-mod reflect;
+pub mod gc;
+pub mod io;
+pub mod libc;
+pub mod os;
+pub mod path;
+pub mod rand;
+pub mod run;
+pub mod sys;
+pub mod cast;
+pub mod mutable;
+pub mod flate;
+pub mod repr;
+pub mod cleanup;
+pub mod reflect;
// Modules supporting compiler-generated code
// Exported but not part of the public interface
-#[legacy_exports]
-mod extfmt;
+pub mod extfmt;
// The test harness links against core, so don't include runtime in tests.
#[cfg(notest)]
#[legacy_exports]
-mod rt;
-
+pub mod rt;
-// For internal use, not exported
+// Ideally not exported, but currently is.
+pub mod private;
+// For internal use, not exported.
mod unicode;
-mod private;
mod cmath;
mod stackwalk;
// Export various ubiquitous types, constructors, methods.
-use option::{Some, None};
-use Option = option::Option;
-use result::{Result, Ok, Err};
+pub use option::{Some, None};
+pub use Option = option::Option;
+pub use result::{Result, Ok, Err};
-use Path = path::Path;
-use GenericPath = path::GenericPath;
-use WindowsPath = path::WindowsPath;
-use PosixPath = path::PosixPath;
+pub use Path = path::Path;
+pub use GenericPath = path::GenericPath;
+pub use WindowsPath = path::WindowsPath;
+pub use PosixPath = path::PosixPath;
-use tuple::{TupleOps, ExtendedTupleOps};
-use str::{StrSlice, UniqueStr};
-use vec::{ConstVector, CopyableVector, ImmutableVector};
-use vec::{ImmutableEqVector, ImmutableCopyableVector};
-use vec::{MutableVector, MutableCopyableVector};
-use iter::{BaseIter, ExtendedIter, EqIter, CopyableIter};
-use iter::{CopyableOrderedIter, Times, TimesIx};
-use num::Num;
-use ptr::Ptr;
-use to_str::ToStr;
-
-export Path, WindowsPath, PosixPath, GenericPath;
-export Option, Some, None;
-export Result, Ok, Err;
-export extensions;
-// The following exports are the extension impls for numeric types
-export Num, Times, TimesIx;
-// The following exports are the common traits
-export StrSlice, UniqueStr;
-export ConstVector, CopyableVector, ImmutableVector;
-export ImmutableEqVector, ImmutableCopyableVector, IterTraitExtensions;
-export MutableVector, MutableCopyableVector;
-export BaseIter, CopyableIter, CopyableOrderedIter, ExtendedIter, EqIter;
-export TupleOps, ExtendedTupleOps;
-export Ptr;
-export ToStr;
+pub use tuple::{TupleOps, ExtendedTupleOps};
+pub use str::{StrSlice, UniqueStr};
+pub use vec::{ConstVector, CopyableVector, ImmutableVector};
+pub use vec::{ImmutableEqVector, ImmutableCopyableVector};
+pub use vec::{MutableVector, MutableCopyableVector};
+pub use iter::{BaseIter, ExtendedIter, EqIter, CopyableIter};
+pub use iter::{CopyableOrderedIter, Times, TimesIx};
+pub use num::Num;
+pub use ptr::Ptr;
+pub use to_str::ToStr;
// The following exports are the core operators and kinds
// The compiler has special knowlege of these so we must not duplicate them
// when compiling for testing
#[cfg(notest)]
-use ops::{Const, Copy, Send, Owned};
+pub use ops::{Const, Copy, Send, Owned};
#[cfg(notest)]
-use ops::{Add, Sub, Mul, Div, Modulo, Neg, BitAnd, BitOr, BitXor};
+pub use ops::{Add, Sub, Mul, Div, Modulo, Neg, BitAnd, BitOr, BitXor};
#[cfg(notest)]
-use ops::{Shl, Shr, Index};
-
-#[cfg(notest)]
-export Const, Copy, Send, Owned;
-#[cfg(notest)]
-export Add, Sub, Mul, Div, Modulo, Neg, BitAnd, BitOr, BitXor;
-#[cfg(notest)]
-export Shl, Shr, Index;
+pub use ops::{Shl, Shr, Index};
#[cfg(test)]
extern mod coreops(name = "core", vers = "0.4");
#[cfg(test)]
-use coreops::ops::{Const, Copy, Send, Owned};
+pub use coreops::ops::{Const, Copy, Send, Owned};
+#[cfg(test)]
+pub use coreops::ops::{Add, Sub, Mul, Div, Modulo, Neg, BitAnd, BitOr};
#[cfg(test)]
-use coreops::ops::{Add, Sub, Mul, Div, Modulo, Neg, BitAnd, BitOr, BitXor};
+pub use coreops::ops::{BitXor};
#[cfg(test)]
-use coreops::ops::{Shl, Shr, Index};
+pub use coreops::ops::{Shl, Shr, Index};
// Export the log levels as global constants. Higher levels mean
// more-verbosity. Error is the bottom level, default logging level is
// warn-and-below.
-export error, warn, info, debug;
-
/// The error log level
-const error : u32 = 0_u32;
+pub const error : u32 = 0_u32;
/// The warning log level
-const warn : u32 = 1_u32;
+pub const warn : u32 = 1_u32;
/// The info log level
-const info : u32 = 2_u32;
+pub const info : u32 = 2_u32;
/// The debug log level
-const debug : u32 = 3_u32;
+pub const debug : u32 = 3_u32;
// A curious inner-module that's not exported that contains the binding
// 'core' so that macro-expanded references to core::error and such
// can be resolved within libcore.
#[doc(hidden)] // FIXME #3538
mod core {
- #[legacy_exports];
- const error : u32 = 0_u32;
- const warn : u32 = 1_u32;
- const info : u32 = 2_u32;
- const debug : u32 = 3_u32;
+ pub const error : u32 = 0_u32;
+ pub const warn : u32 = 1_u32;
+ pub const info : u32 = 2_u32;
+ pub const debug : u32 = 3_u32;
}
// Similar to above. Some magic to make core testable.
#[cfg(test)]
mod std {
- #[legacy_exports];
extern mod std(vers = "0.4");
- use std::test;
+ pub use std::test;
}
*/
// NB: transitionary, de-mode-ing.
-// tjc: re-forbid deprecated modes after snapshot
+#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
type DListLink<T> = Option<DListNode<T>>;
*/
// NB: transitionary, de-mode-ing.
-// tjc: re-forbid deprecated modes after snapshot
+#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
use cast::reinterpret_cast;
// NB: transitionary, de-mode-ing.
-// tjc: re-forbid deprecated modes after snapshot
+#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
//! A type that represents one of two alternatives
#[doc(hidden)];
+// NB: transitionary, de-mode-ing.
+#[forbid(deprecated_mode)];
+#[forbid(deprecated_pattern)];
/*
Syntax Extension: fmt
*/
// Functions used by the fmt extension at compile time
-mod ct {
- #[legacy_exports];
- enum Signedness { Signed, Unsigned, }
- enum Caseness { CaseUpper, CaseLower, }
- enum Ty {
+pub mod ct {
+ pub enum Signedness { Signed, Unsigned, }
+ pub enum Caseness { CaseUpper, CaseLower, }
+ pub enum Ty {
TyBool,
TyStr,
TyChar,
TyFloat,
TyPoly,
}
- enum Flag {
+ pub enum Flag {
FlagLeftJustify,
FlagLeftZeroPad,
FlagSpaceForSign,
FlagSignAlways,
FlagAlternate,
}
- enum Count {
+ pub enum Count {
CountIs(int),
CountIsParam(int),
CountIsNextParam,
}
// A formatted conversion from an expression to a string
- type Conv =
+ pub type Conv =
{param: Option<int>,
flags: ~[Flag],
width: Count,
// A fragment of the output sequence
- enum Piece { PieceString(~str), PieceConv(Conv), }
- type ErrorFn = fn@(&str) -> ! ;
+ pub enum Piece { PieceString(~str), PieceConv(Conv), }
+ pub type ErrorFn = fn@(&str) -> ! ;
- fn parse_fmt_string(s: &str, error: ErrorFn) -> ~[Piece] {
+ pub fn parse_fmt_string(s: &str, error: ErrorFn) -> ~[Piece] {
let mut pieces: ~[Piece] = ~[];
let lim = str::len(s);
let mut buf = ~"";
flush_buf(move buf, &mut pieces);
move pieces
}
- fn peek_num(s: &str, i: uint, lim: uint) ->
+ pub fn peek_num(s: &str, i: uint, lim: uint) ->
Option<{num: uint, next: uint}> {
let mut j = i;
let mut accum = 0u;
None
}
}
- fn parse_conversion(s: &str, i: uint, lim: uint, error: ErrorFn) ->
+ pub fn parse_conversion(s: &str, i: uint, lim: uint,
+ error: ErrorFn) ->
{piece: Piece, next: uint} {
let parm = parse_parameter(s, i, lim);
let flags = parse_flags(s, parm.next, lim);
ty: ty.ty}),
next: ty.next};
}
- fn parse_parameter(s: &str, i: uint, lim: uint) ->
+ pub fn parse_parameter(s: &str, i: uint, lim: uint) ->
{param: Option<int>, next: uint} {
if i >= lim { return {param: None, next: i}; }
let num = peek_num(s, i, lim);
}
};
}
- fn parse_flags(s: &str, i: uint, lim: uint) ->
+ pub fn parse_flags(s: &str, i: uint, lim: uint) ->
{flags: ~[Flag], next: uint} {
let noflags: ~[Flag] = ~[];
if i >= lim { return {flags: move noflags, next: i}; }
more(FlagAlternate, s, i, lim)
} else { {flags: move noflags, next: i} };
}
- fn parse_count(s: &str, i: uint, lim: uint)
+ pub fn parse_count(s: &str, i: uint, lim: uint)
-> {count: Count, next: uint} {
return if i >= lim {
{count: CountImplied, next: i}
}
};
}
- fn parse_precision(s: &str, i: uint, lim: uint) ->
+ pub fn parse_precision(s: &str, i: uint, lim: uint) ->
{count: Count, next: uint} {
return if i >= lim {
{count: CountImplied, next: i}
}
} else { {count: CountImplied, next: i} };
}
- fn parse_type(s: &str, i: uint, lim: uint, error: ErrorFn) ->
+ pub fn parse_type(s: &str, i: uint, lim: uint, error: ErrorFn) ->
{ty: Ty, next: uint} {
if i >= lim { error(~"missing type in conversion"); }
let tstr = str::slice(s, i, i+1u);
// decisions made a runtime. If it proves worthwhile then some of these
// conditions can be evaluated at compile-time. For now though it's cleaner to
// implement it 0this way, I think.
-mod rt {
- #[legacy_exports];
- const flag_none : u32 = 0u32;
- const flag_left_justify : u32 = 0b00000000000000000000000000000001u32;
- const flag_left_zero_pad : u32 = 0b00000000000000000000000000000010u32;
- const flag_space_for_sign : u32 = 0b00000000000000000000000000000100u32;
- const flag_sign_always : u32 = 0b00000000000000000000000000001000u32;
- const flag_alternate : u32 = 0b00000000000000000000000000010000u32;
+pub mod rt {
+ pub const flag_none : u32 = 0u32;
+ pub const flag_left_justify : u32 = 0b00000000000001u32;
+ pub const flag_left_zero_pad : u32 = 0b00000000000010u32;
+ pub const flag_space_for_sign : u32 = 0b00000000000100u32;
+ pub const flag_sign_always : u32 = 0b00000000001000u32;
+ pub const flag_alternate : u32 = 0b00000000010000u32;
- enum Count { CountIs(int), CountImplied, }
- enum Ty { TyDefault, TyBits, TyHexUpper, TyHexLower, TyOctal, }
+ pub enum Count { CountIs(int), CountImplied, }
+ pub enum Ty { TyDefault, TyBits, TyHexUpper, TyHexLower, TyOctal, }
- type Conv = {flags: u32, width: Count, precision: Count, ty: Ty};
+ pub type Conv = {flags: u32, width: Count, precision: Count, ty: Ty};
- pure fn conv_int(cv: Conv, i: int) -> ~str {
+ pub pure fn conv_int(cv: Conv, i: int) -> ~str {
let radix = 10;
let prec = get_int_precision(cv);
let mut s : ~str = int_to_str_prec(i, radix, prec);
}
return unsafe { pad(cv, s, PadSigned) };
}
- pure fn conv_uint(cv: Conv, u: uint) -> ~str {
+ pub pure fn conv_uint(cv: Conv, u: uint) -> ~str {
let prec = get_int_precision(cv);
let mut rs =
match cv.ty {
};
return unsafe { pad(cv, rs, PadUnsigned) };
}
- pure fn conv_bool(cv: Conv, b: bool) -> ~str {
+ pub pure fn conv_bool(cv: Conv, b: bool) -> ~str {
let s = if b { ~"true" } else { ~"false" };
// run the boolean conversion through the string conversion logic,
// giving it the same rules for precision, etc.
return conv_str(cv, s);
}
- pure fn conv_char(cv: Conv, c: char) -> ~str {
+ pub pure fn conv_char(cv: Conv, c: char) -> ~str {
let mut s = str::from_char(c);
return unsafe { pad(cv, s, PadNozero) };
}
- pure fn conv_str(cv: Conv, s: &str) -> ~str {
+ pub pure fn conv_str(cv: Conv, s: &str) -> ~str {
// For strings, precision is the maximum characters
// displayed
let mut unpadded = match cv.precision {
};
return unsafe { pad(cv, unpadded, PadNozero) };
}
- pure fn conv_float(cv: Conv, f: float) -> ~str {
+ pub pure fn conv_float(cv: Conv, f: float) -> ~str {
let (to_str, digits) = match cv.precision {
CountIs(c) => (float::to_str_exact, c as uint),
CountImplied => (float::to_str, 6u)
}
return unsafe { pad(cv, s, PadFloat) };
}
- pure fn conv_poly<T>(cv: Conv, v: &T) -> ~str {
+ pub pure fn conv_poly<T>(cv: Conv, v: &T) -> ~str {
let s = sys::log_str(v);
return conv_str(cv, s);
}
// Convert an int to string with minimum number of digits. If precision is
// 0 and num is 0 then the result is the empty string.
- pure fn int_to_str_prec(num: int, radix: uint, prec: uint) -> ~str {
+ pub pure fn int_to_str_prec(num: int, radix: uint, prec: uint) -> ~str {
return if num < 0 {
~"-" + uint_to_str_prec(-num as uint, radix, prec)
} else { uint_to_str_prec(num as uint, radix, prec) };
// Convert a uint to string with a minimum number of digits. If precision
// is 0 and num is 0 then the result is the empty string. Could move this
// to uint: but it doesn't seem all that useful.
- pure fn uint_to_str_prec(num: uint, radix: uint, prec: uint) -> ~str {
+ pub pure fn uint_to_str_prec(num: uint, radix: uint,
+ prec: uint) -> ~str {
return if prec == 0u && num == 0u {
~""
} else {
} else { move s }
};
}
- pure fn get_int_precision(cv: Conv) -> uint {
+ pub pure fn get_int_precision(cv: Conv) -> uint {
return match cv.precision {
CountIs(c) => c as uint,
CountImplied => 1u
};
}
- enum PadMode { PadSigned, PadUnsigned, PadNozero, PadFloat }
+ pub enum PadMode { PadSigned, PadUnsigned, PadNozero, PadFloat }
- impl PadMode : Eq {
+ pub impl PadMode : Eq {
pure fn eq(other: &PadMode) -> bool {
match (self, (*other)) {
(PadSigned, PadSigned) => true,
pure fn ne(other: &PadMode) -> bool { !self.eq(other) }
}
- fn pad(cv: Conv, s: ~str, mode: PadMode) -> ~str {
+ pub fn pad(cv: Conv, s: ~str, mode: PadMode) -> ~str {
let mut s = move s; // sadtimes
let uwidth : uint = match cv.width {
CountImplied => return s,
}
return padstr + s;
}
- pure fn have_flag(flags: u32, f: u32) -> bool {
- flags & f != 0
- }
-}
-
-// Remove after snapshot
-
-// Functions used by the fmt extension at runtime. For now there are a lot of
-// decisions made a runtime. If it proves worthwhile then some of these
-// conditions can be evaluated at compile-time. For now though it's cleaner to
-// implement it 0this way, I think.
-mod rt2 {
- #[legacy_exports];
- const flag_none : u32 = 0u32;
- const flag_left_justify : u32 = 0b00000000000000000000000000000001u32;
- const flag_left_zero_pad : u32 = 0b00000000000000000000000000000010u32;
- const flag_space_for_sign : u32 = 0b00000000000000000000000000000100u32;
- const flag_sign_always : u32 = 0b00000000000000000000000000001000u32;
- const flag_alternate : u32 = 0b00000000000000000000000000010000u32;
-
- enum Count { CountIs(int), CountImplied, }
- enum Ty { TyDefault, TyBits, TyHexUpper, TyHexLower, TyOctal, }
-
- type Conv = {flags: u32, width: Count, precision: Count, ty: Ty};
-
- pure fn conv_int(cv: Conv, i: int) -> ~str {
- let radix = 10;
- let prec = get_int_precision(cv);
- let mut s : ~str = int_to_str_prec(i, radix, prec);
- if 0 <= i {
- if have_flag(cv.flags, flag_sign_always) {
- unsafe { str::unshift_char(&mut s, '+') };
- } else if have_flag(cv.flags, flag_space_for_sign) {
- unsafe { str::unshift_char(&mut s, ' ') };
- }
- }
- return unsafe { pad(cv, s, PadSigned) };
- }
- pure fn conv_uint(cv: Conv, u: uint) -> ~str {
- let prec = get_int_precision(cv);
- let mut rs =
- match cv.ty {
- TyDefault => uint_to_str_prec(u, 10u, prec),
- TyHexLower => uint_to_str_prec(u, 16u, prec),
- TyHexUpper => str::to_upper(uint_to_str_prec(u, 16u, prec)),
- TyBits => uint_to_str_prec(u, 2u, prec),
- TyOctal => uint_to_str_prec(u, 8u, prec)
- };
- return unsafe { pad(cv, rs, PadUnsigned) };
- }
- pure fn conv_bool(cv: Conv, b: bool) -> ~str {
- let s = if b { ~"true" } else { ~"false" };
- // run the boolean conversion through the string conversion logic,
- // giving it the same rules for precision, etc.
- return conv_str(cv, s);
- }
- pure fn conv_char(cv: Conv, c: char) -> ~str {
- let mut s = str::from_char(c);
- return unsafe { pad(cv, s, PadNozero) };
- }
- pure fn conv_str(cv: Conv, s: &str) -> ~str {
- // For strings, precision is the maximum characters
- // displayed
- let mut unpadded = match cv.precision {
- CountImplied => s.to_unique(),
- CountIs(max) => if max as uint < str::char_len(s) {
- str::substr(s, 0u, max as uint)
- } else {
- s.to_unique()
- }
- };
- return unsafe { pad(cv, unpadded, PadNozero) };
- }
- pure fn conv_float(cv: Conv, f: float) -> ~str {
- let (to_str, digits) = match cv.precision {
- CountIs(c) => (float::to_str_exact, c as uint),
- CountImplied => (float::to_str, 6u)
- };
- let mut s = unsafe { to_str(f, digits) };
- if 0.0 <= f {
- if have_flag(cv.flags, flag_sign_always) {
- s = ~"+" + s;
- } else if have_flag(cv.flags, flag_space_for_sign) {
- s = ~" " + s;
- }
- }
- return unsafe { pad(cv, s, PadFloat) };
- }
- pure fn conv_poly<T>(cv: Conv, v: &T) -> ~str {
- let s = sys::log_str(v);
- return conv_str(cv, s);
- }
-
- // Convert an int to string with minimum number of digits. If precision is
- // 0 and num is 0 then the result is the empty string.
- pure fn int_to_str_prec(num: int, radix: uint, prec: uint) -> ~str {
- return if num < 0 {
- ~"-" + uint_to_str_prec(-num as uint, radix, prec)
- } else { uint_to_str_prec(num as uint, radix, prec) };
- }
-
- // Convert a uint to string with a minimum number of digits. If precision
- // is 0 and num is 0 then the result is the empty string. Could move this
- // to uint: but it doesn't seem all that useful.
- pure fn uint_to_str_prec(num: uint, radix: uint, prec: uint) -> ~str {
- return if prec == 0u && num == 0u {
- ~""
- } else {
- let s = uint::to_str(num, radix);
- let len = str::char_len(s);
- if len < prec {
- let diff = prec - len;
- let pad = str::from_chars(vec::from_elem(diff, '0'));
- pad + s
- } else { move s }
- };
- }
- pure fn get_int_precision(cv: Conv) -> uint {
- return match cv.precision {
- CountIs(c) => c as uint,
- CountImplied => 1u
- };
- }
-
- enum PadMode { PadSigned, PadUnsigned, PadNozero, PadFloat }
-
- impl PadMode : Eq {
- pure fn eq(other: &PadMode) -> bool {
- match (self, (*other)) {
- (PadSigned, PadSigned) => true,
- (PadUnsigned, PadUnsigned) => true,
- (PadNozero, PadNozero) => true,
- (PadFloat, PadFloat) => true,
- (PadSigned, _) => false,
- (PadUnsigned, _) => false,
- (PadNozero, _) => false,
- (PadFloat, _) => false
- }
- }
- pure fn ne(other: &PadMode) -> bool { !self.eq(other) }
- }
-
- fn pad(cv: Conv, s: ~str, mode: PadMode) -> ~str {
- let mut s = move s; // sadtimes
- let uwidth : uint = match cv.width {
- CountImplied => return s,
- CountIs(width) => {
- // FIXME: width should probably be uint (see Issue #1996)
- width as uint
- }
- };
- let strlen = str::char_len(s);
- if uwidth <= strlen { return s; }
- let mut padchar = ' ';
- let diff = uwidth - strlen;
- if have_flag(cv.flags, flag_left_justify) {
- let padstr = str::from_chars(vec::from_elem(diff, padchar));
- return s + padstr;
- }
- let {might_zero_pad, signed} = match mode {
- PadNozero => {might_zero_pad:false, signed:false},
- PadSigned => {might_zero_pad:true, signed:true },
- PadFloat => {might_zero_pad:true, signed:true},
- PadUnsigned => {might_zero_pad:true, signed:false}
- };
- pure fn have_precision(cv: Conv) -> bool {
- return match cv.precision { CountImplied => false, _ => true };
- }
- let zero_padding = {
- if might_zero_pad && have_flag(cv.flags, flag_left_zero_pad) &&
- (!have_precision(cv) || mode == PadFloat) {
- padchar = '0';
- true
- } else {
- false
- }
- };
- let padstr = str::from_chars(vec::from_elem(diff, padchar));
- // This is completely heinous. If we have a signed value then
- // potentially rip apart the intermediate result and insert some
- // zeros. It may make sense to convert zero padding to a precision
- // instead.
-
- if signed && zero_padding && s.len() > 0 {
- let head = str::shift_char(&mut s);
- if head == '+' || head == '-' || head == ' ' {
- let headstr = str::from_chars(vec::from_elem(1u, head));
- return headstr + padstr + s;
- }
- else {
- str::unshift_char(&mut s, head);
- }
- }
- return padstr + s;
- }
- pure fn have_flag(flags: u32, f: u32) -> bool {
+ pub pure fn have_flag(flags: u32, f: u32) -> bool {
flags & f != 0
}
}
#[cfg(test)]
mod test {
- #[legacy_exports];
#[test]
fn fmt_slice() {
let s = "abc";
// NB: transitionary, de-mode-ing.
-// tjc: re-forbid deprecated modes after snapshot
+// tjc: allowing deprecated modes due to function issue.
+// can re-forbid them after snapshot
#[forbid(deprecated_pattern)];
/*!
}
}
-pub fn from_fn<A>(+f: ~fn() -> A) -> Future<A> {
+pub fn from_fn<A>(f: ~fn() -> A) -> Future<A> {
/*!
* Create a future from a function.
*
Future {state: Pending(move f)}
}
-pub fn spawn<A:Send>(+blk: fn~() -> A) -> Future<A> {
+pub fn spawn<A:Send>(blk: fn~() -> A) -> Future<A> {
/*!
* Create a future from a unique closure.
*
// NB: transitionary, de-mode-ing.
-// tjc: re-forbid deprecated modes after snapshot
+#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
use T = inst::T;
*/
+#[forbid(deprecated_mode)];
+#[forbid(deprecated_pattern)];
+
use result::Result;
use cmp::Eq;
// workaround our lack of traits and lack of macros. See core.{rc,rs} for
// how this file is used.
-#[warn(deprecated_mode)];
+#[forbid(deprecated_mode)];
+#[forbid(deprecated_pattern)];
use cmp::{Eq, Ord};
use inst::{IMPL_T, EACH, SIZE_HINT};
*/
+#[forbid(deprecated_mode)];
+#[forbid(deprecated_pattern)];
+
use cmp::{Eq, Ord};
/// A function used to initialize the elements of a sequence
mutation when the data structure should be immutable.
*/
-// tjc: re-forbid deprecated modes after snapshot
+#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
use util::with;
// Core operators and kinds.
+#[forbid(deprecated_mode)];
+#[forbid(deprecated_pattern)];
+
#[lang="const"]
pub trait Const {
// Empty.
/*!
- * Operations on the ubiquitous `option` type.
- *
- * Type `option` represents an optional value.
- *
- * Every `Option<T>` value can either be `Some(T)` or `none`. Where in other
- * languages you might use a nullable type, in Rust you would use an option
- * type.
- */
-
-// NB: transitionary, de-mode-ing.
-#[warn(deprecated_mode)];
+
+Operations on the ubiquitous `Option` type.
+
+Type `Option` represents an optional value.
+
+Every `Option<T>` value can either be `Some(T)` or `None`. Where in other
+languages you might use a nullable type, in Rust you would use an option
+type.
+
+Options are most commonly used with pattern matching to query the presence
+of a value and take action, always accounting for the `None` case.
+
+# Example
+
+~~~
+let msg = Some(~"howdy");
+
+// Take a reference to the contained string
+match msg {
+ Some(ref m) => io::println(m),
+ None => ()
+}
+
+// Remove the contained string, destroying the Option
+let unwrapped_msg = match move msg {
+ Some(move m) => m,
+ None => ~"default message"
+};
+~~~
+
+*/
+
+#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
use cmp::Eq;
pub pure fn get<T: Copy>(opt: &Option<T>) -> T {
/*!
- * Gets the value out of an option
- *
- * # Failure
- *
- * Fails if the value equals `none`
- */
+ Gets the value out of an option
+
+ # Failure
+
+ Fails if the value equals `None`
+
+ # Safety note
+
+ In general, because this function may fail, its use is discouraged
+ (calling `get` on `None` is akin to dereferencing a null pointer).
+ Instead, prefer to use pattern matching and handle the `None`
+ case explicitly.
+ */
match *opt {
Some(copy x) => return x,
pub pure fn get_ref<T>(opt: &r/Option<T>) -> &r/T {
/*!
- * Gets an immutable reference to the value inside an option.
- *
- * # Failure
- *
- * Fails if the value equals `none`
+ Gets an immutable reference to the value inside an option.
+
+ # Failure
+
+ Fails if the value equals `None`
+
+ # Safety note
+
+ In general, because this function may fail, its use is discouraged
+ (calling `get` on `None` is akin to dereferencing a null pointer).
+ Instead, prefer to use pattern matching and handle the `None`
+ case explicitly.
*/
match *opt {
Some(ref x) => x,
#[inline(always)]
pub pure fn unwrap<T>(opt: Option<T>) -> T {
/*!
- * Moves a value out of an option type and returns it.
- *
- * Useful primarily for getting strings, vectors and unique pointers out
- * of option types without copying them.
+ Moves a value out of an option type and returns it.
+
+ Useful primarily for getting strings, vectors and unique pointers out
+ of option types without copying them.
+
+ # Failure
+
+ Fails if the value equals `None`.
+
+ # Safety note
+
+ In general, because this function may fail, its use is discouraged.
+ Instead, prefer to use pattern matching and handle the `None`
+ case explicitly.
*/
match move opt {
Some(move x) => move x,
}
}
-/// The ubiquitous option dance.
#[inline(always)]
pub fn swap_unwrap<T>(opt: &mut Option<T>) -> T {
+ /*!
+ The option dance. Moves a value out of an option type and returns it,
+ replacing the original with `None`.
+
+ # Failure
+
+ Fails if the value equals `None`.
+ */
if opt.is_none() { fail ~"option::swap_unwrap none" }
unwrap(util::replace(opt, None))
}
pure fn iter(f: fn(x: &T)) { iter(self, f) }
/// Maps a `some` value from one type to another by reference
pure fn map<U>(f: fn(x: &T) -> U) -> Option<U> { map(self, f) }
- /// Gets an immutable reference to the value inside a `some`.
+ /**
+ Gets an immutable reference to the value inside an option.
+
+ # Failure
+
+ Fails if the value equals `None`
+
+ # Safety note
+
+ In general, because this function may fail, its use is discouraged
+ (calling `get` on `None` is akin to dereferencing a null pointer).
+ Instead, prefer to use pattern matching and handle the `None`
+ case explicitly.
+ */
pure fn get_ref() -> &self/T { get_ref(self) }
}
impl<T: Copy> Option<T> {
/**
- * Gets the value out of an option
- *
- * # Failure
- *
- * Fails if the value equals `none`
- */
+ Gets the value out of an option
+
+ # Failure
+
+ Fails if the value equals `None`
+
+ # Safety note
+
+ In general, because this function may fail, its use is discouraged
+ (calling `get` on `None` is akin to dereferencing a null pointer).
+ Instead, prefer to use pattern matching and handle the `None`
+ case explicitly.
+ */
pure fn get() -> T { get(&self) }
pure fn get_default(def: T) -> T { get_default(&self, def) }
/**
#[test]
fn test_unwrap_ptr() {
let x = ~0;
- let addr_x = ptr::p2::addr_of(&(*x));
+ let addr_x = ptr::addr_of(&(*x));
let opt = Some(x);
let y = unwrap(opt);
- let addr_y = ptr::p2::addr_of(&(*y));
+ let addr_y = ptr::addr_of(&(*y));
assert addr_x == addr_y;
}
// NB: transitionary, de-mode-ing.
-// tjc: re-forbid
+#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
/*!
let env_ch = get_global_env_chan();
let po = comm::Port();
comm::send(env_ch, MsgGetEnv(str::from_slice(n),
- comm::Chan(po)));
+ comm::Chan(&po)));
comm::recv(po)
}
let po = comm::Port();
comm::send(env_ch, MsgSetEnv(str::from_slice(n),
str::from_slice(v),
- comm::Chan(po)));
+ comm::Chan(&po)));
comm::recv(po)
}
pub fn env() -> ~[(~str,~str)] {
let env_ch = get_global_env_chan();
let po = comm::Port();
- comm::send(env_ch, MsgEnv(comm::Chan(po)));
+ comm::send(env_ch, MsgEnv(comm::Chan(&po)));
comm::recv(po)
}
*/
// NB: transitionary, de-mode-ing.
-// tjc: re-forbid deprecated modes after snapshot
+// tjc: allowing deprecated modes due to function issue,
+// re-forbid after snapshot
#[forbid(deprecated_pattern)];
use cmp::Eq;
pub fn spawn_service<T: Send, Tb: Send>(
init: extern fn() -> (SendPacketBuffered<T, Tb>,
RecvPacketBuffered<T, Tb>),
- +service: fn~(v: RecvPacketBuffered<T, Tb>))
+ service: fn~(v: RecvPacketBuffered<T, Tb>))
-> SendPacketBuffered<T, Tb>
{
let (client, server) = init();
pub fn spawn_service_recv<T: Send, Tb: Send>(
init: extern fn() -> (RecvPacketBuffered<T, Tb>,
SendPacketBuffered<T, Tb>),
- +service: fn~(v: SendPacketBuffered<T, Tb>))
+ service: fn~(v: SendPacketBuffered<T, Tb>))
-> RecvPacketBuffered<T, Tb>
{
let (client, server) = init();
// NB: transitionary, de-mode-ing.
-// tjc: re-forbid deprecated modes after snapshot
+// tjc: Re-forbid deprecated modes once a snapshot fixes the
+// function problem
#[forbid(deprecated_pattern)];
#[doc(hidden)];
pub unsafe fn chan_from_global_ptr<T: Send>(
global: GlobalPtr,
task_fn: fn() -> task::TaskBuilder,
- +f: fn~(comm::Port<T>)
+ f: fn~(comm::Port<T>)
) -> comm::Chan<T> {
enum Msg {
let (setup_po, setup_ch) = do task_fn().spawn_conversation
|move f, setup_po, setup_ch| {
let po = comm::Port::<T>();
- let ch = comm::Chan(po);
+ let ch = comm::Chan(&po);
comm::send(setup_ch, ch);
// Wait to hear if we are the official instance of
// The global channel
let globchan = 0;
- let globchanp = ptr::p2::addr_of(&globchan);
+ let globchanp = ptr::addr_of(&globchan);
// Create the global channel, attached to a new task
let ch = unsafe {
};
// Talk to it
let po = comm::Port();
- comm::send(ch, comm::Chan(po));
+ comm::send(ch, comm::Chan(&po));
assert comm::recv(po) == true;
// This one just reuses the previous channel
// Talk to the original global task
let po = comm::Port();
- comm::send(ch, comm::Chan(po));
+ comm::send(ch, comm::Chan(&po));
assert comm::recv(po) == true;
}
for iter::repeat(100) {
// The global channel
let globchan = 0;
- let globchanp = ptr::p2::addr_of(&globchan);
+ let globchanp = ptr::addr_of(&globchan);
let resultpo = comm::Port();
- let resultch = comm::Chan(resultpo);
+ let resultch = comm::Chan(&resultpo);
// Spawn a bunch of tasks that all want to compete to
// create the global channel
}
};
let po = comm::Port();
- comm::send(ch, comm::Chan(po));
+ comm::send(ch, comm::Chan(&po));
// We are The winner if our version of the
// task was installed
let winner = comm::recv(po);
*/
pub unsafe fn weaken_task(f: fn(comm::Port<()>)) {
let po = comm::Port();
- let ch = comm::Chan(po);
+ let ch = comm::Chan(&po);
unsafe {
rustrt::rust_task_weaken(cast::reinterpret_cast(&ch));
}
//! Unsafe pointer utility functions
+#[forbid(deprecated_mode)];
+#[forbid(deprecated_pattern)];
+
use cmp::{Eq, Ord};
use libc::{c_void, size_t};
#[inline(always)]
pub pure fn addr_of<T>(val: &T) -> *T { unsafe { rusti::addr_of(*val) } }
-pub mod p2 {
- /// Get an unsafe pointer to a value
- #[inline(always)]
- pub pure fn addr_of<T>(val: &T) -> *T { unsafe { rusti::addr_of(*val) } }
-}
-
/// Get an unsafe mut pointer to a value
#[inline(always)]
pub pure fn mut_addr_of<T>(val: &T) -> *mut T {
//! Random number generation
// NB: transitional, de-mode-ing.
-#[warn(deprecated_mode)];
+#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
#[allow(non_camel_case_types)] // runtime type
// used to make space in TLS for a random number generator
-fn tls_rng_state(+_v: @RandRes) {}
+fn tls_rng_state(_v: @RandRes) {}
/**
* Gives back a lazily initialized task-local random number generator,
*/
+#[forbid(deprecated_mode)];
+#[forbid(deprecated_pattern)];
+
use intrinsic::{TyDesc, get_tydesc, visit_tydesc, TyVisitor};
use libc::c_void;
*/
+#[forbid(deprecated_mode)];
+#[forbid(deprecated_pattern)];
+
use dvec::DVec;
use io::{Writer, WriterUtil};
use libc::c_void;
//! A type representing either success or failure
// NB: transitionary, de-mode-ing.
-// tjc: re-forbid deprecated modes after snapshot
+
+#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
use cmp::Eq;
// NB: transitionary, de-mode-ing.
-// tjc: re-forbid deprecated modes after snapshot
+#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
//! Process spawning
// or the other. FIXME (#2625): Surely there's a much more
// clever way to do this.
let p = comm::Port();
- let ch = comm::Chan(p);
+ let ch = comm::Chan(&p);
do task::spawn_sched(task::SingleThreaded) {
let errput = readclose(pipe_err.in);
comm::send(ch, (2, move errput));
#[legacy_modes]; // tjc: remove after snapshot
// NB: transitionary, de-mode-ing.
-// XXX: Can't do this because frame_address needs a deprecated mode.
-//#[forbid(deprecated_mode)];
+// XXX: Can't forbid this because frame_address needs a deprecated mode.
+#[allow(deprecated_mode)];
#[forbid(deprecated_pattern)];
use cast::reinterpret_cast;
* some heavy-duty uses, try std::rope.
*/
-#[warn(deprecated_mode)];
-#[warn(deprecated_pattern)];
+#[forbid(deprecated_mode)];
+#[forbid(deprecated_pattern)];
use cmp::{Eq, Ord};
use libc::size_t;
// NB: transitionary, de-mode-ing.
-// tjc: re-forbid deprecated modes after snapshot
+// tjc: Deprecated modes allowed because of function arg issue
+// in task::spawn. Re-forbid after snapshot.
#[forbid(deprecated_pattern)];
/*!
// FIXME (#2585): Replace the 'consumed' bit with move mode on self
pub enum TaskBuilder = {
opts: TaskOpts,
- gen_body: fn@(+v: fn~()) -> fn~(),
+ gen_body: fn@(v: fn~()) -> fn~(),
can_not_copy: Option<util::NonCopyable>,
mut consumed: bool,
};
pub fn task() -> TaskBuilder {
TaskBuilder({
opts: default_task_opts(),
- gen_body: |+body| move body, // Identity function
+ gen_body: |body| move body, // Identity function
can_not_copy: None,
mut consumed: false,
})
* generator by applying the task body which results from the
* existing body generator to the new body generator.
*/
- fn add_wrapper(wrapper: fn@(+v: fn~()) -> fn~()) -> TaskBuilder {
+ fn add_wrapper(wrapper: fn@(v: fn~()) -> fn~()) -> TaskBuilder {
let prev_gen_body = self.gen_body;
let notify_chan = if self.opts.notify_chan.is_none() {
None
* When spawning into a new scheduler, the number of threads requested
* must be greater than zero.
*/
- fn spawn(+f: fn~()) {
+ fn spawn(f: fn~()) {
let notify_chan = if self.opts.notify_chan.is_none() {
None
} else {
spawn::spawn_raw(move opts, x.gen_body(move f));
}
/// Runs a task, while transfering ownership of one argument to the child.
- fn spawn_with<A: Send>(arg: A, +f: fn~(+v: A)) {
+ fn spawn_with<A: Send>(arg: A, f: fn~(v: A)) {
let arg = ~mut Some(move arg);
do self.spawn |move arg, move f| {
f(option::swap_unwrap(arg))
* otherwise be required to establish communication from the parent
* to the child.
*/
- fn spawn_listener<A: Send>(+f: fn~(comm::Port<A>)) -> comm::Chan<A> {
+ fn spawn_listener<A: Send>(f: fn~(comm::Port<A>)) -> comm::Chan<A> {
let setup_po = comm::Port();
- let setup_ch = comm::Chan(setup_po);
+ let setup_ch = comm::Chan(&setup_po);
do self.spawn |move f| {
let po = comm::Port();
- let ch = comm::Chan(po);
+ let ch = comm::Chan(&po);
comm::send(setup_ch, ch);
f(move po);
}
* Runs a new task, setting up communication in both directions
*/
fn spawn_conversation<A: Send, B: Send>
- (+f: fn~(comm::Port<A>, comm::Chan<B>))
+ (f: fn~(comm::Port<A>, comm::Chan<B>))
-> (comm::Port<B>, comm::Chan<A>) {
let from_child = comm::Port();
- let to_parent = comm::Chan(from_child);
+ let to_parent = comm::Chan(&from_child);
let to_child = do self.spawn_listener |move f, from_parent| {
f(from_parent, to_parent)
};
* # Failure
* Fails if a future_result was already set for this task.
*/
- fn try<T: Send>(+f: fn~() -> T) -> Result<T,()> {
+ fn try<T: Send>(f: fn~() -> T) -> Result<T,()> {
let po = comm::Port();
- let ch = comm::Chan(po);
+ let ch = comm::Chan(&po);
let mut result = None;
let fr_task_builder = self.future_result(|+r| {
/* Spawn convenience functions */
-pub fn spawn(+f: fn~()) {
+pub fn spawn(f: fn~()) {
/*!
* Creates and executes a new child task
*
task().spawn(move f)
}
-pub fn spawn_unlinked(+f: fn~()) {
+pub fn spawn_unlinked(f: fn~()) {
/*!
* Creates a child task unlinked from the current one. If either this
* task or the child task fails, the other will not be killed.
task().unlinked().spawn(move f)
}
-pub fn spawn_supervised(+f: fn~()) {
+pub fn spawn_supervised(f: fn~()) {
/*!
* Creates a child task unlinked from the current one. If either this
* task or the child task fails, the other will not be killed.
task().supervised().spawn(move f)
}
-pub fn spawn_with<A:Send>(+arg: A, +f: fn~(+v: A)) {
+pub fn spawn_with<A:Send>(arg: A, f: fn~(v: A)) {
/*!
* Runs a task, while transfering ownership of one argument to the
* child.
task().spawn_with(move arg, move f)
}
-pub fn spawn_listener<A:Send>(+f: fn~(comm::Port<A>)) -> comm::Chan<A> {
+pub fn spawn_listener<A:Send>(f: fn~(comm::Port<A>)) -> comm::Chan<A> {
/*!
* Runs a new task while providing a channel from the parent to the child
*
}
pub fn spawn_conversation<A: Send, B: Send>
- (+f: fn~(comm::Port<A>, comm::Chan<B>))
+ (f: fn~(comm::Port<A>, comm::Chan<B>))
-> (comm::Port<B>, comm::Chan<A>) {
/*!
* Runs a new task, setting up communication in both directions
task().spawn_conversation(move f)
}
-pub fn spawn_sched(mode: SchedMode, +f: fn~()) {
+pub fn spawn_sched(mode: SchedMode, f: fn~()) {
/*!
* Creates a new scheduler and executes a task on it
*
task().sched_mode(mode).spawn(move f)
}
-pub fn try<T:Send>(+f: fn~() -> T) -> Result<T,()> {
+pub fn try<T:Send>(f: fn~() -> T) -> Result<T,()> {
/*!
* Execute a function in another task and return either the return value
* of the function or result::err.
#[test] #[ignore(cfg(windows))]
fn test_spawn_unlinked_unsup_no_fail_down() { // grandchild sends on a port
let po = comm::Port();
- let ch = comm::Chan(po);
+ let ch = comm::Chan(&po);
do spawn_unlinked {
do spawn_unlinked {
// Give middle task a chance to fail-but-not-kill-us.
#[test] #[should_fail] #[ignore(cfg(windows))]
fn test_spawn_linked_sup_fail_up() { // child fails; parent fails
let po = comm::Port::<()>();
- let _ch = comm::Chan(po);
+ let _ch = comm::Chan(&po);
// Unidirectional "parenting" shouldn't override bidirectional linked.
// We have to cheat with opts - the interface doesn't support them because
// they don't make sense (redundant with task().supervised()).
#[test] #[should_fail] #[ignore(cfg(windows))]
fn test_spawn_linked_unsup_fail_up() { // child fails; parent fails
let po = comm::Port::<()>();
- let _ch = comm::Chan(po);
+ let _ch = comm::Chan(&po);
// Default options are to spawn linked & unsupervised.
do spawn { fail; }
comm::recv(po); // We should get punted awake
#[test]
fn test_run_basic() {
let po = comm::Port();
- let ch = comm::Chan(po);
+ let ch = comm::Chan(&po);
do task().spawn {
comm::send(ch, ());
}
#[test]
fn test_add_wrapper() {
let po = comm::Port();
- let ch = comm::Chan(po);
+ let ch = comm::Chan(&po);
let b0 = task();
let b1 = do b0.add_wrapper |body| {
fn~() {
#[test]
fn test_spawn_listiner_bidi() {
let po = comm::Port();
- let ch = comm::Chan(po);
+ let ch = comm::Chan(&po);
let ch = do spawn_listener |po| {
// Now the child has a port called 'po' to read from and
// an environment-captured channel called 'ch'.
#[test]
fn test_spawn_sched() {
let po = comm::Port();
- let ch = comm::Chan(po);
+ let ch = comm::Chan(&po);
fn f(i: int, ch: comm::Chan<()>) {
let parent_sched_id = rt::rust_get_sched_id();
#[test]
fn test_spawn_sched_childs_on_same_sched() {
let po = comm::Port();
- let ch = comm::Chan(po);
+ let ch = comm::Chan(&po);
do spawn_sched(SingleThreaded) {
let parent_sched_id = rt::rust_get_sched_id();
for iter::repeat(20u) {
let start_po = comm::Port();
- let start_ch = comm::Chan(start_po);
+ let start_ch = comm::Chan(&start_po);
let fin_po = comm::Port();
- let fin_ch = comm::Chan(fin_po);
+ let fin_ch = comm::Chan(&fin_po);
let lock = testrt::rust_dbg_lock_create();
}
let setup_po = comm::Port();
- let setup_ch = comm::Chan(setup_po);
+ let setup_ch = comm::Chan(&setup_po);
let parent_po = comm::Port();
- let parent_ch = comm::Chan(parent_po);
+ let parent_ch = comm::Chan(&parent_po);
do spawn {
let child_po = comm::Port();
- comm::send(setup_ch, comm::Chan(child_po));
+ comm::send(setup_ch, comm::Chan(&child_po));
pingpong(child_po, parent_ch);
};
}
#[cfg(test)]
-fn avoid_copying_the_body(spawnfn: fn(+v: fn~())) {
+fn avoid_copying_the_body(spawnfn: fn(v: fn~())) {
let p = comm::Port::<uint>();
- let ch = comm::Chan(p);
+ let ch = comm::Chan(&p);
let x = ~1;
- let x_in_parent = ptr::p2::addr_of(&(*x)) as uint;
+ let x_in_parent = ptr::addr_of(&(*x)) as uint;
do spawnfn {
- let x_in_child = ptr::p2::addr_of(&(*x)) as uint;
+ let x_in_child = ptr::addr_of(&(*x)) as uint;
comm::send(ch, x_in_child);
}
#[test]
fn test_avoid_copying_the_body_spawn_listener() {
- do avoid_copying_the_body |+f| {
+ do avoid_copying_the_body |f| {
spawn_listener(fn~(move f, _po: comm::Port<int>) {
f();
});
#[test]
fn test_avoid_copying_the_body_spawn_listener_1() {
- do avoid_copying_the_body |+f| {
+ do avoid_copying_the_body |f| {
task().spawn_listener(fn~(move f, _po: comm::Port<int>) {
f();
});
#[test]
fn test_platform_thread() {
let po = comm::Port();
- let ch = comm::Chan(po);
+ let ch = comm::Chan(&po);
do task().sched_mode(PlatformThread).spawn {
comm::send(ch, ());
}
}
#[test]
-pub fn test_tls_multitask() unsafe {
+fn test_tls_multitask() unsafe {
fn my_key(_x: @~str) { }
local_data_set(my_key, @~"parent data");
do task::spawn unsafe {
}
#[test]
-pub fn test_tls_overwrite() unsafe {
+fn test_tls_overwrite() unsafe {
fn my_key(_x: @~str) { }
local_data_set(my_key, @~"first data");
local_data_set(my_key, @~"next data"); // Shouldn't leak.
}
#[test]
-pub fn test_tls_pop() unsafe {
+fn test_tls_pop() unsafe {
fn my_key(_x: @~str) { }
local_data_set(my_key, @~"weasel");
assert *(local_data_pop(my_key).get()) == ~"weasel";
}
#[test]
-pub fn test_tls_modify() unsafe {
+fn test_tls_modify() unsafe {
fn my_key(_x: @~str) { }
local_data_modify(my_key, |data| {
match data {
}
#[test]
-pub fn test_tls_crust_automorestack_memorial_bug() unsafe {
+fn test_tls_crust_automorestack_memorial_bug() unsafe {
// This might result in a stack-canary clobber if the runtime fails to set
// sp_limit to 0 when calling the cleanup extern - it might automatically
// jump over to the rust stack, which causes next_c_sp to get recorded as
}
#[test]
-pub fn test_tls_multiple_types() unsafe {
+fn test_tls_multiple_types() unsafe {
fn str_key(_x: @~str) { }
fn box_key(_x: @@()) { }
fn int_key(_x: @int) { }
}
#[test]
-pub fn test_tls_overwrite_multiple_types() {
+fn test_tls_overwrite_multiple_types() {
fn str_key(_x: @~str) { }
fn box_key(_x: @@()) { }
fn int_key(_x: @int) { }
#[test]
#[should_fail]
#[ignore(cfg(windows))]
-pub fn test_tls_cleanup_on_failure() unsafe {
+fn test_tls_cleanup_on_failure() unsafe {
fn str_key(_x: @~str) { }
fn box_key(_x: @@()) { }
fn int_key(_x: @int) { }
// We use dvec because it's the best data structure in core. If TLS is used
// heavily in future, this could be made more efficient with a proper map.
-pub type TaskLocalElement = (*libc::c_void, *libc::c_void, LocalData);
+type TaskLocalElement = (*libc::c_void, *libc::c_void, LocalData);
// Has to be a pointer at outermost layer; the foreign call returns void *.
-pub type TaskLocalMap = @dvec::DVec<Option<TaskLocalElement>>;
+type TaskLocalMap = @dvec::DVec<Option<TaskLocalElement>>;
-pub extern fn cleanup_task_local_map(map_ptr: *libc::c_void) unsafe {
+extern fn cleanup_task_local_map(map_ptr: *libc::c_void) unsafe {
assert !map_ptr.is_null();
// Get and keep the single reference that was created at the beginning.
let _map: TaskLocalMap = cast::reinterpret_cast(&map_ptr);
}
// Gets the map from the runtime. Lazily initialises if not done so already.
-pub unsafe fn get_task_local_map(task: *rust_task) -> TaskLocalMap {
+unsafe fn get_task_local_map(task: *rust_task) -> TaskLocalMap {
// Relies on the runtime initialising the pointer to null.
// NOTE: The map's box lives in TLS invisibly referenced once. Each time
}
}
-pub unsafe fn key_to_key_value<T: Owned>(
+unsafe fn key_to_key_value<T: Owned>(
key: LocalDataKey<T>) -> *libc::c_void {
// Keys are closures, which are (fnptr,envptr) pairs. Use fnptr.
}
// If returning Some(..), returns with @T with the map's reference. Careful!
-pub unsafe fn local_data_lookup<T: Owned>(
+unsafe fn local_data_lookup<T: Owned>(
map: TaskLocalMap, key: LocalDataKey<T>)
-> Option<(uint, *libc::c_void)> {
}
}
-pub unsafe fn local_get_helper<T: Owned>(
+unsafe fn local_get_helper<T: Owned>(
task: *rust_task, key: LocalDataKey<T>,
do_pop: bool) -> Option<@T> {
****************************************************************************/
#[doc(hidden)]; // FIXME #3538
+#[warn(deprecated_mode)];
use rt::rust_task;
use rt::rust_closure;
{ $x:expr } => { unsafe { let y <- *ptr::addr_of(&($x)); move y } }
)
-pub type TaskSet = send_map::linear::LinearMap<*rust_task,()>;
+type TaskSet = send_map::linear::LinearMap<*rust_task,()>;
-pub fn new_taskset() -> TaskSet {
+fn new_taskset() -> TaskSet {
send_map::linear::LinearMap()
}
-pub fn taskset_insert(tasks: &mut TaskSet, task: *rust_task) {
+fn taskset_insert(tasks: &mut TaskSet, task: *rust_task) {
let didnt_overwrite = tasks.insert(task, ());
assert didnt_overwrite;
}
-pub fn taskset_remove(tasks: &mut TaskSet, task: *rust_task) {
+fn taskset_remove(tasks: &mut TaskSet, task: *rust_task) {
let was_present = tasks.remove(&task);
assert was_present;
}
}
// One of these per group of linked-failure tasks.
-pub type TaskGroupData = {
+type TaskGroupData = {
// All tasks which might kill this group. When this is empty, the group
// can be "GC"ed (i.e., its link in the ancestor list can be removed).
mut members: TaskSet,
// tasks in this group.
mut descendants: TaskSet,
};
-pub type TaskGroupArc = private::Exclusive<Option<TaskGroupData>>;
+type TaskGroupArc = private::Exclusive<Option<TaskGroupData>>;
-pub type TaskGroupInner = &mut Option<TaskGroupData>;
+type TaskGroupInner = &mut Option<TaskGroupData>;
// A taskgroup is 'dead' when nothing can cause it to fail; only members can.
-pub pure fn taskgroup_is_dead(tg: &TaskGroupData) -> bool {
+pure fn taskgroup_is_dead(tg: &TaskGroupData) -> bool {
(&tg.members).is_empty()
}
// taskgroup which was spawned-unlinked. Tasks from intermediate generations
// have references to the middle of the list; when intermediate generations
// die, their node in the list will be collected at a descendant's spawn-time.
-pub type AncestorNode = {
+type AncestorNode = {
// Since the ancestor list is recursive, we end up with references to
// exclusives within other exclusives. This is dangerous business (if
// circular references arise, deadlock and memory leaks are imminent).
// Recursive rest of the list.
mut ancestors: AncestorList,
};
-pub enum AncestorList = Option<private::Exclusive<AncestorNode>>;
+enum AncestorList = Option<private::Exclusive<AncestorNode>>;
// Accessors for taskgroup arcs and ancestor arcs that wrap the unsafety.
#[inline(always)]
-pub fn access_group<U>(x: &TaskGroupArc, blk: fn(TaskGroupInner) -> U) -> U {
+fn access_group<U>(x: &TaskGroupArc, blk: fn(TaskGroupInner) -> U) -> U {
unsafe { x.with(blk) }
}
#[inline(always)]
-pub fn access_ancestors<U>(x: &private::Exclusive<AncestorNode>,
+fn access_ancestors<U>(x: &private::Exclusive<AncestorNode>,
blk: fn(x: &mut AncestorNode) -> U) -> U {
unsafe { x.with(blk) }
}
// (3) As a bonus, coalesces away all 'dead' taskgroup nodes in the list.
// FIXME(#2190): Change Option<fn@(...)> to Option<fn&(...)>, to save on
// allocations. Once that bug is fixed, changing the sigil should suffice.
-pub fn each_ancestor(list: &mut AncestorList,
+fn each_ancestor(list: &mut AncestorList,
bail_opt: Option<fn@(TaskGroupInner)>,
forward_blk: fn(TaskGroupInner) -> bool)
-> bool {
}
// One of these per task.
-pub struct TCB {
+struct TCB {
me: *rust_task,
// List of tasks with whose fates this one's is intertwined.
tasks: TaskGroupArc, // 'none' means the group has failed.
}
}
-pub fn TCB(me: *rust_task, tasks: TaskGroupArc, ancestors: AncestorList,
+fn TCB(me: *rust_task, tasks: TaskGroupArc, ancestors: AncestorList,
is_main: bool, notifier: Option<AutoNotify>) -> TCB {
let notifier = move notifier;
}
}
-pub struct AutoNotify {
+struct AutoNotify {
notify_chan: Chan<Notification>,
mut failed: bool,
drop {
}
}
-pub fn AutoNotify(chan: Chan<Notification>) -> AutoNotify {
+fn AutoNotify(chan: Chan<Notification>) -> AutoNotify {
AutoNotify {
notify_chan: chan,
failed: true // Un-set above when taskgroup successfully made.
}
}
-pub fn enlist_in_taskgroup(state: TaskGroupInner, me: *rust_task,
+fn enlist_in_taskgroup(state: TaskGroupInner, me: *rust_task,
is_member: bool) -> bool {
let newstate = util::replace(state, None);
// If 'None', the group was failing. Can't enlist.
}
// NB: Runs in destructor/post-exit context. Can't 'fail'.
-pub fn leave_taskgroup(state: TaskGroupInner, me: *rust_task,
+fn leave_taskgroup(state: TaskGroupInner, me: *rust_task,
is_member: bool) {
let newstate = util::replace(state, None);
// If 'None', already failing and we've already gotten a kill signal.
}
// NB: Runs in destructor/post-exit context. Can't 'fail'.
-pub fn kill_taskgroup(state: TaskGroupInner, me: *rust_task, is_main: bool) {
+fn kill_taskgroup(state: TaskGroupInner, me: *rust_task, is_main: bool) {
// NB: We could do the killing iteration outside of the group arc, by
// having "let mut newstate" here, swapping inside, and iterating after.
// But that would let other exiting tasks fall-through and exit while we
() => (cast::transmute((-2 as uint, 0u)))
)
-pub fn gen_child_taskgroup(linked: bool, supervised: bool)
+fn gen_child_taskgroup(linked: bool, supervised: bool)
-> (TaskGroupArc, AncestorList, bool) {
let spawner = rt::rust_get_task();
/*######################################################################*
}
}
-pub fn spawn_raw(opts: TaskOpts, +f: fn~()) {
+pub fn spawn_raw(opts: TaskOpts, f: fn~()) {
let (child_tg, ancestors, is_main) =
gen_child_taskgroup(opts.linked, opts.supervised);
fn make_child_wrapper(child: *rust_task, child_arc: TaskGroupArc,
ancestors: AncestorList, is_main: bool,
notify_chan: Option<Chan<Notification>>,
- +f: fn~()) -> fn~() {
+ f: fn~()) -> fn~() {
let child_data = ~mut Some((move child_arc, move ancestors));
return fn~(move notify_chan, move child_data, move f) {
// Agh. Get move-mode items into the closure. FIXME (#2829)
#[test]
fn test_spawn_raw_simple() {
let po = comm::Port();
- let ch = comm::Chan(po);
+ let ch = comm::Chan(&po);
do spawn_raw(default_task_opts()) {
comm::send(ch, ());
}
*/
// NB: transitionary, de-mode-ing.
-// tjc: re-forbid deprecated modes after snapshot
+#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
use cmp::Eq;
//! Vectors
-#[warn(deprecated_mode)];
-#[warn(deprecated_pattern)];
+#[forbid(deprecated_mode)];
+#[forbid(deprecated_pattern)];
#[warn(non_camel_case_types)];
use cmp::{Eq, Ord};
#[abi = "rust-intrinsic"]
extern mod rusti {
- fn move_val_init<T>(&dst: T, -src: T);
+ fn move_val_init<T>(dst: &mut T, -src: T);
}
+
/// Returns true if a vector contains no elements
pub pure fn is_empty<T>(v: &[const T]) -> bool {
as_const_buf(v, |_p, len| len == 0u)
do as_mut_buf(v) |p, _len| {
let mut i: uint = 0u;
while i < n_elts {
- rusti::move_val_init(*ptr::mut_offset(p, i), op(i));
+ rusti::move_val_init(&mut(*ptr::mut_offset(p, i)), op(i));
i += 1u;
}
}
(**repr).unboxed.fill += sys::size_of::<T>();
let p = addr_of(&((**repr).unboxed.data));
let p = ptr::offset(p, fill) as *mut T;
- rusti::move_val_init(*p, move initval);
+ rusti::move_val_init(&mut(*p), move initval);
}
#[inline(never)]
do as_mut_buf(v) |p, _len| {
let mut box2 = None;
box2 <-> box;
- rusti::move_val_init(*ptr::mut_offset(p, i),
+ rusti::move_val_init(&mut(*ptr::mut_offset(p, i)),
option::unwrap(move box2));
}
}
}
pure fn to_vec() -> ~[A] { iter::to_vec(&self) }
- // FIXME--bug in resolve prevents this from working (#2611)
- // fn flat_map_to_vec<B:copy,IB:base_iter<B>>(op: fn(A) -> IB) -> ~[B] {
- // iter::flat_map_to_vec(self, op)
- // }
+ pure fn flat_map_to_vec<B:Copy,IB:BaseIter<B>>(op: fn(A) -> IB) -> ~[B] {
+ iter::flat_map_to_vec(&self, op)
+ }
pub pure fn find(p: fn(a: A) -> bool) -> Option<A> {
iter::find(&self, p)
// NB: transitionary, de-mode-ing.
-// tjc: forbid deprecated modes again after snap
+#[forbid(deprecated_mode)];
/**
* Concurrency-enabled mechanisms for sharing mutable and/or immutable state
* between tasks.
#[abi = "rust-intrinsic"]
extern mod rusti {
- fn move_val_init<T>(&dst: T, -src: T);
+ fn move_val_init<T>(dst: &mut T, -src: T);
fn needs_drop<T>() -> bool;
}
+
extern mod rustrt {
#[rust_stack]
fn rust_call_tydesc_glue(root: *u8, tydesc: *TypeDesc, field: size_t);
(reinterpret_cast(&(p & !1)), p & 1 == 1)
}
-// The duplication between the POD and non-POD functions is annoying.
impl &Arena {
// Functions for the POD part of the arena
fn alloc_pod_grow(n_bytes: uint, align: uint) -> *u8 {
let tydesc = sys::get_type_desc::<T>();
let ptr = self.alloc_pod_inner((*tydesc).size, (*tydesc).align);
let ptr: *mut T = reinterpret_cast(&ptr);
- rusti::move_val_init(*ptr, op());
+ rusti::move_val_init(&mut (*ptr), op());
return reinterpret_cast(&ptr);
}
}
// has *not* been initialized yet.
*ty_ptr = reinterpret_cast(&tydesc);
// Actually initialize it
- rusti::move_val_init(*ptr, op());
+ rusti::move_val_init(&mut(*ptr), op());
// Now that we are done, update the tydesc to indicate that
// the object is there.
*ty_ptr = bitpack_tydesc_ptr(tydesc, true);
-// tjc: forbid deprecated modes again after snap
+#[forbid(deprecated_mode)];
use vec::{to_mut, from_elem};
pure fn right(_w0: uint, w1: uint) -> uint { return w1; }
impl Bitv: ops::Index<uint,bool> {
- pure fn index(+i: uint) -> bool {
+ pure fn index(i: uint) -> bool {
self.get(i)
}
}
* great care must be taken to ensure that a reference to the c_vec::t is
* still held if needed.
*/
+#[forbid(deprecated_mode)];
/**
* The type representing a foreign chunk of memory
*
* Fails if `ofs` is greater or equal to the length of the vector
*/
-pub fn set<T: Copy>(t: CVec<T>, ofs: uint, +v: T) {
+pub fn set<T: Copy>(t: CVec<T>, ofs: uint, v: T) {
assert ofs < len(t);
unsafe { *ptr::mut_offset((*t).base, ofs) = v };
}
-// tjc: forbid deprecated modes again after snap
+#[forbid(deprecated_mode)];
/// A dynamic, mutable location.
///
/// Similar to a mutable option type, but friendlier.
}
impl<T: Send, U: Send> DuplexStream<T, U> : Channel<T> {
- fn send(+x: T) {
+ fn send(x: T) {
self.chan.send(move x)
}
- fn try_send(+x: T) -> bool {
+ fn try_send(x: T) -> bool {
self.chan.try_send(move x)
}
}
-// tjc: forbid deprecated modes again after snap
+#[forbid(deprecated_mode)];
//! Unsafe debugging functions for inspecting values.
use cast::reinterpret_cast;
//! A deque. Untested as of yet. Likely buggy
-// tjc: forbid deprecated modes again after snap
+#[forbid(deprecated_mode)];
#[forbid(non_camel_case_types)];
use option::{Some, None};
assert (deq.get(3) == d);
}
- fn test_parameterized<T: Copy Eq Owned>(a: T, +b: T, +c: T, +d: T) {
+ fn test_parameterized<T: Copy Eq Owned>(a: T, b: T, c: T, d: T) {
let deq: deque::Deque<T> = deque::create::<T>();
assert (deq.size() == 0u);
deq.add_front(a);
+#[forbid(deprecated_mode)];
// Simple Extensible Binary Markup Language (ebml) reader and writer on a
// cursor model. See the specification here:
// http://www.matroska.org/technical/specs/rfc/index.html
type TaggedDoc = {tag: uint, doc: Doc};
impl Doc: ops::Index<uint,Doc> {
- pure fn index(+tag: uint) -> Doc {
+ pure fn index(tag: uint) -> Doc {
unsafe {
get_doc(self, tag)
}
#[test]
fn test_option_int() {
- fn serialize_1<S: serialization::Serializer>(&&s: S, v: int) {
+ fn serialize_1<S: serialization::Serializer>(s: &S, v: int) {
s.emit_i64(v as i64);
}
- fn serialize_0<S: serialization::Serializer>(&&s: S, v: Option<int>) {
+ fn serialize_0<S: serialization::Serializer>(s: &S, v: Option<int>) {
do s.emit_enum(~"core::option::t") {
match v {
None => s.emit_enum_variant(
}
}
- fn deserialize_1<S: serialization::Deserializer>(&&s: S) -> int {
+ fn deserialize_1<S: serialization::Deserializer>(s: &S) -> int {
s.read_i64() as int
}
- fn deserialize_0<S: serialization::Deserializer>(&&s: S) -> Option<int> {
+ fn deserialize_0<S: serialization::Deserializer>(s: &S) -> Option<int> {
do s.read_enum(~"core::option::t") {
do s.read_enum_variant |i| {
match i {
debug!("v == %?", v);
let bytes = do io::with_bytes_writer |wr| {
let ebml_w = ebml::Writer(wr);
- serialize_0(ebml_w, v);
+ serialize_0(&ebml_w, v);
};
let ebml_doc = ebml::Doc(@bytes);
let deser = ebml_deserializer(ebml_doc);
- let v1 = deserialize_0(deser);
+ let v1 = deserialize_0(&deser);
debug!("v1 == %?", v1);
assert v == v1;
}
+#[forbid(deprecated_mode)];
use serialization2;
// Simple Extensible Binary Markup Language (ebml) reader and writer on a
}
impl Doc: ops::Index<uint,Doc> {
- pure fn index(+tag: uint) -> Doc {
+ pure fn index(tag: uint) -> Doc {
unsafe {
get_doc(self, tag)
}
-#[warn(deprecated_mode)];
+#[forbid(deprecated_mode)];
/*!
* A functional key,value store that works on anything.
pub fn init<K, V>() -> Treemap<K, V> { @Empty }
/// Insert a value into the map
-pub fn insert<K: Copy Eq Ord, V: Copy>(m: Treemap<K, V>, +k: K, +v: V)
+pub fn insert<K: Copy Eq Ord, V: Copy>(m: Treemap<K, V>, k: K, v: V)
-> Treemap<K, V> {
@match m {
@Empty => Node(@k, @v, @Empty, @Empty),
}
/// Find a value based on the key
-pub fn find<K: Eq Ord, V: Copy>(m: Treemap<K, V>, +k: K) -> Option<V> {
+pub fn find<K: Eq Ord, V: Copy>(m: Treemap<K, V>, k: K) -> Option<V> {
match *m {
Empty => None,
Node(@ref kk, @copy v, left, right) => {
* do_work(input, output);
* }
*/
-
-// tjc: forbid deprecated modes again after snap
+#[forbid(deprecated_mode)];
use core::cmp::Eq;
use core::result::{Err, Ok};
};
}
-fn find_opt(opts: &[Opt], +nm: Name) -> Option<uint> {
+fn find_opt(opts: &[Opt], nm: Name) -> Option<uint> {
vec::position(opts, |opt| opt.name == nm)
}
*/
pub fn getopts(args: &[~str], opts: &[Opt]) -> Result unsafe {
let n_opts = vec::len::<Opt>(opts);
- fn f(+_x: uint) -> ~[Optval] { return ~[]; }
+ fn f(_x: uint) -> ~[Optval] { return ~[]; }
let vals = vec::to_mut(vec::from_fn(n_opts, f));
let mut free: ~[~str] = ~[];
let l = vec::len(args);
// Rust JSON serialization library
// Copyright (c) 2011 Google Inc.
-// tjc: forbid deprecated modes again after snap
+#[forbid(deprecated_mode)];
#[forbid(non_camel_case_types)];
//! json serialization
while char::is_whitespace(self.ch) { self.bump(); }
}
- fn parse_ident(ident: &str, +value: Json) -> Result<Json, Error> {
+ fn parse_ident(ident: &str, value: Json) -> Result<Json, Error> {
if str::all(ident, |c| c == self.next_char()) {
self.bump();
Ok(move value)
//! A standard linked list
-#[warn(deprecated_mode)];
+#[forbid(deprecated_mode)];
use core::cmp::Eq;
use core::option;
}
/// Returns true if a list contains an element with the given value
-pub fn has<T: Copy Eq>(ls: @List<T>, +elt: T) -> bool {
+pub fn has<T: Copy Eq>(ls: @List<T>, elt: T) -> bool {
for each(ls) |e| {
if *e == elt { return true; }
}
/*
/// Push one element into the front of a list, returning a new list
/// THIS VERSION DOESN'T ACTUALLY WORK
-pure fn push<T: Copy>(ll: &mut @list<T>, +vv: T) {
+pure fn push<T: Copy>(ll: &mut @list<T>, vv: T) {
ll = &mut @cons(vv, *ll)
}
*/
//! A map type
-
-// tjc: forbid deprecated modes again after snap
+#[forbid(deprecated_mode)];
use io::WriterUtil;
use to_str::ToStr;
*
* Returns true if the key did not already exist in the map
*/
- fn insert(v: K, +v: V) -> bool;
+ fn insert(v: K, v: V) -> bool;
/// Returns true if the map contains a value for the specified key
fn contains_key(key: K) -> bool;
fn clear();
/// Iterate over all the key/value pairs in the map by value
- pure fn each(fn(key: K, +value: V) -> bool);
+ pure fn each(fn(key: K, value: V) -> bool);
/// Iterate over all the keys in the map by value
pure fn each_key(fn(key: K) -> bool);
}
}
- fn insert(k: K, +v: V) -> bool {
+ fn insert(k: K, v: V) -> bool {
let hash = k.hash_keyed(0,0) as uint;
match self.search_tbl(&k, hash) {
NotFound => {
self.chains = chains(initial_capacity);
}
- pure fn each(blk: fn(key: K, +value: V) -> bool) {
+ pure fn each(blk: fn(key: K, value: V) -> bool) {
self.each_ref(|k, v| blk(*k, *v))
}
}
impl<K:Eq IterBytes Hash Copy, V: Copy> T<K, V>: ops::Index<K, V> {
- pure fn index(+k: K) -> V {
+ pure fn index(k: K) -> V {
unsafe {
self.get(k)
}
}
/// Convert a set into a vector.
-pub fn vec_from_set<T:Eq IterBytes Hash Copy>(s: Set<T>) -> ~[T] {
+pub pure fn vec_from_set<T:Eq IterBytes Hash Copy>(s: Set<T>) -> ~[T] {
do vec::build_sized(s.size()) |push| {
for s.each_key() |k| {
push(k);
}
}
- pure fn each(op: fn(key: K, +value: V) -> bool) {
+ pure fn each(op: fn(key: K, value: V) -> bool) {
unsafe {
do self.borrow_imm |p| {
p.each(|k, v| op(*k, *v))
//! High-level interface to libuv's TCP functionality
+// XXX Need FFI fixes
+#[allow(deprecated_mode)];
use ip = net_ip;
use uv::iotask;
let result_po = core::comm::Port::<ConnAttempt>();
let closed_signal_po = core::comm::Port::<()>();
let conn_data = {
- result_ch: core::comm::Chan(result_po),
- closed_signal_ch: core::comm::Chan(closed_signal_po)
+ result_ch: core::comm::Chan(&result_po),
+ closed_signal_ch: core::comm::Chan(&closed_signal_po)
};
let conn_data_ptr = ptr::addr_of(&conn_data);
let reader_po = core::comm::Port::<result::Result<~[u8], TcpErrData>>();
*(stream_handle_ptr as *mut uv::ll::uv_tcp_t) = uv::ll::tcp_t();
let socket_data = @{
reader_po: reader_po,
- reader_ch: core::comm::Chan(reader_po),
+ reader_ch: core::comm::Chan(&reader_po),
stream_handle_ptr: stream_handle_ptr,
connect_req: uv::ll::connect_t(),
write_req: uv::ll::write_t(),
* * `sock` - a `net::tcp::tcp_socket` that you wish to stop reading on
*/
pub fn read_stop(sock: &TcpSocket,
- +read_port: comm::Port<result::Result<~[u8], TcpErrData>>) ->
+ read_port: comm::Port<result::Result<~[u8], TcpErrData>>) ->
result::Result<(), TcpErrData> unsafe {
log(debug, fmt!("taking the read_port out of commission %?", read_port));
let socket_data = ptr::addr_of(&(*sock.socket_data));
*(stream_handle_ptr as *mut uv::ll::uv_tcp_t) = uv::ll::tcp_t();
let client_socket_data = @{
reader_po: reader_po,
- reader_ch: core::comm::Chan(reader_po),
+ reader_ch: core::comm::Chan(&reader_po),
stream_handle_ptr : stream_handle_ptr,
connect_req : uv::ll::connect_t(),
write_req : uv::ll::write_t(),
(*client_socket_data_ptr).stream_handle_ptr;
let result_po = core::comm::Port::<Option<TcpErrData>>();
- let result_ch = core::comm::Chan(result_po);
+ let result_ch = core::comm::Chan(&result_po);
// UNSAFE LIBUV INTERACTION BEGIN
// .. normally this happens within the context of
*/
pub fn listen(host_ip: ip::IpAddr, port: uint, backlog: uint,
iotask: IoTask,
- +on_establish_cb: fn~(comm::Chan<Option<TcpErrData>>),
- +new_connect_cb: fn~(TcpNewConnection,
+ on_establish_cb: fn~(comm::Chan<Option<TcpErrData>>),
+ new_connect_cb: fn~(TcpNewConnection,
comm::Chan<Option<TcpErrData>>))
-> result::Result<(), TcpListenErrData> unsafe {
do listen_common(move host_ip, port, backlog, iotask, on_establish_cb)
fn listen_common(host_ip: ip::IpAddr, port: uint, backlog: uint,
iotask: IoTask,
- +on_establish_cb: fn~(comm::Chan<Option<TcpErrData>>),
- +on_connect_cb: fn~(*uv::ll::uv_tcp_t))
+ on_establish_cb: fn~(comm::Chan<Option<TcpErrData>>),
+ on_connect_cb: fn~(*uv::ll::uv_tcp_t))
-> result::Result<(), TcpListenErrData> unsafe {
let stream_closed_po = core::comm::Port::<()>();
let kill_po = core::comm::Port::<Option<TcpErrData>>();
- let kill_ch = core::comm::Chan(kill_po);
+ let kill_ch = core::comm::Chan(&kill_po);
let server_stream = uv::ll::tcp_t();
let server_stream_ptr = ptr::addr_of(&server_stream);
let server_data = {
server_stream_ptr: server_stream_ptr,
- stream_closed_ch: core::comm::Chan(stream_closed_po),
+ stream_closed_ch: core::comm::Chan(&stream_closed_po),
kill_ch: kill_ch,
on_connect_cb: move on_connect_cb,
iotask: iotask,
/// Implementation of `io::reader` trait for a buffered `net::tcp::tcp_socket`
impl TcpSocketBuf: io::Reader {
- fn read(buf: &[mut u8], +len: uint) -> uint {
+ fn read(buf: &[mut u8], len: uint) -> uint {
// Loop until our buffer has enough data in it for us to read from.
while self.data.buf.len() < len {
let read_result = read(&self.data.sock, 0u);
let mut bytes = ~[0];
if self.read(bytes, 1u) == 0 { fail } else { bytes[0] as int }
}
- fn unread_byte(+amt: int) {
+ fn unread_byte(amt: int) {
self.data.buf.unshift(amt as u8);
}
fn eof() -> bool {
false // noop
}
- fn seek(+dist: int, +seek: io::SeekStyle) {
+ fn seek(dist: int, seek: io::SeekStyle) {
log(debug, fmt!("tcp_socket_buf seek stub %? %?", dist, seek));
// noop
}
err_data.err_name, err_data.err_msg));
}
}
- fn seek(+dist: int, +seek: io::SeekStyle) {
+ fn seek(dist: int, seek: io::SeekStyle) {
log(debug, fmt!("tcp_socket_buf seek stub %? %?", dist, seek));
// noop
}
fn tear_down_socket_data(socket_data: @TcpSocketData) unsafe {
let closed_po = core::comm::Port::<()>();
- let closed_ch = core::comm::Chan(closed_po);
+ let closed_ch = core::comm::Chan(&closed_po);
let close_data = {
closed_ch: closed_ch
};
result::Result<(), TcpErrData> unsafe {
let stream_handle_ptr = (*socket_data).stream_handle_ptr;
let stop_po = core::comm::Port::<Option<TcpErrData>>();
- let stop_ch = core::comm::Chan(stop_po);
+ let stop_ch = core::comm::Chan(&stop_po);
do iotask::interact((*socket_data).iotask) |loop_ptr| unsafe {
log(debug, ~"in interact cb for tcp::read_stop");
match uv::ll::read_stop(stream_handle_ptr as *uv::ll::uv_stream_t) {
result::Result<~[u8], TcpErrData>>, TcpErrData> unsafe {
let stream_handle_ptr = (*socket_data).stream_handle_ptr;
let start_po = core::comm::Port::<Option<uv::ll::uv_err_data>>();
- let start_ch = core::comm::Chan(start_po);
+ let start_ch = core::comm::Chan(&start_po);
log(debug, ~"in tcp::read_start before interact loop");
do iotask::interact((*socket_data).iotask) |loop_ptr| unsafe {
log(debug, fmt!("in tcp::read_start interact cb %?", loop_ptr));
let write_buf_vec_ptr = ptr::addr_of(&write_buf_vec);
let result_po = core::comm::Port::<TcpWriteResult>();
let write_data = {
- result_ch: core::comm::Chan(result_po)
+ result_ch: core::comm::Chan(&result_po)
};
let write_data_ptr = ptr::addr_of(&write_data);
do iotask::interact((*socket_data_ptr).iotask) |loop_ptr| unsafe {
let expected_resp = ~"pong";
let server_result_po = core::comm::Port::<~str>();
- let server_result_ch = core::comm::Chan(server_result_po);
+ let server_result_ch = core::comm::Chan(&server_result_po);
let cont_po = core::comm::Port::<()>();
- let cont_ch = core::comm::Chan(cont_po);
+ let cont_ch = core::comm::Chan(&cont_po);
// server
do task::spawn_sched(task::ManualThreads(1u)) {
let actual_req = do comm::listen |server_ch| {
let expected_resp = ~"pong";
let server_result_po = core::comm::Port::<~str>();
- let server_result_ch = core::comm::Chan(server_result_po);
+ let server_result_ch = core::comm::Chan(&server_result_po);
let cont_po = core::comm::Port::<()>();
- let cont_ch = core::comm::Chan(cont_po);
+ let cont_ch = core::comm::Chan(&cont_po);
// server
do task::spawn_sched(task::ManualThreads(1u)) {
let actual_req = do comm::listen |server_ch| {
str::from_bytes(new_bytes)
}
- fn run_tcp_test_server(server_ip: &str, server_port: uint, +resp: ~str,
+ fn run_tcp_test_server(server_ip: &str, server_port: uint, resp: ~str,
server_ch: comm::Chan<~str>,
cont_ch: comm::Chan<()>,
iotask: IoTask) -> ~str {
//! Types/fns concerning URLs (see RFC 3986)
-// tjc: forbid deprecated modes again after a snapshot
+#[forbid(deprecated_mode)];
use core::cmp::Eq;
use map::HashMap;
pub type Query = ~[(~str, ~str)];
-pub fn Url(scheme: ~str, +user: Option<UserInfo>, +host: ~str,
- +port: Option<~str>, +path: ~str, +query: Query,
- +fragment: Option<~str>) -> Url {
+pub fn Url(scheme: ~str, user: Option<UserInfo>, host: ~str,
+ port: Option<~str>, path: ~str, query: Query,
+ fragment: Option<~str>) -> Url {
Url { scheme: move scheme, user: move user, host: move host,
port: move port, path: move path, query: move query,
fragment: move fragment }
}
-fn UserInfo(user: ~str, +pass: Option<~str>) -> UserInfo {
+fn UserInfo(user: ~str, pass: Option<~str>) -> UserInfo {
{user: move user, pass: move pass}
}
}
impl Url: IterBytes {
- pure fn iter_bytes(+lsb0: bool, f: to_bytes::Cb) {
+ pure fn iter_bytes(lsb0: bool, f: to_bytes::Cb) {
unsafe { self.to_str() }.iter_bytes(lsb0, f)
}
}
+#[forbid(deprecated_mode)];
+
use future_spawn = future::spawn;
}
/// A parallel version of map.
-pub fn map<A: Copy Send, B: Copy Send>(xs: &[A], +f: fn~((&A)) -> B) -> ~[B] {
+pub fn map<A: Copy Send, B: Copy Send>(xs: &[A], f: fn~((&A)) -> B) -> ~[B] {
vec::concat(map_slices(xs, || {
fn~(_base: uint, slice : &[A], copy f) -> ~[B] {
vec::map(slice, |x| f(x))
/// A parallel version of mapi.
pub fn mapi<A: Copy Send, B: Copy Send>(xs: &[A],
- +f: fn~(uint, (&A)) -> B) -> ~[B] {
+ f: fn~(uint, (&A)) -> B) -> ~[B] {
let slices = map_slices(xs, || {
fn~(base: uint, slice : &[A], copy f) -> ~[B] {
vec::mapi(slice, |i, x| {
}
/// Returns true if the function holds for all elements in the vector.
-pub fn alli<A: Copy Send>(xs: &[A], +f: fn~(uint, (&A)) -> bool) -> bool {
+pub fn alli<A: Copy Send>(xs: &[A], f: fn~(uint, (&A)) -> bool) -> bool {
do vec::all(map_slices(xs, || {
fn~(base: uint, slice : &[A], copy f) -> bool {
vec::alli(slice, |i, x| {
}
/// Returns true if the function holds for any elements in the vector.
-pub fn any<A: Copy Send>(xs: &[A], +f: fn~(&(A)) -> bool) -> bool {
+pub fn any<A: Copy Send>(xs: &[A], f: fn~(&(A)) -> bool) -> bool {
do vec::any(map_slices(xs, || {
fn~(_base : uint, slice: &[A], copy f) -> bool {
vec::any(slice, |x| f(x))
//! Support code for serialization.
+#[allow(deprecated_mode)];
+
/*
Core serialization interfaces.
*/
-trait Serializer {
+pub trait Serializer {
// Primitive types:
fn emit_nil();
fn emit_uint(v: uint);
fn emit_tup_elt(idx: uint, f: fn());
}
-trait Deserializer {
+pub trait Deserializer {
// Primitive types:
fn read_nil() -> ();
//
// In some cases, these should eventually be coded as traits.
-fn emit_from_vec<S: Serializer, T>(&&s: S, &&v: ~[T], f: fn(&&x: T)) {
+pub fn emit_from_vec<S: Serializer, T>(&&s: S, &&v: ~[T], f: fn(&&x: T)) {
do s.emit_vec(vec::len(v)) {
for vec::eachi(v) |i,e| {
do s.emit_vec_elt(i) {
}
}
-fn read_to_vec<D: Deserializer, T: Copy>(&&d: D, f: fn() -> T) -> ~[T] {
+pub fn read_to_vec<D: Deserializer, T: Copy>(&&d: D, f: fn() -> T) -> ~[T] {
do d.read_vec |len| {
do vec::from_fn(len) |i| {
d.read_vec_elt(i, || f())
}
}
-trait SerializerHelpers {
+pub trait SerializerHelpers {
fn emit_from_vec<T>(&&v: ~[T], f: fn(&&x: T));
}
}
}
-trait DeserializerHelpers {
+pub trait DeserializerHelpers {
fn read_to_vec<T: Copy>(f: fn() -> T) -> ~[T];
}
}
}
-fn serialize_uint<S: Serializer>(&&s: S, v: uint) {
+pub fn serialize_uint<S: Serializer>(&&s: S, v: uint) {
s.emit_uint(v);
}
-fn deserialize_uint<D: Deserializer>(&&d: D) -> uint {
+pub fn deserialize_uint<D: Deserializer>(&&d: D) -> uint {
d.read_uint()
}
-fn serialize_u8<S: Serializer>(&&s: S, v: u8) {
+pub fn serialize_u8<S: Serializer>(&&s: S, v: u8) {
s.emit_u8(v);
}
-fn deserialize_u8<D: Deserializer>(&&d: D) -> u8 {
+pub fn deserialize_u8<D: Deserializer>(&&d: D) -> u8 {
d.read_u8()
}
-fn serialize_u16<S: Serializer>(&&s: S, v: u16) {
+pub fn serialize_u16<S: Serializer>(&&s: S, v: u16) {
s.emit_u16(v);
}
-fn deserialize_u16<D: Deserializer>(&&d: D) -> u16 {
+pub fn deserialize_u16<D: Deserializer>(&&d: D) -> u16 {
d.read_u16()
}
-fn serialize_u32<S: Serializer>(&&s: S, v: u32) {
+pub fn serialize_u32<S: Serializer>(&&s: S, v: u32) {
s.emit_u32(v);
}
-fn deserialize_u32<D: Deserializer>(&&d: D) -> u32 {
+pub fn deserialize_u32<D: Deserializer>(&&d: D) -> u32 {
d.read_u32()
}
-fn serialize_u64<S: Serializer>(&&s: S, v: u64) {
+pub fn serialize_u64<S: Serializer>(&&s: S, v: u64) {
s.emit_u64(v);
}
-fn deserialize_u64<D: Deserializer>(&&d: D) -> u64 {
+pub fn deserialize_u64<D: Deserializer>(&&d: D) -> u64 {
d.read_u64()
}
-fn serialize_int<S: Serializer>(&&s: S, v: int) {
+pub fn serialize_int<S: Serializer>(&&s: S, v: int) {
s.emit_int(v);
}
-fn deserialize_int<D: Deserializer>(&&d: D) -> int {
+pub fn deserialize_int<D: Deserializer>(&&d: D) -> int {
d.read_int()
}
-fn serialize_i8<S: Serializer>(&&s: S, v: i8) {
+pub fn serialize_i8<S: Serializer>(&&s: S, v: i8) {
s.emit_i8(v);
}
-fn deserialize_i8<D: Deserializer>(&&d: D) -> i8 {
+pub fn deserialize_i8<D: Deserializer>(&&d: D) -> i8 {
d.read_i8()
}
-fn serialize_i16<S: Serializer>(&&s: S, v: i16) {
+pub fn serialize_i16<S: Serializer>(&&s: S, v: i16) {
s.emit_i16(v);
}
-fn deserialize_i16<D: Deserializer>(&&d: D) -> i16 {
+pub fn deserialize_i16<D: Deserializer>(&&d: D) -> i16 {
d.read_i16()
}
-fn serialize_i32<S: Serializer>(&&s: S, v: i32) {
+pub fn serialize_i32<S: Serializer>(&&s: S, v: i32) {
s.emit_i32(v);
}
-fn deserialize_i32<D: Deserializer>(&&d: D) -> i32 {
+pub fn deserialize_i32<D: Deserializer>(&&d: D) -> i32 {
d.read_i32()
}
-fn serialize_i64<S: Serializer>(&&s: S, v: i64) {
+pub fn serialize_i64<S: Serializer>(&&s: S, v: i64) {
s.emit_i64(v);
}
-fn deserialize_i64<D: Deserializer>(&&d: D) -> i64 {
+pub fn deserialize_i64<D: Deserializer>(&&d: D) -> i64 {
d.read_i64()
}
-fn serialize_str<S: Serializer>(&&s: S, v: &str) {
+pub fn serialize_str<S: Serializer>(&&s: S, v: &str) {
s.emit_str(v);
}
-fn deserialize_str<D: Deserializer>(&&d: D) -> ~str {
+pub fn deserialize_str<D: Deserializer>(&&d: D) -> ~str {
d.read_str()
}
-fn serialize_float<S: Serializer>(&&s: S, v: float) {
+pub fn serialize_float<S: Serializer>(&&s: S, v: float) {
s.emit_float(v);
}
-fn deserialize_float<D: Deserializer>(&&d: D) -> float {
+pub fn deserialize_float<D: Deserializer>(&&d: D) -> float {
d.read_float()
}
-fn serialize_f32<S: Serializer>(&&s: S, v: f32) {
+pub fn serialize_f32<S: Serializer>(&&s: S, v: f32) {
s.emit_f32(v);
}
-fn deserialize_f32<D: Deserializer>(&&d: D) -> f32 {
+pub fn deserialize_f32<D: Deserializer>(&&d: D) -> f32 {
d.read_f32()
}
-fn serialize_f64<S: Serializer>(&&s: S, v: f64) {
+pub fn serialize_f64<S: Serializer>(&&s: S, v: f64) {
s.emit_f64(v);
}
-fn deserialize_f64<D: Deserializer>(&&d: D) -> f64 {
+pub fn deserialize_f64<D: Deserializer>(&&d: D) -> f64 {
d.read_f64()
}
-fn serialize_bool<S: Serializer>(&&s: S, v: bool) {
+pub fn serialize_bool<S: Serializer>(&&s: S, v: bool) {
s.emit_bool(v);
}
-fn deserialize_bool<D: Deserializer>(&&d: D) -> bool {
+pub fn deserialize_bool<D: Deserializer>(&&d: D) -> bool {
d.read_bool()
}
-fn serialize_Option<S: Serializer,T>(&&s: S, &&v: Option<T>, st: fn(&&x: T)) {
+pub fn serialize_Option<S: Serializer,T>(&&s: S, &&v: Option<T>,
+ st: fn(&&x: T)) {
do s.emit_enum(~"option") {
match v {
None => do s.emit_enum_variant(~"none", 0u, 0u) {
}
}
-fn deserialize_Option<D: Deserializer,T: Copy>(&&d: D, st: fn() -> T)
+pub fn deserialize_Option<D: Deserializer,T: Copy>(&&d: D, st: fn() -> T)
-> Option<T> {
do d.read_enum(~"option") {
do d.read_enum_variant |i| {
* A simple map based on a vector for small integer keys. Space requirements
* are O(highest integer key).
*/
-// tjc: forbid deprecated modes again after snap
+#[forbid(deprecated_mode)];
use core::option;
use core::option::{Some, None};
pure fn find(key: uint) -> Option<V> { find(self, key) }
fn rehash() { fail }
- pure fn each(it: fn(key: uint, +value: V) -> bool) {
+ pure fn each(it: fn(key: uint, value: V) -> bool) {
self.each_ref(|k, v| it(*k, *v))
}
pure fn each_key(it: fn(key: uint) -> bool) {
}
impl<V: Copy> SmallIntMap<V>: ops::Index<uint, V> {
- pure fn index(+key: uint) -> V {
+ pure fn index(key: uint) -> V {
unsafe {
get(self, key)
}
#[no_core];
-#[legacy_exports];
-
#[allow(vecs_implicitly_copyable)];
#[deny(non_camel_case_types)];
+// XXX this is set to allow because there are two methods in serialization
+// that can't be silenced otherwise. Most every module is set to forbid
+#[allow(deprecated_mode)];
#[forbid(deprecated_pattern)];
extern mod core(vers = "0.4");
use core::*;
-export net, net_tcp, net_ip, net_url;
-export uv, uv_ll, uv_iotask, uv_global_loop;
-export c_vec, timer;
-export sync, arc, comm;
-export bitv, deque, fun_treemap, list, map;
-export smallintmap, sort, treemap;
-export rope, arena, par;
-export ebml, ebml2;
-export dbg, getopts, json, rand, sha1, term, time;
-export prettyprint, prettyprint2;
-export test, tempfile, serialization, serialization2;
-export cmp;
-export base64;
-export cell;
-
// General io and system-services modules
-mod net;
-mod net_ip;
-mod net_tcp;
-mod net_url;
+pub mod net;
+pub mod net_ip;
+pub mod net_tcp;
+pub mod net_url;
// libuv modules
-mod uv;
-mod uv_ll;
-mod uv_iotask;
-mod uv_global_loop;
+pub mod uv;
+pub mod uv_ll;
+pub mod uv_iotask;
+pub mod uv_global_loop;
// Utility modules
-mod c_vec;
-mod timer;
-mod cell;
+pub mod c_vec;
+pub mod timer;
+pub mod cell;
// Concurrency
-mod sync;
-mod arc;
-mod comm;
+pub mod sync;
+pub mod arc;
+pub mod comm;
// Collections
-mod bitv;
-mod deque;
-mod fun_treemap;
-mod list;
-mod map;
-mod rope;
-mod smallintmap;
-mod sort;
-mod treemap;
+pub mod bitv;
+pub mod deque;
+pub mod fun_treemap;
+pub mod list;
+pub mod map;
+pub mod rope;
+pub mod smallintmap;
+pub mod sort;
+pub mod treemap;
// And ... other stuff
-mod ebml;
-mod ebml2;
-mod dbg;
-mod getopts;
-mod json;
-mod sha1;
-mod md4;
-mod tempfile;
-mod term;
-mod time;
-mod prettyprint;
-mod prettyprint2;
-mod arena;
-mod par;
-mod cmp;
-mod base64;
+pub mod ebml;
+pub mod ebml2;
+pub mod dbg;
+pub mod getopts;
+pub mod json;
+pub mod sha1;
+pub mod md4;
+pub mod tempfile;
+pub mod term;
+pub mod time;
+pub mod prettyprint;
+pub mod prettyprint2;
+pub mod arena;
+pub mod par;
+pub mod cmp;
+pub mod base64;
#[cfg(unicode)]
mod unicode;
// Compiler support modules
-mod test;
-#[legacy_exports]
-mod serialization;
-mod serialization2;
+pub mod test;
+pub mod serialization;
+pub mod serialization2;
// Local Variables:
// mode: rust;
// NB: transitionary, de-mode-ing.
-// tjc: forbid deprecated modes again after snap
+#[forbid(deprecated_mode)];
/**
* The concurrency primitives you know and love.
*
let m = ~Mutex();
let m2 = ~m.clone();
let mut sharedstate = ~0;
- let ptr = ptr::p2::addr_of(&(*sharedstate));
+ let ptr = ptr::addr_of(&(*sharedstate));
do task::spawn {
let sharedstate: &mut int =
unsafe { cast::reinterpret_cast(&ptr) };
let (c,p) = pipes::stream();
let x2 = ~x.clone();
let mut sharedstate = ~0;
- let ptr = ptr::p2::addr_of(&(*sharedstate));
+ let ptr = ptr::addr_of(&(*sharedstate));
do task::spawn {
let sharedstate: &mut int =
unsafe { cast::reinterpret_cast(&ptr) };
// simplest interface possible for representing and running tests
// while providing a base that other test frameworks may build off of.
-#[warn(deprecated_mode)];
+#[forbid(deprecated_mode)];
use core::cmp::Eq;
use either::Either;
let mut done_idx = 0;
let p = core::comm::Port();
- let ch = core::comm::Chan(p);
+ let ch = core::comm::Chan(&p);
while done_idx < total {
while wait_idx < concurrency && run_idx < total {
should_fail: false
};
let p = core::comm::Port();
- let ch = core::comm::Chan(p);
+ let ch = core::comm::Chan(&p);
run_test(desc, ch);
let (_, res) = core::comm::recv(p);
assert res != TrOk;
should_fail: false
};
let p = core::comm::Port();
- let ch = core::comm::Chan(p);
+ let ch = core::comm::Chan(&p);
run_test(desc, ch);
let (_, res) = core::comm::recv(p);
assert res == TrIgnored;
should_fail: true
};
let p = core::comm::Port();
- let ch = core::comm::Chan(p);
+ let ch = core::comm::Chan(&p);
run_test(desc, ch);
let (_, res) = core::comm::recv(p);
assert res == TrOk;
should_fail: true
};
let p = core::comm::Port();
- let ch = core::comm::Chan(p);
+ let ch = core::comm::Chan(&p);
run_test(desc, ch);
let (_, res) = core::comm::recv(p);
assert res == TrFailed;
-// tjc: forbid deprecated modes again after snap
+#[forbid(deprecated_mode)];
use core::cmp::Eq;
use libc::{c_char, c_int, c_long, size_t, time_t};
#[abi = "cdecl"]
extern mod rustrt {
- #[legacy_exports];
- fn get_time(&sec: i64, &nsec: i32);
- fn precise_time_ns(&ns: u64);
+ #[legacy_exports]
+ fn get_time(sec: &mut i64, nsec: &mut i32);
+
+ fn precise_time_ns(ns: &mut u64);
fn rust_tzset();
// FIXME: The i64 values can be passed by-val when #2064 is fixed.
fn rust_gmtime(&&sec: i64, &&nsec: i32, &&result: Tm);
fn rust_localtime(&&sec: i64, &&nsec: i32, &&result: Tm);
- fn rust_timegm(&&tm: Tm, &sec: i64);
- fn rust_mktime(&&tm: Tm, &sec: i64);
+ fn rust_timegm(&&tm: Tm, sec: &mut i64);
+ fn rust_mktime(&&tm: Tm, sec: &mut i64);
}
/// A record specifying a time value in seconds and nanoseconds.
pub fn get_time() -> Timespec {
let mut sec = 0i64;
let mut nsec = 0i32;
- rustrt::get_time(sec, nsec);
+ rustrt::get_time(&mut sec, &mut nsec);
return {sec: sec, nsec: nsec};
}
+
/**
* Returns the current value of a high-resolution performance counter
* in nanoseconds since an unspecified epoch.
*/
pub fn precise_time_ns() -> u64 {
let mut ns = 0u64;
- rustrt::precise_time_ns(ns);
+ rustrt::precise_time_ns(&mut ns);
ns
}
+
/**
* Returns the current value of a high-resolution performance counter
* in seconds since an unspecified epoch.
fn to_timespec() -> Timespec {
let mut sec = 0i64;
if self.tm_gmtoff == 0_i32 {
- rustrt::rust_timegm(self, sec);
+ rustrt::rust_timegm(self, &mut sec);
} else {
- rustrt::rust_mktime(self, sec);
+ rustrt::rust_mktime(self, &mut sec);
}
{ sec: sec, nsec: self.tm_nsec }
}
//! Utilities that leverage libuv's `uv_timer_*` API
-// tjc: forbid deprecated modes again after snap
+#[forbid(deprecated_mode)];
use uv = uv;
use uv::iotask;
msecs: uint, ch: comm::Chan<T>, val: T) {
unsafe {
let timer_done_po = core::comm::Port::<()>();
- let timer_done_ch = core::comm::Chan(timer_done_po);
+ let timer_done_ch = core::comm::Chan(&timer_done_po);
let timer_done_ch_ptr = ptr::addr_of(&timer_done_ch);
let timer = uv::ll::timer_t();
let timer_ptr = ptr::addr_of(&timer);
*/
pub fn sleep(iotask: IoTask, msecs: uint) {
let exit_po = core::comm::Port::<()>();
- let exit_ch = core::comm::Chan(exit_po);
+ let exit_ch = core::comm::Chan(&exit_po);
delayed_send(iotask, msecs, exit_ch, ());
core::comm::recv(exit_po);
}
msecs: uint,
wait_po: comm::Port<T>) -> Option<T> {
let timeout_po = comm::Port::<()>();
- let timeout_ch = comm::Chan(timeout_po);
+ let timeout_ch = comm::Chan(&timeout_po);
delayed_send(iotask, msecs, timeout_ch, ());
// FIXME: This could be written clearer (#2618)
either::either(
#[test]
fn test_gl_timer_sleep_stress2() {
let po = core::comm::Port();
- let ch = core::comm::Chan(po);
+ let ch = core::comm::Chan(&po);
let hl_loop = uv::global_loop::get();
let repeat = 20u;
for iter::repeat(times as uint) {
let expected = rand::Rng().gen_str(16u);
let test_po = core::comm::Port::<~str>();
- let test_ch = core::comm::Chan(test_po);
+ let test_ch = core::comm::Chan(&test_po);
do task::spawn() {
delayed_send(hl_loop, 50u, test_ch, expected);
* very naive algorithm, but it will probably be updated to be a
* red-black tree or something else.
*/
-#[warn(deprecated_mode)];
+#[forbid(deprecated_mode)];
use core::cmp::{Eq, Ord};
use core::option::{Some, None};
pub fn TreeMap<K, V>() -> TreeMap<K, V> { @mut None }
/// Insert a value into the map
-pub fn insert<K: Copy Eq Ord, V: Copy>(m: &mut TreeEdge<K, V>, +k: K, +v: V) {
+pub fn insert<K: Copy Eq Ord, V: Copy>(m: &mut TreeEdge<K, V>, k: K, v: V) {
match copy *m {
None => {
*m = Some(@TreeNode({key: k,
}
/// Find a value based on the key
-pub fn find<K: Copy Eq Ord, V: Copy>(m: &const TreeEdge<K, V>, +k: K)
+pub fn find<K: Copy Eq Ord, V: Copy>(m: &const TreeEdge<K, V>, k: K)
-> Option<V> {
match copy *m {
None => None,
insert(m, 1, ());
let n = @mut 0;
- fn t(n: @mut int, +k: int, +_v: ()) {
+ fn t(n: @mut int, k: int, _v: ()) {
assert (*n == k); *n += 1;
}
traverse(m, |x,y| t(n, *x, *y));
fn impl_uv_hl_simple_timer(iotask: IoTask) unsafe {
let exit_po = core::comm::Port::<bool>();
- let exit_ch = core::comm::Chan(exit_po);
- let exit_ch_ptr = ptr::p2::addr_of(&exit_ch);
+ let exit_ch = core::comm::Chan(&exit_po);
+ let exit_ch_ptr = ptr::addr_of(&exit_ch);
log(debug, fmt!("EXIT_CH_PTR newly created exit_ch_ptr: %?",
exit_ch_ptr));
let timer_handle = ll::timer_t();
- let timer_ptr = ptr::p2::addr_of(&timer_handle);
+ let timer_ptr = ptr::addr_of(&timer_handle);
do iotask::interact(iotask) |loop_ptr| unsafe {
log(debug, ~"user code inside interact loop!!!");
let init_status = ll::timer_init(loop_ptr, timer_ptr);
fn test_gl_uv_global_loop_high_level_global_timer() unsafe {
let hl_loop = get_gl();
let exit_po = comm::Port::<()>();
- let exit_ch = comm::Chan(exit_po);
+ let exit_ch = comm::Chan(&exit_po);
task::spawn_sched(task::ManualThreads(1u), || {
impl_uv_hl_simple_timer(hl_loop);
core::comm::send(exit_ch, ());
fn test_stress_gl_uv_global_loop_high_level_global_timer() unsafe {
let hl_loop = get_gl();
let exit_po = core::comm::Port::<()>();
- let exit_ch = core::comm::Chan(exit_po);
+ let exit_ch = core::comm::Chan(&exit_po);
let cycles = 5000u;
for iter::repeat(cycles) {
task::spawn_sched(task::ManualThreads(1u), || {
* The I/O task runs in its own single-threaded scheduler. By using the
* `interact` function you can execute code in a uv callback.
*/
-
-// tjc: forbid deprecated modes again after a snapshot
+#[forbid(deprecated_mode)];
use libc::c_void;
-use ptr::p2::addr_of;
+use ptr::addr_of;
use comm = core::comm;
use comm::{Port, Chan, listen};
use task::TaskBuilder;
* via ports/chans.
*/
pub unsafe fn interact(iotask: IoTask,
- +cb: fn~(*c_void)) {
+ cb: fn~(*c_void)) {
send_msg(iotask, Interaction(move cb));
}
};
fn send_msg(iotask: IoTask,
- +msg: IoTaskMsg) unsafe {
+ msg: IoTaskMsg) unsafe {
iotask.op_chan.send(move msg);
ll::async_send(iotask.async_handle);
}
let async_handle = ll::async_t();
let ah_ptr = ptr::addr_of(&async_handle);
let exit_po = core::comm::Port::<()>();
- let exit_ch = core::comm::Chan(exit_po);
+ let exit_ch = core::comm::Chan(&exit_po);
let ah_data = {
iotask: iotask,
exit_ch: exit_ch
// high_level_loop
unsafe fn spawn_test_loop(exit_ch: comm::Chan<()>) -> IoTask {
let iotask_port = comm::Port::<IoTask>();
- let iotask_ch = comm::Chan(iotask_port);
+ let iotask_ch = comm::Chan(&iotask_port);
do task::spawn_sched(task::ManualThreads(1u)) {
run_loop(iotask_ch);
exit_ch.send(());
#[test]
fn test_uv_iotask_async() unsafe {
let exit_po = core::comm::Port::<()>();
- let exit_ch = core::comm::Chan(exit_po);
+ let exit_ch = core::comm::Chan(&exit_po);
let iotask = spawn_test_loop(exit_ch);
// using this handle to manage the lifetime of the high_level_loop,
// lives until, at least, all of the impl_uv_hl_async() runs have been
// called, at least.
let work_exit_po = core::comm::Port::<()>();
- let work_exit_ch = core::comm::Chan(work_exit_po);
+ let work_exit_ch = core::comm::Chan(&work_exit_po);
for iter::repeat(7u) {
do task::spawn_sched(task::ManualThreads(1u)) {
impl_uv_iotask_async(iotask);
let kill_server_msg = ~"does a dog have buddha nature?";
let server_resp_msg = ~"mu!";
let client_port = core::comm::Port::<~str>();
- let client_chan = core::comm::Chan::<~str>(client_port);
+ let client_chan = core::comm::Chan::<~str>(&client_port);
let server_port = core::comm::Port::<~str>();
- let server_chan = core::comm::Chan::<~str>(server_port);
+ let server_chan = core::comm::Chan::<~str>(&server_port);
let continue_port = core::comm::Port::<bool>();
- let continue_chan = core::comm::Chan::<bool>(continue_port);
+ let continue_chan = core::comm::Chan::<bool>(&continue_port);
let continue_chan_ptr = ptr::addr_of(&continue_chan);
do task::spawn_sched(task::ManualThreads(1)) {
// "resolved" mode: the real modes.
#[auto_serialize]
-enum rmode { by_ref, by_val, by_mutbl_ref, by_move, by_copy }
+enum rmode { by_ref, by_val, by_move, by_copy }
impl rmode : to_bytes::IterBytes {
pure fn iter_bytes(+lsb0: bool, f: to_bytes::Cb) {
fn ty_param(id: ast::ident, +bounds: ~[ast::ty_param_bound])
-> ast::ty_param;
fn arg(name: ident, ty: @ast::ty) -> ast::arg;
- fn arg_mode(name: ident, ty: @ast::ty, mode: ast::rmode) -> ast::arg;
fn expr_block(e: @ast::expr) -> ast::blk;
fn fn_decl(+inputs: ~[ast::arg], output: @ast::ty) -> ast::fn_decl;
fn item(name: ident, span: span, +node: ast::item_) -> @ast::item;
id: self.next_id()}
}
- fn arg_mode(name: ident, ty: @ast::ty, mode: ast::rmode) -> ast::arg {
- {mode: ast::expl(mode),
- ty: ty,
- ident: name,
- id: self.next_id()}
- }
-
fn block(+stmts: ~[@ast::stmt], e: @ast::expr) -> ast::blk {
let blk = {view_items: ~[],
stmts: stmts,
let arg_names = tys.mapi(|i, _ty| cx.ident_of(~"x_"+i.to_str()));
let args_ast = (arg_names, tys).map(
- |n, t| cx.arg_mode(*n, *t, ast::by_copy)
+ |n, t| cx.arg(*n, *t)
);
let pipe_ty = cx.ty_path_ast_builder(
path(~[this.data_name()], span)
.add_tys(cx.ty_vars(this.ty_params)));
let args_ast = vec::append(
- ~[cx.arg_mode(cx.ident_of(~"pipe"),
- pipe_ty,
- ast::by_copy)],
+ ~[cx.arg(cx.ident_of(~"pipe"),
+ pipe_ty)],
args_ast);
let mut body = ~"{\n";
let arg_names = tys.mapi(|i, _ty| (~"x_" + i.to_str()));
let args_ast = (arg_names, tys).map(
- |n, t| cx.arg_mode(cx.ident_of(*n), *t, ast::by_copy)
+ |n, t| cx.arg(cx.ident_of(*n), *t)
);
let args_ast = vec::append(
- ~[cx.arg_mode(cx.ident_of(~"pipe"),
+ ~[cx.arg(cx.ident_of(~"pipe"),
cx.ty_path_ast_builder(
path(~[this.data_name()], span)
- .add_tys(cx.ty_vars(this.ty_params))),
- ast::by_copy)],
+ .add_tys(cx.ty_vars(this.ty_params))))],
args_ast);
let message_args = if arg_names.len() == 0 {
}
}
-fn push_blank_line_comment(rdr: string_reader, &comments: ~[cmnt]) {
+fn push_blank_line_comment(rdr: string_reader, comments: &mut ~[cmnt]) {
debug!(">>> blank-line comment");
let v: ~[~str] = ~[];
comments.push({style: blank_line, lines: v, pos: rdr.chpos});
}
fn consume_whitespace_counting_blank_lines(rdr: string_reader,
- &comments: ~[cmnt]) {
+ comments: &mut ~[cmnt]) {
while is_whitespace(rdr.curr) && !is_eof(rdr) {
if rdr.col == 0u && rdr.curr == '\n' {
push_blank_line_comment(rdr, comments);
fn read_shebang_comment(rdr: string_reader, code_to_the_left: bool,
- &comments: ~[cmnt]) {
+ comments: &mut ~[cmnt]) {
debug!(">>> shebang comment");
let p = rdr.chpos;
debug!("<<< shebang comment");
}
fn read_line_comments(rdr: string_reader, code_to_the_left: bool,
- &comments: ~[cmnt]) {
+ comments: &mut ~[cmnt]) {
debug!(">>> line comments");
let p = rdr.chpos;
let mut lines: ~[~str] = ~[];
return true;
}
-fn trim_whitespace_prefix_and_push_line(&lines: ~[~str],
- s: ~str, col: uint) unsafe {
+fn trim_whitespace_prefix_and_push_line(lines: &mut ~[~str],
+ s: ~str, col: uint) {
let mut s1;
let len = str::len(s);
if all_whitespace(s, 0u, uint::min(len, col)) {
}
fn read_block_comment(rdr: string_reader, code_to_the_left: bool,
- &comments: ~[cmnt]) {
+ comments: &mut ~[cmnt]) {
debug!(">>> block comment");
let p = rdr.chpos;
let mut lines: ~[~str] = ~[];
debug!("=== block comment level %d", level);
if is_eof(rdr) {(rdr as reader).fatal(~"unterminated block comment");}
if rdr.curr == '\n' {
- trim_whitespace_prefix_and_push_line(lines, curr_line, col);
+ trim_whitespace_prefix_and_push_line(&mut lines, curr_line, col);
curr_line = ~"";
bump(rdr);
} else {
}
}
}
- if str::len(curr_line) != 0u {
- trim_whitespace_prefix_and_push_line(lines, curr_line, col);
+ if str::len(curr_line) != 0 {
+ trim_whitespace_prefix_and_push_line(&mut lines, curr_line, col);
}
let mut style = if code_to_the_left { trailing } else { isolated };
consume_non_eol_whitespace(rdr);
}
fn consume_comment(rdr: string_reader, code_to_the_left: bool,
- &comments: ~[cmnt]) {
+ comments: &mut ~[cmnt]) {
debug!(">>> consume comment");
if rdr.curr == '/' && nextch(rdr) == '/' {
read_line_comments(rdr, code_to_the_left, comments);
consume_non_eol_whitespace(rdr);
if rdr.curr == '\n' {
code_to_the_left = false;
- consume_whitespace_counting_blank_lines(rdr, comments);
+ consume_whitespace_counting_blank_lines(rdr, &mut comments);
}
while peeking_at_comment(rdr) {
- consume_comment(rdr, code_to_the_left, comments);
- consume_whitespace_counting_blank_lines(rdr, comments);
+ consume_comment(rdr, code_to_the_left, &mut comments);
+ consume_whitespace_counting_blank_lines(rdr, &mut comments);
}
break;
}
fn eval_crate_directives(cx: ctx,
cdirs: ~[@ast::crate_directive],
prefix: &Path,
- &view_items: ~[@ast::view_item],
- &items: ~[@ast::item]) {
+ view_items: &mut~[@ast::view_item],
+ items: &mut~[@ast::item]) {
for cdirs.each |sub_cdir| {
eval_crate_directive(cx, *sub_cdir, prefix, view_items, items);
}
= parse_companion_mod(cx, prefix, suffix);
let mut view_items: ~[@ast::view_item] = ~[];
let mut items: ~[@ast::item] = ~[];
- eval_crate_directives(cx, cdirs, prefix, view_items, items);
+ eval_crate_directives(cx, cdirs, prefix, &mut view_items, &mut items);
return ({view_items: vec::append(view_items, cview_items),
items: vec::append(items, citems)},
cattrs);
}
fn eval_crate_directive(cx: ctx, cdir: @ast::crate_directive, prefix: &Path,
- &view_items: ~[@ast::view_item],
- &items: ~[@ast::item]) {
+ view_items: &mut ~[@ast::view_item],
+ items: &mut ~[@ast::item]) {
match cdir.node {
ast::cdir_src_mod(vis, id, attrs) => {
let file_path = Path(cdir_path_opt(
ObsoleteClassMethod,
ObsoleteClassTraits,
ObsoletePrivSection,
- ObsoleteModeInFnType
+ ObsoleteModeInFnType,
+ ObsoleteByMutRefMode
}
impl ObsoleteSyntax : cmp::Eq {
"to use a (deprecated) mode in a fn type, you should \
give the argument an explicit name (like `&&v: int`)"
),
+ ObsoleteByMutRefMode => (
+ "by-mutable-reference mode",
+ "Declare an argument of type &mut T instead"
+ ),
};
self.report(sp, kind, kind_str, desc);
ObsoleteLowerCaseKindBounds, ObsoleteLet,
ObsoleteFieldTerminator, ObsoleteStructCtor,
ObsoleteWith, ObsoleteClassMethod, ObsoleteClassTraits,
- ObsoleteModeInFnType
+ ObsoleteModeInFnType, ObsoleteByMutRefMode
};
use ast::{_mod, add, alt_check, alt_exhaustive, arg, arm, attribute,
bind_by_ref, bind_by_implicit_ref, bind_by_value, bind_by_move,
bitand, bitor, bitxor, blk, blk_check_mode, bound_const,
bound_copy, bound_send, bound_trait, bound_owned, box, by_copy,
- by_move, by_mutbl_ref, by_ref, by_val, capture_clause,
+ by_move, by_ref, by_val, capture_clause,
capture_item, cdir_dir_mod, cdir_src_mod, cdir_view_item,
class_immutable, class_mutable,
crate, crate_cfg, crate_directive, decl, decl_item, decl_local,
fn parse_arg_mode() -> mode {
if self.eat(token::BINOP(token::AND)) {
- expl(by_mutbl_ref)
+ self.obsolete(copy self.span,
+ ObsoleteByMutRefMode);
+ // Bogus mode, but doesn't matter since it's an error
+ expl(by_ref)
} else if self.eat(token::BINOP(token::MINUS)) {
expl(by_move)
} else if self.eat(token::ANDAND) {
return match self.token {
token::LPAREN | token::LBRACE | token::LBRACKET => {
- let ket = token::flip_delimiter(self.token);
+ // tjc: ??????
+ let ket = token::flip_delimiter(copy self.token);
tt_delim(vec::append(
~[parse_tt_tok(self, true)],
vec::append(
return match self.token {
token::LBRACE | token::LPAREN | token::LBRACKET => {
self.parse_matcher_subseq(name_idx, copy self.token,
- token::flip_delimiter(self.token))
+ // tjc: not sure why we need a copy
+ token::flip_delimiter(copy self.token))
}
_ => self.fatal(~"expected open delimiter")
}
}
/// what's the opposite delimiter?
-fn flip_delimiter(&t: token::token) -> token::token {
+fn flip_delimiter(t: token::token) -> token::token {
match t {
token::LPAREN => token::RPAREN,
token::LBRACE => token::RBRACE,
fn mode_to_str(m: ast::mode) -> ~str {
match m {
- ast::expl(ast::by_mutbl_ref) => ~"&",
ast::expl(ast::by_move) => ~"-",
ast::expl(ast::by_ref) => ~"&&",
ast::expl(ast::by_val) => ~"++",
-Subproject commit c51053bf71de475df6a91204acd9ad78f4747c38
+Subproject commit dc4cdbf052288794ac418f310e7f5cfa609f5902
}
};
-// A global that indicates whether Rust typestate claim statements should be
-// executed Generated code will read this variable directly (I think).
-// FIXME (#2670): This belongs somewhere else
-int check_claims = 0;
-
void* global_crate_map = NULL;
/**
update_log_settings(crate_map, env->logspec);
- // Maybe turn on typestate claim checking
- check_claims = env->check_claims;
-
rust_kernel *kernel = new rust_kernel(env);
// Create the main scheduler and the main task
#define RUST_MIN_STACK "RUST_MIN_STACK"
#define RUST_MAX_STACK "RUST_MAX_STACK"
#define RUST_LOG "RUST_LOG"
-#define CHECK_CLAIMS "CHECK_CLAIMS"
#define DETAILED_LEAKS "DETAILED_LEAKS"
#define RUST_SEED "RUST_SEED"
#define RUST_POISON_ON_FREE "RUST_POISON_ON_FREE"
env->min_stack_size = get_min_stk_size();
env->max_stack_size = get_max_stk_size();
env->logspec = copyenv(RUST_LOG);
- env->check_claims = getenv(CHECK_CLAIMS) != NULL;
env->detailed_leaks = getenv(DETAILED_LEAKS) != NULL;
env->rust_seed = copyenv(RUST_SEED);
env->poison_on_free = getenv(RUST_POISON_ON_FREE) != NULL;
size_t min_stack_size;
size_t max_stack_size;
char* logspec;
- bool check_claims;
bool detailed_leaks;
char* rust_seed;
bool poison_on_free;
#define FASTCALL
#endif
-/* Controls whether claims are turned into checks */
-/* Variable name must be kept consistent with trans.rs */
-extern "C" int check_claims;
-
#define CHECKED(call) \
{ \
int res = (call); \
-check_claims
debug_box
debug_fn
debug_opaque
use rustc::driver::session;
use rustc::middle::lint;
-fn version(argv0: ~str) {
+fn version(argv0: &str) {
let mut vers = ~"unknown version";
let env_vers = env!("CFG_VERSION");
- if str::len(env_vers) != 0u { vers = env_vers; }
+ if env_vers.len() != 0 { vers = env_vers; }
io::println(fmt!("%s %s", argv0, vers));
io::println(fmt!("host: %s", host_triple()));
}
-fn usage(argv0: ~str) {
+fn usage(argv0: &str) {
io::println(fmt!("Usage: %s [options] <input>\n", argv0) +
~"
Options:
let lint_dict = lint::get_lint_dict();
let mut max_key = 0;
for lint_dict.each_key |k| { max_key = uint::max(k.len(), max_key); }
- fn padded(max: uint, s: ~str) -> ~str {
+ fn padded(max: uint, s: &str) -> ~str {
str::from_bytes(vec::from_elem(max - s.len(), ' ' as u8)) + s
}
io::println(fmt!("\nAvailable lint checks:\n"));
}
}
-fn run_compiler(args: ~[~str], demitter: diagnostic::emitter) {
+fn run_compiler(args: &~[~str], demitter: diagnostic::emitter) {
// Don't display log spew by default. Can override with RUST_LOG.
logging::console_off();
- let mut args = args;
+ let mut args = *args;
let binary = args.shift();
- if vec::len(args) == 0u { usage(binary); return; }
+ if args.is_empty() { usage(binary); return; }
let matches =
match getopts::getopts(args, opts()) {
*/
fn monitor(+f: fn~(diagnostic::emitter)) {
let p = comm::Port();
- let ch = comm::Chan(p);
+ let ch = comm::Chan(&p);
match do task::try |move f| {
}
}
-fn main(args: ~[~str]) {
- do monitor |demitter| {
- run_compiler(args, demitter);
+fn main() {
+ let mut args = os::args();
+ do monitor |move args, demitter| {
+ run_compiler(&args, demitter);
}
}
}
fn mk_main(cx: test_ctxt) -> @ast::item {
- let str_pt = path_node(~[cx.sess.ident_of(~"str")]);
- let str_ty_inner = @{id: cx.sess.next_node_id(),
- node: ast::ty_path(str_pt, cx.sess.next_node_id()),
- span: dummy_sp()};
- let str_ty = @{id: cx.sess.next_node_id(),
- node: ast::ty_uniq({ty: str_ty_inner, mutbl: ast::m_imm}),
- span: dummy_sp()};
- let args_mt = {ty: str_ty, mutbl: ast::m_imm};
- let args_ty_inner = @{id: cx.sess.next_node_id(),
- node: ast::ty_vec(args_mt),
- span: dummy_sp()};
- let args_ty = {id: cx.sess.next_node_id(),
- node: ast::ty_uniq({ty: args_ty_inner, mutbl: ast::m_imm}),
- span: dummy_sp()};
-
-
- let args_arg: ast::arg =
- {mode: ast::expl(ast::by_val),
- ty: @args_ty,
- ident: cx.sess.ident_of(~"args"),
- id: cx.sess.next_node_id()};
-
let ret_ty = {id: cx.sess.next_node_id(),
node: ast::ty_nil,
span: dummy_sp()};
let decl: ast::fn_decl =
- {inputs: ~[args_arg],
+ {inputs: ~[],
output: @ret_ty,
cf: ast::return_val};
}
fn mk_test_main_call(cx: test_ctxt) -> @ast::expr {
-
- // Get the args passed to main so we can pass the to test_main
- let args_path = path_node(~[cx.sess.ident_of(~"args")]);
+ // Call os::args to generate the vector of test_descs
+ let args_path = path_node(~[
+ cx.sess.ident_of(~"os"),
+ cx.sess.ident_of(~"args")
+ ]);
let args_path_expr_: ast::expr_ = ast::expr_path(args_path);
{id: cx.sess.next_node_id(), callee_id: cx.sess.next_node_id(),
node: args_path_expr_, span: dummy_sp()};
+ let args_call_expr_ = ast::expr_call(@args_path_expr, ~[], false);
+
+ let args_call_expr: ast::expr =
+ {id: cx.sess.next_node_id(), callee_id: cx.sess.next_node_id(),
+ node: args_call_expr_, span: dummy_sp()};
+
// Call __test::test to generate the vector of test_descs
let test_path = path_node(~[cx.sess.ident_of(~"tests")]);
let test_main_call_expr_: ast::expr_ =
ast::expr_call(@test_main_path_expr,
- ~[@args_path_expr, @test_call_expr], false);
+ ~[@args_call_expr, @test_call_expr], false);
let test_main_call_expr: ast::expr =
{id: cx.sess.next_node_id(), callee_id: cx.sess.next_node_id(),
export def_to_str;
export encode_ctxt;
export write_type;
+export write_vstore;
export encode_def_id;
type abbrev_map = map::HashMap<ty::t, tyencode::ty_abbrev>;
type entry<T> = {val: T, pos: uint};
fn add_to_index(ecx: @encode_ctxt, ebml_w: ebml::Writer, path: &[ident],
- &index: ~[entry<~str>], name: ident) {
+ index: &mut ~[entry<~str>], name: ident) {
let mut full_path = ~[];
full_path.push_all(path);
full_path.push(name);
tyencode::enc_ty(ebml_w.writer, ty_str_ctxt, typ);
}
+fn write_vstore(ecx: @encode_ctxt, ebml_w: ebml::Writer, vstore: ty::vstore) {
+ let ty_str_ctxt =
+ @{diag: ecx.diag,
+ ds: def_to_str,
+ tcx: ecx.tcx,
+ reachable: |a| reachable(ecx, a),
+ abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)};
+ tyencode::enc_vstore(ebml_w.writer, ty_str_ctxt, vstore);
+}
+
fn encode_type(ecx: @encode_ctxt, ebml_w: ebml::Writer, typ: ty::t) {
ebml_w.start_tag(tag_items_data_item_type);
write_type(ecx, ebml_w, typ);
fn parse_mode(st: @pstate) -> ast::mode {
let m = ast::expl(match next(st) {
- '&' => ast::by_mutbl_ref,
'-' => ast::by_move,
'+' => ast::by_copy,
'=' => ast::by_ref,
export enc_bounds;
export enc_mode;
export enc_arg;
+export enc_vstore;
type ctxt = {
diag: span_handler,
fn enc_mode(w: io::Writer, cx: @ctxt, m: mode) {
match ty::resolved_mode(cx.tcx, m) {
- by_mutbl_ref => w.write_char('&'),
by_move => w.write_char('-'),
by_copy => w.write_char('+'),
by_ref => w.write_char('='),
typeck::method_param(mp) => {
typeck::method_param({trait_id:mp.trait_id.tr(xcx),.. mp})
}
- typeck::method_trait(did, m) => {
- typeck::method_trait(did.tr(xcx), m)
+ typeck::method_trait(did, m, vstore) => {
+ typeck::method_trait(did.tr(xcx), m, vstore)
+ }
+ typeck::method_self(did, m) => {
+ typeck::method_self(did.tr(xcx), m)
}
}
}
trait ebml_writer_helpers {
fn emit_arg(ecx: @e::encode_ctxt, arg: ty::arg);
fn emit_ty(ecx: @e::encode_ctxt, ty: ty::t);
+ fn emit_vstore(ecx: @e::encode_ctxt, vstore: ty::vstore);
fn emit_tys(ecx: @e::encode_ctxt, tys: ~[ty::t]);
fn emit_bounds(ecx: @e::encode_ctxt, bs: ty::param_bounds);
fn emit_tpbt(ecx: @e::encode_ctxt, tpbt: ty::ty_param_bounds_and_ty);
}
}
+ fn emit_vstore(ecx: @e::encode_ctxt, vstore: ty::vstore) {
+ do self.emit_opaque {
+ e::write_vstore(ecx, self, vstore)
+ }
+ }
+
fn emit_arg(ecx: @e::encode_ctxt, arg: ty::arg) {
do self.emit_opaque {
tyencode::enc_arg(self.writer, ecx.ty_str_ctxt(), arg);
pure_map: HashMap<ast::node_id, bckerr>
};
-fn save_and_restore<T:Copy,U>(&save_and_restore_t: T, f: fn() -> U) -> U {
- let old_save_and_restore_t = save_and_restore_t;
+fn save_and_restore<T:Copy,U>(save_and_restore_t: &mut T, f: fn() -> U) -> U {
+ let old_save_and_restore_t = *save_and_restore_t;
let u <- f();
- save_and_restore_t = old_save_and_restore_t;
+ *save_and_restore_t = old_save_and_restore_t;
move u
}
ast::by_move => {
self.check_move_out(*arg);
}
- ast::by_mutbl_ref | ast::by_ref |
+ ast::by_ref |
ast::by_copy | ast::by_val => {
}
}
visitor: visit::vt<check_loan_ctxt>) {
debug!("purity on entry=%?", copy self.declared_purity);
- do save_and_restore(self.in_ctor) {
- do save_and_restore(self.declared_purity) {
- do save_and_restore(self.fn_args) {
+ do save_and_restore(&mut(self.in_ctor)) {
+ do save_and_restore(&mut(self.declared_purity)) {
+ do save_and_restore(&mut(self.fn_args)) {
let is_stack_closure = self.is_stack_closure(id);
let fty = ty::node_id_to_type(self.tcx(), id);
self.declared_purity = ty::determine_inherited_purity(
fn check_loans_in_block(blk: ast::blk,
&&self: check_loan_ctxt,
vt: visit::vt<check_loan_ctxt>) {
- do save_and_restore(self.declared_purity) {
+ do save_and_restore(&mut(self.declared_purity)) {
self.check_for_conflicting_loans(blk.node.id);
match blk.node.rules {
let scope_r = ty::re_scope(ex.id);
for vec::each2(args, arg_tys) |arg, arg_ty| {
match ty::resolved_mode(self.tcx(), arg_ty.mode) {
- ast::by_mutbl_ref => {
- let arg_cmt = self.bccx.cat_expr(*arg);
- self.guarantee_valid(arg_cmt, m_mutbl, scope_r);
- }
ast::by_ref => {
let arg_cmt = self.bccx.cat_expr(*arg);
self.guarantee_valid(arg_cmt, m_imm, scope_r);
for ty::ty_fn_args(ty::expr_ty(cx.tcx, f)).each |arg_t| {
match ty::arg_mode(cx.tcx, *arg_t) {
by_copy => maybe_copy(cx, args[i], None),
- by_ref | by_val | by_mutbl_ref | by_move => ()
+ by_ref | by_val | by_move => ()
}
i += 1u;
}
Some(ref mme) => {
match ty::arg_mode(cx.tcx, mme.self_arg) {
by_copy => maybe_copy(cx, lhs, None),
- by_ref | by_val | by_mutbl_ref | by_move => ()
+ by_ref | by_val | by_move => ()
}
}
_ => ()
cx.tcx.sess.span_err(sp, msg);
}
}
- def_arg(_, mode) => {
- match ty::resolved_mode(cx.tcx, mode) {
- by_ref | by_val | by_move | by_copy => { /* ok */ }
- by_mutbl_ref => {
- cx.tcx.sess.span_err(sp, msg);
- }
- }
- }
+ def_arg(*) => { /* ok */ }
def_upvar(_, def1, _, _) => {
check_imm_free_var(cx, *def1, sp);
}
(*v).push(id);
}
- Arg(_, _, by_ref) | Arg(_, _, by_mutbl_ref) |
+ Arg(_, _, by_ref) |
Arg(_, _, by_val) | Self | Field(_) | ImplicitRet |
Local(LocalInfo {kind: FromMatch(bind_by_implicit_ref), _}) => {
debug!("--but it is not owned");
let mut changed = false;
do self.indices2(ln, succ_ln) |idx, succ_idx| {
changed |= copy_if_invalid(copy self.users[succ_idx].reader,
- self.users[idx].reader);
+ &mut self.users[idx].reader);
changed |= copy_if_invalid(copy self.users[succ_idx].writer,
- self.users[idx].writer);
+ &mut self.users[idx].writer);
if self.users[succ_idx].used && !self.users[idx].used {
self.users[idx].used = true;
changed = true;
ln.to_str(), self.ln_str(succ_ln), first_merge, changed);
return changed;
- fn copy_if_invalid(src: LiveNode, &dst: LiveNode) -> bool {
+ fn copy_if_invalid(src: LiveNode, dst: &mut LiveNode) -> bool {
if src.is_valid() {
if !dst.is_valid() {
- dst = src;
+ *dst = src;
return true;
}
}
// inputs passed by & mode should be considered live on exit:
for decl.inputs.each |arg| {
match ty::resolved_mode(self.tcx, arg.mode) {
- by_mutbl_ref | by_ref | by_val => {
+ by_ref | by_val => {
// These are "non-owned" modes, so register a read at
// the end. This will prevent us from moving out of
// such variables but also prevent us from registering
let targs = ty::ty_fn_args(ty::expr_ty(self.tcx, f));
for vec::each2(args, targs) |arg_expr, arg_ty| {
match ty::resolved_mode(self.tcx, arg_ty.mode) {
- by_val | by_copy | by_ref | by_mutbl_ref => {}
+ by_val | by_copy | by_ref => {}
by_move => {
self.check_move_from_expr(*arg_expr, vt);
}
fn warn_about_unused_args(sp: span, decl: fn_decl, entry_ln: LiveNode) {
for decl.inputs.each |arg| {
let var = self.variable(arg.id, arg.ty.span);
- match ty::resolved_mode(self.tcx, arg.mode) {
- by_mutbl_ref => {
- // for mutable reference arguments, something like
- // x = 1;
- // is not worth warning about, as it has visible
- // side effects outside the fn.
- match self.assigned_on_entry(entry_ln, var) {
- Some(_) => { /*ok*/ }
- None => {
- // but if it is not written, it ought to be used
- self.warn_about_unused(sp, entry_ln, var);
- }
- }
- }
- by_val | by_ref | by_move | by_copy => {
- self.warn_about_unused(sp, entry_ln, var);
- }
- }
+ self.warn_about_unused(sp, entry_ln, var);
}
}
// m: mutability of the argument
// lp: loan path, must be none for aliasable things
let {m,lp} = match ty::resolved_mode(self.tcx, mode) {
- ast::by_mutbl_ref => {
- {m: m_mutbl, lp: None}
- }
ast::by_move | ast::by_copy => {
{m: m_imm, lp: Some(@lp_arg(vid))}
}
use syntax::ast::{provided, required};
use syntax::ast_map::{node_item, node_method};
use ty::ty_class;
-use typeck::{method_map, method_origin, method_param, method_static};
-use typeck::{method_trait};
+use typeck::{method_map, method_origin, method_param, method_self};
+use typeck::{method_static, method_trait};
use core::util::ignore;
use dvec::DVec;
}
}
method_param({trait_id: trait_id, method_num: method_num, _}) |
- method_trait(trait_id, method_num) => {
+ method_trait(trait_id, method_num, _) |
+ method_self(trait_id, method_num) => {
if trait_id.crate == local_crate {
match tcx.items.find(trait_id.node) {
Some(node_item(item, _)) => {
}
return self.resolve_identifier(path.idents.last(),
- namespace,
- check_ribs,
- path.span);
+ namespace,
+ check_ribs,
+ path.span);
}
fn resolve_identifier(identifier: ident,
use syntax::attr;
use back::{link, abi, upcall};
use syntax::{ast, ast_util, codemap, ast_map};
-use ast_util::{local_def, path_to_ident};
+use ast_util::{def_id_of_def, local_def, path_to_ident};
use syntax::visit;
use syntax::codemap::span;
use syntax::print::pprust::{expr_to_str, stmt_to_str, path_to_str};
// the event it's not truly needed.
let llarg;
match ty::resolved_mode(tcx, arg_ty.mode) {
- ast::by_ref | ast::by_mutbl_ref => {
+ ast::by_ref => {
llarg = raw_llarg;
}
ast::by_move | ast::by_copy => {
}
}
}
- ast::item_impl(tps, _, _, ms) => {
- meth::trans_impl(ccx, *path, item.ident, ms, tps);
+ ast::item_impl(tps, trait_refs, self_ast_ty, ms) => {
+ meth::trans_impl(ccx, *path, item.ident, ms, tps, None);
+
+ // Translate any methods that have provided implementations.
+ for trait_refs.each |trait_ref_ptr| {
+ let trait_def = ccx.tcx.def_map.get(trait_ref_ptr.ref_id);
+
+ // XXX: Cross-crate default methods.
+ let trait_id = def_id_of_def(trait_def);
+ if trait_id.crate != ast::local_crate {
+ loop;
+ }
+
+ // Get the self type.
+ let self_ty;
+ match ccx.tcx.ast_ty_to_ty_cache.get(self_ast_ty) {
+ ty::atttce_resolved(self_type) => self_ty = self_type,
+ ty::atttce_unresolved => {
+ ccx.tcx.sess.impossible_case(item.span,
+ ~"didn't cache self ast ty");
+ }
+ }
+
+ match ccx.tcx.items.get(trait_id.node) {
+ ast_map::node_item(trait_item, _) => {
+ match trait_item.node {
+ ast::item_trait(tps, _, trait_methods) => {
+ trans_trait(ccx, tps, trait_methods, path,
+ item.ident, self_ty);
+ }
+ _ => {
+ ccx.tcx.sess.impossible_case(item.span,
+ ~"trait item not a \
+ trait");
+ }
+ }
+ }
+ _ => {
+ ccx.tcx.sess.impossible_case(item.span, ~"no trait item");
+ }
+ }
+ }
}
ast::item_mod(m) => {
trans_mod(ccx, m);
ast::item_class(struct_def, tps) => {
trans_struct_def(ccx, struct_def, tps, path, item.ident, item.id);
}
- ast::item_trait(tps, _, trait_methods) => {
- trans_trait(ccx, tps, trait_methods, path, item.ident);
- }
_ => {/* fall through */ }
}
}
// If there are ty params, the ctor will get monomorphized
// Translate methods
- meth::trans_impl(ccx, *path, ident, struct_def.methods, tps);
+ meth::trans_impl(ccx, *path, ident, struct_def.methods, tps, None);
}
fn trans_trait(ccx: @crate_ctxt, tps: ~[ast::ty_param],
trait_methods: ~[ast::trait_method],
- path: @ast_map::path, ident: ast::ident) {
+ path: @ast_map::path, ident: ast::ident,
+ self_ty: ty::t) {
// Translate any methods that have provided implementations
let (_, provided_methods) = ast_util::split_trait_methods(trait_methods);
- meth::trans_impl(ccx, *path, ident, provided_methods, tps);
+ meth::trans_impl(ccx, *path, ident, provided_methods, tps, Some(self_ty));
}
// Translate a module. Doing this amounts to translating the items in the
ast_map::path_to_str(path, ccx.sess.parse_sess.interner));
let is_main = is_main_name(path) && !ccx.sess.building_library;
- if is_main { create_main_wrapper(ccx, sp, llfn, node_type); }
+ if is_main { create_main_wrapper(ccx, sp, llfn); }
llfn
}
// Create a _rust_main(args: ~[str]) function which will be called from the
// runtime rust_start function
-fn create_main_wrapper(ccx: @crate_ctxt, sp: span, main_llfn: ValueRef,
- main_node_type: ty::t) {
+fn create_main_wrapper(ccx: @crate_ctxt, sp: span, main_llfn: ValueRef) {
if ccx.main_fn != None::<ValueRef> {
ccx.sess.span_fatal(sp, ~"multiple 'main' functions");
}
- let main_takes_argv =
- // invariant!
- match ty::get(main_node_type).sty {
- ty::ty_fn(ref fn_ty) => fn_ty.sig.inputs.len() != 0u,
- _ => ccx.sess.span_fatal(sp, ~"main has a non-function type")
- };
-
- let llfn = create_main(ccx, main_llfn, main_takes_argv);
+ let llfn = create_main(ccx, main_llfn);
ccx.main_fn = Some(llfn);
create_entry_fn(ccx, llfn);
- fn create_main(ccx: @crate_ctxt, main_llfn: ValueRef,
- takes_argv: bool) -> ValueRef {
+ fn create_main(ccx: @crate_ctxt, main_llfn: ValueRef) -> ValueRef {
let unit_ty = ty::mk_estr(ccx.tcx, ty::vstore_uniq);
let vecarg_ty: ty::arg =
{mode: ast::expl(ast::by_val),
let lloutputarg = llvm::LLVMGetParam(llfdecl, 0 as c_uint);
let llenvarg = llvm::LLVMGetParam(llfdecl, 1 as c_uint);
let mut args = ~[lloutputarg, llenvarg];
- if takes_argv {
- args.push(llvm::LLVMGetParam(llfdecl, 2 as c_uint));
- }
Call(bcx, main_llfn, args);
build_return(bcx);
DoAutorefArg => { val = arg_datum.to_ref_llval(bcx); }
DontAutorefArg => {
match arg_mode {
- ast::by_ref | ast::by_mutbl_ref => {
+ ast::by_ref => {
val = arg_datum.to_ref_llval(bcx);
}
return T_struct(vec::from_elem::<TypeRef>(n, T_ptr(cx.tydesc_type)));
}
-fn T_opaque_trait(cx: @crate_ctxt) -> TypeRef {
- T_struct(~[T_ptr(cx.tydesc_type), T_opaque_box_ptr(cx)])
+fn T_opaque_trait(cx: @crate_ctxt, vstore: ty::vstore) -> TypeRef {
+ match vstore {
+ ty::vstore_box =>
+ T_struct(~[T_ptr(cx.tydesc_type), T_opaque_box_ptr(cx)]),
+ _ =>
+ T_struct(~[T_ptr(cx.tydesc_type), T_ptr(T_i8())])
+ }
}
fn T_opaque_port_ptr() -> TypeRef { return T_ptr(T_i8()); }
ty::ty_fn(_) => {
closure::make_fn_glue(bcx, v0, t, drop_ty)
}
- ty::ty_trait(_, _, _) => {
+ ty::ty_trait(_, _, ty::vstore_box) => {
let llbox = Load(bcx, GEPi(bcx, v0, [0u, 1u]));
decr_refcnt_maybe_free(bcx, llbox, ty::mk_opaque_box(ccx.tcx))
}
+ ty::ty_trait(_, _, ty::vstore_uniq) => {
+ ccx.tcx.sess.unimpl(~"drop of unique trait");
+ }
ty::ty_opaque_closure_ptr(ck) => {
closure::make_opaque_cbox_drop_glue(bcx, ck, v0)
}
see `trans::base::lval_static_fn()` or `trans::base::monomorphic_fn()`.
*/
fn trans_impl(ccx: @crate_ctxt, path: path, name: ast::ident,
- methods: ~[@ast::method], tps: ~[ast::ty_param]) {
+ methods: ~[@ast::method], tps: ~[ast::ty_param],
+ self_ty: Option<ty::t>) {
let _icx = ccx.insn_ctxt("impl::trans_impl");
if tps.len() > 0u { return; }
let sub_path = vec::append_one(path, path_name(name));
if method.tps.len() == 0u {
let llfn = get_item_val(ccx, method.id);
let path = vec::append_one(sub_path, path_name(method.ident));
- trans_method(ccx, path, *method, None, llfn);
+ trans_method(ccx, path, *method, None, self_ty, llfn);
}
}
}
- `method`: the AST node for the method
- `param_substs`: if this is a generic method, the current values for
type parameters and so forth, else none
+- `base_self_ty`: optionally, the explicit self type for this method. This
+ will be none if this is not a default method and must always be present
+ if this is a default method.
- `llfn`: the LLVM ValueRef for the method
*/
fn trans_method(ccx: @crate_ctxt,
path: path,
method: &ast::method,
param_substs: Option<param_substs>,
+ base_self_ty: Option<ty::t>,
llfn: ValueRef) {
// figure out how self is being passed
_ => {
// determine the (monomorphized) type that `self` maps to for
// this method
- let self_ty = ty::node_id_to_type(ccx.tcx, method.self_id);
+ let self_ty;
+ match base_self_ty {
+ None => self_ty = ty::node_id_to_type(ccx.tcx, method.self_id),
+ Some(provided_self_ty) => self_ty = provided_self_ty
+ }
let self_ty = match param_substs {
None => self_ty,
Some({tys: ref tys, _}) => ty::subst_tps(ccx.tcx, *tys, self_ty)
None => fail ~"trans_method_callee: missing param_substs"
}
}
- typeck::method_trait(_, off) => {
- trans_trait_callee(bcx, callee_id, off, self)
+ typeck::method_trait(_, off, vstore) => {
+ trans_trait_callee(bcx, callee_id, off, self, vstore)
+ }
+ typeck::method_self(*) => {
+ bcx.tcx().sess.span_bug(self.span, ~"self method call");
}
}
}
})
}
}
- typeck::vtable_trait(*) => {
- trans_trait_callee(bcx, callee_id, n_method, base)
+ typeck::vtable_trait(_, _) => {
+ trans_trait_callee(bcx, callee_id, n_method, base, ty::vstore_box)
}
typeck::vtable_param(*) => {
fail ~"vtable_param left in monomorphized function's vtable substs";
fn trans_trait_callee(bcx: block,
callee_id: ast::node_id,
n_method: uint,
- self_expr: @ast::expr)
+ self_expr: @ast::expr,
+ vstore: ty::vstore)
-> Callee
{
//!
// Create a method callee where the method is coming from a trait
// instance (e.g., @Trait type). In this case, we must pull the
// fn pointer out of the vtable that is packaged up with the
- // @Trait instance. @Traits are represented as a pair, so we first
- // evaluate the self expression (expected a by-ref result) and then
+ // @/~/&Trait instance. @/~/&Traits are represented as a pair, so we
+ // first evaluate the self expression (expected a by-ref result) and then
// extract the self data and vtable out of the pair.
let _icx = bcx.insn_ctxt("impl::trans_trait_callee");
let self_datum = unpack_datum!(bcx, expr::trans_to_datum(bcx, self_expr));
let llpair = self_datum.to_ref_llval(bcx);
let callee_ty = node_id_type(bcx, callee_id);
- trans_trait_callee_from_llval(bcx, callee_ty, n_method, llpair)
+ trans_trait_callee_from_llval(bcx, callee_ty, n_method, llpair, vstore)
}
fn trans_trait_callee_from_llval(bcx: block,
callee_ty: ty::t,
n_method: uint,
- llpair: ValueRef)
+ llpair: ValueRef,
+ vstore: ty::vstore)
-> Callee
{
//!
GEPi(bcx, llpair, [0u, 0u]),
T_ptr(T_ptr(T_vtable()))));
- // Load the box from the @Trait pair and GEP over the box header:
+ // Load the box from the @Trait pair and GEP over the box header if
+ // necessary:
+ let llself;
let llbox = Load(bcx, GEPi(bcx, llpair, [0u, 1u]));
- let llself = GEPi(bcx, llbox, [0u, abi::box_field_body]);
+ match vstore {
+ ty::vstore_box | ty::vstore_uniq => {
+ llself = GEPi(bcx, llbox, [0u, abi::box_field_body]);
+ }
+ ty::vstore_slice(_) => {
+ llself = llbox;
+ }
+ ty::vstore_fixed(*) => {
+ bcx.tcx().sess.bug(~"vstore_fixed trait");
+ }
+ }
// Load the function from the vtable and cast it to the expected type.
let llcallee_ty = type_of::type_of_fn_from_ty(ccx, callee_ty);
// XXX: This should support multiple traits.
let trt_id = driver::session::expect(
tcx.sess,
- ty::ty_to_def_id(ty::impl_traits(tcx, impl_id)[0]),
+ ty::ty_to_def_id(ty::impl_traits(tcx, impl_id, ty::vstore_box)[0]),
|| ~"make_impl_vtable: non-trait-type implemented");
let has_tps = (*ty::lookup_item_type(ccx.tcx, impl_id).bounds).len() > 0u;
d
}
ast_map::node_method(mth, _, _) => {
+ // XXX: What should the self type be here?
let d = mk_lldecl();
set_inline_hint_if_appr(mth.attrs, d);
- meth::trans_method(ccx, pt, mth, psubsts, d);
+ meth::trans_method(ccx, pt, mth, psubsts, None, d);
d
}
ast_map::node_ctor(_, tps, ctor, parent_id, _) => {
}
let bool_ty = ty::mk_bool(tcx);
let scratch = scratch_datum(bcx, bool_ty, false);
+ // XXX: Should not be vstore_box!
let bcx = callee::trans_call_inner(
self.bcx, None, mth_ty, bool_ty,
|bcx| meth::trans_trait_callee_from_llval(bcx, mth_ty,
- mth_idx, v),
+ mth_idx, v,
+ ty::vstore_box),
ArgVals(args), SaveIn(scratch.val), DontAutorefArg);
let result = scratch.to_value_llval(bcx);
let next_bcx = sub_block(bcx, ~"next");
ast::expl(e) => match e {
ast::by_ref => 1u,
ast::by_val => 2u,
- ast::by_mutbl_ref => 3u,
ast::by_move => 4u,
ast::by_copy => 5u
}
return {mut next_tag_id: 0u16, pad: 0u16, pad2: 0u32};
}
-fn add_u16(&dest: ~[u8], val: u16) {
- dest += ~[(val & 0xffu16) as u8, (val >> 8u16) as u8];
+/*
+Although these two functions are never called, they are here
+for a VERY GOOD REASON. See #3670
+*/
+fn add_u16(dest: &mut ~[u8], val: u16) {
+ *dest += ~[(val & 0xffu16) as u8, (val >> 8u16) as u8];
}
-fn add_substr(&dest: ~[u8], src: ~[u8]) {
+fn add_substr(dest: &mut ~[u8], src: ~[u8]) {
add_u16(dest, vec::len(src) as u16);
- dest += src;
+ *dest += src;
}
T_struct(~[T_struct(tys)])
}
ty::ty_fn(_) => T_fn_pair(cx, type_of_fn_from_ty(cx, t)),
- ty::ty_trait(_, _, _) => T_opaque_trait(cx),
+ ty::ty_trait(_, _, vstore) => T_opaque_trait(cx, vstore),
ty::ty_type => T_ptr(cx.tydesc_type),
ty::ty_tup(elts) => {
let mut tys = ~[];
by_val | by_move | by_copy => {
type_needs(cx, use_repr, arg.ty);
}
- by_ref | by_mutbl_ref => {}
+ by_ref => {}
}
}
}
typeck::method_param({param_num: param, _}) => {
cx.uses[param] |= use_tydesc;
}
- typeck::method_trait(_, _) => (),
+ typeck::method_trait(*) | typeck::method_self(*) => (),
}
}
}
use common::*;
use build::*;
use base::*;
-use shape::llsize_of;
use datum::immediate_rvalue;
export make_free_glue, autoderef, duplicate;
export ty_evec, mk_evec, type_is_vec;
export ty_unboxed_vec, mk_unboxed_vec, mk_mut_unboxed_vec;
export vstore, vstore_fixed, vstore_uniq, vstore_box, vstore_slice;
+export serialize_vstore, deserialize_vstore;
export ty_nil, mk_nil, type_is_nil;
export ty_trait, mk_trait;
export ty_param, mk_param, ty_params_to_tys;
type mt = {ty: t, mutbl: ast::mutability};
+#[auto_serialize]
enum vstore {
vstore_fixed(uint),
vstore_uniq,
ty_evec(_, vstore_uniq) |
ty_evec(_, vstore_box) => true,
- ty_trait(*) => true,
+ ty_trait(_, _, vstore_box) |
+ ty_trait(_, _, vstore_uniq) => true,
+ ty_trait(_, _, vstore_fixed(_)) |
+ ty_trait(_, _, vstore_slice(_)) => false,
ty_param(*) | ty_infer(*) => true,
}
typeck::method_param({trait_id:trt_id,
method_num:n_mth, _}) |
- typeck::method_trait(trt_id, n_mth) => {
+ typeck::method_trait(trt_id, n_mth, _) |
+ typeck::method_self(trt_id, n_mth) => {
// ...trait methods bounds, in contrast, include only the
// method bounds, so we must preprend the tps from the
// trait itself. This ought to be harmonized.
/*
Could this return a list of (def_id, substs) pairs?
*/
-fn impl_traits(cx: ctxt, id: ast::def_id) -> ~[t] {
+fn impl_traits(cx: ctxt, id: ast::def_id, vstore: vstore) -> ~[t] {
+ fn vstoreify(cx: ctxt, ty: t, vstore: vstore) -> t {
+ match ty::get(ty).sty {
+ ty::ty_trait(_, _, trait_vstore) if vstore == trait_vstore => ty,
+ ty::ty_trait(did, substs, _) => mk_trait(cx, did, substs, vstore),
+ _ => cx.sess.bug(~"impl_traits: not a trait")
+ }
+ }
+
if id.crate == ast::local_crate {
debug!("(impl_traits) searching for trait impl %?", id);
match cx.items.find(id.node) {
_)) => {
do option::map_default(&opt_trait, ~[]) |trait_ref| {
- ~[node_id_to_type(cx, trait_ref.ref_id)]
+ ~[vstoreify(cx,
+ node_id_to_type(cx, trait_ref.ref_id),
+ vstore)]
}
}
Some(ast_map::node_item(@{node: ast::item_class(sd,_),
_},_)) => {
do vec::map(sd.traits) |trait_ref| {
- node_id_to_type(cx, trait_ref.ref_id)
+ vstoreify(cx, node_id_to_type(cx, trait_ref.ref_id),
+ vstore)
}
}
_ => ~[]
}
} else {
- csearch::get_impl_traits(cx, id)
+ vec::map(csearch::get_impl_traits(cx, id),
+ |x| vstoreify(cx, *x, vstore))
}
}
export vtable_map;
export vtable_res;
export vtable_origin;
-export method_static, method_param, method_trait;
+export method_static, method_param, method_trait, method_self;
export vtable_static, vtable_param, vtable_trait;
export provided_methods_map;
method_param(method_param),
// method invoked on a trait instance
- method_trait(ast::def_id, uint),
+ method_trait(ast::def_id, uint, ty::vstore),
+
+ // method invoked on "self" inside a default method
+ method_self(ast::def_id, uint),
}
// details for a method invoked with a receiver whose type is a type parameter
}
let mut ok = ty::type_is_nil(fn_ty.sig.output);
let num_args = vec::len(fn_ty.sig.inputs);
- ok &= num_args == 0u || num_args == 1u &&
- arg_is_argv_ty(tcx, fn_ty.sig.inputs[0]);
+ ok &= num_args == 0u;
if !ok {
tcx.sess.span_err(
main_span,
fmt!("Wrong type in main function: found `%s`, \
- expected `extern fn(++v: ~[~str]) -> ()` \
- or `extern fn() -> ()`",
+ expected `fn() -> ()`",
ty_to_str(tcx, main_t)));
}
}
type_def_id, path);
match ty::get(result.ty).sty {
ty::ty_trait(trait_def_id, substs, _) => {
- if vst != ty::vstore_box {
- tcx.sess.span_unimpl(path.span,
- ~"`~trait` and `&trait` are \
- unimplemented; use \
- `@trait` instead for now");
+ match vst {
+ ty::vstore_box | ty::vstore_slice(*) => {}
+ _ => {
+ tcx.sess.span_unimpl(path.span,
+ ~"`~trait` is \
+ unimplemented; use \
+ `@trait` instead for \
+ now");
+ }
}
return ty::mk_trait(tcx, trait_def_id, substs, vst);
}
- _ =>
- {}
+ _ => {}
}
}
_ => ()
~"addr_of" => (1u, ~[arg(ast::by_ref, param(ccx, 0u))],
ty::mk_imm_ptr(tcx, param(ccx, 0u))),
~"move_val" | ~"move_val_init" => {
- (1u, ~[arg(ast::by_mutbl_ref, param(ccx, 0u)),
+ (1u, ~[arg(ast::by_copy,
+ ty::mk_mut_rptr(tcx, ty::re_bound(ty::br_anon(0)),
+ param(ccx, 0u))),
arg(ast::by_move, param(ccx, 0u))],
ty::mk_nil(tcx))
}
ty_param(p) => {
self.push_inherent_candidates_from_param(p);
}
- ty_trait(did, ref substs, _) => {
+ ty_trait(did, ref substs, vstore) => {
self.push_inherent_candidates_from_trait(
- self_ty, did, substs);
+ self_ty, did, substs, vstore);
self.push_inherent_impl_candidates_for_type(did);
}
ty_self => {
let self_did = self.fcx.self_impl_def_id.expect(
~"unexpected `none` for self_impl_def_id");
let substs = {self_r: None, self_ty: None, tps: ~[]};
- self.push_inherent_candidates_from_trait(
+ self.push_inherent_candidates_from_self(
self_ty, self_did, &substs);
}
ty_enum(did, _) | ty_class(did, _) => {
fn push_inherent_candidates_from_trait(&self,
self_ty: ty::t,
did: def_id,
- substs: &ty::substs)
+ substs: &ty::substs,
+ vstore: ty::vstore)
{
debug!("push_inherent_candidates_from_trait(did=%s, substs=%s)",
self.did_to_str(did),
rcvr_substs: move rcvr_substs,
num_method_tps: method.tps.len(),
self_mode: get_mode_from_self_type(method.self_ty),
- origin: method_trait(did, index)
+ origin: method_trait(did, index, vstore)
+ });
+ }
+
+ fn push_inherent_candidates_from_self(&self,
+ self_ty: ty::t,
+ did: def_id,
+ substs: &ty::substs) {
+ let tcx = self.tcx();
+ let methods = ty::trait_methods(tcx, did); // XXX: Inherited methods.
+ let index;
+ match vec::position(*methods, |m| m.ident == self.m_name) {
+ Some(i) => index = i,
+ None => return
+ }
+ let method = &methods[index];
+
+ let rcvr_substs = { self_ty: Some(self_ty), ..*substs };
+ let (rcvr_ty, rcvr_substs) =
+ self.create_rcvr_ty_and_substs_for_method(
+ method.self_ty, self_ty, move rcvr_substs);
+
+ self.inherent_candidates.push(Candidate {
+ rcvr_ty: rcvr_ty,
+ rcvr_substs: move rcvr_substs,
+ num_method_tps: method.tps.len(),
+ self_mode: get_mode_from_self_type(method.self_ty),
+ origin: method_self(did, index)
});
}
* vtable and hence cannot be monomorphized. */
match candidate.origin {
- method_static(*) | method_param(*) => {
+ method_static(*) | method_param(*) | method_self(*) => {
return; // not a call to a trait instance
}
method_trait(*) => {}
method_param(ref mp) => {
type_of_trait_method(self.tcx(), mp.trait_id, mp.method_num)
}
- method_trait(did, idx) => {
+ method_trait(did, idx, _) | method_self(did, idx) => {
type_of_trait_method(self.tcx(), did, idx)
}
};
method_param(mp) => {
self.report_param_candidate(idx, mp.trait_id)
}
- method_trait(trait_did, _) => {
+ method_trait(trait_did, _, _) | method_self(trait_did, _) => {
self.report_param_candidate(idx, trait_did)
}
}
result::Err(_) => { return; /*typeck will fail anyhow*/ }
result::Ok(target_ty) => {
match ty::get(target_ty).sty {
- ty::ty_trait(_, substs, _) => {
- let trait_region = match substs.self_r {
- Some(r) => {r}
- None => {ty::re_static}
- };
+ ty::ty_trait(_, _, vstore_slice(trait_region)) => {
let source_ty = rcx.fcx.expr_ty(source);
constrain_regions_in_type(rcx, trait_region,
expr.span, source_ty);
match *bound {
ty::bound_trait(i_ty) => {
let i_ty = ty::subst(tcx, substs, i_ty);
- match lookup_vtable(fcx, expr, *ty, i_ty, allow_unsafe,
- is_early) {
+ match lookup_vtable_covariant(fcx, expr, *ty, i_ty,
+ allow_unsafe, is_early) {
Some(vtable) => result.push(vtable),
None => {
fcx.tcx().sess.span_fatal(
demand::suptype(fcx, expr.span, exp_trait_ty, act_trait_ty)
}
-/*
-Look up the vtable to use when treating an item of type <t>
-as if it has type <trait_ty>
-*/
-fn lookup_vtable(fcx: @fn_ctxt,
- expr: @ast::expr,
- ty: ty::t,
- trait_ty: ty::t,
- allow_unsafe: bool,
- is_early: bool)
- -> Option<vtable_origin>
-{
+// Look up the vtable to use when treating an item of type `t` as if it has
+// type `trait_ty`. This does allow subtraits.
+fn lookup_vtable_covariant(fcx: @fn_ctxt,
+ expr: @ast::expr,
+ ty: ty::t,
+ trait_ty: ty::t,
+ allow_unsafe: bool,
+ is_early: bool)
+ -> Option<vtable_origin> {
+ let worklist = dvec::DVec();
+ worklist.push(trait_ty);
+ while worklist.len() > 0 {
+ let trait_ty = worklist.pop();
+ let result = lookup_vtable_invariant(fcx, expr, ty, trait_ty,
+ allow_unsafe, is_early);
+ if result.is_some() {
+ return result;
+ }
+
+ // Add subtraits to the worklist, if applicable.
+ match ty::get(trait_ty).sty {
+ ty::ty_trait(trait_id, _, _) => {
+ let table = fcx.ccx.coherence_info.supertrait_to_subtraits;
+ match table.find(trait_id) {
+ None => {}
+ Some(subtraits) => {
+ for subtraits.each |subtrait_id| {
+ // XXX: This is wrong; subtraits should themselves
+ // have substs.
+ let substs =
+ { self_r: None, self_ty: None, tps: ~[] };
+ let trait_ty = ty::mk_trait(fcx.ccx.tcx,
+ *subtrait_id,
+ substs,
+ ty::vstore_box);
+ worklist.push(trait_ty);
+ }
+ }
+ }
+ }
+ _ => {
+ fcx.ccx.tcx.sess.impossible_case(expr.span,
+ "lookup_vtable_covariant: \
+ non-trait in worklist");
+ }
+ }
+ }
- debug!("lookup_vtable(ty=%s, trait_ty=%s)",
+ return None;
+}
+
+// Look up the vtable to use when treating an item of type `t` as if it has
+// type `trait_ty`. This does not allow subtraits.
+fn lookup_vtable_invariant(fcx: @fn_ctxt,
+ expr: @ast::expr,
+ ty: ty::t,
+ trait_ty: ty::t,
+ allow_unsafe: bool,
+ is_early: bool)
+ -> Option<vtable_origin> {
+ debug!("lookup_vtable_invariant(ty=%s, trait_ty=%s)",
fcx.infcx().ty_to_str(ty), fcx.inh.infcx.ty_to_str(trait_ty));
let _i = indenter();
let tcx = fcx.ccx.tcx;
- let (trait_id, trait_substs) = match ty::get(trait_ty).sty {
- ty::ty_trait(did, substs, _) => (did, substs),
+ let (trait_id, trait_substs, trait_vstore) = match ty::get(trait_ty).sty {
+ ty::ty_trait(did, substs, vstore) => (did, substs, vstore),
_ => tcx.sess.impossible_case(expr.span,
- "lookup_vtable: \
+ "lookup_vtable_invariant: \
don't know how to handle a non-trait")
};
let ty = match fixup_ty(fcx, expr, ty, is_early) {
}
_ => tcx.sess.impossible_case(
expr.span,
- "lookup_vtable: in loop, \
+ "lookup_vtable_invariant: in loop, \
don't know how to handle a non-trait ity")
}
n_bound += 1u;
// it's the same trait as trait_ty, we need to
// unify it with trait_ty in order to get all
// the ty vars sorted out.
- for vec::each(ty::impl_traits(tcx, im.did)) |of_ty| {
+ for vec::each(ty::impl_traits(tcx, im.did,
+ trait_vstore)) |of_ty| {
match ty::get(*of_ty).sty {
ty::ty_trait(id, _, _) => {
// Not the trait we're looking for
// lists of types to unify pairwise.
connect_trait_tps(fcx, expr, substs_f.tps,
- trait_tps, im.did);
+ trait_tps, im.did,
+ trait_vstore);
let subres = lookup_vtables(
fcx, expr, im_bs, &substs_f,
false, is_early);
}
fn connect_trait_tps(fcx: @fn_ctxt, expr: @ast::expr, impl_tys: ~[ty::t],
- trait_tys: ~[ty::t], impl_did: ast::def_id) {
+ trait_tys: ~[ty::t], impl_did: ast::def_id,
+ vstore: ty::vstore) {
let tcx = fcx.ccx.tcx;
// XXX: This should work for multiple traits.
- let ity = ty::impl_traits(tcx, impl_did)[0];
+ let ity = ty::impl_traits(tcx, impl_did, vstore)[0];
let trait_ty = ty::subst_tps(tcx, impl_tys, ity);
debug!("(connect trait tps) trait type is %?, impl did is %?",
ty::get(trait_ty).sty, impl_did);
ast::expr_cast(src, _) => {
let target_ty = fcx.expr_ty(ex);
match ty::get(target_ty).sty {
- ty::ty_trait(*) => {
- /*
- Look up vtables for the type we're casting to,
- passing in the source and target type
- */
+ ty::ty_trait(_, _, vstore) => {
+ // Look up vtables for the type we're casting to, passing in the
+ // source and target type.
+ //
+ // XXX: This is invariant and shouldn't be. --pcw
+
let ty = fcx.expr_ty(src);
- let vtable_opt = lookup_vtable(fcx, ex, ty, target_ty, true,
- is_early);
+ let vtable_opt = lookup_vtable_invariant(fcx, ex, ty, target_ty,
+ true, is_early);
match vtable_opt {
None => {
// Try the new-style boxed trait; "@int as @Trait".
+ // Or the new-style region trait; "&int as &Trait".
let mut err = false;
let ty = structurally_resolved_type(fcx, ex.span, ty);
match ty::get(ty).sty {
- ty::ty_box(boxed_ty) => {
- let vtable_opt = lookup_vtable(fcx, ex,
- boxed_ty.ty,
- target_ty, true,
- is_early);
- match vtable_opt {
- Some(vtable) => {
- /*
- Map this expression to that vtable (that
- is: "ex has vtable <vtable>")
- */
- if !is_early {
- cx.vtable_map.insert(ex.id,
- @~[vtable]);
+ ty::ty_box(mt) | ty::ty_rptr(_, mt) => {
+ // Ensure that the trait vstore and the pointer
+ // type match.
+ match (ty::get(ty).sty, vstore) {
+ (ty::ty_box(_), ty::vstore_box) |
+ (ty::ty_rptr(*), ty::vstore_slice(*)) => {
+ let vtable_opt =
+ lookup_vtable_invariant(fcx,
+ ex,
+ mt.ty,
+ target_ty,
+ true,
+ is_early);
+ match vtable_opt {
+ Some(vtable) => {
+ // Map this expression to that
+ // vtable (that is: "ex has vtable
+ // <vtable>")
+ if !is_early {
+ cx.vtable_map.insert(
+ ex.id, @~[vtable]);
+ }
+ }
+ None => err = true
}
+
+ // Now, if this is &trait, we need to link
+ // the regions.
+ match (ty::get(ty).sty, vstore) {
+ (ty::ty_rptr(ra, _),
+ ty::vstore_slice(rb)) => {
+ infer::mk_subr(fcx.infcx(),
+ false,
+ ex.span,
+ rb,
+ ra);
+ }
+ _ => {}
+ }
+ }
+ (ty::ty_box(_), _) => {
+ fcx.ccx.tcx.sess.span_err(ex.span,
+ ~"must cast \
+ a boxed \
+ pointer to \
+ a boxed
+ trait");
+ err = true;
+ }
+ (ty::ty_rptr(*), _) => {
+ fcx.ccx.tcx.sess.span_err(ex.span,
+ ~"must cast \
+ a borrowed \
+ pointer to \
+ a borrowed \
+ trait");
+ }
+ _ => {
+ fcx.ccx.tcx.sess.impossible_case(
+ ex.span,
+ ~"impossible combination of type and \
+ trait vstore");
}
- None => err = true
}
}
_ => err = true
// Contains implementations of methods associated with a trait. For these,
// the associated trait must be imported at the call site.
extension_methods: HashMap<def_id,@DVec<@Impl>>,
+
+ // A mapping from a supertrait to its subtraits.
+ supertrait_to_subtraits: HashMap<def_id,@DVec<def_id>>
}
fn CoherenceInfo() -> CoherenceInfo {
CoherenceInfo {
inherent_methods: HashMap(),
- extension_methods: HashMap()
+ extension_methods: HashMap(),
+ supertrait_to_subtraits: HashMap()
}
}
}
impl CoherenceChecker {
-
// Create a mapping containing a MethodInfo for every provided
// method in every trait.
fn build_provided_methods_map(crate: @crate) {
}
fn check_coherence(crate: @crate) {
-
- // Check implementations. This populates the tables containing the
- // inherent methods and extension methods.
+ // Check implementations and traits. This populates the tables
+ // containing the inherent methods and extension methods. It also
+ // builds up the trait inheritance table.
visit_crate(*crate, (), mk_simple_visitor(@{
visit_item: |item| {
debug!("(checking coherence) item '%s'",
item_class(struct_def, _) => {
self.check_implementation(item, struct_def.traits);
}
+ item_trait(_, supertraits, _) => {
+ self.register_inherited_trait(item, supertraits);
+ }
_ => {
// Nothing to do.
}
}
}
+ fn register_inherited_trait(item: @item, supertraits: ~[@trait_ref]) {
+ // XXX: This is wrong. We need to support substitutions; e.g.
+ // trait Foo : Bar<int>.
+ let supertrait_to_subtraits =
+ self.crate_context.coherence_info.supertrait_to_subtraits;
+ let subtrait_id = local_def(item.id);
+ for supertraits.each |supertrait| {
+ let supertrait_id = self.trait_ref_to_trait_def_id(*supertrait);
+ match supertrait_to_subtraits.find(supertrait_id) {
+ None => {
+ let new_vec = @dvec::DVec();
+ new_vec.push(subtrait_id);
+ supertrait_to_subtraits.insert(supertrait_id, new_vec);
+ }
+ Some(existing_vec) => {
+ existing_vec.push(subtrait_id);
+ }
+ }
+ }
+ }
+
fn add_inherent_method(base_def_id: def_id, implementation: @Impl) {
let implementation_list;
match self.crate_context.coherence_info.inherent_methods
+f: fn~(ctxt: Ctxt) -> T
) -> T {
let po = comm::Port();
- let ch = comm::Chan(po);
+ let ch = comm::Chan(&po);
let msg = HandleRequest(fn~(move f, ctxt: Ctxt) {
comm::send(ch, f(ctxt))
});
os::close(pipe_in.out);
let stdout_po = comm::Port();
- let stdout_ch = comm::Chan(stdout_po);
+ let stdout_ch = comm::Chan(&stdout_po);
do task::spawn_sched(task::SingleThreaded) {
comm::send(stdout_ch, readclose(pipe_out.in));
}
let stdout = comm::recv(stdout_po);
let stderr_po = comm::Port();
- let stderr_ch = comm::Chan(stderr_po);
+ let stderr_ch = comm::Chan(&stderr_po);
do task::spawn_sched(task::SingleThreaded) {
comm::send(stderr_ch, readclose(pipe_err.in));
}
fn future_writer_factory(
) -> (WriterFactory, comm::Port<(doc::Page, ~str)>) {
let markdown_po = comm::Port();
- let markdown_ch = comm::Chan(markdown_po);
+ let markdown_ch = comm::Chan(&markdown_po);
let writer_factory = fn~(page: doc::Page) -> Writer {
let writer_po = comm::Port();
- let writer_ch = comm::Chan(writer_po);
+ let writer_ch = comm::Chan(&writer_po);
do task::spawn {
let (writer, future) = future_writer();
comm::send(writer_ch, writer);
use pass::Pass;
use config::Config;
-fn main(args: ~[~str]) {
+fn main() {
+ let args = os::args();
if args.contains(&~"-h") || args.contains(&~"--help") {
config::usage();
+S 2012-10-05 937f8f4
+ macos-i386 8b5ddc78b3004e539c6fbe224e492e4a6a1bc867
+ macos-x86_64 03793e0136512c644edfb5f13cc5bb7d67fb24e5
+ freebsd-x86_64 f7f4b402f06b9344fe327a9aa0282aa4ac18fcb0
+ linux-i386 789223cb3db37f6f81f48dff5fa202311fae6c2b
+ linux-x86_64 b5f1ada95528ac5b24d2b3dd3c817b8bcfc3302e
+ winnt-i386 e984437412dc4450931e0bb7ed140652bd66443c
+
+S 2012-10-03 5585514
+ macos-i386 c910d42405e66b444b7870ea66b93e1135776df3
+ macos-x86_64 e0dfa93e8d0d25b91c9684d4f6e92dec521e2d74
+ freebsd-x86_64 228e68ac17ca104554dd8a39a466d20f1b68de24
+ linux-i386 0a2760b24d5bc3cabcc9321b92a08796f95da377
+ linux-x86_64 eace8a5c46f7525355e85b3b570dbd7f4b3b6471
+ winnt-i386 25680d15a358cf4163e08f4e56e54fb497de5eb4
+
S 2012-10-02 4d30b34
macos-i386 2bcce3cde8a7e53df202972cda85b0b59ce4e50d
macos-x86_64 fc5592828392f9eabe8b51cc59639be6d709cc26
fn foo<T: Send Copy>(x: T) -> Port<T> {
let p = Port();
- let c = Chan(p);
+ let c = Chan(&p);
do task::spawn() |copy c, copy x| {
c.send(x);
}
}
}
-fn main(++args: ~[~str]) {
+fn main() {
+ let args = os::args();
let num_keys = {
if args.len() == 2 {
uint::from_str(args[1]).get()
use io::{Reader, ReaderUtil};
-fn main(++argv: ~[~str]) {
+fn main() {
+ let argv = os::args();
#macro[
[#bench[id],
maybe_run_test(argv, #stringify(id), id)
-fn main(++args: ~[~str]) {
+fn main() {
+ let args = os::args();
let args = if os::getenv(~"RUST_BENCH").is_some() {
~[~"", ~"10000000"]
} else if args.len() <= 1u {
return dvec::unwrap(move result);
}
-fn main(++args: ~[~str]) {
+fn main() {
+ let args = os::args();
let args = if os::getenv(~"RUST_BENCH").is_some() {
~[~"", ~"50000000"]
} else if args.len() <= 1u {
true
}
-fn main(++args: ~[~str]) {
+fn main() {
+ let args = os::args();
let args = if os::getenv(~"RUST_BENCH").is_some() {
~[~"", ~"15", ~"48"]
} else if args.len() <= 1u {
assert result == num_bytes * size;
}
-fn main(++args: ~[~str]) {
+fn main() {
+ let args = os::args();
let args = if os::getenv(~"RUST_BENCH").is_some() {
~[~"", ~"1000000", ~"10000"]
} else if args.len() <= 1u {
assert result == num_bytes * size;
}
-fn main(++args: ~[~str]) {
+fn main() {
+ let args = os::args();
let args = if os::getenv(~"RUST_BENCH").is_some() {
~[~"", ~"1000000", ~"8"]
} else if args.len() <= 1u {
};
}
-fn main(++args: ~[~str]) {
+fn main() {
+ let args = os::args();
let args = if os::getenv(~"RUST_BENCH").is_some() {
~[~"", ~"100", ~"10000"]
} else if args.len() <= 1u {
};
}
-fn main(++args: ~[~str]) {
+fn main() {
+ let args = os::args();
let args = if os::getenv(~"RUST_BENCH").is_some() {
~[~"", ~"100", ~"10000"]
} else if args.len() <= 1u {
};
}
-fn main(++args: ~[~str]) {
+fn main() {
+ let args = os::args();
let args = if os::getenv(~"RUST_BENCH").is_some() {
~[~"", ~"100", ~"10000"]
} else if args.len() <= 1u {
};
}
-fn main(++args: ~[~str]) {
+fn main() {
+ let args = os::args();
let args = if os::getenv(~"RUST_BENCH").is_some() {
~[~"", ~"100", ~"10000"]
} else if args.len() <= 1u {
let msg_per_task = uint::from_str(args[2]).get();
let num_port = Port();
- let mut num_chan = Chan(num_port);
+ let mut num_chan = Chan(&num_port);
let start = time::precise_time_s();
for uint::range(1u, num_tasks) |i| {
let get_chan = Port();
- let get_chan_chan = Chan(get_chan);
+ let get_chan_chan = Chan(&get_chan);
let new_future = do future::spawn
|copy num_chan, move get_chan_chan| {
let p = Port();
- get_chan_chan.send(Chan(p));
+ get_chan_chan.send(Chan(&p));
thread_ring(i, msg_per_task, num_chan, p)
};
futures.push(new_future);
io::stdout().write_str(fmt!("Throughput=%f per sec\n", thruput));
}
-fn main(++args: ~[~str]) {
+fn main() {
+ let args = os::args();
let args = if os::getenv(~"RUST_BENCH").is_some() {
~[~"", ~"1000000", ~"10000"]
} else if args.len() <= 1u {
}
}
-fn main(++args: ~[~str]) {
+fn main() {
+ let args = os::args();
let args = if os::getenv(~"RUST_BENCH").is_some() {
~[~"", ~"12"]
} else if args.len() <= 1u {
return arena.alloc(|| nil);
}
-fn main(++args: ~[~str]) {
+fn main() {
+ let args = os::args();
let args = if os::getenv(~"RUST_BENCH").is_some() {
~[~"", ~"17"]
} else if args.len() <= 1u {
let from_creatures_log: comm::Port<~str> = comm::Port();
// these channels will be passed to the creatures so they can talk to us
- let to_rendezvous = comm::Chan(from_creatures);
- let to_rendezvous_log = comm::Chan(from_creatures_log);
+ let to_rendezvous = comm::Chan(&from_creatures);
+ let to_rendezvous_log = comm::Chan(&from_creatures_log);
// these channels will allow us to talk to each creature by 'name'/index
let to_creature: ~[comm::Chan<Option<creature_info>>] =
io::println(show_number(creatures_met));
}
-fn main(++args: ~[~str]) {
+fn main() {
+ let args = os::args();
let args = if os::getenv(~"RUST_BENCH").is_some() {
~[~"", ~"200000"]
} else if args.len() <= 1u {
return flips;
}
-fn main(++args: ~[~str]) {
+fn main() {
+ let args = os::args();
let args = if os::getenv(~"RUST_BENCH").is_some() {
~[~"", ~"10"]
} else if args.len() <= 1u {
fn acid(ch: char, prob: u32) -> aminoacids { return {ch: ch, prob: prob}; }
-fn main(++args: ~[~str]) {
+fn main() {
+ let args = os::args();
let args = if os::getenv(~"RUST_BENCH").is_some() {
// alioth tests k-nucleotide with this data at 25,000,000
~[~"", ~"5000000"]
}
}
-fn main(++args: ~[~str]) {
+fn main() {
+ let args = os::args();
let args = if os::getenv(~"RUST_BENCH").is_some() {
~[~"", ~"40"]
} else if args.len() <= 1u {
}
// given a FASTA file on stdin, process sequence THREE
-fn main(++args: ~[~str]) {
+fn main() {
+ let args = os::args();
let rdr = if os::getenv(~"RUST_BENCH").is_some() {
// FIXME: Using this compile-time env variable is a crummy way to
// get to this massive data set, but #include_bin chokes on it (#2598)
}
// given a FASTA file on stdin, process sequence THREE
-fn main(++args: ~[~str]) {
+fn main() {
+ let args = os::args();
let rdr = if os::getenv(~"RUST_BENCH").is_some() {
// FIXME: Using this compile-time env variable is a crummy way to
// get to this massive data set, but #include_bin chokes on it (#2598)
// initialize each sequence sorter
let sizes = ~[1u,2u,3u,4u,6u,12u,18u];
let from_child = vec::map (sizes, |_sz| comm::Port() );
- let to_parent = vec::mapi(sizes, |ii, _sz| comm::Chan(from_child[ii]) );
+ let to_parent = vec::mapi(sizes, |ii, _sz| comm::Chan(&from_child[ii]) );
let to_child = vec::mapi(sizes, |ii, sz| {
let ii = ii;
let sz = *sz;
fn writer(path: ~str, writech: comm::Chan<comm::Chan<line>>, size: uint)
{
let p: comm::Port<line> = comm::Port();
- let ch = comm::Chan(p);
+ let ch = comm::Chan(&p);
comm::send(writech, ch);
let cout: io::Writer = match path {
~"" => {
}
}
-fn main(++args: ~[~str]) {
+fn main() {
+ let args = os::args();
let args = if os::getenv(~"RUST_BENCH").is_some() {
~[~"", ~"4000", ~"10"]
} else {
else { uint::from_str(args[1]).get() };
let writep = comm::Port();
- let writech = comm::Chan(writep);
+ let writech = comm::Chan(&writep);
do task::spawn {
writer(path, writech, size);
};
fn sqrt(n: float) -> float;
}
-fn main(++args: ~[~str]) {
+fn main() {
+ let args = os::args();
let args = if os::getenv(~"RUST_BENCH").is_some() {
~[~"", ~"4000000"]
} else if args.len() <= 1u {
for results.each |r| { future::get(r); }
}
-fn main(++args: ~[~str]) {
+fn main() {
+ let args = os::args();
let args = if os::getenv(~"RUST_BENCH").is_some() {
~[~"", ~"20"]
} else if args.len() <= 1u {
eval_At_times_u(v, AtAu);
}
-fn main(++args: ~[~str]) {
+fn main() {
+ let args = os::args();
let args = if os::getenv(~"RUST_BENCH").is_some() {
~[~"", ~"2000"]
} else if args.len() <= 1u {
use iter::*;
let p = comm::Port();
- let mut ch = comm::Chan(p);
+ let mut ch = comm::Chan(&p);
for int::range(2, n_threads + 1) |i| {
let id = n_threads + 2 - i;
let to_child = do task::spawn_listener::<int> |p, copy ch| {
}
}
-fn main(++args: ~[~str]) {
+fn main() {
+ let args = os::args();
let args = if os::getenv(~"RUST_BENCH").is_some() {
~[~"", ~"2000000"]
} else if args.len() <= 1u {
}
}
-fn main(++args: ~[~str]) {
+fn main() {
+ let args = os::args();
let args = if os::getenv(~"RUST_BENCH").is_some() {
~[~"", ~"100000", ~"100"]
} else if args.len() <= 1u {
}
}
-fn main(++args: ~[~str]) {
+fn main() {
+ let args = os::args();
let grid = if vec::len(args) == 1u {
// FIXME create sudoku inline since nested vec consts dont work yet
// (#571)
}
}
-fn main(++args: ~[~str]) {
+fn main() {
+ let args = os::args();
let args = if os::getenv(~"RUST_BENCH").is_some() {
~[~"", ~"100000"]
} else if args.len() <= 1u {
// Doesn't return until all such tasks are ready, but doesn't block forever itself.
fn grandchild_group(num_tasks: uint) {
let po = comm::Port();
- let ch = comm::Chan(po);
+ let ch = comm::Chan(&po);
for num_tasks.times {
do task::spawn { // linked
assert x == task::Success;
}
-fn main(++args: ~[~str]) {
+fn main() {
+ let args = os::args();
let args = if os::getenv(~"RUST_BENCH").is_some() {
~[~"", ~"100000"]
} else if args.len() <= 1u {
fn calc(children: uint, parent_ch: comm::Chan<msg>) {
let port = comm::Port();
- let chan = comm::Chan(port);
+ let chan = comm::Chan(&port);
let mut child_chs = ~[];
let mut sum = 0;
comm::send(parent_ch, done(sum + 1));
}
-fn main(++args: ~[~str]) {
+fn main() {
+ let args = os::args();
let args = if os::getenv(~"RUST_BENCH").is_some() {
~[~"", ~"100000"]
} else if args.len() <= 1u {
let children = uint::from_str(args[1]).get();
let port = comm::Port();
- let chan = comm::Chan(port);
+ let chan = comm::Chan(&port);
do task::spawn {
calc(children, chan);
};
fn g() { }
-fn main(++args: ~[~str]) {
+fn main() {
+ let args = os::args();
let args = if os::getenv(~"RUST_BENCH").is_some() {
~[~"", ~"400"]
} else if args.len() <= 1u {
// xfail-pretty
-#[legacy_modes];
-
extern mod std;
use option = option;
type joinable_task = Port<()>;
fn spawn_joinable(+f: fn~()) -> joinable_task {
let p = Port();
- let c = Chan(p);
+ let c = Chan(&p);
do task::spawn() |move f| {
f();
c.send(());
let f = f();
loop {
match f.read_word() {
- Some(w) => { emit(w, 1); }
+ Some(w) => { emit(&w, 1); }
None => { break; }
}
}
}
-fn reduce(&&word: ~str, get: map_reduce::getter<int>) {
+fn reduce(word: &~str, get: map_reduce::getter<int>) {
let mut count = 0;
loop { match get() { Some(_) => { count += 1; } None => { break; } } }
- io::println(fmt!("%s\t%?", word, count));
+ io::println(fmt!("%s\t%?", *word, count));
}
struct box<T> {
export reducer;
export map_reduce;
- type putter<K: Send, V: Send> = fn(K, V);
+ type putter<K: Send, V: Send> = fn(&K, V);
type mapper<K1: Send, K2: Send, V: Send> = fn~(K1, putter<K2, V>);
type getter<V: Send> = fn() -> Option<V>;
- type reducer<K: Copy Send, V: Copy Send> = fn~(K, getter<V>);
+ type reducer<K: Copy Send, V: Copy Send> = fn~(&K, getter<V>);
enum ctrl_proto<K: Copy Send, V: Copy Send> {
find_reducer(K, Chan<Chan<reduce_proto<V>>>),
fn start_mappers<K1: Copy Send, K2: Hash IterBytes Eq Const Copy Send,
V: Copy Send>(
- map: mapper<K1, K2, V>,
- &ctrls: ~[ctrl_proto::server::open<K2, V>],
- inputs: ~[K1])
+ map: &mapper<K1, K2, V>,
+ ctrls: &mut ~[ctrl_proto::server::open<K2, V>],
+ inputs: &~[K1])
-> ~[joinable_task]
{
let mut tasks = ~[];
let (ctrl, ctrl_server) = ctrl_proto::init();
let ctrl = box(ctrl);
let i = copy *i;
- tasks.push(spawn_joinable(|move i| map_task(map, ctrl, i)));
+ let m = copy *map;
+ tasks.push(spawn_joinable(|move i| map_task(m, &ctrl, i)));
ctrls.push(ctrl_server);
}
return tasks;
fn map_task<K1: Copy Send, K2: Hash IterBytes Eq Const Copy Send, V: Copy Send>(
map: mapper<K1, K2, V>,
- ctrl: box<ctrl_proto::client::open<K2, V>>,
+ ctrl: &box<ctrl_proto::client::open<K2, V>>,
input: K1)
{
// log(error, "map_task " + input);
- let intermediates = map::HashMap();
+ let intermediates: HashMap<K2, Chan<reduce_proto<V>>>
+ = map::HashMap();
- do map(input) |key, val| {
+ do map(input) |key: &K2, val| {
let mut c = None;
- let found = intermediates.find(key);
+ let found: Option<Chan<reduce_proto<V>>>
+ = intermediates.find(*key);
match found {
Some(_c) => { c = Some(_c); }
None => {
do ctrl.swap |ctrl| {
- let ctrl = ctrl_proto::client::find_reducer(ctrl, key);
+ let ctrl = ctrl_proto::client::find_reducer(ctrl, *key);
match pipes::recv(ctrl) {
ctrl_proto::reducer(c_, ctrl) => {
c = Some(c_);
}
}
}
- intermediates.insert(key, c.get());
+ intermediates.insert(*key, c.get());
send(c.get(), addref);
}
}
}
fn reduce_task<K: Copy Send, V: Copy Send>(
- reduce: reducer<K, V>,
+ reduce: ~reducer<K, V>,
key: K,
out: Chan<Chan<reduce_proto<V>>>)
{
let p = Port();
- send(out, Chan(p));
+ send(out, Chan(&p));
let mut ref_count = 0;
let mut is_done = false;
fn get<V: Copy Send>(p: Port<reduce_proto<V>>,
- &ref_count: int, &is_done: bool)
+ ref_count: &mut int, is_done: &mut bool)
-> Option<V> {
- while !is_done || ref_count > 0 {
+ while !*is_done || *ref_count > 0 {
match recv(p) {
emit_val(v) => {
// error!("received %d", v);
}
done => {
// error!("all done");
- is_done = true;
+ *is_done = true;
}
- addref => { ref_count += 1; }
- release => { ref_count -= 1; }
+ addref => { *ref_count += 1; }
+ release => { *ref_count -= 1; }
}
}
return None;
}
- reduce(key, || get(p, ref_count, is_done) );
+ (*reduce)(&key, || get(p, &mut ref_count, &mut is_done) );
}
fn map_reduce<K1: Copy Send, K2: Hash IterBytes Eq Const Copy Send, V: Copy Send>(
// to do the rest.
let reducers = map::HashMap();
- let mut tasks = start_mappers(map, ctrl, inputs);
+ let mut tasks = start_mappers(&map, &mut ctrl, &inputs);
let mut num_mappers = vec::len(inputs) as int;
while num_mappers > 0 {
None => {
// log(error, "creating new reducer for " + k);
let p = Port();
- let ch = Chan(p);
+ let ch = Chan(&p);
let r = reduce, kk = k;
- tasks.push(spawn_joinable(|| reduce_task(r, kk, ch) ));
+ tasks.push(spawn_joinable(|| reduce_task(~r, kk, ch) ));
c = recv(p);
reducers.insert(k, c);
}
}
}
-fn main(++argv: ~[~str]) {
+fn main() {
+ let argv = os::args();
if vec::len(argv) < 2u && !os::getenv(~"RUST_BENCH").is_some() {
let out = io::stdout();
-// error-pattern:expected `extern fn(++v: ~[~str])
+// error-pattern:expected `fn()
fn main(x: int) { }
borrow(v);
}
-fn borrow_from_arg_mut_ref(&v: ~int) {
- borrow(v); //~ ERROR illegal borrow unless pure
+fn borrow_from_arg_mut_ref(v: &mut ~int) {
+ borrow(*v); //~ ERROR illegal borrow unless pure
//~^ NOTE impure due to access to impure function
}
#[forbid(deprecated_mode)];
-fn foo(_f: fn(&i: int)) { //~ ERROR explicit mode
+fn foo(_f: fn(&i: int)) { //~ ERROR by-mutable-reference mode
}
-type Bar = fn(&i: int); //~ ERROR explicit mode
+type Bar = fn(&i: int); //~ ERROR by-mutable-reference mode
fn main() {
}
\ No newline at end of file
enum bottom { }
fn main() {
- let x = ptr::p2::addr_of(&()) as *bottom;
+ let x = ptr::addr_of(&()) as *bottom;
match x { } //~ ERROR non-exhaustive patterns
}
extern mod std;
use cmp::Eq;
-fn f<T:Eq>(&o: Option<T>) {
- assert o == option::None;
+fn f<T:Eq>(o: &mut Option<T>) {
+ assert *o == option::None;
}
fn main() {
- f::<int>(option::None);
+ f::<int>(&mut option::None);
//~^ ERROR illegal borrow: creating mutable alias to static item
}
-fn f1(&x: int) {
- x = 1; // no error
+fn f1(x: &mut int) {
+ *x = 1; // no error
}
fn f2() {
take(x); //~ ERROR illegal move from argument `x`, which is not copy or move mode
}
-fn from_by_mut_ref_arg(&x: int) {
- take(x); //~ ERROR illegal move from argument `x`, which is not copy or move mode
-}
-
fn from_by_ref_arg(&&x: int) {
take(x); //~ ERROR illegal move from argument `x`, which is not copy or move mode
}
//~^ WARNING unused variable: `x`
}
-fn f1b(&x: int) {
+fn f1b(x: &mut int) {
//~^ WARNING unused variable: `x`
}
// Note: it would be nice to give fewer warnings in these cases.
-fn mutate_by_mut_ref(&x: uint) {
- x = 0u;
+fn mutate_by_mut_ref(x: &mut uint) {
+ *x = 0;
}
fn mutate_by_ref(&&x: uint) {
//~^ WARNING unused variable: `x`
- x = 0u; //~ ERROR assigning to argument
+ x = 0; //~ ERROR assigning to argument
}
fn mutate_by_val(++x: uint) {
//~^ WARNING unused variable: `x`
- x = 0u; //~ ERROR assigning to argument
+ x = 0; //~ ERROR assigning to argument
}
fn mutate_by_copy(+x: uint) {
//~^ WARNING unused variable: `x`
- x = 0u; //~ ERROR assigning to argument
+ x = 0; //~ ERROR assigning to argument
//~^ WARNING value assigned to `x` is never read
}
fn mutate_by_move(-x: uint) {
//~^ WARNING unused variable: `x`
- x = 0u; //~ ERROR assigning to argument
+ x = 0; //~ ERROR assigning to argument
//~^ WARNING value assigned to `x` is never read
}
fn main() {
- let x : *~[int] = ptr::p2::addr_of(&~[1,2,3]);
+ let x : *~[int] = ptr::addr_of(&~[1,2,3]);
let y : *libc::c_void = x as *libc::c_void;
unsafe {
let _z = *y;
-//error-pattern: mismatched types
+//error-pattern: by-mutable-reference mode
fn bad(&a: int) {
}
-// unnamed argument &int is now parsed x: &int
-// it's not parsed &x: int anymore
-
fn called(f: fn(&int)) {
}
fn main() {
let cat = ~"kitty";
let po = comm::Port(); //~ ERROR missing `send`
- let ch = comm::Chan(po); //~ ERROR missing `send`
+ let ch = comm::Chan(&po); //~ ERROR missing `send`
comm::send(ch, foo(42, @cat)); //~ ERROR missing `send`
}
fn call_it<B: TraitB>(b: B) -> int {
let y = 4u;
- b.gimme_an_a(y) //~ ERROR failed to find an implementation of trait @TraitA for uint
+ b.gimme_an_a(y) //~ ERROR failed to find an implementation of trait @TraitA
}
fn main() {
// Tests that the type argument in port gets
// visited
let p = Port::<T>();
- send(oc, Chan(p));
+ send(oc, Chan(&p));
let x = recv(p);
send(c, x);
// xfail-fast
#[legacy_modes];
-fn f1(a: {mut x: int}, &b: int, -c: int) -> int {
- let r = a.x + b + c;
+fn f1(a: {mut x: int}, b: &mut int, -c: int) -> int {
+ let r = a.x + *b + c;
a.x = 0;
- b = 10;
+ *b = 10;
return r;
}
fn main() {
let mut a = {mut x: 1}, b = 2, c = 3;
- assert (f1(a, b, c) == 6);
+ assert (f1(a, &mut b, c) == 6);
assert (a.x == 0);
assert (b == 10);
assert (f2(a.x, |x| a.x = 50 ) == 0);
+++ /dev/null
-fn main(++args: ~[~str]) {
- let vs: ~[~str] = ~[~"hi", ~"there", ~"this", ~"is", ~"a", ~"vec"];
- let vvs: ~[~[~str]] = ~[args, vs];
- for vvs.each |vs| { for vs.each |s| { log(debug, *s); } }
-}
fn main() {
let p = Port();
- let ch = Chan(p);
+ let ch = Chan(&p);
task::spawn(|| a(ch) );
task::spawn(|| a(ch) );
let mut n: int = 0;
fn main() {
let p = Port();
- let ch = Chan(p);
+ let ch = Chan(&p);
task::spawn(|| a(ch) );
task::spawn(|| b(ch) );
let mut n: int = 0;
let mut n: int = 2 + 3 * 7;
let s: ~str = ~"hello there";
let p = comm::Port();
- let ch = comm::Chan(p);
+ let ch = comm::Chan(&p);
task::spawn(|| a(ch) );
task::spawn(|| b(ch) );
let mut x: int = 10;
fn foo(&&x: ()) -> Port<()> {
let p = Port();
- let c = Chan(p);
+ let c = Chan(&p);
do task::spawn() |copy c, copy x| {
c.send(x);
}
fn request_task(c: Chan<ctx>) {
let p = Port();
- send(c, Chan(p));
+ send(c, Chan(&p));
let mut req: request;
req = recv(p);
// Need to drop req before receiving it again
fn new_cx() -> ctx {
let p = Port();
- let ch = Chan(p);
+ let ch = Chan(&p);
let t = task::spawn(|| request_task(ch) );
let mut cx: ctx;
cx = recv(p);
let cx = new_cx();
let p = Port::<bool>();
- send(cx, close(Chan(p)));
+ send(cx, close(Chan(&p)));
send(cx, quit);
}
fn main() {
let p = comm::Port();
- let ch = comm::Chan(p);
+ let ch = comm::Chan(&p);
let t = task::spawn(|| child(ch) );
let y = recv(p);
error!("received");
+++ /dev/null
-
-
-fn main(++args: ~[~str]) { log(debug, args[0]); }
fn main() {
let po = Port();
- let ch = Chan(po);
+ let ch = Chan(&po);
send(ch, 10);
let i = recv(po);
assert (i == 10);
-fn f(i: int, &called: bool) {
+fn f(i: int, called: &mut bool) {
assert i == 10;
- called = true;
+ *called = true;
}
-fn g(f: extern fn(int, &v: bool), &called: bool) {
+fn g(f: extern fn(int, v: &mut bool), called: &mut bool) {
f(10, called);
}
fn main() {
let mut called = false;
let h = f;
- g(h, called);
+ g(h, &mut called);
assert called == true;
}
\ No newline at end of file
None => {
let p = Port();
error!("sending find_reducer");
- send(ctrl, find_reducer(str::to_bytes(key), Chan(p)));
+ send(ctrl, find_reducer(str::to_bytes(key), Chan(&p)));
error!("receiving");
c = recv(p);
log(error, c);
reducers = map::HashMap();
- start_mappers(Chan(ctrl), inputs);
+ start_mappers(Chan(&ctrl), inputs);
let mut num_mappers = vec::len(inputs) as int;
#[abi = "rust-intrinsic"]
extern mod rusti {
#[legacy_exports];
- fn move_val_init<T>(&dst: T, -src: T);
- fn move_val<T>(&dst: T, -src: T);
+ fn move_val_init<T>(dst: &mut T, -src: T);
+ fn move_val<T>(dst: &mut T, -src: T);
}
fn main() {
let mut x = @1;
let mut y = @2;
- rusti::move_val(y, x);
+ rusti::move_val(&mut y, x);
assert *y == 1;
}
\ No newline at end of file
fn main() {
let p = comm::Port();
- let ch = Chan(p);
+ let ch = Chan(&p);
task::spawn(|| child(ch) );
fn packager(cb: Chan<Chan<~[u8]>>, msg: Chan<msg>) {
let p: Port<~[u8]> = Port();
- send(cb, Chan(p));
+ send(cb, Chan(&p));
loop {
debug!("waiting for bytes");
let data = recv(p);
fn main() {
let p: Port<msg> = Port();
- let ch = Chan(p);
+ let ch = Chan(&p);
let recv_reader: Port<Chan<~[u8]>> = Port();
- let recv_reader_chan = Chan(recv_reader);
+ let recv_reader_chan = Chan(&recv_reader);
let pack = task::spawn(|| packager(recv_reader_chan, ch) );
let source_chan: Chan<~[u8]> = recv(recv_reader);
fn doit() {
fn b(c: Chan<Chan<int>>) {
let p = Port();
- send(c, Chan(p));
+ send(c, Chan(&p));
}
let p = Port();
- let ch = Chan(p);
+ let ch = Chan(&p);
spawn(|| b(ch) );
recv(p);
}
fn main() {
let p: Port<~[u8]> = Port();
- let ch = Chan(p);
+ let ch = Chan(&p);
let prod = task::spawn(|| producer(ch) );
let data: ~[u8] = recv(p);
-fn incr(&x: int) -> bool { x += 1; assert (false); return false; }
+fn incr(x: &mut int) -> bool { *x += 1; assert (false); return false; }
fn main() {
let x = 1 == 2 || 3 == 3;
assert (x);
let mut y: int = 10;
- log(debug, x || incr(y));
+ log(debug, x || incr(&mut y));
assert (y == 10);
if true && x { assert (true); } else { assert (false); }
}
fn main() {
let p = Port();
- let ch = Chan(p);
+ let ch = Chan(&p);
let mut y: int;
task::spawn(|| child(ch) );
+++ /dev/null
-fn main(++args: ~[~str]) { for args.each |s| { log(debug, *s); } }
comm::send(parent, 0);
} else {
let p = comm::Port();
- let ch = comm::Chan(p);
+ let ch = comm::Chan(&p);
let child = task::spawn(|| sub(ch, id - 1) );
let y = comm::recv(p);
comm::send(parent, y + 1);
fn main() {
let p = comm::Port();
- let ch = comm::Chan(p);
+ let ch = comm::Chan(&p);
let child = task::spawn(|| sub(ch, 200) );
let y = comm::recv(p);
debug!("transmission complete");
// -*- rust -*-
extern mod std;
-fn grow(&v: ~[int]) { v += ~[1]; }
+fn grow(v: &mut ~[int]) { *v += ~[1]; }
fn main() {
let mut v: ~[int] = ~[];
- grow(v);
- grow(v);
- grow(v);
+ grow(&mut v);
+ grow(&mut v);
+ grow(&mut v);
let len = vec::len::<int>(v);
log(debug, len);
assert (len == 3 as uint);
+// xfail-pretty
+// FIXME #3654
+
mod a {
pub fn f() {}
pub fn g() {}
// assertions.
fn test_init() {
let myport = Port();
- let mychan = Chan(myport);
+ let mychan = Chan(&myport);
let val: record = {val1: 0u32, val2: 0u32, val3: 0u32};
send(mychan, val);
}
// Don't trigger any assertions.
fn test_grow() {
let myport = Port();
- let mychan = Chan(myport);
+ let mychan = Chan(&myport);
for uint::range(0u, 100u) |i| {
let val: record = {val1: 0u32, val2: 0u32, val3: 0u32};
comm::send(mychan, val);
// Don't allow the buffer to shrink below it's original size
fn test_shrink1() {
let myport = Port();
- let mychan = Chan(myport);
+ let mychan = Chan(&myport);
send(mychan, 0i8);
let x = recv(myport);
}
fn test_shrink2() {
let myport = Port();
- let mychan = Chan(myport);
+ let mychan = Chan(&myport);
for uint::range(0u, 100u) |_i| {
let val: record = {val1: 0u32, val2: 0u32, val3: 0u32};
send(mychan, val);
// Test rotating the buffer when the unit size is not a power of two
fn test_rotate() {
let myport = Port();
- let mychan = Chan(myport);
+ let mychan = Chan(&myport);
for uint::range(0u, 100u) |i| {
let val = {val1: i as u32, val2: i as u32, val3: i as u32};
send(mychan, val);
// the unit size is not a power of two
fn test_rotate_grow() {
let myport = Port::<record>();
- let mychan = Chan(myport);
+ let mychan = Chan(&myport);
for uint::range(0u, 10u) |j| {
for uint::range(0u, 10u) |i| {
let val: record =
fn main() unsafe {
let po = comm::Port();
- let ch = comm::Chan(po);
+ let ch = comm::Chan(&po);
let parent_sched_id = rustrt::rust_get_sched_id();
error!("parent %?", parent_sched_id);
let num_threads = 1u;
fn iloop() {
task::spawn(|| die() );
let p = comm::Port::<()>();
- let c = comm::Chan(p);
+ let c = comm::Chan(&p);
loop {
// Sending and receiving here because these actions yield,
// at which point our child can kill us
fn main() {
let p = Port();
- let c = Chan(p);
+ let c = Chan(&p);
do spawn() {
let p = Port();
- c.send(Chan(p));
+ c.send(Chan(&p));
let _r = p.recv();
}
fn cache_server<K: Send, V: Send>(c: Chan<Chan<command<K, V>>>) {
let ctrl = Port();
- send(c, Chan(ctrl));
+ send(c, Chan(&ctrl));
}
fn main() { }
fn main() {
let po = comm::Port::<foo>();
- let ch = comm::Chan(po);
+ let ch = comm::Chan(&po);
comm::send(ch, foo(42, 'c'));
}
\ No newline at end of file
fn main() {
let p = comm::Port::<int>();
- let ch = comm::Chan(p);
+ let ch = comm::Chan(&p);
task::spawn(|| iotask(ch, ~"localhost") );
}
fn main() {
let p = comm::Port();
- let c = comm::Chan(p);
+ let c = comm::Chan(&p);
comm::send(c, ~"coffee");
}
\ No newline at end of file
fn main() {
let p = comm::Port();
- let c = comm::Chan(p);
+ let c = comm::Chan(&p);
comm::send(c, ~"coffee");
}
\ No newline at end of file
fn main() {
let c = {
let p = comm::Port();
- comm::Chan(p)
+ comm::Chan(&p)
};
comm::send(c, ~"coffee");
}
\ No newline at end of file
fn starbase() {
for int::range(0, 10) |_i| {
let p = comm::Port();
- let c = comm::Chan(p);
+ let c = comm::Chan(&p);
task::spawn(|| starship(c) );
task::yield();
}
// or not this is desirable I don't know, but here's a regression test.
fn main() {
let po = comm::Port();
- let ch = comm::Chan(po);
+ let ch = comm::Chan(&po);
comm::send(ch, ());
let n: () = comm::recv(po);
assert (n == ());
debug!("Creating tasks");
let po = Port();
- let ch = Chan(po);
+ let ch = Chan(&po);
let mut i: int = 0;
fn test02() {
let p = Port();
- let c = Chan(p);
+ let c = Chan(&p);
debug!("Writing to a local task channel.");
send(c, 42);
debug!("Reading from a local task port.");
fn test05() {
let po = comm::Port();
- let ch = Chan(po);
+ let ch = Chan(&po);
task::spawn(|| test05_start(ch) );
let mut value: int;
value = recv(po);
*b = true;
}
let p = comm::Port();
- let c = comm::Chan(p);
+ let c = comm::Chan(&p);
do task::spawn_unlinked { wrapper(c, copy f) };
p
}
fn main() {
let p = comm::Port::<uint>();
- let ch = comm::Chan(p);
+ let ch = comm::Chan(&p);
let x = ~1;
let x_in_parent = ptr::addr_of(&(*x)) as uint;
--- /dev/null
+// xfail-fast
+// xfail-test
+
+// Broken on 32 bit, I guess?
+
+trait Foo {
+ fn f();
+}
+
+trait Bar : Foo {
+ fn g();
+}
+
+struct A {
+ x: int
+}
+
+impl A : Bar {
+ fn g() { io::println("in g"); }
+ fn f() { io::println("in f"); }
+}
+
+fn h<T:Foo>(a: &T) {
+ a.f();
+}
+
+fn main() {
+ let a = A { x: 3 };
+ h(&a);
+}
+
--- /dev/null
+trait Foo {
+ fn f() -> int;
+}
+
+struct A {
+ x: int
+}
+
+impl A : Foo {
+ fn f() -> int {
+ io::println(~"Today's number is " + self.x.to_str());
+ return self.x;
+ }
+}
+
+fn main() {
+ let a = A { x: 3 };
+ let b = (&a) as &Foo;
+ assert b.f() == 3;
+}
+
-fn f(&i: ~int) {
- i = ~200;
+fn f(i: &mut ~int) {
+ *i = ~200;
}
fn main() {
let mut i = ~100;
- f(i);
+ f(&mut i);
assert *i == 200;
}
\ No newline at end of file
fn main() {
let p = comm::Port();
- let ch = comm::Chan(p);
+ let ch = comm::Chan(&p);
let n = 100u;
let mut expected = 0u;
for uint::range(0u, n) |i| {
fn main() {
let p = comm::Port();
- let c = comm::Chan(p);
+ let c = comm::Chan(&p);
comm::send(c, ~100);
let v = comm::recv(p);
assert v == ~100;
fn main() {
let p = comm::Port();
- let c = comm::Chan(p);
+ let c = comm::Chan(&p);
task::spawn_unlinked(|| f(c) );
error!("hiiiiiiiii");
assert comm::recv(p);
// -*- rust -*-
type point = {x: int, y: int, mut z: int};
-fn f(&p: point) { p.z = 13; }
+fn f(p: &mut point) { p.z = 13; }
fn main() {
let mut x: point = {x: 10, y: 11, mut z: 12};
- f(x);
+ f(&mut x);
assert (x.z == 13);
}