auto merge of #20104 : alexcrichton/rust/rollup, r=alexcrichton

This commit is contained in:
bors 2014-12-22 00:12:47 +00:00
commit 34d6800092
246 changed files with 2268 additions and 2215 deletions

View File

@ -216,36 +216,6 @@ endef
$(foreach docname,$(DOCS),$(eval $(call DEF_DOC,$(docname))))
# Localized documentation
# FIXME: I (huonw) haven't actually been able to test properly, since
# e.g. (by default) I'm doing an out-of-tree build (#12763), but even
# adjusting for that, the files are too old(?) and are rejected by
# po4a.
#
# As such, I've attempted to get it working as much as possible (and
# switching from pandoc to rustdoc), but preserving the old behaviour
# (e.g. only running on the guide)
.PHONY: l10n-mds
l10n-mds: $(D)/po4a.conf \
$(foreach lang,$(L10N_LANG),$(D)/po/$(lang)/*.md.po)
$(warning WARNING: localized documentation is experimental)
po4a --copyright-holder="The Rust Project Developers" \
--package-name="Rust" \
--package-version="$(CFG_RELEASE)" \
-M UTF-8 -L UTF-8 \
$(D)/po4a.conf
define DEF_L10N_DOC
DOC_L10N_TARGETS += doc/l10n/$(1)/$(2).html
doc/l10n/$(1)/$(2).html: l10n-mds $$(HTML_DEPS) $$(RUSTDOC_DEPS_$(2))
@$$(call E, rustdoc: $$@)
$$(RUSTDOC) $$(RUSTDOC_HTML_OPTS) $$(RUSTDOC_FLAGS_$(1)) doc/l10n/$(1)/$(2).md
endef
$(foreach lang,$(L10N_LANGS),$(eval $(call DEF_L10N_DOC,$(lang),guide)))
######################################################################
# Rustdoc (libstd/extra)
######################################################################
@ -294,7 +264,3 @@ endif
docs: $(DOC_TARGETS)
compiler-docs: $(COMPILER_DOC_TARGETS)
docs-l10n: $(DOC_L10N_TARGETS)
.PHONY: docs-l10n

View File

@ -74,21 +74,6 @@ endif
TEST_LOG_FILE=tmp/check-stage$(1)-T-$(2)-H-$(3)-$(4).log
TEST_OK_FILE=tmp/check-stage$(1)-T-$(2)-H-$(3)-$(4).ok
TEST_RATCHET_FILE=tmp/check-stage$(1)-T-$(2)-H-$(3)-$(4)-metrics.json
TEST_RATCHET_NOISE_PERCENT=10.0
# Whether to ratchet or merely save benchmarks
ifdef CFG_RATCHET_BENCH
CRATE_TEST_EXTRA_ARGS= \
--test $(TEST_BENCH) \
--ratchet-metrics $(call TEST_RATCHET_FILE,$(1),$(2),$(3),$(4)) \
--ratchet-noise-percent $(TEST_RATCHET_NOISE_PERCENT)
else
CRATE_TEST_EXTRA_ARGS= \
--test $(TEST_BENCH) \
--save-metrics $(call TEST_RATCHET_FILE,$(1),$(2),$(3),$(4))
endif
# If we're sharding the testsuite between parallel testers,
# pass this argument along to the compiletest and crate test
# invocations.
@ -455,7 +440,6 @@ $$(call TEST_OK_FILE,$(1),$(2),$(3),$(4)): \
$$(Q)touch tmp/check-stage$(1)-T-$(2)-H-$(3)-$(4).log
$$(Q)$(CFG_ADB) pull $(CFG_ADB_TEST_DIR)/check-stage$(1)-T-$(2)-H-$(3)-$(4).log tmp/
$$(Q)$(CFG_ADB) shell rm $(CFG_ADB_TEST_DIR)/check-stage$(1)-T-$(2)-H-$(3)-$(4).log
$$(Q)$(CFG_ADB) pull $(CFG_ADB_TEST_DIR)/$$(call TEST_RATCHET_FILE,$(1),$(2),$(3),$(4)) tmp/
@if grep -q "result: ok" tmp/check-stage$(1)-T-$(2)-H-$(3)-$(4).tmp; \
then \
rm tmp/check-stage$(1)-T-$(2)-H-$(3)-$(4).tmp; \
@ -697,7 +681,6 @@ CTEST_ARGS$(1)-T-$(2)-H-$(3)-$(4) := \
$$(CTEST_COMMON_ARGS$(1)-T-$(2)-H-$(3)) \
--src-base $$(S)src/test/$$(CTEST_SRC_BASE_$(4))/ \
--build-base $(3)/test/$$(CTEST_BUILD_BASE_$(4))/ \
--ratchet-metrics $(call TEST_RATCHET_FILE,$(1),$(2),$(3),$(4)) \
--mode $$(CTEST_MODE_$(4)) \
$$(CTEST_RUNTOOL_$(4))

View File

@ -1609,7 +1609,7 @@ fn _arm_exec_compiled_test(config: &Config,
stderr_out.as_slice());
ProcRes {
status: process::ExitStatus(exitcode),
status: process::ProcessExit::ExitStatus(exitcode),
stdout: stdout_out,
stderr: stderr_out,
cmdline: cmdline

View File

@ -6,12 +6,6 @@
document converter, is required to generate docs as HTML from Rust's
source code.
[po4a](http://po4a.alioth.debian.org/) is required for generating translated
docs from the master (English) docs.
[GNU gettext](http://www.gnu.org/software/gettext/) is required for managing
the translation data.
## Building
To generate all the docs, just run `make docs` from the root of the repository.
@ -44,43 +38,3 @@ The syntax for pandoc flavored markdown can be found at:
A nice quick reference (for non-pandoc markdown) is at:
- http://kramdown.gettalong.org/quickref.html
## Notes for translators
Notice: The procedure described below is a work in progress. We are working on
translation system but the procedure contains some manual operations for now.
To start the translation for a new language, see `po4a.conf` at first.
To generate `.pot` and `.po` files, do something like:
~~~~
po4a --copyright-holder="The Rust Project Developers" \
--package-name="Rust" \
--package-version="0.13.0" \
-M UTF-8 -L UTF-8 \
src/doc/po4a.conf
~~~~
(the version number must be changed if it is not `0.13.0` now.)
Now you can translate documents with `.po` files, commonly used with gettext. If
you are not familiar with gettext-based translation, please read the online
manual linked from http://www.gnu.org/software/gettext/ . We use UTF-8 as the
file encoding of `.po` files.
When you want to make a commit, do the command below before staging your
change:
~~~~
for f in src/doc/po/**/*.po; do
msgattrib --translated $f -o $f.strip
if [ -e $f.strip ]; then
mv $f.strip $f
else
rm $f
fi
done
~~~~
This removes untranslated entries from `.po` files to save disk space.

View File

@ -324,7 +324,7 @@ fn main() {
let f = Foo { x: y }; // -+ f goes into scope
// stuff // |
// |
} // -+ f & y go out of scope
} // -+ f and y go out of scope
```
Our `f` lives within the scope of `y`, so everything works. What if it didn't?
@ -342,7 +342,7 @@ fn main() {
let y = &5i; // ---+ y goes into scope
let f = Foo { x: y }; // ---+ f goes into scope
x = &f.x; // | | error here
} // ---+ f & y go out of scope
} // ---+ f and y go out of scope
// |
println!("{}", x); // |
} // -+ x goes out of scope
@ -395,7 +395,7 @@ struct Wheel {
}
fn main() {
let car = Car { name: "DeLorian".to_string() };
let car = Car { name: "DeLorean".to_string() };
for _ in range(0u, 4) {
Wheel { size: 360, owner: car };
@ -431,7 +431,7 @@ struct Wheel {
}
fn main() {
let car = Car { name: "DeLorian".to_string() };
let car = Car { name: "DeLorean".to_string() };
let car_owner = Rc::new(car);

View File

@ -31,7 +31,6 @@ below.)
If you're on Windows, please download either the [32-bit
installer](https://static.rust-lang.org/dist/rust-nightly-i686-pc-windows-gnu.exe)
or the [64-bit
installer](https://static.rust-lang.org/dist/rust-nightly-x86_64-pc-windows-gnu.exe)
and run it.
@ -1170,7 +1169,7 @@ enum StringResult {
ErrorReason(String),
}
```
Where a `StringResult` is either an `StringOK`, with the result of a computation, or an
Where a `StringResult` is either a `StringOK`, with the result of a computation, or an
`ErrorReason` with a `String` explaining what caused the computation to fail. These kinds of
`enum`s are actually very useful and are even part of the standard library.
@ -1192,7 +1191,7 @@ fn respond(greeting: &str) -> StringResult {
```
Notice that we need both the enum name and the variant name: `StringResult::StringOK`, but
we didn't need to with `Ordering`, we just said `Greater` rather than `Ordering::Greater`.
we didn't need to with `Ordering` we just said `Greater` rather than `Ordering::Greater`.
There's a reason: the Rust prelude imports the variants of `Ordering` as well as the enum
itself. We can use the `use` keyword to do something similar with `StringResult`:
@ -1223,16 +1222,16 @@ now, rather than the full `StringResult::StringOK`. Importing variants can be co
also cause name conflicts, so do this with caution. It's considered good style to rarely import
variants for this reason.
As you can see `enum`s with values are quite a powerful tool for data representation,
and can be even more useful when they're generic across types. But before we get to
generics, let's talk about how to use them with pattern matching, a tool that will
As you can see, `enum`s with values are quite a powerful tool for data representation,
and can be even more useful when they're generic across types. Before we get to generics,
though, let's talk about how to use them with pattern matching, a tool that will
let us deconstruct this sum type (the type theory term for enums) in a very elegant
way and avoid all these messy `if`/`else`s.
# Match
Often, a simple `if`/`else` isn't enough, because you have more than two
possible options. And `else` conditions can get incredibly complicated. So
possible options. Also, `else` conditions can get incredibly complicated, so
what's the solution?
Rust has a keyword, `match`, that allows you to replace complicated `if`/`else`
@ -1251,13 +1250,13 @@ match x {
}
```
`match` takes an expression, and then branches based on its value. Each 'arm' of
`match` takes an expression and then branches based on its value. Each 'arm' of
the branch is of the form `val => expression`. When the value matches, that arm's
expression will be evaluated. It's called `match` because of the term 'pattern
matching,' which `match` is an implementation of.
matching', which `match` is an implementation of.
So what's the big advantage here? Well, there are a few. First of all, `match`
enforces 'exhaustiveness checking.' Do you see that last arm, the one with the
enforces 'exhaustiveness checking'. Do you see that last arm, the one with the
underscore (`_`)? If we remove that arm, Rust will give us an error:
```text
@ -1265,11 +1264,11 @@ error: non-exhaustive patterns: `_` not covered
```
In other words, Rust is trying to tell us we forgot a value. Because `x` is an
integer, Rust knows that it can have a number of different values. For example,
`6i`. But without the `_`, there is no arm that could match, and so Rust refuses
to compile. `_` is sort of like a catch-all arm. If none of the other arms match,
the arm with `_` will. And since we have this catch-all arm, we now have an arm
for every possible value of `x`, and so our program will now compile.
integer, Rust knows that it can have a number of different values for example,
`6i`. Without the `_`, however, there is no arm that could match, and so Rust refuses
to compile. `_` acts like a 'catch-all arm'. If none of the other arms match,
the arm with `_` will, and since we have this catch-all arm, we now have an arm
for every possible value of `x`, and so our program will compile successfully.
`match` statements also destructure enums, as well. Remember this code from the
section on enums?
@ -1350,14 +1349,14 @@ fn main() {
```
That is how you can get and use the values contained in `enum`s.
It can also allow us to treat errors or unexpected computations, for example, a
function that is not guaranteed to be able to compute a result (an `int` here),
It can also allow us to handle errors or unexpected computations; for example, a
function that is not guaranteed to be able to compute a result (an `int` here)
could return an `OptionalInt`, and we would handle that value with a `match`.
As you can see, `enum` and `match` used together are quite useful!
`match` is also an expression, which means we can use it on the right
hand side of a `let` binding or directly where an expression is
used. We could also implement the previous line like this:
`match` is also an expression, which means we can use it on the right-hand
side of a `let` binding or directly where an expression is used. We could
also implement the previous line like this:
```{rust}
fn cmp(a: int, b: int) -> Ordering {
@ -1389,7 +1388,7 @@ two main looping constructs: `for` and `while`.
The `for` loop is used to loop a particular number of times. Rust's `for` loops
work a bit differently than in other systems languages, however. Rust's `for`
loop doesn't look like this "C style" `for` loop:
loop doesn't look like this "C-style" `for` loop:
```{c}
for (x = 0; x < 10; x++) {
@ -1424,7 +1423,7 @@ In our example, `range` is a function that takes a start and an end position,
and gives an iterator over those values. The upper bound is exclusive, though,
so our loop will print `0` through `9`, not `10`.
Rust does not have the "C style" `for` loop on purpose. Manually controlling
Rust does not have the "C-style" `for` loop on purpose. Manually controlling
each element of the loop is complicated and error prone, even for experienced C
developers.
@ -1455,7 +1454,7 @@ If you need an infinite loop, you may be tempted to write this:
while true {
```
Rust has a dedicated keyword, `loop`, to handle this case:
However, Rust has a dedicated keyword, `loop`, to handle this case:
```{rust,ignore}
loop {
@ -1465,7 +1464,7 @@ Rust's control-flow analysis treats this construct differently than a
`while true`, since we know that it will always loop. The details of what
that _means_ aren't super important to understand at this stage, but in
general, the more information we can give to the compiler, the better it
can do with safety and code generation. So you should always prefer
can do with safety and code generation, so you should always prefer
`loop` when you plan to loop infinitely.
## Ending iteration early
@ -1484,7 +1483,7 @@ while !done {
```
We had to keep a dedicated `mut` boolean variable binding, `done`, to know
when we should skip out of the loop. Rust has two keywords to help us with
when we should exit out of the loop. Rust has two keywords to help us with
modifying iteration: `break` and `continue`.
In this case, we can write the loop in a better way with `break`:
@ -1499,10 +1498,10 @@ loop {
}
```
We now loop forever with `loop`, and use `break` to break out early.
We now loop forever with `loop` and use `break` to break out early.
`continue` is similar, but instead of ending the loop, goes to the next
iteration: This will only print the odd numbers:
iteration. This will only print the odd numbers:
```{rust}
for x in range(0i, 10i) {
@ -1519,8 +1518,8 @@ Both `continue` and `break` are valid in both kinds of loops.
Strings are an important concept for any programmer to master. Rust's string
handling system is a bit different from other languages, due to its systems
focus. Any time you have a data structure of variable size, things can get
tricky, and strings are a re-sizable data structure. That said, Rust's strings
also work differently than in some other systems languages, such as C.
tricky, and strings are a re-sizable data structure. That being said, Rust's
strings also work differently than in some other systems languages, such as C.
Let's dig into the details. A **string** is a sequence of Unicode scalar values
encoded as a stream of UTF-8 bytes. All strings are guaranteed to be
@ -1793,22 +1792,22 @@ fn main() {
}
```
We had to match each time, to see if we had a value or not. In this case,
though, we _know_ that `x` has a `Value`. But `match` forces us to handle
We had to match each time to see if we had a value or not. In this case,
though, we _know_ that `x` has a `Value`, but `match` forces us to handle
the `missing` case. This is what we want 99% of the time, but sometimes, we
know better than the compiler.
Likewise, `read_line()` does not return a line of input. It _might_ return a
line of input. It might also fail to do so. This could happen if our program
line of input, though it might also fail to do so. This could happen if our program
isn't running in a terminal, but as part of a cron job, or some other context
where there's no standard input. Because of this, `read_line` returns a type
very similar to our `OptionalInt`: an `IoResult<T>`. We haven't talked about
`IoResult<T>` yet because it is the **generic** form of our `OptionalInt`.
Until then, you can think of it as being the same thing, just for any type, not
just `int`s.
Until then, you can think of it as being the same thing, just for any type
not just `int`s.
Rust provides a method on these `IoResult<T>`s called `ok()`, which does the
same thing as our `match` statement, but assuming that we have a valid value.
same thing as our `match` statement but assumes that we have a valid value.
We then call `expect()` on the result, which will terminate our program if we
don't have a valid value. In this case, if we can't get input, our program
doesn't work, so we're okay with that. In most cases, we would want to handle
@ -1852,7 +1851,7 @@ fn main() {
}
```
Sometimes, this makes things more readable. Sometimes, less. Use your judgment
Sometimes, this makes things more readable sometimes, less. Use your judgement
here.
That's all you need to get basic input from the standard input! It's not too
@ -1972,10 +1971,8 @@ You can find that page [here](std/index.html). There's a lot of information on
that page, but the best part is the search bar. Right up at the top, there's
a box that you can enter in a search term. The search is pretty primitive
right now, but is getting better all the time. If you type 'random' in that
box, the page will update to [this
one](std/index.html?search=random). The very first
result is a link to
[std::rand::random](std/rand/fn.random.html). If we
box, the page will update to [this one](std/index.html?search=random). The very
first result is a link to [`std::rand::random`](std/rand/fn.random.html). If we
click on that result, we'll be taken to its documentation page.
This page shows us a few things: the type signature of the function, some
@ -2039,7 +2036,7 @@ rand::random::<int>();
```
This says "please give me a random `int` value." We can change our code to use
this hint...
this hint:
```{rust,no_run}
use std::io;
@ -2380,7 +2377,7 @@ fn cmp(a: uint, b: uint) -> Ordering {
}
```
We use a `match` to either give us the `uint` inside of the `Option`, or we
We use a `match` to either give us the `uint` inside of the `Option`, or else
print an error message and return. Let's give this a shot:
```bash
@ -2398,8 +2395,8 @@ Uh, what? But we did!
... actually, we didn't. See, when you get a line of input from `stdin()`,
you get all the input. Including the `\n` character from you pressing Enter.
So, `from_str()` sees the string `"5\n"` and says "nope, that's not a number,
there's non-number stuff in there!" Luckily for us, `&str`s have an easy
Therefore, `from_str()` sees the string `"5\n"` and says "nope, that's not a
number; there's non-number stuff in there!" Luckily for us, `&str`s have an easy
method we can use defined on them: `trim()`. One small modification, and our
code looks like this:
@ -2465,7 +2462,7 @@ out that I guessed 76. Run the program a few times, and verify that guessing
the number works, as well as guessing a number too small.
The Rust compiler helped us out quite a bit there! This technique is called
"lean on the compiler," and it's often useful when working on some code. Let
"lean on the compiler", and it's often useful when working on some code. Let
the error messages help guide you towards the correct types.
Now we've got most of the game working, but we can only make one guess. Let's
@ -2473,8 +2470,8 @@ change that by adding loops!
## Looping
As we already discussed, the `loop` keyword gives us an infinite loop. So
let's add that in:
As we already discussed, the `loop` keyword gives us an infinite loop.
Let's add that in:
```{rust,no_run}
use std::io;
@ -2780,12 +2777,11 @@ $ cargo run
Hello, world!
```
Excellent! So, we already have a single crate here: our `src/main.rs` is a crate.
Excellent! We already have a single crate here: our `src/main.rs` is a crate.
Everything in that file is in the crate root. A crate that generates an executable
defines a `main` function inside its root, as we've done here.
Let's define a new module inside our crate. Edit `src/main.rs` to look
like this:
Let's define a new module inside our crate. Edit `src/main.rs` to look like this:
```
fn main() {
@ -2803,7 +2799,7 @@ We now have a module named `hello` inside of our crate root. Modules use
`snake_case` naming, like functions and variable bindings.
Inside the `hello` module, we've defined a `print_hello` function. This will
also print out our hello world message. Modules allow you to split up your
also print out our "hello world" message. Modules allow you to split up your
program into nice neat boxes of functionality, grouping common things together,
and keeping different things apart. It's kinda like having a set of shelves:
a place for everything and everything in its place.
@ -2963,7 +2959,7 @@ You'll get a warning if you use something marked unstable.
You may have noticed an exclamation point in the `warn` attribute declaration.
The `!` in this attribute means that this attribute applies to the enclosing
item, rather than to the item that follows the attribute. So this `warn`
item, rather than to the item that follows the attribute. This `warn`
attribute declaration applies to the enclosing crate itself, rather than
to whatever item statement follows it:
@ -3003,9 +2999,9 @@ Hello, world!
Great. Rust's infrastructure supports tests in two sorts of places, and they're
for two kinds of tests: you include **unit test**s inside of the crate itself,
and you place **integration test**s inside a `tests` directory. "Unit tests"
are small tests that test one focused unit, "integration tests" tests multiple
units in integration. That said, this is a social convention, they're no different
in syntax. Let's make a `tests` directory:
are small tests that test one focused unit; "integration tests" test multiple
units in integration. That being said, this is a social convention they're no
different in syntax. Let's make a `tests` directory:
```{bash,ignore}
$ mkdir tests
@ -3085,7 +3081,7 @@ test foo ... FAILED
Now we're getting somewhere. Remember when we talked about naming our tests
with good names? This is why. Here, it says 'test foo' because we called our
test 'foo.' If we had given it a good name, it'd be more clear which test
test 'foo'. If we had given it a good name, it'd be more clear which test
failed, especially as we accumulate more tests.
```text
@ -3156,7 +3152,7 @@ our tests, it sets things up so that `cfg(test)` is true. But we want to only
include `main` when it's _not_ true. So we use `not` to negate things:
`cfg(not(test))` will only compile our code when the `cfg(test)` is false.
With this attribute we won't get the warning (even
With this attribute, we won't get the warning (even
though `src/main.rs` gets recompiled this time):
```bash
@ -3200,7 +3196,7 @@ error: aborting due to previous error
Build failed, waiting for other jobs to finish...
Could not compile `testing`.
To learn more, run the command again with --verbose.
To learn more, run the command again with `--verbose`.
```
Rust can't find this function. That makes sense, as we didn't write it yet!
@ -3208,7 +3204,7 @@ Rust can't find this function. That makes sense, as we didn't write it yet!
In order to share this code with our tests, we'll need to make a library crate.
This is also just good software design: as we mentioned before, it's a good idea
to put most of your functionality into a library crate, and have your executable
crate use that library. This allows for code re-use.
crate use that library. This allows for code reuse.
To do that, we'll need to make a new module. Make a new file, `src/lib.rs`,
and put this in it:
@ -3282,8 +3278,8 @@ test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
Great! One test passed. We've got an integration test showing that our public
method works, but maybe we want to test some of the internal logic as well.
While this function is simple, if it were more complicated, you can imagine
we'd need more tests. So let's break it up into two helper functions, and
write some unit tests to test those.
we'd need more tests. Let's break it up into two helper functions and write
some unit tests to test those.
Change your `src/lib.rs` to look like this:
@ -3532,7 +3528,7 @@ error: cannot borrow immutable local variable `x` as mutable
```
We don't want a mutable reference to immutable data! This error message uses a
term we haven't talked about yet, 'borrow.' We'll get to that in just a moment.
term we haven't talked about yet, 'borrow'. We'll get to that in just a moment.
This simple example actually illustrates a lot of Rust's power: Rust has
prevented us, at compile time, from breaking our own rules. Because Rust's
@ -3653,9 +3649,10 @@ all of Rust. Let's see this syntax in action:
fn foo(x: &int) -> &int { x }
{
let x = 5i; // x is the owner of this integer, which is memory on the stack.
// x is the owner of the integer, which is memory on the stack.
let x = 5i;
// privilege 2: you may lend that resource, to as many borrowers as you'd like
// privilege 2: you may lend that resource to as many borrowers as you like
let y = &x;
let z = &x;
@ -3665,10 +3662,11 @@ fn foo(x: &int) -> &int { x }
}
{
let mut x = 5i; // x is the owner of this integer, which is memory on the stack.
// x is the owner of this integer, which is memory on the stack.
let mut x = 5i;
let y = &mut x; // privilege 3: you may lend that resource to a single borrower,
// mutably
// privilege 3: you may lend that resource to a single borrower, mutably
let y = &mut x;
}
```
@ -3684,7 +3682,7 @@ This last requirement can seem odd, but it also makes sense. If you have to
return something, and you've lent it to someone, they need to give it back to
you for you to give it back! If we didn't, then the owner could deallocate
the memory, and the person we've loaned it out to would have a pointer to
invalid memory. This is called a 'dangling pointer.'
invalid memory. This is called a 'dangling pointer'.
Let's re-examine the error that led us to talk about all of this, which was a
violation of the restrictions placed on owners who lend something out mutably.
@ -3807,8 +3805,8 @@ an integer `5` and makes `x` a pointer to it:
```
The great thing about boxes is that we don't have to manually free this
allocation! Instead, when `x` reaches the end of its lifetime -- in this case,
when it goes out of scope at the end of the block -- Rust `free`s `x`. This
allocation! Instead, when `x` reaches the end of its lifetime in this case,
when it goes out of scope at the end of the block Rust `free`s `x`. This
isn't because Rust has a garbage collector (it doesn't). Instead, by tracking
the ownership and lifetime of a variable (with a little help from you, the
programmer), the compiler knows precisely when it is no longer used.
@ -3873,12 +3871,12 @@ Sometimes you need a variable that is referenced from multiple places
(immutably!), lasting as long as any of those places, and disappearing when it
is no longer referenced. For instance, in a graph-like data structure, a node
might be referenced from all of its neighbors. In this case, it is not possible
for the compiler to determine ahead of time when the value can be freed -- it
for the compiler to determine ahead of time when the value can be freed it
needs a little run-time support.
Rust's **Rc** type provides shared ownership of a dynamically allocated value
that is automatically freed at the end of its last owner's lifetime. (`Rc`
stands for 'reference counted,' referring to the way these library types are
stands for 'reference counted', referring to the way these library types are
implemented.) This provides more flexibility than single-owner boxes, but has
some runtime overhead.
@ -4300,7 +4298,7 @@ This line is more interesting. Here, we call our function, `twice`, and we pass
it two arguments: an integer, `5`, and our closure, `square`. This is just like
passing any other two variable bindings to a function, but if you've never
worked with closures before, it can seem a little complex. Just think: "I'm
passing two variables, one is an int, and one is a function."
passing two variables: one is an int, and one is a function."
Next, let's look at how `twice` is defined:
@ -4336,7 +4334,7 @@ fn twice(x: int, f: |int| -> int) -> int {
```
Since our closure is named `f`, we can call it just like we called our closures
before. And we pass in our `x` argument to each one. Hence 'twice.'
before, and we pass in our `x` argument to each one, hence the name `twice`.
If you do the math, `(5 * 5) + (5 * 5) == 50`, so that's the output we get.
@ -4807,7 +4805,7 @@ enum Result<H, N> {
```
if we wanted to. Convention says that the first generic parameter should be
`T`, for 'type,' and that we use `E` for 'error.' Rust doesn't care, however.
`T`, for 'type,' and that we use `E` for 'error'. Rust doesn't care, however.
The `Result<T, E>` type is intended to
be used to return the result of a computation, and to have the ability to
@ -5212,7 +5210,7 @@ fn main() {
The names don't actually change to this, it's just for illustration. But
as you can see, there's no overhead of deciding which version to call here,
hence 'statically dispatched.' The downside is that we have two copies of
hence 'statically dispatched'. The downside is that we have two copies of
the same function, so our binary is a little bit larger.
# Tasks
@ -5412,7 +5410,7 @@ fn main() {
}
```
You can have the macros expanded like this: `rustc print.rs --pretty=expanded` which will
You can have the macros expanded like this: `rustc print.rs --pretty=expanded`, which will
give us this huge result:
```{rust,ignore}
@ -5498,7 +5496,6 @@ We covered a lot of ground here. When you've mastered everything in this Guide,
you will have a firm grasp of basic Rust development. There's a whole lot more
out there, we've just covered the surface. There's tons of topics that you can
dig deeper into, and we've built specialized guides for many of them. To learn
more, dig into the [full documentation
index](index.html).
more, dig into the [full documentation index](index.html).
Happy hacking!

View File

@ -1,28 +0,0 @@
# Add here a list of target languages; po4a will automatically
# generates .po for them and build .md when translated, eg:
# [po4a_langs] es fr it pt_BR
[po4a_langs] ja
[po4a_paths] doc/po/$master.pot $lang:src/doc/po/$lang/$master.po
# Add here below all source documents to be translated
[type: text] src/doc/complement-bugreport.md $lang:doc/l10n/$lang/complement-bugreport.md
[type: text] src/doc/complement-design-faq.md $lang:doc/l10n/$lang/complement-design-faq.md
[type: text] src/doc/complement-lang-faq.md $lang:doc/l10n/$lang/complement-lang-faq.md
[type: text] src/doc/complement-project-faq.md $lang:doc/l10n/$lang/complement-project-faq.md
[type: text] src/doc/guide-container.md $lang:doc/l10n/$lang/guide-container.md
[type: text] src/doc/guide-ffi.md $lang:doc/l10n/$lang/guide-ffi.md
[type: text] src/doc/guide-ownership.md $lang:doc/l10n/$lang/guide-ownership.md
[type: text] src/doc/guide-macros.md $lang:doc/l10n/$lang/guide-macros.md
[type: text] src/doc/guide-plugin.md $lang:doc/l10n/$lang/guide-plugin.md
[type: text] src/doc/guide-pointers.md $lang:doc/l10n/$lang/guide-pointers.md
[type: text] src/doc/guide-strings.md $lang:doc/l10n/$lang/guide-strings.md
[type: text] src/doc/guide-tasks.md $lang:doc/l10n/$lang/guide-tasks.md
[type: text] src/doc/guide-testing.md $lang:doc/l10n/$lang/guide-testing.md
[type: text] src/doc/guide-unsafe.md $lang:doc/l10n/$lang/guide-unsafe.md
[type: text] src/doc/guide-crates.md $lang:doc/l10n/$lang/guide-crates.md
[type: text] src/doc/guide-error-handling.md $lang:doc/l10n/$lang/guide-error-handling.md
[type: text] src/doc/guide.md $lang:doc/l10n/$lang/guide.md
[type: text] src/doc/index.md $lang:doc/l10n/$lang/index.md
[type: text] src/doc/intro.md $lang:doc/l10n/$lang/intro.md
[type: text] src/doc/rust.md $lang:doc/l10n/$lang/rust.md
[type: text] src/doc/rustdoc.md $lang:doc/l10n/$lang/rustdoc.md

View File

@ -518,7 +518,7 @@ This last example is different because it is not possible to use the suffix
syntax with a floating point literal ending in a period. `2.f64` would attempt
to call a method named `f64` on `2`.
##### Boolean literals
#### Boolean literals
The two values of the boolean type are written `true` and `false`.
@ -934,7 +934,7 @@ kinds of view items:
```{.ebnf .gram}
extern_crate_decl : "extern" "crate" crate_name
crate_name: ident | ( string_lit as ident )
crate_name: ident | ( string_lit "as" ident )
```
An _`extern crate` declaration_ specifies a dependency on an external crate.

View File

@ -1,5 +1,5 @@
/**
* Copyright 2013 The Rust Project Developers. See the COPYRIGHT
* Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
* file at the top-level directory of this distribution and at
* http://rust-lang.org/COPYRIGHT.
* With elements taken from Bootstrap v3.0.2 (MIT licensed).
@ -209,7 +209,6 @@ pre {
code {
padding: 0 2px;
color: #8D1A38;
white-space: pre-wrap;
}
pre code {
padding: 0;

View File

@ -10,8 +10,62 @@
#![stable]
//! Concurrency-enabled mechanisms for sharing mutable and/or immutable state
//! between tasks.
//! Threadsafe reference-counted boxes (the `Arc<T>` type).
//!
//! The `Arc<T>` type provides shared ownership of an immutable value. Destruction is
//! deterministic, and will occur as soon as the last owner is gone. It is marked as `Send` because
//! it uses atomic reference counting.
//!
//! If you do not need thread-safety, and just need shared ownership, consider the [`Rc<T>`
//! type](../rc/struct.Rc.html). It is the same as `Arc<T>`, but does not use atomics, making it
//! both thread-unsafe as well as significantly faster when updating the reference count.
//!
//! The `downgrade` method can be used to create a non-owning `Weak<T>` pointer to the box. A
//! `Weak<T>` pointer can be upgraded to an `Arc<T>` pointer, but will return `None` if the value
//! has already been dropped.
//!
//! For example, a tree with parent pointers can be represented by putting the nodes behind strong
//! `Arc<T>` pointers, and then storing the parent pointers as `Weak<T>` pointers.
//!
//! # Examples
//!
//! Sharing some immutable data between tasks:
//!
//! ```
//! use std::sync::Arc;
//! use std::thread::Thread;
//!
//! let five = Arc::new(5i);
//!
//! for i in range(0u, 10) {
//! let five = five.clone();
//!
//! Thread::spawn(move || {
//! println!("{}", five);
//! }).detach();
//! }
//! ```
//!
//! Sharing mutable data safely between tasks with a `Mutex`:
//!
//! ```
//! use std::sync::{Arc, Mutex};
//! use std::thread::Thread;
//!
//! let five = Arc::new(Mutex::new(5i));
//!
//! for _ in range(0u, 10) {
//! let five = five.clone();
//!
//! Thread::spawn(move || {
//! let mut number = five.lock();
//!
//! *number += 1;
//!
//! println!("{}", *number); // prints 6
//! }).detach();
//! }
//! ```
use core::atomic;
use core::borrow::BorrowFrom;
@ -33,9 +87,8 @@ use heap::deallocate;
///
/// # Example
///
/// In this example, a large vector of floats is shared between several tasks.
/// With simple pipes, without `Arc`, a copy would have to be made for each
/// task.
/// In this example, a large vector of floats is shared between several tasks. With simple pipes,
/// without `Arc`, a copy would have to be made for each task.
///
/// ```rust
/// use std::sync::Arc;
@ -66,8 +119,8 @@ pub struct Arc<T> {
/// A weak pointer to an `Arc`.
///
/// Weak pointers will not keep the data inside of the `Arc` alive, and can be
/// used to break cycles between `Arc` pointers.
/// Weak pointers will not keep the data inside of the `Arc` alive, and can be used to break cycles
/// between `Arc` pointers.
#[unsafe_no_drop_flag]
#[experimental = "Weak pointers may not belong in this module."]
pub struct Weak<T> {
@ -83,7 +136,15 @@ struct ArcInner<T> {
}
impl<T: Sync + Send> Arc<T> {
/// Creates an atomically reference counted wrapper.
/// Constructs a new `Arc<T>`.
///
/// # Examples
///
/// ```
/// use std::sync::Arc;
///
/// let five = Arc::new(5i);
/// ```
#[inline]
#[stable]
pub fn new(data: T) -> Arc<T> {
@ -97,11 +158,17 @@ impl<T: Sync + Send> Arc<T> {
Arc { _ptr: unsafe { mem::transmute(x) } }
}
/// Downgrades a strong pointer to a weak pointer.
/// Downgrades the `Arc<T>` to a `Weak<T>` reference.
///
/// Weak pointers will not keep the data alive. Once all strong references
/// to the underlying data have been dropped, the data itself will be
/// destroyed.
/// # Examples
///
/// ```
/// use std::sync::Arc;
///
/// let five = Arc::new(5i);
///
/// let weak_five = five.downgrade();
/// ```
#[experimental = "Weak pointers may not belong in this module."]
pub fn downgrade(&self) -> Weak<T> {
// See the clone() impl for why this is relaxed
@ -113,11 +180,10 @@ impl<T: Sync + Send> Arc<T> {
impl<T> Arc<T> {
#[inline]
fn inner(&self) -> &ArcInner<T> {
// This unsafety is ok because while this arc is alive we're guaranteed
// that the inner pointer is valid. Furthermore, we know that the
// `ArcInner` structure itself is `Sync` because the inner data is
// `Sync` as well, so we're ok loaning out an immutable pointer to
// these contents.
// This unsafety is ok because while this arc is alive we're guaranteed that the inner
// pointer is valid. Furthermore, we know that the `ArcInner` structure itself is `Sync`
// because the inner data is `Sync` as well, so we're ok loaning out an immutable pointer
// to these contents.
unsafe { &*self._ptr }
}
}
@ -132,24 +198,30 @@ pub fn weak_count<T>(this: &Arc<T>) -> uint { this.inner().weak.load(atomic::Seq
#[experimental]
pub fn strong_count<T>(this: &Arc<T>) -> uint { this.inner().strong.load(atomic::SeqCst) }
#[unstable = "waiting on stability of Clone"]
#[stable]
impl<T> Clone for Arc<T> {
/// Duplicate an atomically reference counted wrapper.
/// Makes a clone of the `Arc<T>`.
///
/// The resulting two `Arc` objects will point to the same underlying data
/// object. However, one of the `Arc` objects can be sent to another task,
/// allowing them to share the underlying data.
/// This increases the strong reference count.
///
/// # Examples
///
/// ```
/// use std::sync::Arc;
///
/// let five = Arc::new(5i);
///
/// five.clone();
/// ```
#[inline]
fn clone(&self) -> Arc<T> {
// Using a relaxed ordering is alright here, as knowledge of the
// original reference prevents other threads from erroneously deleting
// the object.
// Using a relaxed ordering is alright here, as knowledge of the original reference
// prevents other threads from erroneously deleting the object.
//
// As explained in the [Boost documentation][1], Increasing the
// reference counter can always be done with memory_order_relaxed: New
// references to an object can only be formed from an existing
// reference, and passing an existing reference from one thread to
// another must already provide any required synchronization.
// As explained in the [Boost documentation][1], Increasing the reference counter can
// always be done with memory_order_relaxed: New references to an object can only be formed
// from an existing reference, and passing an existing reference from one thread to another
// must already provide any required synchronization.
//
// [1]: (www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html)
self.inner().strong.fetch_add(1, atomic::Relaxed);
@ -172,26 +244,33 @@ impl<T> Deref<T> for Arc<T> {
}
impl<T: Send + Sync + Clone> Arc<T> {
/// Acquires a mutable pointer to the inner contents by guaranteeing that
/// the reference count is one (no sharing is possible).
/// Make a mutable reference from the given `Arc<T>`.
///
/// This is also referred to as a copy-on-write operation because the inner
/// data is cloned if the reference count is greater than one.
/// This is also referred to as a copy-on-write operation because the inner data is cloned if
/// the reference count is greater than one.
///
/// # Examples
///
/// ```
/// use std::sync::Arc;
///
/// let mut five = Arc::new(5i);
///
/// let mut_five = five.make_unique();
/// ```
#[inline]
#[experimental]
pub fn make_unique(&mut self) -> &mut T {
// Note that we hold a strong reference, which also counts as
// a weak reference, so we only clone if there is an
// additional reference of either kind.
// Note that we hold a strong reference, which also counts as a weak reference, so we only
// clone if there is an additional reference of either kind.
if self.inner().strong.load(atomic::SeqCst) != 1 ||
self.inner().weak.load(atomic::SeqCst) != 1 {
*self = Arc::new((**self).clone())
}
// This unsafety is ok because we're guaranteed that the pointer
// returned is the *only* pointer that will ever be returned to T. Our
// reference count is guaranteed to be 1 at this point, and we required
// the Arc itself to be `mut`, so we're returning the only possible
// reference to the inner data.
// This unsafety is ok because we're guaranteed that the pointer returned is the *only*
// pointer that will ever be returned to T. Our reference count is guaranteed to be 1 at
// this point, and we required the Arc itself to be `mut`, so we're returning the only
// possible reference to the inner data.
let inner = unsafe { &mut *self._ptr };
&mut inner.data
}
@ -200,38 +279,59 @@ impl<T: Send + Sync + Clone> Arc<T> {
#[unsafe_destructor]
#[experimental = "waiting on stability of Drop"]
impl<T: Sync + Send> Drop for Arc<T> {
/// Drops the `Arc<T>`.
///
/// This will decrement the strong reference count. If the strong reference count becomes zero
/// and the only other references are `Weak<T>` ones, `drop`s the inner value.
///
/// # Examples
///
/// ```
/// use std::sync::Arc;
///
/// {
/// let five = Arc::new(5i);
///
/// // stuff
///
/// drop(five); // explict drop
/// }
/// {
/// let five = Arc::new(5i);
///
/// // stuff
///
/// } // implicit drop
/// ```
fn drop(&mut self) {
// This structure has #[unsafe_no_drop_flag], so this drop glue may run
// more than once (but it is guaranteed to be zeroed after the first if
// it's run more than once)
// This structure has #[unsafe_no_drop_flag], so this drop glue may run more than once (but
// it is guaranteed to be zeroed after the first if it's run more than once)
if self._ptr.is_null() { return }
// Because `fetch_sub` is already atomic, we do not need to synchronize
// with other threads unless we are going to delete the object. This
// same logic applies to the below `fetch_sub` to the `weak` count.
// Because `fetch_sub` is already atomic, we do not need to synchronize with other threads
// unless we are going to delete the object. This same logic applies to the below
// `fetch_sub` to the `weak` count.
if self.inner().strong.fetch_sub(1, atomic::Release) != 1 { return }
// This fence is needed to prevent reordering of use of the data and
// deletion of the data. Because it is marked `Release`, the
// decreasing of the reference count synchronizes with this `Acquire`
// fence. This means that use of the data happens before decreasing
// the reference count, which happens before this fence, which
// happens before the deletion of the data.
// This fence is needed to prevent reordering of use of the data and deletion of the data.
// Because it is marked `Release`, the decreasing of the reference count synchronizes with
// this `Acquire` fence. This means that use of the data happens before decreasing the
// reference count, which happens before this fence, which happens before the deletion of
// the data.
//
// As explained in the [Boost documentation][1],
//
// It is important to enforce any possible access to the object in
// one thread (through an existing reference) to *happen before*
// deleting the object in a different thread. This is achieved by a
// "release" operation after dropping a reference (any access to the
// object through this reference must obviously happened before),
// and an "acquire" operation before deleting the object.
// > It is important to enforce any possible access to the object in one thread (through an
// > existing reference) to *happen before* deleting the object in a different thread. This
// > is achieved by a "release" operation after dropping a reference (any access to the
// > object through this reference must obviously happened before), and an "acquire"
// > operation before deleting the object.
//
// [1]: (www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html)
atomic::fence(atomic::Acquire);
// Destroy the data at this time, even though we may not free the box
// allocation itself (there may still be weak pointers lying around).
// Destroy the data at this time, even though we may not free the box allocation itself
// (there may still be weak pointers lying around).
unsafe { drop(ptr::read(&self.inner().data)); }
if self.inner().weak.fetch_sub(1, atomic::Release) == 1 {
@ -244,14 +344,26 @@ impl<T: Sync + Send> Drop for Arc<T> {
#[experimental = "Weak pointers may not belong in this module."]
impl<T: Sync + Send> Weak<T> {
/// Attempts to upgrade this weak reference to a strong reference.
/// Upgrades a weak reference to a strong reference.
///
/// This method will not upgrade this reference if the strong reference count has already
/// reached 0, but if there are still other active strong references this function will return
/// a new strong reference to the data.
/// Upgrades the `Weak<T>` reference to an `Arc<T>`, if possible.
///
/// Returns `None` if there were no strong references and the data was destroyed.
///
/// # Examples
///
/// ```
/// use std::sync::Arc;
///
/// let five = Arc::new(5i);
///
/// let weak_five = five.downgrade();
///
/// let strong_five: Option<Arc<_>> = weak_five.upgrade();
/// ```
pub fn upgrade(&self) -> Option<Arc<T>> {
// We use a CAS loop to increment the strong count instead of a
// fetch_add because once the count hits 0 is must never be above 0.
// We use a CAS loop to increment the strong count instead of a fetch_add because once the
// count hits 0 is must never be above 0.
let inner = self.inner();
loop {
let n = inner.strong.load(atomic::SeqCst);
@ -270,6 +382,19 @@ impl<T: Sync + Send> Weak<T> {
#[experimental = "Weak pointers may not belong in this module."]
impl<T: Sync + Send> Clone for Weak<T> {
/// Makes a clone of the `Weak<T>`.
///
/// This increases the weak reference count.
///
/// # Examples
///
/// ```
/// use std::sync::Arc;
///
/// let weak_five = Arc::new(5i).downgrade();
///
/// weak_five.clone();
/// ```
#[inline]
fn clone(&self) -> Weak<T> {
// See comments in Arc::clone() for why this is relaxed
@ -281,13 +406,37 @@ impl<T: Sync + Send> Clone for Weak<T> {
#[unsafe_destructor]
#[experimental = "Weak pointers may not belong in this module."]
impl<T: Sync + Send> Drop for Weak<T> {
/// Drops the `Weak<T>`.
///
/// This will decrement the weak reference count.
///
/// # Examples
///
/// ```
/// use std::sync::Arc;
///
/// {
/// let five = Arc::new(5i);
/// let weak_five = five.downgrade();
///
/// // stuff
///
/// drop(weak_five); // explict drop
/// }
/// {
/// let five = Arc::new(5i);
/// let weak_five = five.downgrade();
///
/// // stuff
///
/// } // implicit drop
/// ```
fn drop(&mut self) {
// see comments above for why this check is here
if self._ptr.is_null() { return }
// If we find out that we were the last weak pointer, then its time to
// deallocate the data entirely. See the discussion in Arc::drop() about
// the memory orderings
// If we find out that we were the last weak pointer, then its time to deallocate the data
// entirely. See the discussion in Arc::drop() about the memory orderings
if self.inner().weak.fetch_sub(1, atomic::Release) == 1 {
atomic::fence(atomic::Acquire);
unsafe { deallocate(self._ptr as *mut u8, size_of::<ArcInner<T>>(),
@ -298,18 +447,114 @@ impl<T: Sync + Send> Drop for Weak<T> {
#[unstable = "waiting on PartialEq"]
impl<T: PartialEq> PartialEq for Arc<T> {
/// Equality for two `Arc<T>`s.
///
/// Two `Arc<T>`s are equal if their inner value are equal.
///
/// # Examples
///
/// ```
/// use std::sync::Arc;
///
/// let five = Arc::new(5i);
///
/// five == Arc::new(5i);
/// ```
fn eq(&self, other: &Arc<T>) -> bool { *(*self) == *(*other) }
/// Inequality for two `Arc<T>`s.
///
/// Two `Arc<T>`s are unequal if their inner value are unequal.
///
/// # Examples
///
/// ```
/// use std::sync::Arc;
///
/// let five = Arc::new(5i);
///
/// five != Arc::new(5i);
/// ```
fn ne(&self, other: &Arc<T>) -> bool { *(*self) != *(*other) }
}
#[unstable = "waiting on PartialOrd"]
impl<T: PartialOrd> PartialOrd for Arc<T> {
/// Partial comparison for two `Arc<T>`s.
///
/// The two are compared by calling `partial_cmp()` on their inner values.
///
/// # Examples
///
/// ```
/// use std::sync::Arc;
///
/// let five = Arc::new(5i);
///
/// five.partial_cmp(&Arc::new(5i));
/// ```
fn partial_cmp(&self, other: &Arc<T>) -> Option<Ordering> {
(**self).partial_cmp(&**other)
}
/// Less-than comparison for two `Arc<T>`s.
///
/// The two are compared by calling `<` on their inner values.
///
/// # Examples
///
/// ```
/// use std::sync::Arc;
///
/// let five = Arc::new(5i);
///
/// five < Arc::new(5i);
/// ```
fn lt(&self, other: &Arc<T>) -> bool { *(*self) < *(*other) }
/// 'Less-than or equal to' comparison for two `Arc<T>`s.
///
/// The two are compared by calling `<=` on their inner values.
///
/// # Examples
///
/// ```
/// use std::sync::Arc;
///
/// let five = Arc::new(5i);
///
/// five <= Arc::new(5i);
/// ```
fn le(&self, other: &Arc<T>) -> bool { *(*self) <= *(*other) }
fn ge(&self, other: &Arc<T>) -> bool { *(*self) >= *(*other) }
/// Greater-than comparison for two `Arc<T>`s.
///
/// The two are compared by calling `>` on their inner values.
///
/// # Examples
///
/// ```
/// use std::sync::Arc;
///
/// let five = Arc::new(5i);
///
/// five > Arc::new(5i);
/// ```
fn gt(&self, other: &Arc<T>) -> bool { *(*self) > *(*other) }
/// 'Greater-than or equal to' comparison for two `Arc<T>`s.
///
/// The two are compared by calling `>=` on their inner values.
///
/// # Examples
///
/// ```
/// use std::sync::Arc;
///
/// let five = Arc::new(5i);
///
/// five >= Arc::new(5i);
/// ```
fn ge(&self, other: &Arc<T>) -> bool { *(*self) >= *(*other) }
}
#[unstable = "waiting on Ord"]
impl<T: Ord> Ord for Arc<T> {

View File

@ -22,6 +22,7 @@ use core::option::Option;
use core::raw::TraitObject;
use core::result::Result;
use core::result::Result::{Ok, Err};
use core::ops::{Deref, DerefMut};
/// A value that represents the global exchange heap. This is the default
/// place that the `box` keyword allocates into when no place is supplied.
@ -57,7 +58,7 @@ impl<T> Default for Box<[T]> {
fn default() -> Box<[T]> { box [] }
}
#[unstable]
#[stable]
impl<T: Clone> Clone for Box<T> {
/// Returns a copy of the owned box.
#[inline]
@ -147,6 +148,14 @@ impl fmt::Show for Box<Any+'static> {
}
}
impl<Sized? T> Deref<T> for Box<T> {
fn deref(&self) -> &T { &**self }
}
impl<Sized? T> DerefMut<T> for Box<T> {
fn deref_mut(&mut self) -> &mut T { &mut **self }
}
#[cfg(test)]
mod test {
#[test]
@ -193,4 +202,10 @@ mod test {
let s = format!("{}", b);
assert_eq!(s, "&Any");
}
#[test]
fn deref() {
fn homura<T: Deref<i32>>(_: T) { }
homura(box 765i32);
}
}

View File

@ -168,12 +168,12 @@ struct RcBox<T> {
/// An immutable reference-counted pointer type.
///
/// See the [module level documentation](../index.html) for more.
/// See the [module level documentation](../index.html) for more details.
#[unsafe_no_drop_flag]
#[stable]
pub struct Rc<T> {
// FIXME #12808: strange names to try to avoid interfering with
// field accesses of the contained type via Deref
// FIXME #12808: strange names to try to avoid interfering with field accesses of the contained
// type via Deref
_ptr: *mut RcBox<T>,
_nosend: marker::NoSend,
_noshare: marker::NoSync
@ -193,11 +193,9 @@ impl<T> Rc<T> {
pub fn new(value: T) -> Rc<T> {
unsafe {
Rc {
// there is an implicit weak pointer owned by all the
// strong pointers, which ensures that the weak
// destructor never frees the allocation while the
// strong destructor is running, even if the weak
// pointer is stored inside the strong one.
// there is an implicit weak pointer owned by all the strong pointers, which
// ensures that the weak destructor never frees the allocation while the strong
// destructor is running, even if the weak pointer is stored inside the strong one.
_ptr: transmute(box RcBox {
value: value,
strong: Cell::new(1),
@ -341,11 +339,10 @@ impl<T: Clone> Rc<T> {
if !is_unique(self) {
*self = Rc::new((**self).clone())
}
// This unsafety is ok because we're guaranteed that the pointer
// returned is the *only* pointer that will ever be returned to T. Our
// reference count is guaranteed to be 1 at this point, and we required
// the `Rc<T>` itself to be `mut`, so we're returning the only possible
// reference to the inner value.
// This unsafety is ok because we're guaranteed that the pointer returned is the *only*
// pointer that will ever be returned to T. Our reference count is guaranteed to be 1 at
// this point, and we required the `Rc<T>` itself to be `mut`, so we're returning the only
// possible reference to the inner value.
let inner = unsafe { &mut *self._ptr };
&mut inner.value
}
@ -399,8 +396,8 @@ impl<T> Drop for Rc<T> {
if self.strong() == 0 {
ptr::read(&**self); // destroy the contained object
// remove the implicit "strong weak" pointer now
// that we've destroyed the contents.
// remove the implicit "strong weak" pointer now that we've destroyed the
// contents.
self.dec_weak();
if self.weak() == 0 {
@ -413,7 +410,7 @@ impl<T> Drop for Rc<T> {
}
}
#[unstable = "Clone is unstable."]
#[stable]
impl<T> Clone for Rc<T> {
/// Makes a clone of the `Rc<T>`.
///
@ -687,8 +684,8 @@ impl<T> Drop for Weak<T> {
unsafe {
if !self._ptr.is_null() {
self.dec_weak();
// the weak count starts at 1, and will only go to
// zero if all the strong pointers have disappeared.
// the weak count starts at 1, and will only go to zero if all the strong pointers
// have disappeared.
if self.weak() == 0 {
deallocate(self._ptr as *mut u8, size_of::<RcBox<T>>(),
min_align_of::<RcBox<T>>())

View File

@ -239,7 +239,7 @@ impl<T: Ord> BinaryHeap<T> {
/// }
/// ```
#[unstable = "matches collection reform specification, waiting for dust to settle"]
pub fn iter<'a>(&'a self) -> Items<'a, T> {
pub fn iter(&self) -> Items<T> {
Items { iter: self.data.iter() }
}
@ -280,8 +280,8 @@ impl<T: Ord> BinaryHeap<T> {
/// assert_eq!(heap.top(), Some(&5i));
///
/// ```
pub fn top<'a>(&'a self) -> Option<&'a T> {
if self.is_empty() { None } else { Some(&self.data[0]) }
pub fn top(&self) -> Option<&T> {
self.data.get(0)
}
/// Returns the number of elements the queue can hold without reallocating.
@ -392,9 +392,9 @@ impl<T: Ord> BinaryHeap<T> {
/// ```
#[unstable = "matches collection reform specification, waiting for dust to settle"]
pub fn push(&mut self, item: T) {
let old_len = self.len();
self.data.push(item);
let new_len = self.len() - 1;
self.siftup(0, new_len);
self.siftup(0, old_len);
}
/// Pushes an item onto a queue then pops the greatest item off the queue in
@ -415,10 +415,16 @@ impl<T: Ord> BinaryHeap<T> {
/// assert_eq!(heap.top(), Some(&3i));
/// ```
pub fn push_pop(&mut self, mut item: T) -> T {
if !self.is_empty() && *self.top().unwrap() > item {
swap(&mut item, &mut self.data[0]);
self.siftdown(0);
match self.data.get_mut(0) {
None => return item,
Some(top) => if *top > item {
swap(&mut item, top);
} else {
return item;
},
}
self.siftdown(0);
item
}
@ -465,7 +471,7 @@ impl<T: Ord> BinaryHeap<T> {
/// println!("{}", x);
/// }
/// ```
pub fn into_vec(self) -> Vec<T> { let BinaryHeap{data: v} = self; v }
pub fn into_vec(self) -> Vec<T> { self.data }
/// Consumes the `BinaryHeap` and returns a vector in sorted
/// (ascending) order.
@ -482,15 +488,14 @@ impl<T: Ord> BinaryHeap<T> {
/// let vec = heap.into_sorted_vec();
/// assert_eq!(vec, vec![1i, 2, 3, 4, 5, 6, 7]);
/// ```
pub fn into_sorted_vec(self) -> Vec<T> {
let mut q = self;
let mut end = q.len();
pub fn into_sorted_vec(mut self) -> Vec<T> {
let mut end = self.len();
while end > 1 {
end -= 1;
q.data.swap(0, end);
q.siftdown_range(0, end)
self.data.swap(0, end);
self.siftdown_range(0, end)
}
q.into_vec()
self.into_vec()
}
// The implementations of siftup and siftdown use unsafe blocks in
@ -566,13 +571,13 @@ impl<T: Ord> BinaryHeap<T> {
}
/// `BinaryHeap` iterator.
pub struct Items <'a, T:'a> {
pub struct Items<'a, T: 'a> {
iter: slice::Items<'a, T>,
}
impl<'a, T> Iterator<&'a T> for Items<'a, T> {
#[inline]
fn next(&mut self) -> Option<(&'a T)> { self.iter.next() }
fn next(&mut self) -> Option<&'a T> { self.iter.next() }
#[inline]
fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
@ -580,7 +585,7 @@ impl<'a, T> Iterator<&'a T> for Items<'a, T> {
impl<'a, T> DoubleEndedIterator<&'a T> for Items<'a, T> {
#[inline]
fn next_back(&mut self) -> Option<(&'a T)> { self.iter.next_back() }
fn next_back(&mut self) -> Option<&'a T> { self.iter.next_back() }
}
impl<'a, T> ExactSizeIterator<&'a T> for Items<'a, T> {}
@ -627,8 +632,7 @@ impl<'a, T: 'a> ExactSizeIterator<T> for Drain<'a, T> {}
impl<T: Ord> FromIterator<T> for BinaryHeap<T> {
fn from_iter<Iter: Iterator<T>>(iter: Iter) -> BinaryHeap<T> {
let vec: Vec<T> = iter.collect();
BinaryHeap::from_vec(vec)
BinaryHeap::from_vec(iter.collect())
}
}
@ -822,20 +826,20 @@ mod tests {
#[test]
fn test_empty_pop() {
let mut heap: BinaryHeap<int> = BinaryHeap::new();
let mut heap = BinaryHeap::<int>::new();
assert!(heap.pop().is_none());
}
#[test]
fn test_empty_top() {
let empty: BinaryHeap<int> = BinaryHeap::new();
let empty = BinaryHeap::<int>::new();
assert!(empty.top().is_none());
}
#[test]
fn test_empty_replace() {
let mut heap: BinaryHeap<int> = BinaryHeap::new();
heap.replace(5).is_none();
let mut heap = BinaryHeap::<int>::new();
assert!(heap.replace(5).is_none());
}
#[test]

View File

@ -851,6 +851,7 @@ impl Extend<bool> for Bitv {
}
}
#[stable]
impl Clone for Bitv {
#[inline]
fn clone(&self) -> Bitv {

View File

@ -390,6 +390,7 @@ impl<K, V> Node<K, V> {
}
// FIXME(gereeter) Write an efficient clone_from
#[stable]
impl<K: Clone, V: Clone> Clone for Node<K, V> {
fn clone(&self) -> Node<K, V> {
let mut ret = if self.is_leaf() {

View File

@ -448,30 +448,6 @@ impl<T: Ord> Default for BTreeSet<T> {
}
#[unstable = "matches collection reform specification, waiting for dust to settle"]
// NOTE(stage0): Remove impl after a snapshot
#[cfg(stage0)]
impl<T: Ord + Clone> Sub<BTreeSet<T>,BTreeSet<T>> for BTreeSet<T> {
/// Returns the difference of `self` and `rhs` as a new `BTreeSet<T>`.
///
/// # Examples
///
/// ```
/// use std::collections::BTreeSet;
///
/// let a: BTreeSet<int> = vec![1,2,3].into_iter().collect();
/// let b: BTreeSet<int> = vec![3,4,5].into_iter().collect();
///
/// let result: BTreeSet<int> = a - b;
/// let result_vec: Vec<int> = result.into_iter().collect();
/// assert_eq!(result_vec, vec![1,2]);
/// ```
fn sub(&self, rhs: &BTreeSet<T>) -> BTreeSet<T> {
self.difference(rhs).cloned().collect()
}
}
#[unstable = "matches collection reform specification, waiting for dust to settle"]
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
impl<'a, 'b, T: Ord + Clone> Sub<&'b BTreeSet<T>, BTreeSet<T>> for &'a BTreeSet<T> {
/// Returns the difference of `self` and `rhs` as a new `BTreeSet<T>`.
///
@ -493,30 +469,6 @@ impl<'a, 'b, T: Ord + Clone> Sub<&'b BTreeSet<T>, BTreeSet<T>> for &'a BTreeSet<
}
#[unstable = "matches collection reform specification, waiting for dust to settle"]
// NOTE(stage0): Remove impl after a snapshot
#[cfg(stage0)]
impl<T: Ord + Clone> BitXor<BTreeSet<T>,BTreeSet<T>> for BTreeSet<T> {
/// Returns the symmetric difference of `self` and `rhs` as a new `BTreeSet<T>`.
///
/// # Examples
///
/// ```
/// use std::collections::BTreeSet;
///
/// let a: BTreeSet<int> = vec![1,2,3].into_iter().collect();
/// let b: BTreeSet<int> = vec![2,3,4].into_iter().collect();
///
/// let result: BTreeSet<int> = a ^ b;
/// let result_vec: Vec<int> = result.into_iter().collect();
/// assert_eq!(result_vec, vec![1,4]);
/// ```
fn bitxor(&self, rhs: &BTreeSet<T>) -> BTreeSet<T> {
self.symmetric_difference(rhs).cloned().collect()
}
}
#[unstable = "matches collection reform specification, waiting for dust to settle"]
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
impl<'a, 'b, T: Ord + Clone> BitXor<&'b BTreeSet<T>, BTreeSet<T>> for &'a BTreeSet<T> {
/// Returns the symmetric difference of `self` and `rhs` as a new `BTreeSet<T>`.
///
@ -538,30 +490,6 @@ impl<'a, 'b, T: Ord + Clone> BitXor<&'b BTreeSet<T>, BTreeSet<T>> for &'a BTreeS
}
#[unstable = "matches collection reform specification, waiting for dust to settle"]
// NOTE(stage0): Remove impl after a snapshot
#[cfg(stage0)]
impl<T: Ord + Clone> BitAnd<BTreeSet<T>,BTreeSet<T>> for BTreeSet<T> {
/// Returns the intersection of `self` and `rhs` as a new `BTreeSet<T>`.
///
/// # Examples
///
/// ```
/// use std::collections::BTreeSet;
///
/// let a: BTreeSet<int> = vec![1,2,3].into_iter().collect();
/// let b: BTreeSet<int> = vec![2,3,4].into_iter().collect();
///
/// let result: BTreeSet<int> = a & b;
/// let result_vec: Vec<int> = result.into_iter().collect();
/// assert_eq!(result_vec, vec![2,3]);
/// ```
fn bitand(&self, rhs: &BTreeSet<T>) -> BTreeSet<T> {
self.intersection(rhs).cloned().collect()
}
}
#[unstable = "matches collection reform specification, waiting for dust to settle"]
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
impl<'a, 'b, T: Ord + Clone> BitAnd<&'b BTreeSet<T>, BTreeSet<T>> for &'a BTreeSet<T> {
/// Returns the intersection of `self` and `rhs` as a new `BTreeSet<T>`.
///
@ -583,30 +511,6 @@ impl<'a, 'b, T: Ord + Clone> BitAnd<&'b BTreeSet<T>, BTreeSet<T>> for &'a BTreeS
}
#[unstable = "matches collection reform specification, waiting for dust to settle"]
// NOTE(stage0): Remove impl after a snapshot
#[cfg(stage0)]
impl<T: Ord + Clone> BitOr<BTreeSet<T>,BTreeSet<T>> for BTreeSet<T> {
/// Returns the union of `self` and `rhs` as a new `BTreeSet<T>`.
///
/// # Examples
///
/// ```
/// use std::collections::BTreeSet;
///
/// let a: BTreeSet<int> = vec![1,2,3].into_iter().collect();
/// let b: BTreeSet<int> = vec![3,4,5].into_iter().collect();
///
/// let result: BTreeSet<int> = a | b;
/// let result_vec: Vec<int> = result.into_iter().collect();
/// assert_eq!(result_vec, vec![1,2,3,4,5]);
/// ```
fn bitor(&self, rhs: &BTreeSet<T>) -> BTreeSet<T> {
self.union(rhs).cloned().collect()
}
}
#[unstable = "matches collection reform specification, waiting for dust to settle"]
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
impl<'a, 'b, T: Ord + Clone> BitOr<&'b BTreeSet<T>, BTreeSet<T>> for &'a BTreeSet<T> {
/// Returns the union of `self` and `rhs` as a new `BTreeSet<T>`.
///

View File

@ -758,6 +758,7 @@ impl<A: Ord> Ord for DList<A> {
}
}
#[stable]
impl<A: Clone> Clone for DList<A> {
fn clone(&self) -> DList<A> {
self.iter().map(|x| x.clone()).collect()

View File

@ -183,60 +183,24 @@ impl<E:CLike> EnumSet<E> {
}
}
// NOTE(stage0): Remove impl after a snapshot
#[cfg(stage0)]
impl<E:CLike> Sub<EnumSet<E>, EnumSet<E>> for EnumSet<E> {
fn sub(&self, e: &EnumSet<E>) -> EnumSet<E> {
EnumSet {bits: self.bits & !e.bits}
}
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
impl<E:CLike> Sub<EnumSet<E>, EnumSet<E>> for EnumSet<E> {
fn sub(self, e: EnumSet<E>) -> EnumSet<E> {
EnumSet {bits: self.bits & !e.bits}
}
}
// NOTE(stage0): Remove impl after a snapshot
#[cfg(stage0)]
impl<E:CLike> BitOr<EnumSet<E>, EnumSet<E>> for EnumSet<E> {
fn bitor(&self, e: &EnumSet<E>) -> EnumSet<E> {
EnumSet {bits: self.bits | e.bits}
}
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
impl<E:CLike> BitOr<EnumSet<E>, EnumSet<E>> for EnumSet<E> {
fn bitor(self, e: EnumSet<E>) -> EnumSet<E> {
EnumSet {bits: self.bits | e.bits}
}
}
// NOTE(stage0): Remove impl after a snapshot
#[cfg(stage0)]
impl<E:CLike> BitAnd<EnumSet<E>, EnumSet<E>> for EnumSet<E> {
fn bitand(&self, e: &EnumSet<E>) -> EnumSet<E> {
EnumSet {bits: self.bits & e.bits}
}
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
impl<E:CLike> BitAnd<EnumSet<E>, EnumSet<E>> for EnumSet<E> {
fn bitand(self, e: EnumSet<E>) -> EnumSet<E> {
EnumSet {bits: self.bits & e.bits}
}
}
// NOTE(stage0): Remove impl after a snapshot
#[cfg(stage0)]
impl<E:CLike> BitXor<EnumSet<E>, EnumSet<E>> for EnumSet<E> {
fn bitxor(&self, e: &EnumSet<E>) -> EnumSet<E> {
EnumSet {bits: self.bits ^ e.bits}
}
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
impl<E:CLike> BitXor<EnumSet<E>, EnumSet<E>> for EnumSet<E> {
fn bitxor(self, e: EnumSet<E>) -> EnumSet<E> {
EnumSet {bits: self.bits ^ e.bits}

View File

@ -48,6 +48,7 @@ pub struct RingBuf<T> {
ptr: *mut T
}
#[stable]
impl<T: Clone> Clone for RingBuf<T> {
fn clone(&self) -> RingBuf<T> {
self.iter().map(|t| t.clone()).collect()

View File

@ -51,7 +51,7 @@
#![doc(primitive = "str")]
pub use self::MaybeOwned::*;
use self::MaybeOwned::*;
use self::RecompositionState::*;
use self::DecompositionType::*;
@ -842,7 +842,7 @@ mod tests {
use core::iter::AdditiveIterator;
use super::{eq_slice, from_utf8, is_utf8, is_utf16, raw};
use super::truncate_utf16_at_nul;
use super::{Owned, Slice};
use super::MaybeOwned::{Owned, Slice};
#[test]
fn test_eq_slice() {

View File

@ -26,7 +26,8 @@ use core::raw::Slice as RawSlice;
use slice::CloneSliceExt;
use str;
use str::{CharRange, CowString, FromStr, StrAllocating, Owned};
use str::{CharRange, CowString, FromStr, StrAllocating};
use str::MaybeOwned::Owned;
use vec::{DerefVec, Vec, as_vec};
/// A growable string stored as a UTF-8 encoded buffer.
@ -512,6 +513,11 @@ impl String {
#[inline]
#[stable = "function just renamed from push_char"]
pub fn push(&mut self, ch: char) {
if (ch as u32) < 0x80 {
self.vec.push(ch as u8);
return;
}
let cur_len = self.len();
// This may use up to 4 bytes.
self.vec.reserve(4);
@ -856,28 +862,7 @@ impl<'a, S: Str> Equiv<S> for String {
}
}
// NOTE(stage0): Remove impl after a snapshot
#[cfg(stage0)]
#[experimental = "waiting on Add stabilization"]
impl<S: Str> Add<S, String> for String {
/// Concatenates `self` and `other` as a new mutable `String`.
///
/// # Examples
///
/// ```
/// let string1 = "foo".to_string();
/// let string2 = "bar".to_string();
/// let string3 = string1 + string2;
/// assert_eq!(string3, "foobar".to_string());
/// ```
fn add(&self, other: &S) -> String {
let mut s = String::from_str(self.as_slice());
s.push_str(other.as_slice());
return s;
}
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
impl<'a> Add<&'a str, String> for String {
fn add(mut self, other: &str) -> String {
self.push_str(other);
@ -885,14 +870,6 @@ impl<'a> Add<&'a str, String> for String {
}
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
impl<'a> Add<String, String> for &'a str {
fn add(self, mut other: String) -> String {
other.push_str(self);
other
}
}
impl ops::Slice<uint, str> for String {
#[inline]
fn as_slice_<'a>(&'a self) -> &'a str {
@ -1408,6 +1385,41 @@ mod tests {
});
}
const REPETITIONS: u64 = 10_000;
#[bench]
fn bench_push_str_one_byte(b: &mut Bencher) {
b.bytes = REPETITIONS;
b.iter(|| {
let mut r = String::new();
for _ in range(0, REPETITIONS) {
r.push_str("a")
}
});
}
#[bench]
fn bench_push_char_one_byte(b: &mut Bencher) {
b.bytes = REPETITIONS;
b.iter(|| {
let mut r = String::new();
for _ in range(0, REPETITIONS) {
r.push('a')
}
});
}
#[bench]
fn bench_push_char_two_bytes(b: &mut Bencher) {
b.bytes = REPETITIONS * 2;
b.iter(|| {
let mut r = String::new();
for _ in range(0, REPETITIONS) {
r.push('â')
}
});
}
#[bench]
fn from_utf8_lossy_100_ascii(b: &mut Bencher) {
let s = b"Hello there, the quick brown fox jumped over the lazy dog! \

View File

@ -53,6 +53,7 @@ use core::cmp::max;
use core::default::Default;
use core::fmt;
use core::hash::{mod, Hash};
use core::iter::repeat;
use core::kinds::marker::{ContravariantLifetime, InvariantType};
use core::mem;
use core::num::{Int, UnsignedInt};
@ -411,6 +412,33 @@ impl<T: Clone> Vec<T> {
}
}
/// Resizes the `Vec` in-place so that `len()` is equal to `new_len`.
///
/// Calls either `extend()` or `truncate()` depending on whether `new_len`
/// is larger than the current value of `len()` or not.
///
/// # Examples
///
/// ```
/// let mut vec = vec!["hello"];
/// vec.resize(3, "world");
/// assert_eq!(vec, vec!["hello", "world", "world"]);
///
/// let mut vec = vec![1i, 2, 3, 4];
/// vec.resize(2, 0);
/// assert_eq!(vec, vec![1, 2]);
/// ```
#[unstable = "matches collection reform specification; waiting for dust to settle"]
pub fn resize(&mut self, new_len: uint, value: T) {
let len = self.len();
if new_len > len {
self.extend(repeat(value).take(new_len - len));
} else {
self.truncate(new_len);
}
}
/// Partitions a vector based on a predicate.
///
/// Clones the elements of the vector, partitioning them into two `Vec<T>`s
@ -442,7 +470,7 @@ impl<T: Clone> Vec<T> {
}
}
#[unstable]
#[stable]
impl<T:Clone> Clone for Vec<T> {
fn clone(&self) -> Vec<T> { self.as_slice().to_vec() }
@ -1334,20 +1362,6 @@ impl<T> AsSlice<T> for Vec<T> {
}
}
// NOTE(stage0): Remove impl after a snapshot
#[cfg(stage0)]
impl<T: Clone, Sized? V: AsSlice<T>> Add<V, Vec<T>> for Vec<T> {
#[inline]
fn add(&self, rhs: &V) -> Vec<T> {
let mut res = Vec::with_capacity(self.len() + rhs.as_slice().len());
res.push_all(self.as_slice());
res.push_all(rhs.as_slice());
res
}
}
#[cfg(not(stage0))] // NOTE(stage0): Remove impl after a snapshot
impl<'a, T: Clone> Add<&'a [T], Vec<T>> for Vec<T> {
#[inline]
fn add(mut self, rhs: &[T]) -> Vec<T> {
@ -1356,15 +1370,6 @@ impl<'a, T: Clone> Add<&'a [T], Vec<T>> for Vec<T> {
}
}
#[cfg(not(stage0))] // NOTE(stage0): Remove impl after a snapshot
impl<'a, T: Clone> Add<Vec<T>, Vec<T>> for &'a [T] {
#[inline]
fn add(self, mut rhs: Vec<T>) -> Vec<T> {
rhs.push_all(self);
rhs
}
}
#[unsafe_destructor]
impl<T> Drop for Vec<T> {
fn drop(&mut self) {

View File

@ -25,7 +25,7 @@ use option::Option;
macro_rules! array_impls {
($($N:expr)+) => {
$(
#[unstable = "waiting for Clone to stabilize"]
#[stable]
impl<T:Copy> Clone for [T, ..$N] {
fn clone(&self) -> [T, ..$N] {
*self
@ -115,4 +115,3 @@ array_impls! {
20 21 22 23 24 25 26 27 28 29
30 31 32
}

View File

@ -137,6 +137,7 @@ pub enum Cow<'a, T, Sized? B: 'a> where B: ToOwned<T> {
Owned(T)
}
#[stable]
impl<'a, T, Sized? B> Clone for Cow<'a, T, B> where B: ToOwned<T> {
fn clone(&self) -> Cow<'a, T, B> {
match *self {

View File

@ -164,7 +164,7 @@ use option::Option;
use option::Option::{None, Some};
/// A mutable memory location that admits only `Copy` data.
#[unstable = "likely to be renamed; otherwise stable"]
#[stable]
pub struct Cell<T> {
value: UnsafeCell<T>,
noshare: marker::NoSync,
@ -208,7 +208,7 @@ impl<T:Copy> Cell<T> {
}
}
#[unstable = "waiting for `Clone` trait to become stable"]
#[stable]
impl<T:Copy> Clone for Cell<T> {
fn clone(&self) -> Cell<T> {
Cell::new(self.get())
@ -231,7 +231,7 @@ impl<T:PartialEq + Copy> PartialEq for Cell<T> {
}
/// A mutable memory location with dynamically checked borrow rules
#[unstable = "likely to be renamed; otherwise stable"]
#[stable]
pub struct RefCell<T> {
value: UnsafeCell<T>,
borrow: Cell<BorrowFlag>,
@ -256,7 +256,7 @@ impl<T> RefCell<T> {
}
/// Consumes the `RefCell`, returning the wrapped value.
#[unstable = "recently renamed per RFC 430"]
#[stable]
pub fn into_inner(self) -> T {
// Since this function takes `self` (the `RefCell`) by value, the
// compiler statically verifies that it is not currently borrowed.
@ -275,7 +275,7 @@ impl<T> RefCell<T> {
/// immutable borrows can be taken out at the same time.
///
/// Returns `None` if the value is currently mutably borrowed.
#[unstable = "may be renamed, depending on global conventions"]
#[unstable = "may be renamed or removed"]
pub fn try_borrow<'a>(&'a self) -> Option<Ref<'a, T>> {
match BorrowRef::new(&self.borrow) {
Some(b) => Some(Ref { _value: unsafe { &*self.value.get() }, _borrow: b }),
@ -291,7 +291,7 @@ impl<T> RefCell<T> {
/// # Panics
///
/// Panics if the value is currently mutably borrowed.
#[unstable]
#[stable]
pub fn borrow<'a>(&'a self) -> Ref<'a, T> {
match self.try_borrow() {
Some(ptr) => ptr,
@ -305,7 +305,7 @@ impl<T> RefCell<T> {
/// cannot be borrowed while this borrow is active.
///
/// Returns `None` if the value is currently borrowed.
#[unstable = "may be renamed, depending on global conventions"]
#[unstable = "may be renamed or removed"]
pub fn try_borrow_mut<'a>(&'a self) -> Option<RefMut<'a, T>> {
match BorrowRefMut::new(&self.borrow) {
Some(b) => Some(RefMut { _value: unsafe { &mut *self.value.get() }, _borrow: b }),
@ -321,7 +321,7 @@ impl<T> RefCell<T> {
/// # Panics
///
/// Panics if the value is currently borrowed.
#[unstable]
#[stable]
pub fn borrow_mut<'a>(&'a self) -> RefMut<'a, T> {
match self.try_borrow_mut() {
Some(ptr) => ptr,
@ -341,7 +341,7 @@ impl<T> RefCell<T> {
}
}
#[unstable = "waiting for `Clone` to become stable"]
#[stable]
impl<T: Clone> Clone for RefCell<T> {
fn clone(&self) -> RefCell<T> {
RefCell::new(self.borrow().clone())
@ -400,7 +400,7 @@ impl<'b> Clone for BorrowRef<'b> {
}
/// Wraps a borrowed reference to a value in a `RefCell` box.
#[unstable]
#[stable]
pub struct Ref<'b, T:'b> {
// FIXME #12808: strange name to try to avoid interfering with
// field accesses of the contained type via Deref
@ -456,7 +456,7 @@ impl<'b> BorrowRefMut<'b> {
}
/// Wraps a mutable borrowed reference to a value in a `RefCell` box.
#[unstable]
#[stable]
pub struct RefMut<'b, T:'b> {
// FIXME #12808: strange name to try to avoid interfering with
// field accesses of the contained type via Deref
@ -517,7 +517,7 @@ impl<'b, T> DerefMut<T> for RefMut<'b, T> {
/// is not recommended to access its fields directly, `get` should be used
/// instead.
#[lang="unsafe"]
#[unstable = "this type may be renamed in the future"]
#[stable]
pub struct UnsafeCell<T> {
/// Wrapped value
///
@ -539,22 +539,16 @@ impl<T> UnsafeCell<T> {
}
/// Gets a mutable pointer to the wrapped value.
///
/// This function is unsafe as the pointer returned is an unsafe pointer and
/// no guarantees are made about the aliasing of the pointers being handed
/// out in this or other tasks.
#[inline]
#[unstable = "conventions around acquiring an inner reference are still \
under development"]
pub unsafe fn get(&self) -> *mut T { &self.value as *const T as *mut T }
#[stable]
pub fn get(&self) -> *mut T { &self.value as *const T as *mut T }
/// Unwraps the value
///
/// This function is unsafe because there is no guarantee that this or other
/// tasks are currently inspecting the inner value.
#[inline]
#[unstable = "conventions around the name `unwrap` are still under \
development"]
#[stable]
pub unsafe fn into_inner(self) -> T { self.value }
/// Deprecated, use into_inner() instead

View File

@ -19,13 +19,15 @@
//! explicitly, by convention implementing the `Clone` trait and calling
//! the `clone` method.
#![unstable]
#![stable]
use kinds::Sized;
/// A common trait for cloning an object.
#[stable]
pub trait Clone {
/// Returns a copy of the value.
#[stable]
fn clone(&self) -> Self;
/// Perform copy-assignment from `source`.
@ -34,12 +36,13 @@ pub trait Clone {
/// but can be overridden to reuse the resources of `a` to avoid unnecessary
/// allocations.
#[inline(always)]
#[experimental = "this function is mostly unused"]
#[unstable = "this function rarely unused"]
fn clone_from(&mut self, source: &Self) {
*self = source.clone()
}
}
#[stable]
impl<'a, Sized? T> Clone for &'a T {
/// Return a shallow copy of the reference.
#[inline]
@ -48,6 +51,7 @@ impl<'a, Sized? T> Clone for &'a T {
macro_rules! clone_impl {
($t:ty) => {
#[stable]
impl Clone for $t {
/// Return a deep copy of the value.
#[inline]
@ -95,4 +99,3 @@ extern_fn_clone! { A, B, C, D, E }
extern_fn_clone! { A, B, C, D, E, F }
extern_fn_clone! { A, B, C, D, E, F, G }
extern_fn_clone! { A, B, C, D, E, F, G, H }

View File

@ -195,6 +195,7 @@ impl Writer for SipState {
}
}
#[stable]
impl Clone for SipState {
#[inline]
fn clone(&self) -> SipState {

View File

@ -222,7 +222,7 @@ extern "rust-intrinsic" {
/// Both types must have the same size and alignment, and this guarantee
/// is enforced at compile-time.
///
/// # Example
/// # Examples
///
/// ```rust
/// use std::mem;
@ -253,14 +253,20 @@ extern "rust-intrinsic" {
/// integer, since the conversion would throw away aliasing information.
pub fn offset<T>(dst: *const T, offset: int) -> *const T;
/// Copies data from one location to another.
///
/// Copies `count` elements (not bytes) from `src` to `dst`. The source
/// Copies `count * size_of<T>` bytes from `src` to `dst`. The source
/// and destination may *not* overlap.
///
/// `copy_nonoverlapping_memory` is semantically equivalent to C's `memcpy`.
///
/// # Example
/// # Safety
///
/// Beyond requiring that both regions of memory be allocated, it is Undefined Behaviour
/// for source and destination to overlap. Care must also be taken with the ownership of
/// `src` and `dst`. This method semantically moves the values of `src` into `dst`.
/// However it does not drop the contents of `dst`, or prevent the contents of `src`
/// from being dropped or used.
///
/// # Examples
///
/// A safe swap function:
///
@ -284,22 +290,22 @@ extern "rust-intrinsic" {
/// }
/// }
/// ```
///
/// # Safety Note
///
/// If the source and destination overlap then the behavior of this
/// function is undefined.
#[unstable]
pub fn copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T, count: uint);
/// Copies data from one location to another.
///
/// Copies `count` elements (not bytes) from `src` to `dst`. The source
/// Copies `count * size_of<T>` bytes from `src` to `dst`. The source
/// and destination may overlap.
///
/// `copy_memory` is semantically equivalent to C's `memmove`.
///
/// # Example
/// # Safety
///
/// Care must be taken with the ownership of `src` and `dst`.
/// This method semantically moves the values of `src` into `dst`.
/// However it does not drop the contents of `dst`, or prevent the contents of `src`
/// from being dropped or used.
///
/// # Examples
///
/// Efficiently create a Rust vector from an unsafe buffer:
///

View File

@ -1386,6 +1386,7 @@ pub struct Map<A, B, I: Iterator<A>, F: FnMut(A) -> B> {
}
// FIXME(#19839) Remove in favor of `#[deriving(Clone)]`
#[stable]
impl<A, B, I, F> Clone for Map<A, B, I, F> where
I: Clone + Iterator<A>,
F: Clone + FnMut(A) -> B,
@ -1460,6 +1461,7 @@ pub struct Filter<A, I, P> where I: Iterator<A>, P: FnMut(&A) -> bool {
}
// FIXME(#19839) Remove in favor of `#[deriving(Clone)]`
#[stable]
impl<A, I, P> Clone for Filter<A, I, P> where
I: Clone + Iterator<A>,
P: Clone + FnMut(&A) -> bool,
@ -1518,6 +1520,7 @@ pub struct FilterMap<A, B, I, F> where I: Iterator<A>, F: FnMut(A) -> Option<B>
}
// FIXME(#19839) Remove in favor of `#[deriving(Clone)]`
#[stable]
impl<A, B, I, F> Clone for FilterMap<A, B, I, F> where
I: Clone + Iterator<A>,
F: Clone + FnMut(A) -> Option<B>,
@ -1693,6 +1696,7 @@ pub struct SkipWhile<A, I, P> where I: Iterator<A>, P: FnMut(&A) -> bool {
}
// FIXME(#19839) Remove in favor of `#[deriving(Clone)]`
#[stable]
impl<A, I, P> Clone for SkipWhile<A, I, P> where
I: Clone + Iterator<A>,
P: Clone + FnMut(&A) -> bool,
@ -1736,6 +1740,7 @@ pub struct TakeWhile<A, I, P> where I: Iterator<A>, P: FnMut(&A) -> bool {
}
// FIXME(#19839) Remove in favor of `#[deriving(Clone)]`
#[stable]
impl<A, I, P> Clone for TakeWhile<A, I, P> where
I: Clone + Iterator<A>,
P: Clone + FnMut(&A) -> bool,
@ -1911,6 +1916,7 @@ pub struct Scan<A, B, I, St, F> where I: Iterator<A>, F: FnMut(&mut St, A) -> Op
}
// FIXME(#19839) Remove in favor of `#[deriving(Clone)]`
#[stable]
impl<A, B, I, St, F> Clone for Scan<A, B, I, St, F> where
I: Clone + Iterator<A>,
St: Clone,
@ -1955,6 +1961,7 @@ pub struct FlatMap<A, B, I, U, F> where I: Iterator<A>, U: Iterator<B>, F: FnMut
}
// FIXME(#19839) Remove in favor of `#[deriving(Clone)]`
#[stable]
impl<A, B, I, U, F> Clone for FlatMap<A, B, I, U, F> where
I: Clone + Iterator<A>,
U: Clone + Iterator<B>,
@ -2115,6 +2122,7 @@ pub struct Inspect<A, I, F> where I: Iterator<A>, F: FnMut(&A) {
}
// FIXME(#19839) Remove in favor of `#[deriving(Clone)]`
#[stable]
impl<A, I, F> Clone for Inspect<A, I, F> where
I: Clone + Iterator<A>,
F: Clone + FnMut(&A),
@ -2222,6 +2230,7 @@ pub struct Unfold<A, St, F> where F: FnMut(&mut St) -> Option<A> {
}
// FIXME(#19839) Remove in favor of `#[deriving(Clone)]`
#[stable]
impl<A, St, F> Clone for Unfold<A, St, F> where
F: Clone + FnMut(&mut St) -> Option<A>,
St: Clone,

View File

@ -91,7 +91,8 @@ pub trait Sync for Sized? {
/// implemented using unsafe code. In that case, you may want to embed
/// some of the marker types below into your type.
pub mod marker {
use super::Copy;
use super::{Copy,Sized};
use clone::Clone;
/// A marker type whose type parameter `T` is considered to be
/// covariant with respect to the type itself. This is (typically)
@ -131,10 +132,13 @@ pub mod marker {
/// (for example, `S<&'static int>` is a subtype of `S<&'a int>`
/// for some lifetime `'a`, but not the other way around).
#[lang="covariant_type"]
#[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct CovariantType<T>;
#[deriving(PartialEq, Eq, PartialOrd, Ord)]
pub struct CovariantType<Sized? T>;
impl<T> Copy for CovariantType<T> {}
impl<Sized? T> Copy for CovariantType<T> {}
impl<Sized? T> Clone for CovariantType<T> {
fn clone(&self) -> CovariantType<T> { *self }
}
/// A marker type whose type parameter `T` is considered to be
/// contravariant with respect to the type itself. This is (typically)
@ -176,10 +180,13 @@ pub mod marker {
/// function requires arguments of type `T`, it must also accept
/// arguments of type `U`, hence such a conversion is safe.
#[lang="contravariant_type"]
#[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct ContravariantType<T>;
#[deriving(PartialEq, Eq, PartialOrd, Ord)]
pub struct ContravariantType<Sized? T>;
impl<T> Copy for ContravariantType<T> {}
impl<Sized? T> Copy for ContravariantType<T> {}
impl<Sized? T> Clone for ContravariantType<T> {
fn clone(&self) -> ContravariantType<T> { *self }
}
/// A marker type whose type parameter `T` is considered to be
/// invariant with respect to the type itself. This is (typically)
@ -203,10 +210,13 @@ pub mod marker {
/// never written, but in fact `Cell` uses unsafe code to achieve
/// interior mutability.
#[lang="invariant_type"]
#[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct InvariantType<T>;
#[deriving(PartialEq, Eq, PartialOrd, Ord)]
pub struct InvariantType<Sized? T>;
impl<T> Copy for InvariantType<T> {}
impl<Sized? T> Copy for InvariantType<T> {}
impl<Sized? T> Clone for InvariantType<T> {
fn clone(&self) -> InvariantType<T> { *self }
}
/// As `CovariantType`, but for lifetime parameters. Using
/// `CovariantLifetime<'a>` indicates that it is ok to substitute
@ -252,11 +262,9 @@ pub mod marker {
/// and this pointer is itself stored in an inherently mutable
/// location (such as a `Cell`).
#[lang="invariant_lifetime"]
#[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)]
#[deriving(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct InvariantLifetime<'a>;
impl<'a> Copy for InvariantLifetime<'a> {}
/// A type which is considered "not sendable", meaning that it cannot
/// be safely sent between tasks, even if it is owned. This is
/// typically embedded in other types, such as `Gc`, to ensure that

View File

@ -107,7 +107,6 @@ pub mod default;
pub mod any;
pub mod atomic;
pub mod bool;
pub mod borrow;
pub mod cell;
pub mod char;
@ -120,15 +119,11 @@ pub mod result;
pub mod simd;
pub mod slice;
pub mod str;
pub mod tuple;
pub mod hash;
// FIXME #15320: primitive documentation needs top-level modules, this
// should be `core::tuple::unit`.
#[path = "tuple/unit.rs"]
pub mod unit;
pub mod fmt;
// note: does not need to be public
mod tuple;
mod array;
#[doc(hidden)]

View File

@ -10,9 +10,8 @@
//! Operations and constants for architecture-sized signed integers (`int` type)
#![unstable]
#![stable]
#![doc(primitive = "int")]
#[cfg(target_word_size = "32")] int_module! { int, 32 }
#[cfg(target_word_size = "64")] int_module! { int, 64 }

View File

@ -24,13 +24,12 @@ pub const BYTES : uint = ($bits / 8);
// FIXME(#11621): Should be deprecated once CTFE is implemented in favour of
// calling the `Bounded::min_value` function.
#[unstable]
#[stable]
pub const MIN: $T = (-1 as $T) << (BITS - 1);
// FIXME(#9837): Compute MIN like this so the high bits that shouldn't exist are 0.
// FIXME(#11621): Should be deprecated once CTFE is implemented in favour of
// calling the `Bounded::max_value` function.
#[unstable]
#[stable]
pub const MAX: $T = !MIN;
) }

View File

@ -10,8 +10,7 @@
//! Operations and constants for architecture-sized unsigned integers (`uint` type)
#![unstable]
#![stable]
#![doc(primitive = "uint")]
uint_module! { uint, int, ::int::BITS }

View File

@ -18,10 +18,9 @@ pub const BITS : uint = $bits;
#[unstable]
pub const BYTES : uint = ($bits / 8);
#[unstable]
#[stable]
pub const MIN: $T = 0 as $T;
#[unstable]
#[stable]
pub const MAX: $T = 0 as $T - 1 as $T;
) }

View File

@ -92,46 +92,6 @@ pub trait Drop {
/// struct Foo;
///
/// impl Add<Foo, Foo> for Foo {
/// fn add(&self, _rhs: &Foo) -> Foo {
/// println!("Adding!");
/// *self
/// }
/// }
///
/// fn main() {
/// Foo + Foo;
/// }
/// ```
// NOTE(stage0): Remove trait after a snapshot
#[cfg(stage0)]
#[lang="add"]
pub trait Add<Sized? RHS,Result> for Sized? {
/// The method for the `+` operator
fn add(&self, rhs: &RHS) -> Result;
}
// NOTE(stage0): Remove macro after a snapshot
#[cfg(stage0)]
macro_rules! add_impl {
($($t:ty)*) => ($(
impl Add<$t, $t> for $t {
#[inline]
fn add(&self, other: &$t) -> $t { (*self) + (*other) }
}
)*)
}
/// The `Add` trait is used to specify the functionality of `+`.
///
/// # Example
///
/// A trivial implementation of `Add`. When `Foo + Foo` happens, it ends up
/// calling `add`, and therefore, `main` prints `Adding!`.
///
/// ```rust
/// struct Foo;
///
/// impl Add<Foo, Foo> for Foo {
/// fn add(self, _rhs: Foo) -> Foo {
/// println!("Adding!");
/// self
@ -142,14 +102,12 @@ macro_rules! add_impl {
/// Foo + Foo;
/// }
/// ```
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
#[lang="add"]
pub trait Add<RHS, Result> {
/// The method for the `+` operator
fn add(self, rhs: RHS) -> Result;
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
macro_rules! add_impl {
($($t:ty)*) => ($(
impl Add<$t, $t> for $t {
@ -173,46 +131,6 @@ add_impl! { uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64 }
/// struct Foo;
///
/// impl Sub<Foo, Foo> for Foo {
/// fn sub(&self, _rhs: &Foo) -> Foo {
/// println!("Subtracting!");
/// *self
/// }
/// }
///
/// fn main() {
/// Foo - Foo;
/// }
/// ```
// NOTE(stage0): Remove trait after a snapshot
#[cfg(stage0)]
#[lang="sub"]
pub trait Sub<Sized? RHS, Result> for Sized? {
/// The method for the `-` operator
fn sub(&self, rhs: &RHS) -> Result;
}
// NOTE(stage0): Remove macro after a snapshot
#[cfg(stage0)]
macro_rules! sub_impl {
($($t:ty)*) => ($(
impl Sub<$t, $t> for $t {
#[inline]
fn sub(&self, other: &$t) -> $t { (*self) - (*other) }
}
)*)
}
/// The `Sub` trait is used to specify the functionality of `-`.
///
/// # Example
///
/// A trivial implementation of `Sub`. When `Foo - Foo` happens, it ends up
/// calling `sub`, and therefore, `main` prints `Subtracting!`.
///
/// ```rust
/// struct Foo;
///
/// impl Sub<Foo, Foo> for Foo {
/// fn sub(self, _rhs: Foo) -> Foo {
/// println!("Subtracting!");
/// self
@ -223,14 +141,12 @@ macro_rules! sub_impl {
/// Foo - Foo;
/// }
/// ```
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
#[lang="sub"]
pub trait Sub<RHS, Result> {
/// The method for the `-` operator
fn sub(self, rhs: RHS) -> Result;
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
macro_rules! sub_impl {
($($t:ty)*) => ($(
impl Sub<$t, $t> for $t {
@ -254,46 +170,6 @@ sub_impl! { uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64 }
/// struct Foo;
///
/// impl Mul<Foo, Foo> for Foo {
/// fn mul(&self, _rhs: &Foo) -> Foo {
/// println!("Multiplying!");
/// *self
/// }
/// }
///
/// fn main() {
/// Foo * Foo;
/// }
/// ```
// NOTE(stage0): Remove trait after a snapshot
#[cfg(stage0)]
#[lang="mul"]
pub trait Mul<Sized? RHS, Result> for Sized? {
/// The method for the `*` operator
fn mul(&self, rhs: &RHS) -> Result;
}
// NOTE(stage0): Remove macro after a snapshot
#[cfg(stage0)]
macro_rules! mul_impl {
($($t:ty)*) => ($(
impl Mul<$t, $t> for $t {
#[inline]
fn mul(&self, other: &$t) -> $t { (*self) * (*other) }
}
)*)
}
/// The `Mul` trait is used to specify the functionality of `*`.
///
/// # Example
///
/// A trivial implementation of `Mul`. When `Foo * Foo` happens, it ends up
/// calling `mul`, and therefore, `main` prints `Multiplying!`.
///
/// ```rust
/// struct Foo;
///
/// impl Mul<Foo, Foo> for Foo {
/// fn mul(self, _rhs: Foo) -> Foo {
/// println!("Multiplying!");
/// self
@ -304,14 +180,12 @@ macro_rules! mul_impl {
/// Foo * Foo;
/// }
/// ```
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
#[lang="mul"]
pub trait Mul<RHS, Result> {
/// The method for the `*` operator
fn mul(self, rhs: RHS) -> Result;
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
macro_rules! mul_impl {
($($t:ty)*) => ($(
impl Mul<$t, $t> for $t {
@ -335,46 +209,6 @@ mul_impl! { uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64 }
/// struct Foo;
///
/// impl Div<Foo, Foo> for Foo {
/// fn div(&self, _rhs: &Foo) -> Foo {
/// println!("Dividing!");
/// *self
/// }
/// }
///
/// fn main() {
/// Foo / Foo;
/// }
/// ```
// NOTE(stage0): Remove trait after a snapshot
#[cfg(stage0)]
#[lang="div"]
pub trait Div<Sized? RHS, Result> for Sized? {
/// The method for the `/` operator
fn div(&self, rhs: &RHS) -> Result;
}
// NOTE(stage0): Remove macro after a snapshot
#[cfg(stage0)]
macro_rules! div_impl {
($($t:ty)*) => ($(
impl Div<$t, $t> for $t {
#[inline]
fn div(&self, other: &$t) -> $t { (*self) / (*other) }
}
)*)
}
/// The `Div` trait is used to specify the functionality of `/`.
///
/// # Example
///
/// A trivial implementation of `Div`. When `Foo / Foo` happens, it ends up
/// calling `div`, and therefore, `main` prints `Dividing!`.
///
/// ```
/// struct Foo;
///
/// impl Div<Foo, Foo> for Foo {
/// fn div(self, _rhs: Foo) -> Foo {
/// println!("Dividing!");
/// self
@ -385,14 +219,12 @@ macro_rules! div_impl {
/// Foo / Foo;
/// }
/// ```
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
#[lang="div"]
pub trait Div<RHS, Result> {
/// The method for the `/` operator
fn div(self, rhs: RHS) -> Result;
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
macro_rules! div_impl {
($($t:ty)*) => ($(
impl Div<$t, $t> for $t {
@ -416,60 +248,6 @@ div_impl! { uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64 }
/// struct Foo;
///
/// impl Rem<Foo, Foo> for Foo {
/// fn rem(&self, _rhs: &Foo) -> Foo {
/// println!("Remainder-ing!");
/// *self
/// }
/// }
///
/// fn main() {
/// Foo % Foo;
/// }
/// ```
// NOTE(stage0): Remove trait after a snapshot
#[cfg(stage0)]
#[lang="rem"]
pub trait Rem<Sized? RHS, Result> for Sized? {
/// The method for the `%` operator
fn rem(&self, rhs: &RHS) -> Result;
}
// NOTE(stage0): Remove macro after a snapshot
#[cfg(stage0)]
macro_rules! rem_impl {
($($t:ty)*) => ($(
impl Rem<$t, $t> for $t {
#[inline]
fn rem(&self, other: &$t) -> $t { (*self) % (*other) }
}
)*)
}
// NOTE(stage0): Remove macro after a snapshot
#[cfg(stage0)]
macro_rules! rem_float_impl {
($t:ty, $fmod:ident) => {
impl Rem<$t, $t> for $t {
#[inline]
fn rem(&self, other: &$t) -> $t {
extern { fn $fmod(a: $t, b: $t) -> $t; }
unsafe { $fmod(*self, *other) }
}
}
}
}
/// The `Rem` trait is used to specify the functionality of `%`.
///
/// # Example
///
/// A trivial implementation of `Rem`. When `Foo % Foo` happens, it ends up
/// calling `rem`, and therefore, `main` prints `Remainder-ing!`.
///
/// ```
/// struct Foo;
///
/// impl Rem<Foo, Foo> for Foo {
/// fn rem(self, _rhs: Foo) -> Foo {
/// println!("Remainder-ing!");
/// self
@ -480,14 +258,12 @@ macro_rules! rem_float_impl {
/// Foo % Foo;
/// }
/// ```
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
#[lang="rem"]
pub trait Rem<RHS, Result> {
/// The method for the `%` operator
fn rem(self, rhs: RHS) -> Result;
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
macro_rules! rem_impl {
($($t:ty)*) => ($(
impl Rem<$t, $t> for $t {
@ -497,7 +273,6 @@ macro_rules! rem_impl {
)*)
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
macro_rules! rem_float_impl {
($t:ty, $fmod:ident) => {
impl Rem<$t, $t> for $t {
@ -721,46 +496,6 @@ not_impl! { bool uint u8 u16 u32 u64 int i8 i16 i32 i64 }
/// struct Foo;
///
/// impl BitAnd<Foo, Foo> for Foo {
/// fn bitand(&self, _rhs: &Foo) -> Foo {
/// println!("Bitwise And-ing!");
/// *self
/// }
/// }
///
/// fn main() {
/// Foo & Foo;
/// }
/// ```
// NOTE(stage0): Remove trait after a snapshot
#[cfg(stage0)]
#[lang="bitand"]
pub trait BitAnd<Sized? RHS, Result> for Sized? {
/// The method for the `&` operator
fn bitand(&self, rhs: &RHS) -> Result;
}
// NOTE(stage0): Remove macro after a snapshot
#[cfg(stage0)]
macro_rules! bitand_impl {
($($t:ty)*) => ($(
impl BitAnd<$t, $t> for $t {
#[inline]
fn bitand(&self, rhs: &$t) -> $t { (*self) & (*rhs) }
}
)*)
}
/// The `BitAnd` trait is used to specify the functionality of `&`.
///
/// # Example
///
/// A trivial implementation of `BitAnd`. When `Foo & Foo` happens, it ends up
/// calling `bitand`, and therefore, `main` prints `Bitwise And-ing!`.
///
/// ```
/// struct Foo;
///
/// impl BitAnd<Foo, Foo> for Foo {
/// fn bitand(self, _rhs: Foo) -> Foo {
/// println!("Bitwise And-ing!");
/// self
@ -771,14 +506,12 @@ macro_rules! bitand_impl {
/// Foo & Foo;
/// }
/// ```
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
#[lang="bitand"]
pub trait BitAnd<RHS, Result> {
/// The method for the `&` operator
fn bitand(self, rhs: RHS) -> Result;
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
macro_rules! bitand_impl {
($($t:ty)*) => ($(
impl BitAnd<$t, $t> for $t {
@ -802,46 +535,6 @@ bitand_impl! { bool uint u8 u16 u32 u64 int i8 i16 i32 i64 }
/// struct Foo;
///
/// impl BitOr<Foo, Foo> for Foo {
/// fn bitor(&self, _rhs: &Foo) -> Foo {
/// println!("Bitwise Or-ing!");
/// *self
/// }
/// }
///
/// fn main() {
/// Foo | Foo;
/// }
/// ```
// NOTE(stage0): Remove trait after a snapshot
#[cfg(stage0)]
#[lang="bitor"]
pub trait BitOr<Sized? RHS, Result> for Sized? {
/// The method for the `|` operator
fn bitor(&self, rhs: &RHS) -> Result;
}
// NOTE(stage0): Remove macro after a snapshot
#[cfg(stage0)]
macro_rules! bitor_impl {
($($t:ty)*) => ($(
impl BitOr<$t,$t> for $t {
#[inline]
fn bitor(&self, rhs: &$t) -> $t { (*self) | (*rhs) }
}
)*)
}
/// The `BitOr` trait is used to specify the functionality of `|`.
///
/// # Example
///
/// A trivial implementation of `BitOr`. When `Foo | Foo` happens, it ends up
/// calling `bitor`, and therefore, `main` prints `Bitwise Or-ing!`.
///
/// ```
/// struct Foo;
///
/// impl BitOr<Foo, Foo> for Foo {
/// fn bitor(self, _rhs: Foo) -> Foo {
/// println!("Bitwise Or-ing!");
/// self
@ -852,14 +545,12 @@ macro_rules! bitor_impl {
/// Foo | Foo;
/// }
/// ```
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
#[lang="bitor"]
pub trait BitOr<RHS, Result> {
/// The method for the `|` operator
fn bitor(self, rhs: RHS) -> Result;
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
macro_rules! bitor_impl {
($($t:ty)*) => ($(
impl BitOr<$t,$t> for $t {
@ -883,46 +574,6 @@ bitor_impl! { bool uint u8 u16 u32 u64 int i8 i16 i32 i64 }
/// struct Foo;
///
/// impl BitXor<Foo, Foo> for Foo {
/// fn bitxor(&self, _rhs: &Foo) -> Foo {
/// println!("Bitwise Xor-ing!");
/// *self
/// }
/// }
///
/// fn main() {
/// Foo ^ Foo;
/// }
/// ```
// NOTE(stage0): Remove trait after a snapshot
#[cfg(stage0)]
#[lang="bitxor"]
pub trait BitXor<Sized? RHS, Result> for Sized? {
/// The method for the `^` operator
fn bitxor(&self, rhs: &RHS) -> Result;
}
// NOTE(stage0): Remove macro after a snapshot
#[cfg(stage0)]
macro_rules! bitxor_impl {
($($t:ty)*) => ($(
impl BitXor<$t, $t> for $t {
#[inline]
fn bitxor(&self, other: &$t) -> $t { (*self) ^ (*other) }
}
)*)
}
/// The `BitXor` trait is used to specify the functionality of `^`.
///
/// # Example
///
/// A trivial implementation of `BitXor`. When `Foo ^ Foo` happens, it ends up
/// calling `bitxor`, and therefore, `main` prints `Bitwise Xor-ing!`.
///
/// ```
/// struct Foo;
///
/// impl BitXor<Foo, Foo> for Foo {
/// fn bitxor(self, _rhs: Foo) -> Foo {
/// println!("Bitwise Xor-ing!");
/// self
@ -933,14 +584,12 @@ macro_rules! bitxor_impl {
/// Foo ^ Foo;
/// }
/// ```
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
#[lang="bitxor"]
pub trait BitXor<RHS, Result> {
/// The method for the `^` operator
fn bitxor(self, rhs: RHS) -> Result;
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
macro_rules! bitxor_impl {
($($t:ty)*) => ($(
impl BitXor<$t, $t> for $t {
@ -964,48 +613,6 @@ bitxor_impl! { bool uint u8 u16 u32 u64 int i8 i16 i32 i64 }
/// struct Foo;
///
/// impl Shl<Foo, Foo> for Foo {
/// fn shl(&self, _rhs: &Foo) -> Foo {
/// println!("Shifting left!");
/// *self
/// }
/// }
///
/// fn main() {
/// Foo << Foo;
/// }
/// ```
// NOTE(stage0): Remove trait after a snapshot
#[cfg(stage0)]
#[lang="shl"]
pub trait Shl<Sized? RHS, Result> for Sized? {
/// The method for the `<<` operator
fn shl(&self, rhs: &RHS) -> Result;
}
// NOTE(stage0): Remove macro after a snapshot
#[cfg(stage0)]
macro_rules! shl_impl {
($($t:ty)*) => ($(
impl Shl<uint, $t> for $t {
#[inline]
fn shl(&self, other: &uint) -> $t {
(*self) << (*other)
}
}
)*)
}
/// The `Shl` trait is used to specify the functionality of `<<`.
///
/// # Example
///
/// A trivial implementation of `Shl`. When `Foo << Foo` happens, it ends up
/// calling `shl`, and therefore, `main` prints `Shifting left!`.
///
/// ```
/// struct Foo;
///
/// impl Shl<Foo, Foo> for Foo {
/// fn shl(self, _rhs: Foo) -> Foo {
/// println!("Shifting left!");
/// self
@ -1016,14 +623,12 @@ macro_rules! shl_impl {
/// Foo << Foo;
/// }
/// ```
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
#[lang="shl"]
pub trait Shl<RHS, Result> {
/// The method for the `<<` operator
fn shl(self, rhs: RHS) -> Result;
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
macro_rules! shl_impl {
($($t:ty)*) => ($(
impl Shl<uint, $t> for $t {
@ -1049,46 +654,6 @@ shl_impl! { uint u8 u16 u32 u64 int i8 i16 i32 i64 }
/// struct Foo;
///
/// impl Shr<Foo, Foo> for Foo {
/// fn shr(&self, _rhs: &Foo) -> Foo {
/// println!("Shifting right!");
/// *self
/// }
/// }
///
/// fn main() {
/// Foo >> Foo;
/// }
/// ```
// NOTE(stage0): Remove trait after a snapshot
#[cfg(stage0)]
#[lang="shr"]
pub trait Shr<Sized? RHS, Result> for Sized? {
/// The method for the `>>` operator
fn shr(&self, rhs: &RHS) -> Result;
}
// NOTE(stage0): Remove macro after a snapshot
#[cfg(stage0)]
macro_rules! shr_impl {
($($t:ty)*) => ($(
impl Shr<uint, $t> for $t {
#[inline]
fn shr(&self, other: &uint) -> $t { (*self) >> (*other) }
}
)*)
}
/// The `Shr` trait is used to specify the functionality of `>>`.
///
/// # Example
///
/// A trivial implementation of `Shr`. When `Foo >> Foo` happens, it ends up
/// calling `shr`, and therefore, `main` prints `Shifting right!`.
///
/// ```
/// struct Foo;
///
/// impl Shr<Foo, Foo> for Foo {
/// fn shr(self, _rhs: Foo) -> Foo {
/// println!("Shifting right!");
/// self
@ -1099,14 +664,12 @@ macro_rules! shr_impl {
/// Foo >> Foo;
/// }
/// ```
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
#[lang="shr"]
pub trait Shr<RHS, Result> {
/// The method for the `>>` operator
fn shr(self, rhs: RHS) -> Result;
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
macro_rules! shr_impl {
($($t:ty)*) => ($(
impl Shr<uint, $t> for $t {

View File

@ -819,6 +819,7 @@ impl<'a, A> DoubleEndedIterator<&'a A> for Iter<'a, A> {
impl<'a, A> ExactSizeIterator<&'a A> for Iter<'a, A> {}
#[stable]
impl<'a, A> Clone for Iter<'a, A> {
fn clone(&self) -> Iter<'a, A> {
Iter { inner: self.inner.clone() }

View File

@ -97,13 +97,20 @@ use cmp::{PartialEq, Eq, Ord, PartialOrd, Equiv};
use cmp::Ordering;
use cmp::Ordering::{Less, Equal, Greater};
pub use intrinsics::copy_memory;
// FIXME #19649: instrinsic docs don't render, so these have no docs :(
#[unstable]
pub use intrinsics::copy_nonoverlapping_memory;
#[unstable]
pub use intrinsics::copy_memory;
#[experimental = "uncertain about naming and semantics"]
pub use intrinsics::set_memory;
/// Create a null pointer.
/// Creates a null raw pointer.
///
/// # Example
/// # Examples
///
/// ```
/// use std::ptr;
@ -115,9 +122,9 @@ pub use intrinsics::set_memory;
#[unstable = "may need a different name after pending changes to pointer types"]
pub fn null<T>() -> *const T { 0 as *const T }
/// Create an unsafe mutable null pointer.
/// Creates a null mutable raw pointer.
///
/// # Example
/// # Examples
///
/// ```
/// use std::ptr;
@ -129,7 +136,12 @@ pub fn null<T>() -> *const T { 0 as *const T }
#[unstable = "may need a different name after pending changes to pointer types"]
pub fn null_mut<T>() -> *mut T { 0 as *mut T }
/// Zeroes out `count * size_of::<T>` bytes of memory at `dst`
/// Zeroes out `count * size_of::<T>` bytes of memory at `dst`. `count` may be `0`.
///
/// # Safety
///
/// Beyond accepting a raw pointer, this is unsafe because it will not drop the contents of `dst`,
/// and may be used to create invalid instances of `T`.
#[inline]
#[experimental = "uncertain about naming and semantics"]
#[allow(experimental)]
@ -137,8 +149,13 @@ pub unsafe fn zero_memory<T>(dst: *mut T, count: uint) {
set_memory(dst, 0, count);
}
/// Swap the values at two mutable locations of the same type, without
/// deinitialising either. They may overlap.
/// Swaps the values at two mutable locations of the same type, without
/// deinitialising either. They may overlap, unlike `mem::swap` which is otherwise
/// equivalent.
///
/// # Safety
///
/// This is only unsafe because it accepts a raw pointer.
#[inline]
#[unstable]
pub unsafe fn swap<T>(x: *mut T, y: *mut T) {
@ -156,8 +173,13 @@ pub unsafe fn swap<T>(x: *mut T, y: *mut T) {
mem::forget(tmp);
}
/// Replace the value at a mutable location with a new one, returning the old
/// value, without deinitialising either.
/// Replaces the value at `dest` with `src`, returning the old
/// value, without dropping either.
///
/// # Safety
///
/// This is only unsafe because it accepts a raw pointer.
/// Otherwise, this operation is identical to `mem::replace`.
#[inline]
#[unstable]
pub unsafe fn replace<T>(dest: *mut T, mut src: T) -> T {
@ -165,7 +187,17 @@ pub unsafe fn replace<T>(dest: *mut T, mut src: T) -> T {
src
}
/// Reads the value from `*src` and returns it.
/// Reads the value from `src` without dropping it. This leaves the
/// memory in `src` unchanged.
///
/// # Safety
///
/// Beyond accepting a raw pointer, this is unsafe because it semantically
/// moves the value out of `src` without preventing further usage of `src`.
/// If `T` is not `Copy`, then care must be taken to ensure that the value at
/// `src` is not used before the data is overwritten again (e.g. with `write`,
/// `zero_memory`, or `copy_memory`). Note that `*src = foo` counts as a use
/// because it will attempt to drop the value previously at `*src`.
#[inline(always)]
#[unstable]
pub unsafe fn read<T>(src: *const T) -> T {
@ -174,8 +206,11 @@ pub unsafe fn read<T>(src: *const T) -> T {
tmp
}
/// Reads the value from `*src` and nulls it out.
/// This currently prevents destructors from executing.
/// Reads the value from `src` and nulls it out without dropping it.
///
/// # Safety
///
/// This is unsafe for the same reasons that `read` is unsafe.
#[inline(always)]
#[experimental]
#[allow(experimental)]
@ -189,12 +224,17 @@ pub unsafe fn read_and_zero<T>(dest: *mut T) -> T {
tmp
}
/// Unsafely overwrite a memory location with the given value without destroying
/// Overwrites a memory location with the given value without reading or dropping
/// the old value.
///
/// This operation is unsafe because it does not destroy the previous value
/// contained at the location `dst`. This could leak allocations or resources,
/// so care must be taken to previously deallocate the value at `dst`.
/// # Safety
///
/// Beyond accepting a raw pointer, this operation is unsafe because it does
/// not drop the contents of `dst`. This could leak allocations or resources,
/// so care must be taken not to overwrite an object that should be dropped.
///
/// This is appropriate for initializing uninitialized memory, or overwritting memory
/// that has previously been `read` from.
#[inline]
#[unstable]
pub unsafe fn write<T>(dst: *mut T, src: T) {
@ -203,39 +243,47 @@ pub unsafe fn write<T>(dst: *mut T, src: T) {
/// Methods on raw pointers
pub trait RawPtr<T> {
/// Returns the null pointer.
/// Returns a null raw pointer.
fn null() -> Self;
/// Returns true if the pointer is equal to the null pointer.
/// Returns true if the pointer is null.
fn is_null(&self) -> bool;
/// Returns true if the pointer is not equal to the null pointer.
/// Returns true if the pointer is not null.
fn is_not_null(&self) -> bool { !self.is_null() }
/// Returns the value of this pointer (ie, the address it points to)
/// Returns the address of the pointer.
fn to_uint(&self) -> uint;
/// Returns `None` if the pointer is null, or else returns a reference to the
/// value wrapped in `Some`.
///
/// # Safety Notes
/// # Safety
///
/// While this method and its mutable counterpart are useful for null-safety,
/// it is important to note that this is still an unsafe operation because
/// the returned value could be pointing to invalid memory.
unsafe fn as_ref<'a>(&self) -> Option<&'a T>;
/// Calculates the offset from a pointer. The offset *must* be in-bounds of
/// the object, or one-byte-past-the-end. `count` is in units of T; e.g. a
/// Calculates the offset from a pointer. `count` is in units of T; e.g. a
/// `count` of 3 represents a pointer offset of `3 * sizeof::<T>()` bytes.
///
/// # Safety
///
/// The offset must be in-bounds of the object, or one-byte-past-the-end. Otherwise
/// `offset` invokes Undefined Behaviour, regardless of whether the pointer is used.
unsafe fn offset(self, count: int) -> Self;
}
/// Methods on mutable raw pointers
pub trait RawMutPtr<T>{
/// Returns `None` if the pointer is null, or else returns a mutable reference
/// to the value wrapped in `Some`. As with `as_ref`, this is unsafe because
/// it cannot verify the validity of the returned pointer.
/// to the value wrapped in `Some`.
///
/// # Safety
///
/// As with `as_ref`, this is unsafe because it cannot verify the validity
/// of the returned pointer.
unsafe fn as_mut<'a>(&self) -> Option<&'a mut T>;
}
@ -340,6 +388,7 @@ impl<T> Equiv<*const T> for *mut T {
}
}
#[stable]
impl<T> Clone for *const T {
#[inline]
fn clone(&self) -> *const T {
@ -347,6 +396,7 @@ impl<T> Clone for *const T {
}
}
#[stable]
impl<T> Clone for *mut T {
#[inline]
fn clone(&self) -> *mut T {
@ -451,4 +501,3 @@ impl<T> PartialOrd for *mut T {
#[inline]
fn ge(&self, other: &*mut T) -> bool { *self >= *other }
}

View File

@ -781,7 +781,7 @@ iterator!{struct Items -> *const T, &'a T}
#[experimental = "needs review"]
impl<'a, T> ExactSizeIterator<&'a T> for Items<'a, T> {}
#[experimental = "needs review"]
#[stable]
impl<'a, T> Clone for Items<'a, T> {
fn clone(&self) -> Items<'a, T> { *self }
}
@ -893,6 +893,7 @@ pub struct Splits<'a, T:'a, P> where P: FnMut(&T) -> bool {
}
// FIXME(#19839) Remove in favor of `#[deriving(Clone)]`
#[stable]
impl<'a, T, P> Clone for Splits<'a, T, P> where P: Clone + FnMut(&T) -> bool {
fn clone(&self) -> Splits<'a, T, P> {
Splits {
@ -1550,4 +1551,3 @@ impl_int_slice! { u16, i16 }
impl_int_slice! { u32, i32 }
impl_int_slice! { u64, i64 }
impl_int_slice! { uint, int }

View File

@ -62,12 +62,10 @@
//! assert_eq!(d, (0u32, 0.0f32));
//! ```
#![doc(primitive = "tuple")]
#![stable]
#[unstable = "this is just a documentation module and should not be part \
of the public api"]
pub use unit;
use clone::Clone;
use cmp::*;
@ -126,7 +124,7 @@ macro_rules! tuple_impls {
)+
}
#[unstable = "waiting for Clone to stabilize"]
#[stable]
impl<$($T:Clone),+> Clone for ($($T,)+) {
fn clone(&self) -> ($($T,)+) {
($(e!(self.$idx.clone()),)+)
@ -328,4 +326,3 @@ tuple_impls! {
(val11, ref11, mut11, 11) -> L
}
}

View File

@ -37,7 +37,7 @@ use util::nodemap::{FnvHashMap, NodeSet};
use lint::{Context, LintPass, LintArray};
use std::{cmp, slice};
use std::collections::hash_map::{Occupied, Vacant};
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::num::SignedInt;
use std::{i8, i16, i32, i64, u8, u16, u32, u64, f32, f64};
use syntax::{abi, ast, ast_map};
@ -1157,9 +1157,9 @@ impl LintPass for UnusedParens {
ast::ExprIf(ref cond, _, _) => (cond, "`if` condition", true),
ast::ExprWhile(ref cond, _, _) => (cond, "`while` condition", true),
ast::ExprMatch(ref head, _, source) => match source {
ast::MatchNormal => (head, "`match` head expression", true),
ast::MatchIfLetDesugar => (head, "`if let` head expression", true),
ast::MatchWhileLetDesugar => (head, "`while let` head expression", true),
ast::MatchSource::Normal => (head, "`match` head expression", true),
ast::MatchSource::IfLetDesugar { .. } => (head, "`if let` head expression", true),
ast::MatchSource::WhileLetDesugar => (head, "`while let` head expression", true),
},
ast::ExprRet(Some(ref value)) => (value, "`return` value", false),
ast::ExprAssign(_, ref value) => (value, "assigned value", false),

View File

@ -23,7 +23,7 @@ use plugin::load::PluginMetadata;
use util::nodemap::FnvHashMap;
use std::rc::Rc;
use std::collections::hash_map::{Occupied, Vacant};
use std::collections::hash_map::Entry::{Occupied, Vacant};
use syntax::ast;
use syntax::abi;
use syntax::attr;

View File

@ -1478,6 +1478,9 @@ fn encode_info_for_foreign_item(ecx: &EncodeContext,
if abi == abi::RustIntrinsic {
encode_inlined_item(ecx, rbml_w, IIForeignRef(nitem));
}
encode_attributes(rbml_w, &*nitem.attrs);
let stab = stability::lookup(ecx.tcx, ast_util::local_def(nitem.id));
encode_stability(rbml_w, stab);
encode_symbol(ecx, rbml_w, nitem.id);
}
ast::ForeignItemStatic(_, mutbl) => {
@ -1488,6 +1491,9 @@ fn encode_info_for_foreign_item(ecx: &EncodeContext,
}
encode_bounds_and_type(rbml_w, ecx,
&lookup_item_type(ecx.tcx,local_def(nitem.id)));
encode_attributes(rbml_w, &*nitem.attrs);
let stab = stability::lookup(ecx.tcx, ast_util::local_def(nitem.id));
encode_stability(rbml_w, stab);
encode_symbol(ecx, rbml_w, nitem.id);
encode_name(rbml_w, nitem.ident.name);
}

View File

@ -228,7 +228,7 @@ use util::fs;
use std::c_str::ToCStr;
use std::cmp;
use std::collections::hash_map::{Occupied, Vacant};
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::collections::{HashMap, HashSet};
use std::io::fs::PathExtensions;
use std::io;

View File

@ -55,7 +55,103 @@ pub fn enc_ty<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>, t: Ty<'t
None => {}
}
let pos = w.tell().unwrap();
enc_sty(w, cx, &t.sty);
match t.sty {
ty::ty_bool => mywrite!(w, "b"),
ty::ty_char => mywrite!(w, "c"),
ty::ty_int(t) => {
match t {
ast::TyI => mywrite!(w, "i"),
ast::TyI8 => mywrite!(w, "MB"),
ast::TyI16 => mywrite!(w, "MW"),
ast::TyI32 => mywrite!(w, "ML"),
ast::TyI64 => mywrite!(w, "MD")
}
}
ty::ty_uint(t) => {
match t {
ast::TyU => mywrite!(w, "u"),
ast::TyU8 => mywrite!(w, "Mb"),
ast::TyU16 => mywrite!(w, "Mw"),
ast::TyU32 => mywrite!(w, "Ml"),
ast::TyU64 => mywrite!(w, "Md")
}
}
ty::ty_float(t) => {
match t {
ast::TyF32 => mywrite!(w, "Mf"),
ast::TyF64 => mywrite!(w, "MF"),
}
}
ty::ty_enum(def, ref substs) => {
mywrite!(w, "t[{}|", (cx.ds)(def));
enc_substs(w, cx, substs);
mywrite!(w, "]");
}
ty::ty_trait(box ty::TyTrait { ref principal,
ref bounds }) => {
mywrite!(w, "x[");
enc_trait_ref(w, cx, &principal.0);
enc_existential_bounds(w, cx, bounds);
mywrite!(w, "]");
}
ty::ty_tup(ref ts) => {
mywrite!(w, "T[");
for t in ts.iter() { enc_ty(w, cx, *t); }
mywrite!(w, "]");
}
ty::ty_uniq(typ) => { mywrite!(w, "~"); enc_ty(w, cx, typ); }
ty::ty_ptr(mt) => { mywrite!(w, "*"); enc_mt(w, cx, mt); }
ty::ty_rptr(r, mt) => {
mywrite!(w, "&");
enc_region(w, cx, r);
enc_mt(w, cx, mt);
}
ty::ty_vec(t, sz) => {
mywrite!(w, "V");
enc_ty(w, cx, t);
mywrite!(w, "/");
match sz {
Some(n) => mywrite!(w, "{}|", n),
None => mywrite!(w, "|"),
}
}
ty::ty_str => {
mywrite!(w, "v");
}
ty::ty_closure(ref f) => {
mywrite!(w, "f");
enc_closure_ty(w, cx, &**f);
}
ty::ty_bare_fn(ref f) => {
mywrite!(w, "F");
enc_bare_fn_ty(w, cx, f);
}
ty::ty_infer(_) => {
cx.diag.handler().bug("cannot encode inference variable types");
}
ty::ty_param(ParamTy {space, idx: id, def_id: did}) => {
mywrite!(w, "p{}|{}|{}|", (cx.ds)(did), id, space.to_uint())
}
ty::ty_struct(def, ref substs) => {
mywrite!(w, "a[{}|", (cx.ds)(def));
enc_substs(w, cx, substs);
mywrite!(w, "]");
}
ty::ty_unboxed_closure(def, region, ref substs) => {
mywrite!(w, "k[{}|", (cx.ds)(def));
enc_region(w, cx, region);
enc_substs(w, cx, substs);
mywrite!(w, "]");
}
ty::ty_err => {
mywrite!(w, "e");
}
ty::ty_open(_) => {
cx.diag.handler().bug("unexpected type in enc_sty (ty_open)");
}
}
let end = w.tell().unwrap();
let len = end - pos;
fn estimate_sz(u: u64) -> u64 {
@ -214,105 +310,6 @@ pub fn enc_trait_store(w: &mut SeekableMemWriter, cx: &ctxt, s: ty::TraitStore)
}
}
fn enc_sty<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>,
st: &ty::sty<'tcx>) {
match *st {
ty::ty_bool => mywrite!(w, "b"),
ty::ty_char => mywrite!(w, "c"),
ty::ty_int(t) => {
match t {
ast::TyI => mywrite!(w, "i"),
ast::TyI8 => mywrite!(w, "MB"),
ast::TyI16 => mywrite!(w, "MW"),
ast::TyI32 => mywrite!(w, "ML"),
ast::TyI64 => mywrite!(w, "MD")
}
}
ty::ty_uint(t) => {
match t {
ast::TyU => mywrite!(w, "u"),
ast::TyU8 => mywrite!(w, "Mb"),
ast::TyU16 => mywrite!(w, "Mw"),
ast::TyU32 => mywrite!(w, "Ml"),
ast::TyU64 => mywrite!(w, "Md")
}
}
ty::ty_float(t) => {
match t {
ast::TyF32 => mywrite!(w, "Mf"),
ast::TyF64 => mywrite!(w, "MF"),
}
}
ty::ty_enum(def, ref substs) => {
mywrite!(w, "t[{}|", (cx.ds)(def));
enc_substs(w, cx, substs);
mywrite!(w, "]");
}
ty::ty_trait(box ty::TyTrait { ref principal,
ref bounds }) => {
mywrite!(w, "x[");
enc_trait_ref(w, cx, &principal.0);
enc_existential_bounds(w, cx, bounds);
mywrite!(w, "]");
}
ty::ty_tup(ref ts) => {
mywrite!(w, "T[");
for t in ts.iter() { enc_ty(w, cx, *t); }
mywrite!(w, "]");
}
ty::ty_uniq(typ) => { mywrite!(w, "~"); enc_ty(w, cx, typ); }
ty::ty_ptr(mt) => { mywrite!(w, "*"); enc_mt(w, cx, mt); }
ty::ty_rptr(r, mt) => {
mywrite!(w, "&");
enc_region(w, cx, r);
enc_mt(w, cx, mt);
}
ty::ty_vec(t, sz) => {
mywrite!(w, "V");
enc_ty(w, cx, t);
mywrite!(w, "/");
match sz {
Some(n) => mywrite!(w, "{}|", n),
None => mywrite!(w, "|"),
}
}
ty::ty_str => {
mywrite!(w, "v");
}
ty::ty_closure(ref f) => {
mywrite!(w, "f");
enc_closure_ty(w, cx, &**f);
}
ty::ty_bare_fn(ref f) => {
mywrite!(w, "F");
enc_bare_fn_ty(w, cx, f);
}
ty::ty_infer(_) => {
cx.diag.handler().bug("cannot encode inference variable types");
}
ty::ty_param(ParamTy {space, idx: id, def_id: did}) => {
mywrite!(w, "p{}|{}|{}|", (cx.ds)(did), id, space.to_uint())
}
ty::ty_struct(def, ref substs) => {
mywrite!(w, "a[{}|", (cx.ds)(def));
enc_substs(w, cx, substs);
mywrite!(w, "]");
}
ty::ty_unboxed_closure(def, region, ref substs) => {
mywrite!(w, "k[{}|", (cx.ds)(def));
enc_region(w, cx, region);
enc_substs(w, cx, substs);
mywrite!(w, "]");
}
ty::ty_err => {
mywrite!(w, "e");
}
ty::ty_open(_) => {
cx.diag.handler().bug("unexpected type in enc_sty (ty_open)");
}
}
}
fn enc_unsafety(w: &mut SeekableMemWriter, p: ast::Unsafety) {
match p {
ast::Unsafety::Normal => mywrite!(w, "n"),

View File

@ -48,4 +48,8 @@ impl CFG {
blk: &ast::Block) -> CFG {
construct::construct(tcx, blk)
}
pub fn node_is_reachable(&self, id: ast::NodeId) -> bool {
self.graph.depth_traverse(self.entry).any(|node| node.id == id)
}
}

View File

@ -307,7 +307,7 @@ fn check_arms(cx: &MatchCheckCtxt,
match is_useful(cx, &seen, v.as_slice(), LeaveOutWitness) {
NotUseful => {
match source {
ast::MatchIfLetDesugar => {
ast::MatchSource::IfLetDesugar { .. } => {
if printed_if_let_err {
// we already printed an irrefutable if-let pattern error.
// We don't want two, that's just confusing.
@ -321,7 +321,7 @@ fn check_arms(cx: &MatchCheckCtxt,
}
},
ast::MatchWhileLetDesugar => {
ast::MatchSource::WhileLetDesugar => {
// find the first arm pattern so we can use its span
let &(ref first_arm_pats, _) = &arms[0];
let first_pat = &first_arm_pats[0];
@ -329,7 +329,7 @@ fn check_arms(cx: &MatchCheckCtxt,
span_err!(cx.tcx.sess, span, E0165, "irrefutable while-let pattern");
},
ast::MatchNormal => {
ast::MatchSource::Normal => {
span_err!(cx.tcx.sess, pat.span, E0001, "unreachable pattern")
},
}

View File

@ -28,7 +28,7 @@ use syntax::visit::{mod, Visitor};
use syntax::{ast_map, ast_util, codemap};
use std::rc::Rc;
use std::collections::hash_map::Vacant;
use std::collections::hash_map::Entry::Vacant;
//
// This pass classifies expressions by their constant-ness.

View File

@ -34,6 +34,7 @@
use std::fmt::{Formatter, Error, Show};
use std::uint;
use std::collections::BitvSet;
pub struct Graph<N,E> {
nodes: Vec<Node<N>> ,
@ -288,6 +289,40 @@ impl<N,E> Graph<N,E> {
}
}
}
pub fn depth_traverse<'a>(&'a self, start: NodeIndex) -> DepthFirstTraversal<'a, N, E> {
DepthFirstTraversal {
graph: self,
stack: vec![start],
visited: BitvSet::new()
}
}
}
pub struct DepthFirstTraversal<'g, N:'g, E:'g> {
graph: &'g Graph<N, E>,
stack: Vec<NodeIndex>,
visited: BitvSet
}
impl<'g, N, E> Iterator<&'g N> for DepthFirstTraversal<'g, N, E> {
fn next(&mut self) -> Option<&'g N> {
while let Some(idx) = self.stack.pop() {
if !self.visited.insert(idx.node_id()) {
continue;
}
self.graph.each_outgoing_edge(idx, |_, e| -> bool {
if !self.visited.contains(&e.target().node_id()) {
self.stack.push(e.target());
}
true
});
return Some(self.graph.node_data(idx));
}
return None;
}
}
pub fn each_edge_index<F>(max_edge_index: EdgeIndex, mut f: F) where

View File

@ -90,8 +90,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
b.repr(self.get_ref().infcx.tcx));
// Consider coercing the subtype to a DST
let unsize = self.unpack_actual_value(a, |sty_a| {
self.coerce_unsized(a, sty_a, b)
let unsize = self.unpack_actual_value(a, |a| {
self.coerce_unsized(a, b)
});
if unsize.is_ok() {
return unsize;
@ -105,14 +105,14 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
ty::ty_ptr(mt_b) => {
match mt_b.ty.sty {
ty::ty_str => {
return self.unpack_actual_value(a, |sty_a| {
self.coerce_unsafe_ptr(a, sty_a, b, ast::MutImmutable)
return self.unpack_actual_value(a, |a| {
self.coerce_unsafe_ptr(a, b, ast::MutImmutable)
});
}
ty::ty_trait(..) => {
let result = self.unpack_actual_value(a, |sty_a| {
self.coerce_unsafe_object(a, sty_a, b, mt_b.mutbl)
let result = self.unpack_actual_value(a, |a| {
self.coerce_unsafe_object(a, b, mt_b.mutbl)
});
match result {
@ -122,8 +122,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
}
_ => {
return self.unpack_actual_value(a, |sty_a| {
self.coerce_unsafe_ptr(a, sty_a, b, mt_b.mutbl)
return self.unpack_actual_value(a, |a| {
self.coerce_unsafe_ptr(a, b, mt_b.mutbl)
});
}
};
@ -132,14 +132,14 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
ty::ty_rptr(_, mt_b) => {
match mt_b.ty.sty {
ty::ty_str => {
return self.unpack_actual_value(a, |sty_a| {
self.coerce_borrowed_pointer(a, sty_a, b, ast::MutImmutable)
return self.unpack_actual_value(a, |a| {
self.coerce_borrowed_pointer(a, b, ast::MutImmutable)
});
}
ty::ty_trait(..) => {
let result = self.unpack_actual_value(a, |sty_a| {
self.coerce_borrowed_object(a, sty_a, b, mt_b.mutbl)
let result = self.unpack_actual_value(a, |a| {
self.coerce_borrowed_object(a, b, mt_b.mutbl)
});
match result {
@ -149,8 +149,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
}
_ => {
return self.unpack_actual_value(a, |sty_a| {
self.coerce_borrowed_pointer(a, sty_a, b, mt_b.mutbl)
return self.unpack_actual_value(a, |a| {
self.coerce_borrowed_pointer(a, b, mt_b.mutbl)
});
}
};
@ -160,16 +160,16 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
store: ty::RegionTraitStore(..),
..
}) => {
return self.unpack_actual_value(a, |sty_a| {
self.coerce_borrowed_fn(a, sty_a, b)
return self.unpack_actual_value(a, |a| {
self.coerce_borrowed_fn(a, b)
});
}
_ => {}
}
self.unpack_actual_value(a, |sty_a| {
match *sty_a {
self.unpack_actual_value(a, |a| {
match a.sty {
ty::ty_bare_fn(ref a_f) => {
// Bare functions are coercible to any closure type.
//
@ -194,20 +194,19 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
}
pub fn unpack_actual_value<T, F>(&self, a: Ty<'tcx>, f: F) -> T where
F: FnOnce(&ty::sty<'tcx>) -> T,
F: FnOnce(Ty<'tcx>) -> T,
{
f(&self.get_ref().infcx.shallow_resolve(a).sty)
f(self.get_ref().infcx.shallow_resolve(a))
}
// ~T -> &T or &mut T -> &T (including where T = [U] or str)
pub fn coerce_borrowed_pointer(&self,
a: Ty<'tcx>,
sty_a: &ty::sty<'tcx>,
b: Ty<'tcx>,
mutbl_b: ast::Mutability)
-> CoerceResult<'tcx> {
debug!("coerce_borrowed_pointer(a={}, sty_a={}, b={})",
a.repr(self.get_ref().infcx.tcx), sty_a,
debug!("coerce_borrowed_pointer(a={}, b={})",
a.repr(self.get_ref().infcx.tcx),
b.repr(self.get_ref().infcx.tcx));
// If we have a parameter of type `&M T_a` and the value
@ -220,7 +219,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
let coercion = Coercion(self.get_ref().trace.clone());
let r_borrow = self.get_ref().infcx.next_region_var(coercion);
let inner_ty = match *sty_a {
let inner_ty = match a.sty {
ty::ty_uniq(_) => return Err(ty::terr_mismatch),
ty::ty_rptr(_, mt_a) => mt_a.ty,
_ => {
@ -245,11 +244,10 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
// or &Concrete -> &Trait, etc.
fn coerce_unsized(&self,
a: Ty<'tcx>,
sty_a: &ty::sty<'tcx>,
b: Ty<'tcx>)
-> CoerceResult<'tcx> {
debug!("coerce_unsized(a={}, sty_a={}, b={})",
a.repr(self.get_ref().infcx.tcx), sty_a,
debug!("coerce_unsized(a={}, b={})",
a.repr(self.get_ref().infcx.tcx),
b.repr(self.get_ref().infcx.tcx));
// Note, we want to avoid unnecessary unsizing. We don't want to coerce to
@ -259,11 +257,10 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
let sub = Sub(self.get_ref().clone());
let sty_b = &b.sty;
match (sty_a, sty_b) {
match (&a.sty, &b.sty) {
(&ty::ty_rptr(_, ty::mt{ty: t_a, mutbl: mutbl_a}), &ty::ty_rptr(_, mt_b)) => {
self.unpack_actual_value(t_a, |sty_a| {
match self.unsize_ty(t_a, sty_a, mt_b.ty) {
self.unpack_actual_value(t_a, |a| {
match self.unsize_ty(t_a, a, mt_b.ty) {
Some((ty, kind)) => {
if !can_coerce_mutbls(mutbl_a, mt_b.mutbl) {
return Err(ty::terr_mutability);
@ -288,8 +285,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
})
}
(&ty::ty_rptr(_, ty::mt{ty: t_a, mutbl: mutbl_a}), &ty::ty_ptr(mt_b)) => {
self.unpack_actual_value(t_a, |sty_a| {
match self.unsize_ty(t_a, sty_a, mt_b.ty) {
self.unpack_actual_value(t_a, |a| {
match self.unsize_ty(t_a, a, mt_b.ty) {
Some((ty, kind)) => {
if !can_coerce_mutbls(mutbl_a, mt_b.mutbl) {
return Err(ty::terr_mutability);
@ -311,8 +308,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
})
}
(&ty::ty_uniq(t_a), &ty::ty_uniq(t_b)) => {
self.unpack_actual_value(t_a, |sty_a| {
match self.unsize_ty(t_a, sty_a, t_b) {
self.unpack_actual_value(t_a, |a| {
match self.unsize_ty(t_a, a, t_b) {
Some((ty, kind)) => {
let ty = ty::mk_uniq(self.get_ref().infcx.tcx, ty);
try!(self.get_ref().infcx.try(|_| sub.tys(ty, b)));
@ -336,15 +333,15 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
// E.g., `[T, ..n]` -> `([T], UnsizeLength(n))`
fn unsize_ty(&self,
ty_a: Ty<'tcx>,
sty_a: &ty::sty<'tcx>,
a: Ty<'tcx>,
ty_b: Ty<'tcx>)
-> Option<(Ty<'tcx>, ty::UnsizeKind<'tcx>)> {
debug!("unsize_ty(sty_a={}, ty_b={})", sty_a, ty_b.repr(self.get_ref().infcx.tcx));
debug!("unsize_ty(a={}, ty_b={})", a, ty_b.repr(self.get_ref().infcx.tcx));
let tcx = self.get_ref().infcx.tcx;
self.unpack_actual_value(ty_b, |sty_b|
match (sty_a, sty_b) {
self.unpack_actual_value(ty_b, |b|
match (&a.sty, &b.sty) {
(&ty::ty_vec(t_a, Some(len)), &ty::ty_vec(_, None)) => {
let ty = ty::mk_vec(tcx, t_a, None);
Some((ty, ty::UnsizeLength(len)))
@ -412,44 +409,41 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
fn coerce_borrowed_object(&self,
a: Ty<'tcx>,
sty_a: &ty::sty<'tcx>,
b: Ty<'tcx>,
b_mutbl: ast::Mutability) -> CoerceResult<'tcx>
{
let tcx = self.get_ref().infcx.tcx;
debug!("coerce_borrowed_object(a={}, sty_a={}, b={}, b_mutbl={})",
a.repr(tcx), sty_a,
debug!("coerce_borrowed_object(a={}, b={}, b_mutbl={})",
a.repr(tcx),
b.repr(tcx), b_mutbl);
let coercion = Coercion(self.get_ref().trace.clone());
let r_a = self.get_ref().infcx.next_region_var(coercion);
self.coerce_object(a, sty_a, b, b_mutbl,
self.coerce_object(a, b, b_mutbl,
|tr| ty::mk_rptr(tcx, r_a, ty::mt{ mutbl: b_mutbl, ty: tr }),
|| AutoPtr(r_a, b_mutbl, None))
}
fn coerce_unsafe_object(&self,
a: Ty<'tcx>,
sty_a: &ty::sty<'tcx>,
b: Ty<'tcx>,
b_mutbl: ast::Mutability) -> CoerceResult<'tcx>
{
let tcx = self.get_ref().infcx.tcx;
debug!("coerce_unsafe_object(a={}, sty_a={}, b={}, b_mutbl={})",
a.repr(tcx), sty_a,
debug!("coerce_unsafe_object(a={}, b={}, b_mutbl={})",
a.repr(tcx),
b.repr(tcx), b_mutbl);
self.coerce_object(a, sty_a, b, b_mutbl,
self.coerce_object(a, b, b_mutbl,
|tr| ty::mk_ptr(tcx, ty::mt{ mutbl: b_mutbl, ty: tr }),
|| AutoUnsafe(b_mutbl, None))
}
fn coerce_object<F, G>(&self,
a: Ty<'tcx>,
sty_a: &ty::sty<'tcx>,
b: Ty<'tcx>,
b_mutbl: ast::Mutability,
mk_ty: F,
@ -459,7 +453,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
{
let tcx = self.get_ref().infcx.tcx;
match *sty_a {
match a.sty {
ty::ty_rptr(_, ty::mt{ty, mutbl}) => match ty.sty {
ty::ty_trait(box ty::TyTrait { ref principal, bounds }) => {
debug!("mutbl={} b_mutbl={}", mutbl, b_mutbl);
@ -483,14 +477,13 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
pub fn coerce_borrowed_fn(&self,
a: Ty<'tcx>,
sty_a: &ty::sty<'tcx>,
b: Ty<'tcx>)
-> CoerceResult<'tcx> {
debug!("coerce_borrowed_fn(a={}, sty_a={}, b={})",
a.repr(self.get_ref().infcx.tcx), sty_a,
debug!("coerce_borrowed_fn(a={}, b={})",
a.repr(self.get_ref().infcx.tcx),
b.repr(self.get_ref().infcx.tcx));
match *sty_a {
match a.sty {
ty::ty_bare_fn(ref f) => {
self.coerce_from_bare_fn(a, f, b)
}
@ -504,7 +497,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
/// `proc`.
fn coerce_from_bare_fn(&self, a: Ty<'tcx>, fn_ty_a: &ty::BareFnTy<'tcx>, b: Ty<'tcx>)
-> CoerceResult<'tcx> {
self.unpack_actual_value(b, |sty_b| {
self.unpack_actual_value(b, |b| {
debug!("coerce_from_bare_fn(a={}, b={})",
a.repr(self.get_ref().infcx.tcx), b.repr(self.get_ref().infcx.tcx));
@ -513,7 +506,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
return self.subtype(a, b);
}
let fn_ty_b = match *sty_b {
let fn_ty_b = match b.sty {
ty::ty_closure(ref f) => (*f).clone(),
_ => return self.subtype(a, b)
};
@ -531,15 +524,14 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
pub fn coerce_unsafe_ptr(&self,
a: Ty<'tcx>,
sty_a: &ty::sty<'tcx>,
b: Ty<'tcx>,
mutbl_b: ast::Mutability)
-> CoerceResult<'tcx> {
debug!("coerce_unsafe_ptr(a={}, sty_a={}, b={})",
a.repr(self.get_ref().infcx.tcx), sty_a,
debug!("coerce_unsafe_ptr(a={}, b={})",
a.repr(self.get_ref().infcx.tcx),
b.repr(self.get_ref().infcx.tcx));
let mt_a = match *sty_a {
let mt_a = match a.sty {
ty::ty_rptr(_, mt) | ty::ty_ptr(mt) => mt,
_ => {
return self.subtype(a, b);

View File

@ -34,7 +34,7 @@ use middle::ty::{mod, Ty};
use middle::ty_fold;
use middle::ty_fold::TypeFoldable;
use middle::ty_fold::TypeFolder;
use std::collections::hash_map;
use std::collections::hash_map::{mod, Entry};
use super::InferCtxt;
use super::unify::InferCtxtMethodsForSimplyUnifiableTypes;
@ -67,8 +67,8 @@ impl<'a, 'tcx> TypeFreshener<'a, 'tcx> {
}
match self.freshen_map.entry(key) {
hash_map::Occupied(entry) => *entry.get(),
hash_map::Vacant(entry) => {
Entry::Occupied(entry) => *entry.get(),
Entry::Vacant(entry) => {
let index = self.freshen_count;
self.freshen_count += 1;
let t = ty::mk_infer(self.infcx.tcx, freshener(index));

View File

@ -26,7 +26,7 @@ use session::config;
use util::nodemap::{FnvHashMap, FnvHashSet};
use util::ppaux::Repr;
use std::collections::hash_map::Vacant;
use std::collections::hash_map::Entry::Vacant;
use std::io::{mod, File};
use std::os;
use std::sync::atomic;

View File

@ -43,7 +43,8 @@ struct Annotator {
impl Annotator {
// Determine the stability for a node based on its attributes and inherited
// stability. The stability is recorded in the index and used as the parent.
fn annotate<F>(&mut self, id: NodeId, attrs: &Vec<Attribute>, f: F) where
fn annotate<F>(&mut self, id: NodeId, use_parent: bool,
attrs: &Vec<Attribute>, f: F) where
F: FnOnce(&mut Annotator),
{
match attr::find_stability(attrs.as_slice()) {
@ -60,7 +61,9 @@ impl Annotator {
}
}
None => {
self.parent.clone().map(|stab| self.index.local.insert(id, stab));
if use_parent {
self.parent.clone().map(|stab| self.index.local.insert(id, stab));
}
f(self);
}
}
@ -69,11 +72,24 @@ impl Annotator {
impl<'v> Visitor<'v> for Annotator {
fn visit_item(&mut self, i: &Item) {
self.annotate(i.id, &i.attrs, |v| visit::walk_item(v, i));
// FIXME (#18969): the following is a hack around the fact
// that we cannot currently annotate the stability of
// `deriving`. Basically, we do *not* allow stability
// inheritance on trait implementations, so that derived
// implementations appear to be unannotated. This then allows
// derived implementations to be automatically tagged with the
// stability of the trait. This is WRONG, but expedient to get
// libstd stabilized for the 1.0 release.
let use_parent = match i.node {
ast::ItemImpl(_, _, Some(_), _, _) => false,
_ => true,
};
self.annotate(i.id, use_parent, &i.attrs, |v| visit::walk_item(v, i));
if let ast::ItemStruct(ref sd, _) = i.node {
sd.ctor_id.map(|id| {
self.annotate(id, &i.attrs, |_| {})
self.annotate(id, true, &i.attrs, |_| {})
});
}
}
@ -82,7 +98,7 @@ impl<'v> Visitor<'v> for Annotator {
_: &'v Block, _: Span, _: NodeId) {
if let FkMethod(_, _, meth) = fk {
// Methods are not already annotated, so we annotate it
self.annotate(meth.id, &meth.attrs, |_| {});
self.annotate(meth.id, true, &meth.attrs, |_| {});
}
// Items defined in a function body have no reason to have
// a stability attribute, so we don't recurse.
@ -101,15 +117,21 @@ impl<'v> Visitor<'v> for Annotator {
TypeTraitItem(ref typedef) => (typedef.ty_param.id, &typedef.attrs),
};
self.annotate(id, attrs, |v| visit::walk_trait_item(v, t));
self.annotate(id, true, attrs, |v| visit::walk_trait_item(v, t));
}
fn visit_variant(&mut self, var: &Variant, g: &'v Generics) {
self.annotate(var.node.id, &var.node.attrs, |v| visit::walk_variant(v, var, g))
self.annotate(var.node.id, true, &var.node.attrs,
|v| visit::walk_variant(v, var, g))
}
fn visit_struct_field(&mut self, s: &StructField) {
self.annotate(s.node.id, &s.node.attrs, |v| visit::walk_struct_field(v, s));
self.annotate(s.node.id, true, &s.node.attrs,
|v| visit::walk_struct_field(v, s));
}
fn visit_foreign_item(&mut self, i: &ast::ForeignItem) {
self.annotate(i.id, true, &i.attrs, |_| {});
}
}
@ -123,7 +145,8 @@ impl Index {
},
parent: None
};
annotator.annotate(ast::CRATE_NODE_ID, &krate.attrs, |v| visit::walk_crate(v, krate));
annotator.annotate(ast::CRATE_NODE_ID, true, &krate.attrs,
|v| visit::walk_crate(v, krate));
annotator.index
}
}
@ -135,16 +158,29 @@ pub fn lookup(tcx: &ty::ctxt, id: DefId) -> Option<Stability> {
match ty::trait_item_of_item(tcx, id) {
Some(ty::MethodTraitItemId(trait_method_id))
if trait_method_id != id => {
lookup(tcx, trait_method_id)
}
_ if is_local(id) => {
tcx.stability.borrow().local.get(&id.node).cloned()
}
_ => {
let stab = csearch::get_stability(&tcx.sess.cstore, id);
let mut index = tcx.stability.borrow_mut();
(*index).extern_cache.insert(id, stab.clone());
stab
return lookup(tcx, trait_method_id)
}
_ => {}
}
let item_stab = if is_local(id) {
tcx.stability.borrow().local.get(&id.node).cloned()
} else {
let stab = csearch::get_stability(&tcx.sess.cstore, id);
let mut index = tcx.stability.borrow_mut();
(*index).extern_cache.insert(id, stab.clone());
stab
};
item_stab.or_else(|| {
if let Some(trait_id) = ty::trait_id_of_impl(tcx, id) {
// FIXME (#18969): for the time being, simply use the
// stability of the trait to determine the stability of any
// unmarked impls for it. See FIXME above for more details.
lookup(tcx, trait_id)
} else {
None
}
})
}

View File

@ -12,7 +12,7 @@ use middle::infer::InferCtxt;
use middle::mem_categorization::Typer;
use middle::ty::{mod, Ty};
use std::collections::HashSet;
use std::collections::hash_map::{Occupied, Vacant};
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::default::Default;
use std::rc::Rc;
use syntax::ast;

View File

@ -77,7 +77,8 @@ use std::mem;
use std::ops;
use std::rc::Rc;
use collections::enum_set::{EnumSet, CLike};
use std::collections::hash_map::{HashMap, Occupied, Vacant};
use std::collections::hash_map::HashMap;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use syntax::abi;
use syntax::ast::{CrateNum, DefId, DUMMY_NODE_ID, Ident, ItemTrait, LOCAL_CRATE};
use syntax::ast::{MutImmutable, MutMutable, Name, NamedField, NodeId};
@ -2851,45 +2852,18 @@ impl TypeContents {
}
}
// NOTE(stage0): Remove impl after a snapshot
#[cfg(stage0)]
impl ops::BitOr<TypeContents,TypeContents> for TypeContents {
fn bitor(&self, other: &TypeContents) -> TypeContents {
TypeContents {bits: self.bits | other.bits}
}
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
impl ops::BitOr<TypeContents,TypeContents> for TypeContents {
fn bitor(self, other: TypeContents) -> TypeContents {
TypeContents {bits: self.bits | other.bits}
}
}
// NOTE(stage0): Remove impl after a snapshot
#[cfg(stage0)]
impl ops::BitAnd<TypeContents,TypeContents> for TypeContents {
fn bitand(&self, other: &TypeContents) -> TypeContents {
TypeContents {bits: self.bits & other.bits}
}
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
impl ops::BitAnd<TypeContents, TypeContents> for TypeContents {
fn bitand(self, other: TypeContents) -> TypeContents {
TypeContents {bits: self.bits & other.bits}
}
}
// NOTE(stage0): Remove impl after a snapshot
#[cfg(stage0)]
impl ops::Sub<TypeContents,TypeContents> for TypeContents {
fn sub(&self, other: &TypeContents) -> TypeContents {
TypeContents {bits: self.bits & !other.bits}
}
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
impl ops::Sub<TypeContents, TypeContents> for TypeContents {
fn sub(self, other: TypeContents) -> TypeContents {
TypeContents {bits: self.bits & !other.bits}

View File

@ -82,10 +82,6 @@ pub trait TypeFolder<'tcx> {
super_fold_trait_ref(self, t)
}
fn fold_sty(&mut self, sty: &ty::sty<'tcx>) -> ty::sty<'tcx> {
super_fold_sty(self, sty)
}
fn fold_substs(&mut self,
substs: &subst::Substs<'tcx>)
-> subst::Substs<'tcx> {
@ -260,12 +256,6 @@ impl<'tcx> TypeFoldable<'tcx> for ty::FnSig<'tcx> {
}
}
impl<'tcx> TypeFoldable<'tcx> for ty::sty<'tcx> {
fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::sty<'tcx> {
folder.fold_sty(self)
}
}
impl<'tcx> TypeFoldable<'tcx> for ty::TraitRef<'tcx> {
fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::TraitRef<'tcx> {
folder.fold_trait_ref(self)
@ -521,9 +511,55 @@ impl<'tcx,T,U> TypeFoldable<'tcx> for ty::OutlivesPredicate<T,U>
// They should invoke `foo.fold_with()` to do recursive folding.
pub fn super_fold_ty<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
t: Ty<'tcx>)
ty: Ty<'tcx>)
-> Ty<'tcx> {
let sty = t.sty.fold_with(this);
let sty = match ty.sty {
ty::ty_uniq(typ) => {
ty::ty_uniq(typ.fold_with(this))
}
ty::ty_ptr(ref tm) => {
ty::ty_ptr(tm.fold_with(this))
}
ty::ty_vec(typ, sz) => {
ty::ty_vec(typ.fold_with(this), sz)
}
ty::ty_open(typ) => {
ty::ty_open(typ.fold_with(this))
}
ty::ty_enum(tid, ref substs) => {
ty::ty_enum(tid, substs.fold_with(this))
}
ty::ty_trait(box ty::TyTrait { ref principal, bounds }) => {
ty::ty_trait(box ty::TyTrait {
principal: (*principal).fold_with(this),
bounds: bounds.fold_with(this),
})
}
ty::ty_tup(ref ts) => {
ty::ty_tup(ts.fold_with(this))
}
ty::ty_bare_fn(ref f) => {
ty::ty_bare_fn(f.fold_with(this))
}
ty::ty_closure(ref f) => {
ty::ty_closure(box f.fold_with(this))
}
ty::ty_rptr(r, ref tm) => {
ty::ty_rptr(r.fold_with(this), tm.fold_with(this))
}
ty::ty_struct(did, ref substs) => {
ty::ty_struct(did, substs.fold_with(this))
}
ty::ty_unboxed_closure(did, ref region, ref substs) => {
ty::ty_unboxed_closure(did, region.fold_with(this), substs.fold_with(this))
}
ty::ty_bool | ty::ty_char | ty::ty_str |
ty::ty_int(_) | ty::ty_uint(_) | ty::ty_float(_) |
ty::ty_err | ty::ty_infer(_) |
ty::ty_param(..) => {
ty.sty.clone()
}
};
ty::mk_t(this.tcx(), sty)
}
@ -601,58 +637,6 @@ pub fn super_fold_mt<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
mutbl: mt.mutbl}
}
pub fn super_fold_sty<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
sty: &ty::sty<'tcx>)
-> ty::sty<'tcx> {
match *sty {
ty::ty_uniq(typ) => {
ty::ty_uniq(typ.fold_with(this))
}
ty::ty_ptr(ref tm) => {
ty::ty_ptr(tm.fold_with(this))
}
ty::ty_vec(typ, sz) => {
ty::ty_vec(typ.fold_with(this), sz)
}
ty::ty_open(typ) => {
ty::ty_open(typ.fold_with(this))
}
ty::ty_enum(tid, ref substs) => {
ty::ty_enum(tid, substs.fold_with(this))
}
ty::ty_trait(box ty::TyTrait { ref principal, bounds }) => {
ty::ty_trait(box ty::TyTrait {
principal: (*principal).fold_with(this),
bounds: bounds.fold_with(this),
})
}
ty::ty_tup(ref ts) => {
ty::ty_tup(ts.fold_with(this))
}
ty::ty_bare_fn(ref f) => {
ty::ty_bare_fn(f.fold_with(this))
}
ty::ty_closure(ref f) => {
ty::ty_closure(box f.fold_with(this))
}
ty::ty_rptr(r, ref tm) => {
ty::ty_rptr(r.fold_with(this), tm.fold_with(this))
}
ty::ty_struct(did, ref substs) => {
ty::ty_struct(did, substs.fold_with(this))
}
ty::ty_unboxed_closure(did, ref region, ref substs) => {
ty::ty_unboxed_closure(did, region.fold_with(this), substs.fold_with(this))
}
ty::ty_bool | ty::ty_char | ty::ty_str |
ty::ty_int(_) | ty::ty_uint(_) | ty::ty_float(_) |
ty::ty_err | ty::ty_infer(_) |
ty::ty_param(..) => {
(*sty).clone()
}
}
}
pub fn super_fold_trait_store<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
trait_store: ty::TraitStore)
-> ty::TraitStore {

View File

@ -33,7 +33,7 @@ use syntax::parse;
use syntax::parse::token::InternedString;
use std::collections::HashMap;
use std::collections::hash_map::{Occupied, Vacant};
use std::collections::hash_map::Entry::{Occupied, Vacant};
use getopts::{optopt, optmulti, optflag, optflagopt};
use getopts;
use std::cell::{RefCell};

View File

@ -93,8 +93,9 @@ pub fn explain_region_and_span(cx: &ctxt, region: ty::Region)
ast::ExprMethodCall(..) => {
explain_span(cx, "method call", expr.span)
},
ast::ExprMatch(_, _, ast::MatchIfLetDesugar) => explain_span(cx, "if let", expr.span),
ast::ExprMatch(_, _, ast::MatchWhileLetDesugar) => {
ast::ExprMatch(_, _, ast::MatchSource::IfLetDesugar { .. }) =>
explain_span(cx, "if let", expr.span),
ast::ExprMatch(_, _, ast::MatchSource::WhileLetDesugar) => {
explain_span(cx, "while let", expr.span)
},
ast::ExprMatch(..) => explain_span(cx, "match", expr.span),
@ -452,7 +453,7 @@ pub fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String {
ty_vec(t, sz) => {
let inner_str = ty_to_string(cx, t);
match sz {
Some(n) => format!("[{}, ..{}]", inner_str, n),
Some(n) => format!("[{}; {}]", inner_str, n),
None => format!("[{}]", inner_str),
}
}
@ -532,7 +533,13 @@ pub fn parameterized<'tcx>(cx: &ctxt<'tcx>,
if cx.lang_items.fn_trait_kind(did).is_some() {
format!("{}({}){}",
base,
strs[0][1 .. strs[0].len() - (strs[0].ends_with(",)") as uint+1)],
if strs[0].starts_with("(") && strs[0].ends_with(",)") {
strs[0][1 .. strs[0].len() - 2] // Remove '(' and ',)'
} else if strs[0].starts_with("(") && strs[0].ends_with(")") {
strs[0][1 .. strs[0].len() - 1] // Remove '(' and ')'
} else {
strs[0][]
},
if &*strs[1] == "()" { String::new() } else { format!(" -> {}", strs[1]) })
} else if strs.len() > 0 {
format!("{}<{}>", base, strs.connect(", "))

View File

@ -480,7 +480,7 @@ pub fn list_metadata(sess: &Session, path: &Path,
/// The diagnostic emitter yielded to the procedure should be used for reporting
/// errors of the compiler.
pub fn monitor<F:FnOnce()+Send>(f: F) {
static STACK_SIZE: uint = 32000000; // 32MB
static STACK_SIZE: uint = 8 * 1024 * 1024; // 8MB
let (tx, rx) = channel();
let w = io::ChanWriter::new(tx);

View File

@ -90,7 +90,7 @@ use syntax::owned_slice::OwnedSlice;
use syntax::visit::{mod, Visitor};
use std::collections::{HashMap, HashSet};
use std::collections::hash_map::{Occupied, Vacant};
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::cell::{Cell, RefCell};
use std::mem::replace;
use std::rc::{Rc, Weak};

View File

@ -38,6 +38,7 @@ use llvm::{BasicBlockRef, Linkage, ValueRef, Vector, get_param};
use llvm;
use metadata::{csearch, encoder, loader};
use middle::astencode;
use middle::cfg;
use middle::lang_items::{LangItem, ExchangeMallocFnLangItem, StartFnLangItem};
use middle::subst;
use middle::weak_lang_items;
@ -1306,47 +1307,33 @@ pub fn make_return_slot_pointer<'a, 'tcx>(fcx: &FunctionContext<'a, 'tcx>,
}
}
struct CheckForNestedReturnsVisitor {
struct FindNestedReturn {
found: bool,
in_return: bool
}
impl CheckForNestedReturnsVisitor {
fn explicit() -> CheckForNestedReturnsVisitor {
CheckForNestedReturnsVisitor { found: false, in_return: false }
}
fn implicit() -> CheckForNestedReturnsVisitor {
CheckForNestedReturnsVisitor { found: false, in_return: true }
impl FindNestedReturn {
fn new() -> FindNestedReturn {
FindNestedReturn { found: false }
}
}
impl<'v> Visitor<'v> for CheckForNestedReturnsVisitor {
impl<'v> Visitor<'v> for FindNestedReturn {
fn visit_expr(&mut self, e: &ast::Expr) {
match e.node {
ast::ExprRet(..) => {
if self.in_return {
self.found = true;
} else {
self.in_return = true;
visit::walk_expr(self, e);
self.in_return = false;
}
self.found = true;
}
_ => visit::walk_expr(self, e)
}
}
}
fn has_nested_returns(tcx: &ty::ctxt, id: ast::NodeId) -> bool {
match tcx.map.find(id) {
fn build_cfg(tcx: &ty::ctxt, id: ast::NodeId) -> (ast::NodeId, Option<cfg::CFG>) {
let blk = match tcx.map.find(id) {
Some(ast_map::NodeItem(i)) => {
match i.node {
ast::ItemFn(_, _, _, _, ref blk) => {
let mut explicit = CheckForNestedReturnsVisitor::explicit();
let mut implicit = CheckForNestedReturnsVisitor::implicit();
visit::walk_item(&mut explicit, &*i);
visit::walk_expr_opt(&mut implicit, &blk.expr);
explicit.found || implicit.found
blk
}
_ => tcx.sess.bug("unexpected item variant in has_nested_returns")
}
@ -1356,11 +1343,7 @@ fn has_nested_returns(tcx: &ty::ctxt, id: ast::NodeId) -> bool {
ast::ProvidedMethod(ref m) => {
match m.node {
ast::MethDecl(_, _, _, _, _, _, ref blk, _) => {
let mut explicit = CheckForNestedReturnsVisitor::explicit();
let mut implicit = CheckForNestedReturnsVisitor::implicit();
visit::walk_method_helper(&mut explicit, &**m);
visit::walk_expr_opt(&mut implicit, &blk.expr);
explicit.found || implicit.found
blk
}
ast::MethMac(_) => tcx.sess.bug("unexpanded macro")
}
@ -1380,11 +1363,7 @@ fn has_nested_returns(tcx: &ty::ctxt, id: ast::NodeId) -> bool {
ast::MethodImplItem(ref m) => {
match m.node {
ast::MethDecl(_, _, _, _, _, _, ref blk, _) => {
let mut explicit = CheckForNestedReturnsVisitor::explicit();
let mut implicit = CheckForNestedReturnsVisitor::implicit();
visit::walk_method_helper(&mut explicit, &**m);
visit::walk_expr_opt(&mut implicit, &blk.expr);
explicit.found || implicit.found
blk
}
ast::MethMac(_) => tcx.sess.bug("unexpanded macro")
}
@ -1398,24 +1377,58 @@ fn has_nested_returns(tcx: &ty::ctxt, id: ast::NodeId) -> bool {
Some(ast_map::NodeExpr(e)) => {
match e.node {
ast::ExprClosure(_, _, _, ref blk) => {
let mut explicit = CheckForNestedReturnsVisitor::explicit();
let mut implicit = CheckForNestedReturnsVisitor::implicit();
visit::walk_expr(&mut explicit, e);
visit::walk_expr_opt(&mut implicit, &blk.expr);
explicit.found || implicit.found
blk
}
_ => tcx.sess.bug("unexpected expr variant in has_nested_returns")
}
}
Some(ast_map::NodeVariant(..)) | Some(ast_map::NodeStructCtor(..)) => false,
Some(ast_map::NodeVariant(..)) |
Some(ast_map::NodeStructCtor(..)) => return (ast::DUMMY_NODE_ID, None),
// glue, shims, etc
None if id == ast::DUMMY_NODE_ID => false,
None if id == ast::DUMMY_NODE_ID => return (ast::DUMMY_NODE_ID, None),
_ => tcx.sess.bug(format!("unexpected variant in has_nested_returns: {}",
tcx.map.path_to_string(id)).as_slice())
};
(blk.id, Some(cfg::CFG::new(tcx, &**blk)))
}
// Checks for the presence of "nested returns" in a function.
// Nested returns are when the inner expression of a return expression
// (the 'expr' in 'return expr') contains a return expression. Only cases
// where the outer return is actually reachable are considered. Implicit
// returns from the end of blocks are considered as well.
//
// This check is needed to handle the case where the inner expression is
// part of a larger expression that may have already partially-filled the
// return slot alloca. This can cause errors related to clean-up due to
// the clobbering of the existing value in the return slot.
fn has_nested_returns(tcx: &ty::ctxt, cfg: &cfg::CFG, blk_id: ast::NodeId) -> bool {
for n in cfg.graph.depth_traverse(cfg.entry) {
match tcx.map.find(n.id) {
Some(ast_map::NodeExpr(ex)) => {
if let ast::ExprRet(Some(ref ret_expr)) = ex.node {
let mut visitor = FindNestedReturn::new();
visit::walk_expr(&mut visitor, &**ret_expr);
if visitor.found {
return true;
}
}
}
Some(ast_map::NodeBlock(blk)) if blk.id == blk_id => {
let mut visitor = FindNestedReturn::new();
visit::walk_expr_opt(&mut visitor, &blk.expr);
if visitor.found {
return true;
}
}
_ => {}
}
}
return false;
}
// NB: must keep 4 fns in sync:
@ -1454,7 +1467,12 @@ pub fn new_fn_ctxt<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>,
ty::FnDiverging => false
};
let debug_context = debuginfo::create_function_debug_context(ccx, id, param_substs, llfndecl);
let nested_returns = has_nested_returns(ccx.tcx(), id);
let (blk_id, cfg) = build_cfg(ccx.tcx(), id);
let nested_returns = if let Some(ref cfg) = cfg {
has_nested_returns(ccx.tcx(), cfg, blk_id)
} else {
false
};
let mut fcx = FunctionContext {
llfn: llfndecl,
@ -1473,7 +1491,8 @@ pub fn new_fn_ctxt<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>,
block_arena: block_arena,
ccx: ccx,
debug_context: debug_context,
scopes: RefCell::new(Vec::new())
scopes: RefCell::new(Vec::new()),
cfg: cfg
};
if has_env {

View File

@ -18,6 +18,7 @@ use session::Session;
use llvm;
use llvm::{ValueRef, BasicBlockRef, BuilderRef, ContextRef};
use llvm::{True, False, Bool};
use middle::cfg;
use middle::def;
use middle::infer;
use middle::lang_items::LangItem;
@ -262,6 +263,8 @@ pub struct FunctionContext<'a, 'tcx: 'a> {
// Cleanup scopes.
pub scopes: RefCell<Vec<cleanup::CleanupScope<'a, 'tcx>>>,
pub cfg: Option<cfg::CFG>,
}
impl<'a, 'tcx> FunctionContext<'a, 'tcx> {

View File

@ -112,8 +112,17 @@ pub fn trans_block<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
if dest != expr::Ignore {
let block_ty = node_id_type(bcx, b.id);
if b.expr.is_none() || type_is_zero_size(bcx.ccx(), block_ty) {
dest = expr::Ignore;
} else if b.expr.is_some() {
// If the block has an expression, but that expression isn't reachable,
// don't save into the destination given, ignore it.
if let Some(ref cfg) = bcx.fcx.cfg {
if !cfg.node_is_reachable(b.expr.as_ref().unwrap().id) {
dest = expr::Ignore;
}
}
}
}
@ -277,6 +286,7 @@ pub fn trans_for<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
debug!("iterator type is {}, datum type is {}",
ppaux::ty_to_string(bcx.tcx(), iterator_type),
ppaux::ty_to_string(bcx.tcx(), iterator_datum.ty));
let lliterator = load_ty(bcx, iterator_datum.val, iterator_datum.ty);
// Create our basic blocks and set up our loop cleanups.
@ -356,6 +366,8 @@ pub fn trans_for<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
llpayload,
binding_cleanup_scope_id);
debuginfo::create_for_loop_var_metadata(body_bcx_in, pat);
// Codegen the body.
body_bcx_out = trans_block(body_bcx_out, body, expr::Ignore);
body_bcx_out =

View File

@ -182,7 +182,6 @@
//! comparatively expensive to construct, though, `ty::type_id()` is still used
//! additionally as an optimization for cases where the exact same type has been
//! seen before (which is most of the time).
use self::FunctionDebugContextRepr::*;
use self::VariableAccess::*;
use self::VariableKind::*;
use self::MemberOffset::*;
@ -334,7 +333,7 @@ impl<'tcx> TypeMap<'tcx> {
// mut ptr (*mut) -> {*mut :pointee-uid:}
// unique ptr (~) -> {~ :pointee-uid:}
// @-ptr (@) -> {@ :pointee-uid:}
// sized vec ([T, ..x]) -> {[:size:] :element-uid:}
// sized vec ([T; x]) -> {[:size:] :element-uid:}
// unsized vec ([T]) -> {[] :element-uid:}
// trait (T) -> {trait_:svh: / :node-id:_<(:param-uid:),*> }
// closure -> {<unsafe_> <once_> :store-sigil: |(:param-uid:),* <,_...>| -> \
@ -679,12 +678,8 @@ impl<'tcx> CrateDebugContext<'tcx> {
}
}
pub struct FunctionDebugContext {
repr: FunctionDebugContextRepr,
}
enum FunctionDebugContextRepr {
DebugInfo(Box<FunctionDebugContextData>),
pub enum FunctionDebugContext {
RegularContext(Box<FunctionDebugContextData>),
DebugInfoDisabled,
FunctionWithoutDebugInfo,
}
@ -694,13 +689,13 @@ impl FunctionDebugContext {
cx: &CrateContext,
span: Span)
-> &'a FunctionDebugContextData {
match self.repr {
DebugInfo(box ref data) => data,
DebugInfoDisabled => {
match *self {
FunctionDebugContext::RegularContext(box ref data) => data,
FunctionDebugContext::DebugInfoDisabled => {
cx.sess().span_bug(span,
FunctionDebugContext::debuginfo_disabled_message());
}
FunctionWithoutDebugInfo => {
FunctionDebugContext::FunctionWithoutDebugInfo => {
cx.sess().span_bug(span,
FunctionDebugContext::should_be_ignored_message());
}
@ -844,6 +839,8 @@ pub fn create_global_var_metadata(cx: &CrateContext,
/// Creates debug information for the given local variable.
///
/// This function assumes that there's a datum for each pattern component of the
/// local in `bcx.fcx.lllocals`.
/// Adds the created metadata nodes directly to the crate's IR.
pub fn create_local_var_metadata(bcx: Block, local: &ast::Local) {
if fn_should_be_ignored(bcx.fcx) {
@ -852,11 +849,10 @@ pub fn create_local_var_metadata(bcx: Block, local: &ast::Local) {
let cx = bcx.ccx();
let def_map = &cx.tcx().def_map;
let locals = bcx.fcx.lllocals.borrow();
pat_util::pat_bindings(def_map, &*local.pat, |_, node_id, span, path1| {
let var_ident = path1.node;
let datum = match bcx.fcx.lllocals.borrow().get(&node_id).cloned() {
pat_util::pat_bindings(def_map, &*local.pat, |_, node_id, span, var_ident| {
let datum = match locals.get(&node_id) {
Some(datum) => datum,
None => {
bcx.sess().span_bug(span,
@ -865,10 +861,15 @@ pub fn create_local_var_metadata(bcx: Block, local: &ast::Local) {
}
};
if unsafe { llvm::LLVMIsAAllocaInst(datum.val) } == ptr::null_mut() {
cx.sess().span_bug(span, "debuginfo::create_local_var_metadata() - \
Referenced variable location is not an alloca!");
}
let scope_metadata = scope_metadata(bcx.fcx, node_id, span);
declare_local(bcx,
var_ident,
var_ident.node,
datum.ty,
scope_metadata,
DirectVariable { alloca: datum.val },
@ -981,7 +982,7 @@ pub fn create_match_binding_metadata<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
// for the binding. For ByRef bindings that's a `T*` but for ByMove bindings we
// actually have `T**`. So to get the actual variable we need to dereference once
// more. For ByCopy we just use the stack slot we created for the binding.
let var_type = match binding.trmode {
let var_access = match binding.trmode {
TrByCopy(llbinding) => DirectVariable {
alloca: llbinding
},
@ -998,27 +999,31 @@ pub fn create_match_binding_metadata<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
variable_ident,
binding.ty,
scope_metadata,
var_type,
var_access,
LocalVariable,
binding.span);
}
/// Creates debug information for the given function argument.
///
/// This function assumes that there's a datum for each pattern component of the
/// argument in `bcx.fcx.lllocals`.
/// Adds the created metadata nodes directly to the crate's IR.
pub fn create_argument_metadata(bcx: Block, arg: &ast::Arg) {
if fn_should_be_ignored(bcx.fcx) {
return;
}
let fcx = bcx.fcx;
let cx = fcx.ccx;
let def_map = &bcx.tcx().def_map;
let scope_metadata = bcx
.fcx
.debug_context
.get_ref(bcx.ccx(), arg.pat.span)
.fn_metadata;
let locals = bcx.fcx.lllocals.borrow();
let def_map = &cx.tcx().def_map;
let scope_metadata = bcx.fcx.debug_context.get_ref(cx, arg.pat.span).fn_metadata;
pat_util::pat_bindings(def_map, &*arg.pat, |_, node_id, span, path1| {
let llarg = match bcx.fcx.lllocals.borrow().get(&node_id).cloned() {
pat_util::pat_bindings(def_map, &*arg.pat, |_, node_id, span, var_ident| {
let datum = match locals.get(&node_id) {
Some(v) => v,
None => {
bcx.sess().span_bug(span,
@ -1027,28 +1032,72 @@ pub fn create_argument_metadata(bcx: Block, arg: &ast::Arg) {
}
};
if unsafe { llvm::LLVMIsAAllocaInst(llarg.val) } == ptr::null_mut() {
cx.sess().span_bug(span, "debuginfo::create_argument_metadata() - \
Referenced variable location is not an alloca!");
if unsafe { llvm::LLVMIsAAllocaInst(datum.val) } == ptr::null_mut() {
bcx.sess().span_bug(span, "debuginfo::create_argument_metadata() - \
Referenced variable location is not an alloca!");
}
let argument_index = {
let counter = &fcx.debug_context.get_ref(cx, span).argument_counter;
let counter = &bcx
.fcx
.debug_context
.get_ref(bcx.ccx(), span)
.argument_counter;
let argument_index = counter.get();
counter.set(argument_index + 1);
argument_index
};
declare_local(bcx,
path1.node,
llarg.ty,
var_ident.node,
datum.ty,
scope_metadata,
DirectVariable { alloca: llarg.val },
DirectVariable { alloca: datum.val },
ArgumentVariable(argument_index),
span);
})
}
/// Creates debug information for the given for-loop variable.
///
/// This function assumes that there's a datum for each pattern component of the
/// loop variable in `bcx.fcx.lllocals`.
/// Adds the created metadata nodes directly to the crate's IR.
pub fn create_for_loop_var_metadata(bcx: Block, pat: &ast::Pat) {
if fn_should_be_ignored(bcx.fcx) {
return;
}
let def_map = &bcx.tcx().def_map;
let locals = bcx.fcx.lllocals.borrow();
pat_util::pat_bindings(def_map, pat, |_, node_id, span, var_ident| {
let datum = match locals.get(&node_id) {
Some(datum) => datum,
None => {
bcx.sess().span_bug(span,
format!("no entry in lllocals table for {}",
node_id).as_slice());
}
};
if unsafe { llvm::LLVMIsAAllocaInst(datum.val) } == ptr::null_mut() {
bcx.sess().span_bug(span, "debuginfo::create_for_loop_var_metadata() - \
Referenced variable location is not an alloca!");
}
let scope_metadata = scope_metadata(bcx.fcx, node_id, span);
declare_local(bcx,
var_ident.node,
datum.ty,
scope_metadata,
DirectVariable { alloca: datum.val },
LocalVariable,
span);
})
}
pub fn get_cleanup_debug_loc_for_ast_node<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
node_id: ast::NodeId,
node_span: Span,
@ -1117,13 +1166,13 @@ pub fn get_cleanup_debug_loc_for_ast_node<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
pub fn set_source_location(fcx: &FunctionContext,
node_id: ast::NodeId,
span: Span) {
match fcx.debug_context.repr {
DebugInfoDisabled => return,
FunctionWithoutDebugInfo => {
match fcx.debug_context {
FunctionDebugContext::DebugInfoDisabled => return,
FunctionDebugContext::FunctionWithoutDebugInfo => {
set_debug_location(fcx.ccx, UnknownLocation);
return;
}
DebugInfo(box ref function_debug_context) => {
FunctionDebugContext::RegularContext(box ref function_debug_context) => {
let cx = fcx.ccx;
debug!("set_source_location: {}", cx.sess().codemap().span_to_string(span));
@ -1160,8 +1209,8 @@ pub fn clear_source_location(fcx: &FunctionContext) {
/// switches source location emitting on and must therefore be called before the
/// first real statement/expression of the function is translated.
pub fn start_emitting_source_locations(fcx: &FunctionContext) {
match fcx.debug_context.repr {
DebugInfo(box ref data) => {
match fcx.debug_context {
FunctionDebugContext::RegularContext(box ref data) => {
data.source_locations_enabled.set(true)
},
_ => { /* safe to ignore */ }
@ -1179,7 +1228,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
param_substs: &Substs<'tcx>,
llfn: ValueRef) -> FunctionDebugContext {
if cx.sess().opts.debuginfo == NoDebugInfo {
return FunctionDebugContext { repr: DebugInfoDisabled };
return FunctionDebugContext::DebugInfoDisabled;
}
// Clear the debug location so we don't assign them in the function prelude.
@ -1189,7 +1238,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
if fn_ast_id == ast::DUMMY_NODE_ID {
// This is a function not linked to any source location, so don't
// generate debuginfo for it.
return FunctionDebugContext { repr: FunctionWithoutDebugInfo };
return FunctionDebugContext::FunctionWithoutDebugInfo;
}
let empty_generics = ast_util::empty_generics();
@ -1199,7 +1248,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
let (ident, fn_decl, generics, top_level_block, span, has_path) = match fnitem {
ast_map::NodeItem(ref item) => {
if contains_nodebug_attribute(item.attrs.as_slice()) {
return FunctionDebugContext { repr: FunctionWithoutDebugInfo };
return FunctionDebugContext::FunctionWithoutDebugInfo;
}
match item.node {
@ -1216,9 +1265,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
match **item {
ast::MethodImplItem(ref method) => {
if contains_nodebug_attribute(method.attrs.as_slice()) {
return FunctionDebugContext {
repr: FunctionWithoutDebugInfo
};
return FunctionDebugContext::FunctionWithoutDebugInfo;
}
(method.pe_ident(),
@ -1257,9 +1304,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
match **trait_method {
ast::ProvidedMethod(ref method) => {
if contains_nodebug_attribute(method.attrs.as_slice()) {
return FunctionDebugContext {
repr: FunctionWithoutDebugInfo
};
return FunctionDebugContext::FunctionWithoutDebugInfo;
}
(method.pe_ident(),
@ -1280,7 +1325,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
ast_map::NodeForeignItem(..) |
ast_map::NodeVariant(..) |
ast_map::NodeStructCtor(..) => {
return FunctionDebugContext { repr: FunctionWithoutDebugInfo };
return FunctionDebugContext::FunctionWithoutDebugInfo;
}
_ => cx.sess().bug(format!("create_function_debug_context: \
unexpected sort of node: {}",
@ -1289,7 +1334,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
// This can be the case for functions inlined from another crate
if span == codemap::DUMMY_SP {
return FunctionDebugContext { repr: FunctionWithoutDebugInfo };
return FunctionDebugContext::FunctionWithoutDebugInfo;
}
let loc = span_start(cx, span);
@ -1356,22 +1401,23 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
})
});
let scope_map = create_scope_map(cx,
fn_decl.inputs.as_slice(),
&*top_level_block,
fn_metadata,
fn_ast_id);
// Initialize fn debug context (including scope map and namespace map)
let fn_debug_context = box FunctionDebugContextData {
scope_map: RefCell::new(NodeMap::new()),
scope_map: RefCell::new(scope_map),
fn_metadata: fn_metadata,
argument_counter: Cell::new(1),
source_locations_enabled: Cell::new(false),
};
populate_scope_map(cx,
fn_decl.inputs.as_slice(),
&*top_level_block,
fn_metadata,
fn_ast_id,
&mut *fn_debug_context.scope_map.borrow_mut());
return FunctionDebugContext { repr: DebugInfo(fn_debug_context) };
return FunctionDebugContext::RegularContext(fn_debug_context);
fn get_function_signature<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
fn_ast_id: ast::NodeId,
@ -3134,8 +3180,8 @@ fn DIB(cx: &CrateContext) -> DIBuilderRef {
}
fn fn_should_be_ignored(fcx: &FunctionContext) -> bool {
match fcx.debug_context.repr {
DebugInfo(_) => false,
match fcx.debug_context {
FunctionDebugContext::RegularContext(_) => false,
_ => true
}
}
@ -3169,12 +3215,14 @@ fn get_namespace_and_span_for_item(cx: &CrateContext, def_id: ast::DefId)
// what belongs to which scope, creating DIScope DIEs along the way, and
// introducing *artificial* lexical scope descriptors where necessary. These
// artificial scopes allow GDB to correctly handle name shadowing.
fn populate_scope_map(cx: &CrateContext,
args: &[ast::Arg],
fn_entry_block: &ast::Block,
fn_metadata: DISubprogram,
fn_ast_id: ast::NodeId,
scope_map: &mut NodeMap<DIScope>) {
fn create_scope_map(cx: &CrateContext,
args: &[ast::Arg],
fn_entry_block: &ast::Block,
fn_metadata: DISubprogram,
fn_ast_id: ast::NodeId)
-> NodeMap<DIScope> {
let mut scope_map = NodeMap::new();
let def_map = &cx.tcx().def_map;
struct ScopeStackEntry {
@ -3200,11 +3248,14 @@ fn populate_scope_map(cx: &CrateContext,
with_new_scope(cx,
fn_entry_block.span,
&mut scope_stack,
scope_map,
&mut scope_map,
|cx, scope_stack, scope_map| {
walk_block(cx, fn_entry_block, scope_stack, scope_map);
});
return scope_map;
// local helper functions for walking the AST.
fn with_new_scope<F>(cx: &CrateContext,
scope_span: Span,
@ -3440,7 +3491,7 @@ fn populate_scope_map(cx: &CrateContext,
}
ast::PatMac(_) => {
cx.sess().span_bug(pat.span, "debuginfo::populate_scope_map() - \
cx.sess().span_bug(pat.span, "debuginfo::create_scope_map() - \
Found unexpanded macro.");
}
}
@ -3526,7 +3577,7 @@ fn populate_scope_map(cx: &CrateContext,
}
ast::ExprIfLet(..) => {
cx.sess().span_bug(exp.span, "debuginfo::populate_scope_map() - \
cx.sess().span_bug(exp.span, "debuginfo::create_scope_map() - \
Found unexpanded if-let.");
}
@ -3543,7 +3594,7 @@ fn populate_scope_map(cx: &CrateContext,
}
ast::ExprWhileLet(..) => {
cx.sess().span_bug(exp.span, "debuginfo::populate_scope_map() - \
cx.sess().span_bug(exp.span, "debuginfo::create_scope_map() - \
Found unexpanded while-let.");
}
@ -3568,7 +3619,7 @@ fn populate_scope_map(cx: &CrateContext,
}
ast::ExprMac(_) => {
cx.sess().span_bug(exp.span, "debuginfo::populate_scope_map() - \
cx.sess().span_bug(exp.span, "debuginfo::create_scope_map() - \
Found unexpanded macro.");
}
@ -3752,7 +3803,7 @@ fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
match optional_length {
Some(len) => {
output.push_str(format!(", ..{}", len).as_slice());
output.push_str(format!("; {}", len).as_slice());
}
None => { /* nothing to do */ }
};

View File

@ -926,7 +926,29 @@ fn trans_rvalue_stmt_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
controlflow::trans_cont(bcx, expr.id, label_opt)
}
ast::ExprRet(ref ex) => {
controlflow::trans_ret(bcx, ex.as_ref().map(|e| &**e))
// Check to see if the return expression itself is reachable.
// This can occur when the inner expression contains a return
let reachable = if let Some(ref cfg) = bcx.fcx.cfg {
cfg.node_is_reachable(expr.id)
} else {
true
};
if reachable {
controlflow::trans_ret(bcx, ex.as_ref().map(|e| &**e))
} else {
// If it's not reachable, just translate the inner expression
// directly. This avoids having to manage a return slot when
// it won't actually be used anyway.
if let &Some(ref x) = ex {
bcx = trans_into(bcx, &**x, Ignore);
}
// Mark the end of the block as unreachable. Once we get to
// a return expression, there's no more we should be doing
// after this.
Unreachable(bcx);
bcx
}
}
ast::ExprWhile(ref cond, ref body, _) => {
controlflow::trans_while(bcx, expr.id, &**cond, &**body)

View File

@ -21,7 +21,7 @@ use util::nodemap::FnvHashMap;
use util::ppaux::Repr;
use std::cmp;
use std::collections::hash_map::{Occupied, Vacant};
use std::collections::hash_map::Entry::{Occupied, Vacant};
use syntax::ast;
use syntax::ast_util;
use syntax::codemap::{Span, Spanned};
@ -238,7 +238,8 @@ pub fn check_match<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
expr: &ast::Expr,
discrim: &ast::Expr,
arms: &[ast::Arm],
expected: Expectation<'tcx>) {
expected: Expectation<'tcx>,
match_src: ast::MatchSource) {
let tcx = fcx.ccx.tcx;
let discrim_ty = fcx.infcx().next_ty_var();
@ -290,12 +291,27 @@ pub fn check_match<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
if ty::type_is_error(result_ty) || ty::type_is_error(bty) {
ty::mk_err()
} else {
let (origin, expected, found) = match match_src {
/* if-let construct without an else block */
ast::MatchSource::IfLetDesugar { contains_else_clause }
if !contains_else_clause => (
infer::IfExpressionWithNoElse(expr.span),
bty,
result_ty,
),
_ => (
infer::MatchExpressionArm(expr.span, arm.body.span),
result_ty,
bty,
),
};
infer::common_supertype(
fcx.infcx(),
infer::MatchExpressionArm(expr.span, arm.body.span),
true, // result_ty is "expected" here
result_ty,
bty
origin,
true,
expected,
found,
)
}
});

View File

@ -261,44 +261,43 @@ fn check_boxed_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
// Find the expected input/output types (if any). Substitute
// fresh bound regions for any bound regions we find in the
// expected types so as to avoid capture.
let expected_sty = expected.map_to_option(fcx, |x| Some((*x).clone()));
let (expected_sig,
expected_onceness,
expected_bounds) = {
match expected_sty {
Some(ty::ty_closure(ref cenv)) => {
let (sig, _) =
ty::replace_late_bound_regions(
tcx,
&cenv.sig,
|_, debruijn| fcx.inh.infcx.fresh_bound_region(debruijn));
let onceness = match (&store, &cenv.store) {
// As the closure type and onceness go, only three
// combinations are legit:
// once closure
// many closure
// once proc
// If the actual and expected closure type disagree with
// each other, set expected onceness to be always Once or
// Many according to the actual type. Otherwise, it will
// yield either an illegal "many proc" or a less known
// "once closure" in the error message.
(&ty::UniqTraitStore, &ty::UniqTraitStore) |
(&ty::RegionTraitStore(..), &ty::RegionTraitStore(..)) =>
cenv.onceness,
(&ty::UniqTraitStore, _) => ast::Once,
(&ty::RegionTraitStore(..), _) => ast::Many,
};
(Some(sig), onceness, cenv.bounds)
}
_ => {
// Not an error! Means we're inferring the closure type
let region = fcx.infcx().next_region_var(
infer::AddrOfRegion(expr.span));
let bounds = ty::region_existential_bound(region);
let onceness = ast::Many;
(None, onceness, bounds)
}
let expected_cenv = expected.map_to_option(fcx, |ty| match ty.sty {
ty::ty_closure(ref cenv) => Some(cenv),
_ => None
});
let (expected_sig, expected_onceness, expected_bounds) = match expected_cenv {
Some(cenv) => {
let (sig, _) =
ty::replace_late_bound_regions(
tcx,
&cenv.sig,
|_, debruijn| fcx.inh.infcx.fresh_bound_region(debruijn));
let onceness = match (&store, &cenv.store) {
// As the closure type and onceness go, only three
// combinations are legit:
// once closure
// many closure
// once proc
// If the actual and expected closure type disagree with
// each other, set expected onceness to be always Once or
// Many according to the actual type. Otherwise, it will
// yield either an illegal "many proc" or a less known
// "once closure" in the error message.
(&ty::UniqTraitStore, &ty::UniqTraitStore) |
(&ty::RegionTraitStore(..), &ty::RegionTraitStore(..)) =>
cenv.onceness,
(&ty::UniqTraitStore, _) => ast::Once,
(&ty::RegionTraitStore(..), _) => ast::Many,
};
(Some(sig), onceness, cenv.bounds)
}
_ => {
// Not an error! Means we're inferring the closure type
let region = fcx.infcx().next_region_var(
infer::AddrOfRegion(expr.span));
let bounds = ty::region_existential_bound(region);
let onceness = ast::Many;
(None, onceness, bounds)
}
};

View File

@ -2042,7 +2042,7 @@ fn try_overloaded_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
-> bool {
// Bail out if the callee is a bare function or a closure. We check those
// manually.
match *structure_of(fcx, callee.span, callee_type) {
match structurally_resolved_type(fcx, callee.span, callee_type).sty {
ty::ty_bare_fn(_) | ty::ty_closure(_) => return false,
_ => {}
}
@ -2717,10 +2717,9 @@ fn check_lit<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
ast::LitInt(_, ast::SignedIntLit(t, _)) => ty::mk_mach_int(t),
ast::LitInt(_, ast::UnsignedIntLit(t)) => ty::mk_mach_uint(t),
ast::LitInt(_, ast::UnsuffixedIntLit(_)) => {
let opt_ty = expected.map_to_option(fcx, |sty| {
match *sty {
ty::ty_int(i) => Some(ty::mk_mach_int(i)),
ty::ty_uint(i) => Some(ty::mk_mach_uint(i)),
let opt_ty = expected.map_to_option(fcx, |ty| {
match ty.sty {
ty::ty_int(_) | ty::ty_uint(_) => Some(ty),
ty::ty_char => Some(ty::mk_mach_uint(ast::TyU8)),
ty::ty_ptr(..) => Some(ty::mk_mach_uint(ast::TyU)),
ty::ty_bare_fn(..) => Some(ty::mk_mach_uint(ast::TyU)),
@ -2732,9 +2731,9 @@ fn check_lit<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
}
ast::LitFloat(_, t) => ty::mk_mach_float(t),
ast::LitFloatUnsuffixed(_) => {
let opt_ty = expected.map_to_option(fcx, |sty| {
match *sty {
ty::ty_float(i) => Some(ty::mk_mach_float(i)),
let opt_ty = expected.map_to_option(fcx, |ty| {
match ty.sty {
ty::ty_float(_) => Some(ty),
_ => None
}
});
@ -2910,7 +2909,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
let fn_ty = fcx.expr_ty(f);
// Extract the function signature from `in_fty`.
let fn_sty = structure_of(fcx, f.span, fn_ty);
let fn_ty = structurally_resolved_type(fcx, f.span, fn_ty);
// This is the "default" function signature, used in case of error.
// In that case, we check each argument against "error" in order to
@ -2921,7 +2920,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
variadic: false
});
let fn_sig = match *fn_sty {
let fn_sig = match fn_ty.sty {
ty::ty_bare_fn(ty::BareFnTy {ref sig, ..}) |
ty::ty_closure(box ty::ClosureTy {ref sig, ..}) => sig,
_ => {
@ -3655,9 +3654,9 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
}
}
ast::ExprUnary(unop, ref oprnd) => {
let expected_inner = expected.map(fcx, |sty| {
let expected_inner = expected.map(fcx, |ty| {
match unop {
ast::UnUniq => match *sty {
ast::UnUniq => match ty.sty {
ty::ty_uniq(ty) => {
ExpectHasType(ty)
}
@ -3746,9 +3745,11 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
}
ast::ExprAddrOf(mutbl, ref oprnd) => {
let expected = expected.only_has_type();
let hint = expected.map(fcx, |sty| {
match *sty { ty::ty_rptr(_, ref mt) | ty::ty_ptr(ref mt) => ExpectHasType(mt.ty),
_ => NoExpectation }
let hint = expected.map(fcx, |ty| {
match ty.sty {
ty::ty_rptr(_, ref mt) | ty::ty_ptr(ref mt) => ExpectHasType(mt.ty),
_ => NoExpectation
}
});
let lvalue_pref = match mutbl {
ast::MutMutable => PreferMutLvalue,
@ -3918,8 +3919,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
fcx.write_nil(id);
}
}
ast::ExprMatch(ref discrim, ref arms, _) => {
_match::check_match(fcx, expr, &**discrim, arms.as_slice(), expected);
ast::ExprMatch(ref discrim, ref arms, match_src) => {
_match::check_match(fcx, expr, &**discrim, arms.as_slice(), expected, match_src);
}
ast::ExprClosure(_, opt_kind, ref decl, ref body) => {
closure::check_expr_closure(fcx, expr, opt_kind, &**decl, &**body, expected);
@ -4037,9 +4038,9 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
}
ast::ExprTup(ref elts) => {
let expected = expected.only_has_type();
let flds = expected.map_to_option(fcx, |sty| {
match *sty {
ty::ty_tup(ref flds) => Some((*flds).clone()),
let flds = expected.map_to_option(fcx, |ty| {
match ty.sty {
ty::ty_tup(ref flds) => Some(flds[]),
_ => None
}
});
@ -4304,20 +4305,20 @@ impl<'tcx> Expectation<'tcx> {
}
fn map<'a, F>(self, fcx: &FnCtxt<'a, 'tcx>, unpack: F) -> Expectation<'tcx> where
F: FnOnce(&ty::sty<'tcx>) -> Expectation<'tcx>
F: FnOnce(Ty<'tcx>) -> Expectation<'tcx>
{
match self.resolve(fcx) {
NoExpectation => NoExpectation,
ExpectCastableToType(t) | ExpectHasType(t) => unpack(&t.sty),
ExpectCastableToType(ty) | ExpectHasType(ty) => unpack(ty),
}
}
fn map_to_option<'a, O, F>(self, fcx: &FnCtxt<'a, 'tcx>, unpack: F) -> Option<O> where
F: FnOnce(&ty::sty<'tcx>) -> Option<O>,
F: FnOnce(Ty<'tcx>) -> Option<O>,
{
match self.resolve(fcx) {
NoExpectation => None,
ExpectCastableToType(t) | ExpectHasType(t) => unpack(&t.sty),
ExpectCastableToType(ty) | ExpectHasType(ty) => unpack(ty),
}
}
}
@ -5320,12 +5321,6 @@ pub fn structurally_resolved_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span,
ty
}
// Returns the one-level-deep structure of the given type.
pub fn structure_of<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span, typ: Ty<'tcx>)
-> &'tcx ty::sty<'tcx> {
&structurally_resolved_type(fcx, sp, typ).sty
}
// Returns true if b contains a break that can exit from b
pub fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: &ast::Block) -> bool {
// First: is there an unlabeled break immediately

View File

@ -135,7 +135,7 @@ use syntax::visit;
use syntax::visit::Visitor;
use std::cell::{RefCell};
use std::collections::hash_map::{Vacant, Occupied};
use std::collections::hash_map::Entry::{Vacant, Occupied};
use self::RepeatingScope::Repeating;
use self::SubjectNode::Subject;

View File

@ -17,7 +17,7 @@ use middle::subst::{Subst};
use middle::traits;
use middle::ty::{mod, Ty};
use middle::ty::liberate_late_bound_regions;
use middle::ty_fold::{TypeFolder, TypeFoldable};
use middle::ty_fold::{TypeFolder, TypeFoldable, super_fold_ty};
use util::ppaux::Repr;
use std::collections::HashSet;
@ -368,8 +368,8 @@ impl<'cx,'tcx> TypeFolder<'tcx> for BoundsChecker<'cx,'tcx> {
self.binding_count -= 1;
}
ref sty => {
self.fold_sty(sty);
_ => {
super_fold_ty(self, t);
}
}

View File

@ -163,33 +163,24 @@ impl<'a, 'tcx> Clean<Crate> for visit_ast::RustdocVisitor<'a, 'tcx> {
};
let mut tmp = Vec::new();
for child in m.items.iter_mut() {
let inner = match child.inner {
ModuleItem(ref mut m) => m,
match child.inner {
ModuleItem(..) => {}
_ => continue,
};
}
let prim = match PrimitiveType::find(child.attrs.as_slice()) {
Some(prim) => prim,
None => continue,
};
primitives.push(prim);
let mut i = Item {
tmp.push(Item {
source: Span::empty(),
name: Some(prim.to_url_str().to_string()),
attrs: Vec::new(),
visibility: None,
attrs: child.attrs.clone(),
visibility: Some(ast::Public),
stability: None,
def_id: ast_util::local_def(prim.to_node_id()),
inner: PrimitiveItem(prim),
};
// Push one copy to get indexed for the whole crate, and push a
// another copy in the proper location which will actually get
// documented. The first copy will also serve as a redirect to
// the other copy.
tmp.push(i.clone());
i.visibility = Some(ast::Public);
i.attrs = child.attrs.clone();
inner.items.push(i);
});
}
m.items.extend(tmp.into_iter());
}

View File

@ -35,7 +35,7 @@
pub use self::ExternalLocation::*;
use std::cell::RefCell;
use std::collections::hash_map::{Occupied, Vacant};
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::collections::{HashMap, HashSet};
use std::default::Default;
use std::fmt;

View File

@ -34,7 +34,7 @@ extern crate "test" as testing;
use std::cell::RefCell;
use std::collections::HashMap;
use std::collections::hash_map::{Occupied, Vacant};
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::io::File;
use std::io;
use std::rc::Rc;

View File

@ -2012,7 +2012,6 @@ macro_rules! read_primitive {
impl ::Decoder<DecoderError> for Decoder {
fn read_nil(&mut self) -> DecodeResult<()> {
debug!("read_nil");
expect!(self.pop(), Null)
}
@ -2030,7 +2029,6 @@ impl ::Decoder<DecoderError> for Decoder {
fn read_f32(&mut self) -> DecodeResult<f32> { self.read_f64().map(|x| x as f32) }
fn read_f64(&mut self) -> DecodeResult<f64> {
debug!("read_f64");
match self.pop() {
Json::I64(f) => Ok(f as f64),
Json::U64(f) => Ok(f as f64),
@ -2049,7 +2047,6 @@ impl ::Decoder<DecoderError> for Decoder {
}
fn read_bool(&mut self) -> DecodeResult<bool> {
debug!("read_bool");
expect!(self.pop(), Boolean)
}
@ -2067,14 +2064,12 @@ impl ::Decoder<DecoderError> for Decoder {
}
fn read_str(&mut self) -> DecodeResult<string::String> {
debug!("read_str");
expect!(self.pop(), String)
}
fn read_enum<T, F>(&mut self, name: &str, f: F) -> DecodeResult<T> where
fn read_enum<T, F>(&mut self, _name: &str, f: F) -> DecodeResult<T> where
F: FnOnce(&mut Decoder) -> DecodeResult<T>,
{
debug!("read_enum({})", name);
f(self)
}
@ -2082,7 +2077,6 @@ impl ::Decoder<DecoderError> for Decoder {
mut f: F) -> DecodeResult<T>
where F: FnMut(&mut Decoder, uint) -> DecodeResult<T>,
{
debug!("read_enum_variant(names={})", names);
let name = match self.pop() {
Json::String(s) => s,
Json::Object(mut o) => {
@ -2122,36 +2116,32 @@ impl ::Decoder<DecoderError> for Decoder {
f(self, idx)
}
fn read_enum_variant_arg<T, F>(&mut self, idx: uint, f: F) -> DecodeResult<T> where
fn read_enum_variant_arg<T, F>(&mut self, _idx: uint, f: F) -> DecodeResult<T> where
F: FnOnce(&mut Decoder) -> DecodeResult<T>,
{
debug!("read_enum_variant_arg(idx={})", idx);
f(self)
}
fn read_enum_struct_variant<T, F>(&mut self, names: &[&str], f: F) -> DecodeResult<T> where
F: FnMut(&mut Decoder, uint) -> DecodeResult<T>,
{
debug!("read_enum_struct_variant(names={})", names);
self.read_enum_variant(names, f)
}
fn read_enum_struct_variant_field<T, F>(&mut self,
name: &str,
_name: &str,
idx: uint,
f: F)
-> DecodeResult<T> where
F: FnOnce(&mut Decoder) -> DecodeResult<T>,
{
debug!("read_enum_struct_variant_field(name={}, idx={})", name, idx);
self.read_enum_variant_arg(idx, f)
}
fn read_struct<T, F>(&mut self, name: &str, len: uint, f: F) -> DecodeResult<T> where
fn read_struct<T, F>(&mut self, _name: &str, _len: uint, f: F) -> DecodeResult<T> where
F: FnOnce(&mut Decoder) -> DecodeResult<T>,
{
debug!("read_struct(name={}, len={})", name, len);
let value = try!(f(self));
self.pop();
Ok(value)
@ -2159,12 +2149,11 @@ impl ::Decoder<DecoderError> for Decoder {
fn read_struct_field<T, F>(&mut self,
name: &str,
idx: uint,
_idx: uint,
f: F)
-> DecodeResult<T> where
F: FnOnce(&mut Decoder) -> DecodeResult<T>,
{
debug!("read_struct_field(name={}, idx={})", name, idx);
let mut obj = try!(expect!(self.pop(), Object));
let value = match obj.remove(&name.to_string()) {
@ -2189,7 +2178,6 @@ impl ::Decoder<DecoderError> for Decoder {
fn read_tuple<T, F>(&mut self, tuple_len: uint, f: F) -> DecodeResult<T> where
F: FnOnce(&mut Decoder) -> DecodeResult<T>,
{
debug!("read_tuple()");
self.read_seq(move |d, len| {
if len == tuple_len {
f(d)
@ -2202,18 +2190,16 @@ impl ::Decoder<DecoderError> for Decoder {
fn read_tuple_arg<T, F>(&mut self, idx: uint, f: F) -> DecodeResult<T> where
F: FnOnce(&mut Decoder) -> DecodeResult<T>,
{
debug!("read_tuple_arg(idx={})", idx);
self.read_seq_elt(idx, f)
}
fn read_tuple_struct<T, F>(&mut self,
name: &str,
_name: &str,
len: uint,
f: F)
-> DecodeResult<T> where
F: FnOnce(&mut Decoder) -> DecodeResult<T>,
{
debug!("read_tuple_struct(name={})", name);
self.read_tuple(len, f)
}
@ -2223,14 +2209,12 @@ impl ::Decoder<DecoderError> for Decoder {
-> DecodeResult<T> where
F: FnOnce(&mut Decoder) -> DecodeResult<T>,
{
debug!("read_tuple_struct_arg(idx={})", idx);
self.read_tuple_arg(idx, f)
}
fn read_option<T, F>(&mut self, mut f: F) -> DecodeResult<T> where
F: FnMut(&mut Decoder, bool) -> DecodeResult<T>,
{
debug!("read_option()");
match self.pop() {
Json::Null => f(self, false),
value => { self.stack.push(value); f(self, true) }
@ -2240,7 +2224,6 @@ impl ::Decoder<DecoderError> for Decoder {
fn read_seq<T, F>(&mut self, f: F) -> DecodeResult<T> where
F: FnOnce(&mut Decoder, uint) -> DecodeResult<T>,
{
debug!("read_seq()");
let array = try!(expect!(self.pop(), Array));
let len = array.len();
for v in array.into_iter().rev() {
@ -2249,17 +2232,15 @@ impl ::Decoder<DecoderError> for Decoder {
f(self, len)
}
fn read_seq_elt<T, F>(&mut self, idx: uint, f: F) -> DecodeResult<T> where
fn read_seq_elt<T, F>(&mut self, _idx: uint, f: F) -> DecodeResult<T> where
F: FnOnce(&mut Decoder) -> DecodeResult<T>,
{
debug!("read_seq_elt(idx={})", idx);
f(self)
}
fn read_map<T, F>(&mut self, f: F) -> DecodeResult<T> where
F: FnOnce(&mut Decoder, uint) -> DecodeResult<T>,
{
debug!("read_map()");
let obj = try!(expect!(self.pop(), Object));
let len = obj.len();
for (key, value) in obj.into_iter() {
@ -2269,17 +2250,15 @@ impl ::Decoder<DecoderError> for Decoder {
f(self, len)
}
fn read_map_elt_key<T, F>(&mut self, idx: uint, f: F) -> DecodeResult<T> where
fn read_map_elt_key<T, F>(&mut self, _idx: uint, f: F) -> DecodeResult<T> where
F: FnOnce(&mut Decoder) -> DecodeResult<T>,
{
debug!("read_map_elt_key(idx={})", idx);
f(self)
}
fn read_map_elt_val<T, F>(&mut self, idx: uint, f: F) -> DecodeResult<T> where
fn read_map_elt_val<T, F>(&mut self, _idx: uint, f: F) -> DecodeResult<T> where
F: FnOnce(&mut Decoder) -> DecodeResult<T>,
{
debug!("read_map_elt_val(idx={})", idx);
f(self)
}
@ -2441,9 +2420,7 @@ mod tests {
use super::ParserError::*;
use super::DecoderError::*;
use super::JsonEvent::*;
use super::ParserState::*;
use super::StackElement::*;
use super::InternalStackElement::*;
use super::{PrettyEncoder, Json, from_str, DecodeResult, DecoderError, JsonEvent, Parser,
StackElement, Stack, Encoder, Decoder};
use std::{i64, u64, f32, f64, io};
@ -2678,8 +2655,6 @@ mod tests {
}
fn with_str_writer<F>(f: F) -> string::String where F: FnOnce(&mut io::Writer){
use std::str;
let mut m = Vec::new();
f(&mut m as &mut io::Writer);
string::String::from_utf8(m).unwrap()
@ -2756,9 +2731,9 @@ mod tests {
fn test_write_char() {
check_encoder_for_simple!('a', "\"a\"");
check_encoder_for_simple!('\t', "\"\\t\"");
check_encoder_for_simple!('\u00a0', "\"\u00a0\"");
check_encoder_for_simple!('\uabcd', "\"\uabcd\"");
check_encoder_for_simple!('\U0010ffff', "\"\U0010ffff\"");
check_encoder_for_simple!('\u{00a0}', "\"\u{00a0}\"");
check_encoder_for_simple!('\u{abcd}', "\"\u{abcd}\"");
check_encoder_for_simple!('\u{10ffff}', "\"\u{10ffff}\"");
}
#[test]

View File

@ -24,9 +24,9 @@
/// ```{.rust}
/// bitflags! {
/// flags Flags: u32 {
/// const FLAG_A = 0x00000001,
/// const FLAG_B = 0x00000010,
/// const FLAG_C = 0x00000100,
/// const FLAG_A = 0b00000001,
/// const FLAG_B = 0b00000010,
/// const FLAG_C = 0b00000100,
/// const FLAG_ABC = FLAG_A.bits
/// | FLAG_B.bits
/// | FLAG_C.bits,
@ -50,8 +50,8 @@
///
/// bitflags! {
/// flags Flags: u32 {
/// const FLAG_A = 0x00000001,
/// const FLAG_B = 0x00000010,
/// const FLAG_A = 0b00000001,
/// const FLAG_B = 0b00000010,
/// }
/// }
///
@ -205,17 +205,6 @@ macro_rules! bitflags {
}
}
// NOTE(stage0): Remove impl after a snapshot
#[cfg(stage0)]
impl BitOr<$BitFlags, $BitFlags> for $BitFlags {
/// Returns the union of the two sets of flags.
#[inline]
fn bitor(&self, other: &$BitFlags) -> $BitFlags {
$BitFlags { bits: self.bits | other.bits }
}
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
impl BitOr<$BitFlags, $BitFlags> for $BitFlags {
/// Returns the union of the two sets of flags.
#[inline]
@ -224,17 +213,6 @@ macro_rules! bitflags {
}
}
// NOTE(stage0): Remove impl after a snapshot
#[cfg(stage0)]
impl BitXor<$BitFlags, $BitFlags> for $BitFlags {
/// Returns the left flags, but with all the right flags toggled.
#[inline]
fn bitxor(&self, other: &$BitFlags) -> $BitFlags {
$BitFlags { bits: self.bits ^ other.bits }
}
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
impl BitXor<$BitFlags, $BitFlags> for $BitFlags {
/// Returns the left flags, but with all the right flags toggled.
#[inline]
@ -243,17 +221,6 @@ macro_rules! bitflags {
}
}
// NOTE(stage0): Remove impl after a snapshot
#[cfg(stage0)]
impl BitAnd<$BitFlags, $BitFlags> for $BitFlags {
/// Returns the intersection between the two sets of flags.
#[inline]
fn bitand(&self, other: &$BitFlags) -> $BitFlags {
$BitFlags { bits: self.bits & other.bits }
}
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
impl BitAnd<$BitFlags, $BitFlags> for $BitFlags {
/// Returns the intersection between the two sets of flags.
#[inline]
@ -262,17 +229,6 @@ macro_rules! bitflags {
}
}
// NOTE(stage0): Remove impl after a snapshot
#[cfg(stage0)]
impl Sub<$BitFlags, $BitFlags> for $BitFlags {
/// Returns the set difference of the two sets of flags.
#[inline]
fn sub(&self, other: &$BitFlags) -> $BitFlags {
$BitFlags { bits: self.bits & !other.bits }
}
}
#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot
impl Sub<$BitFlags, $BitFlags> for $BitFlags {
/// Returns the set difference of the two sets of flags.
#[inline]
@ -325,10 +281,10 @@ mod tests {
#[doc = "> "]
#[doc = "> - Richard Feynman"]
flags Flags: u32 {
const FlagA = 0x00000001,
const FlagA = 0b00000001,
#[doc = "<pcwalton> macros are way better at generating code than trans is"]
const FlagB = 0x00000010,
const FlagC = 0x00000100,
const FlagB = 0b00000010,
const FlagC = 0b00000100,
#[doc = "* cmr bed"]
#[doc = "* strcat table"]
#[doc = "<strcat> wait what?"]
@ -346,21 +302,21 @@ mod tests {
#[test]
fn test_bits(){
assert_eq!(Flags::empty().bits(), 0x00000000);
assert_eq!(FlagA.bits(), 0x00000001);
assert_eq!(FlagABC.bits(), 0x00000111);
assert_eq!(Flags::empty().bits(), 0b00000000);
assert_eq!(FlagA.bits(), 0b00000001);
assert_eq!(FlagABC.bits(), 0b00000111);
assert_eq!(AnotherSetOfFlags::empty().bits(), 0x00);
assert_eq!(AnotherSetOfFlags::empty().bits(), 0b00);
assert_eq!(AnotherFlag.bits(), !0_i8);
}
#[test]
fn test_from_bits() {
assert!(Flags::from_bits(0) == Some(Flags::empty()));
assert!(Flags::from_bits(0x1) == Some(FlagA));
assert!(Flags::from_bits(0x10) == Some(FlagB));
assert!(Flags::from_bits(0x11) == Some(FlagA | FlagB));
assert!(Flags::from_bits(0x1000) == None);
assert!(Flags::from_bits(0b1) == Some(FlagA));
assert!(Flags::from_bits(0b10) == Some(FlagB));
assert!(Flags::from_bits(0b11) == Some(FlagA | FlagB));
assert!(Flags::from_bits(0b1000) == None);
assert!(AnotherSetOfFlags::from_bits(!0_i8) == Some(AnotherFlag));
}
@ -368,11 +324,11 @@ mod tests {
#[test]
fn test_from_bits_truncate() {
assert!(Flags::from_bits_truncate(0) == Flags::empty());
assert!(Flags::from_bits_truncate(0x1) == FlagA);
assert!(Flags::from_bits_truncate(0x10) == FlagB);
assert!(Flags::from_bits_truncate(0x11) == (FlagA | FlagB));
assert!(Flags::from_bits_truncate(0x1000) == Flags::empty());
assert!(Flags::from_bits_truncate(0x1001) == FlagA);
assert!(Flags::from_bits_truncate(0b1) == FlagA);
assert!(Flags::from_bits_truncate(0b10) == FlagB);
assert!(Flags::from_bits_truncate(0b11) == (FlagA | FlagB));
assert!(Flags::from_bits_truncate(0b1000) == Flags::empty());
assert!(Flags::from_bits_truncate(0b1001) == FlagA);
assert!(AnotherSetOfFlags::from_bits_truncate(0_i8) == AnotherSetOfFlags::empty());
}

View File

@ -11,6 +11,5 @@
//! The boolean type
#![doc(primitive = "bool")]
#![unstable = "this module is purely for documentation and it will likely be \
removed from the public api"]
#![stable]

View File

@ -10,7 +10,7 @@
//
// ignore-lexer-test FIXME #15883
pub use self::Entry::*;
use self::Entry::*;
use self::SearchResult::*;
use self::VacantEntryState::*;
@ -30,18 +30,20 @@ use option::Option::{Some, None};
use result::Result;
use result::Result::{Ok, Err};
use super::table;
use super::table::{
mod,
Bucket,
Empty,
EmptyBucket,
Full,
FullBucket,
FullBucketImm,
FullBucketMut,
RawTable,
SafeHash
};
use super::table::BucketState::{
Empty,
Full,
};
const INITIAL_LOG2_CAP: uint = 5;
pub const INITIAL_CAPACITY: uint = 1 << INITIAL_LOG2_CAP; // 2^5
@ -379,7 +381,7 @@ fn robin_hood<'a, K: 'a, V: 'a>(mut bucket: FullBucketMut<'a, K, V>,
assert!(probe.index() != idx_end);
let full_bucket = match probe.peek() {
table::Empty(bucket) => {
Empty(bucket) => {
// Found a hole!
let b = bucket.put(old_hash, old_key, old_val);
// Now that it's stolen, just read the value's pointer
@ -390,7 +392,7 @@ fn robin_hood<'a, K: 'a, V: 'a>(mut bucket: FullBucketMut<'a, K, V>,
.into_mut_refs()
.1;
},
table::Full(bucket) => bucket
Full(bucket) => bucket
};
let probe_ib = full_bucket.index() - full_bucket.distance();
@ -1470,7 +1472,7 @@ mod test_map {
use prelude::*;
use super::HashMap;
use super::{Occupied, Vacant};
use super::Entry::{Occupied, Vacant};
use hash;
use iter::{range_inclusive, range_step_inclusive};
use cell::RefCell;

View File

@ -17,7 +17,7 @@ use default::Default;
use fmt::Show;
use fmt;
use hash::{Hash, Hasher, RandomSipHasher};
use iter::{Iterator, IteratorExt, FromIterator, Map, FilterMap, Chain, Repeat, Zip, Extend, repeat};
use iter::{Iterator, IteratorExt, FromIterator, Map, Chain, Extend};
use option::Option::{Some, None, mod};
use result::Result::{Ok, Err};
@ -250,8 +250,8 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
/// }
/// ```
#[unstable = "matches collection reform specification, waiting for dust to settle"]
pub fn iter<'a>(&'a self) -> SetItems<'a, T> {
SetItems { iter: self.map.keys() }
pub fn iter<'a>(&'a self) -> Iter<'a, T> {
Iter { iter: self.map.keys() }
}
/// Creates a consuming iterator, that is, one that moves each value out
@ -275,10 +275,10 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
/// }
/// ```
#[unstable = "matches collection reform specification, waiting for dust to settle"]
pub fn into_iter(self) -> SetMoveItems<T> {
pub fn into_iter(self) -> IntoIter<T> {
fn first<A, B>((a, _): (A, B)) -> A { a }
SetMoveItems { iter: self.map.into_iter().map(first) }
IntoIter { iter: self.map.into_iter().map(first) }
}
/// Visit the values representing the difference.
@ -304,14 +304,11 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
/// assert_eq!(diff, [4i].iter().map(|&x| x).collect());
/// ```
#[unstable = "matches collection reform specification, waiting for dust to settle"]
pub fn difference<'a>(&'a self, other: &'a HashSet<T, H>) -> SetAlgebraItems<'a, T, H> {
fn filter<'a, T, S, H>((other, elt): (&HashSet<T, H>, &'a T)) -> Option<&'a T> where
T: Eq + Hash<S>, H: Hasher<S>
{
if !other.contains(elt) { Some(elt) } else { None }
pub fn difference<'a>(&'a self, other: &'a HashSet<T, H>) -> Difference<'a, T, H> {
Difference {
iter: self.iter(),
other: other,
}
SetAlgebraItems { iter: repeat(other).zip(self.iter()).filter_map(filter) }
}
/// Visit the values representing the symmetric difference.
@ -336,8 +333,8 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
/// ```
#[unstable = "matches collection reform specification, waiting for dust to settle"]
pub fn symmetric_difference<'a>(&'a self, other: &'a HashSet<T, H>)
-> SymDifferenceItems<'a, T, H> {
SymDifferenceItems { iter: self.difference(other).chain(other.difference(self)) }
-> SymmetricDifference<'a, T, H> {
SymmetricDifference { iter: self.difference(other).chain(other.difference(self)) }
}
/// Visit the values representing the intersection.
@ -358,14 +355,11 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
/// assert_eq!(diff, [2i, 3].iter().map(|&x| x).collect());
/// ```
#[unstable = "matches collection reform specification, waiting for dust to settle"]
pub fn intersection<'a>(&'a self, other: &'a HashSet<T, H>) -> SetAlgebraItems<'a, T, H> {
fn filter<'a, T, S, H>((other, elt): (&HashSet<T, H>, &'a T)) -> Option<&'a T> where
T: Eq + Hash<S>, H: Hasher<S>
{
if other.contains(elt) { Some(elt) } else { None }
pub fn intersection<'a>(&'a self, other: &'a HashSet<T, H>) -> Intersection<'a, T, H> {
Intersection {
iter: self.iter(),
other: other,
}
SetAlgebraItems { iter: repeat(other).zip(self.iter()).filter_map(filter) }
}
/// Visit the values representing the union.
@ -386,8 +380,8 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
/// assert_eq!(diff, [1i, 2, 3, 4].iter().map(|&x| x).collect());
/// ```
#[unstable = "matches collection reform specification, waiting for dust to settle"]
pub fn union<'a>(&'a self, other: &'a HashSet<T, H>) -> UnionItems<'a, T, H> {
UnionItems { iter: self.iter().chain(other.difference(self)) }
pub fn union<'a>(&'a self, other: &'a HashSet<T, H>) -> Union<'a, T, H> {
Union { iter: self.iter().chain(other.difference(self)) }
}
/// Return the number of elements in the set
@ -625,12 +619,12 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S> + Default> Default for HashSet<T, H> {
}
/// HashSet iterator
pub struct SetItems<'a, K: 'a> {
pub struct Iter<'a, K: 'a> {
iter: Keys<'a, K, ()>
}
/// HashSet move iterator
pub struct SetMoveItems<K> {
pub struct IntoIter<K> {
iter: Map<(K, ()), K, MoveEntries<K, ()>, fn((K, ())) -> K>
}
@ -639,34 +633,38 @@ pub struct Drain<'a, K: 'a> {
iter: Map<(K, ()), K, map::Drain<'a, K, ()>, fn((K, ())) -> K>,
}
// `Repeat` is used to feed the filter closure an explicit capture
// of a reference to the other set
/// Set operations iterator, used directly for intersection and difference
pub struct SetAlgebraItems<'a, T: 'a, H: 'a> {
iter: FilterMap<
(&'a HashSet<T, H>, &'a T),
&'a T,
Zip<Repeat<&'a HashSet<T, H>>, SetItems<'a, T>>,
for<'b> fn((&HashSet<T, H>, &'b T)) -> Option<&'b T>,
>
/// Intersection iterator
pub struct Intersection<'a, T: 'a, H: 'a> {
// iterator of the first set
iter: Iter<'a, T>,
// the second set
other: &'a HashSet<T, H>,
}
/// Difference iterator
pub struct Difference<'a, T: 'a, H: 'a> {
// iterator of the first set
iter: Iter<'a, T>,
// the second set
other: &'a HashSet<T, H>,
}
/// Symmetric difference iterator.
pub struct SymDifferenceItems<'a, T: 'a, H: 'a> {
iter: Chain<SetAlgebraItems<'a, T, H>, SetAlgebraItems<'a, T, H>>
pub struct SymmetricDifference<'a, T: 'a, H: 'a> {
iter: Chain<Difference<'a, T, H>, Difference<'a, T, H>>
}
/// Set union iterator.
pub struct UnionItems<'a, T: 'a, H: 'a> {
iter: Chain<SetItems<'a, T>, SetAlgebraItems<'a, T, H>>
pub struct Union<'a, T: 'a, H: 'a> {
iter: Chain<Iter<'a, T>, Difference<'a, T, H>>
}
impl<'a, K> Iterator<&'a K> for SetItems<'a, K> {
impl<'a, K> Iterator<&'a K> for Iter<'a, K> {
fn next(&mut self) -> Option<&'a K> { self.iter.next() }
fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
}
impl<K> Iterator<K> for SetMoveItems<K> {
impl<K> Iterator<K> for IntoIter<K> {
fn next(&mut self) -> Option<K> { self.iter.next() }
fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
}
@ -676,17 +674,56 @@ impl<'a, K: 'a> Iterator<K> for Drain<'a, K> {
fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
}
impl<'a, T, H> Iterator<&'a T> for SetAlgebraItems<'a, T, H> {
impl<'a, T, S, H> Iterator<&'a T> for Intersection<'a, T, H>
where T: Eq + Hash<S>, H: Hasher<S>
{
fn next(&mut self) -> Option<&'a T> {
loop {
match self.iter.next() {
None => return None,
Some(elt) => if self.other.contains(elt) {
return Some(elt)
},
}
}
}
fn size_hint(&self) -> (uint, Option<uint>) {
let (_, upper) = self.iter.size_hint();
(0, upper)
}
}
impl<'a, T, S, H> Iterator<&'a T> for Difference<'a, T, H>
where T: Eq + Hash<S>, H: Hasher<S>
{
fn next(&mut self) -> Option<&'a T> {
loop {
match self.iter.next() {
None => return None,
Some(elt) => if !self.other.contains(elt) {
return Some(elt)
},
}
}
}
fn size_hint(&self) -> (uint, Option<uint>) {
let (_, upper) = self.iter.size_hint();
(0, upper)
}
}
impl<'a, T, S, H> Iterator<&'a T> for SymmetricDifference<'a, T, H>
where T: Eq + Hash<S>, H: Hasher<S>
{
fn next(&mut self) -> Option<&'a T> { self.iter.next() }
fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
}
impl<'a, T, H> Iterator<&'a T> for SymDifferenceItems<'a, T, H> {
fn next(&mut self) -> Option<&'a T> { self.iter.next() }
fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
}
impl<'a, T, H> Iterator<&'a T> for UnionItems<'a, T, H> {
impl<'a, T, S, H> Iterator<&'a T> for Union<'a, T, H>
where T: Eq + Hash<S>, H: Hasher<S>
{
fn next(&mut self) -> Option<&'a T> { self.iter.next() }
fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
}

View File

@ -10,7 +10,7 @@
//
// ignore-lexer-test FIXME #15883
pub use self::BucketState::*;
use self::BucketState::*;
use clone::Clone;
use cmp;

View File

@ -628,7 +628,7 @@ impl<T: Send> Sender<T> {
}
}
#[unstable]
#[stable]
impl<T: Send> Clone for Sender<T> {
fn clone(&self) -> Sender<T> {
let (packet, sleeper, guard) = match *unsafe { self.inner() } {
@ -756,7 +756,7 @@ impl<T: Send> SyncSender<T> {
}
}
#[unstable]
#[stable]
impl<T: Send> Clone for SyncSender<T> {
fn clone(&self) -> SyncSender<T> {
unsafe { (*self.inner.get()).clone_chan(); }

View File

@ -200,7 +200,7 @@ mod test {
target_os = "freebsd",
target_os = "dragonfly"))]
pub mod dl {
pub use self::Rtld::*;
use self::Rtld::*;
use prelude::*;
use c_str::CString;

View File

@ -132,6 +132,7 @@ impl ChanWriter {
}
}
#[stable]
impl Clone for ChanWriter {
fn clone(&self) -> ChanWriter {
ChanWriter { tx: self.tx.clone() }

View File

@ -104,7 +104,7 @@ pub struct StdinReader {
inner: Arc<Mutex<BufferedReader<StdReader>>>,
}
/// A guard for exlusive access to `StdinReader`'s internal `BufferedReader`.
/// A guard for exclusive access to `StdinReader`'s internal `BufferedReader`.
pub struct StdinReaderGuard<'a> {
inner: MutexGuard<'a, BufferedReader<StdReader>>,
}

View File

@ -23,6 +23,56 @@ use sync::atomic;
/// A wrapper for a path to temporary directory implementing automatic
/// scope-based deletion.
///
/// # Examples
///
/// ```no_run
/// use std::io::TempDir;
///
/// {
/// // create a temporary directory
/// let tmpdir = match TempDir::new("mysuffix") {
/// Ok(dir) => dir,
/// Err(e) => panic!("couldn't create temporary directory: {}", e)
/// };
///
/// // get the path of the temporary directory without affecting the wrapper
/// let tmppath = tmpdir.path();
///
/// println!("The path of temporary directory is {}", tmppath.display());
///
/// // the temporary directory is automatically removed when tmpdir goes
/// // out of scope at the end of the block
/// }
/// {
/// // create a temporary directory, this time using a custom path
/// let tmpdir = match TempDir::new_in(&Path::new("/tmp/best/custom/path"), "mysuffix") {
/// Ok(dir) => dir,
/// Err(e) => panic!("couldn't create temporary directory: {}", e)
/// };
///
/// // get the path of the temporary directory and disable automatic deletion in the wrapper
/// let tmppath = tmpdir.into_inner();
///
/// println!("The path of the not-so-temporary directory is {}", tmppath.display());
///
/// // the temporary directory is not removed here
/// // because the directory is detached from the wrapper
/// }
/// {
/// // create a temporary directory
/// let tmpdir = match TempDir::new("mysuffix") {
/// Ok(dir) => dir,
/// Err(e) => panic!("couldn't create temporary directory: {}", e)
/// };
///
/// // close the temporary directory manually and check the result
/// match tmpdir.close() {
/// Ok(_) => println!("success!"),
/// Err(e) => panic!("couldn't remove temporary directory: {}", e)
/// };
/// }
/// ```
pub struct TempDir {
path: Option<Path>,
disarmed: bool

View File

@ -135,7 +135,6 @@ extern crate libc;
// NB: These reexports are in the order they should be listed in rustdoc
pub use core::any;
pub use core::bool;
pub use core::borrow;
pub use core::cell;
pub use core::clone;
@ -150,10 +149,6 @@ pub use core::mem;
pub use core::ptr;
pub use core::raw;
pub use core::simd;
pub use core::tuple;
// FIXME #15320: primitive documentation needs top-level modules, this
// should be `std::tuple::unit`.
pub use core::unit;
pub use core::result;
pub use core::option;
@ -243,6 +238,12 @@ pub mod comm;
pub mod rt;
mod failure;
// Documentation for primitive types
mod bool;
mod unit;
mod tuple;
// A curious inner-module that's not exported that contains the binding
// 'std' so that macro-expanded references to std::error and such
// can be resolved within libstd.

View File

@ -21,6 +21,9 @@ use intrinsics;
use libc::c_int;
use num::{Float, FloatMath};
use num::strconv;
use num::strconv::ExponentFormat::{ExpNone, ExpDec};
use num::strconv::SignificantDigits::{DigAll, DigMax, DigExact};
use num::strconv::SignFormat::SignNeg;
pub use core::f32::{RADIX, MANTISSA_DIGITS, DIGITS, EPSILON, MIN_VALUE};
pub use core::f32::{MIN_POS_VALUE, MAX_VALUE, MIN_EXP, MAX_EXP, MIN_10_EXP};
@ -252,7 +255,7 @@ impl FloatMath for f32 {
#[experimental = "may be removed or relocated"]
pub fn to_string(num: f32) -> String {
let (r, _) = strconv::float_to_str_common(
num, 10u, true, strconv::SignNeg, strconv::DigAll, strconv::ExpNone, false);
num, 10u, true, SignNeg, DigAll, ExpNone, false);
r
}
@ -265,7 +268,7 @@ pub fn to_string(num: f32) -> String {
#[experimental = "may be removed or relocated"]
pub fn to_str_hex(num: f32) -> String {
let (r, _) = strconv::float_to_str_common(
num, 16u, true, strconv::SignNeg, strconv::DigAll, strconv::ExpNone, false);
num, 16u, true, SignNeg, DigAll, ExpNone, false);
r
}
@ -279,8 +282,7 @@ pub fn to_str_hex(num: f32) -> String {
#[inline]
#[experimental = "may be removed or relocated"]
pub fn to_str_radix_special(num: f32, rdx: uint) -> (String, bool) {
strconv::float_to_str_common(num, rdx, true,
strconv::SignNeg, strconv::DigAll, strconv::ExpNone, false)
strconv::float_to_str_common(num, rdx, true, SignNeg, DigAll, ExpNone, false)
}
/// Converts a float to a string with exactly the number of
@ -294,7 +296,7 @@ pub fn to_str_radix_special(num: f32, rdx: uint) -> (String, bool) {
#[experimental = "may be removed or relocated"]
pub fn to_str_exact(num: f32, dig: uint) -> String {
let (r, _) = strconv::float_to_str_common(
num, 10u, true, strconv::SignNeg, strconv::DigExact(dig), strconv::ExpNone, false);
num, 10u, true, SignNeg, DigExact(dig), ExpNone, false);
r
}
@ -309,7 +311,7 @@ pub fn to_str_exact(num: f32, dig: uint) -> String {
#[experimental = "may be removed or relocated"]
pub fn to_str_digits(num: f32, dig: uint) -> String {
let (r, _) = strconv::float_to_str_common(
num, 10u, true, strconv::SignNeg, strconv::DigMax(dig), strconv::ExpNone, false);
num, 10u, true, SignNeg, DigMax(dig), ExpNone, false);
r
}
@ -325,7 +327,7 @@ pub fn to_str_digits(num: f32, dig: uint) -> String {
#[experimental = "may be removed or relocated"]
pub fn to_str_exp_exact(num: f32, dig: uint, upper: bool) -> String {
let (r, _) = strconv::float_to_str_common(
num, 10u, true, strconv::SignNeg, strconv::DigExact(dig), strconv::ExpDec, upper);
num, 10u, true, SignNeg, DigExact(dig), ExpDec, upper);
r
}
@ -341,7 +343,7 @@ pub fn to_str_exp_exact(num: f32, dig: uint, upper: bool) -> String {
#[experimental = "may be removed or relocated"]
pub fn to_str_exp_digits(num: f32, dig: uint, upper: bool) -> String {
let (r, _) = strconv::float_to_str_common(
num, 10u, true, strconv::SignNeg, strconv::DigMax(dig), strconv::ExpDec, upper);
num, 10u, true, SignNeg, DigMax(dig), ExpDec, upper);
r
}

View File

@ -20,6 +20,9 @@ use intrinsics;
use libc::c_int;
use num::{Float, FloatMath};
use num::strconv;
use num::strconv::ExponentFormat::{ExpNone, ExpDec};
use num::strconv::SignificantDigits::{DigAll, DigMax, DigExact};
use num::strconv::SignFormat::SignNeg;
pub use core::f64::{RADIX, MANTISSA_DIGITS, DIGITS, EPSILON, MIN_VALUE};
pub use core::f64::{MIN_POS_VALUE, MAX_VALUE, MIN_EXP, MAX_EXP, MIN_10_EXP};
@ -260,7 +263,7 @@ impl FloatMath for f64 {
#[experimental = "may be removed or relocated"]
pub fn to_string(num: f64) -> String {
let (r, _) = strconv::float_to_str_common(
num, 10u, true, strconv::SignNeg, strconv::DigAll, strconv::ExpNone, false);
num, 10u, true, SignNeg, DigAll, ExpNone, false);
r
}
@ -273,7 +276,7 @@ pub fn to_string(num: f64) -> String {
#[experimental = "may be removed or relocated"]
pub fn to_str_hex(num: f64) -> String {
let (r, _) = strconv::float_to_str_common(
num, 16u, true, strconv::SignNeg, strconv::DigAll, strconv::ExpNone, false);
num, 16u, true, SignNeg, DigAll, ExpNone, false);
r
}
@ -287,8 +290,7 @@ pub fn to_str_hex(num: f64) -> String {
#[inline]
#[experimental = "may be removed or relocated"]
pub fn to_str_radix_special(num: f64, rdx: uint) -> (String, bool) {
strconv::float_to_str_common(num, rdx, true,
strconv::SignNeg, strconv::DigAll, strconv::ExpNone, false)
strconv::float_to_str_common(num, rdx, true, SignNeg, DigAll, ExpNone, false)
}
/// Converts a float to a string with exactly the number of
@ -302,7 +304,7 @@ pub fn to_str_radix_special(num: f64, rdx: uint) -> (String, bool) {
#[experimental = "may be removed or relocated"]
pub fn to_str_exact(num: f64, dig: uint) -> String {
let (r, _) = strconv::float_to_str_common(
num, 10u, true, strconv::SignNeg, strconv::DigExact(dig), strconv::ExpNone, false);
num, 10u, true, SignNeg, DigExact(dig), ExpNone, false);
r
}
@ -317,7 +319,7 @@ pub fn to_str_exact(num: f64, dig: uint) -> String {
#[experimental = "may be removed or relocated"]
pub fn to_str_digits(num: f64, dig: uint) -> String {
let (r, _) = strconv::float_to_str_common(
num, 10u, true, strconv::SignNeg, strconv::DigMax(dig), strconv::ExpNone, false);
num, 10u, true, SignNeg, DigMax(dig), ExpNone, false);
r
}
@ -333,7 +335,7 @@ pub fn to_str_digits(num: f64, dig: uint) -> String {
#[experimental = "may be removed or relocated"]
pub fn to_str_exp_exact(num: f64, dig: uint, upper: bool) -> String {
let (r, _) = strconv::float_to_str_common(
num, 10u, true, strconv::SignNeg, strconv::DigExact(dig), strconv::ExpDec, upper);
num, 10u, true, SignNeg, DigExact(dig), ExpDec, upper);
r
}
@ -349,7 +351,7 @@ pub fn to_str_exp_exact(num: f64, dig: uint, upper: bool) -> String {
#[experimental = "may be removed or relocated"]
pub fn to_str_exp_digits(num: f64, dig: uint, upper: bool) -> String {
let (r, _) = strconv::float_to_str_common(
num, 10u, true, strconv::SignNeg, strconv::DigMax(dig), strconv::ExpDec, upper);
num, 10u, true, SignNeg, DigMax(dig), ExpDec, upper);
r
}

View File

@ -10,7 +10,7 @@
//! Operations and constants for architecture-sized signed integers (`int` type)
#![unstable]
#![stable]
#![doc(primitive = "int")]
pub use core::int::{BITS, BYTES, MIN, MAX};

View File

@ -12,9 +12,9 @@
#![allow(missing_docs)]
pub use self::ExponentFormat::*;
pub use self::SignificantDigits::*;
pub use self::SignFormat::*;
use self::ExponentFormat::*;
use self::SignificantDigits::*;
use self::SignFormat::*;
use char::{mod, Char};
use num::{mod, Int, Float, FPNaN, FPInfinite, ToPrimitive};

View File

@ -10,7 +10,7 @@
//! Operations and constants for architecture-sized unsigned integers (`uint` type)
#![unstable]
#![stable]
#![doc(primitive = "uint")]
pub use core::uint::{BITS, BYTES, MIN, MAX};

View File

@ -28,9 +28,9 @@
#![allow(non_snake_case)]
#![allow(unused_imports)]
pub use self::MemoryMapKind::*;
pub use self::MapOption::*;
pub use self::MapError::*;
use self::MemoryMapKind::*;
use self::MapOption::*;
use self::MapError::*;
use clone::Clone;
use error::{FromError, Error};
@ -1617,8 +1617,8 @@ mod tests {
use result::Result::{Ok, Err};
let chunk = match os::MemoryMap::new(16, &[
os::MapReadable,
os::MapWritable
os::MapOption::MapReadable,
os::MapOption::MapWritable
]) {
Ok(chunk) => chunk,
Err(msg) => panic!("{}", msg)
@ -1660,10 +1660,10 @@ mod tests {
file.write_u8(0);
let chunk = MemoryMap::new(size / 2, &[
MapReadable,
MapWritable,
MapFd(get_fd(&file)),
MapOffset(size / 2)
MapOption::MapReadable,
MapOption::MapWritable,
MapOption::MapFd(get_fd(&file)),
MapOption::MapOffset(size / 2)
]).unwrap();
assert!(chunk.len > 0);

View File

@ -12,7 +12,7 @@
//! Windows file path handling
pub use self::PathPrefix::*;
use self::PathPrefix::*;
use ascii::AsciiCast;
use c_str::{CString, ToCStr};
@ -1117,6 +1117,7 @@ fn prefix_len(p: Option<PathPrefix>) -> uint {
mod tests {
use prelude::*;
use super::*;
use super::PathPrefix::*;
use super::parse_prefix;
macro_rules! t {

View File

@ -81,9 +81,9 @@
#[doc(no_inline)] pub use io::{Buffer, Writer, Reader, Seek, BufferPrelude};
#[doc(no_inline)] pub use str::{Str, StrVector, StrPrelude};
#[doc(no_inline)] pub use str::{StrAllocating, UnicodeStrPrelude};
#[doc(no_inline)] pub use tuple::{Tuple1, Tuple2, Tuple3, Tuple4};
#[doc(no_inline)] pub use tuple::{Tuple5, Tuple6, Tuple7, Tuple8};
#[doc(no_inline)] pub use tuple::{Tuple9, Tuple10, Tuple11, Tuple12};
#[doc(no_inline)] pub use core::prelude::{Tuple1, Tuple2, Tuple3, Tuple4};
#[doc(no_inline)] pub use core::prelude::{Tuple5, Tuple6, Tuple7, Tuple8};
#[doc(no_inline)] pub use core::prelude::{Tuple9, Tuple10, Tuple11, Tuple12};
#[doc(no_inline)] pub use slice::AsSlice;
#[doc(no_inline)] pub use slice::{VectorVector, PartialEqSliceExt};
#[doc(no_inline)] pub use slice::{CloneSliceExt, OrdSliceExt, SliceExt};

View File

@ -45,7 +45,7 @@
//! so the "quality" of `/dev/random` is not better than `/dev/urandom` in most cases.
//! However, this means that `/dev/urandom` can yield somewhat predictable randomness
//! if the entropy pool is very small, such as immediately after first booting.
//! Linux 3,17 added `getrandom(2)` system call which solves the issue: it blocks if entropy
//! Linux 3.17 added the `getrandom(2)` system call which solves the issue: it blocks if entropy
//! pool is not initialized yet, but it does not block once initialized.
//! `OsRng` tries to use `getrandom(2)` if available, and use `/dev/urandom` fallback if not.
//! If an application does not have `getrandom` and likely to be run soon after first booting,
@ -126,7 +126,7 @@
//! > Is it to your advantage to switch your choice?
//!
//! The rather unintuitive answer is that you will have a 2/3 chance of winning if
//! you switch and a 1/3 chance of winning of you don't, so it's better to switch.
//! you switch and a 1/3 chance of winning if you don't, so it's better to switch.
//!
//! This program will simulate the game show and with large enough simulation steps
//! it will indeed confirm that it is better to switch.

View File

@ -170,7 +170,6 @@ mod imp {
extern crate libc;
use io::{IoResult};
use kinds::marker;
use mem;
use os;
use rand::Rng;

View File

@ -44,12 +44,10 @@ pub fn clone() -> Option<Vec<Vec<u8>>> { imp::clone() }
target_os = "freebsd",
target_os = "dragonfly"))]
mod imp {
use core::prelude::*;
use prelude::*;
use boxed::Box;
use vec::Vec;
use string::String;
use mem;
use slice;
use sync::{StaticMutex, MUTEX_INIT};
@ -98,7 +96,12 @@ mod imp {
unsafe fn load_argc_and_argv(argc: int, argv: *const *const u8) -> Vec<Vec<u8>> {
Vec::from_fn(argc as uint, |i| {
String::from_raw_buf(*argv.offset(i as int)).into_bytes()
let arg = *argv.offset(i as int);
let mut len = 0u;
while *arg.offset(len as int) != 0 {
len += 1u;
}
slice::from_raw_buf(&arg, len).to_vec()
})
}

View File

@ -8,8 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
pub use self::SocketStatus::*;
pub use self::InAddr::*;
use self::SocketStatus::*;
use self::InAddr::*;
use alloc::arc::Arc;
use libc::{mod, c_char, c_int};

View File

@ -105,7 +105,7 @@ use sys_common::backtrace::*;
#[cfg(all(target_os = "ios", target_arch = "arm"))]
#[inline(never)]
pub fn write(w: &mut Writer) -> IoResult<()> {
use iter::{Iterator, range};
use iter::{IteratorExt, range};
use result;
use slice::SliceExt;
@ -117,7 +117,7 @@ pub fn write(w: &mut Writer) -> IoResult<()> {
// while it doesn't requires lock for work as everything is
// local, it still displays much nicer backtraces when a
// couple of tasks panic simultaneously
static LOCK: StaticNativeMutex = NATIVE_MUTEX_INIT;
static LOCK: StaticMutex = MUTEX_INIT;
let _g = unsafe { LOCK.lock() };
try!(writeln!(w, "stack backtrace:"));

View File

@ -19,6 +19,7 @@ use prelude::*;
use sys::{mod, timer, retry, c, set_nonblocking, wouldblock};
use sys::fs::{fd_t, FileDesc};
use sys_common::net::*;
use sys_common::net::SocketStatus::*;
use sys_common::{eof, mkerr_libc};
fn unix_socket(ty: libc::c_int) -> IoResult<fd_t> {

View File

@ -21,6 +21,7 @@ use sys::{set_nonblocking, wouldblock};
use sys;
use sys_common;
use sys_common::net;
use sys_common::net::SocketStatus::Readable;
pub use sys_common::net::TcpStream;
@ -124,7 +125,7 @@ impl TcpAcceptor {
fd => return Ok(TcpStream::new(fd as sock_t)),
}
try!(net::await(&[self.fd(), self.inner.reader.fd()],
deadline, net::Readable));
deadline, Readable));
}
Err(sys_common::eof())

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