auto merge of #20104 : alexcrichton/rust/rollup, r=alexcrichton
This commit is contained in:
commit
34d6800092
34
mk/docs.mk
34
mk/docs.mk
@ -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
|
||||
|
17
mk/tests.mk
17
mk/tests.mk
@ -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))
|
||||
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
||||
|
155
src/doc/guide.md
155
src/doc/guide.md
@ -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!
|
||||
|
@ -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
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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> {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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>>())
|
||||
|
@ -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]
|
||||
|
@ -851,6 +851,7 @@ impl Extend<bool> for Bitv {
|
||||
}
|
||||
}
|
||||
|
||||
#[stable]
|
||||
impl Clone for Bitv {
|
||||
#[inline]
|
||||
fn clone(&self) -> Bitv {
|
||||
|
@ -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() {
|
||||
|
@ -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>`.
|
||||
///
|
||||
|
@ -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()
|
||||
|
@ -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}
|
||||
|
@ -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()
|
||||
|
@ -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() {
|
||||
|
@ -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! \
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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 }
|
||||
|
||||
|
@ -195,6 +195,7 @@ impl Writer for SipState {
|
||||
}
|
||||
}
|
||||
|
||||
#[stable]
|
||||
impl Clone for SipState {
|
||||
#[inline]
|
||||
fn clone(&self) -> SipState {
|
||||
|
@ -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:
|
||||
///
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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)]
|
||||
|
@ -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 }
|
||||
|
||||
|
@ -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;
|
||||
|
||||
) }
|
||||
|
||||
|
@ -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 }
|
||||
|
||||
|
@ -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;
|
||||
|
||||
) }
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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() }
|
||||
|
@ -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 }
|
||||
}
|
||||
|
||||
|
@ -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 }
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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),
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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"),
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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")
|
||||
},
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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}
|
||||
|
@ -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 {
|
||||
|
@ -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};
|
||||
|
@ -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(", "))
|
||||
|
@ -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);
|
||||
|
@ -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};
|
||||
|
@ -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 {
|
||||
|
@ -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> {
|
||||
|
@ -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 =
|
||||
|
@ -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 */ }
|
||||
};
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
)
|
||||
}
|
||||
});
|
||||
|
@ -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)
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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]
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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]
|
||||
|
@ -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;
|
||||
|
@ -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() }
|
||||
}
|
||||
|
@ -10,7 +10,7 @@
|
||||
//
|
||||
// ignore-lexer-test FIXME #15883
|
||||
|
||||
pub use self::BucketState::*;
|
||||
use self::BucketState::*;
|
||||
|
||||
use clone::Clone;
|
||||
use cmp;
|
||||
|
@ -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(); }
|
||||
|
@ -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;
|
||||
|
@ -132,6 +132,7 @@ impl ChanWriter {
|
||||
}
|
||||
}
|
||||
|
||||
#[stable]
|
||||
impl Clone for ChanWriter {
|
||||
fn clone(&self) -> ChanWriter {
|
||||
ChanWriter { tx: self.tx.clone() }
|
||||
|
@ -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>>,
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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};
|
||||
|
@ -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};
|
||||
|
@ -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};
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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};
|
||||
|
@ -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.
|
||||
|
@ -170,7 +170,6 @@ mod imp {
|
||||
extern crate libc;
|
||||
|
||||
use io::{IoResult};
|
||||
use kinds::marker;
|
||||
use mem;
|
||||
use os;
|
||||
use rand::Rng;
|
||||
|
@ -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()
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -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};
|
||||
|
@ -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:"));
|
||||
|
@ -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> {
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user