Manual merge of #22475 - alexcrichton:rollup, r=alexcrichton

One windows bot failed spuriously.
This commit is contained in:
Huon Wilson 2015-02-18 23:50:21 +11:00
commit dfc5c0f1e8
381 changed files with 6886 additions and 3250 deletions

View file

@ -1,60 +1,156 @@
## How to submit a bug report
# Contributing to Rust
If you're just reporting a bug, please see:
Thank you for your interest in contributing to Rust! There are many ways to
contribute, and we appreciate all of them. This document is a bit long, so here's
links to the major sections:
http://doc.rust-lang.org/complement-bugreport.html
* [Feature Requests](#feature-requests)
* [Bug Reports](#bug-reports)
* [Pull Requests](#pull-requests)
* [Writing Documentation](#writing-documentation)
* [Issue Triage](#issue-triage)
* [Out-of-tree Contributions](#out-of-tree-contributions)
## Submitting an issue
If you have questions, please make a post on [internals.rust-lang.org][internals] or
hop on [#rust-internals][pound-rust-internals].
Please submit issues here for bug reports or implementation details. For feature
requests, language changes, or major changes to the libraries, please submit an
issue against the [RFCs repository](https://github.com/rust-lang/rfcs).
## Pull request procedure
Pull requests should be targeted at Rust's `master` branch.
Before pushing to your Github repo and issuing the pull request,
please do two things:
1. [Rebase](http://git-scm.com/book/en/Git-Branching-Rebasing) your
local changes against the `master` branch. Resolve any conflicts
that arise.
2. Run the full Rust test suite with the `make check` command. You're
not off the hook even if you just stick to documentation; code
examples in the docs are tested as well! Although for simple
wording or grammar fixes, this is probably unnecessary.
Pull requests will be treated as "review requests", and we will give
feedback we expect to see corrected on
[style](http://aturon.github.io/) and
substance before pulling. Changes contributed via pull request should
focus on a single issue at a time, like any other. We will not accept
pull-requests that try to "sneak" unrelated changes in.
Normally, all pull requests must include regression tests (see
[Note-testsuite](https://github.com/rust-lang/rust/wiki/Note-testsuite))
that test your change. Occasionally, a change will be very difficult
to test for. In those cases, please include a note in your commit
message explaining why.
In the licensing header at the beginning of any files you change,
please make sure the listed date range includes the current year. For
example, if it's 2014, and you change a Rust file that was created in
2010, it should begin:
```
// Copyright 2010-2014 The Rust Project Developers.
```
# Coordination and communication
Get feedback from other developers on
[internals.rust-lang.org][internals], and
[#rust-internals][pound-rust-internals].
As a reminder, all contributors are expected to follow our [Code of Conduct](coc).
[pound-rust-internals]: http://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust-internals
[internals]: http://internals.rust-lang.org
[coc]: http://www.rust-lang.org/conduct.html
For more details, please refer to
[Note-development-policy](https://github.com/rust-lang/rust/wiki/Note-development-policy).
## Feature Requests
To request a change to the way that the Rust language works, please open an
issue in the [RFCs repository](https://github.com/rust-lang/rfcs/issues/new)
rather than this one. New features and other significant language changes
must go through the RFC process.
## Bug Reports
While bugs are unfortunate, they're a reality in software. We can't fix what we
don't know about, so please report liberally. If you're not sure if something
is a bug or not, feel free to file a bug anyway.
If you have the chance, before reporting a bug, please [search existing
issues](https://github.com/rust-lang/rust/search?q=&type=Issues&utf8=%E2%9C%93),
as it's possible that someone else has already reported your error. This doesn't
always work, and sometimes it's hard to know what to search for, so consider this
extra credit. We won't mind if you accidentally file a duplicate report.
Opening an issue is as easy as following [this
link](https://github.com/rust-lang/rust/issues/new) and filling out the fields.
Here's a template that you can use to file a bug, though it's not necessary to
use it exactly:
<short summary of the bug>
I tried this code:
<code sample that causes the bug>
I expected to see this happen: <explanation>
Instead, this happened: <explanation>
## Meta
`rustc --version --verbose`:
Backtrace:
All three components are important: what you did, what you expected, what
happened instead. Please include the output of `rustc --version --verbose`,
which includes important information about what platform you're on, what
version of Rust you're using, etc.
Sometimes, a backtrace is helpful, and so including that is nice. To get
a backtrace, set the `RUST_BACKTRACE` environment variable. The easiest way
to do this is to invoke `rustc` like this:
```bash
$ RUST_BACKTRACE=1 rustc ...
```
## Pull Requests
Pull requests are the primary mechanism we use to change Rust. GitHub itself
has some [great documentation][pull-requests] on using the Pull Request
feature. We use the 'fork and pull' model described there.
[pull-requests]: https://help.github.com/articles/using-pull-requests/
Please make pull requests against the `master` branch.
All pull requests are reviewed by another person. We have a bot,
@rust-highfive, that will automatically assign a random person to review your request.
If you want to request that a specific person reviews your pull request,
you can add an `r?` to the message. For example, Steve usually reviews
documentation changes. So if you were to make a documentation change, add
r? @steveklabnik
to the end of the message, and @rust-highfive will assign @steveklabnik instead
of a random person. This is entirely optional.
After someone has reviewed your pull request, they will leave an annotation
on the pull request with an `r+`. It will look something like this:
@bors: r+ 38fe8d2
This tells @bors, our lovable integration bot, that your pull request has
been approved. The PR then enters the [merge queue][merge-queue], where @bors
will run all the tests on every platform we support. If it all works out,
@bors will merge your code into `master` and close the pull request.
[merge-queue]: http://buildbot.rust-lang.org/homu/queue/rust
## Writing Documentation
Documentation improvements are very welcome. The source of `doc.rust-lang.org`
is located in `src/doc` in the tree, and standard API documentation is generated
from the source code itself.
Documentation pull requests function in the same as other pull requests, though
you may see a slightly different form of `r+`:
@bors: r+ 38fe8d2 rollup
That additional `rollup` tells @bors that this change is eligible for a 'rollup'.
To save @bors some work, and to get small changes through more quickly, when
@bors attempts to merge a commit that's rollup-eligible, it will also merge
the other rollup-eligible patches too, and they'll get tested and merged at
the same time.
## Issue Triage
Sometimes, an issue will stay open, even though the bug has been fixed. And
sometimes, the original bug may go stale because something has changed in the
meantime.
It can be helpful to go through older bug reports and make sure that they are
still valid. Load up an older issue, double check that it's still true, and
leave a comment letting us know if it is or is not. The [least recently updated sort][lru] is good for finding issues like this.
[lru]: https://github.com/rust-lang/rust/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-asc
## Out-of-tree Contributions
There are a number of other ways to contribute to Rust that don't deal with
this repository.
Answer questions in [#rust][pound-rust], or on [users.rust-lang.org][users],
or on [StackOverflow][so].
Participate in the [RFC process](https://github.com/rust-lang/rfcs).
Find a [requested community library][community-library], build it, and publish
it to [Crates.io](http://crates.io). Easier said than done, but very, very
valuable!
[pound-rust]: http://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust
[users]: http://users.rust-lang.org/
[so]: http://stackoverflow.com/questions/tagged/rust
[community-library]: https://github.com/rust-lang/rfcs/labels/A-community-library

View file

@ -18,6 +18,7 @@ Read ["Installing Rust"][install] from [The Book][trpl].
* GNU `make` 3.81 or later
* `curl`
* `git`
2. Download and build Rust:
You can either download a [tarball] or build directly from the [repo].
@ -97,19 +98,21 @@ There is a lot more documentation in the [wiki].
[wiki]: https://github.com/rust-lang/rust/wiki
## Getting help and getting involved
## Getting help
The Rust community congregates in a few places:
* [StackOverflow] - Direct questions about using the language here.
* [users.rust-lang.org] - General discussion, broader questions.
* [internals.rust-lang.org] - For development of the Rust language itself.
* [/r/rust] - News and general discussion.
[StackOverflow]: http://stackoverflow.com/questions/tagged/rust
[/r/rust]: http://reddit.com/r/rust
[users.rust-lang.org]: http://users.rust-lang.org/
[internals.rust-lang.org]: http://internals.rust-lang.org/
## Contributing
To contribute to Rust, please see [CONTRIBUTING.md](CONTRIBUTING.md).
## License

View file

@ -25,7 +25,7 @@
# L10N_LANGS are the languages for which the docs have been
# translated.
######################################################################
DOCS := index intro tutorial complement-bugreport \
DOCS := index intro tutorial \
complement-lang-faq complement-design-faq complement-project-faq \
rustdoc reference grammar
@ -73,7 +73,7 @@ RUSTBOOK = $(RPATH_VAR2_T_$(CFG_BUILD)_H_$(CFG_BUILD)) $(RUSTBOOK_EXE)
D := $(S)src/doc
DOC_TARGETS := trpl
DOC_TARGETS := trpl style
COMPILER_DOC_TARGETS :=
DOC_L10N_TARGETS :=
@ -275,3 +275,9 @@ trpl: doc/book/index.html
doc/book/index.html: $(RUSTBOOK_EXE) $(wildcard $(S)/src/doc/trpl/*.md) | doc/
$(Q)rm -rf doc/book
$(Q)$(RUSTBOOK) build $(S)src/doc/trpl doc/book
style: doc/style/index.html
doc/style/index.html: $(RUSTBOOK_EXE) $(wildcard $(S)/src/doc/style/*.md) | doc/
$(Q)rm -rf doc/style
$(Q)$(RUSTBOOK) build $(S)src/doc/style doc/style

View file

@ -13,8 +13,8 @@
#![feature(box_syntax)]
#![feature(collections)]
#![feature(int_uint)]
#![feature(io)]
#![feature(path)]
#![feature(old_io)]
#![feature(old_path)]
#![feature(rustc_private)]
#![feature(unboxed_closures)]
#![feature(std_misc)]

View file

@ -35,7 +35,7 @@
use std::iter::repeat;
use std::str;
use std::string::String;
use std::thread::Thread;
use std::thread;
use std::time::Duration;
use test::MetricMap;
@ -458,7 +458,7 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) {
loop {
//waiting 1 second for gdbserver start
timer::sleep(Duration::milliseconds(1000));
let result = Thread::scoped(move || {
let result = thread::spawn(move || {
tcp::TcpStream::connect("127.0.0.1:5039").unwrap();
}).join();
if result.is_err() {

View file

@ -1,61 +0,0 @@
% How to submit a Rust bug report
# I think I found a bug in the compiler!
If you see this message: `error: internal compiler error: unexpected panic`,
then you have definitely found a bug in the compiler. It's also possible that
your code is not well-typed, but if you saw this message, it's still a bug in
error reporting.
If you see a message about an LLVM assertion failure, then you have also
definitely found a bug in the compiler. In both of these cases, it's not your
fault and you should report a bug!
If you see a compiler error message that you think is meant for users to see,
but it confuses you, *that's a bug too*. If it wasn't clear to you, then it's
an error message we want to improve, so please report it so that we can try
to make it better.
# How do I know the bug I found isn't a bug that already exists in the issue tracker?
If you don't have enough time for a search, then don't worry about that. Just submit
the bug. If it's a duplicate, somebody will notice that and close it during triage.
If you have the time for it, it would be useful to type the text of the error
message you got [into the issue tracker search box](https://github.com/rust-lang/rust/issues)
to see if there's an existing bug that resembles your problem. If there is,
and it's an open bug, you can comment on that issue and say you are also affected.
This will encourage the devs to fix it. But again, don't let this stop you from
submitting a bug. We'd rather have to do the work of closing duplicates than
miss out on valid bug reports.
# What information should I include in a bug report?
It generally helps our diagnosis to include your specific OS (for example: Mac OS X 10.8.3,
Windows 7, Ubuntu 12.04) and your hardware architecture (for example: i686, x86_64).
It's also helpful to provide the exact version and host by copying the output of
re-running the erroneous rustc command with the `--version --verbose` flags, which will
produce something like this:
```text
rustc 0.12.0 (ba4081a5a 2014-10-07 13:44:41 -0700)
binary: rustc
commit-hash: ba4081a5a8573875fed17545846f6f6902c8ba8d
commit-date: 2014-10-07 13:44:41 -0700
host: i686-apple-darwin
release: 0.12.0
```
Finally, if you can also provide a backtrace, that'd be great. You can get a
backtrace by setting the `RUST_BACKTRACE` environment variable to `1`, like
this:
```bash
$ RUST_BACKTRACE=1 rustc ...
```
# I submitted a bug, but nobody has commented on it!
This is sad, but does happen sometimes, since we're short-staffed. If you submit a
bug and you haven't received a comment on it within 3 business days, it's entirely
reasonable to ask about the status of the bug in #rust on irc.mozilla.org.

View file

@ -2398,6 +2398,10 @@ The currently implemented features of the reference compiler are:
ways insufficient for concatenating identifiers, and may be
removed entirely for something more wholesome.
* `custom_attribute` - Allows the usage of attributes unknown to the compiler
so that new attributes can be added in a bacwards compatible
manner (RFC 572).
* `intrinsics` - Allows use of the "rust-intrinsics" ABI. Compiler intrinsics
are inherently unstable and no promise about them is made.
@ -2458,6 +2462,9 @@ The currently implemented features of the reference compiler are:
implemented very poorly and will likely change significantly
with a proper implementation.
* `rustc_attrs` - Gates internal `#[rustc_*]` attributes which may be
for internal use only or have meaning added to them in the future.
* `rustc_diagnostic_macros`- A mysterious feature, used in the implementation
of rustc, not meant for mortals.

64
src/doc/style/README.md Normal file
View file

@ -0,0 +1,64 @@
% Style Guidelines
This document collects the emerging principles, conventions, abstractions, and
best practices for writing Rust code.
Since Rust is evolving at a rapid pace, these guidelines are
preliminary. The hope is that writing them down explicitly will help
drive discussion, consensus and adoption.
Whenever feasible, guidelines provide specific examples from Rust's standard
libraries.
### Guideline statuses
Every guideline has a status:
* **[FIXME]**: Marks places where there is more work to be done. In
some cases, that just means going through the RFC process.
* **[FIXME #NNNNN]**: Like **[FIXME]**, but links to the issue tracker.
* **[RFC #NNNN]**: Marks accepted guidelines, linking to the rust-lang
RFC establishing them.
### Guideline stabilization
One purpose of these guidelines is to reach decisions on a number of
cross-cutting API and stylistic choices. Discussion and development of
the guidelines will happen primarily on http://discuss.rust-lang.org/,
using the Guidelines category. Discussion can also occur on the
[guidelines issue tracker](https://github.com/rust-lang/rust-guidelines).
Guidelines that are under development or discussion will be marked with the
status **[FIXME]**, with a link to the issue tracker when appropriate.
Once a concrete guideline is ready to be proposed, it should be filed
as an [FIXME: needs RFC](https://github.com/rust-lang/rfcs). If the RFC is
accepted, the official guidelines will be updated to match, and will
include the tag **[RFC #NNNN]** linking to the RFC document.
### What's in this document
This document is broken into four parts:
* **[Style](style/README.md)** provides a set of rules governing naming conventions,
whitespace, and other stylistic issues.
* **[Guidelines by Rust feature](features/README.md)** places the focus on each of
Rust's features, starting from expressions and working the way out toward
crates, dispensing guidelines relevant to each.
* **Topical guidelines and patterns**. The rest of the document proceeds by
cross-cutting topic, starting with
[Ownership and resources](ownership/README.md).
* **[APIs for a changing Rust](changing/README.md)**
discusses the forward-compatibility hazards, especially those that interact
with the pre-1.0 library stabilization process.
> **[FIXME]** Add cross-references throughout this document to the tutorial,
> reference manual, and other guides.
> **[FIXME]** What are some _non_-goals, _non_-principles, or _anti_-patterns that
> we should document?

54
src/doc/style/SUMMARY.md Normal file
View file

@ -0,0 +1,54 @@
# Summary
* [Style](style/README.md)
* [Whitespace](style/whitespace.md)
* [Comments](style/comments.md)
* [Braces, semicolons, commas](style/braces.md)
* [Naming](style/naming/README.md)
* [Ownership variants](style/naming/ownership.md)
* [Containers/wrappers](style/naming/containers.md)
* [Conversions](style/naming/conversions.md)
* [Iterators](style/naming/iterators.md)
* [Imports](style/imports.md)
* [Organization](style/organization.md)
* [Guidelines by Rust feature](features/README.md)
* [Let binding](features/let.md)
* [Pattern matching](features/match.md)
* [Loops](features/loops.md)
* [Functions and methods](features/functions-and-methods/README.md)
* [Input](features/functions-and-methods/input.md)
* [Output](features/functions-and-methods/output.md)
* [For convenience](features/functions-and-methods/convenience.md)
* [Types](features/types/README.md)
* [Conversions](features/types/conversions.md)
* [The newtype pattern](features/types/newtype.md)
* [Traits](features/traits/README.md)
* [For generics](features/traits/generics.md)
* [For objects](features/traits/objects.md)
* [For overloading](features/traits/overloading.md)
* [For extensions](features/traits/extensions.md)
* [For reuse](features/traits/reuse.md)
* [Common traits](features/traits/common.md)
* [Modules](features/modules.md)
* [Crates](features/crates.md)
* [Ownership and resources](ownership/README.md)
* [Constructors](ownership/constructors.md)
* [Builders](ownership/builders.md)
* [Destructors](ownership/destructors.md)
* [RAII](ownership/raii.md)
* [Cells and smart pointers](ownership/cell-smart.md)
* [Errors](errors/README.md)
* [Signaling](errors/signaling.md)
* [Handling](errors/handling.md)
* [Propagation](errors/propagation.md)
* [Ergonomics](errors/ergonomics.md)
* [Safety and guarantees](safety/README.md)
* [Using unsafe](safety/unsafe.md)
* [Library guarantees](safety/lib-guarantees.md)
* [Testing](testing/README.md)
* [Unit testing](testing/unit.md)
* [FFI, platform-specific code](platform.md)
* [APIs for a changing Rust](changing/README.md)
* [Pre-1.0 changes](changing/pre-1-0.md)
* [Post-1.0 changes](changing/post-1-0.md)
* [Timing unclear](changing/unclear.md)

View file

@ -0,0 +1,5 @@
% API design for a changing Rust
A number of planned Rust features will drastically affect the API design
story. This section collects some of the biggest features with concrete examples
of how the API will change.

View file

@ -0,0 +1,12 @@
% Post-1.0 changes
### Higher-kinded types
* A trait encompassing both `Iterable<T>` for some fixed `T` and
`FromIterator<U>` for _all_ `U` (where HKT comes in). The train
could provide e.g. a default `map` method producing the same kind of
the container, but with a new type parameter.
* **Monadic-generic programming**? Can we add this without deprecating
huge swaths of the API (including `Option::map`, `option::collect`,
`result::collect`, `try!` etc.

View file

@ -0,0 +1,17 @@
% Pre-1.0 changes
### `std` facade
We should revisit some APIs in `libstd` now that the facade effort is complete.
For example, the treatment of environment variables in the new
`Command` API is waiting on access to hashtables before being
approved.
### Trait reform
Potential for standard conversion traits (`to`, `into`, `as`).
Probably many other opportunities here.
### Unboxed closures

View file

@ -0,0 +1,28 @@
% Changes with unclear timing
### Associated items
* Many traits that currently take type parameters should instead use associated
types; this will _drastically_ simplify signatures in some cases.
* Associated constants would be useful in a few places, e.g. traits for
numerics, traits for paths.
### Anonymous, unboxed return types (aka `impl Trait` types)
* See https://github.com/rust-lang/rfcs/pull/105
* Could affect API design in several places, e.g. the `Iterator` trait.
### Default type parameters
We are already using this in a few places (e.g. `HashMap`), but it's
feature-gated.
### Compile-time function evaluation (CTFE)
https://github.com/mozilla/rust/issues/11621
### Improved constant folding
https://github.com/rust-lang/rust/issues/7834

View file

@ -0,0 +1,3 @@
% Errors
> **[FIXME]** Add some general text here.

View file

@ -0,0 +1,66 @@
% Ergonomic error handling
Error propagation with raw `Result`s can require tedious matching and
repackaging. This tedium is largely alleviated by the `try!` macro,
and can be completely removed (in some cases) by the "`Result`-`impl`"
pattern.
### The `try!` macro
Prefer
```rust
use std::io::{File, Open, Write, IoError};
struct Info {
name: String,
age: int,
rating: int
}
fn write_info(info: &Info) -> Result<(), IoError> {
let mut file = File::open_mode(&Path::new("my_best_friends.txt"),
Open, Write);
// Early return on error
try!(file.write_line(format!("name: {}", info.name).as_slice()));
try!(file.write_line(format!("age: {}", info.age).as_slice()));
try!(file.write_line(format!("rating: {}", info.rating).as_slice()));
return Ok(());
}
```
over
```rust
use std::io::{File, Open, Write, IoError};
struct Info {
name: String,
age: int,
rating: int
}
fn write_info(info: &Info) -> Result<(), IoError> {
let mut file = File::open_mode(&Path::new("my_best_friends.txt"),
Open, Write);
// Early return on error
match file.write_line(format!("name: {}", info.name).as_slice()) {
Ok(_) => (),
Err(e) => return Err(e)
}
match file.write_line(format!("age: {}", info.age).as_slice()) {
Ok(_) => (),
Err(e) => return Err(e)
}
return file.write_line(format!("rating: {}", info.rating).as_slice());
}
```
See
[the `result` module documentation](http://static.rust-lang.org/doc/master/std/result/index.html#the-try!-macro)
for more details.
### The `Result`-`impl` pattern [FIXME]
> **[FIXME]** Document the way that the `io` module uses trait impls
> on `IoResult` to painlessly propagate errors.

View file

@ -0,0 +1,7 @@
% Handling errors
### Use task isolation to cope with failure. [FIXME]
> **[FIXME]** Explain how to isolate tasks and detect task failure for recovery.
### Consuming `Result` [FIXME]

View file

@ -0,0 +1,8 @@
% Propagation
> **[FIXME]** We need guidelines on how to layer error information up a stack of
> abstractions.
### Error interoperation [FIXME]
> **[FIXME]** Document the `FromError` infrastructure.

View file

@ -0,0 +1,125 @@
% Signaling errors [RFC #236]
> The guidelines below were approved by [RFC #236](https://github.com/rust-lang/rfcs/pull/236).
Errors fall into one of three categories:
* Catastrophic errors, e.g. out-of-memory.
* Contract violations, e.g. wrong input encoding, index out of bounds.
* Obstructions, e.g. file not found, parse error.
The basic principle of the convention is that:
* Catastrophic errors and programming errors (bugs) can and should only be
recovered at a *coarse grain*, i.e. a task boundary.
* Obstructions preventing an operation should be reported at a maximally *fine
grain* -- to the immediate invoker of the operation.
## Catastrophic errors
An error is _catastrophic_ if there is no meaningful way for the current task to
continue after the error occurs.
Catastrophic errors are _extremely_ rare, especially outside of `libstd`.
**Canonical examples**: out of memory, stack overflow.
### For catastrophic errors, panic
For errors like stack overflow, Rust currently aborts the process, but
could in principle panic, which (in the best case) would allow
reporting and recovery from a supervisory task.
## Contract violations
An API may define a contract that goes beyond the type checking enforced by the
compiler. For example, slices support an indexing operation, with the contract
that the supplied index must be in bounds.
Contracts can be complex and involve more than a single function invocation. For
example, the `RefCell` type requires that `borrow_mut` not be called until all
existing borrows have been relinquished.
### For contract violations, panic
A contract violation is always a bug, and for bugs we follow the Erlang
philosophy of "let it crash": we assume that software *will* have bugs, and we
design coarse-grained task boundaries to report, and perhaps recover, from these
bugs.
### Contract design
One subtle aspect of these guidelines is that the contract for a function is
chosen by an API designer -- and so the designer also determines what counts as
a violation.
This RFC does not attempt to give hard-and-fast rules for designing
contracts. However, here are some rough guidelines:
* Prefer expressing contracts through static types whenever possible.
* It *must* be possible to write code that uses the API without violating the
contract.
* Contracts are most justified when violations are *inarguably* bugs -- but this
is surprisingly rare.
* Consider whether the API client could benefit from the contract-checking
logic. The checks may be expensive. Or there may be useful programming
patterns where the client does not want to check inputs before hand, but would
rather attempt the operation and then find out whether the inputs were invalid.
* When a contract violation is the *only* kind of error a function may encounter
-- i.e., there are no obstructions to its success other than "bad" inputs --
using `Result` or `Option` instead is especially warranted. Clients can then use
`unwrap` to assert that they have passed valid input, or re-use the error
checking done by the API for their own purposes.
* When in doubt, use loose contracts and instead return a `Result` or `Option`.
## Obstructions
An operation is *obstructed* if it cannot be completed for some reason, even
though the operation's contract has been satisfied. Obstructed operations may
have (documented!) side effects -- they are not required to roll back after
encountering an obstruction. However, they should leave the data structures in
a "coherent" state (satisfying their invariants, continuing to guarantee safety,
etc.).
Obstructions may involve external conditions (e.g., I/O), or they may involve
aspects of the input that are not covered by the contract.
**Canonical examples**: file not found, parse error.
### For obstructions, use `Result`
The
[`Result<T,E>` type](http://static.rust-lang.org/doc/master/std/result/index.html)
represents either a success (yielding `T`) or failure (yielding `E`). By
returning a `Result`, a function allows its clients to discover and react to
obstructions in a fine-grained way.
#### What about `Option`?
The `Option` type should not be used for "obstructed" operations; it
should only be used when a `None` return value could be considered a
"successful" execution of the operation.
This is of course a somewhat subjective question, but a good litmus
test is: would a reasonable client ever ignore the result? The
`Result` type provides a lint that ensures the result is actually
inspected, while `Option` does not, and this difference of behavior
can help when deciding between the two types.
Another litmus test: can the operation be understood as asking a
question (possibly with sideeffects)? Operations like `pop` on a
vector can be viewed as asking for the contents of the first element,
with the side effect of removing it if it exists -- with an `Option`
return value.
## Do not provide both `Result` and `panic!` variants.
An API should not provide both `Result`-producing and `panic`king versions of an
operation. It should provide just the `Result` version, allowing clients to use
`try!` or `unwrap` instead as needed. This is part of the general pattern of
cutting down on redundant variants by instead using method chaining.

View file

@ -0,0 +1,9 @@
% Guidelines by language feature
Rust provides a unique combination of language features, some new and some
old. This section gives guidance on when and how to use Rust's features, and
brings attention to some of the tradeoffs between different features.
Notably missing from this section is an in-depth discussion of Rust's pointer
types (both built-in and in the library). The topic of pointers is discussed at
length in a [separate section on ownership](../ownership/README.md).

View file

@ -0,0 +1,6 @@
% Crates
> **[FIXME]** What general guidelines should we provide for crate design?
> Possible topics: facades; per-crate preludes (to be imported as globs);
> "lib.rs"

View file

@ -0,0 +1,43 @@
% Functions and methods
### Prefer methods to functions if there is a clear receiver. **[FIXME: needs RFC]**
Prefer
```rust
impl Foo {
pub fn frob(&self, w: widget) { ... }
}
```
over
```rust
pub fn frob(foo: &Foo, w: widget) { ... }
```
for any operation that is clearly associated with a particular
type.
Methods have numerous advantages over functions:
* They do not need to be imported or qualified to be used: all you
need is a value of the appropriate type.
* Their invocation performs autoborrowing (including mutable borrows).
* They make it easy to answer the question "what can I do with a value
of type `T`" (especially when using rustdoc).
* They provide `self` notation, which is more concise and often more
clearly conveys ownership distinctions.
> **[FIXME]** Revisit these guidelines with
> [UFCS](https://github.com/nick29581/rfcs/blob/ufcs/0000-ufcs.md) and
> conventions developing around it.
### Guidelines for inherent methods. **[FIXME]**
> **[FIXME]** We need guidelines for when to provide inherent methods on a type,
> versus methods through a trait or functions.
> **NOTE**: Rules for method resolution around inherent methods are in flux,
> which may impact the guidelines.

View file

@ -0,0 +1,43 @@
% Convenience methods
### Provide small, coherent sets of convenience methods. **[FIXME: needs RFC]**
_Convenience methods_ wrap up existing functionality in a more convenient
way. The work done by a convenience method varies widely:
* _Re-providing functions as methods_. For example, the `std::path::Path` type
provides methods like `stat` on `Path`s that simply invoke the corresponding
function in `std::io::fs`.
* _Skipping through conversions_. For example, the `str` type provides a
`.len()` convenience method which is also expressible as `.as_bytes().len()`.
Sometimes the conversion is more complex: the `str` module also provides
`from_chars`, which encapsulates a simple use of iterators.
* _Encapsulating common arguments_. For example, vectors of `&str`s
provide a `connect` as well as a special case, `concat`, that is expressible
using `connect` with a fixed separator of `""`.
* _Providing more efficient special cases_. The `connect` and `concat` example
also applies here: singling out `concat` as a special case allows for a more
efficient implementation.
Note, however, that the `connect` method actually detects the special case
internally and invokes `concat`. Usually, it is not necessary to add a public
convenience method just for efficiency gains; there should also be a
_conceptual_ reason to add it, e.g. because it is such a common special case.
It is tempting to add convenience methods in a one-off, haphazard way as
common use patterns emerge. Avoid this temptation, and instead _design_ small,
coherent sets of convenience methods that are easy to remember:
* _Small_: Avoid combinatorial explosions of convenience methods. For example,
instead of adding `_str` variants of methods that provide a `str` output,
instead ensure that the normal output type of methods is easily convertible to
`str`.
* _Coherent_: Look for small groups of convenience methods that make sense to
include together. For example, the `Path` API mentioned above includes a small
selection of the most common filesystem operations that take a `Path`
argument. If one convenience method strongly suggests the existence of others,
consider adding the whole group.
* _Memorable_: It is not worth saving a few characters of typing if you have to
look up the name of a convenience method every time you use it. Add
convenience methods with names that are obvious and easy to remember, and add
them for the most common or painful use cases.

View file

@ -0,0 +1,201 @@
% Input to functions and methods
### Let the client decide when to copy and where to place data. [FIXME: needs RFC]
#### Copying:
Prefer
```rust
fn foo(b: Bar) {
// use b as owned, directly
}
```
over
```rust
fn foo(b: &Bar) {
let b = b.clone();
// use b as owned after cloning
}
```
If a function requires ownership of a value of unknown type `T`, but does not
otherwise need to make copies, the function should take ownership of the
argument (pass by value `T`) rather than using `.clone()`. That way, the caller
can decide whether to relinquish ownership or to `clone`.
Similarly, the `Copy` trait bound should only be demanded it when absolutely
needed, not as a way of signaling that copies should be cheap to make.
#### Placement:
Prefer
```rust
fn foo(b: Bar) -> Bar { ... }
```
over
```rust
fn foo(b: Box<Bar>) -> Box<Bar> { ... }
```
for concrete types `Bar` (as opposed to trait objects). This way, the caller can
decide whether to place data on the stack or heap. No overhead is imposed by
letting the caller determine the placement.
### Minimize assumptions about parameters. [FIXME: needs RFC]
The fewer assumptions a function makes about its inputs, the more widely usable
it becomes.
#### Minimizing assumptions through generics:
Prefer
```rust
fn foo<T: Iterator<int>>(c: T) { ... }
```
over any of
```rust
fn foo(c: &[int]) { ... }
fn foo(c: &Vec<int>) { ... }
fn foo(c: &SomeOtherCollection<int>) { ... }
```
if the function only needs to iterate over the data.
More generally, consider using generics to pinpoint the assumptions a function
needs to make about its arguments.
On the other hand, generics can make it more difficult to read and understand a
function's signature. Aim for "natural" parameter types that a neither overly
concrete nor overly abstract. See the discussion on
[traits](../../traits/README.md) for more guidance.
#### Minimizing ownership assumptions:
Prefer either of
```rust
fn foo(b: &Bar) { ... }
fn foo(b: &mut Bar) { ... }
```
over
```rust
fn foo(b: Bar) { ... }
```
That is, prefer borrowing arguments rather than transferring ownership, unless
ownership is actually needed.
### Prefer compound return types to out-parameters. [FIXME: needs RFC]
Prefer
```rust
fn foo() -> (Bar, Bar)
```
over
```rust
fn foo(output: &mut Bar) -> Bar
```
for returning multiple `Bar` values.
Compound return types like tuples and structs are efficiently compiled
and do not require heap allocation. If a function needs to return
multiple values, it should do so via one of these types.
The primary exception: sometimes a function is meant to modify data
that the caller already owns, for example to re-use a buffer:
```rust
fn read(&mut self, buf: &mut [u8]) -> IoResult<uint>
```
(From the [Reader trait](http://static.rust-lang.org/doc/master/std/io/trait.Reader.html#tymethod.read).)
### Consider validating arguments, statically or dynamically. [FIXME: needs RFC]
_Note: this material is closely related to
[library-level guarantees](../../safety/lib-guarantees.md)._
Rust APIs do _not_ generally follow the
[robustness principle](http://en.wikipedia.org/wiki/Robustness_principle): "be
conservative in what you send; be liberal in what you accept".
Instead, Rust code should _enforce_ the validity of input whenever practical.
Enforcement can be achieved through the following mechanisms (listed
in order of preference).
#### Static enforcement:
Choose an argument type that rules out bad inputs.
For example, prefer
```rust
fn foo(a: ascii::Ascii) { ... }
```
over
```rust
fn foo(a: u8) { ... }
```
Note that
[`ascii::Ascii`](http://static.rust-lang.org/doc/master/std/ascii/struct.Ascii.html)
is a _wrapper_ around `u8` that guarantees the highest bit is zero; see
[newtype patterns]() for more details on creating typesafe wrappers.
Static enforcement usually comes at little run-time cost: it pushes the
costs to the boundaries (e.g. when a `u8` is first converted into an
`Ascii`). It also catches bugs early, during compilation, rather than through
run-time failures.
On the other hand, some properties are difficult or impossible to
express using types.
#### Dynamic enforcement:
Validate the input as it is processed (or ahead of time, if necessary). Dynamic
checking is often easier to implement than static checking, but has several
downsides:
1. Runtime overhead (unless checking can be done as part of processing the input).
2. Delayed detection of bugs.
3. Introduces failure cases, either via `fail!` or `Result`/`Option` types (see
the [error handling guidelines](../../errors/README.md)), which must then be
dealt with by client code.
#### Dynamic enforcement with `debug_assert!`:
Same as dynamic enforcement, but with the possibility of easily turning off
expensive checks for production builds.
#### Dynamic enforcement with opt-out:
Same as dynamic enforcement, but adds sibling functions that opt out of the
checking.
The convention is to mark these opt-out functions with a suffix like
`_unchecked` or by placing them in a `raw` submodule.
The unchecked functions can be used judiciously in cases where (1) performance
dictates avoiding checks and (2) the client is otherwise confident that the
inputs are valid.
> **[FIXME]** Should opt-out functions be marked `unsafe`?

View file

@ -0,0 +1,56 @@
% Output from functions and methods
### Don't overpromise. [FIXME]
> **[FIXME]** Add discussion of overly-specific return types,
> e.g. returning a compound iterator type rather than hiding it behind
> a use of newtype.
### Let clients choose what to throw away. [FIXME: needs RFC]
#### Return useful intermediate results:
Many functions that answer a question also compute interesting related data. If
this data is potentially of interest to the client, consider exposing it in the
API.
Prefer
```rust
struct SearchResult {
found: bool, // item in container?
expected_index: uint // what would the item's index be?
}
fn binary_search(&self, k: Key) -> SearchResult
```
or
```rust
fn binary_search(&self, k: Key) -> (bool, uint)
```
over
```rust
fn binary_search(&self, k: Key) -> bool
```
#### Yield back ownership:
Prefer
```rust
fn from_utf8_owned(vv: Vec<u8>) -> Result<String, Vec<u8>>
```
over
```rust
fn from_utf8_owned(vv: Vec<u8>) -> Option<String>
```
The `from_utf8_owned` function gains ownership of a vector. In the successful
case, the function consumes its input, returning an owned string without
allocating or copying. In the unsuccessful case, however, the function returns
back ownership of the original slice.

View file

@ -0,0 +1,103 @@
% Let binding
### Always separately bind RAII guards. [FIXME: needs RFC]
Prefer
```rust
fn use_mutex(m: sync::mutex::Mutex<int>) {
let guard = m.lock();
do_work(guard);
drop(guard); // unlock the lock
// do other work
}
```
over
```rust
fn use_mutex(m: sync::mutex::Mutex<int>) {
do_work(m.lock());
// do other work
}
```
As explained in the [RAII guide](../ownership/raii.md), RAII guards are values
that represent ownership of some resource and whose destructor releases the
resource. Because the lifetime of guards are significant, they should always be
explicitly `let`-bound to make the lifetime clear. Consider using an explicit
`drop` to release the resource early.
### Prefer conditional expressions to deferred initialization. [FIXME: needs RFC]
Prefer
```rust
let foo = match bar {
Baz => 0,
Quux => 1
};
```
over
```rust
let foo;
match bar {
Baz => {
foo = 0;
}
Quux => {
foo = 1;
}
}
```
unless the conditions for initialization are too complex to fit into a simple
conditional expression.
### Use type annotations for clarification; prefer explicit generics when inference fails. [FIXME: needs RFC]
Prefer
```rust
s.iter().map(|x| x * 2)
.collect::<Vec<_>>()
```
over
```rust
let v: Vec<_> = s.iter().map(|x| x * 2)
.collect();
```
When the type of a value might be unclear to the _reader_ of the code, consider
explicitly annotating it in a `let`.
On the other hand, when the type is unclear to the _compiler_, prefer to specify
the type by explicit generics instantiation, which is usually more clear.
### Shadowing [FIXME]
> **[FIXME]** Repeatedly shadowing a binding is somewhat common in Rust code. We
> need to articulate a guideline on when it is appropriate/useful and when not.
### Prefer immutable bindings. [FIXME: needs RFC]
Use `mut` bindings to signal the span during which a value is mutated:
```rust
let mut v = Vec::new();
// push things onto v
let v = v;
// use v immutably henceforth
```
### Prefer to bind all `struct` or tuple fields. [FIXME: needs RFC]
When consuming a `struct` or tuple via a `let`, bind all of the fields rather
than using `..` to elide the ones you don't need. The benefit is that when
fields are added, the compiler will pinpoint all of the places where that type
of value was consumed, which will often need to be adjusted to take the new
field properly into account.

View file

@ -0,0 +1,13 @@
% Loops
### Prefer `for` to `while`. [FIXME: needs RFC]
A `for` loop is preferable to a `while` loop, unless the loop counts in a
non-uniform way (making it difficult to express using `for`).
### Guidelines for `loop`. [FIXME]
> **[FIXME]** When is `loop` recommended? Some possibilities:
> * For optimistic retry algorithms
> * For servers
> * To avoid mutating local variables sometimes needed to fit `while`

View file

@ -0,0 +1,26 @@
% Pattern matching
### Dereference `match` targets when possible. [FIXME: needs RFC]
Prefer
~~~~
match *foo {
X(...) => ...
Y(...) => ...
}
~~~~
over
~~~~
match foo {
box X(...) => ...
box Y(...) => ...
}
~~~~
<!-- ### Clearly indicate important scopes. **[FIXME: needs RFC]** -->
<!-- If it is important that the destructor for a value be executed at a specific -->
<!-- time, clearly bind that value using a standalone `let` -->

View file

@ -0,0 +1,133 @@
% Modules
> **[FIXME]** What general guidelines should we provide for module design?
> We should discuss visibility, nesting, `mod.rs`, and any interesting patterns
> around modules.
### Headers [FIXME: needs RFC]
Organize module headers as follows:
1. [Imports](../style/imports.md).
1. `mod` declarations.
1. `pub mod` declarations.
### Avoid `path` directives. [FIXME: needs RFC]
Avoid using `#[path="..."]` directives; make the file system and
module hierarchy match, instead.
### Use the module hirearchy to organize APIs into coherent sections. [FIXME]
> **[FIXME]** Flesh this out with examples; explain what a "coherent
> section" is with examples.
>
> The module hirearchy defines both the public and internal API of your module.
> Breaking related functionality into submodules makes it understandable to both
> users and contributors to the module.
### Place modules in their own file. [FIXME: needs RFC]
> **[FIXME]**
> - "<100 lines" is arbitrary, but it's a clearer recommendation
> than "~1 page" or similar suggestions that vary by screen size, etc.
For all except very short modules (<100 lines) and [tests](../testing/README.md),
place the module `foo` in a separate file, as in:
```rust
pub mod foo;
// in foo.rs or foo/mod.rs
pub fn bar() { println!("..."); }
/* ... */
```
rather than declaring it inline:
```rust
pub mod foo {
pub fn bar() { println!("..."); }
/* ... */
}
```
#### Use subdirectories for modules with children. [FIXME: needs RFC]
For modules that themselves have submodules, place the module in a separate
directory (e.g., `bar/mod.rs` for a module `bar`) rather than the same directory.
Note the structure of
[`std::io`](http://doc.rust-lang.org/std/io/). Many of the submodules lack
children, like
[`io::fs`](http://doc.rust-lang.org/std/io/fs/)
and
[`io::stdio`](http://doc.rust-lang.org/std/io/stdio/).
On the other hand,
[`io::net`](http://doc.rust-lang.org/std/io/net/)
contains submodules, so it lives in a separate directory:
```
io/mod.rs
io/extensions.rs
io/fs.rs
io/net/mod.rs
io/net/addrinfo.rs
io/net/ip.rs
io/net/tcp.rs
io/net/udp.rs
io/net/unix.rs
io/pipe.rs
...
```
While it is possible to define all of `io` within a single directory,
mirroring the module hirearchy in the directory structure makes
submodules of `io::net` easier to find.
### Consider top-level definitions or reexports. [FIXME: needs RFC]
For modules with submodules,
define or [reexport](http://doc.rust-lang.org/std/io/#reexports) commonly used
definitions at the top level:
* Functionality relevant to the module itself or to many of its
children should be defined in `mod.rs`.
* Functionality specific to a submodule should live in that
submodule. Reexport at the top level for the most important or
common definitions.
For example,
[`IoError`](http://doc.rust-lang.org/std/io/struct.IoError.html)
is defined in `io/mod.rs`, since it pertains to the entirety of `io`,
while
[`TcpStream`](http://doc.rust-lang.org/std/io/net/tcp/struct.TcpStream.html)
is defined in `io/net/tcp.rs` and reexported in the `io` module.
### Use internal module hirearchies for organization. [FIXME: needs RFC]
> **[FIXME]**
> - Referencing internal modules from the standard library is subject to
> becoming outdated.
Internal module hirearchies (i.e., private submodules) may be used to
hide implementation details that are not part of the module's API.
For example, in [`std::io`](http://doc.rust-lang.org/std/io/), `mod mem`
provides implementations for
[`BufReader`](http://doc.rust-lang.org/std/io/struct.BufReader.html)
and
[`BufWriter`](http://doc.rust-lang.org/std/io/struct.BufWriter.html),
but these are re-exported in `io/mod.rs` at the top level of the module:
```rust
// libstd/io/mod.rs
pub use self::mem::{MemReader, BufReader, MemWriter, BufWriter};
/* ... */
mod mem;
```
This hides the detail that there even exists a `mod mem` in `io`, and
helps keep code organized while offering freedom to change the
implementation.

View file

@ -0,0 +1,22 @@
% Traits
Traits are probably Rust's most complex feature, supporting a wide range of use
cases and design tradeoffs. Patterns of trait usage are still emerging.
### Know whether a trait will be used as an object. [FIXME: needs RFC]
Trait objects have some [significant limitations](objects.md): methods
invoked through a trait object cannot use generics, and cannot use
`Self` except in receiver position.
When designing a trait, decide early on whether the trait will be used
as an [object](objects.md) or as a [bound on generics](generics.md);
the tradeoffs are discussed in each of the linked sections.
If a trait is meant to be used as an object, its methods should take
and return trait objects rather than use generics.
### Default methods [FIXME]
> **[FIXME]** Guidelines for default methods.

View file

@ -0,0 +1,71 @@
% Common traits
### Eagerly implement common traits. [FIXME: needs RFC]
Rust's trait system does not allow _orphans_: roughly, every `impl` must live
either in the crate that defines the trait or the implementing
type. Consequently, crates that define new types should eagerly implement all
applicable, common traits.
To see why, consider the following situation:
* Crate `std` defines trait `Show`.
* Crate `url` defines type `Url`, without implementing `Show`.
* Crate `webapp` imports from both `std` and `url`,
There is no way for `webapp` to add `Show` to `url`, since it defines neither.
(Note: the newtype pattern can provide an efficient, but inconvenient
workaround; see [newtype for views](../types/newtype.md))
The most important common traits to implement from `std` are:
```rust
Clone, Show, Hash, Eq
```
#### When safe, derive or otherwise implement `Send` and `Share`. [FIXME]
> **[FIXME]**. This guideline is in flux while the "opt-in" nature of
> built-in traits is being decided. See https://github.com/rust-lang/rfcs/pull/127
### Prefer to derive, rather than implement. [FIXME: needs RFC]
Deriving saves implementation effort, makes correctness trivial, and
automatically adapts to upstream changes.
### Do not overload operators in surprising ways. [FIXME: needs RFC]
Operators with built in syntax (`*`, `|`, and so on) can be provided for a type
by implementing the traits in `core::ops`. These operators come with strong
expectations: implement `Mul` only for an operation that bears some resemblance
to multiplication (and shares the expected properties, e.g. associativity), and
so on for the other traits.
### The `Drop` trait
The `Drop` trait is treated specially by the compiler as a way of
associating destructors with types. See
[the section on destructors](../../ownership/destructors.md) for
guidance.
### The `Deref`/`DerefMut` traits
#### Use `Deref`/`DerefMut` only for smart pointers. [FIXME: needs RFC]
The `Deref` traits are used implicitly by the compiler in many circumstances,
and interact with method resolution. The relevant rules are designed
specifically to accommodate smart pointers, and so the traits should be used
only for that purpose.
#### Do not fail within a `Deref`/`DerefMut` implementation. [FIXME: needs RFC]
Because the `Deref` traits are invoked implicitly by the compiler in sometimes
subtle ways, failure during dereferencing can be extremely confusing. If a
dereference might not succeed, target the `Deref` trait as a `Result` or
`Option` type instead.
#### Avoid inherent methods when implementing `Deref`/`DerefMut` [FIXME: needs RFC]
The rules around method resolution and `Deref` are in flux, but inherent methods
on a type implementing `Deref` are likely to shadow any methods of the referent
with the same name.

View file

@ -0,0 +1,7 @@
% Using traits to add extension methods
> **[FIXME]** Elaborate.
### Consider using default methods rather than extension traits **[FIXME]**
> **[FIXME]** Elaborate.

View file

@ -0,0 +1,68 @@
% Using traits for bounds on generics
The most widespread use of traits is for writing generic functions or types. For
example, the following signature describes a function for consuming any iterator
yielding items of type `A` to produce a collection of `A`:
```rust
fn from_iter<T: Iterator<A>>(iterator: T) -> SomeCollection<A>
```
Here, the `Iterator` trait is specifies an interface that a type `T` must
explicitly implement to be used by this generic function.
**Pros**:
* _Reusability_. Generic functions can be applied to an open-ended collection of
types, while giving a clear contract for the functionality those types must
provide.
* _Static dispatch and optimization_. Each use of a generic function is
specialized ("monomorphized") to the particular types implementing the trait
bounds, which means that (1) invocations of trait methods are static, direct
calls to the implementation and (2) the compiler can inline and otherwise
optimize these calls.
* _Inline layout_. If a `struct` and `enum` type is generic over some type
parameter `T`, values of type `T` will be laid out _inline_ in the
`struct`/`enum`, without any indirection.
* _Inference_. Since the type parameters to generic functions can usually be
inferred, generic functions can help cut down on verbosity in code where
explicit conversions or other method calls would usually be necessary. See the
[overloading/implicits use case](#use-case:-limited-overloading-and/or-implicit-conversions)
below.
* _Precise types_. Because generic give a _name_ to the specific type
implementing a trait, it is possible to be precise about places where that
exact type is required or produced. For example, a function
```rust
fn binary<T: Trait>(x: T, y: T) -> T
```
is guaranteed to consume and produce elements of exactly the same type `T`; it
cannot be invoked with parameters of different types that both implement
`Trait`.
**Cons**:
* _Code size_. Specializing generic functions means that the function body is
duplicated. The increase in code size must be weighed against the performance
benefits of static dispatch.
* _Homogeneous types_. This is the other side of the "precise types" coin: if
`T` is a type parameter, it stands for a _single_ actual type. So for example
a `Vec<T>` contains elements of a single concrete type (and, indeed, the
vector representation is specialized to lay these out in line). Sometimes
heterogeneous collections are useful; see
[trait objects](#use-case:-trait-objects) below.
* _Signature verbosity_. Heavy use of generics can bloat function signatures.
**[Ed. note]** This problem may be mitigated by some language improvements; stay tuned.
### Favor widespread traits. **[FIXME: needs RFC]**
Generic types are a form of abstraction, which entails a mental indirection: if
a function takes an argument of type `T` bounded by `Trait`, clients must first
think about the concrete types that implement `Trait` to understand how and when
the function is callable.
To keep the cost of abstraction low, favor widely-known traits. Whenever
possible, implement and use traits provided as part of the standard library. Do
not introduce new traits for generics lightly; wait until there are a wide range
of types that can implement the type.

View file

@ -0,0 +1,49 @@
% Using trait objects
> **[FIXME]** What are uses of trait objects other than heterogeneous collections?
Trait objects are useful primarily when _heterogeneous_ collections of objects
need to be treated uniformly; it is the closest that Rust comes to
object-oriented programming.
```rust
struct Frame { ... }
struct Button { ... }
struct Label { ... }
trait Widget { ... }
impl Widget for Frame { ... }
impl Widget for Button { ... }
impl Widget for Label { ... }
impl Frame {
fn new(contents: &[Box<Widget>]) -> Frame {
...
}
}
fn make_gui() -> Box<Widget> {
let b: Box<Widget> = box Button::new(...);
let l: Box<Widget> = box Label::new(...);
box Frame::new([b, l]) as Box<Widget>
}
```
By using trait objects, we can set up a GUI framework with a `Frame` widget that
contains a heterogeneous collection of children widgets.
**Pros**:
* _Heterogeneity_. When you need it, you really need it.
* _Code size_. Unlike generics, trait objects do not generate specialized
(monomorphized) versions of code, which can greatly reduce code size.
**Cons**:
* _No generic methods_. Trait objects cannot currently provide generic methods.
* _Dynamic dispatch and fat pointers_. Trait objects inherently involve
indirection and vtable dispatch, which can carry a performance penalty.
* _No Self_. Except for the method receiver argument, methods on trait objects
cannot use the `Self` type.

View file

@ -0,0 +1,7 @@
% Using traits for overloading
> **[FIXME]** Elaborate.
> **[FIXME]** We need to decide on guidelines for this use case. There are a few
> patterns emerging in current Rust code, but it's not clear how widespread they
> should be.

View file

@ -0,0 +1,30 @@
% Using traits to share implementations
> **[FIXME]** Elaborate.
> **[FIXME]** We probably want to discourage this, at least when used in a way
> that is publicly exposed.
Traits that provide default implmentations for function can provide code reuse
across types. For example, a `print` method can be defined across multiple
types as follows:
``` Rust
trait Printable {
// Default method implementation
fn print(&self) { println!("{:?}", *self) }
}
impl Printable for int {}
impl Printable for String {
fn print(&self) { println!("{}", *self) }
}
impl Printable for bool {}
impl Printable for f32 {}
```
This allows the implementation of `print` to be shared across types, yet
overridden where needed, as seen in the `impl` for `String`.

View file

@ -0,0 +1,68 @@
% Data types
### Use custom types to imbue meaning; do not abuse `bool`, `Option` or other core types. **[FIXME: needs RFC]**
Prefer
```rust
let w = Widget::new(Small, Round)
```
over
```rust
let w = Widget::new(true, false)
```
Core types like `bool`, `u8` and `Option` have many possible interpretations.
Use custom types (whether `enum`s, `struct`, or tuples) to convey
interpretation and invariants. In the above example,
it is not immediately clear what `true` and `false` are conveying without
looking up the argument names, but `Small` and `Round` are more suggestive.
Using custom types makes it easier to expand the
options later on, for example by adding an `ExtraLarge` variant.
See [the newtype pattern](newtype.md) for a no-cost way to wrap
existing types with a distinguished name.
### Prefer private fields, except for passive data. **[FIXME: needs RFC]**
Making a field public is a strong commitment: it pins down a representation
choice, _and_ prevents the type from providing any validation or maintaining any
invariants on the contents of the field, since clients can mutate it arbitrarily.
Public fields are most appropriate for `struct` types in the C spirit: compound,
passive data structures. Otherwise, consider providing getter/setter methods
and hiding fields instead.
> **[FIXME]** Cross-reference validation for function arguments.
### Use custom `enum`s for alternatives, `bitflags` for C-style flags. **[FIXME: needs RFC]**
Rust supports `enum` types with "custom discriminants":
~~~~
enum Color {
Red = 0xff0000,
Green = 0x00ff00,
Blue = 0x0000ff
}
~~~~
Custom discriminants are useful when an `enum` type needs to be serialized to an
integer value compatibly with some other system/language. They support
"typesafe" APIs: by taking a `Color`, rather than an integer, a function is
guaranteed to get well-formed inputs, even if it later views those inputs as
integers.
An `enum` allows an API to request exactly one choice from among many. Sometimes
an API's input is instead the presence or absence of a set of flags. In C code,
this is often done by having each flag correspond to a particular bit, allowing
a single integer to represent, say, 32 or 64 flags. Rust's `std::bitflags`
module provides a typesafe way for doing so.
### Phantom types. [FIXME]
> **[FIXME]** Add some material on phantom types (https://blog.mozilla.org/research/2014/06/23/static-checking-of-units-in-servo/)

View file

@ -0,0 +1,22 @@
% Conversions between types
### Associate conversions with the most specific type involved. **[FIXME: needs RFC]**
When in doubt, prefer `to_`/`as_`/`into_` to `from_`, because they are
more ergonomic to use (and can be chained with other methods).
For many conversions between two types, one of the types is clearly more
"specific": it provides some additional invariant or interpretation that is not
present in the other type. For example, `str` is more specific than `&[u8]`,
since it is a utf-8 encoded sequence of bytes.
Conversions should live with the more specific of the involved types. Thus,
`str` provides both the `as_bytes` method and the `from_utf8` constructor for
converting to and from `&[u8]` values. Besides being intuitive, this convention
avoids polluting concrete types like `&[u8]` with endless conversion methods.
### Explicitly mark lossy conversions, or do not label them as conversions. **[FIXME: needs RFC]**
If a function's name implies that it is a conversion (prefix `from_`, `as_`,
`to_` or `into_`), but the function loses information, add a suffix `_lossy` or
otherwise indicate the lossyness. Consider avoiding the conversion name prefix.

View file

@ -0,0 +1,69 @@
% The newtype pattern
A "newtype" is a tuple or `struct` with a single field. The terminology is borrowed from Haskell.
Newtypes are a zero-cost abstraction: they introduce a new, distinct name for an
existing type, with no runtime overhead when converting between the two types.
### Use newtypes to provide static distinctions. [FIXME: needs RFC]
Newtypes can statically distinguish between different interpretations of an
underlying type.
For example, a `f64` value might be used to represent a quantity in miles or in
kilometers. Using newtypes, we can keep track of the intended interpretation:
```rust
struct Miles(pub f64);
struct Kilometers(pub f64);
impl Miles {
fn as_kilometers(&self) -> Kilometers { ... }
}
impl Kilometers {
fn as_miles(&self) -> Miles { ... }
}
```
Once we have separated these two types, we can statically ensure that we do not
confuse them. For example, the function
```rust
fn are_we_there_yet(distance_travelled: Miles) -> bool { ... }
```
cannot accidentally be called with a `Kilometers` value. The compiler will
remind us to perform the conversion, thus averting certain
[catastrophic bugs](http://en.wikipedia.org/wiki/Mars_Climate_Orbiter).
### Use newtypes with private fields for hiding. [FIXME: needs RFC]
A newtype can be used to hide representation details while making precise
promises to the client.
For example, consider a function `my_transform` that returns a compound iterator
type `Enumerate<Skip<vec::MoveItems<T>>>`. We wish to hide this type from the
client, so that the client's view of the return type is roughly `Iterator<(uint,
T)>`. We can do so using the newtype pattern:
```rust
struct MyTransformResult<T>(Enumerate<Skip<vec::MoveItems<T>>>);
impl<T> Iterator<(uint, T)> for MyTransformResult<T> { ... }
fn my_transform<T, Iter: Iterator<T>>(iter: Iter) -> MyTransformResult<T> {
...
}
```
Aside from simplifying the signature, this use of newtypes allows us to make a
expose and promise less to the client. The client does not know _how_ the result
iterator is constructed or represented, which means the representation can
change in the future without breaking client code.
> **[FIXME]** Interaction with auto-deref.
### Use newtypes to provide cost-free _views_ of another type. **[FIXME]**
> **[FIXME]** Describe the pattern of using newtypes to provide a new set of
> inherent or trait methods, providing a different perspective on the underlying
> type.

View file

@ -0,0 +1,3 @@
% Ownership and resource management
> **[FIXME]** Add general remarks about ownership/resources here.

View file

@ -0,0 +1,176 @@
% The builder pattern
Some data structures are complicated to construct, due to their construction needing:
* a large number of inputs
* compound data (e.g. slices)
* optional configuration data
* choice between several flavors
which can easily lead to a large number of distinct constructors with
many arguments each.
If `T` is such a data structure, consider introducing a `T` _builder_:
1. Introduce a separate data type `TBuilder` for incrementally configuring a `T`
value. When possible, choose a better name: e.g. `Command` is the builder for
`Process`.
2. The builder constructor should take as parameters only the data _required_ to
to make a `T`.
3. The builder should offer a suite of convenient methods for configuration,
including setting up compound inputs (like slices) incrementally.
These methods should return `self` to allow chaining.
4. The builder should provide one or more "_terminal_" methods for actually building a `T`.
The builder pattern is especially appropriate when building a `T` involves side
effects, such as spawning a task or launching a process.
In Rust, there are two variants of the builder pattern, differing in the
treatment of ownership, as described below.
### Non-consuming builders (preferred):
In some cases, constructing the final `T` does not require the builder itself to
be consumed. The follow variant on
[`std::io::process::Command`](http://static.rust-lang.org/doc/master/std/io/process/struct.Command.html)
is one example:
```rust
// NOTE: the actual Command API does not use owned Strings;
// this is a simplified version.
pub struct Command {
program: String,
args: Vec<String>,
cwd: Option<String>,
// etc
}
impl Command {
pub fn new(program: String) -> Command {
Command {
program: program,
args: Vec::new(),
cwd: None,
}
}
/// Add an argument to pass to the program.
pub fn arg<'a>(&'a mut self, arg: String) -> &'a mut Command {
self.args.push(arg);
self
}
/// Add multiple arguments to pass to the program.
pub fn args<'a>(&'a mut self, args: &[String])
-> &'a mut Command {
self.args.push_all(args);
self
}
/// Set the working directory for the child process.
pub fn cwd<'a>(&'a mut self, dir: String) -> &'a mut Command {
self.cwd = Some(dir);
self
}
/// Executes the command as a child process, which is returned.
pub fn spawn(&self) -> IoResult<Process> {
...
}
}
```
Note that the `spawn` method, which actually uses the builder configuration to
spawn a process, takes the builder by immutable reference. This is possible
because spawning the process does not require ownership of the configuration
data.
Because the terminal `spawn` method only needs a reference, the configuration
methods take and return a mutable borrow of `self`.
#### The benefit
By using borrows throughout, `Command` can be used conveniently for both
one-liner and more complex constructions:
```rust
// One-liners
Command::new("/bin/cat").arg("file.txt").spawn();
// Complex configuration
let mut cmd = Command::new("/bin/ls");
cmd.arg(".");
if size_sorted {
cmd.arg("-S");
}
cmd.spawn();
```
### Consuming builders:
Sometimes builders must transfer ownership when constructing the final type
`T`, meaning that the terminal methods must take `self` rather than `&self`:
```rust
// A simplified excerpt from std::task::TaskBuilder
impl TaskBuilder {
/// Name the task-to-be. Currently the name is used for identification
/// only in failure messages.
pub fn named(mut self, name: String) -> TaskBuilder {
self.name = Some(name);
self
}
/// Redirect task-local stdout.
pub fn stdout(mut self, stdout: Box<Writer + Send>) -> TaskBuilder {
self.stdout = Some(stdout);
// ^~~~~~ this is owned and cannot be cloned/re-used
self
}
/// Creates and executes a new child task.
pub fn spawn(self, f: proc():Send) {
// consume self
...
}
}
```
Here, the `stdout` configuration involves passing ownership of a `Writer`,
which must be transferred to the task upon construction (in `spawn`).
When the terminal methods of the builder require ownership, there is a basic tradeoff:
* If the other builder methods take/return a mutable borrow, the complex
configuration case will work well, but one-liner configuration becomes
_impossible_.
* If the other builder methods take/return an owned `self`, one-liners
continue to work well but complex configuration is less convenient.
Under the rubric of making easy things easy and hard things possible, _all_
builder methods for a consuming builder should take and returned an owned
`self`. Then client code works as follows:
```rust
// One-liners
TaskBuilder::new().named("my_task").spawn(proc() { ... });
// Complex configuration
let mut task = TaskBuilder::new();
task = task.named("my_task_2"); // must re-assign to retain ownership
if reroute {
task = task.stdout(mywriter);
}
task.spawn(proc() { ... });
```
One-liners work as before, because ownership is threaded through each of the
builder methods until being consumed by `spawn`. Complex configuration,
however, is more verbose: it requires re-assigning the builder at each step.

View file

@ -0,0 +1,4 @@
% Cells and smart pointers
> **[FIXME]** Add guidelines about when to use Cell, RefCell, Rc and
> Arc (and how to use them together).

View file

@ -0,0 +1,62 @@
% Constructors
### Define constructors as static, inherent methods. [FIXME: needs RFC]
In Rust, "constructors" are just a convention:
```rust
impl<T> Vec<T> {
pub fn new() -> Vec<T> { ... }
}
```
Constructors are static (no `self`) inherent methods for the type that they
construct. Combined with the practice of
[fully importing type names](../style/imports.md), this convention leads to
informative but concise construction:
```rust
use vec::Vec;
// construct a new vector
let mut v = Vec::new();
```
This convention also applied to conversion constructors (prefix `from` rather
than `new`).
### Provide constructors for passive `struct`s with defaults. [FIXME: needs RFC]
Given the `struct`
```rust
pub struct Config {
pub color: Color,
pub size: Size,
pub shape: Shape,
}
```
provide a constructor if there are sensible defaults:
```rust
impl Config {
pub fn new() -> Config {
Config {
color: Brown,
size: Medium,
shape: Square,
}
}
}
```
which then allows clients to concisely override using `struct` update syntax:
```rust
Config { color: Red, .. Config::new() };
```
See the [guideline for field privacy](../features/types/README.md) for
discussion on when to create such "passive" `struct`s with public
fields.

View file

@ -0,0 +1,22 @@
% Destructors
Unlike constructors, destructors in Rust have a special status: they are added
by implementing `Drop` for a type, and they are automatically invoked as values
go out of scope.
> **[FIXME]** This section needs to be expanded.
### Destructors should not fail. [FIXME: needs RFC]
Destructors are executed on task failure, and in that context a failing
destructor causes the program to abort.
Instead of failing in a destructor, provide a separate method for checking for
clean teardown, e.g. a `close` method, that returns a `Result` to signal
problems.
### Destructors should not block. [FIXME: needs RFC]
Similarly, destructors should not invoke blocking operations, which can make
debugging much more difficult. Again, consider providing a separate method for
preparing for an infallible, nonblocking teardown.

View file

@ -0,0 +1,12 @@
% RAII
Resource Acquisition is Initialization
> **[FIXME]** Explain the RAII pattern and give best practices.
### Whenever possible, tie resource access to guard scopes [FIXME]
> **[FIXME]** Example: Mutex guards guarantee that access to the
> protected resource only happens when the guard is in scope.
`must_use`

View file

@ -0,0 +1,7 @@
% FFI and platform-specific code **[FIXME]**
> **[FIXME]** Not sure where this should live.
When writing cross-platform code, group platform-specific code into a
module called `platform`. Avoid `#[cfg]` directives outside this
`platform` module.

View file

@ -0,0 +1,19 @@
% Safety and guarantees
> **[FIXME]** Is there a better phrase than "strong guarantees" that encompasses
> both e.g. memory safety and e.g. data structure invariants?
A _guarantee_ is a property that holds no matter what client code does, unless
the client explicitly opts out:
* Rust guarantees memory safety and data-race freedom, with `unsafe`
blocks as an opt-out mechanism.
* APIs in Rust often provide their own guarantees. For example, `std::str`
guarantees that its underlying buffer is valid utf-8. The `std::path::Path` type
guarantees no interior nulls. Both strings and paths provide `unsafe` mechanisms
for opting out of these guarantees (and thereby avoiding runtime checks).
Thinking about guarantees is an essential part of writing good Rust code. The
rest of this subsection outlines some cross-cutting principles around
guarantees.

View file

@ -0,0 +1,81 @@
% Library-level guarantees
Most libraries rely on internal invariants, e.g. about their data, resource
ownership, or protocol states. In Rust, broken invariants cannot produce
segfaults, but they can still lead to wrong answers.
### Provide library-level guarantees whenever practical. **[FIXME: needs RFC]**
Library-level invariants should be turned into guarantees whenever
practical. They should hold no matter what the client does, modulo
explicit opt-outs. Depending on the kind of invariant, this can be
achieved through a combination of static and dynamic enforcement, as
described below.
#### Static enforcement:
Guaranteeing invariants almost always requires _hiding_,
i.e. preventing the client from directly accessing or modifying
internal data.
For example, the representation of the `str` type is hidden,
which means that any value of type `str` must have been produced
through an API under the control of the `str` module, and these
APIs in turn ensure valid utf-8 encoding.
Rust's type system makes it possible to provide guarantees even while
revealing more of the representation than usual. For example, the
`as_bytes()` method on `&str` gives a _read-only_ view into the
underlying buffer, which cannot be used to violate the utf-8 property.
#### Dynamic enforcement:
Malformed inputs from the client are hazards to library-level
guarantees, so library APIs should validate their input.
For example, `std::str::from_utf8_owned` attempts to convert a `u8`
slice into an owned string, but dynamically checks that the slice is
valid utf-8 and returns `Err` if not.
See
[the discussion on input validation](../features/functions-and-methods/input.md)
for more detail.
### Prefer static enforcement of guarantees. **[FIXME: needs RFC]**
Static enforcement provides two strong benefits over dynamic enforcement:
* Bugs are caught at compile time.
* There is no runtime cost.
Sometimes purely static enforcement is impossible or impractical. In these
cases, a library should check as much as possible statically, but defer to
dynamic checks where needed.
For example, the `std::string` module exports a `String` type with the guarantee
that all instances are valid utf-8:
* Any _consumer_ of a `String` is statically guaranteed utf-8 contents. For example,
the `append` method can push a `&str` onto the end of a `String` without
checking anything dynamically, since the existing `String` and `&str` are
statically guaranteed to be in utf-8.
* Some _producers_ of a `String` must perform dynamic checks. For example, the
`from_utf8` function attempts to convert a `Vec<u8>` into a `String`, but
dynamically checks that the contents are utf-8.
### Provide opt-outs with caution; make them explicit. **[FIXME: needs RFC]**
Providing library-level guarantees sometimes entails inconvenience (for static
checks) or overhead (for dynamic checks). So it is sometimes desirable to allow
clients to sidestep this checking, while promising to use the API in a way that
still provides the guarantee. Such escape hatches should only be be introduced
when there is a demonstrated need for them.
It should be trivial for clients to audit their use of the library for
escape hatches.
See
[the discussion on input validation](../features/functions-and-methods/input.md)
for conventions on marking opt-out functions.

View file

@ -0,0 +1,22 @@
% Using `unsafe`
### Unconditionally guarantee safety, or mark API as `unsafe`. **[FIXME: needs RFC]**
Memory safety, type safety, and data race freedom are basic assumptions for all
Rust code.
APIs that use `unsafe` blocks internally thus have two choices:
* They can guarantee safety _unconditionally_ (i.e., regardless of client
behavior or inputs) and be exported as safe code. Any safety violation is then
the library's fault, not the client's fault.
* They can export potentially unsafe functions with the `unsafe` qualifier. In
this case, the documentation should make very clear the conditions under which
safety is guaranteed.
The result is that a client program can never violate safety merely by having a
bug; it must have explicitly opted out by using an `unsafe` block.
Of the two options for using `unsafe`, creating such safe abstractions (the
first option above) is strongly preferred.

View file

@ -0,0 +1,5 @@
% Style
This section gives a set of strict rules for styling Rust code.
> **[FIXME]** General remarks about the style guidelines

View file

@ -0,0 +1,77 @@
% Braces, semicolons, and commas [FIXME: needs RFC]
### Opening braces always go on the same line.
``` rust
fn foo() {
...
}
fn frobnicate(a: Bar, b: Bar,
c: Bar, d: Bar)
-> Bar {
...
}
trait Bar {
fn baz(&self);
}
impl Bar for Baz {
fn baz(&self) {
...
}
}
frob(|x| {
x.transpose()
})
```
### `match` arms get braces, except for single-line expressions.
``` rust
match foo {
bar => baz,
quux => {
do_something();
do_something_else()
}
}
```
### `return` statements get semicolons.
``` rust
fn foo() {
do_something();
if condition() {
return;
}
do_something_else();
}
```
### Trailing commas
> **[FIXME]** We should have a guideline for when to include trailing
> commas in `struct`s, `match`es, function calls, etc.
>
> One possible rule: a trailing comma should be included whenever the
> closing delimiter appears on a separate line:
```rust
Foo { bar: 0, baz: 1 }
Foo {
bar: 0,
baz: 1,
}
match a_thing {
None => 0,
Some(x) => 1,
}
```

View file

@ -0,0 +1,87 @@
% Comments [FIXME: needs RFC]
### Avoid block comments.
Use line comments:
``` rust
// Wait for the main task to return, and set the process error code
// appropriately.
```
Instead of:
``` rust
/*
* Wait for the main task to return, and set the process error code
* appropriately.
*/
```
## Doc comments
Doc comments are prefixed by three slashes (`///`) and indicate
documentation that you would like to be included in Rustdoc's output.
They support
[Markdown syntax](https://en.wikipedia.org/wiki/Markdown)
and are the main way of documenting your public APIs.
The supported markdown syntax includes all of the extensions listed in the
[GitHub Flavored Markdown]
(https://help.github.com/articles/github-flavored-markdown) documentation,
plus superscripts.
### Summary line
The first line in any doc comment should be a single-line short sentence
providing a summary of the code. This line is used as a short summary
description throughout Rustdoc's output, so it's a good idea to keep it
short.
### Sentence structure
All doc comments, including the summary line, should begin with a
capital letter and end with a period, question mark, or exclamation
point. Prefer full sentences to fragments.
The summary line should be written in
[third person singular present indicative form]
(http://en.wikipedia.org/wiki/English_verbs#Third_person_singular_present).
Basically, this means write "Returns" instead of "Return".
For example:
``` rust
/// Sets up a default runtime configuration, given compiler-supplied arguments.
///
/// This function will block until the entire pool of M:N schedulers has
/// exited. This function also requires a local task to be available.
///
/// # Arguments
///
/// * `argc` & `argv` - The argument vector. On Unix this information is used
/// by `os::args`.
/// * `main` - The initial procedure to run inside of the M:N scheduling pool.
/// Once this procedure exits, the scheduling pool will begin to shut
/// down. The entire pool (and this function) will only return once
/// all child tasks have finished executing.
///
/// # Return value
///
/// The return value is used as the process return code. 0 on success, 101 on
/// error.
```
### Code snippets
> **[FIXME]**
### Avoid inner doc comments.
Use inner doc comments _only_ to document crates and file-level modules:
``` rust
//! The core library.
//!
//! The core library is a something something...
```

View file

@ -0,0 +1,13 @@
## `return` [FIXME: needs RFC]
Terminate `return` statements with semicolons:
``` rust
fn foo(bar: int) -> Option<int> {
if some_condition() {
return None;
}
...
}
```

View file

@ -0,0 +1,50 @@
% Imports [FIXME: needs RFC]
The imports of a crate/module should consist of the following
sections, in order, with a blank space between each:
* `extern crate` directives
* external `use` imports
* local `use` imports
* `pub use` imports
For example:
```rust
// Crates.
extern crate getopts;
extern crate mylib;
// Standard library imports.
use getopts::{optopt, getopts};
use std::os;
// Import from a library that we wrote.
use mylib::webserver;
// Will be reexported when we import this module.
pub use self::types::Webdata;
```
### Avoid `use *`, except in tests.
Glob imports have several downsides:
* They make it harder to tell where names are bound.
* They are forwards-incompatible, since new upstream exports can clash
with existing names.
When writing a [`test` submodule](../testing/README.md), importing `super::*` is appropriate
as a convenience.
### Prefer fully importing types/traits while module-qualifying functions.
For example:
```rust
use option::Option;
use mem;
let i: int = mem::transmute(Option(0));
```
> **[FIXME]** Add rationale.

View file

@ -0,0 +1,115 @@
% Naming conventions
### General conventions [RFC #430]
> The guidelines below were approved by [RFC #430](https://github.com/rust-lang/rfcs/pull/430).
In general, Rust tends to use `CamelCase` for "type-level" constructs
(types and traits) and `snake_case` for "value-level" constructs. More
precisely:
| Item | Convention |
| ---- | ---------- |
| Crates | `snake_case` (but prefer single word) |
| Modules | `snake_case` |
| Types | `CamelCase` |
| Traits | `CamelCase` |
| Enum variants | `CamelCase` |
| Functions | `snake_case` |
| Methods | `snake_case` |
| General constructors | `new` or `with_more_details` |
| Conversion constructors | `from_some_other_type` |
| Local variables | `snake_case` |
| Static variables | `SCREAMING_SNAKE_CASE` |
| Constant variables | `SCREAMING_SNAKE_CASE` |
| Type parameters | concise `CamelCase`, usually single uppercase letter: `T` |
| Lifetimes | short, lowercase: `'a` |
<p>
In `CamelCase`, acronyms count as one word: use `Uuid` rather than
`UUID`. In `snake_case`, acronyms are lower-cased: `is_xid_start`.
In `snake_case` or `SCREAMING_SNAKE_CASE`, a "word" should never
consist of a single letter unless it is the last "word". So, we have
`btree_map` rather than `b_tree_map`, but `PI_2` rather than `PI2`.
### Referring to types in function/method names [RFC 344]
> The guidelines below were approved by [RFC #344](https://github.com/rust-lang/rfcs/pull/344).
Function names often involve type names, the most common example being conversions
like `as_slice`. If the type has a purely textual name (ignoring parameters), it
is straightforward to convert between type conventions and function conventions:
Type name | Text in methods
--------- | ---------------
`String` | `string`
`Vec<T>` | `vec`
`YourType`| `your_type`
Types that involve notation follow the convention below. There is some
overlap on these rules; apply the most specific applicable rule:
Type name | Text in methods
--------- | ---------------
`&str` | `str`
`&[T]` | `slice`
`&mut [T]`| `mut_slice`
`&[u8]` | `bytes`
`&T` | `ref`
`&mut T` | `mut`
`*const T`| `ptr`
`*mut T` | `mut_ptr`
### Avoid redundant prefixes [RFC 356]
> The guidelines below were approved by [RFC #356](https://github.com/rust-lang/rfcs/pull/356).
Names of items within a module should not be prefixed with that module's name:
Prefer
``` rust
mod foo {
pub struct Error { ... }
}
```
over
``` rust
mod foo {
pub struct FooError { ... }
}
```
This convention avoids stuttering (like `io::IoError`). Library clients can
rename on import to avoid clashes.
### Getter/setter methods [RFC 344]
> The guidelines below were approved by [RFC #344](https://github.com/rust-lang/rfcs/pull/344).
Some data structures do not wish to provide direct access to their fields, but
instead offer "getter" and "setter" methods for manipulating the field state
(often providing checking or other functionality).
The convention for a field `foo: T` is:
* A method `foo(&self) -> &T` for getting the current value of the field.
* A method `set_foo(&self, val: T)` for setting the field. (The `val` argument
here may take `&T` or some other type, depending on the context.)
Note that this convention is about getters/setters on ordinary data types, *not*
on [builder objects](../ownership/builders.html).
### Escape hatches [FIXME]
> **[FIXME]** Should we standardize a convention for functions that may break API
> guarantees? e.g. `ToCStr::to_c_str_unchecked`
### Predicates
* Simple boolean predicates should be prefixed with `is_` or another
short question word, e.g., `is_empty`.
* Common exceptions: `lt`, `gt`, and other established predicate names.

View file

@ -0,0 +1,69 @@
% Common container/wrapper methods [FIXME: needs RFC]
Containers, wrappers, and cells all provide ways to access the data
they enclose. Accessor methods often have variants to access the data
by value, by reference, and by mutable reference.
In general, the `get` family of methods is used to access contained
data without any risk of task failure; they return `Option` as
appropriate. This name is chosen rather than names like `find` or
`lookup` because it is appropriate for a wider range of container types.
#### Containers
For a container with keys/indexes of type `K` and elements of type `V`:
```rust
// Look up element without failing
fn get(&self, key: K) -> Option<&V>
fn get_mut(&mut self, key: K) -> Option<&mut V>
// Convenience for .get(key).map(|elt| elt.clone())
fn get_clone(&self, key: K) -> Option<V>
// Lookup element, failing if it is not found:
impl Index<K, V> for Container { ... }
impl IndexMut<K, V> for Container { ... }
```
#### Wrappers/Cells
Prefer specific conversion functions like `as_bytes` or `into_vec` whenever
possible. Otherwise, use:
```rust
// Extract contents without failing
fn get(&self) -> &V
fn get_mut(&mut self) -> &mut V
fn unwrap(self) -> V
```
#### Wrappers/Cells around `Copy` data
```rust
// Extract contents without failing
fn get(&self) -> V
```
#### `Option`-like types
Finally, we have the cases of types like `Option` and `Result`, which
play a special role for failure.
For `Option<V>`:
```rust
// Extract contents or fail if not available
fn assert(self) -> V
fn expect(self, &str) -> V
```
For `Result<V, E>`:
```rust
// Extract the contents of Ok variant; fail if Err
fn assert(self) -> V
// Extract the contents of Err variant; fail if Ok
fn assert_err(self) -> E
```

View file

@ -0,0 +1,32 @@
% Conversions [Rust issue #7087]
> The guidelines below were approved by [rust issue #7087](https://github.com/rust-lang/rust/issues/7087).
> **[FIXME]** Should we provide standard traits for conversions? Doing
> so nicely will require
> [trait reform](https://github.com/rust-lang/rfcs/pull/48) to land.
Conversions should be provided as methods, with names prefixed as follows:
| Prefix | Cost | Consumes convertee |
| ------ | ---- | ------------------ |
| `as_` | Free | No |
| `to_` | Expensive | No |
| `into_` | Variable | Yes |
<p>
For example:
* `as_bytes()` gives a `&[u8]` view into a `&str`, which is a no-op.
* `to_owned()` copies a `&str` to a new `String`.
* `into_bytes()` consumes a `String` and yields the underlying
`Vec<u8>`, which is a no-op.
Conversions prefixed `as_` and `into_` typically _decrease abstraction_, either
exposing a view into the underlying representation (`as`) or deconstructing data
into its underlying representation (`into`). Conversions prefixed `to_`, on the
other hand, typically stay at the same level of abstraction but do some work to
change one representation into another.
> **[FIXME]** The distinctions between conversion methods does not work
> so well for `from_` conversion constructors. Is that a problem?

View file

@ -0,0 +1,32 @@
% Iterators
#### Method names [RFC #199]
> The guidelines below were approved by [RFC #199](https://github.com/rust-lang/rfcs/pull/199).
For a container with elements of type `U`, iterator methods should be named:
```rust
fn iter(&self) -> T // where T implements Iterator<&U>
fn iter_mut(&mut self) -> T // where T implements Iterator<&mut U>
fn into_iter(self) -> T // where T implements Iterator<U>
```
The default iterator variant yields shared references `&U`.
#### Type names [RFC #344]
> The guidelines below were approved by [RFC #344](https://github.com/rust-lang/rfcs/pull/344).
The name of an iterator type should be the same as the method that
produces the iterator.
For example:
* `iter` should yield an `Iter`
* `iter_mut` should yield an `IterMut`
* `into_iter` should yield an `IntoIter`
* `keys` should yield `Keys`
These type names make the most sense when prefixed with their owning module,
e.g. `vec::IntoIter`.

View file

@ -0,0 +1,34 @@
% Ownership variants [RFC #199]
> The guidelines below were approved by [RFC #199](https://github.com/rust-lang/rfcs/pull/199).
Functions often come in multiple variants: immutably borrowed, mutably
borrowed, and owned.
The right default depends on the function in question. Variants should
be marked through suffixes.
#### Immutably borrowed by default
If `foo` uses/produces an immutable borrow by default, use:
* The `_mut` suffix (e.g. `foo_mut`) for the mutably borrowed variant.
* The `_move` suffix (e.g. `foo_move`) for the owned variant.
#### Owned by default
If `foo` uses/produces owned data by default, use:
* The `_ref` suffix (e.g. `foo_ref`) for the immutably borrowed variant.
* The `_mut` suffix (e.g. `foo_mut`) for the mutably borrowed variant.
#### Exceptions
In the case of iterators, the moving variant can also be understood as
an `into` conversion, `into_iter`, and `for x in v.into_iter()` reads
arguably better than `for x in v.iter_move()`, so the convention is
`into_iter`.
For mutably borrowed variants, if the `mut` qualifier is part of a
type name (e.g. `as_mut_slice`), it should appear as it would appear
in the type.

View file

@ -0,0 +1,3 @@
*
*

View file

@ -0,0 +1,14 @@
% Organization [FIXME: needs RFC]
> **[FIXME]** What else?
### Reexport the most important types at the crate level.
Crates `pub use` the most common types for convenience, so that clients do not
have to remember or write the crate's module hierarchy to use these types.
### Define types and operations together.
Type definitions and the functions/methods that operate on them should be
defined together in a single module, with the type appearing above the
functions/methods.

View file

@ -0,0 +1,133 @@
% Whitespace [FIXME: needs RFC]
* Lines must not exceed 99 characters.
* Use 4 spaces for indentation, _not_ tabs.
* No trailing whitespace at the end of lines or files.
### Spaces
* Use spaces around binary operators, including the equals sign in attributes:
``` rust
#[deprecated = "Use `bar` instead."]
fn foo(a: uint, b: uint) -> uint {
a + b
}
```
* Use a space after colons and commas:
``` rust
fn foo(a: Bar);
MyStruct { foo: 3, bar: 4 }
foo(bar, baz);
```
* Use a space after the opening and before the closing brace for
single line blocks or `struct` expressions:
``` rust
spawn(proc() { do_something(); })
Point { x: 0.1, y: 0.3 }
```
### Line wrapping
* For multiline function signatures, each new line should align with the
first parameter. Multiple parameters per line are permitted:
``` rust
fn frobnicate(a: Bar, b: Bar,
c: Bar, d: Bar)
-> Bar {
...
}
fn foo<T: This,
U: That>(
a: Bar,
b: Bar)
-> Baz {
...
}
```
* Multiline function invocations generally follow the same rule as for
signatures. However, if the final argument begins a new block, the
contents of the block may begin on a new line, indented one level:
``` rust
fn foo_bar(a: Bar, b: Bar,
c: |Bar|) -> Bar {
...
}
// Same line is fine:
foo_bar(x, y, |z| { z.transpose(y) });
// Indented body on new line is also fine:
foo_bar(x, y, |z| {
z.quux();
z.rotate(x)
})
```
> **[FIXME]** Do we also want to allow the following?
>
> ```rust
> frobnicate(
> arg1,
> arg2,
> arg3)
> ```
>
> This style could ease the conflict between line length and functions
> with many parameters (or long method chains).
### Matches
> * **[Deprecated]** If you have multiple patterns in a single `match`
> arm, write each pattern on a separate line:
>
> ``` rust
> match foo {
> bar(_)
> | baz => quux,
> x
> | y
> | z => {
> quuux
> }
> }
> ```
### Alignment
Idiomatic code should not use extra whitespace in the middle of a line
to provide alignment.
``` rust
// Good
struct Foo {
short: f64,
really_long: f64,
}
// Bad
struct Bar {
short: f64,
really_long: f64,
}
// Good
let a = 0;
let radius = 7;
// Bad
let b = 0;
let diameter = 7;
```

View file

@ -0,0 +1,5 @@
% Testing
> **[FIXME]** Add some general remarks about when and how to unit
> test, versus other kinds of testing. What are our expectations for
> Rust's core libraries?

View file

@ -0,0 +1,30 @@
% Unit testing
Unit tests should live in a `test` submodule at the bottom of the module they
test. Mark the `test` submodule with `#[cfg(test)]` so it is only compiled when
testing.
The `test` module should contain:
* Imports needed only for testing.
* Functions marked with `#[test]` striving for full coverage of the parent module's
definitions.
* Auxiliary functions needed for writing the tests.
For example:
``` rust
// Excerpt from std::str
#[cfg(test)]
mod test {
#[test]
fn test_eq() {
assert!((eq(&"".to_owned(), &"".to_owned())));
assert!((eq(&"foo".to_owned(), &"foo".to_owned())));
assert!((!eq(&"foo".to_owned(), &"bar".to_owned())));
}
}
```
> **[FIXME]** add details about useful macros for testing, e.g. `assert!`

5
src/doc/style/todo.md Normal file
View file

@ -0,0 +1,5 @@
* [Containers and iteration]()
* [The visitor pattern]()
* [Concurrency]()
* [Documentation]()
* [Macros]()

View file

@ -28,13 +28,14 @@
* [Generics](generics.md)
* [Traits](traits.md)
* [Static and Dynamic Dispatch](static-and-dynamic-dispatch.md)
* [Macros](macros.md)
* [Concurrency](concurrency.md)
* [Error Handling](error-handling.md)
* [Documentation](documentation.md)
* [III: Advanced Topics](advanced.md)
* [FFI](ffi.md)
* [Unsafe Code](unsafe.md)
* [Macros](macros.md)
* [Advanced Macros](advanced-macros.md)
* [Compiler Plugins](plugins.md)
* [Conclusion](conclusion.md)
* [Glossary](glossary.md)

View file

@ -0,0 +1,210 @@
% Advanced macros
This chapter picks up where the [introductory macro chapter](macros.html) left
off.
# Syntactic requirements
Even when Rust code contains un-expanded macros, it can be parsed as a full
syntax tree. This property can be very useful for editors and other tools that
process code. It also has a few consequences for the design of Rust's macro
system.
One consequence is that Rust must determine, when it parses a macro invocation,
whether the macro stands in for
* zero or more items,
* zero or more methods,
* an expression,
* a statement, or
* a pattern.
A macro invocation within a block could stand for some items, or for an
expression / statement. Rust uses a simple rule to resolve this ambiguity. A
macro invocation that stands for items must be either
* delimited by curly braces, e.g. `foo! { ... }`, or
* terminated by a semicolon, e.g. `foo!(...);`
Another consequence of pre-expansion parsing is that the macro invocation must
consist of valid Rust tokens. Furthermore, parentheses, brackets, and braces
must be balanced within a macro invocation. For example, `foo!([)` is
forbidden. This allows Rust to know where the macro invocation ends.
More formally, the macro invocation body must be a sequence of *token trees*.
A token tree is defined recursively as either
* a sequence of token trees surrounded by matching `()`, `[]`, or `{}`, or
* any other single token.
Within a matcher, each metavariable has a *fragment specifier*, identifying
which syntactic form it matches.
* `ident`: an identifier. Examples: `x`; `foo`.
* `path`: a qualified name. Example: `T::SpecialA`.
* `expr`: an expression. Examples: `2 + 2`; `if true then { 1 } else { 2 }`; `f(42)`.
* `ty`: a type. Examples: `i32`; `Vec<(char, String)>`; `&T`.
* `pat`: a pattern. Examples: `Some(t)`; `(17, 'a')`; `_`.
* `stmt`: a single statement. Example: `let x = 3`.
* `block`: a brace-delimited sequence of statements. Example:
`{ log(error, "hi"); return 12; }`.
* `item`: an [item][]. Examples: `fn foo() { }`; `struct Bar;`.
* `meta`: a "meta item", as found in attributes. Example: `cfg(target_os = "windows")`.
* `tt`: a single token tree.
There are additional rules regarding the next token after a metavariable:
* `expr` variables must be followed by one of: `=> , ;`
* `ty` and `path` variables must be followed by one of: `=> , : = > as`
* `pat` variables must be followed by one of: `=> , =`
* Other variables may be followed by any token.
These rules provide some flexibility for Rust's syntax to evolve without
breaking existing macros.
The macro system does not deal with parse ambiguity at all. For example, the
grammar `$($t:ty)* $e:expr` will always fail to parse, because the parser would
be forced to choose between parsing `$t` and parsing `$e`. Changing the
invocation syntax to put a distinctive token in front can solve the problem. In
this case, you can write `$(T $t:ty)* E $e:exp`.
[item]: ../reference.html#items
# Scoping and macro import/export
Macros are expanded at an early stage in compilation, before name resolution.
One downside is that scoping works differently for macros, compared to other
constructs in the language.
Definition and expansion of macros both happen in a single depth-first,
lexical-order traversal of a crate's source. So a macro defined at module scope
is visible to any subsequent code in the same module, which includes the body
of any subsequent child `mod` items.
A macro defined within the body of a single `fn`, or anywhere else not at
module scope, is visible only within that item.
If a module has the `macro_use` attribute, its macros are also visible in its
parent module after the child's `mod` item. If the parent also has `macro_use`
then the macros will be visible in the grandparent after the parent's `mod`
item, and so forth.
The `macro_use` attribute can also appear on `extern crate`. In this context
it controls which macros are loaded from the external crate, e.g.
```rust,ignore
#[macro_use(foo, bar)]
extern crate baz;
```
If the attribute is given simply as `#[macro_use]`, all macros are loaded. If
there is no `#[macro_use]` attribute then no macros are loaded. Only macros
defined with the `#[macro_export]` attribute may be loaded.
To load a crate's macros *without* linking it into the output, use `#[no_link]`
as well.
An example:
```rust
macro_rules! m1 { () => (()) }
// visible here: m1
mod foo {
// visible here: m1
#[macro_export]
macro_rules! m2 { () => (()) }
// visible here: m1, m2
}
// visible here: m1
macro_rules! m3 { () => (()) }
// visible here: m1, m3
#[macro_use]
mod bar {
// visible here: m1, m3
macro_rules! m4 { () => (()) }
// visible here: m1, m3, m4
}
// visible here: m1, m3, m4
# fn main() { }
```
When this library is loaded with `#[macro_use] extern crate`, only `m2` will
be imported.
The Rust Reference has a [listing of macro-related
attributes](../reference.html#macro--and-plugin-related-attributes).
# The variable `$crate`
A further difficulty occurs when a macro is used in multiple crates. Say that
`mylib` defines
```rust
pub fn increment(x: u32) -> u32 {
x + 1
}
#[macro_export]
macro_rules! inc_a {
($x:expr) => ( ::increment($x) )
}
#[macro_export]
macro_rules! inc_b {
($x:expr) => ( ::mylib::increment($x) )
}
# fn main() { }
```
`inc_a` only works within `mylib`, while `inc_b` only works outside the
library. Furthermore, `inc_b` will break if the user imports `mylib` under
another name.
Rust does not (yet) have a hygiene system for crate references, but it does
provide a simple workaround for this problem. Within a macro imported from a
crate named `foo`, the special macro variable `$crate` will expand to `::foo`.
By contrast, when a macro is defined and then used in the same crate, `$crate`
will expand to nothing. This means we can write
```rust
#[macro_export]
macro_rules! inc {
($x:expr) => ( $crate::increment($x) )
}
# fn main() { }
```
to define a single macro that works both inside and outside our library. The
function name will expand to either `::increment` or `::mylib::increment`.
To keep this system simple and correct, `#[macro_use] extern crate ...` may
only appear at the root of your crate, not inside `mod`. This ensures that
`$crate` is a single identifier.
# A final note
Macros, as currently implemented, are not for the faint of heart. Even
ordinary syntax errors can be more difficult to debug when they occur inside a
macro, and errors caused by parse problems in generated code can be very
tricky. Invoking the `log_syntax!` macro can help elucidate intermediate
states, invoking `trace_macros!(true)` will automatically print those
intermediate states out, and passing the flag `--pretty expanded` as a
command-line argument to the compiler will show the result of expansion.
If Rust's macro system can't do what you need, you may want to write a
[compiler plugin](plugins.html) instead. Compared to `macro_rules!`
macros, this is significantly more work, the interfaces are much less stable,
and the warnings about debugging apply ten-fold. In exchange you get the
flexibility of running arbitrary Rust code within the compiler. Syntax
extension plugins are sometimes called *procedural macros* for this reason.

View file

@ -322,8 +322,8 @@ The `ordering` variable has the type `Ordering`, and so contains one of the
three values. We then do a bunch of `if`/`else` comparisons to check which
one it is.
This `Ordering::Greater` notation is too long. Lets use `use` to import can
the `enum` variants instead. This will avoid full scoping:
This `Ordering::Greater` notation is too long. Let's use `use` to import the
`enum` variants instead. This will avoid full scoping:
```{rust}
use std::cmp::Ordering::{self, Equal, Less, Greater};

View file

@ -57,13 +57,13 @@ place!
## Threads
Rust's standard library provides a library for 'threads', which allow you to
run Rust code in parallel. Here's a basic example of using `Thread`:
run Rust code in parallel. Here's a basic example of using `std::thread`:
```
use std::thread::Thread;
use std::thread;
fn main() {
Thread::scoped(|| {
thread::scoped(|| {
println!("Hello from a thread!");
});
}
@ -73,10 +73,10 @@ The `Thread::scoped()` method accepts a closure, which is executed in a new
thread. It's called `scoped` because this thread returns a join guard:
```
use std::thread::Thread;
use std::thread;
fn main() {
let guard = Thread::scoped(|| {
let guard = thread::scoped(|| {
println!("Hello from a thread!");
});
@ -85,15 +85,15 @@ fn main() {
```
When `guard` goes out of scope, it will block execution until the thread is
finished. If we didn't want this behaviour, we could use `Thread::spawn()`:
finished. If we didn't want this behaviour, we could use `thread::spawn()`:
```
use std::thread::Thread;
use std::thread;
use std::old_io::timer;
use std::time::Duration;
fn main() {
Thread::spawn(|| {
thread::spawn(|| {
println!("Hello from a thread!");
});
@ -101,24 +101,6 @@ fn main() {
}
```
Or call `.detach()`:
```
use std::thread::Thread;
use std::old_io::timer;
use std::time::Duration;
fn main() {
let guard = Thread::scoped(|| {
println!("Hello from a thread!");
});
guard.detach();
timer::sleep(Duration::milliseconds(50));
}
```
We need to `sleep` here because when `main()` ends, it kills all of the
running threads.
@ -164,7 +146,7 @@ As an example, here is a Rust program that would have a data race in many
languages. It will not compile:
```ignore
use std::thread::Thread;
use std::thread;
use std::old_io::timer;
use std::time::Duration;
@ -172,7 +154,7 @@ fn main() {
let mut data = vec![1u32, 2, 3];
for i in 0..2 {
Thread::spawn(move || {
thread::spawn(move || {
data[i] += 1;
});
}
@ -203,7 +185,7 @@ only one person at a time can mutate what's inside. For that, we can use the
but for a different reason:
```ignore
use std::thread::Thread;
use std::thread;
use std::old_io::timer;
use std::time::Duration;
use std::sync::Mutex;
@ -213,7 +195,7 @@ fn main() {
for i in 0..2 {
let data = data.lock().unwrap();
Thread::spawn(move || {
thread::spawn(move || {
data[i] += 1;
});
}
@ -255,7 +237,7 @@ We can use `Arc<T>` to fix this. Here's the working version:
```
use std::sync::{Arc, Mutex};
use std::thread::Thread;
use std::thread;
use std::old_io::timer;
use std::time::Duration;
@ -264,7 +246,7 @@ fn main() {
for i in 0us..2 {
let data = data.clone();
Thread::spawn(move || {
thread::spawn(move || {
let mut data = data.lock().unwrap();
data[i] += 1;
});
@ -280,14 +262,14 @@ thread more closely:
```
# use std::sync::{Arc, Mutex};
# use std::thread::Thread;
# use std::thread;
# use std::old_io::timer;
# use std::time::Duration;
# fn main() {
# let data = Arc::new(Mutex::new(vec![1u32, 2, 3]));
# for i in 0us..2 {
# let data = data.clone();
Thread::spawn(move || {
thread::spawn(move || {
let mut data = data.lock().unwrap();
data[i] += 1;
});
@ -315,7 +297,7 @@ than waiting for a specific time:
```
use std::sync::{Arc, Mutex};
use std::thread::Thread;
use std::thread;
use std::sync::mpsc;
fn main() {
@ -326,7 +308,7 @@ fn main() {
for _ in 0..10 {
let (data, tx) = (data.clone(), tx.clone());
Thread::spawn(move || {
thread::spawn(move || {
let mut data = data.lock().unwrap();
*data += 1;
@ -348,7 +330,7 @@ is `Send` over the channel!
```
use std::sync::{Arc, Mutex};
use std::thread::Thread;
use std::thread;
use std::sync::mpsc;
fn main() {
@ -357,7 +339,7 @@ fn main() {
for _ in 0..10 {
let tx = tx.clone();
Thread::spawn(move || {
thread::spawn(move || {
let answer = 42u32;
tx.send(answer);
@ -378,9 +360,9 @@ A `panic!` will crash the currently executing thread. You can use Rust's
threads as a simple isolation mechanism:
```
use std::thread::Thread;
use std::thread;
let result = Thread::scoped(move || {
let result = thread::spawn(move || {
panic!("oops!");
}).join();

View file

@ -15,7 +15,7 @@ comments":
// the "link" crate attribute is currently required for rustdoc, but normally
// isn't needed.
#![crate_id = "universe"]
#![crate_type="lib"]
#![crate_type= "lib"]
//! Tools for dealing with universes (this is a doc comment, and is shown on
//! the crate index page. The ! makes it apply to the parent of the comment,

View file

@ -4,19 +4,19 @@ Let's talk about loops.
Remember Rust's `for` loop? Here's an example:
```{rust}
```rust
for x in 0..10 {
println!("{}", x);
}
```
Now that you know more Rust, we can talk in detail about how this works. The
`range` function returns an *iterator*. An iterator is something that we can
Now that you know more Rust, we can talk in detail about how this works.
Ranges (the `0..10`) are 'iterators'. An iterator is something that we can
call the `.next()` method on repeatedly, and it gives us a sequence of things.
Like this:
```{rust}
```rust
let mut range = 0..10;
loop {
@ -29,12 +29,12 @@ loop {
}
```
We make a mutable binding to the return value of `range`, which is our iterator.
We then `loop`, with an inner `match`. This `match` is used on the result of
`range.next()`, which gives us a reference to the next value of the iterator.
`next` returns an `Option<i32>`, in this case, which will be `Some(i32)` when
we have a value and `None` once we run out. If we get `Some(i32)`, we print it
out, and if we get `None`, we `break` out of the loop.
We make a mutable binding to the range, which is our iterator. We then `loop`,
with an inner `match`. This `match` is used on the result of `range.next()`,
which gives us a reference to the next value of the iterator. `next` returns an
`Option<i32>`, in this case, which will be `Some(i32)` when we have a value and
`None` once we run out. If we get `Some(i32)`, we print it out, and if we get
`None`, we `break` out of the loop.
This code sample is basically the same as our `for` loop version. The `for`
loop is just a handy way to write this `loop`/`match`/`break` construct.
@ -43,13 +43,13 @@ loop is just a handy way to write this `loop`/`match`/`break` construct.
own iterator involves implementing the `Iterator` trait. While doing that is
outside of the scope of this guide, Rust provides a number of useful iterators
to accomplish various tasks. Before we talk about those, we should talk about a
Rust anti-pattern. And that's `range`.
Rust anti-pattern. And that's using ranges like this.
Yes, we just talked about how `range` is cool. But `range` is also very
primitive. For example, if you needed to iterate over the contents of
a vector, you may be tempted to write this:
Yes, we just talked about how ranges are cool. But ranges are also very
primitive. For example, if you needed to iterate over the contents of a vector,
you may be tempted to write this:
```{rust}
```rust
let nums = vec![1, 2, 3];
for i in 0..nums.len() {
@ -61,7 +61,7 @@ This is strictly worse than using an actual iterator. The `.iter()` method on
vectors returns an iterator which iterates through a reference to each element
of the vector in turn. So write this:
```{rust}
```rust
let nums = vec![1, 2, 3];
for num in nums.iter() {
@ -83,7 +83,7 @@ works. `num` is actually of type `&i32`. That is, it's a reference to an `i32`,
not an `i32` itself. `println!` handles the dereferencing for us, so we don't
see it. This code works fine too:
```{rust}
```rust
let nums = vec![1, 2, 3];
for num in nums.iter() {
@ -97,7 +97,7 @@ involve making a copy of the data and giving us the copy. With references,
we're just borrowing a reference to the data, and so it's just passing
a reference, without needing to do the copy.
So, now that we've established that `range` is often not what you want, let's
So, now that we've established that ranges are often not what you want, let's
talk about what you do want instead.
There are three broad classes of things that are relevant here: iterators,
@ -108,8 +108,7 @@ There are three broad classes of things that are relevant here: iterators,
different output sequence.
* *consumers* operate on an iterator, producing some final set of values.
Let's talk about consumers first, since you've already seen an iterator,
`range`.
Let's talk about consumers first, since you've already seen an iterator, ranges.
## Consumers
@ -118,7 +117,7 @@ The most common consumer is `collect()`. This code doesn't quite compile,
but it shows the intention:
```{rust,ignore}
let one_to_one_hundred = (1..101i32).collect();
let one_to_one_hundred = (1..101).collect();
```
As you can see, we call `collect()` on our iterator. `collect()` takes
@ -127,8 +126,8 @@ of the results. So why won't this compile? Rust can't determine what
type of things you want to collect, and so you need to let it know.
Here's the version that does compile:
```{rust}
let one_to_one_hundred = (1..101i32).collect::<Vec<i32>>();
```rust
let one_to_one_hundred = (1..101).collect::<Vec<i32>>();
```
If you remember, the `::<>` syntax allows us to give a type hint,
@ -137,7 +136,7 @@ need to use the whole type, though. Using a `_` will let you provide
a partial hint:
```rust
let one_to_one_hundred = range(1, 101).collect::<Vec<_>>();
let one_to_one_hundred = (1..101).collect::<Vec<_>>();
```
This says "Collect into a `Vec<T>`, please, but infer what the `T` is for me."
@ -146,8 +145,8 @@ This says "Collect into a `Vec<T>`, please, but infer what the `T` is for me."
`collect()` is the most common consumer, but there are others too. `find()`
is one:
```{rust}
let greater_than_forty_two = (0..100i32)
```rust
let greater_than_forty_two = (0..100)
.find(|x| *x > 42);
match greater_than_forty_two {
@ -163,9 +162,8 @@ element, `find` returns an `Option` rather than the element itself.
Another important consumer is `fold`. Here's what it looks like:
```{rust}
let sum = (1..4)
.fold(0, |sum, x| sum + x);
```rust
let sum = (1..4).fold(0, |sum, x| sum + x);
```
`fold()` is a consumer that looks like this:
@ -187,7 +185,7 @@ in this iterator:
We called `fold()` with these arguments:
```{rust}
```rust
# (1..4)
.fold(0, |sum, x| sum + x);
```
@ -218,25 +216,25 @@ are *lazy* and don't need to generate all of the values upfront.
This code, for example, does not actually generate the numbers
`1-100`, and just creates a value that represents the sequence:
```{rust}
```rust
let nums = 1..100;
```
Since we didn't do anything with the range, it didn't generate the sequence.
Let's add the consumer:
```{rust}
```rust
let nums = (1..100).collect::<Vec<i32>>();
```
Now, `collect()` will require that the range gives it some numbers, and so
it will do the work of generating the sequence.
A range is one of two basic iterators that you'll see. The other is `iter()`,
Ranges are one of two basic iterators that you'll see. The other is `iter()`,
which you've used before. `iter()` can turn a vector into a simple iterator
that gives you each element in turn:
```{rust}
```rust
let nums = [1, 2, 3];
for num in nums.iter() {
@ -247,7 +245,7 @@ for num in nums.iter() {
These two basic iterators should serve you well. There are some more
advanced iterators, including ones that are infinite. Like `count`:
```{rust}
```rust
std::iter::count(1, 5);
```
@ -265,7 +263,7 @@ we need to talk about with regards to iterators. Let's get to it!
a new iterator. The simplest one is called `map`:
```{rust,ignore}
(1..100i32).map(|x| x + 1);
(1..100).map(|x| x + 1);
```
`map` is called upon another iterator, and produces a new iterator where each
@ -273,7 +271,7 @@ element reference has the closure it's been given as an argument called on it.
So this would give us the numbers from `2-100`. Well, almost! If you
compile the example, you'll get a warning:
```{notrust,ignore}
```text
warning: unused result which must be used: iterator adaptors are lazy and
do nothing unless consumed, #[warn(unused_must_use)] on by default
(1..100).map(|x| x + 1);
@ -295,7 +293,7 @@ iterator over the next `n` elements of the original iterator, note that this
has no side effect on the original iterator. Let's try it out with our infinite
iterator from before, `count()`:
```{rust}
```rust
for i in std::iter::count(1, 5).take(5) {
println!("{}", i);
}
@ -303,7 +301,7 @@ for i in std::iter::count(1, 5).take(5) {
This will print
```{notrust,ignore}
```text
1
6
11
@ -315,8 +313,8 @@ This will print
returns `true` or `false`. The new iterator `filter()` produces
only the elements that that closure returns `true` for:
```{rust}
for i in (1..100i32).filter(|&x| x % 2 == 0) {
```rust
for i in (1..100).filter(|&x| x % 2 == 0) {
println!("{}", i);
}
```
@ -330,8 +328,8 @@ itself.)
You can chain all three things together: start with an iterator, adapt it
a few times, and then consume the result. Check it out:
```{rust}
(1..1000i32)
```rust
(1..1000)
.filter(|&x| x % 2 == 0)
.filter(|&x| x % 3 == 0)
.take(5)

View file

@ -1,588 +1,365 @@
% Macros
# Introduction
By now you've learned about many of the tools Rust provides for abstracting and
reusing code. These units of code reuse have a rich semantic structure. For
example, functions have a type signature, type parameters have trait bounds,
and overloaded functions must belong to a particular trait.
Functions are the primary tool that programmers can use to build abstractions.
Sometimes, however, programmers want to abstract over compile-time syntax
rather than run-time values.
Macros provide syntactic abstraction.
For an example of how this can be useful, consider the following two code fragments,
which both pattern-match on their input and both return early in one case,
doing nothing otherwise:
This structure means that Rust's core abstractions have powerful compile-time
correctness checking. But this comes at the price of reduced flexibility. If
you visually identify a pattern of repeated code, you may find it's difficult
or cumbersome to express that pattern as a generic function, a trait, or
anything else within Rust's semantics.
~~~~
# enum T { SpecialA(u32), SpecialB(u32) }
# fn f() -> u32 {
# let input_1 = T::SpecialA(0);
# let input_2 = T::SpecialA(0);
match input_1 {
T::SpecialA(x) => { return x; }
_ => {}
}
// ...
match input_2 {
T::SpecialB(x) => { return x; }
_ => {}
}
# return 0;
# }
~~~~
Macros allow us to abstract at a *syntactic* level. A macro invocation is
shorthand for an "expanded" syntactic form. This expansion happens early in
compilation, before any static checking. As a result, macros can capture many
patterns of code reuse that Rust's core abstractions cannot.
This code could become tiresome if repeated many times.
However, no function can capture its functionality to make it possible
to abstract the repetition away.
Rust's macro system, however, can eliminate the repetition. Macros are
lightweight custom syntax extensions, themselves defined using the
`macro_rules!` syntax extension. The following `early_return` macro captures
the pattern in the above code:
The drawback is that macro-based code can be harder to understand, because
fewer of the built-in rules apply. Like an ordinary function, a well-behaved
macro can be used without understanding its implementation. However, it can be
difficult to design a well-behaved macro! Additionally, compiler errors in
macro code are harder to interpret, because they describe problems in the
expanded code, not the source-level form that developers use.
~~~~
# enum T { SpecialA(u32), SpecialB(u32) }
# fn f() -> u32 {
# let input_1 = T::SpecialA(0);
# let input_2 = T::SpecialA(0);
macro_rules! early_return {
($inp:expr, $sp:path) => ( // invoke it like `(input_5, SpecialE)`
match $inp {
$sp(x) => { return x; }
_ => {}
}
);
}
// ...
early_return!(input_1, T::SpecialA);
// ...
early_return!(input_2, T::SpecialB);
# return 0;
# }
# fn main() {}
~~~~
These drawbacks make macros something of a "feature of last resort". That's not
to say that macros are bad; they are part of Rust because sometimes they're
needed for truly concise, well-abstracted code. Just keep this tradeoff in
mind.
Macros are defined in pattern-matching style: in the above example, the text
`($inp:expr, $sp:path)` that appears on the left-hand side of the `=>` is the
*macro invocation syntax*, a pattern denoting how to write a call to the
macro. The text on the right-hand side of the `=>`, beginning with `match
$inp`, is the *macro transcription syntax*: what the macro expands to.
# Defining a macro
# Invocation syntax
You may have seen the `vec!` macro, used to initialize a [vector][] with any
number of elements.
The macro invocation syntax specifies the syntax for the arguments to the
macro. It appears on the left-hand side of the `=>` in a macro definition. It
conforms to the following rules:
[vector]: arrays-vectors-and-slices.html
1. It must be surrounded by parentheses.
2. `$` has special meaning (described below).
3. The `()`s, `[]`s, and `{}`s it contains must balance. For example, `([)` is
forbidden.
4. Some arguments can be followed only by a limited set of separators, to
avoid ambiguity (described below).
```rust
let x: Vec<u32> = vec![1, 2, 3];
# assert_eq!(&[1,2,3], &x);
```
Otherwise, the invocation syntax is free-form.
This can't be an ordinary function, because it takes any number of arguments.
But we can imagine it as syntactic shorthand for
To take a fragment of Rust code as an argument, write `$` followed by a name
(for use on the right-hand side), followed by a `:`, followed by a *fragment
specifier*. The fragment specifier denotes the sort of fragment to match. The
most common fragment specifiers are:
```rust
let x: Vec<u32> = {
let mut temp_vec = Vec::new();
temp_vec.push(1);
temp_vec.push(2);
temp_vec.push(3);
temp_vec
};
# assert_eq!(&[1,2,3], &x);
```
* `ident` (an identifier, referring to a variable or item. Examples: `f`, `x`,
`foo`.)
* `expr` (an expression. Examples: `2 + 2`; `if true then { 1 } else { 2 }`;
`f(42)`.)
* `ty` (a type. Examples: `i32`, `Vec<(char, String)>`, `&T`.)
* `path` (a path to struct or enum variant. Example: `T::SpecialA`)
* `pat` (a pattern, usually appearing in a `match` or on the left-hand side of
a declaration. Examples: `Some(t)`; `(17, 'a')`; `_`.)
* `block` (a sequence of actions. Example: `{ log(error, "hi"); return 12; }`)
We can implement this shorthand, using a macro: [^actual]
The parser interprets any token that's not preceded by a `$` literally. Rust's usual
rules of tokenization apply,
[^actual]: The actual definition of `vec!` in libcollections differs from the
one presented here, for reasons of efficiency and reusability. Some
of these are mentioned in the [advanced macros chapter][].
So `($x:ident -> (($e:expr)))`, though excessively fancy, would designate a macro
that could be invoked like: `my_macro!(i->(( 2+2 )))`.
To avoid ambiguity, macro invocation syntax must conform to the following rules:
* `expr` must be followed by `=>`, `,` or `;`.
* `ty` and `path` must be followed by `=>`, `,`, `:`, `=`, `>` or `as`.
* `pat` must be followed by `=>`, `,` or `=`.
* `ident` and `block` can be followed by any token.
## Invocation location
A macro invocation may take the place of (and therefore expand to) an
expression, item, statement, or pattern. The Rust parser will parse the macro
invocation as a "placeholder" for whichever syntactic form is appropriate for
the location.
At expansion time, the output of the macro will be parsed as whichever of the
three nonterminals it stands in for. This means that a single macro might,
for example, expand to an item or an expression, depending on its arguments
(and cause a syntax error if it is called with the wrong argument for its
location). Although this behavior sounds excessively dynamic, it is known to
be useful under some circumstances.
# Transcription syntax
The right-hand side of the `=>` follows the same rules as the left-hand side,
except that a `$` need only be followed by the name of the syntactic fragment
to transcribe into the macro expansion; its type need not be repeated.
The right-hand side must be enclosed by delimiters, which the transcriber ignores.
Therefore `() => ((1,2,3))` is a macro that expands to a tuple expression,
`() => (let $x=$val)` is a macro that expands to a statement,
and `() => (1,2,3)` is a macro that expands to a syntax error
(since the transcriber interprets the parentheses on the right-hand-size as delimiters,
and `1,2,3` is not a valid Rust expression on its own).
Except for permissibility of `$name` (and `$(...)*`, discussed below), the
right-hand side of a macro definition is ordinary Rust syntax. In particular,
macro invocations (including invocations of the macro currently being defined)
are permitted in expression, statement, and item locations. However, nothing
else about the code is examined or executed by the macro system; execution
still has to wait until run-time.
## Interpolation location
The interpolation `$argument_name` may appear in any location consistent with
its fragment specifier (i.e., if it is specified as `ident`, it may be used
anywhere an identifier is permitted).
# Multiplicity
## Invocation
Going back to the motivating example, recall that `early_return` expanded into
a `match` that would `return` if the `match`'s scrutinee matched the
"special case" identifier provided as the second argument to `early_return`,
and do nothing otherwise. Now suppose that we wanted to write a
version of `early_return` that could handle a variable number of "special"
cases.
The syntax `$(...)*` on the left-hand side of the `=>` in a macro definition
accepts zero or more occurrences of its contents. It works much
like the `*` 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".
~~~~
# enum T { SpecialA(u32), SpecialB(u32), SpecialC(u32), SpecialD(u32) }
# fn f() -> u32 {
# let input_1 = T::SpecialA(0);
# let input_2 = T::SpecialA(0);
macro_rules! early_return {
($inp:expr, [ $($sp:path),+ ]) => (
match $inp {
```rust
macro_rules! vec {
( $( $x:expr ),* ) => {
{
let mut temp_vec = Vec::new();
$(
$sp(x) => { return x; }
)+
_ => {}
temp_vec.push($x);
)*
temp_vec
}
)
};
}
// ...
early_return!(input_1, [T::SpecialA,T::SpecialC,T::SpecialD]);
// ...
early_return!(input_2, [T::SpecialB]);
# return 0;
# }
# fn main() {}
~~~~
### Transcription
As the above example demonstrates, `$(...)*` is also valid on the right-hand
side of a macro definition. The behavior of `*` in transcription,
especially in cases where multiple `*`s are nested, and multiple different
names are involved, can seem somewhat magical and unintuitive at first. The
system that interprets them is called "Macro By Example". The two rules to
keep in mind are (1) the behavior of `$(...)*` is to walk through one "layer"
of repetitions for all of the `$name`s it contains in lockstep, and (2) each
`$name` must be under at least as many `$(...)*`s as it was matched against.
If it is under more, it'll be repeated, as appropriate.
## Parsing limitations
For technical reasons, there are two limitations to the treatment of syntax
fragments by the macro parser:
1. The parser will always parse as much as possible of a Rust syntactic
fragment. For example, if the comma were omitted from the syntax of
`early_return!` above, `input_1 [` would've been interpreted as the beginning
of an array index. In fact, invoking the macro would have been impossible.
2. The parser must have eliminated all ambiguity by the time it reaches a
`$name:fragment_specifier` declaration. This limitation can result in parse
errors when declarations occur at the beginning of, or immediately after,
a `$(...)*`. For example, the grammar `$($t:ty)* $e:expr` will always fail to
parse because the parser would be forced to choose between parsing `t` and
parsing `e`. Changing the invocation syntax to require a distinctive token in
front can solve the problem. In the above example, `$(T $t:ty)* E $e:exp`
solves the problem.
# Macro argument pattern matching
## Motivation
Now consider code like the following:
~~~~
# enum T1 { Good1(T2, u32), Bad1}
# struct T2 { body: T3 }
# enum T3 { Good2(u32), Bad2}
# fn f(x: T1) -> u32 {
match x {
T1::Good1(g1, val) => {
match g1.body {
T3::Good2(result) => {
// complicated stuff goes here
return result + val;
},
_ => panic!("Didn't get good_2")
}
}
_ => return 0 // default value
}
# }
# fn main() {}
~~~~
All the complicated stuff is deeply indented, and the error-handling code is
separated from matches that fail. We'd like to write a macro that performs
a match, but with a syntax that suits the problem better. The following macro
can solve the problem:
~~~~
macro_rules! biased_match {
// special case: `let (x) = ...` is illegal, so use `let x = ...` instead
( ($e:expr) -> ($p:pat) else $err:stmt ;
binds $bind_res:ident
) => (
let $bind_res = match $e {
$p => ( $bind_res ),
_ => { $err }
};
);
// more than one name; use a tuple
( ($e:expr) -> ($p:pat) else $err:stmt ;
binds $( $bind_res:ident ),*
) => (
let ( $( $bind_res ),* ) = match $e {
$p => ( $( $bind_res ),* ),
_ => { $err }
};
)
}
# enum T1 { Good1(T2, u32), Bad1}
# struct T2 { body: T3 }
# enum T3 { Good2(u32), Bad2}
# fn f(x: T1) -> u32 {
biased_match!((x) -> (T1::Good1(g1, val)) else { return 0 };
binds g1, val );
biased_match!((g1.body) -> (T3::Good2(result) )
else { panic!("Didn't get good_2") };
binds result );
// complicated stuff goes here
return result + val;
# }
# fn main() {}
~~~~
This solves the indentation problem. But if we have a lot of chained matches
like this, we might prefer to write a single macro invocation. The input
pattern we want is clear:
~~~~
# fn main() {}
# macro_rules! b {
( $( ($e:expr) -> ($p:pat) else $err:stmt ; )*
binds $( $bind_res:ident ),*
)
# => (0) }
~~~~
However, it's not possible to directly expand to nested match statements. But
there is a solution.
## The recursive approach to macro writing
A macro may accept multiple different input grammars. The first one to
successfully match the actual argument to a macro invocation is the one that
"wins".
In the case of the example above, we want to write a recursive macro to
process the semicolon-terminated lines, one-by-one. So, we want the following
input patterns:
~~~~
# macro_rules! b {
( binds $( $bind_res:ident ),* )
# => (0) }
# fn main() {}
~~~~
...and:
~~~~
# fn main() {}
# macro_rules! b {
( ($e :expr) -> ($p :pat) else $err :stmt ;
$( ($e_rest:expr) -> ($p_rest:pat) else $err_rest:stmt ; )*
binds $( $bind_res:ident ),*
)
# => (0) }
~~~~
The resulting macro looks like this. Note that the separation into
`biased_match!` and `biased_match_rec!` occurs only because we have an outer
piece of syntax (the `let`) which we only want to transcribe once.
~~~~
# fn main() {
macro_rules! biased_match_rec {
// Handle the first layer
( ($e :expr) -> ($p :pat) else $err :stmt ;
$( ($e_rest:expr) -> ($p_rest:pat) else $err_rest:stmt ; )*
binds $( $bind_res:ident ),*
) => (
match $e {
$p => {
// Recursively handle the next layer
biased_match_rec!($( ($e_rest) -> ($p_rest) else $err_rest ; )*
binds $( $bind_res ),*
)
}
_ => { $err }
}
);
// Produce the requested values
( binds $( $bind_res:ident ),* ) => ( ($( $bind_res ),*) )
}
// Wrap the whole thing in a `let`.
macro_rules! biased_match {
// special case: `let (x) = ...` is illegal, so use `let x = ...` instead
( $( ($e:expr) -> ($p:pat) else $err:stmt ; )*
binds $bind_res:ident
) => (
let $bind_res = biased_match_rec!(
$( ($e) -> ($p) else $err ; )*
binds $bind_res
);
);
// more than one name: use a tuple
( $( ($e:expr) -> ($p:pat) else $err:stmt ; )*
binds $( $bind_res:ident ),*
) => (
let ( $( $bind_res ),* ) = biased_match_rec!(
$( ($e) -> ($p) else $err ; )*
binds $( $bind_res ),*
);
)
}
# enum T1 { Good1(T2, u32), Bad1}
# struct T2 { body: T3 }
# enum T3 { Good2(u32), Bad2}
# fn f(x: T1) -> u32 {
biased_match!(
(x) -> (T1::Good1(g1, val)) else { return 0 };
(g1.body) -> (T3::Good2(result) ) else { panic!("Didn't get Good2") };
binds val, result );
// complicated stuff goes here
return result + val;
# assert_eq!(&[1,2,3], &vec![1,2,3]);
# }
# }
~~~~
```
This technique applies to many cases where transcribing a result all at once is not possible.
The resulting code resembles ordinary functional programming in some respects,
but has some important differences from functional programming.
Whoa, that's a lot of new syntax! Let's break it down.
The first difference is important, but also easy to forget: the transcription
(right-hand) side of a `macro_rules!` rule is literal syntax, which can only
be executed at run-time. If a piece of transcription syntax does not itself
appear inside another macro invocation, it will become part of the final
program. If it is inside a macro invocation (for example, the recursive
invocation of `biased_match_rec!`), it does have the opportunity to affect
transcription, but only through the process of attempted pattern matching.
```ignore
macro_rules! vec { ... }
```
The second, related, difference is that the evaluation order of macros feels
"backwards" compared to ordinary programming. Given an invocation
`m1!(m2!())`, the expander first expands `m1!`, giving it as input the literal
syntax `m2!()`. If it transcribes its argument unchanged into an appropriate
position (in particular, not as an argument to yet another macro invocation),
the expander will then proceed to evaluate `m2!()` (along with any other macro
invocations `m1!(m2!())` produced).
This says we're defining a macro named `vec`, much as `fn vec` would define a
function named `vec`. In prose, we informally write a macro's name with an
exclamation point, e.g. `vec!`. The exclamation point is part of the invocation
syntax and serves to distinguish a macro from an ordinary function.
# Hygiene
## Matching
To prevent clashes, rust implements
[hygienic macros](http://en.wikipedia.org/wiki/Hygienic_macro).
The macro is defined through a series of *rules*, which are pattern-matching
cases. Above, we had
As an example, `loop` and `for-loop` labels (discussed in the lifetimes guide)
will not clash. The following code will print "Hello!" only once:
```ignore
( $( $x:expr ),* ) => { ... };
```
~~~
macro_rules! loop_x {
($e: expr) => (
// $e will not interact with this 'x
'x: loop {
println!("Hello!");
$e
}
);
This is like a `match` expression arm, but the matching happens on Rust syntax
trees, at compile time. The semicolon is optional on the last (here, only)
case. The "pattern" on the left-hand side of `=>` is known as a *matcher*.
These have [their own little grammar] within the language.
[their own little grammar]: ../reference.html#macros
The matcher `$x:expr` will match any Rust expression, binding that syntax tree
to the *metavariable* `$x`. The identifier `expr` is a *fragment specifier*;
the full possibilities are enumerated in the [advanced macros chapter][].
Surrounding the matcher with `$(...),*` will match zero or more expressions,
separated by commas.
Aside from the special matcher syntax, any Rust tokens that appear in a matcher
must match exactly. For example,
```rust
macro_rules! foo {
(x => $e:expr) => (println!("mode X: {}", $e));
(y => $e:expr) => (println!("mode Y: {}", $e));
}
fn main() {
'x: loop {
loop_x!(break 'x);
println!("I am never printed.");
}
foo!(y => 3);
}
~~~
```
The two `'x` names did not clash, which would have caused the loop
to print "I am never printed" and to run forever.
will print
# Scoping and macro import/export
```text
mode Y: 3
```
Macros are expanded at an early stage in compilation, before name resolution.
One downside is that scoping works differently for macros, compared to other
constructs in the language.
Definition and expansion of macros both happen in a single depth-first,
lexical-order traversal of a crate's source. So a macro defined at module scope
is visible to any subsequent code in the same module, which includes the body
of any subsequent child `mod` items.
A macro defined within the body of a single `fn`, or anywhere else not at
module scope, is visible only within that item.
If a module has the `macro_use` attribute, its macros are also visible in its
parent module after the child's `mod` item. If the parent also has `macro_use`
then the macros will be visible in the grandparent after the parent's `mod`
item, and so forth.
The `macro_use` attribute can also appear on `extern crate`. In this context
it controls which macros are loaded from the external crate, e.g.
With
```rust,ignore
#[macro_use(foo, bar)]
extern crate baz;
foo!(z => 3);
```
If the attribute is given simply as `#[macro_use]`, all macros are loaded. If
there is no `#[macro_use]` attribute then no macros are loaded. Only macros
defined with the `#[macro_export]` attribute may be loaded.
we get the compiler error
To load a crate's macros *without* linking it into the output, use `#[no_link]`
as well.
```text
error: no rules expected the token `z`
```
An example:
## Expansion
The right-hand side of a macro rule is ordinary Rust syntax, for the most part.
But we can splice in bits of syntax captured by the matcher. From the original
example:
```ignore
$(
temp_vec.push($x);
)*
```
Each matched expression `$x` will produce a single `push` statement in the
macro expansion. The repetition in the expansion proceeds in "lockstep" with
repetition in the matcher (more on this in a moment).
Because `$x` was already declared as matching an expression, we don't repeat
`:expr` on the right-hand side. Also, we don't include a separating comma as
part of the repetition operator. Instead, we have a terminating semicolon
within the repeated block.
Another detail: the `vec!` macro has *two* pairs of braces on the right-hand
side. They are often combined like so:
```ignore
macro_rules! foo {
() => {{
...
}}
}
```
The outer braces are part of the syntax of `macro_rules!`. In fact, you can use
`()` or `[]` instead. They simply delimit the right-hand side as a whole.
The inner braces are part of the expanded syntax. Remember, the `vec!` macro is
used in an expression context. To write an expression with multiple statements,
including `let`-bindings, we use a block. If your macro expands to a single
expression, you don't need this extra layer of braces.
Note that we never *declared* that the macro produces an expression. In fact,
this is not determined until we use the macro as an expression. With care, you
can write a macro whose expansion works in several contexts. For example,
shorthand for a data type could be valid as either an expression or a pattern.
## Repetition
The repetition behavior can seem somewhat magical, especially when multiple
names are bound at multiple nested levels of repetition. The two rules to keep
in mind are:
1. the behavior of `$(...)*` is to walk through one "layer" of repetitions, for
all of the `$name`s it contains, in lockstep, and
2. each `$name` must be under at least as many `$(...)*`s as it was matched
against. If it is under more, it'll be duplicated, as appropriate.
This baroque macro illustrates the duplication of variables from outer
repetition levels.
```rust
macro_rules! m1 { () => (()) }
// visible here: m1
mod foo {
// visible here: m1
#[macro_export]
macro_rules! m2 { () => (()) }
// visible here: m1, m2
macro_rules! o_O {
(
$(
$x:expr; [ $( $y:expr ),* ]
);*
) => {
&[ $($( $x + $y ),*),* ]
}
}
// visible here: m1
fn main() {
let a: &[i32]
= o_O!(10; [1, 2, 3];
20; [4, 5, 6]);
macro_rules! m3 { () => (()) }
// visible here: m1, m3
#[macro_use]
mod bar {
// visible here: m1, m3
macro_rules! m4 { () => (()) }
// visible here: m1, m3, m4
assert_eq!(a, [11, 12, 13, 24, 25, 26]);
}
// visible here: m1, m3, m4
# fn main() { }
```
When this library is loaded with `#[use_macros] extern crate`, only `m2` will
be imported.
That's most of the matcher syntax. These examples use `$(...)*`, which is a
"zero or more" match. Alternatively you can write `$(...)+` for a "one or
more" match. Both forms optionally include a separator, which can be any token
except `+` or `*`.
The Rust Reference has a [listing of macro-related
attributes](../reference.html#macro--and-plugin-related-attributes).
# Hygiene
# The variable `$crate`
Some languages implement macros using simple text substitution, which leads to
various problems. For example, this C program prints `13` instead of the
expected `25`.
A further difficulty occurs when a macro is used in multiple crates. Say that
`mylib` defines
```text
#define FIVE_TIMES(x) 5 * x
int main() {
printf("%d\n", FIVE_TIMES(2 + 3));
return 0;
}
```
After expansion we have `5 * 2 + 3`, and multiplication has greater precedence
than addition. If you've used C macros a lot, you probably know the standard
idioms for avoiding this problem, as well as five or six others. In Rust, we
don't have to worry about it.
```rust
pub fn increment(x: u32) -> u32 {
x + 1
macro_rules! five_times {
($x:expr) => (5 * $x);
}
#[macro_export]
macro_rules! inc_a {
($x:expr) => ( ::increment($x) )
fn main() {
assert_eq!(25, five_times!(2 + 3));
}
#[macro_export]
macro_rules! inc_b {
($x:expr) => ( ::mylib::increment($x) )
}
# fn main() { }
```
`inc_a` only works within `mylib`, while `inc_b` only works outside the
library. Furthermore, `inc_b` will break if the user imports `mylib` under
another name.
The metavariable `$x` is parsed as a single expression node, and keeps its
place in the syntax tree even after substitution.
Rust does not (yet) have a hygiene system for crate references, but it does
provide a simple workaround for this problem. Within a macro imported from a
crate named `foo`, the special macro variable `$crate` will expand to `::foo`.
By contrast, when a macro is defined and then used in the same crate, `$crate`
will expand to nothing. This means we can write
Another common problem in macro systems is *variable capture*. Here's a C
macro, using [a GNU C extension] to emulate Rust's expression blocks.
[a GNU C extension]: https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html
```text
#define LOG(msg) ({ \
int state = get_log_state(); \
if (state > 0) { \
printf("log(%d): %s\n", state, msg); \
} \
})
```
This looks reasonable, but watch what happens in this example:
```text
const char *state = "reticulating splines";
LOG(state);
```
The program will likely segfault, after it tries to execute
```text
printf("log(%d): %s\n", state, state);
```
The equivalent Rust macro has the desired behavior.
```rust
#[macro_export]
macro_rules! inc {
($x:expr) => ( $crate::increment($x) )
# fn get_log_state() -> i32 { 3 }
macro_rules! log {
($msg:expr) => {{
let state: i32 = get_log_state();
if state > 0 {
println!("log({}): {}", state, $msg);
}
}};
}
fn main() {
let state: &str = "reticulating splines";
log!(state);
}
# fn main() { }
```
to define a single macro that works both inside and outside our library. The
function name will expand to either `::increment` or `::mylib::increment`.
This works because Rust has a [hygienic macro system][]. Each macro expansion
happens in a distinct *syntax context*, and each variable is tagged with the
syntax context where it was introduced. It's as though the variable `state`
inside `main` is painted a different "color" from the variable `state` inside
the macro, and therefore they don't conflict.
To keep this system simple and correct, `#[macro_use] extern crate ...` may
only appear at the root of your crate, not inside `mod`. This ensures that
`$crate` is a single identifier.
[hygienic macro system]: http://en.wikipedia.org/wiki/Hygienic_macro
# A final note
This also restricts the ability of macros to introduce new bindings at the
invocation site. Code such as the following will not work:
Macros, as currently implemented, are not for the faint of heart. Even
ordinary syntax errors can be more difficult to debug when they occur inside a
macro, and errors caused by parse problems in generated code can be very
tricky. Invoking the `log_syntax!` macro can help elucidate intermediate
states, invoking `trace_macros!(true)` will automatically print those
intermediate states out, and passing the flag `--pretty expanded` as a
command-line argument to the compiler will show the result of expansion.
```rust,ignore
macro_rules! foo {
() => (let x = 3);
}
If Rust's macro system can't do what you need, you may want to write a
[compiler plugin](plugins.html) instead. Compared to `macro_rules!`
macros, this is significantly more work, the interfaces are much less stable,
and the warnings about debugging apply ten-fold. In exchange you get the
flexibility of running arbitrary Rust code within the compiler. Syntax
extension plugins are sometimes called *procedural macros* for this reason.
fn main() {
foo!();
println!("{}", x);
}
```
Instead you need to pass the variable name into the invocation, so it's tagged
with the right syntax context.
```rust
macro_rules! foo {
($v:ident) => (let $v = 3);
}
fn main() {
foo!(x);
println!("{}", x);
}
```
This holds for `let` bindings and loop labels, but not for [items][].
So the following code does compile:
```rust
macro_rules! foo {
() => (fn x() { });
}
fn main() {
foo!();
x();
}
```
[items]: ../reference.html#items
# Further reading
The [advanced macros chapter][] goes into more detail about macro syntax. It
also describes how to share macros between different modules or crates.
[advanced macros chapter]: advanced-macros.html

View file

@ -99,8 +99,8 @@ fn grow(&self) -> Circle {
# Circle } }
```
We just say we're returning a `Circle`. With this, we can grow a new circle
that's twice as big as the old one.
We just say we're returning a `Circle`. With this method, we can grow a new
circle with an area that's 100 times larger than the old one.
## Static methods

View file

@ -293,7 +293,7 @@ struct Foo<'a> {
}
fn main() {
let y = &5; // this is the same as `let _y = 5; let y = &_y;
let y = &5; // this is the same as `let _y = 5; let y = &_y;`
let f = Foo { x: y };
println!("{}", f.x);

View file

@ -273,6 +273,96 @@ One last thing about traits: generic functions with a trait bound use
dispatched. What's that mean? Check out the chapter on [static and dynamic
dispatch](static-and-dynamic-dispatch.html) for more.
## Where clause
Writing functions with only a few generic types and a small number of trait
bounds isn't too bad, but as the number increases, the syntax gets increasingly
awkward:
```
use std::fmt::Debug;
fn foo<T: Clone, K: Clone + Debug>(x: T, y: K) {
x.clone();
y.clone();
println!("{:?}", y);
}
```
The name of the function is on the far left, and the parameter list is on the
far right. The bounds are getting in the way.
Rust has a solution, and it's called a '`where` clause':
```
use std::fmt::Debug;
fn foo<T: Clone, K: Clone + Debug>(x: T, y: K) {
x.clone();
y.clone();
println!("{:?}", y);
}
fn bar<T, K>(x: T, y: K) where T: Clone, K: Clone + Debug {
x.clone();
y.clone();
println!("{:?}", y);
}
fn main() {
foo("Hello", "world");
bar("Hello", "workd");
}
```
`foo()` uses the syntax we showed earlier, and `bar()` uses a `where` clause.
All you need to do is leave off the bounds when defining your type parameters,
and then add `where` after the parameter list. For longer lists, whitespace can
be added:
```
use std::fmt::Debug;
fn bar<T, K>(x: T, y: K)
where T: Clone,
K: Clone + Debug {
x.clone();
y.clone();
println!("{:?}", y);
}
```
This flexibility can add clarity in complex situations.
`where` is also more powerful than the simpler syntax. For example:
```
trait ConvertTo<Output> {
fn convert(&self) -> Output;
}
impl ConvertTo<i64> for i32 {
fn convert(&self) -> i64 { *self as i64 }
}
// can be called with T == i32
fn normal<T: ConvertTo<i64>>(x: &T) -> i64 {
x.convert()
}
// can be called with T == i64
fn inverse<T>() -> T
// this is using ConvertTo as if it were "ConvertFrom<i32>"
where i32: ConvertTo<T> {
1i32.convert()
}
```
This shows off the additional feature of `where` clauses: they allow bounds
where the left-hand side is an arbitrary type (`i32` in this case), not just a
plain type parameter (like `T`).
## Our `inverse` Example
Back in [Generics](generics.html), we were trying to write code like this:

View file

@ -308,7 +308,7 @@ crate to allow) and of course requires an `unsafe` block.
## Assembly template
The `assembly template` is the only required parameter and must be a
literal string (i.e `""`)
literal string (i.e. `""`)
```
#![feature(asm)]
@ -412,7 +412,7 @@ memory, `memory` should also be specified.
## Options
The last section, `options` is specific to Rust. The format is comma
separated literal strings (i.e `:"foo", "bar", "baz"`). It's used to
separated literal strings (i.e. `:"foo", "bar", "baz"`). It's used to
specify some extra info about the inline assembly:
Current valid options are:
@ -420,7 +420,7 @@ Current valid options are:
1. *volatile* - specifying this is analogous to
`__asm__ __volatile__ (...)` in gcc/clang.
2. *alignstack* - certain instructions expect the stack to be
aligned a certain way (i.e SSE) and specifying this indicates to
aligned a certain way (i.e. SSE) and specifying this indicates to
the compiler to insert its usual stack alignment code
3. *intel* - use intel syntax instead of the default AT&T.
@ -646,8 +646,8 @@ The `rustc` compiler has certain pluggable operations, that is,
functionality that isn't hard-coded into the language, but is
implemented in libraries, with a special marker to tell the compiler
it exists. The marker is the attribute `#[lang="..."]` and there are
various different values of `...`, i.e. various different "lang
items".
various different values of `...`, i.e. various different 'lang
items'.
For example, `Box` pointers require two lang items, one for allocation
and one for deallocation. A freestanding program that uses the `Box`

View file

@ -35,14 +35,14 @@
//!
//! ```
//! use std::sync::Arc;
//! use std::thread::Thread;
//! use std::thread;
//!
//! let five = Arc::new(5);
//!
//! for _ in 0..10 {
//! let five = five.clone();
//!
//! Thread::spawn(move || {
//! thread::spawn(move || {
//! println!("{:?}", five);
//! });
//! }
@ -52,14 +52,14 @@
//!
//! ```
//! use std::sync::{Arc, Mutex};
//! use std::thread::Thread;
//! use std::thread;
//!
//! let five = Arc::new(Mutex::new(5));
//!
//! for _ in 0..10 {
//! let five = five.clone();
//!
//! Thread::spawn(move || {
//! thread::spawn(move || {
//! let mut number = five.lock().unwrap();
//!
//! *number += 1;
@ -95,7 +95,7 @@
///
/// ```rust
/// use std::sync::Arc;
/// use std::thread::Thread;
/// use std::thread;
///
/// fn main() {
/// let numbers: Vec<_> = (0..100u32).map(|i| i as f32).collect();
@ -104,7 +104,7 @@
/// for _ in 0..10 {
/// let child_numbers = shared_numbers.clone();
///
/// Thread::spawn(move || {
/// thread::spawn(move || {
/// let local_numbers = child_numbers.as_slice();
///
/// // Work with the local numbers
@ -621,7 +621,7 @@ mod tests {
use std::option::Option::{Some, None};
use std::sync::atomic;
use std::sync::atomic::Ordering::{Acquire, SeqCst};
use std::thread::Thread;
use std::thread;
use std::vec::Vec;
use super::{Arc, Weak, weak_count, strong_count};
use std::sync::Mutex;
@ -648,7 +648,7 @@ fn manually_share_arc() {
let (tx, rx) = channel();
let _t = Thread::spawn(move || {
let _t = thread::spawn(move || {
let arc_v: Arc<Vec<i32>> = rx.recv().unwrap();
assert_eq!((*arc_v)[3], 4);
});

View file

@ -126,11 +126,3 @@ pub fn oom() -> ! {
// optimize it out).
#[doc(hidden)]
pub fn fixme_14344_be_sure_to_link_to_collections() {}
// NOTE: remove after next snapshot
#[cfg(all(stage0, not(test)))]
#[doc(hidden)]
mod std {
pub use core::fmt;
pub use core::option;
}

View file

@ -170,7 +170,7 @@ struct RcBox<T> {
weak: Cell<usize>
}
/// An immutable reference-counted pointer type.
/// A reference-counted pointer type over an immutable value.
///
/// See the [module level documentation](./index.html) for more details.
#[unsafe_no_drop_flag]
@ -776,9 +776,7 @@ fn inner(&self) -> &RcBox<T> {
// the contract anyway.
// This allows the null check to be elided in the destructor if we
// manipulated the reference count in the same function.
if cfg!(not(stage0)) { // NOTE remove cfg after next snapshot
assume(!self._ptr.is_null());
}
assume(!self._ptr.is_null());
&(**self._ptr)
}
}
@ -792,9 +790,7 @@ fn inner(&self) -> &RcBox<T> {
// the contract anyway.
// This allows the null check to be elided in the destructor if we
// manipulated the reference count in the same function.
if cfg!(not(stage0)) { // NOTE remove cfg after next snapshot
assume(!self._ptr.is_null());
}
assume(!self._ptr.is_null());
&(**self._ptr)
}
}

View file

@ -655,17 +655,7 @@ fn from_iter<Iter: Iterator<Item=T>>(iter: Iter) -> BinaryHeap<T> {
}
}
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
impl<T: Ord> IntoIterator for BinaryHeap<T> {
type IntoIter = IntoIter<T>;
fn into_iter(self) -> IntoIter<T> {
self.into_iter()
}
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Ord> IntoIterator for BinaryHeap<T> {
type Item = T;
type IntoIter = IntoIter<T>;
@ -675,17 +665,7 @@ fn into_iter(self) -> IntoIter<T> {
}
}
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
impl<'a, T> IntoIterator for &'a BinaryHeap<T> where T: Ord {
type IntoIter = Iter<'a, T>;
fn into_iter(self) -> Iter<'a, T> {
self.iter()
}
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> IntoIterator for &'a BinaryHeap<T> where T: Ord {
type Item = &'a T;
type IntoIter = Iter<'a, T>;

View file

@ -1070,17 +1070,7 @@ fn idx(&mut self, index: usize) -> Option<bool> {
}
}
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
impl<'a> IntoIterator for &'a Bitv {
type IntoIter = Iter<'a>;
fn into_iter(self) -> Iter<'a> {
self.iter()
}
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> IntoIterator for &'a Bitv {
type Item = bool;
type IntoIter = Iter<'a>;
@ -1894,17 +1884,7 @@ impl<'a> Iterator for SymmetricDifference<'a> {
#[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.0.size_hint() }
}
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
impl<'a> IntoIterator for &'a BitvSet {
type IntoIter = SetIter<'a>;
fn into_iter(self) -> SetIter<'a> {
self.iter()
}
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> IntoIterator for &'a BitvSet {
type Item = usize;
type IntoIter = SetIter<'a>;

View file

@ -462,17 +462,7 @@ pub fn remove<Q: ?Sized>(&mut self, key: &Q) -> Option<V> where Q: BorrowFrom<K>
}
}
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
impl<K, V> IntoIterator for BTreeMap<K, V> {
type IntoIter = IntoIter<K, V>;
fn into_iter(self) -> IntoIter<K, V> {
self.into_iter()
}
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[stable(feature = "rust1", since = "1.0.0")]
impl<K, V> IntoIterator for BTreeMap<K, V> {
type Item = (K, V);
type IntoIter = IntoIter<K, V>;
@ -482,17 +472,7 @@ fn into_iter(self) -> IntoIter<K, V> {
}
}
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
impl<'a, K, V> IntoIterator for &'a BTreeMap<K, V> {
type IntoIter = Iter<'a, K, V>;
fn into_iter(self) -> Iter<'a, K, V> {
self.iter()
}
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, K, V> IntoIterator for &'a BTreeMap<K, V> {
type Item = (&'a K, &'a V);
type IntoIter = Iter<'a, K, V>;
@ -502,17 +482,7 @@ fn into_iter(self) -> Iter<'a, K, V> {
}
}
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
impl<'a, K, V> IntoIterator for &'a mut BTreeMap<K, V> {
type IntoIter = IterMut<'a, K, V>;
fn into_iter(mut self) -> IterMut<'a, K, V> {
self.iter_mut()
}
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, K, V> IntoIterator for &'a mut BTreeMap<K, V> {
type Item = (&'a K, &'a mut V);
type IntoIter = IterMut<'a, K, V>;

View file

@ -480,17 +480,7 @@ fn from_iter<Iter: Iterator<Item=T>>(iter: Iter) -> BTreeSet<T> {
}
}
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
impl<T> IntoIterator for BTreeSet<T> {
type IntoIter = IntoIter<T>;
fn into_iter(self) -> IntoIter<T> {
self.into_iter()
}
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> IntoIterator for BTreeSet<T> {
type Item = T;
type IntoIter = IntoIter<T>;
@ -500,17 +490,7 @@ fn into_iter(self) -> IntoIter<T> {
}
}
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
impl<'a, T> IntoIterator for &'a BTreeSet<T> {
type IntoIter = Iter<'a, T>;
fn into_iter(self) -> Iter<'a, T> {
self.iter()
}
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> IntoIterator for &'a BTreeSet<T> {
type Item = &'a T;
type IntoIter = Iter<'a, T>;

View file

@ -837,17 +837,7 @@ fn from_iter<T: Iterator<Item=A>>(iterator: T) -> DList<A> {
}
}
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
impl<T> IntoIterator for DList<T> {
type IntoIter = IntoIter<T>;
fn into_iter(self) -> IntoIter<T> {
self.into_iter()
}
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> IntoIterator for DList<T> {
type Item = T;
type IntoIter = IntoIter<T>;
@ -857,17 +847,7 @@ fn into_iter(self) -> IntoIter<T> {
}
}
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
impl<'a, T> IntoIterator for &'a DList<T> {
type IntoIter = Iter<'a, T>;
fn into_iter(self) -> Iter<'a, T> {
self.iter()
}
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> IntoIterator for &'a DList<T> {
type Item = &'a T;
type IntoIter = Iter<'a, T>;
@ -877,17 +857,6 @@ fn into_iter(self) -> Iter<'a, T> {
}
}
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
impl<'a, T> IntoIterator for &'a mut DList<T> {
type IntoIter = IterMut<'a, T>;
fn into_iter(mut self) -> IterMut<'a, T> {
self.iter_mut()
}
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
impl<'a, T> IntoIterator for &'a mut DList<T> {
type Item = &'a mut T;
type IntoIter = IterMut<'a, T>;
@ -971,7 +940,7 @@ mod tests {
use prelude::*;
use std::rand;
use std::hash::{self, SipHasher};
use std::thread::Thread;
use std::thread;
use test::Bencher;
use test;
@ -1320,7 +1289,7 @@ fn test_mut_rev_iter() {
#[test]
fn test_send() {
let n = list_from(&[1,2,3]);
Thread::scoped(move || {
thread::spawn(move || {
check_links(&n);
let a: &[_] = &[&1,&2,&3];
assert_eq!(a, n.iter().collect::<Vec<_>>());

View file

@ -257,17 +257,7 @@ fn from_iter<I:Iterator<Item=E>>(iterator: I) -> EnumSet<E> {
}
}
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
impl<'a, E> IntoIterator for &'a EnumSet<E> where E: CLike {
type IntoIter = Iter<E>;
fn into_iter(self) -> Iter<E> {
self.iter()
}
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, E> IntoIterator for &'a EnumSet<E> where E: CLike {
type Item = E;
type IntoIter = Iter<E>;

View file

@ -111,15 +111,6 @@ pub fn fixme_14344_be_sure_to_link_to_collections() {}
#[cfg(not(test))]
mod std {
// NOTE: remove after next snapshot
#[cfg(stage0)] pub use core::clone; // derive(Clone)
#[cfg(stage0)] pub use core::cmp; // derive(Eq, Ord, etc.)
#[cfg(stage0)] pub use core::marker; // derive(Copy)
#[cfg(stage0)] pub use core::hash; // derive(Hash)
#[cfg(stage0)] pub use core::iter;
#[cfg(stage0)] pub use core::fmt; // necessary for panic!()
#[cfg(stage0)] pub use core::option; // necessary for panic!()
pub use core::ops; // RangeFull
}

View file

@ -9,12 +9,34 @@
// except according to those terms.
/// Creates a `Vec` containing the arguments.
///
/// `vec!` allows `Vec`s to be defined with the same syntax as array expressions.
/// There are two forms of this macro:
///
/// - Create a `Vec` containing a given list of elements:
///
/// ```
/// let v = vec![1, 2, 3];
/// assert_eq!(v[0], 1);
/// assert_eq!(v[1], 2);
/// assert_eq!(v[2], 3);
/// ```
///
/// - Create a `Vec` from a given element and size:
///
/// ```
/// let v = vec![1; 3];
/// assert_eq!(v, vec![1, 1, 1]);
/// ```
///
/// Note that unlike array expressions this syntax supports all elements
/// which implement `Clone` and the number of elements doesn't have to be
/// a constant.
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
macro_rules! vec {
($x:expr; $y:expr) => (
<[_] as $crate::slice::SliceExt>::into_vec(
$crate::boxed::Box::new([$x; $y]))
($elem:expr; $n:expr) => (
$crate::vec::from_elem($elem, $n)
);
($($x:expr),*) => (
<[_] as $crate::slice::SliceExt>::into_vec(

View file

@ -8,9 +8,13 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! This crate implements a double-ended queue with `O(1)` amortized inserts and removals from both
//! ends of the container. It also has `O(1)` indexing like a vector. The contained elements are
//! not required to be copyable, and the queue will be sendable if the contained type is sendable.
//! RingBuf is a double-ended queue, which is implemented with the help of a
//! growing circular buffer.
//!
//! This queue has `O(1)` amortized inserts and removals from both ends of the
//! container. It also has `O(1)` indexing like a vector. The contained elements
//! are not required to be copyable, and the queue will be sendable if the
//! contained type is sendable.
#![stable(feature = "rust1", since = "1.0.0")]
@ -113,7 +117,8 @@ unsafe fn buffer_write(&mut self, off: usize, t: T) {
#[inline]
fn is_full(&self) -> bool { self.cap - self.len() == 1 }
/// Returns the index in the underlying buffer for a given logical element index.
/// Returns the index in the underlying buffer for a given logical element
/// index.
#[inline]
fn wrap_index(&self, idx: usize) -> usize { wrap_index(idx, self.cap) }
@ -1699,17 +1704,7 @@ fn from_iter<T: Iterator<Item=A>>(iterator: T) -> RingBuf<A> {
}
}
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
impl<T> IntoIterator for RingBuf<T> {
type IntoIter = IntoIter<T>;
fn into_iter(self) -> IntoIter<T> {
self.into_iter()
}
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> IntoIterator for RingBuf<T> {
type Item = T;
type IntoIter = IntoIter<T>;
@ -1719,17 +1714,7 @@ fn into_iter(self) -> IntoIter<T> {
}
}
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
impl<'a, T> IntoIterator for &'a RingBuf<T> {
type IntoIter = Iter<'a, T>;
fn into_iter(self) -> Iter<'a, T> {
self.iter()
}
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> IntoIterator for &'a RingBuf<T> {
type Item = &'a T;
type IntoIter = Iter<'a, T>;
@ -1739,17 +1724,7 @@ fn into_iter(self) -> Iter<'a, T> {
}
}
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
impl<'a, T> IntoIterator for &'a mut RingBuf<T> {
type IntoIter = IterMut<'a, T>;
fn into_iter(mut self) -> IterMut<'a, T> {
self.iter_mut()
}
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> IntoIterator for &'a mut RingBuf<T> {
type Item = &'a mut T;
type IntoIter = IterMut<'a, T>;

View file

@ -1252,6 +1252,30 @@ unsafe fn dealloc<T>(ptr: *mut T, len: usize) {
}
}
#[doc(hidden)]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn from_elem<T: Clone>(elem: T, n: usize) -> Vec<T> {
unsafe {
let mut v = Vec::with_capacity(n);
let mut ptr = v.as_mut_ptr();
// Write all elements except the last one
for i in 1..n {
ptr::write(ptr, Clone::clone(&elem));
ptr = ptr.offset(1);
v.set_len(i); // Increment the length in every step in case Clone::clone() panics
}
if n > 0 {
// We can write the last element directly without cloning needlessly
ptr::write(ptr, elem);
v.set_len(n);
}
v
}
}
////////////////////////////////////////////////////////////////////////////////
// Common trait implementations for Vec
////////////////////////////////////////////////////////////////////////////////
@ -1383,7 +1407,7 @@ fn deref_mut(&mut self) -> &mut [T] { self.as_mut_slice() }
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> FromIterator<T> for Vec<T> {
#[inline]
fn from_iter<I:Iterator<Item=T>>(iterator: I) -> Vec<T> {
fn from_iter<I:Iterator<Item=T>>(mut iterator: I) -> Vec<T> {
let (lower, _) = iterator.size_hint();
let mut vector = Vec::with_capacity(lower);
@ -1393,13 +1417,20 @@ fn from_iter<I:Iterator<Item=T>>(iterator: I) -> Vec<T> {
// vector.push(item);
// }
//
// This equivalent crucially runs the iterator precisely once. The
// optimization below (eliding bound/growth checks) means that we
// actually run the iterator twice. To ensure the "moral equivalent" we
// do a `fuse()` operation to ensure that the iterator continues to
// return `None` after seeing the first `None`.
let mut i = iterator.fuse();
for element in i.by_ref().take(vector.capacity()) {
// This equivalent crucially runs the iterator precisely once. Below we
// actually in theory run the iterator twice (one without bounds checks
// and one with). To achieve the "moral equivalent", we use the `if`
// statement below to break out early.
//
// If the first loop has terminated, then we have one of two conditions.
//
// 1. The underlying iterator returned `None`. In this case we are
// guaranteed that less than `vector.capacity()` elements have been
// returned, so we break out early.
// 2. The underlying iterator yielded `vector.capacity()` elements and
// has not yielded `None` yet. In this case we run the iterator to
// its end below.
for element in iterator.by_ref().take(vector.capacity()) {
let len = vector.len();
unsafe {
ptr::write(vector.get_unchecked_mut(len), element);
@ -1407,24 +1438,16 @@ fn from_iter<I:Iterator<Item=T>>(iterator: I) -> Vec<T> {
}
}
for element in i {
vector.push(element)
if vector.len() == vector.capacity() {
for element in iterator {
vector.push(element);
}
}
vector
}
}
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
impl<T> IntoIterator for Vec<T> {
type IntoIter = IntoIter<T>;
fn into_iter(self) -> IntoIter<T> {
self.into_iter()
}
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> IntoIterator for Vec<T> {
type Item = T;
type IntoIter = IntoIter<T>;
@ -1434,17 +1457,7 @@ fn into_iter(self) -> IntoIter<T> {
}
}
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
impl<'a, T> IntoIterator for &'a Vec<T> {
type IntoIter = slice::Iter<'a, T>;
fn into_iter(self) -> slice::Iter<'a, T> {
self.iter()
}
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> IntoIterator for &'a Vec<T> {
type Item = &'a T;
type IntoIter = slice::Iter<'a, T>;
@ -1454,17 +1467,7 @@ fn into_iter(self) -> slice::Iter<'a, T> {
}
}
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
impl<'a, T> IntoIterator for &'a mut Vec<T> {
type IntoIter = slice::IterMut<'a, T>;
fn into_iter(mut self) -> slice::IterMut<'a, T> {
self.iter_mut()
}
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> IntoIterator for &'a mut Vec<T> {
type Item = &'a mut T;
type IntoIter = slice::IterMut<'a, T>;

View file

@ -668,17 +668,7 @@ fn from_iter<Iter: Iterator<Item=(usize, V)>>(iter: Iter) -> VecMap<V> {
}
}
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
impl<T> IntoIterator for VecMap<T> {
type IntoIter = IntoIter<T>;
fn into_iter(self) -> IntoIter<T> {
self.into_iter()
}
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> IntoIterator for VecMap<T> {
type Item = (usize, T);
type IntoIter = IntoIter<T>;
@ -688,17 +678,7 @@ fn into_iter(self) -> IntoIter<T> {
}
}
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
impl<'a, T> IntoIterator for &'a VecMap<T> {
type IntoIter = Iter<'a, T>;
fn into_iter(self) -> Iter<'a, T> {
self.iter()
}
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> IntoIterator for &'a VecMap<T> {
type Item = (usize, &'a T);
type IntoIter = Iter<'a, T>;
@ -708,17 +688,7 @@ fn into_iter(self) -> Iter<'a, T> {
}
}
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
impl<'a, T> IntoIterator for &'a mut VecMap<T> {
type IntoIter = IterMut<'a, T>;
fn into_iter(mut self) -> IterMut<'a, T> {
self.iter_mut()
}
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> IntoIterator for &'a mut VecMap<T> {
type Item = (usize, &'a mut T);
type IntoIter = IterMut<'a, T>;

View file

@ -48,17 +48,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
}
}
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
impl<'a, T> IntoIterator for &'a [T; $N] {
type IntoIter = Iter<'a, T>;
fn into_iter(self) -> Iter<'a, T> {
self.iter()
}
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> IntoIterator for &'a [T; $N] {
type Item = &'a T;
type IntoIter = Iter<'a, T>;
@ -68,17 +58,7 @@ fn into_iter(self) -> Iter<'a, T> {
}
}
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
impl<'a, T> IntoIterator for &'a mut [T; $N] {
type IntoIter = IterMut<'a, T>;
fn into_iter(self) -> IterMut<'a, T> {
self.iter_mut()
}
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> IntoIterator for &'a mut [T; $N] {
type Item = &'a mut T;
type IntoIter = IterMut<'a, T>;

View file

@ -42,13 +42,13 @@
//! ```
//! use std::sync::Arc;
//! use std::sync::atomic::{AtomicUsize, Ordering};
//! use std::thread::Thread;
//! use std::thread;
//!
//! fn main() {
//! let spinlock = Arc::new(AtomicUsize::new(1));
//!
//! let spinlock_clone = spinlock.clone();
//! Thread::spawn(move|| {
//! thread::spawn(move|| {
//! spinlock_clone.store(0, Ordering::SeqCst);
//! });
//!

View file

@ -78,12 +78,12 @@
//! use std::cell::RefCell;
//!
//! struct Graph {
//! edges: Vec<(uint, uint)>,
//! span_tree_cache: RefCell<Option<Vec<(uint, uint)>>>
//! edges: Vec<(i32, i32)>,
//! span_tree_cache: RefCell<Option<Vec<(i32, i32)>>>
//! }
//!
//! impl Graph {
//! fn minimum_spanning_tree(&self) -> Vec<(uint, uint)> {
//! fn minimum_spanning_tree(&self) -> Vec<(i32, i32)> {
//! // Create a new scope to contain the lifetime of the
//! // dynamic borrow
//! {
@ -104,7 +104,7 @@
//! // This is the major hazard of using `RefCell`.
//! self.minimum_spanning_tree()
//! }
//! # fn calc_span_tree(&self) -> Vec<(uint, uint)> { vec![] }
//! # fn calc_span_tree(&self) -> Vec<(i32, i32)> { vec![] }
//! }
//! ```
//!
@ -125,7 +125,7 @@
//!
//! struct RcBox<T> {
//! value: T,
//! refcount: Cell<uint>
//! refcount: Cell<usize>
//! }
//!
//! impl<T> Clone for Rc<T> {
@ -279,8 +279,8 @@ pub enum BorrowState {
}
// Values [1, MAX-1] represent the number of `Ref` active
// (will not outgrow its range since `uint` is the size of the address space)
type BorrowFlag = uint;
// (will not outgrow its range since `usize` is the size of the address space)
type BorrowFlag = usize;
const UNUSED: BorrowFlag = 0;
const WRITING: BorrowFlag = -1;
@ -375,9 +375,9 @@ pub fn try_borrow<'a>(&'a self) -> Option<Ref<'a, T>> {
///
/// ```
/// use std::cell::RefCell;
/// use std::thread::Thread;
/// use std::thread;
///
/// let result = Thread::scoped(move || {
/// let result = thread::spawn(move || {
/// let c = RefCell::new(5);
/// let m = c.borrow_mut();
///
@ -436,9 +436,9 @@ pub fn try_borrow_mut<'a>(&'a self) -> Option<RefMut<'a, T>> {
///
/// ```
/// use std::cell::RefCell;
/// use std::thread::Thread;
/// use std::thread;
///
/// let result = Thread::scoped(move || {
/// let result = thread::spawn(move || {
/// let c = RefCell::new(5);
/// let m = c.borrow_mut();
///
@ -649,8 +649,7 @@ fn deref_mut<'a>(&'a mut self) -> &'a mut T {
///
/// **NOTE:** `UnsafeCell<T>`'s fields are public to allow static initializers. It is not
/// recommended to access its fields directly, `get` should be used instead.
#[cfg_attr(stage0, lang="unsafe")] // NOTE: remove after next snapshot
#[cfg_attr(not(stage0), lang="unsafe_cell")]
#[lang="unsafe_cell"]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct UnsafeCell<T> {
/// Wrapped value

View file

@ -8,35 +8,33 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! Defines the `PartialOrd` and `PartialEq` comparison traits.
//! Functionality for ordering and comparison.
//!
//! This module defines both `PartialOrd` and `PartialEq` traits which are used by the
//! compiler to implement comparison operators. Rust programs may implement
//!`PartialOrd` to overload the `<`, `<=`, `>`, and `>=` operators, and may implement
//! `PartialEq` to overload the `==` and `!=` operators.
//! This module defines both `PartialOrd` and `PartialEq` traits which are used by the compiler to
//! implement comparison operators. Rust programs may implement `PartialOrd` to overload the `<`,
//! `<=`, `>`, and `>=` operators, and may implement `PartialEq` to overload the `==` and `!=`
//! operators.
//!
//! For example, to define a type with a customized definition for the PartialEq
//! operators, you could do the following:
//! For example, to define a type with a customized definition for the PartialEq operators, you
//! could do the following:
//!
//! ```rust
//! ```
//! use core::num::SignedInt;
//!
//! // Our type.
//! struct SketchyNum {
//! num : int
//! struct FuzzyNum {
//! num: i32,
//! }
//!
//! // Our implementation of `PartialEq` to support `==` and `!=`.
//! impl PartialEq for SketchyNum {
//! impl PartialEq for FuzzyNum {
//! // Our custom eq allows numbers which are near each other to be equal! :D
//! fn eq(&self, other: &SketchyNum) -> bool {
//! fn eq(&self, other: &FuzzyNum) -> bool {
//! (self.num - other.num).abs() < 5
//! }
//! }
//!
//! // Now these binary operators will work when applied!
//! assert!(SketchyNum {num: 37} == SketchyNum {num: 34});
//! assert!(SketchyNum {num: 25} != SketchyNum {num: 57});
//! assert!(FuzzyNum { num: 37 } == FuzzyNum { num: 34 });
//! assert!(FuzzyNum { num: 25 } != FuzzyNum { num: 57 });
//! ```
#![stable(feature = "rust1", since = "1.0.0")]
@ -49,24 +47,22 @@
/// Trait for equality comparisons which are [partial equivalence relations](
/// http://en.wikipedia.org/wiki/Partial_equivalence_relation).
///
/// This trait allows for partial equality, for types that do not have a full
/// equivalence relation. For example, in floating point numbers `NaN != NaN`,
/// so floating point types implement `PartialEq` but not `Eq`.
/// This trait allows for partial equality, for types that do not have a full equivalence relation.
/// For example, in floating point numbers `NaN != NaN`, so floating point types implement
/// `PartialEq` but not `Eq`.
///
/// Formally, the equality must be (for all `a`, `b` and `c`):
///
/// - symmetric: `a == b` implies `b == a`; and
/// - transitive: `a == b` and `b == c` implies `a == c`.
///
/// Note that these requirements mean that the trait itself must be
/// implemented symmetrically and transitively: if `T: PartialEq<U>`
/// and `U: PartialEq<V>` then `U: PartialEq<T>` and `T:
/// Note that these requirements mean that the trait itself must be implemented symmetrically and
/// transitively: if `T: PartialEq<U>` and `U: PartialEq<V>` then `U: PartialEq<T>` and `T:
/// PartialEq<V>`.
///
/// PartialEq only requires the `eq` method to be implemented; `ne` is defined
/// in terms of it by default. Any manual implementation of `ne` *must* respect
/// the rule that `eq` is a strict inverse of `ne`; that is, `!(a == b)` if and
/// only if `a != b`.
/// PartialEq only requires the `eq` method to be implemented; `ne` is defined in terms of it by
/// default. Any manual implementation of `ne` *must* respect the rule that `eq` is a strict
/// inverse of `ne`; that is, `!(a == b)` if and only if `a != b`.
#[lang="eq"]
#[stable(feature = "rust1", since = "1.0.0")]
#[old_orphan_check]
@ -84,12 +80,15 @@ fn ne(&self, other: &Rhs) -> bool { !self.eq(other) }
/// Trait for equality comparisons which are [equivalence relations](
/// https://en.wikipedia.org/wiki/Equivalence_relation).
///
/// This means, that in addition to `a == b` and `a != b` being strict
/// inverses, the equality must be (for all `a`, `b` and `c`):
/// This means, that in addition to `a == b` and `a != b` being strict inverses, the equality must
/// be (for all `a`, `b` and `c`):
///
/// - reflexive: `a == a`;
/// - symmetric: `a == b` implies `b == a`; and
/// - transitive: `a == b` and `b == c` implies `a == c`.
///
/// This property cannot be checked by the compiler, and therefore `Eq` implies
/// `PartialEq`, and has no extra methods.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Eq: PartialEq<Self> {
// FIXME #13101: this method is used solely by #[deriving] to
@ -101,10 +100,26 @@ pub trait Eq: PartialEq<Self> {
// This should never be implemented by hand.
#[doc(hidden)]
#[inline(always)]
#[stable(feature = "rust1", since = "1.0.0")]
fn assert_receiver_is_total_eq(&self) {}
}
/// An ordering is, e.g, a result of a comparison between two values.
/// An `Ordering` is the result of a comparison between two values.
///
/// # Examples
///
/// ```
/// use std::cmp::Ordering;
///
/// let result = 1.cmp(&2);
/// assert_eq!(Ordering::Less, result);
///
/// let result = 1.cmp(&1);
/// assert_eq!(Ordering::Equal, result);
///
/// let result = 2.cmp(&1);
/// assert_eq!(Ordering::Greater, result);
/// ```
#[derive(Clone, Copy, PartialEq, Debug)]
#[stable(feature = "rust1", since = "1.0.0")]
pub enum Ordering {
@ -120,17 +135,28 @@ pub enum Ordering {
}
impl Ordering {
/// Reverse the `Ordering`, so that `Less` becomes `Greater` and
/// vice versa.
/// Reverse the `Ordering`.
///
/// # Example
/// * `Less` becomes `Greater`.
/// * `Greater` becomes `Less`.
/// * `Equal` becomes `Equal`.
///
/// ```rust
/// use std::cmp::Ordering::{Less, Equal, Greater};
/// # Examples
///
/// assert_eq!(Less.reverse(), Greater);
/// assert_eq!(Equal.reverse(), Equal);
/// assert_eq!(Greater.reverse(), Less);
/// Basic behavior:
///
/// ```
/// use std::cmp::Ordering;
///
/// assert_eq!(Ordering::Less.reverse(), Ordering::Greater);
/// assert_eq!(Ordering::Equal.reverse(), Ordering::Equal);
/// assert_eq!(Ordering::Greater.reverse(), Ordering::Less);
/// ```
///
/// This method can be used to reverse a comparison:
///
/// ```
/// use std::cmp::Ordering;
///
/// let mut data: &mut [_] = &mut [2, 10, 5, 8];
///
@ -155,28 +181,27 @@ pub fn reverse(self) -> Ordering {
}
}
/// Trait for types that form a [total order](
/// https://en.wikipedia.org/wiki/Total_order).
/// Trait for types that form a [total order](https://en.wikipedia.org/wiki/Total_order).
///
/// An order is a total order if it is (for all `a`, `b` and `c`):
///
/// - total and antisymmetric: exactly one of `a < b`, `a == b` or `a > b` is
/// true; and
/// - transitive, `a < b` and `b < c` implies `a < c`. The same must hold for
/// both `==` and `>`.
/// - total and antisymmetric: exactly one of `a < b`, `a == b` or `a > b` is true; and
/// - transitive, `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Ord: Eq + PartialOrd<Self> {
/// This method returns an ordering between `self` and `other` values.
/// This method returns an `Ordering` between `self` and `other`.
///
/// By convention, `self.cmp(&other)` returns the ordering matching
/// the expression `self <operator> other` if true. For example:
/// By convention, `self.cmp(&other)` returns the ordering matching the expression
/// `self <operator> other` if true.
///
/// # Examples
///
/// ```
/// use std::cmp::Ordering::{Less, Equal, Greater};
/// use std::cmp::Ordering;
///
/// assert_eq!( 5.cmp(&10), Less); // because 5 < 10
/// assert_eq!(10.cmp(&5), Greater); // because 10 > 5
/// assert_eq!( 5.cmp(&5), Equal); // because 5 == 5
/// assert_eq!(5.cmp(&10), Ordering::Less);
/// assert_eq!(10.cmp(&5), Ordering::Greater);
/// assert_eq!(5.cmp(&5), Ordering::Equal);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn cmp(&self, other: &Self) -> Ordering;
@ -208,30 +233,60 @@ fn partial_cmp(&self, other: &Ordering) -> Option<Ordering> {
/// The comparison must satisfy, for all `a`, `b` and `c`:
///
/// - antisymmetry: if `a < b` then `!(a > b)` and vice versa; and
/// - transitivity: `a < b` and `b < c` implies `a < c`. The same must hold for
/// both `==` and `>`.
/// - transitivity: `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`.
///
/// Note that these requirements mean that the trait itself must be
/// implemented symmetrically and transitively: if `T: PartialOrd<U>`
/// and `U: PartialOrd<V>` then `U: PartialOrd<T>` and `T:
/// Note that these requirements mean that the trait itself must be implemented symmetrically and
/// transitively: if `T: PartialOrd<U>` and `U: PartialOrd<V>` then `U: PartialOrd<T>` and `T:
/// PartialOrd<V>`.
///
/// PartialOrd only requires implementation of the `partial_cmp` method,
/// with the others generated from default implementations.
/// PartialOrd only requires implementation of the `partial_cmp` method, with the others generated
/// from default implementations.
///
/// However it remains possible to implement the others separately for types
/// which do not have a total order. For example, for floating point numbers,
/// `NaN < 0 == false` and `NaN >= 0 == false` (cf. IEEE 754-2008 section
/// 5.11).
/// However it remains possible to implement the others separately for types which do not have a
/// total order. For example, for floating point numbers, `NaN < 0 == false` and `NaN >= 0 ==
/// false` (cf. IEEE 754-2008 section 5.11).
#[lang="ord"]
#[stable(feature = "rust1", since = "1.0.0")]
pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
/// This method returns an ordering between `self` and `other` values
/// if one exists.
/// This method returns an ordering between `self` and `other` values if one exists.
///
/// # Examples
///
/// ```
/// use std::cmp::Ordering;
///
/// let result = 1.0.partial_cmp(&2.0);
/// assert_eq!(result, Some(Ordering::Less));
///
/// let result = 1.0.partial_cmp(&1.0);
/// assert_eq!(result, Some(Ordering::Equal));
///
/// let result = 2.0.partial_cmp(&1.0);
/// assert_eq!(result, Some(Ordering::Greater));
/// ```
///
/// When comparison is impossible:
///
/// ```
/// let result = std::f64::NAN.partial_cmp(&1.0);
/// assert_eq!(result, None);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>;
/// This method tests less than (for `self` and `other`) and is used by the `<` operator.
///
/// # Examples
///
/// ```
/// use std::cmp::Ordering;
///
/// let result = 1.0 < 2.0;
/// assert_eq!(result, true);
///
/// let result = 2.0 < 1.0;
/// assert_eq!(result, false);
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
fn lt(&self, other: &Rhs) -> bool {
@ -241,7 +296,18 @@ fn lt(&self, other: &Rhs) -> bool {
}
}
/// This method tests less than or equal to (`<=`).
/// This method tests less than or equal to (for `self` and `other`) and is used by the `<=`
/// operator.
///
/// # Examples
///
/// ```
/// let result = 1.0 <= 2.0;
/// assert_eq!(result, true);
///
/// let result = 2.0 <= 2.0;
/// assert_eq!(result, true);
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
fn le(&self, other: &Rhs) -> bool {
@ -251,7 +317,17 @@ fn le(&self, other: &Rhs) -> bool {
}
}
/// This method tests greater than (`>`).
/// This method tests greater than (for `self` and `other`) and is used by the `>` operator.
///
/// # Examples
///
/// ```
/// let result = 1.0 > 2.0;
/// assert_eq!(result, false);
///
/// let result = 2.0 > 2.0;
/// assert_eq!(result, false);
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
fn gt(&self, other: &Rhs) -> bool {
@ -261,7 +337,18 @@ fn gt(&self, other: &Rhs) -> bool {
}
}
/// This method tests greater than or equal to (`>=`).
/// This method tests greater than or equal to (for `self` and `other`) and is used by the `>=`
/// operator.
///
/// # Examples
///
/// ```
/// let result = 2.0 >= 1.0;
/// assert_eq!(result, true);
///
/// let result = 2.0 >= 2.0;
/// assert_eq!(result, true);
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
fn ge(&self, other: &Rhs) -> bool {
@ -273,6 +360,15 @@ fn ge(&self, other: &Rhs) -> bool {
}
/// Compare and return the minimum of two values.
///
/// # Examples
///
/// ```
/// use std::cmp;
///
/// assert_eq!(1, cmp::min(1, 2));
/// assert_eq!(2, cmp::min(2, 2));
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn min<T: Ord>(v1: T, v2: T) -> T {
@ -280,6 +376,15 @@ pub fn min<T: Ord>(v1: T, v2: T) -> T {
}
/// Compare and return the maximum of two values.
///
/// # Examples
///
/// ```
/// use std::cmp;
///
/// assert_eq!(2, cmp::max(1, 2));
/// assert_eq!(2, cmp::max(2, 2));
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn max<T: Ord>(v1: T, v2: T) -> T {
@ -289,6 +394,24 @@ pub fn max<T: Ord>(v1: T, v2: T) -> T {
/// Compare and return the minimum of two values if there is one.
///
/// Returns the first argument if the comparison determines them to be equal.
///
/// # Examples
///
/// ```
/// use std::cmp;
///
/// assert_eq!(Some(1), cmp::partial_min(1, 2));
/// assert_eq!(Some(2), cmp::partial_min(2, 2));
/// ```
///
/// When comparison is impossible:
///
/// ```
/// use std::cmp;
///
/// let result = cmp::partial_min(std::f64::NAN, 1.0);
/// assert_eq!(result, None);
/// ```
#[inline]
#[unstable(feature = "core")]
pub fn partial_min<T: PartialOrd>(v1: T, v2: T) -> Option<T> {
@ -302,6 +425,24 @@ pub fn partial_min<T: PartialOrd>(v1: T, v2: T) -> Option<T> {
/// Compare and return the maximum of two values if there is one.
///
/// Returns the first argument if the comparison determines them to be equal.
///
/// # Examples
///
/// ```
/// use std::cmp;
///
/// assert_eq!(Some(2), cmp::partial_max(1, 2));
/// assert_eq!(Some(2), cmp::partial_max(2, 2));
/// ```
///
/// When comparison is impossible:
///
/// ```
/// use std::cmp;
///
/// let result = cmp::partial_max(std::f64::NAN, 1.0);
/// assert_eq!(result, None);
/// ```
#[inline]
#[unstable(feature = "core")]
pub fn partial_max<T: PartialOrd>(v1: T, v2: T) -> Option<T> {

View file

@ -197,6 +197,7 @@ pub fn new_v1(pieces: &'a [&'a str],
/// created with `argumentuint`. However, failing to do so doesn't cause
/// unsafety, but will ignore invalid .
#[doc(hidden)] #[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn new_v1_formatted(pieces: &'a [&'a str],
args: &'a [ArgumentV1<'a>],
fmt: &'a [rt::v1::Argument]) -> Arguments<'a> {

View file

@ -118,21 +118,13 @@ pub trait FromIterator<A> {
fn from_iter<T: Iterator<Item=A>>(iterator: T) -> Self;
}
// NOTE(stage0): remove trait after a snapshot
#[cfg(stage0)]
/// Conversion into an `Iterator`
#[stable(feature = "rust1", since = "1.0.0")]
pub trait IntoIterator {
type IntoIter: Iterator;
/// Consumes `Self` and returns an iterator over it
#[stable(feature = "rust1", since = "1.0.0")]
fn into_iter(self) -> Self::IntoIter;
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
/// Conversion into an `Iterator`
pub trait IntoIterator {
type Item;
#[stable(feature = "rust1", since = "1.0.0")]
type IntoIter: Iterator<Item=Self::Item>;
/// Consumes `Self` and returns an iterator over it
@ -140,17 +132,7 @@ pub trait IntoIterator {
fn into_iter(self) -> Self::IntoIter;
}
// NOTE(stage0): remove impl after a snapshot
#[cfg(stage0)]
impl<I> IntoIterator for I where I: Iterator {
type IntoIter = I;
fn into_iter(self) -> I {
self
}
}
#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
#[stable(feature = "rust1", since = "1.0.0")]
impl<I: Iterator> IntoIterator for I {
type Item = I::Item;
type IntoIter = I;
@ -2374,7 +2356,7 @@ fn size_hint(&self) -> (usize, Option<usize>) {
/// iteration
#[derive(Clone)]
#[unstable(feature = "core",
reason = "may be renamed or replaced by range notation adapaters")]
reason = "may be renamed or replaced by range notation adapters")]
pub struct Counter<A> {
/// The current state the counter is at (next value to be yielded)
state: A,
@ -2385,7 +2367,7 @@ pub struct Counter<A> {
/// Creates a new counter with the specified start/step
#[inline]
#[unstable(feature = "core",
reason = "may be renamed or replaced by range notation adapaters")]
reason = "may be renamed or replaced by range notation adapters")]
pub fn count<A>(start: A, step: A) -> Counter<A> {
Counter{state: start, step: step}
}

View file

@ -67,6 +67,7 @@
#![feature(simd, unsafe_destructor)]
#![feature(staged_api)]
#![feature(unboxed_closures)]
#![feature(rustc_attrs)]
#[macro_use]
mod macros;
@ -153,25 +154,16 @@ mod bool {
mod core {
pub use panicking;
pub use fmt;
#[cfg(not(stage0))] pub use clone;
#[cfg(not(stage0))] pub use cmp;
#[cfg(not(stage0))] pub use hash;
#[cfg(not(stage0))] pub use marker;
#[cfg(not(stage0))] pub use option;
#[cfg(not(stage0))] pub use iter;
pub use clone;
pub use cmp;
pub use hash;
pub use marker;
pub use option;
pub use iter;
}
#[doc(hidden)]
mod std {
// NOTE: remove after next snapshot
#[cfg(stage0)] pub use clone;
#[cfg(stage0)] pub use cmp;
#[cfg(stage0)] pub use hash;
#[cfg(stage0)] pub use marker;
#[cfg(stage0)] pub use option;
#[cfg(stage0)] pub use fmt;
#[cfg(stage0)] pub use iter;
// range syntax
pub use ops;
}

View file

@ -32,9 +32,19 @@
reason = "will be overhauled with new lifetime rules; see RFC 458")]
#[lang="send"]
#[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"]
#[cfg(stage0)]
pub unsafe trait Send: 'static {
// empty.
}
/// Types able to be transferred across thread boundaries.
#[unstable(feature = "core",
reason = "will be overhauled with new lifetime rules; see RFC 458")]
#[lang="send"]
#[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"]
#[cfg(not(stage0))]
pub unsafe trait Send {
// empty.
}
/// Types with a constant size known at compile-time.
#[stable(feature = "rust1", since = "1.0.0")]
@ -424,3 +434,11 @@ fn clone(&self) -> InvariantType<T> { *self }
#[lang="managed_bound"]
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct Managed;
#[cfg(not(stage0))]
mod impls {
use super::{Send, Sync, Sized};
unsafe impl<'a, T: Sync + ?Sized> Send for &'a T {}
unsafe impl<'a, T: Send + ?Sized> Send for &'a mut T {}
}

View file

@ -43,7 +43,7 @@
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn size_of<T>() -> uint {
pub fn size_of<T>() -> usize {
unsafe { intrinsics::size_of::<T>() }
}
@ -58,7 +58,7 @@ pub fn size_of<T>() -> uint {
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn size_of_val<T>(_val: &T) -> uint {
pub fn size_of_val<T>(_val: &T) -> usize {
size_of::<T>()
}
@ -75,7 +75,7 @@ pub fn size_of_val<T>(_val: &T) -> uint {
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn min_align_of<T>() -> uint {
pub fn min_align_of<T>() -> usize {
unsafe { intrinsics::min_align_of::<T>() }
}
@ -90,7 +90,7 @@ pub fn min_align_of<T>() -> uint {
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn min_align_of_val<T>(_val: &T) -> uint {
pub fn min_align_of_val<T>(_val: &T) -> usize {
min_align_of::<T>()
}
@ -108,7 +108,7 @@ pub fn min_align_of_val<T>(_val: &T) -> uint {
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn align_of<T>() -> uint {
pub fn align_of<T>() -> usize {
// We use the preferred alignment as the default alignment for a type. This
// appears to be what clang migrated towards as well:
//
@ -130,7 +130,7 @@ pub fn align_of<T>() -> uint {
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn align_of_val<T>(_val: &T) -> uint {
pub fn align_of_val<T>(_val: &T) -> usize {
align_of::<T>()
}
@ -150,7 +150,7 @@ pub fn align_of_val<T>(_val: &T) -> uint {
/// ```
/// use std::mem;
///
/// let x: int = unsafe { mem::zeroed() };
/// let x: i32 = unsafe { mem::zeroed() };
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
@ -171,7 +171,7 @@ pub unsafe fn zeroed<T>() -> T {
/// ```
/// use std::mem;
///
/// let x: int = unsafe { mem::uninitialized() };
/// let x: i32 = unsafe { mem::uninitialized() };
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]

View file

@ -19,8 +19,8 @@ pub unsafe trait Zeroable {}
unsafe impl<T> Zeroable for *const T {}
unsafe impl<T> Zeroable for *mut T {}
unsafe impl<T> Zeroable for Unique<T> { }
unsafe impl Zeroable for int {}
unsafe impl Zeroable for uint {}
unsafe impl Zeroable for isize {}
unsafe impl Zeroable for usize {}
unsafe impl Zeroable for i8 {}
unsafe impl Zeroable for u8 {}
unsafe impl Zeroable for i16 {}

View file

@ -605,6 +605,8 @@ pub fn and<U>(self, optb: Option<U>) -> Option<U> {
/// Returns `None` if the option is `None`, otherwise calls `f` with the
/// wrapped value and returns the result.
///
/// Some languages call this operation flatmap.
///
/// # Example
///
/// ```

Some files were not shown because too many files have changed in this diff Show more