-## How to submit a bug report
+# Contributing to Rust
-If you're just reporting a bug, please see:
+Thank you for your interest in contributing to Rust! There are many ways to
+contribute, and we appreciate all of them. This document is a bit long, so here's
+links to the major sections:
-http://doc.rust-lang.org/complement-bugreport.html
+* [Feature Requests](#feature-requests)
+* [Bug Reports](#bug-reports)
+* [Pull Requests](#pull-requests)
+* [Writing Documentation](#writing-documentation)
+* [Issue Triage](#issue-triage)
+* [Out-of-tree Contributions](#out-of-tree-contributions)
-## Submitting an issue
+If you have questions, please make a post on [internals.rust-lang.org][internals] or
+hop on [#rust-internals][pound-rust-internals].
-Please submit issues here for bug reports or implementation details. For feature
-requests, language changes, or major changes to the libraries, please submit an
-issue against the [RFCs repository](https://github.com/rust-lang/rfcs).
+As a reminder, all contributors are expected to follow our [Code of Conduct](coc).
-## Pull request procedure
+[pound-rust-internals]: http://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust-internals
+[internals]: http://internals.rust-lang.org
+[coc]: http://www.rust-lang.org/conduct.html
-Pull requests should be targeted at Rust's `master` branch.
-Before pushing to your Github repo and issuing the pull request,
-please do two things:
+## Feature Requests
-1. [Rebase](http://git-scm.com/book/en/Git-Branching-Rebasing) your
- local changes against the `master` branch. Resolve any conflicts
- that arise.
+To request a change to the way that the Rust language works, please open an
+issue in the [RFCs repository](https://github.com/rust-lang/rfcs/issues/new)
+rather than this one. New features and other significant language changes
+must go through the RFC process.
-2. Run the full Rust test suite with the `make check` command. You're
- not off the hook even if you just stick to documentation; code
- examples in the docs are tested as well! Although for simple
- wording or grammar fixes, this is probably unnecessary.
+## Bug Reports
-Pull requests will be treated as "review requests", and we will give
-feedback we expect to see corrected on
-[style](http://aturon.github.io/) and
-substance before pulling. Changes contributed via pull request should
-focus on a single issue at a time, like any other. We will not accept
-pull-requests that try to "sneak" unrelated changes in.
+While bugs are unfortunate, they're a reality in software. We can't fix what we
+don't know about, so please report liberally. If you're not sure if something
+is a bug or not, feel free to file a bug anyway.
-Normally, all pull requests must include regression tests (see
-[Note-testsuite](https://github.com/rust-lang/rust/wiki/Note-testsuite))
-that test your change. Occasionally, a change will be very difficult
-to test for. In those cases, please include a note in your commit
-message explaining why.
+If you have the chance, before reporting a bug, please [search existing
+issues](https://github.com/rust-lang/rust/search?q=&type=Issues&utf8=%E2%9C%93),
+as it's possible that someone else has already reported your error. This doesn't
+always work, and sometimes it's hard to know what to search for, so consider this
+extra credit. We won't mind if you accidentally file a duplicate report.
-In the licensing header at the beginning of any files you change,
-please make sure the listed date range includes the current year. For
-example, if it's 2014, and you change a Rust file that was created in
-2010, it should begin:
+Opening an issue is as easy as following [this
+link](https://github.com/rust-lang/rust/issues/new) and filling out the fields.
+Here's a template that you can use to file a bug, though it's not necessary to
+use it exactly:
-```
-// Copyright 2010-2014 The Rust Project Developers.
+ <short summary of the bug>
+
+ I tried this code:
+
+ <code sample that causes the bug>
+
+ I expected to see this happen: <explanation>
+
+ Instead, this happened: <explanation>
+
+ ## Meta
+
+ `rustc --version --verbose`:
+
+ Backtrace:
+
+All three components are important: what you did, what you expected, what
+happened instead. Please include the output of `rustc --version --verbose`,
+which includes important information about what platform you're on, what
+version of Rust you're using, etc.
+
+Sometimes, a backtrace is helpful, and so including that is nice. To get
+a backtrace, set the `RUST_BACKTRACE` environment variable. The easiest way
+to do this is to invoke `rustc` like this:
+
+```bash
+$ RUST_BACKTRACE=1 rustc ...
```
-# Coordination and communication
+## Pull Requests
-Get feedback from other developers on
-[internals.rust-lang.org][internals], and
-[#rust-internals][pound-rust-internals].
+Pull requests are the primary mechanism we use to change Rust. GitHub itself
+has some [great documentation][pull-requests] on using the Pull Request
+feature. We use the 'fork and pull' model described there.
-[pound-rust-internals]: http://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust-internals
-[internals]: http://internals.rust-lang.org
+[pull-requests]: https://help.github.com/articles/using-pull-requests/
+
+Please make pull requests against the `master` branch.
+
+All pull requests are reviewed by another person. We have a bot,
+@rust-highfive, that will automatically assign a random person to review your request.
+
+If you want to request that a specific person reviews your pull request,
+you can add an `r?` to the message. For example, Steve usually reviews
+documentation changes. So if you were to make a documentation change, add
+
+ r? @steveklabnik
+
+to the end of the message, and @rust-highfive will assign @steveklabnik instead
+of a random person. This is entirely optional.
+
+After someone has reviewed your pull request, they will leave an annotation
+on the pull request with an `r+`. It will look something like this:
+
+ @bors: r+ 38fe8d2
+
+This tells @bors, our lovable integration bot, that your pull request has
+been approved. The PR then enters the [merge queue][merge-queue], where @bors
+will run all the tests on every platform we support. If it all works out,
+@bors will merge your code into `master` and close the pull request.
+
+[merge-queue]: http://buildbot.rust-lang.org/homu/queue/rust
+
+## Writing Documentation
+
+Documentation improvements are very welcome. The source of `doc.rust-lang.org`
+is located in `src/doc` in the tree, and standard API documentation is generated
+from the source code itself.
+
+Documentation pull requests function in the same as other pull requests, though
+you may see a slightly different form of `r+`:
+
+ @bors: r+ 38fe8d2 rollup
+
+That additional `rollup` tells @bors that this change is eligible for a 'rollup'.
+To save @bors some work, and to get small changes through more quickly, when
+@bors attempts to merge a commit that's rollup-eligible, it will also merge
+the other rollup-eligible patches too, and they'll get tested and merged at
+the same time.
+
+## Issue Triage
+
+Sometimes, an issue will stay open, even though the bug has been fixed. And
+sometimes, the original bug may go stale because something has changed in the
+meantime.
+
+It can be helpful to go through older bug reports and make sure that they are
+still valid. Load up an older issue, double check that it's still true, and
+leave a comment letting us know if it is or is not. The [least recently updated sort][lru] is good for finding issues like this.
+
+[lru]: https://github.com/rust-lang/rust/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-asc
+
+## Out-of-tree Contributions
+
+There are a number of other ways to contribute to Rust that don't deal with
+this repository.
+
+Answer questions in [#rust][pound-rust], or on [users.rust-lang.org][users],
+or on [StackOverflow][so].
+
+Participate in the [RFC process](https://github.com/rust-lang/rfcs).
+
+Find a [requested community library][community-library], build it, and publish
+it to [Crates.io](http://crates.io). Easier said than done, but very, very
+valuable!
-For more details, please refer to
-[Note-development-policy](https://github.com/rust-lang/rust/wiki/Note-development-policy).
+[pound-rust]: http://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust
+[users]: http://users.rust-lang.org/
+[so]: http://stackoverflow.com/questions/tagged/rust
+[community-library]: https://github.com/rust-lang/rfcs/labels/A-community-library
# The Rust Programming Language
This is a compiler for Rust, including standard libraries, tools and
-documentation.
+documentation. Rust is a systems programming language that is fast,
+memory safe and multithreaded, but does not employ a garbage collector
+or otherwise impose significant runtime overhead.
## Quick Start
-Read ["Installing Rust"][install] from [The Book][trpl].
+Read ["Installing Rust"] from [The Book].
-[install]: http://doc.rust-lang.org/book/installing-rust.html
-[trpl]: http://doc.rust-lang.org/book/index.html
+["Installing Rust"]: http://doc.rust-lang.org/book/installing-rust.html
+[The Book]: http://doc.rust-lang.org/book/index.html
## Building from Source
* GNU `make` 3.81 or later
* `curl`
* `git`
-2. Download and build Rust:
- You can either download a [tarball] or build directly from the [repo].
-
- To build from the [tarball] do:
-
- $ curl -O https://static.rust-lang.org/dist/rustc-nightly-src.tar.gz
- $ tar -xzf rustc-nightly-src.tar.gz
- $ cd rustc-nightly
-
- Or to build from the [repo] do:
+2. Clone the [source] with `git`:
$ git clone https://github.com/rust-lang/rust.git
$ cd rust
- Now that you have Rust's source code, you can configure and build it:
+[source]: https://github.com/rust-lang/rust
+
+3. Build and install:
$ ./configure
$ make && make install
When complete, `make install` will place several programs into
`/usr/local/bin`: `rustc`, the Rust compiler, and `rustdoc`, the
- API-documentation tool.
+ API-documentation tool. This install does not include [Cargo],
+ Rust's package manager, which you may also want to build.
+
+[Cargo]: https://github.com/rust-lang/cargo
### Building on Windows
$ ./configure
$ make && make install
-[repo]: https://github.com/rust-lang/rust
-[tarball]: https://static.rust-lang.org/dist/rustc-nightly-src.tar.gz
-
## Notes
Since the Rust compiler is written in Rust, it must be built by a
Rust currently needs about 1.5 GiB of RAM to build without swapping; if it hits
swap, it will take a very long time to build.
-There is a lot more documentation in the [wiki].
+There is more advice about hacking on Rust in [CONTRIBUTING.md].
-[wiki]: https://github.com/rust-lang/rust/wiki
+[CONTRIBUTING.md]: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md
-## Getting help and getting involved
+## Getting help
The Rust community congregates in a few places:
* [StackOverflow] - Direct questions about using the language here.
* [users.rust-lang.org] - General discussion, broader questions.
-* [internals.rust-lang.org] - For development of the Rust language itself.
* [/r/rust] - News and general discussion.
[StackOverflow]: http://stackoverflow.com/questions/tagged/rust
[/r/rust]: http://reddit.com/r/rust
[users.rust-lang.org]: http://users.rust-lang.org/
-[internals.rust-lang.org]: http://internals.rust-lang.org/
+
+## Contributing
+
+To contribute to Rust, please see [CONTRIBUTING.md](CONTRIBUTING.md).
+
+Rust has an [IRC] culture and most real-time collaboration happens in a
+variety of channels on Mozilla's IRC network, irc.mozilla.org. The
+most popular channel is [#rust], a venue for general discussion about
+Rust, and a good place to ask for help,
+
+[IRC]: https://en.wikipedia.org/wiki/Internet_Relay_Chat
+[#rust]: irc://irc.mozilla.org/rust
## License
make_dir $h/test/run-pass-fulldeps
make_dir $h/test/run-fail
make_dir $h/test/compile-fail
+ make_dir $h/test/parse-fail
make_dir $h/test/compile-fail-fulldeps
make_dir $h/test/bench
make_dir $h/test/perf
# L10N_LANGS are the languages for which the docs have been
# translated.
######################################################################
-DOCS := index intro tutorial complement-bugreport \
+DOCS := index intro tutorial \
complement-lang-faq complement-design-faq complement-project-faq \
rustdoc reference grammar
D := $(S)src/doc
-DOC_TARGETS := trpl
+DOC_TARGETS := trpl style
COMPILER_DOC_TARGETS :=
DOC_L10N_TARGETS :=
doc/book/index.html: $(RUSTBOOK_EXE) $(wildcard $(S)/src/doc/trpl/*.md) | doc/
$(Q)rm -rf doc/book
$(Q)$(RUSTBOOK) build $(S)src/doc/trpl doc/book
+
+style: doc/style/index.html
+
+doc/style/index.html: $(RUSTBOOK_EXE) $(wildcard $(S)/src/doc/style/*.md) | doc/
+ $(Q)rm -rf doc/style
+ $(Q)$(RUSTBOOK) build $(S)src/doc/style doc/style
# Android runtime setup
# FIXME: This probably belongs somewhere else
-# target platform specific variables
-# for arm-linux-androidabi
+# target platform specific variables for android
define DEF_ADB_DEVICE_STATUS
CFG_ADB_DEVICE_STATUS=$(1)
endef
$(foreach target,$(CFG_TARGET), \
- $(if $(findstring $(target),"arm-linux-androideabi"), \
+ $(if $(findstring android, $(target)), \
$(if $(findstring adb,$(CFG_ADB)), \
$(if $(findstring device,$(shell $(CFG_ADB) devices 2>/dev/null | grep -E '^[_A-Za-z0-9-]+[[:blank:]]+device')), \
$(info install: install-runtime-target for $(target) enabled \
$$(call ADB_SHELL,rm,$$(CFG_RUNTIME_PUSH_DIR)/$$(call CFG_LIB_GLOB_$(1),$$(crate)));)
endef
-$(eval $(call INSTALL_RUNTIME_TARGET_N,arm-linux-androideabi,$(CFG_BUILD)))
-$(eval $(call INSTALL_RUNTIME_TARGET_CLEANUP_N,arm-linux-androideabi))
+$(foreach target,$(CFG_TARGET), \
+ $(if $(findstring $(CFG_ADB_DEVICE_STATUS),"true"), \
+ $(eval $(call INSTALL_RUNTIME_TARGET_N,$(taget),$(CFG_BUILD))) \
+ $(eval $(call INSTALL_RUNTIME_TARGET_CLEANUP_N,$(target))) \
+ ))
install-runtime-target: \
install-runtime-target-arm-linux-androideabi-cleanup \
JEMALLOC_ARGS_$(1) := --enable-lazy-lock
else ifeq ($(OSTYPE_$(1)), apple-ios)
JEMALLOC_ARGS_$(1) := --disable-tls
-else ifeq ($(OSTYPE_$(1)), linux-androideabi)
- JEMALLOC_ARGS_$(1) := --disable-tls
-else ifeq ($(OSTYPE_$(1)), linux-android)
+else ifeq ($(findstring android, $(OSTYPE_$(1))), android)
JEMALLOC_ARGS_$(1) := --disable-tls
endif
$(foreach target,$(CFG_TARGET), \
$(eval $(call DEF_TARGET_COMMANDS,$(target))))
-# Target platform specific variables
-# for arm-linux-androidabi
+# Target platform specific variables for android
define DEF_ADB_DEVICE_STATUS
CFG_ADB_DEVICE_STATUS=$(1)
endef
$(foreach target,$(CFG_TARGET), \
- $(if $(findstring $(target),"arm-linux-androideabi"), \
+ $(if $(findstring android, $(target)), \
$(if $(findstring adb,$(CFG_ADB)), \
$(if $(findstring device,$(shell $(CFG_ADB) devices 2>/dev/null | grep -E '^[:_A-Za-z0-9-]+[[:blank:]]+device')), \
$(info check: android device attached) \
$(shell $(CFG_ADB) remount 1>/dev/null) \
$(shell $(CFG_ADB) shell rm -r $(CFG_ADB_TEST_DIR) >/dev/null) \
$(shell $(CFG_ADB) shell mkdir $(CFG_ADB_TEST_DIR)) \
- $(shell $(CFG_ADB) shell mkdir $(CFG_ADB_TEST_DIR)/tmp) \
$(shell $(CFG_ADB) push $(S)src/etc/adb_run_wrapper.sh $(CFG_ADB_TEST_DIR) 1>/dev/null) \
- $(foreach crate,$(TARGET_CRATES), \
- $(shell $(CFG_ADB) push $(TLIB2_T_arm-linux-androideabi_H_$(CFG_BUILD))/$(call CFG_LIB_GLOB_arm-linux-androideabi,$(crate)) \
- $(CFG_ADB_TEST_DIR))) \
- )
+ $(foreach target,$(CFG_TARGET), \
+ $(if $(findstring android, $(target)), \
+ $(shell $(CFG_ADB) shell mkdir $(CFG_ADB_TEST_DIR)/$(target)) \
+ $(foreach crate,$(TARGET_CRATES), \
+ $(shell $(CFG_ADB) push $(TLIB2_T_$(target)_H_$(CFG_BUILD))/$(call CFG_LIB_GLOB_$(target),$(crate)) \
+ $(CFG_ADB_TEST_DIR)/$(target))), \
+ )))
else
CFG_ADB_TEST_DIR=
endif
check-lite: cleantestlibs cleantmptestlogs \
$(foreach crate,$(TEST_TARGET_CRATES),check-stage2-$(crate)) \
check-stage2-rpass check-stage2-rpass-valgrind \
- check-stage2-rfail check-stage2-cfail check-stage2-rmake
+ check-stage2-rfail check-stage2-cfail check-stage2-pfail check-stage2-rmake
$(Q)$(CFG_PYTHON) $(S)src/etc/check-summary.py tmp/*.log
# Only check the 'reference' tests: rpass/cfail/rfail/rmake.
check-ref: cleantestlibs cleantmptestlogs check-stage2-rpass check-stage2-rpass-valgrind \
- check-stage2-rfail check-stage2-cfail check-stage2-rmake
+ check-stage2-rfail check-stage2-cfail check-stage2-pfail check-stage2-rmake
$(Q)$(CFG_PYTHON) $(S)src/etc/check-summary.py tmp/*.log
# Only check the docs.
check-stage$(1)-T-$(2)-H-$(3)-rpass-exec \
check-stage$(1)-T-$(2)-H-$(3)-rfail-exec \
check-stage$(1)-T-$(2)-H-$(3)-cfail-exec \
+ check-stage$(1)-T-$(2)-H-$(3)-pfail-exec \
check-stage$(1)-T-$(2)-H-$(3)-rpass-valgrind-exec \
check-stage$(1)-T-$(2)-H-$(3)-rpass-full-exec \
check-stage$(1)-T-$(2)-H-$(3)-cfail-full-exec \
&& touch $$@
endef
-define DEF_TEST_CRATE_RULES_arm-linux-androideabi
+define DEF_TEST_CRATE_RULES_android
check-stage$(1)-T-$(2)-H-$(3)-$(4)-exec: $$(call TEST_OK_FILE,$(1),$(2),$(3),$(4))
$$(call TEST_OK_FILE,$(1),$(2),$(3),$(4)): \
$(3)/stage$(1)/test/$(4)test-$(2)$$(X_$(2))
@$$(call E, run: $$< via adb)
$$(Q)$(CFG_ADB) push $$< $(CFG_ADB_TEST_DIR)
- $$(Q)$(CFG_ADB) shell '(cd $(CFG_ADB_TEST_DIR); LD_LIBRARY_PATH=. \
+ $$(Q)$(CFG_ADB) shell '(cd $(CFG_ADB_TEST_DIR); LD_LIBRARY_PATH=./$(2) \
./$$(notdir $$<) \
--logfile $(CFG_ADB_TEST_DIR)/check-stage$(1)-T-$(2)-H-$(3)-$(4).log \
$$(call CRATE_TEST_EXTRA_ARGS,$(1),$(2),$(3),$(4)) $(TESTARGS))' \
$(foreach crate, $(TEST_CRATES), \
$(if $(findstring $(target),$(CFG_BUILD)), \
$(eval $(call DEF_TEST_CRATE_RULES,$(stage),$(target),$(host),$(crate))), \
- $(if $(findstring $(target),"arm-linux-androideabi"), \
+ $(if $(findstring android, $(target)), \
$(if $(findstring $(CFG_ADB_DEVICE_STATUS),"true"), \
- $(eval $(call DEF_TEST_CRATE_RULES_arm-linux-androideabi,$(stage),$(target),$(host),$(crate))), \
+ $(eval $(call DEF_TEST_CRATE_RULES_android,$(stage),$(target),$(host),$(crate))), \
$(eval $(call DEF_TEST_CRATE_RULES_null,$(stage),$(target),$(host),$(crate))) \
), \
$(eval $(call DEF_TEST_CRATE_RULES,$(stage),$(target),$(host),$(crate))) \
RPASS_FULL_TESTS := $(RPASS_FULL_RS)
CFAIL_FULL_TESTS := $(CFAIL_FULL_RS)
RFAIL_TESTS := $(RFAIL_RS)
-CFAIL_TESTS := $(CFAIL_RS) $(PFAIL_RS)
+CFAIL_TESTS := $(CFAIL_RS)
+PFAIL_TESTS := $(PFAIL_RS)
BENCH_TESTS := $(BENCH_RS)
PERF_TESTS := $(PERF_RS)
PRETTY_TESTS := $(PRETTY_RS)
CTEST_MODE_cfail = compile-fail
CTEST_RUNTOOL_cfail = $(CTEST_RUNTOOL)
+CTEST_SRC_BASE_pfail = parse-fail
+CTEST_BUILD_BASE_pfail = parse-fail
+CTEST_MODE_pfail = parse-fail
+CTEST_RUNTOOL_pfail = $(CTEST_RUNTOOL)
+
CTEST_SRC_BASE_bench = bench
CTEST_BUILD_BASE_bench = bench
CTEST_MODE_bench = run-pass
CTEST_DEPS_cfail-full_$(1)-T-$(2)-H-$(3) = $$(CFAIL_FULL_TESTS) $$(CSREQ$(1)_T_$(3)_H_$(3)) $$(SREQ$(1)_T_$(2)_H_$(3))
CTEST_DEPS_rfail_$(1)-T-$(2)-H-$(3) = $$(RFAIL_TESTS)
CTEST_DEPS_cfail_$(1)-T-$(2)-H-$(3) = $$(CFAIL_TESTS)
+CTEST_DEPS_pfail_$(1)-T-$(2)-H-$(3) = $$(PFAIL_TESTS)
CTEST_DEPS_bench_$(1)-T-$(2)-H-$(3) = $$(BENCH_TESTS)
CTEST_DEPS_perf_$(1)-T-$(2)-H-$(3) = $$(PERF_TESTS)
CTEST_DEPS_debuginfo-gdb_$(1)-T-$(2)-H-$(3) = $$(DEBUGINFO_GDB_TESTS)
endef
-CTEST_NAMES = rpass rpass-valgrind rpass-full cfail-full rfail cfail bench perf debuginfo-gdb debuginfo-lldb codegen
+CTEST_NAMES = rpass rpass-valgrind rpass-full cfail-full rfail cfail pfail bench perf debuginfo-gdb debuginfo-lldb codegen
$(foreach host,$(CFG_HOST), \
$(eval $(foreach target,$(CFG_TARGET), \
cfail-full \
rfail \
cfail \
+ pfail \
bench \
perf \
rmake \
#[derive(Clone, Copy, PartialEq, Debug)]
pub enum Mode {
CompileFail,
+ ParseFail,
RunFail,
RunPass,
RunPassValgrind,
fn from_str(s: &str) -> Result<Mode, ()> {
match s {
"compile-fail" => Ok(CompileFail),
+ "parse-fail" => Ok(ParseFail),
"run-fail" => Ok(RunFail),
"run-pass" => Ok(RunPass),
"run-pass-valgrind" => Ok(RunPassValgrind),
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(match *self {
CompileFail => "compile-fail",
+ ParseFail => "parse-fail",
RunFail => "run-fail",
RunPass => "run-pass",
RunPassValgrind => "run-pass-valgrind",
#![feature(box_syntax)]
#![feature(collections)]
#![feature(int_uint)]
-#![feature(io)]
-#![feature(path)]
+#![feature(old_io)]
+#![feature(old_path)]
#![feature(rustc_private)]
#![feature(unboxed_closures)]
#![feature(std_misc)]
#![feature(test)]
#![feature(unicode)]
#![feature(env)]
+#![feature(core)]
#![deny(warnings)]
reqopt("", "aux-base", "directory to find auxiliary test files", "PATH"),
reqopt("", "stage-id", "the target-stage identifier", "stageN-TARGET"),
reqopt("", "mode", "which sort of compile tests to run",
- "(compile-fail|run-fail|run-pass|run-pass-valgrind|pretty|debug-info)"),
+ "(compile-fail|parse-fail|run-fail|run-pass|run-pass-valgrind|pretty|debug-info)"),
optflag("", "ignored", "run tests marked as ignored"),
optopt("", "runtool", "supervisor program to run tests under \
(eg. emulator, valgrind)", "PROGRAM"),
lldb_version: extract_lldb_version(matches.opt_str("lldb-version")),
android_cross_path: opt_path(matches, "android-cross-path"),
adb_path: opt_str2(matches.opt_str("adb-path")),
- adb_test_dir: opt_str2(matches.opt_str("adb-test-dir")),
+ adb_test_dir: format!("{}/{}",
+ opt_str2(matches.opt_str("adb-test-dir")),
+ opt_str2(matches.opt_str("target"))),
adb_device_status:
- "arm-linux-androideabi" ==
- opt_str2(matches.opt_str("target")) &&
- "(none)" !=
- opt_str2(matches.opt_str("adb-test-dir")) &&
+ opt_str2(matches.opt_str("target")).contains("android") &&
+ "(none)" != opt_str2(matches.opt_str("adb-test-dir")) &&
!opt_str2(matches.opt_str("adb-test-dir")).is_empty(),
lldb_python_dir: matches.opt_str("lldb-python-dir"),
verbose: matches.opt_present("verbose"),
}
pub fn run_tests(config: &Config) {
- if config.target == "arm-linux-androideabi" {
+ if config.target.contains("android") {
match config.mode {
DebugInfoGdb => {
- println!("arm-linux-androideabi debug-info \
- test uses tcp 5039 port. please reserve it");
+ println!("{} debug-info test uses tcp 5039 port.\
+ please reserve it", config.target);
}
_ =>{}
}
- //arm-linux-androideabi debug-info test uses remote debugger
- //so, we test 1 task at once.
+ // android debug-info test uses remote debugger
+ // so, we test 1 task at once.
// also trying to isolate problems with adb_run_wrapper.sh ilooping
env::set_var("RUST_TEST_TASKS","1");
}
use self::TargetLocation::*;
use common::Config;
-use common::{CompileFail, Pretty, RunFail, RunPass, RunPassValgrind, DebugInfoGdb};
+use common::{CompileFail, ParseFail, Pretty, RunFail, RunPass, RunPassValgrind, DebugInfoGdb};
use common::{Codegen, DebugInfoLldb};
use errors;
use header::TestProps;
use std::iter::repeat;
use std::str;
use std::string::String;
-use std::thread::Thread;
+use std::thread;
use std::time::Duration;
use test::MetricMap;
pub fn run(config: Config, testfile: String) {
match &*config.target {
- "arm-linux-androideabi" => {
+ "arm-linux-androideabi" | "aarch64-linux-android" => {
if !config.adb_device_status {
panic!("android device not available");
}
debug!("loaded props");
match config.mode {
CompileFail => run_cfail_test(&config, &props, &testfile),
+ ParseFail => run_cfail_test(&config, &props, &testfile),
RunFail => run_rfail_test(&config, &props, &testfile),
RunPass => run_rpass_test(&config, &props, &testfile),
RunPassValgrind => run_valgrind_test(&config, &props, &testfile),
let proc_res = compile_test(config, props, testfile);
if proc_res.status.success() {
- fatal_proc_rec("compile-fail test compiled successfully!",
+ fatal_proc_rec(&format!("{} test compiled successfully!", config.mode)[],
&proc_res);
}
let debugger_run_result;
match &*config.target {
- "arm-linux-androideabi" => {
+ "arm-linux-androideabi" | "aarch64-linux-android" => {
- cmds = cmds.replace("run", "continue").to_string();
+ cmds = cmds.replace("run", "continue");
// write debugger script
- let script_str = ["set charset UTF-8".to_string(),
- format!("file {}", exe_file.as_str().unwrap()
- .to_string()),
- "target remote :5039".to_string(),
- cmds,
- "quit".to_string()].connect("\n");
+ let mut script_str = String::with_capacity(2048);
+ script_str.push_str("set charset UTF-8\n");
+ script_str.push_str(&format!("file {}\n", exe_file.as_str().unwrap()));
+ script_str.push_str("target remote :5039\n");
+ script_str.push_str(&format!("set solib-search-path \
+ ./{}/stage2/lib/rustlib/{}/lib/\n",
+ config.host, config.target));
+ for line in breakpoint_lines.iter() {
+ script_str.push_str(&format!("break {:?}:{}\n",
+ testfile.filename_display(),
+ *line)[]);
+ }
+ script_str.push_str(&cmds);
+ script_str.push_str("quit\n");
+
debug!("script_str = {}", script_str);
dump_output_file(config,
testfile,
.expect(&format!("failed to exec `{:?}`", config.adb_path));
let adb_arg = format!("export LD_LIBRARY_PATH={}; \
- gdbserver :5039 {}/{}",
+ gdbserver{} :5039 {}/{}",
config.adb_test_dir.clone(),
+ if config.target.contains("aarch64")
+ {"64"} else {""},
config.adb_test_dir.clone(),
str::from_utf8(
exe_file.filename()
loop {
//waiting 1 second for gdbserver start
timer::sleep(Duration::milliseconds(1000));
- let result = Thread::scoped(move || {
+ let result = thread::spawn(move || {
tcp::TcpStream::connect("127.0.0.1:5039").unwrap();
}).join();
if result.is_err() {
format!("-command={}", debugger_script.as_str().unwrap()));
let mut gdb_path = tool_path;
- gdb_path.push_str("/bin/arm-linux-androideabi-gdb");
+ gdb_path.push_str(&format!("/bin/{}-gdb", config.target));
let procsrv::Result {
out,
err,
.expect(&format!("failed to exec `{:?}`", gdb_path));
let cmdline = {
let cmdline = make_cmdline("",
- "arm-linux-androideabi-gdb",
+ &format!("{}-gdb", config.target),
&debugger_opts);
logv(config, format!("executing {}", cmdline));
cmdline
stderr: err,
cmdline: cmdline
};
- process.signal_kill().unwrap();
+ if process.signal_kill().is_err() {
+ println!("Adb process is already finished.");
+ }
}
_=> {
// FIXME (#9639): This needs to handle non-utf8 paths
let mut link_args = vec!("-L".to_string(),
aux_dir.as_str().unwrap().to_string());
- link_args.extend(extra_args.iter().map(|s| s.clone()));
+ link_args.extend(extra_args.iter().cloned());
let args = make_compile_args(config,
props,
link_args,
match &*config.target {
- "arm-linux-androideabi" => {
+ "arm-linux-androideabi" | "aarch64-linux-android" => {
_arm_exec_compiled_test(config, props, testfile, env)
}
}
match &*config.target {
- "arm-linux-androideabi" => {
+ "arm-linux-androideabi" | "aarch64-linux-android" => {
_arm_push_aux_shared_library(config, testfile);
}
_ => {}
for (key, val) in env {
runargs.push(format!("{}={}", key, val));
}
- runargs.push(format!("{}/adb_run_wrapper.sh", config.adb_test_dir));
+ runargs.push(format!("{}/../adb_run_wrapper.sh", config.adb_test_dir));
runargs.push(format!("{}", config.adb_test_dir));
runargs.push(format!("{}", prog_short));
file.as_str()
.unwrap()
.to_string(),
- config.adb_test_dir.to_string()
+ config.adb_test_dir.to_string(),
],
vec!(("".to_string(),
"".to_string())),
+++ /dev/null
-% How to submit a Rust bug report
-
-# I think I found a bug in the compiler!
-
-If you see this message: `error: internal compiler error: unexpected panic`,
-then you have definitely found a bug in the compiler. It's also possible that
-your code is not well-typed, but if you saw this message, it's still a bug in
-error reporting.
-
-If you see a message about an LLVM assertion failure, then you have also
-definitely found a bug in the compiler. In both of these cases, it's not your
-fault and you should report a bug!
-
-If you see a compiler error message that you think is meant for users to see,
-but it confuses you, *that's a bug too*. If it wasn't clear to you, then it's
-an error message we want to improve, so please report it so that we can try
-to make it better.
-
-# How do I know the bug I found isn't a bug that already exists in the issue tracker?
-
-If you don't have enough time for a search, then don't worry about that. Just submit
-the bug. If it's a duplicate, somebody will notice that and close it during triage.
-
-If you have the time for it, it would be useful to type the text of the error
-message you got [into the issue tracker search box](https://github.com/rust-lang/rust/issues)
-to see if there's an existing bug that resembles your problem. If there is,
-and it's an open bug, you can comment on that issue and say you are also affected.
-This will encourage the devs to fix it. But again, don't let this stop you from
-submitting a bug. We'd rather have to do the work of closing duplicates than
-miss out on valid bug reports.
-
-# What information should I include in a bug report?
-
-It generally helps our diagnosis to include your specific OS (for example: Mac OS X 10.8.3,
-Windows 7, Ubuntu 12.04) and your hardware architecture (for example: i686, x86_64).
-It's also helpful to provide the exact version and host by copying the output of
-re-running the erroneous rustc command with the `--version --verbose` flags, which will
-produce something like this:
-
-```text
-rustc 0.12.0 (ba4081a5a 2014-10-07 13:44:41 -0700)
-binary: rustc
-commit-hash: ba4081a5a8573875fed17545846f6f6902c8ba8d
-commit-date: 2014-10-07 13:44:41 -0700
-host: i686-apple-darwin
-release: 0.12.0
-```
-
-Finally, if you can also provide a backtrace, that'd be great. You can get a
-backtrace by setting the `RUST_BACKTRACE` environment variable to `1`, like
-this:
-
-```bash
-$ RUST_BACKTRACE=1 rustc ...
-```
-
-# I submitted a bug, but nobody has commented on it!
-
-This is sad, but does happen sometimes, since we're short-staffed. If you submit a
-bug and you haven't received a comment on it within 3 business days, it's entirely
-reasonable to ask about the status of the bug in #rust on irc.mozilla.org.
ways insufficient for concatenating identifiers, and may be
removed entirely for something more wholesome.
+* `custom_attribute` - Allows the usage of attributes unknown to the compiler
+ so that new attributes can be added in a bacwards compatible
+ manner (RFC 572).
+
* `intrinsics` - Allows use of the "rust-intrinsics" ABI. Compiler intrinsics
are inherently unstable and no promise about them is made.
implemented very poorly and will likely change significantly
with a proper implementation.
+* `rustc_attrs` - Gates internal `#[rustc_*]` attributes which may be
+ for internal use only or have meaning added to them in the future.
+
* `rustc_diagnostic_macros`- A mysterious feature, used in the implementation
of rustc, not meant for mortals.
--- /dev/null
+% Style Guidelines
+
+This document collects the emerging principles, conventions, abstractions, and
+best practices for writing Rust code.
+
+Since Rust is evolving at a rapid pace, these guidelines are
+preliminary. The hope is that writing them down explicitly will help
+drive discussion, consensus and adoption.
+
+Whenever feasible, guidelines provide specific examples from Rust's standard
+libraries.
+
+### Guideline statuses
+
+Every guideline has a status:
+
+* **[FIXME]**: Marks places where there is more work to be done. In
+ some cases, that just means going through the RFC process.
+
+* **[FIXME #NNNNN]**: Like **[FIXME]**, but links to the issue tracker.
+
+* **[RFC #NNNN]**: Marks accepted guidelines, linking to the rust-lang
+ RFC establishing them.
+
+### Guideline stabilization
+
+One purpose of these guidelines is to reach decisions on a number of
+cross-cutting API and stylistic choices. Discussion and development of
+the guidelines will happen primarily on http://discuss.rust-lang.org/,
+using the Guidelines category. Discussion can also occur on the
+[guidelines issue tracker](https://github.com/rust-lang/rust-guidelines).
+
+Guidelines that are under development or discussion will be marked with the
+status **[FIXME]**, with a link to the issue tracker when appropriate.
+
+Once a concrete guideline is ready to be proposed, it should be filed
+as an [FIXME: needs RFC](https://github.com/rust-lang/rfcs). If the RFC is
+accepted, the official guidelines will be updated to match, and will
+include the tag **[RFC #NNNN]** linking to the RFC document.
+
+### What's in this document
+
+This document is broken into four parts:
+
+* **[Style](style/README.md)** provides a set of rules governing naming conventions,
+ whitespace, and other stylistic issues.
+
+* **[Guidelines by Rust feature](features/README.md)** places the focus on each of
+ Rust's features, starting from expressions and working the way out toward
+ crates, dispensing guidelines relevant to each.
+
+* **Topical guidelines and patterns**. The rest of the document proceeds by
+ cross-cutting topic, starting with
+ [Ownership and resources](ownership/README.md).
+
+* **[APIs for a changing Rust](changing/README.md)**
+ discusses the forward-compatibility hazards, especially those that interact
+ with the pre-1.0 library stabilization process.
+
+> **[FIXME]** Add cross-references throughout this document to the tutorial,
+> reference manual, and other guides.
+
+> **[FIXME]** What are some _non_-goals, _non_-principles, or _anti_-patterns that
+> we should document?
--- /dev/null
+# Summary
+
+* [Style](style/README.md)
+ * [Whitespace](style/whitespace.md)
+ * [Comments](style/comments.md)
+ * [Braces, semicolons, commas](style/braces.md)
+ * [Naming](style/naming/README.md)
+ * [Ownership variants](style/naming/ownership.md)
+ * [Containers/wrappers](style/naming/containers.md)
+ * [Conversions](style/naming/conversions.md)
+ * [Iterators](style/naming/iterators.md)
+ * [Imports](style/imports.md)
+ * [Organization](style/organization.md)
+* [Guidelines by Rust feature](features/README.md)
+ * [Let binding](features/let.md)
+ * [Pattern matching](features/match.md)
+ * [Loops](features/loops.md)
+ * [Functions and methods](features/functions-and-methods/README.md)
+ * [Input](features/functions-and-methods/input.md)
+ * [Output](features/functions-and-methods/output.md)
+ * [For convenience](features/functions-and-methods/convenience.md)
+ * [Types](features/types/README.md)
+ * [Conversions](features/types/conversions.md)
+ * [The newtype pattern](features/types/newtype.md)
+ * [Traits](features/traits/README.md)
+ * [For generics](features/traits/generics.md)
+ * [For objects](features/traits/objects.md)
+ * [For overloading](features/traits/overloading.md)
+ * [For extensions](features/traits/extensions.md)
+ * [For reuse](features/traits/reuse.md)
+ * [Common traits](features/traits/common.md)
+ * [Modules](features/modules.md)
+ * [Crates](features/crates.md)
+* [Ownership and resources](ownership/README.md)
+ * [Constructors](ownership/constructors.md)
+ * [Builders](ownership/builders.md)
+ * [Destructors](ownership/destructors.md)
+ * [RAII](ownership/raii.md)
+ * [Cells and smart pointers](ownership/cell-smart.md)
+* [Errors](errors/README.md)
+ * [Signaling](errors/signaling.md)
+ * [Handling](errors/handling.md)
+ * [Propagation](errors/propagation.md)
+ * [Ergonomics](errors/ergonomics.md)
+* [Safety and guarantees](safety/README.md)
+ * [Using unsafe](safety/unsafe.md)
+ * [Library guarantees](safety/lib-guarantees.md)
+* [Testing](testing/README.md)
+ * [Unit testing](testing/unit.md)
+* [FFI, platform-specific code](platform.md)
+* [APIs for a changing Rust](changing/README.md)
+ * [Pre-1.0 changes](changing/pre-1-0.md)
+ * [Post-1.0 changes](changing/post-1-0.md)
+ * [Timing unclear](changing/unclear.md)
--- /dev/null
+% API design for a changing Rust
+
+A number of planned Rust features will drastically affect the API design
+story. This section collects some of the biggest features with concrete examples
+of how the API will change.
--- /dev/null
+% Post-1.0 changes
+
+### Higher-kinded types
+
+* A trait encompassing both `Iterable<T>` for some fixed `T` and
+ `FromIterator<U>` for _all_ `U` (where HKT comes in). The train
+ could provide e.g. a default `map` method producing the same kind of
+ the container, but with a new type parameter.
+
+* **Monadic-generic programming**? Can we add this without deprecating
+ huge swaths of the API (including `Option::map`, `option::collect`,
+ `result::collect`, `try!` etc.
--- /dev/null
+% Pre-1.0 changes
+
+### `std` facade
+
+We should revisit some APIs in `libstd` now that the facade effort is complete.
+
+For example, the treatment of environment variables in the new
+`Command` API is waiting on access to hashtables before being
+approved.
+
+### Trait reform
+
+Potential for standard conversion traits (`to`, `into`, `as`).
+
+Probably many other opportunities here.
+
+### Unboxed closures
--- /dev/null
+% Changes with unclear timing
+
+### Associated items
+
+* Many traits that currently take type parameters should instead use associated
+ types; this will _drastically_ simplify signatures in some cases.
+
+* Associated constants would be useful in a few places, e.g. traits for
+ numerics, traits for paths.
+
+### Anonymous, unboxed return types (aka `impl Trait` types)
+
+* See https://github.com/rust-lang/rfcs/pull/105
+
+* Could affect API design in several places, e.g. the `Iterator` trait.
+
+### Default type parameters
+
+We are already using this in a few places (e.g. `HashMap`), but it's
+feature-gated.
+
+### Compile-time function evaluation (CTFE)
+
+https://github.com/mozilla/rust/issues/11621
+
+### Improved constant folding
+
+https://github.com/rust-lang/rust/issues/7834
--- /dev/null
+% Errors
+
+> **[FIXME]** Add some general text here.
--- /dev/null
+% Ergonomic error handling
+
+Error propagation with raw `Result`s can require tedious matching and
+repackaging. This tedium is largely alleviated by the `try!` macro,
+and can be completely removed (in some cases) by the "`Result`-`impl`"
+pattern.
+
+### The `try!` macro
+
+Prefer
+
+```rust
+use std::io::{File, Open, Write, IoError};
+
+struct Info {
+ name: String,
+ age: int,
+ rating: int
+}
+
+fn write_info(info: &Info) -> Result<(), IoError> {
+ let mut file = File::open_mode(&Path::new("my_best_friends.txt"),
+ Open, Write);
+ // Early return on error
+ try!(file.write_line(format!("name: {}", info.name).as_slice()));
+ try!(file.write_line(format!("age: {}", info.age).as_slice()));
+ try!(file.write_line(format!("rating: {}", info.rating).as_slice()));
+ return Ok(());
+}
+```
+
+over
+
+```rust
+use std::io::{File, Open, Write, IoError};
+
+struct Info {
+ name: String,
+ age: int,
+ rating: int
+}
+
+fn write_info(info: &Info) -> Result<(), IoError> {
+ let mut file = File::open_mode(&Path::new("my_best_friends.txt"),
+ Open, Write);
+ // Early return on error
+ match file.write_line(format!("name: {}", info.name).as_slice()) {
+ Ok(_) => (),
+ Err(e) => return Err(e)
+ }
+ match file.write_line(format!("age: {}", info.age).as_slice()) {
+ Ok(_) => (),
+ Err(e) => return Err(e)
+ }
+ return file.write_line(format!("rating: {}", info.rating).as_slice());
+}
+```
+
+See
+[the `result` module documentation](http://static.rust-lang.org/doc/master/std/result/index.html#the-try!-macro)
+for more details.
+
+### The `Result`-`impl` pattern [FIXME]
+
+> **[FIXME]** Document the way that the `io` module uses trait impls
+> on `IoResult` to painlessly propagate errors.
--- /dev/null
+% Handling errors
+
+### Use task isolation to cope with failure. [FIXME]
+
+> **[FIXME]** Explain how to isolate tasks and detect task failure for recovery.
+
+### Consuming `Result` [FIXME]
--- /dev/null
+% Propagation
+
+> **[FIXME]** We need guidelines on how to layer error information up a stack of
+> abstractions.
+
+### Error interoperation [FIXME]
+
+> **[FIXME]** Document the `FromError` infrastructure.
--- /dev/null
+% Signaling errors [RFC #236]
+
+> The guidelines below were approved by [RFC #236](https://github.com/rust-lang/rfcs/pull/236).
+
+Errors fall into one of three categories:
+
+* Catastrophic errors, e.g. out-of-memory.
+* Contract violations, e.g. wrong input encoding, index out of bounds.
+* Obstructions, e.g. file not found, parse error.
+
+The basic principle of the convention is that:
+
+* Catastrophic errors and programming errors (bugs) can and should only be
+recovered at a *coarse grain*, i.e. a task boundary.
+* Obstructions preventing an operation should be reported at a maximally *fine
+grain* -- to the immediate invoker of the operation.
+
+## Catastrophic errors
+
+An error is _catastrophic_ if there is no meaningful way for the current task to
+continue after the error occurs.
+
+Catastrophic errors are _extremely_ rare, especially outside of `libstd`.
+
+**Canonical examples**: out of memory, stack overflow.
+
+### For catastrophic errors, panic
+
+For errors like stack overflow, Rust currently aborts the process, but
+could in principle panic, which (in the best case) would allow
+reporting and recovery from a supervisory task.
+
+## Contract violations
+
+An API may define a contract that goes beyond the type checking enforced by the
+compiler. For example, slices support an indexing operation, with the contract
+that the supplied index must be in bounds.
+
+Contracts can be complex and involve more than a single function invocation. For
+example, the `RefCell` type requires that `borrow_mut` not be called until all
+existing borrows have been relinquished.
+
+### For contract violations, panic
+
+A contract violation is always a bug, and for bugs we follow the Erlang
+philosophy of "let it crash": we assume that software *will* have bugs, and we
+design coarse-grained task boundaries to report, and perhaps recover, from these
+bugs.
+
+### Contract design
+
+One subtle aspect of these guidelines is that the contract for a function is
+chosen by an API designer -- and so the designer also determines what counts as
+a violation.
+
+This RFC does not attempt to give hard-and-fast rules for designing
+contracts. However, here are some rough guidelines:
+
+* Prefer expressing contracts through static types whenever possible.
+
+* It *must* be possible to write code that uses the API without violating the
+ contract.
+
+* Contracts are most justified when violations are *inarguably* bugs -- but this
+ is surprisingly rare.
+
+* Consider whether the API client could benefit from the contract-checking
+ logic. The checks may be expensive. Or there may be useful programming
+ patterns where the client does not want to check inputs before hand, but would
+ rather attempt the operation and then find out whether the inputs were invalid.
+
+* When a contract violation is the *only* kind of error a function may encounter
+ -- i.e., there are no obstructions to its success other than "bad" inputs --
+ using `Result` or `Option` instead is especially warranted. Clients can then use
+ `unwrap` to assert that they have passed valid input, or re-use the error
+ checking done by the API for their own purposes.
+
+* When in doubt, use loose contracts and instead return a `Result` or `Option`.
+
+## Obstructions
+
+An operation is *obstructed* if it cannot be completed for some reason, even
+though the operation's contract has been satisfied. Obstructed operations may
+have (documented!) side effects -- they are not required to roll back after
+encountering an obstruction. However, they should leave the data structures in
+a "coherent" state (satisfying their invariants, continuing to guarantee safety,
+etc.).
+
+Obstructions may involve external conditions (e.g., I/O), or they may involve
+aspects of the input that are not covered by the contract.
+
+**Canonical examples**: file not found, parse error.
+
+### For obstructions, use `Result`
+
+The
+[`Result<T,E>` type](http://static.rust-lang.org/doc/master/std/result/index.html)
+represents either a success (yielding `T`) or failure (yielding `E`). By
+returning a `Result`, a function allows its clients to discover and react to
+obstructions in a fine-grained way.
+
+#### What about `Option`?
+
+The `Option` type should not be used for "obstructed" operations; it
+should only be used when a `None` return value could be considered a
+"successful" execution of the operation.
+
+This is of course a somewhat subjective question, but a good litmus
+test is: would a reasonable client ever ignore the result? The
+`Result` type provides a lint that ensures the result is actually
+inspected, while `Option` does not, and this difference of behavior
+can help when deciding between the two types.
+
+Another litmus test: can the operation be understood as asking a
+question (possibly with sideeffects)? Operations like `pop` on a
+vector can be viewed as asking for the contents of the first element,
+with the side effect of removing it if it exists -- with an `Option`
+return value.
+
+## Do not provide both `Result` and `panic!` variants.
+
+An API should not provide both `Result`-producing and `panic`king versions of an
+operation. It should provide just the `Result` version, allowing clients to use
+`try!` or `unwrap` instead as needed. This is part of the general pattern of
+cutting down on redundant variants by instead using method chaining.
--- /dev/null
+% Guidelines by language feature
+
+Rust provides a unique combination of language features, some new and some
+old. This section gives guidance on when and how to use Rust's features, and
+brings attention to some of the tradeoffs between different features.
+
+Notably missing from this section is an in-depth discussion of Rust's pointer
+types (both built-in and in the library). The topic of pointers is discussed at
+length in a [separate section on ownership](../ownership/README.md).
--- /dev/null
+% Crates
+
+> **[FIXME]** What general guidelines should we provide for crate design?
+
+> Possible topics: facades; per-crate preludes (to be imported as globs);
+> "lib.rs"
--- /dev/null
+% Functions and methods
+
+### Prefer methods to functions if there is a clear receiver. **[FIXME: needs RFC]**
+
+Prefer
+
+```rust
+impl Foo {
+ pub fn frob(&self, w: widget) { ... }
+}
+```
+
+over
+
+```rust
+pub fn frob(foo: &Foo, w: widget) { ... }
+```
+
+for any operation that is clearly associated with a particular
+type.
+
+Methods have numerous advantages over functions:
+* They do not need to be imported or qualified to be used: all you
+ need is a value of the appropriate type.
+* Their invocation performs autoborrowing (including mutable borrows).
+* They make it easy to answer the question "what can I do with a value
+ of type `T`" (especially when using rustdoc).
+* They provide `self` notation, which is more concise and often more
+ clearly conveys ownership distinctions.
+
+> **[FIXME]** Revisit these guidelines with
+> [UFCS](https://github.com/nick29581/rfcs/blob/ufcs/0000-ufcs.md) and
+> conventions developing around it.
+
+
+
+### Guidelines for inherent methods. **[FIXME]**
+
+> **[FIXME]** We need guidelines for when to provide inherent methods on a type,
+> versus methods through a trait or functions.
+
+> **NOTE**: Rules for method resolution around inherent methods are in flux,
+> which may impact the guidelines.
--- /dev/null
+% Convenience methods
+
+### Provide small, coherent sets of convenience methods. **[FIXME: needs RFC]**
+
+_Convenience methods_ wrap up existing functionality in a more convenient
+way. The work done by a convenience method varies widely:
+
+* _Re-providing functions as methods_. For example, the `std::path::Path` type
+ provides methods like `stat` on `Path`s that simply invoke the corresponding
+ function in `std::io::fs`.
+* _Skipping through conversions_. For example, the `str` type provides a
+ `.len()` convenience method which is also expressible as `.as_bytes().len()`.
+ Sometimes the conversion is more complex: the `str` module also provides
+ `from_chars`, which encapsulates a simple use of iterators.
+* _Encapsulating common arguments_. For example, vectors of `&str`s
+ provide a `connect` as well as a special case, `concat`, that is expressible
+ using `connect` with a fixed separator of `""`.
+* _Providing more efficient special cases_. The `connect` and `concat` example
+ also applies here: singling out `concat` as a special case allows for a more
+ efficient implementation.
+
+ Note, however, that the `connect` method actually detects the special case
+ internally and invokes `concat`. Usually, it is not necessary to add a public
+ convenience method just for efficiency gains; there should also be a
+ _conceptual_ reason to add it, e.g. because it is such a common special case.
+
+It is tempting to add convenience methods in a one-off, haphazard way as
+common use patterns emerge. Avoid this temptation, and instead _design_ small,
+coherent sets of convenience methods that are easy to remember:
+
+* _Small_: Avoid combinatorial explosions of convenience methods. For example,
+ instead of adding `_str` variants of methods that provide a `str` output,
+ instead ensure that the normal output type of methods is easily convertible to
+ `str`.
+* _Coherent_: Look for small groups of convenience methods that make sense to
+ include together. For example, the `Path` API mentioned above includes a small
+ selection of the most common filesystem operations that take a `Path`
+ argument. If one convenience method strongly suggests the existence of others,
+ consider adding the whole group.
+* _Memorable_: It is not worth saving a few characters of typing if you have to
+ look up the name of a convenience method every time you use it. Add
+ convenience methods with names that are obvious and easy to remember, and add
+ them for the most common or painful use cases.
--- /dev/null
+% Input to functions and methods
+
+### Let the client decide when to copy and where to place data. [FIXME: needs RFC]
+
+#### Copying:
+
+Prefer
+
+```rust
+fn foo(b: Bar) {
+ // use b as owned, directly
+}
+```
+
+over
+
+```rust
+fn foo(b: &Bar) {
+ let b = b.clone();
+ // use b as owned after cloning
+}
+```
+
+If a function requires ownership of a value of unknown type `T`, but does not
+otherwise need to make copies, the function should take ownership of the
+argument (pass by value `T`) rather than using `.clone()`. That way, the caller
+can decide whether to relinquish ownership or to `clone`.
+
+Similarly, the `Copy` trait bound should only be demanded it when absolutely
+needed, not as a way of signaling that copies should be cheap to make.
+
+#### Placement:
+
+Prefer
+
+```rust
+fn foo(b: Bar) -> Bar { ... }
+```
+
+over
+
+```rust
+fn foo(b: Box<Bar>) -> Box<Bar> { ... }
+```
+
+for concrete types `Bar` (as opposed to trait objects). This way, the caller can
+decide whether to place data on the stack or heap. No overhead is imposed by
+letting the caller determine the placement.
+
+### Minimize assumptions about parameters. [FIXME: needs RFC]
+
+The fewer assumptions a function makes about its inputs, the more widely usable
+it becomes.
+
+#### Minimizing assumptions through generics:
+
+Prefer
+
+```rust
+fn foo<T: Iterator<int>>(c: T) { ... }
+```
+
+over any of
+
+```rust
+fn foo(c: &[int]) { ... }
+fn foo(c: &Vec<int>) { ... }
+fn foo(c: &SomeOtherCollection<int>) { ... }
+```
+
+if the function only needs to iterate over the data.
+
+More generally, consider using generics to pinpoint the assumptions a function
+needs to make about its arguments.
+
+On the other hand, generics can make it more difficult to read and understand a
+function's signature. Aim for "natural" parameter types that a neither overly
+concrete nor overly abstract. See the discussion on
+[traits](../../traits/README.md) for more guidance.
+
+
+#### Minimizing ownership assumptions:
+
+Prefer either of
+
+```rust
+fn foo(b: &Bar) { ... }
+fn foo(b: &mut Bar) { ... }
+```
+
+over
+
+```rust
+fn foo(b: Bar) { ... }
+```
+
+That is, prefer borrowing arguments rather than transferring ownership, unless
+ownership is actually needed.
+
+### Prefer compound return types to out-parameters. [FIXME: needs RFC]
+
+Prefer
+
+```rust
+fn foo() -> (Bar, Bar)
+```
+
+over
+
+```rust
+fn foo(output: &mut Bar) -> Bar
+```
+
+for returning multiple `Bar` values.
+
+Compound return types like tuples and structs are efficiently compiled
+and do not require heap allocation. If a function needs to return
+multiple values, it should do so via one of these types.
+
+The primary exception: sometimes a function is meant to modify data
+that the caller already owns, for example to re-use a buffer:
+
+```rust
+fn read(&mut self, buf: &mut [u8]) -> IoResult<uint>
+```
+
+(From the [Reader trait](http://static.rust-lang.org/doc/master/std/io/trait.Reader.html#tymethod.read).)
+
+### Consider validating arguments, statically or dynamically. [FIXME: needs RFC]
+
+_Note: this material is closely related to
+ [library-level guarantees](../../safety/lib-guarantees.md)._
+
+Rust APIs do _not_ generally follow the
+[robustness principle](http://en.wikipedia.org/wiki/Robustness_principle): "be
+conservative in what you send; be liberal in what you accept".
+
+Instead, Rust code should _enforce_ the validity of input whenever practical.
+
+Enforcement can be achieved through the following mechanisms (listed
+in order of preference).
+
+#### Static enforcement:
+
+Choose an argument type that rules out bad inputs.
+
+For example, prefer
+
+```rust
+fn foo(a: ascii::Ascii) { ... }
+```
+
+over
+
+```rust
+fn foo(a: u8) { ... }
+```
+
+Note that
+[`ascii::Ascii`](http://static.rust-lang.org/doc/master/std/ascii/struct.Ascii.html)
+is a _wrapper_ around `u8` that guarantees the highest bit is zero; see
+[newtype patterns]() for more details on creating typesafe wrappers.
+
+Static enforcement usually comes at little run-time cost: it pushes the
+costs to the boundaries (e.g. when a `u8` is first converted into an
+`Ascii`). It also catches bugs early, during compilation, rather than through
+run-time failures.
+
+On the other hand, some properties are difficult or impossible to
+express using types.
+
+#### Dynamic enforcement:
+
+Validate the input as it is processed (or ahead of time, if necessary). Dynamic
+checking is often easier to implement than static checking, but has several
+downsides:
+
+1. Runtime overhead (unless checking can be done as part of processing the input).
+2. Delayed detection of bugs.
+3. Introduces failure cases, either via `fail!` or `Result`/`Option` types (see
+ the [error handling guidelines](../../errors/README.md)), which must then be
+ dealt with by client code.
+
+#### Dynamic enforcement with `debug_assert!`:
+
+Same as dynamic enforcement, but with the possibility of easily turning off
+expensive checks for production builds.
+
+#### Dynamic enforcement with opt-out:
+
+Same as dynamic enforcement, but adds sibling functions that opt out of the
+checking.
+
+The convention is to mark these opt-out functions with a suffix like
+`_unchecked` or by placing them in a `raw` submodule.
+
+The unchecked functions can be used judiciously in cases where (1) performance
+dictates avoiding checks and (2) the client is otherwise confident that the
+inputs are valid.
+
+> **[FIXME]** Should opt-out functions be marked `unsafe`?
--- /dev/null
+% Output from functions and methods
+
+### Don't overpromise. [FIXME]
+
+> **[FIXME]** Add discussion of overly-specific return types,
+> e.g. returning a compound iterator type rather than hiding it behind
+> a use of newtype.
+
+### Let clients choose what to throw away. [FIXME: needs RFC]
+
+#### Return useful intermediate results:
+
+Many functions that answer a question also compute interesting related data. If
+this data is potentially of interest to the client, consider exposing it in the
+API.
+
+Prefer
+
+```rust
+struct SearchResult {
+ found: bool, // item in container?
+ expected_index: uint // what would the item's index be?
+}
+
+fn binary_search(&self, k: Key) -> SearchResult
+```
+or
+
+```rust
+fn binary_search(&self, k: Key) -> (bool, uint)
+```
+
+over
+
+```rust
+fn binary_search(&self, k: Key) -> bool
+```
+
+#### Yield back ownership:
+
+Prefer
+
+```rust
+fn from_utf8_owned(vv: Vec<u8>) -> Result<String, Vec<u8>>
+```
+
+over
+
+```rust
+fn from_utf8_owned(vv: Vec<u8>) -> Option<String>
+```
+
+The `from_utf8_owned` function gains ownership of a vector. In the successful
+case, the function consumes its input, returning an owned string without
+allocating or copying. In the unsuccessful case, however, the function returns
+back ownership of the original slice.
--- /dev/null
+% Let binding
+
+### Always separately bind RAII guards. [FIXME: needs RFC]
+
+Prefer
+
+```rust
+fn use_mutex(m: sync::mutex::Mutex<int>) {
+ let guard = m.lock();
+ do_work(guard);
+ drop(guard); // unlock the lock
+ // do other work
+}
+```
+
+over
+
+```rust
+fn use_mutex(m: sync::mutex::Mutex<int>) {
+ do_work(m.lock());
+ // do other work
+}
+```
+
+As explained in the [RAII guide](../ownership/raii.md), RAII guards are values
+that represent ownership of some resource and whose destructor releases the
+resource. Because the lifetime of guards are significant, they should always be
+explicitly `let`-bound to make the lifetime clear. Consider using an explicit
+`drop` to release the resource early.
+
+### Prefer conditional expressions to deferred initialization. [FIXME: needs RFC]
+
+Prefer
+
+```rust
+let foo = match bar {
+ Baz => 0,
+ Quux => 1
+};
+```
+
+over
+
+```rust
+let foo;
+match bar {
+ Baz => {
+ foo = 0;
+ }
+ Quux => {
+ foo = 1;
+ }
+}
+```
+
+unless the conditions for initialization are too complex to fit into a simple
+conditional expression.
+
+### Use type annotations for clarification; prefer explicit generics when inference fails. [FIXME: needs RFC]
+
+Prefer
+
+```rust
+s.iter().map(|x| x * 2)
+ .collect::<Vec<_>>()
+```
+
+over
+
+```rust
+let v: Vec<_> = s.iter().map(|x| x * 2)
+ .collect();
+```
+
+When the type of a value might be unclear to the _reader_ of the code, consider
+explicitly annotating it in a `let`.
+
+On the other hand, when the type is unclear to the _compiler_, prefer to specify
+the type by explicit generics instantiation, which is usually more clear.
+
+### Shadowing [FIXME]
+
+> **[FIXME]** Repeatedly shadowing a binding is somewhat common in Rust code. We
+> need to articulate a guideline on when it is appropriate/useful and when not.
+
+### Prefer immutable bindings. [FIXME: needs RFC]
+
+Use `mut` bindings to signal the span during which a value is mutated:
+
+```rust
+let mut v = Vec::new();
+// push things onto v
+let v = v;
+// use v immutably henceforth
+```
+
+### Prefer to bind all `struct` or tuple fields. [FIXME: needs RFC]
+
+When consuming a `struct` or tuple via a `let`, bind all of the fields rather
+than using `..` to elide the ones you don't need. The benefit is that when
+fields are added, the compiler will pinpoint all of the places where that type
+of value was consumed, which will often need to be adjusted to take the new
+field properly into account.
--- /dev/null
+% Loops
+
+### Prefer `for` to `while`. [FIXME: needs RFC]
+
+A `for` loop is preferable to a `while` loop, unless the loop counts in a
+non-uniform way (making it difficult to express using `for`).
+
+### Guidelines for `loop`. [FIXME]
+
+> **[FIXME]** When is `loop` recommended? Some possibilities:
+> * For optimistic retry algorithms
+> * For servers
+> * To avoid mutating local variables sometimes needed to fit `while`
--- /dev/null
+% Pattern matching
+
+### Dereference `match` targets when possible. [FIXME: needs RFC]
+
+Prefer
+
+~~~~
+match *foo {
+ X(...) => ...
+ Y(...) => ...
+}
+~~~~
+
+over
+
+~~~~
+match foo {
+ box X(...) => ...
+ box Y(...) => ...
+}
+~~~~
+
+<!-- ### Clearly indicate important scopes. **[FIXME: needs RFC]** -->
+
+<!-- If it is important that the destructor for a value be executed at a specific -->
+<!-- time, clearly bind that value using a standalone `let` -->
--- /dev/null
+% Modules
+
+> **[FIXME]** What general guidelines should we provide for module design?
+
+> We should discuss visibility, nesting, `mod.rs`, and any interesting patterns
+> around modules.
+
+### Headers [FIXME: needs RFC]
+
+Organize module headers as follows:
+ 1. [Imports](../style/imports.md).
+ 1. `mod` declarations.
+ 1. `pub mod` declarations.
+
+### Avoid `path` directives. [FIXME: needs RFC]
+
+Avoid using `#[path="..."]` directives; make the file system and
+module hierarchy match, instead.
+
+### Use the module hirearchy to organize APIs into coherent sections. [FIXME]
+
+> **[FIXME]** Flesh this out with examples; explain what a "coherent
+> section" is with examples.
+>
+> The module hirearchy defines both the public and internal API of your module.
+> Breaking related functionality into submodules makes it understandable to both
+> users and contributors to the module.
+
+### Place modules in their own file. [FIXME: needs RFC]
+
+> **[FIXME]**
+> - "<100 lines" is arbitrary, but it's a clearer recommendation
+> than "~1 page" or similar suggestions that vary by screen size, etc.
+
+For all except very short modules (<100 lines) and [tests](../testing/README.md),
+place the module `foo` in a separate file, as in:
+
+```rust
+pub mod foo;
+
+// in foo.rs or foo/mod.rs
+pub fn bar() { println!("..."); }
+/* ... */
+```
+
+rather than declaring it inline:
+
+```rust
+pub mod foo {
+ pub fn bar() { println!("..."); }
+ /* ... */
+}
+```
+
+#### Use subdirectories for modules with children. [FIXME: needs RFC]
+
+For modules that themselves have submodules, place the module in a separate
+directory (e.g., `bar/mod.rs` for a module `bar`) rather than the same directory.
+
+Note the structure of
+[`std::io`](http://doc.rust-lang.org/std/io/). Many of the submodules lack
+children, like
+[`io::fs`](http://doc.rust-lang.org/std/io/fs/)
+and
+[`io::stdio`](http://doc.rust-lang.org/std/io/stdio/).
+On the other hand,
+[`io::net`](http://doc.rust-lang.org/std/io/net/)
+contains submodules, so it lives in a separate directory:
+
+```
+io/mod.rs
+ io/extensions.rs
+ io/fs.rs
+ io/net/mod.rs
+ io/net/addrinfo.rs
+ io/net/ip.rs
+ io/net/tcp.rs
+ io/net/udp.rs
+ io/net/unix.rs
+ io/pipe.rs
+ ...
+```
+
+While it is possible to define all of `io` within a single directory,
+mirroring the module hirearchy in the directory structure makes
+submodules of `io::net` easier to find.
+
+### Consider top-level definitions or reexports. [FIXME: needs RFC]
+
+For modules with submodules,
+define or [reexport](http://doc.rust-lang.org/std/io/#reexports) commonly used
+definitions at the top level:
+
+* Functionality relevant to the module itself or to many of its
+ children should be defined in `mod.rs`.
+* Functionality specific to a submodule should live in that
+ submodule. Reexport at the top level for the most important or
+ common definitions.
+
+For example,
+[`IoError`](http://doc.rust-lang.org/std/io/struct.IoError.html)
+is defined in `io/mod.rs`, since it pertains to the entirety of `io`,
+while
+[`TcpStream`](http://doc.rust-lang.org/std/io/net/tcp/struct.TcpStream.html)
+is defined in `io/net/tcp.rs` and reexported in the `io` module.
+
+### Use internal module hirearchies for organization. [FIXME: needs RFC]
+
+> **[FIXME]**
+> - Referencing internal modules from the standard library is subject to
+> becoming outdated.
+
+Internal module hirearchies (i.e., private submodules) may be used to
+hide implementation details that are not part of the module's API.
+
+For example, in [`std::io`](http://doc.rust-lang.org/std/io/), `mod mem`
+provides implementations for
+[`BufReader`](http://doc.rust-lang.org/std/io/struct.BufReader.html)
+and
+[`BufWriter`](http://doc.rust-lang.org/std/io/struct.BufWriter.html),
+but these are re-exported in `io/mod.rs` at the top level of the module:
+
+```rust
+// libstd/io/mod.rs
+
+pub use self::mem::{MemReader, BufReader, MemWriter, BufWriter};
+/* ... */
+mod mem;
+```
+
+This hides the detail that there even exists a `mod mem` in `io`, and
+helps keep code organized while offering freedom to change the
+implementation.
--- /dev/null
+% Traits
+
+Traits are probably Rust's most complex feature, supporting a wide range of use
+cases and design tradeoffs. Patterns of trait usage are still emerging.
+
+### Know whether a trait will be used as an object. [FIXME: needs RFC]
+
+Trait objects have some [significant limitations](objects.md): methods
+invoked through a trait object cannot use generics, and cannot use
+`Self` except in receiver position.
+
+When designing a trait, decide early on whether the trait will be used
+as an [object](objects.md) or as a [bound on generics](generics.md);
+the tradeoffs are discussed in each of the linked sections.
+
+If a trait is meant to be used as an object, its methods should take
+and return trait objects rather than use generics.
+
+
+### Default methods [FIXME]
+
+> **[FIXME]** Guidelines for default methods.
--- /dev/null
+% Common traits
+
+### Eagerly implement common traits. [FIXME: needs RFC]
+
+Rust's trait system does not allow _orphans_: roughly, every `impl` must live
+either in the crate that defines the trait or the implementing
+type. Consequently, crates that define new types should eagerly implement all
+applicable, common traits.
+
+To see why, consider the following situation:
+
+* Crate `std` defines trait `Show`.
+* Crate `url` defines type `Url`, without implementing `Show`.
+* Crate `webapp` imports from both `std` and `url`,
+
+There is no way for `webapp` to add `Show` to `url`, since it defines neither.
+(Note: the newtype pattern can provide an efficient, but inconvenient
+workaround; see [newtype for views](../types/newtype.md))
+
+The most important common traits to implement from `std` are:
+
+```rust
+Clone, Show, Hash, Eq
+```
+
+#### When safe, derive or otherwise implement `Send` and `Share`. [FIXME]
+
+> **[FIXME]**. This guideline is in flux while the "opt-in" nature of
+> built-in traits is being decided. See https://github.com/rust-lang/rfcs/pull/127
+
+### Prefer to derive, rather than implement. [FIXME: needs RFC]
+
+Deriving saves implementation effort, makes correctness trivial, and
+automatically adapts to upstream changes.
+
+### Do not overload operators in surprising ways. [FIXME: needs RFC]
+
+Operators with built in syntax (`*`, `|`, and so on) can be provided for a type
+by implementing the traits in `core::ops`. These operators come with strong
+expectations: implement `Mul` only for an operation that bears some resemblance
+to multiplication (and shares the expected properties, e.g. associativity), and
+so on for the other traits.
+
+### The `Drop` trait
+
+The `Drop` trait is treated specially by the compiler as a way of
+associating destructors with types. See
+[the section on destructors](../../ownership/destructors.md) for
+guidance.
+
+### The `Deref`/`DerefMut` traits
+
+#### Use `Deref`/`DerefMut` only for smart pointers. [FIXME: needs RFC]
+
+The `Deref` traits are used implicitly by the compiler in many circumstances,
+and interact with method resolution. The relevant rules are designed
+specifically to accommodate smart pointers, and so the traits should be used
+only for that purpose.
+
+#### Do not fail within a `Deref`/`DerefMut` implementation. [FIXME: needs RFC]
+
+Because the `Deref` traits are invoked implicitly by the compiler in sometimes
+subtle ways, failure during dereferencing can be extremely confusing. If a
+dereference might not succeed, target the `Deref` trait as a `Result` or
+`Option` type instead.
+
+#### Avoid inherent methods when implementing `Deref`/`DerefMut` [FIXME: needs RFC]
+
+The rules around method resolution and `Deref` are in flux, but inherent methods
+on a type implementing `Deref` are likely to shadow any methods of the referent
+with the same name.
--- /dev/null
+% Using traits to add extension methods
+
+> **[FIXME]** Elaborate.
+
+### Consider using default methods rather than extension traits **[FIXME]**
+
+> **[FIXME]** Elaborate.
--- /dev/null
+% Using traits for bounds on generics
+
+The most widespread use of traits is for writing generic functions or types. For
+example, the following signature describes a function for consuming any iterator
+yielding items of type `A` to produce a collection of `A`:
+
+```rust
+fn from_iter<T: Iterator<A>>(iterator: T) -> SomeCollection<A>
+```
+
+Here, the `Iterator` trait is specifies an interface that a type `T` must
+explicitly implement to be used by this generic function.
+
+**Pros**:
+
+* _Reusability_. Generic functions can be applied to an open-ended collection of
+ types, while giving a clear contract for the functionality those types must
+ provide.
+* _Static dispatch and optimization_. Each use of a generic function is
+ specialized ("monomorphized") to the particular types implementing the trait
+ bounds, which means that (1) invocations of trait methods are static, direct
+ calls to the implementation and (2) the compiler can inline and otherwise
+ optimize these calls.
+* _Inline layout_. If a `struct` and `enum` type is generic over some type
+ parameter `T`, values of type `T` will be laid out _inline_ in the
+ `struct`/`enum`, without any indirection.
+* _Inference_. Since the type parameters to generic functions can usually be
+ inferred, generic functions can help cut down on verbosity in code where
+ explicit conversions or other method calls would usually be necessary. See the
+ [overloading/implicits use case](#use-case:-limited-overloading-and/or-implicit-conversions)
+ below.
+* _Precise types_. Because generic give a _name_ to the specific type
+ implementing a trait, it is possible to be precise about places where that
+ exact type is required or produced. For example, a function
+
+ ```rust
+ fn binary<T: Trait>(x: T, y: T) -> T
+ ```
+
+ is guaranteed to consume and produce elements of exactly the same type `T`; it
+ cannot be invoked with parameters of different types that both implement
+ `Trait`.
+
+**Cons**:
+
+* _Code size_. Specializing generic functions means that the function body is
+ duplicated. The increase in code size must be weighed against the performance
+ benefits of static dispatch.
+* _Homogeneous types_. This is the other side of the "precise types" coin: if
+ `T` is a type parameter, it stands for a _single_ actual type. So for example
+ a `Vec<T>` contains elements of a single concrete type (and, indeed, the
+ vector representation is specialized to lay these out in line). Sometimes
+ heterogeneous collections are useful; see
+ [trait objects](#use-case:-trait-objects) below.
+* _Signature verbosity_. Heavy use of generics can bloat function signatures.
+ **[Ed. note]** This problem may be mitigated by some language improvements; stay tuned.
+
+### Favor widespread traits. **[FIXME: needs RFC]**
+
+Generic types are a form of abstraction, which entails a mental indirection: if
+a function takes an argument of type `T` bounded by `Trait`, clients must first
+think about the concrete types that implement `Trait` to understand how and when
+the function is callable.
+
+To keep the cost of abstraction low, favor widely-known traits. Whenever
+possible, implement and use traits provided as part of the standard library. Do
+not introduce new traits for generics lightly; wait until there are a wide range
+of types that can implement the type.
--- /dev/null
+% Using trait objects
+
+> **[FIXME]** What are uses of trait objects other than heterogeneous collections?
+
+Trait objects are useful primarily when _heterogeneous_ collections of objects
+need to be treated uniformly; it is the closest that Rust comes to
+object-oriented programming.
+
+```rust
+struct Frame { ... }
+struct Button { ... }
+struct Label { ... }
+
+trait Widget { ... }
+
+impl Widget for Frame { ... }
+impl Widget for Button { ... }
+impl Widget for Label { ... }
+
+impl Frame {
+ fn new(contents: &[Box<Widget>]) -> Frame {
+ ...
+ }
+}
+
+fn make_gui() -> Box<Widget> {
+ let b: Box<Widget> = box Button::new(...);
+ let l: Box<Widget> = box Label::new(...);
+
+ box Frame::new([b, l]) as Box<Widget>
+}
+```
+
+By using trait objects, we can set up a GUI framework with a `Frame` widget that
+contains a heterogeneous collection of children widgets.
+
+**Pros**:
+
+* _Heterogeneity_. When you need it, you really need it.
+* _Code size_. Unlike generics, trait objects do not generate specialized
+ (monomorphized) versions of code, which can greatly reduce code size.
+
+**Cons**:
+
+* _No generic methods_. Trait objects cannot currently provide generic methods.
+* _Dynamic dispatch and fat pointers_. Trait objects inherently involve
+ indirection and vtable dispatch, which can carry a performance penalty.
+* _No Self_. Except for the method receiver argument, methods on trait objects
+ cannot use the `Self` type.
--- /dev/null
+% Using traits for overloading
+
+> **[FIXME]** Elaborate.
+
+> **[FIXME]** We need to decide on guidelines for this use case. There are a few
+> patterns emerging in current Rust code, but it's not clear how widespread they
+> should be.
--- /dev/null
+% Using traits to share implementations
+
+> **[FIXME]** Elaborate.
+
+> **[FIXME]** We probably want to discourage this, at least when used in a way
+> that is publicly exposed.
+
+Traits that provide default implmentations for function can provide code reuse
+across types. For example, a `print` method can be defined across multiple
+types as follows:
+
+``` Rust
+trait Printable {
+ // Default method implementation
+ fn print(&self) { println!("{:?}", *self) }
+}
+
+impl Printable for int {}
+
+impl Printable for String {
+ fn print(&self) { println!("{}", *self) }
+}
+
+impl Printable for bool {}
+
+impl Printable for f32 {}
+```
+
+This allows the implementation of `print` to be shared across types, yet
+overridden where needed, as seen in the `impl` for `String`.
--- /dev/null
+% Data types
+
+### Use custom types to imbue meaning; do not abuse `bool`, `Option` or other core types. **[FIXME: needs RFC]**
+
+Prefer
+
+```rust
+let w = Widget::new(Small, Round)
+```
+
+over
+
+```rust
+let w = Widget::new(true, false)
+```
+
+Core types like `bool`, `u8` and `Option` have many possible interpretations.
+
+Use custom types (whether `enum`s, `struct`, or tuples) to convey
+interpretation and invariants. In the above example,
+it is not immediately clear what `true` and `false` are conveying without
+looking up the argument names, but `Small` and `Round` are more suggestive.
+
+Using custom types makes it easier to expand the
+options later on, for example by adding an `ExtraLarge` variant.
+
+See [the newtype pattern](newtype.md) for a no-cost way to wrap
+existing types with a distinguished name.
+
+### Prefer private fields, except for passive data. **[FIXME: needs RFC]**
+
+Making a field public is a strong commitment: it pins down a representation
+choice, _and_ prevents the type from providing any validation or maintaining any
+invariants on the contents of the field, since clients can mutate it arbitrarily.
+
+Public fields are most appropriate for `struct` types in the C spirit: compound,
+passive data structures. Otherwise, consider providing getter/setter methods
+and hiding fields instead.
+
+> **[FIXME]** Cross-reference validation for function arguments.
+
+### Use custom `enum`s for alternatives, `bitflags` for C-style flags. **[FIXME: needs RFC]**
+
+Rust supports `enum` types with "custom discriminants":
+
+~~~~
+enum Color {
+ Red = 0xff0000,
+ Green = 0x00ff00,
+ Blue = 0x0000ff
+}
+~~~~
+
+Custom discriminants are useful when an `enum` type needs to be serialized to an
+integer value compatibly with some other system/language. They support
+"typesafe" APIs: by taking a `Color`, rather than an integer, a function is
+guaranteed to get well-formed inputs, even if it later views those inputs as
+integers.
+
+An `enum` allows an API to request exactly one choice from among many. Sometimes
+an API's input is instead the presence or absence of a set of flags. In C code,
+this is often done by having each flag correspond to a particular bit, allowing
+a single integer to represent, say, 32 or 64 flags. Rust's `std::bitflags`
+module provides a typesafe way for doing so.
+
+### Phantom types. [FIXME]
+
+> **[FIXME]** Add some material on phantom types (https://blog.mozilla.org/research/2014/06/23/static-checking-of-units-in-servo/)
--- /dev/null
+% Conversions between types
+
+### Associate conversions with the most specific type involved. **[FIXME: needs RFC]**
+
+When in doubt, prefer `to_`/`as_`/`into_` to `from_`, because they are
+more ergonomic to use (and can be chained with other methods).
+
+For many conversions between two types, one of the types is clearly more
+"specific": it provides some additional invariant or interpretation that is not
+present in the other type. For example, `str` is more specific than `&[u8]`,
+since it is a utf-8 encoded sequence of bytes.
+
+Conversions should live with the more specific of the involved types. Thus,
+`str` provides both the `as_bytes` method and the `from_utf8` constructor for
+converting to and from `&[u8]` values. Besides being intuitive, this convention
+avoids polluting concrete types like `&[u8]` with endless conversion methods.
+
+### Explicitly mark lossy conversions, or do not label them as conversions. **[FIXME: needs RFC]**
+
+If a function's name implies that it is a conversion (prefix `from_`, `as_`,
+`to_` or `into_`), but the function loses information, add a suffix `_lossy` or
+otherwise indicate the lossyness. Consider avoiding the conversion name prefix.
--- /dev/null
+% The newtype pattern
+
+A "newtype" is a tuple or `struct` with a single field. The terminology is borrowed from Haskell.
+
+Newtypes are a zero-cost abstraction: they introduce a new, distinct name for an
+existing type, with no runtime overhead when converting between the two types.
+
+### Use newtypes to provide static distinctions. [FIXME: needs RFC]
+
+Newtypes can statically distinguish between different interpretations of an
+underlying type.
+
+For example, a `f64` value might be used to represent a quantity in miles or in
+kilometers. Using newtypes, we can keep track of the intended interpretation:
+
+```rust
+struct Miles(pub f64);
+struct Kilometers(pub f64);
+
+impl Miles {
+ fn as_kilometers(&self) -> Kilometers { ... }
+}
+impl Kilometers {
+ fn as_miles(&self) -> Miles { ... }
+}
+```
+
+Once we have separated these two types, we can statically ensure that we do not
+confuse them. For example, the function
+
+```rust
+fn are_we_there_yet(distance_travelled: Miles) -> bool { ... }
+```
+
+cannot accidentally be called with a `Kilometers` value. The compiler will
+remind us to perform the conversion, thus averting certain
+[catastrophic bugs](http://en.wikipedia.org/wiki/Mars_Climate_Orbiter).
+
+### Use newtypes with private fields for hiding. [FIXME: needs RFC]
+
+A newtype can be used to hide representation details while making precise
+promises to the client.
+
+For example, consider a function `my_transform` that returns a compound iterator
+type `Enumerate<Skip<vec::MoveItems<T>>>`. We wish to hide this type from the
+client, so that the client's view of the return type is roughly `Iterator<(uint,
+T)>`. We can do so using the newtype pattern:
+
+```rust
+struct MyTransformResult<T>(Enumerate<Skip<vec::MoveItems<T>>>);
+impl<T> Iterator<(uint, T)> for MyTransformResult<T> { ... }
+
+fn my_transform<T, Iter: Iterator<T>>(iter: Iter) -> MyTransformResult<T> {
+ ...
+}
+```
+
+Aside from simplifying the signature, this use of newtypes allows us to make a
+expose and promise less to the client. The client does not know _how_ the result
+iterator is constructed or represented, which means the representation can
+change in the future without breaking client code.
+
+> **[FIXME]** Interaction with auto-deref.
+
+### Use newtypes to provide cost-free _views_ of another type. **[FIXME]**
+
+> **[FIXME]** Describe the pattern of using newtypes to provide a new set of
+> inherent or trait methods, providing a different perspective on the underlying
+> type.
--- /dev/null
+% Ownership and resource management
+
+> **[FIXME]** Add general remarks about ownership/resources here.
--- /dev/null
+% The builder pattern
+
+Some data structures are complicated to construct, due to their construction needing:
+
+* a large number of inputs
+* compound data (e.g. slices)
+* optional configuration data
+* choice between several flavors
+
+which can easily lead to a large number of distinct constructors with
+many arguments each.
+
+If `T` is such a data structure, consider introducing a `T` _builder_:
+
+1. Introduce a separate data type `TBuilder` for incrementally configuring a `T`
+ value. When possible, choose a better name: e.g. `Command` is the builder for
+ `Process`.
+2. The builder constructor should take as parameters only the data _required_ to
+ to make a `T`.
+3. The builder should offer a suite of convenient methods for configuration,
+ including setting up compound inputs (like slices) incrementally.
+ These methods should return `self` to allow chaining.
+4. The builder should provide one or more "_terminal_" methods for actually building a `T`.
+
+The builder pattern is especially appropriate when building a `T` involves side
+effects, such as spawning a task or launching a process.
+
+In Rust, there are two variants of the builder pattern, differing in the
+treatment of ownership, as described below.
+
+### Non-consuming builders (preferred):
+
+In some cases, constructing the final `T` does not require the builder itself to
+be consumed. The follow variant on
+[`std::io::process::Command`](http://static.rust-lang.org/doc/master/std/io/process/struct.Command.html)
+is one example:
+
+```rust
+// NOTE: the actual Command API does not use owned Strings;
+// this is a simplified version.
+
+pub struct Command {
+ program: String,
+ args: Vec<String>,
+ cwd: Option<String>,
+ // etc
+}
+
+impl Command {
+ pub fn new(program: String) -> Command {
+ Command {
+ program: program,
+ args: Vec::new(),
+ cwd: None,
+ }
+ }
+
+ /// Add an argument to pass to the program.
+ pub fn arg<'a>(&'a mut self, arg: String) -> &'a mut Command {
+ self.args.push(arg);
+ self
+ }
+
+ /// Add multiple arguments to pass to the program.
+ pub fn args<'a>(&'a mut self, args: &[String])
+ -> &'a mut Command {
+ self.args.push_all(args);
+ self
+ }
+
+ /// Set the working directory for the child process.
+ pub fn cwd<'a>(&'a mut self, dir: String) -> &'a mut Command {
+ self.cwd = Some(dir);
+ self
+ }
+
+ /// Executes the command as a child process, which is returned.
+ pub fn spawn(&self) -> IoResult<Process> {
+ ...
+ }
+}
+```
+
+Note that the `spawn` method, which actually uses the builder configuration to
+spawn a process, takes the builder by immutable reference. This is possible
+because spawning the process does not require ownership of the configuration
+data.
+
+Because the terminal `spawn` method only needs a reference, the configuration
+methods take and return a mutable borrow of `self`.
+
+#### The benefit
+
+By using borrows throughout, `Command` can be used conveniently for both
+one-liner and more complex constructions:
+
+```rust
+// One-liners
+Command::new("/bin/cat").arg("file.txt").spawn();
+
+// Complex configuration
+let mut cmd = Command::new("/bin/ls");
+cmd.arg(".");
+
+if size_sorted {
+ cmd.arg("-S");
+}
+
+cmd.spawn();
+```
+
+### Consuming builders:
+
+Sometimes builders must transfer ownership when constructing the final type
+`T`, meaning that the terminal methods must take `self` rather than `&self`:
+
+```rust
+// A simplified excerpt from std::task::TaskBuilder
+
+impl TaskBuilder {
+ /// Name the task-to-be. Currently the name is used for identification
+ /// only in failure messages.
+ pub fn named(mut self, name: String) -> TaskBuilder {
+ self.name = Some(name);
+ self
+ }
+
+ /// Redirect task-local stdout.
+ pub fn stdout(mut self, stdout: Box<Writer + Send>) -> TaskBuilder {
+ self.stdout = Some(stdout);
+ // ^~~~~~ this is owned and cannot be cloned/re-used
+ self
+ }
+
+ /// Creates and executes a new child task.
+ pub fn spawn(self, f: proc():Send) {
+ // consume self
+ ...
+ }
+}
+```
+
+Here, the `stdout` configuration involves passing ownership of a `Writer`,
+which must be transferred to the task upon construction (in `spawn`).
+
+When the terminal methods of the builder require ownership, there is a basic tradeoff:
+
+* If the other builder methods take/return a mutable borrow, the complex
+ configuration case will work well, but one-liner configuration becomes
+ _impossible_.
+
+* If the other builder methods take/return an owned `self`, one-liners
+ continue to work well but complex configuration is less convenient.
+
+Under the rubric of making easy things easy and hard things possible, _all_
+builder methods for a consuming builder should take and returned an owned
+`self`. Then client code works as follows:
+
+```rust
+// One-liners
+TaskBuilder::new().named("my_task").spawn(proc() { ... });
+
+// Complex configuration
+let mut task = TaskBuilder::new();
+task = task.named("my_task_2"); // must re-assign to retain ownership
+
+if reroute {
+ task = task.stdout(mywriter);
+}
+
+task.spawn(proc() { ... });
+```
+
+One-liners work as before, because ownership is threaded through each of the
+builder methods until being consumed by `spawn`. Complex configuration,
+however, is more verbose: it requires re-assigning the builder at each step.
--- /dev/null
+% Cells and smart pointers
+
+> **[FIXME]** Add guidelines about when to use Cell, RefCell, Rc and
+> Arc (and how to use them together).
--- /dev/null
+% Constructors
+
+### Define constructors as static, inherent methods. [FIXME: needs RFC]
+
+In Rust, "constructors" are just a convention:
+
+```rust
+impl<T> Vec<T> {
+ pub fn new() -> Vec<T> { ... }
+}
+```
+
+Constructors are static (no `self`) inherent methods for the type that they
+construct. Combined with the practice of
+[fully importing type names](../style/imports.md), this convention leads to
+informative but concise construction:
+
+```rust
+use vec::Vec;
+
+// construct a new vector
+let mut v = Vec::new();
+```
+
+This convention also applied to conversion constructors (prefix `from` rather
+than `new`).
+
+### Provide constructors for passive `struct`s with defaults. [FIXME: needs RFC]
+
+Given the `struct`
+
+```rust
+pub struct Config {
+ pub color: Color,
+ pub size: Size,
+ pub shape: Shape,
+}
+```
+
+provide a constructor if there are sensible defaults:
+
+```rust
+impl Config {
+ pub fn new() -> Config {
+ Config {
+ color: Brown,
+ size: Medium,
+ shape: Square,
+ }
+ }
+}
+```
+
+which then allows clients to concisely override using `struct` update syntax:
+
+```rust
+Config { color: Red, .. Config::new() };
+```
+
+See the [guideline for field privacy](../features/types/README.md) for
+discussion on when to create such "passive" `struct`s with public
+fields.
--- /dev/null
+% Destructors
+
+Unlike constructors, destructors in Rust have a special status: they are added
+by implementing `Drop` for a type, and they are automatically invoked as values
+go out of scope.
+
+> **[FIXME]** This section needs to be expanded.
+
+### Destructors should not fail. [FIXME: needs RFC]
+
+Destructors are executed on task failure, and in that context a failing
+destructor causes the program to abort.
+
+Instead of failing in a destructor, provide a separate method for checking for
+clean teardown, e.g. a `close` method, that returns a `Result` to signal
+problems.
+
+### Destructors should not block. [FIXME: needs RFC]
+
+Similarly, destructors should not invoke blocking operations, which can make
+debugging much more difficult. Again, consider providing a separate method for
+preparing for an infallible, nonblocking teardown.
--- /dev/null
+% RAII
+
+Resource Acquisition is Initialization
+
+> **[FIXME]** Explain the RAII pattern and give best practices.
+
+### Whenever possible, tie resource access to guard scopes [FIXME]
+
+> **[FIXME]** Example: Mutex guards guarantee that access to the
+> protected resource only happens when the guard is in scope.
+
+`must_use`
--- /dev/null
+% FFI and platform-specific code **[FIXME]**
+
+> **[FIXME]** Not sure where this should live.
+
+When writing cross-platform code, group platform-specific code into a
+module called `platform`. Avoid `#[cfg]` directives outside this
+`platform` module.
--- /dev/null
+% Safety and guarantees
+
+> **[FIXME]** Is there a better phrase than "strong guarantees" that encompasses
+> both e.g. memory safety and e.g. data structure invariants?
+
+A _guarantee_ is a property that holds no matter what client code does, unless
+the client explicitly opts out:
+
+* Rust guarantees memory safety and data-race freedom, with `unsafe`
+ blocks as an opt-out mechanism.
+
+* APIs in Rust often provide their own guarantees. For example, `std::str`
+guarantees that its underlying buffer is valid utf-8. The `std::path::Path` type
+guarantees no interior nulls. Both strings and paths provide `unsafe` mechanisms
+for opting out of these guarantees (and thereby avoiding runtime checks).
+
+Thinking about guarantees is an essential part of writing good Rust code. The
+rest of this subsection outlines some cross-cutting principles around
+guarantees.
--- /dev/null
+% Library-level guarantees
+
+Most libraries rely on internal invariants, e.g. about their data, resource
+ownership, or protocol states. In Rust, broken invariants cannot produce
+segfaults, but they can still lead to wrong answers.
+
+### Provide library-level guarantees whenever practical. **[FIXME: needs RFC]**
+
+Library-level invariants should be turned into guarantees whenever
+practical. They should hold no matter what the client does, modulo
+explicit opt-outs. Depending on the kind of invariant, this can be
+achieved through a combination of static and dynamic enforcement, as
+described below.
+
+#### Static enforcement:
+
+Guaranteeing invariants almost always requires _hiding_,
+i.e. preventing the client from directly accessing or modifying
+internal data.
+
+For example, the representation of the `str` type is hidden,
+which means that any value of type `str` must have been produced
+through an API under the control of the `str` module, and these
+APIs in turn ensure valid utf-8 encoding.
+
+Rust's type system makes it possible to provide guarantees even while
+revealing more of the representation than usual. For example, the
+`as_bytes()` method on `&str` gives a _read-only_ view into the
+underlying buffer, which cannot be used to violate the utf-8 property.
+
+#### Dynamic enforcement:
+
+Malformed inputs from the client are hazards to library-level
+guarantees, so library APIs should validate their input.
+
+For example, `std::str::from_utf8_owned` attempts to convert a `u8`
+slice into an owned string, but dynamically checks that the slice is
+valid utf-8 and returns `Err` if not.
+
+See
+[the discussion on input validation](../features/functions-and-methods/input.md)
+for more detail.
+
+
+### Prefer static enforcement of guarantees. **[FIXME: needs RFC]**
+
+Static enforcement provides two strong benefits over dynamic enforcement:
+
+* Bugs are caught at compile time.
+* There is no runtime cost.
+
+Sometimes purely static enforcement is impossible or impractical. In these
+cases, a library should check as much as possible statically, but defer to
+dynamic checks where needed.
+
+For example, the `std::string` module exports a `String` type with the guarantee
+that all instances are valid utf-8:
+
+* Any _consumer_ of a `String` is statically guaranteed utf-8 contents. For example,
+ the `append` method can push a `&str` onto the end of a `String` without
+ checking anything dynamically, since the existing `String` and `&str` are
+ statically guaranteed to be in utf-8.
+
+* Some _producers_ of a `String` must perform dynamic checks. For example, the
+ `from_utf8` function attempts to convert a `Vec<u8>` into a `String`, but
+ dynamically checks that the contents are utf-8.
+
+### Provide opt-outs with caution; make them explicit. **[FIXME: needs RFC]**
+
+Providing library-level guarantees sometimes entails inconvenience (for static
+checks) or overhead (for dynamic checks). So it is sometimes desirable to allow
+clients to sidestep this checking, while promising to use the API in a way that
+still provides the guarantee. Such escape hatches should only be be introduced
+when there is a demonstrated need for them.
+
+It should be trivial for clients to audit their use of the library for
+escape hatches.
+
+See
+[the discussion on input validation](../features/functions-and-methods/input.md)
+for conventions on marking opt-out functions.
--- /dev/null
+% Using `unsafe`
+
+### Unconditionally guarantee safety, or mark API as `unsafe`. **[FIXME: needs RFC]**
+
+Memory safety, type safety, and data race freedom are basic assumptions for all
+Rust code.
+
+APIs that use `unsafe` blocks internally thus have two choices:
+
+* They can guarantee safety _unconditionally_ (i.e., regardless of client
+ behavior or inputs) and be exported as safe code. Any safety violation is then
+ the library's fault, not the client's fault.
+
+* They can export potentially unsafe functions with the `unsafe` qualifier. In
+ this case, the documentation should make very clear the conditions under which
+ safety is guaranteed.
+
+The result is that a client program can never violate safety merely by having a
+bug; it must have explicitly opted out by using an `unsafe` block.
+
+Of the two options for using `unsafe`, creating such safe abstractions (the
+first option above) is strongly preferred.
--- /dev/null
+% Style
+
+This section gives a set of strict rules for styling Rust code.
+
+> **[FIXME]** General remarks about the style guidelines
--- /dev/null
+% Braces, semicolons, and commas [FIXME: needs RFC]
+
+### Opening braces always go on the same line.
+
+``` rust
+fn foo() {
+ ...
+}
+
+fn frobnicate(a: Bar, b: Bar,
+ c: Bar, d: Bar)
+ -> Bar {
+ ...
+}
+
+trait Bar {
+ fn baz(&self);
+}
+
+impl Bar for Baz {
+ fn baz(&self) {
+ ...
+ }
+}
+
+frob(|x| {
+ x.transpose()
+})
+```
+
+### `match` arms get braces, except for single-line expressions.
+
+``` rust
+match foo {
+ bar => baz,
+ quux => {
+ do_something();
+ do_something_else()
+ }
+}
+```
+
+### `return` statements get semicolons.
+
+``` rust
+fn foo() {
+ do_something();
+
+ if condition() {
+ return;
+ }
+
+ do_something_else();
+}
+```
+
+### Trailing commas
+
+> **[FIXME]** We should have a guideline for when to include trailing
+> commas in `struct`s, `match`es, function calls, etc.
+>
+> One possible rule: a trailing comma should be included whenever the
+> closing delimiter appears on a separate line:
+
+```rust
+Foo { bar: 0, baz: 1 }
+
+Foo {
+ bar: 0,
+ baz: 1,
+}
+
+match a_thing {
+ None => 0,
+ Some(x) => 1,
+}
+```
--- /dev/null
+% Comments [FIXME: needs RFC]
+
+### Avoid block comments.
+
+Use line comments:
+
+``` rust
+// Wait for the main task to return, and set the process error code
+// appropriately.
+```
+
+Instead of:
+
+``` rust
+/*
+ * Wait for the main task to return, and set the process error code
+ * appropriately.
+ */
+```
+
+## Doc comments
+
+Doc comments are prefixed by three slashes (`///`) and indicate
+documentation that you would like to be included in Rustdoc's output.
+They support
+[Markdown syntax](https://en.wikipedia.org/wiki/Markdown)
+and are the main way of documenting your public APIs.
+
+The supported markdown syntax includes all of the extensions listed in the
+[GitHub Flavored Markdown]
+(https://help.github.com/articles/github-flavored-markdown) documentation,
+plus superscripts.
+
+### Summary line
+
+The first line in any doc comment should be a single-line short sentence
+providing a summary of the code. This line is used as a short summary
+description throughout Rustdoc's output, so it's a good idea to keep it
+short.
+
+### Sentence structure
+
+All doc comments, including the summary line, should begin with a
+capital letter and end with a period, question mark, or exclamation
+point. Prefer full sentences to fragments.
+
+The summary line should be written in
+[third person singular present indicative form]
+(http://en.wikipedia.org/wiki/English_verbs#Third_person_singular_present).
+Basically, this means write "Returns" instead of "Return".
+
+For example:
+
+``` rust
+/// Sets up a default runtime configuration, given compiler-supplied arguments.
+///
+/// This function will block until the entire pool of M:N schedulers has
+/// exited. This function also requires a local task to be available.
+///
+/// # Arguments
+///
+/// * `argc` & `argv` - The argument vector. On Unix this information is used
+/// by `os::args`.
+/// * `main` - The initial procedure to run inside of the M:N scheduling pool.
+/// Once this procedure exits, the scheduling pool will begin to shut
+/// down. The entire pool (and this function) will only return once
+/// all child tasks have finished executing.
+///
+/// # Return value
+///
+/// The return value is used as the process return code. 0 on success, 101 on
+/// error.
+```
+
+### Code snippets
+
+> **[FIXME]**
+
+### Avoid inner doc comments.
+
+Use inner doc comments _only_ to document crates and file-level modules:
+
+``` rust
+//! The core library.
+//!
+//! The core library is a something something...
+```
--- /dev/null
+## `return` [FIXME: needs RFC]
+
+Terminate `return` statements with semicolons:
+
+``` rust
+fn foo(bar: int) -> Option<int> {
+ if some_condition() {
+ return None;
+ }
+
+ ...
+}
+```
--- /dev/null
+% Imports [FIXME: needs RFC]
+
+The imports of a crate/module should consist of the following
+sections, in order, with a blank space between each:
+
+* `extern crate` directives
+* external `use` imports
+* local `use` imports
+* `pub use` imports
+
+For example:
+
+```rust
+// Crates.
+extern crate getopts;
+extern crate mylib;
+
+// Standard library imports.
+use getopts::{optopt, getopts};
+use std::os;
+
+// Import from a library that we wrote.
+use mylib::webserver;
+
+// Will be reexported when we import this module.
+pub use self::types::Webdata;
+```
+
+### Avoid `use *`, except in tests.
+
+Glob imports have several downsides:
+* They make it harder to tell where names are bound.
+* They are forwards-incompatible, since new upstream exports can clash
+ with existing names.
+
+When writing a [`test` submodule](../testing/README.md), importing `super::*` is appropriate
+as a convenience.
+
+### Prefer fully importing types/traits while module-qualifying functions.
+
+For example:
+
+```rust
+use option::Option;
+use mem;
+
+let i: int = mem::transmute(Option(0));
+```
+
+> **[FIXME]** Add rationale.
--- /dev/null
+% Naming conventions
+
+### General conventions [RFC #430]
+
+> The guidelines below were approved by [RFC #430](https://github.com/rust-lang/rfcs/pull/430).
+
+In general, Rust tends to use `CamelCase` for "type-level" constructs
+(types and traits) and `snake_case` for "value-level" constructs. More
+precisely:
+
+| Item | Convention |
+| ---- | ---------- |
+| Crates | `snake_case` (but prefer single word) |
+| Modules | `snake_case` |
+| Types | `CamelCase` |
+| Traits | `CamelCase` |
+| Enum variants | `CamelCase` |
+| Functions | `snake_case` |
+| Methods | `snake_case` |
+| General constructors | `new` or `with_more_details` |
+| Conversion constructors | `from_some_other_type` |
+| Local variables | `snake_case` |
+| Static variables | `SCREAMING_SNAKE_CASE` |
+| Constant variables | `SCREAMING_SNAKE_CASE` |
+| Type parameters | concise `CamelCase`, usually single uppercase letter: `T` |
+| Lifetimes | short, lowercase: `'a` |
+
+<p>
+In `CamelCase`, acronyms count as one word: use `Uuid` rather than
+`UUID`. In `snake_case`, acronyms are lower-cased: `is_xid_start`.
+
+In `snake_case` or `SCREAMING_SNAKE_CASE`, a "word" should never
+consist of a single letter unless it is the last "word". So, we have
+`btree_map` rather than `b_tree_map`, but `PI_2` rather than `PI2`.
+
+### Referring to types in function/method names [RFC 344]
+
+> The guidelines below were approved by [RFC #344](https://github.com/rust-lang/rfcs/pull/344).
+
+Function names often involve type names, the most common example being conversions
+like `as_slice`. If the type has a purely textual name (ignoring parameters), it
+is straightforward to convert between type conventions and function conventions:
+
+Type name | Text in methods
+--------- | ---------------
+`String` | `string`
+`Vec<T>` | `vec`
+`YourType`| `your_type`
+
+Types that involve notation follow the convention below. There is some
+overlap on these rules; apply the most specific applicable rule:
+
+Type name | Text in methods
+--------- | ---------------
+`&str` | `str`
+`&[T]` | `slice`
+`&mut [T]`| `mut_slice`
+`&[u8]` | `bytes`
+`&T` | `ref`
+`&mut T` | `mut`
+`*const T`| `ptr`
+`*mut T` | `mut_ptr`
+
+### Avoid redundant prefixes [RFC 356]
+
+> The guidelines below were approved by [RFC #356](https://github.com/rust-lang/rfcs/pull/356).
+
+Names of items within a module should not be prefixed with that module's name:
+
+Prefer
+
+``` rust
+mod foo {
+ pub struct Error { ... }
+}
+```
+
+over
+
+``` rust
+mod foo {
+ pub struct FooError { ... }
+}
+```
+
+This convention avoids stuttering (like `io::IoError`). Library clients can
+rename on import to avoid clashes.
+
+### Getter/setter methods [RFC 344]
+
+> The guidelines below were approved by [RFC #344](https://github.com/rust-lang/rfcs/pull/344).
+
+Some data structures do not wish to provide direct access to their fields, but
+instead offer "getter" and "setter" methods for manipulating the field state
+(often providing checking or other functionality).
+
+The convention for a field `foo: T` is:
+
+* A method `foo(&self) -> &T` for getting the current value of the field.
+* A method `set_foo(&self, val: T)` for setting the field. (The `val` argument
+ here may take `&T` or some other type, depending on the context.)
+
+Note that this convention is about getters/setters on ordinary data types, *not*
+on [builder objects](../ownership/builders.html).
+
+### Escape hatches [FIXME]
+
+> **[FIXME]** Should we standardize a convention for functions that may break API
+> guarantees? e.g. `ToCStr::to_c_str_unchecked`
+
+### Predicates
+
+* Simple boolean predicates should be prefixed with `is_` or another
+ short question word, e.g., `is_empty`.
+* Common exceptions: `lt`, `gt`, and other established predicate names.
--- /dev/null
+% Common container/wrapper methods [FIXME: needs RFC]
+
+Containers, wrappers, and cells all provide ways to access the data
+they enclose. Accessor methods often have variants to access the data
+by value, by reference, and by mutable reference.
+
+In general, the `get` family of methods is used to access contained
+data without any risk of task failure; they return `Option` as
+appropriate. This name is chosen rather than names like `find` or
+`lookup` because it is appropriate for a wider range of container types.
+
+#### Containers
+
+For a container with keys/indexes of type `K` and elements of type `V`:
+
+```rust
+// Look up element without failing
+fn get(&self, key: K) -> Option<&V>
+fn get_mut(&mut self, key: K) -> Option<&mut V>
+
+// Convenience for .get(key).map(|elt| elt.clone())
+fn get_clone(&self, key: K) -> Option<V>
+
+// Lookup element, failing if it is not found:
+impl Index<K, V> for Container { ... }
+impl IndexMut<K, V> for Container { ... }
+```
+
+#### Wrappers/Cells
+
+Prefer specific conversion functions like `as_bytes` or `into_vec` whenever
+possible. Otherwise, use:
+
+```rust
+// Extract contents without failing
+fn get(&self) -> &V
+fn get_mut(&mut self) -> &mut V
+fn unwrap(self) -> V
+```
+
+#### Wrappers/Cells around `Copy` data
+
+```rust
+// Extract contents without failing
+fn get(&self) -> V
+```
+
+#### `Option`-like types
+
+Finally, we have the cases of types like `Option` and `Result`, which
+play a special role for failure.
+
+For `Option<V>`:
+
+```rust
+// Extract contents or fail if not available
+fn assert(self) -> V
+fn expect(self, &str) -> V
+```
+
+For `Result<V, E>`:
+
+```rust
+// Extract the contents of Ok variant; fail if Err
+fn assert(self) -> V
+
+// Extract the contents of Err variant; fail if Ok
+fn assert_err(self) -> E
+```
--- /dev/null
+% Conversions [Rust issue #7087]
+
+> The guidelines below were approved by [rust issue #7087](https://github.com/rust-lang/rust/issues/7087).
+
+> **[FIXME]** Should we provide standard traits for conversions? Doing
+> so nicely will require
+> [trait reform](https://github.com/rust-lang/rfcs/pull/48) to land.
+
+Conversions should be provided as methods, with names prefixed as follows:
+
+| Prefix | Cost | Consumes convertee |
+| ------ | ---- | ------------------ |
+| `as_` | Free | No |
+| `to_` | Expensive | No |
+| `into_` | Variable | Yes |
+
+<p>
+For example:
+
+* `as_bytes()` gives a `&[u8]` view into a `&str`, which is a no-op.
+* `to_owned()` copies a `&str` to a new `String`.
+* `into_bytes()` consumes a `String` and yields the underlying
+ `Vec<u8>`, which is a no-op.
+
+Conversions prefixed `as_` and `into_` typically _decrease abstraction_, either
+exposing a view into the underlying representation (`as`) or deconstructing data
+into its underlying representation (`into`). Conversions prefixed `to_`, on the
+other hand, typically stay at the same level of abstraction but do some work to
+change one representation into another.
+
+> **[FIXME]** The distinctions between conversion methods does not work
+> so well for `from_` conversion constructors. Is that a problem?
--- /dev/null
+% Iterators
+
+#### Method names [RFC #199]
+
+> The guidelines below were approved by [RFC #199](https://github.com/rust-lang/rfcs/pull/199).
+
+For a container with elements of type `U`, iterator methods should be named:
+
+```rust
+fn iter(&self) -> T // where T implements Iterator<&U>
+fn iter_mut(&mut self) -> T // where T implements Iterator<&mut U>
+fn into_iter(self) -> T // where T implements Iterator<U>
+```
+
+The default iterator variant yields shared references `&U`.
+
+#### Type names [RFC #344]
+
+> The guidelines below were approved by [RFC #344](https://github.com/rust-lang/rfcs/pull/344).
+
+The name of an iterator type should be the same as the method that
+produces the iterator.
+
+For example:
+
+* `iter` should yield an `Iter`
+* `iter_mut` should yield an `IterMut`
+* `into_iter` should yield an `IntoIter`
+* `keys` should yield `Keys`
+
+These type names make the most sense when prefixed with their owning module,
+e.g. `vec::IntoIter`.
--- /dev/null
+% Ownership variants [RFC #199]
+
+> The guidelines below were approved by [RFC #199](https://github.com/rust-lang/rfcs/pull/199).
+
+Functions often come in multiple variants: immutably borrowed, mutably
+borrowed, and owned.
+
+The right default depends on the function in question. Variants should
+be marked through suffixes.
+
+#### Immutably borrowed by default
+
+If `foo` uses/produces an immutable borrow by default, use:
+
+* The `_mut` suffix (e.g. `foo_mut`) for the mutably borrowed variant.
+* The `_move` suffix (e.g. `foo_move`) for the owned variant.
+
+#### Owned by default
+
+If `foo` uses/produces owned data by default, use:
+
+* The `_ref` suffix (e.g. `foo_ref`) for the immutably borrowed variant.
+* The `_mut` suffix (e.g. `foo_mut`) for the mutably borrowed variant.
+
+#### Exceptions
+
+In the case of iterators, the moving variant can also be understood as
+an `into` conversion, `into_iter`, and `for x in v.into_iter()` reads
+arguably better than `for x in v.iter_move()`, so the convention is
+`into_iter`.
+
+For mutably borrowed variants, if the `mut` qualifier is part of a
+type name (e.g. `as_mut_slice`), it should appear as it would appear
+in the type.
--- /dev/null
+% Organization [FIXME: needs RFC]
+
+> **[FIXME]** What else?
+
+### Reexport the most important types at the crate level.
+
+Crates `pub use` the most common types for convenience, so that clients do not
+have to remember or write the crate's module hierarchy to use these types.
+
+### Define types and operations together.
+
+Type definitions and the functions/methods that operate on them should be
+defined together in a single module, with the type appearing above the
+functions/methods.
--- /dev/null
+% Whitespace [FIXME: needs RFC]
+
+* Lines must not exceed 99 characters.
+* Use 4 spaces for indentation, _not_ tabs.
+* No trailing whitespace at the end of lines or files.
+
+### Spaces
+
+* Use spaces around binary operators, including the equals sign in attributes:
+
+``` rust
+#[deprecated = "Use `bar` instead."]
+fn foo(a: uint, b: uint) -> uint {
+ a + b
+}
+```
+
+* Use a space after colons and commas:
+
+``` rust
+fn foo(a: Bar);
+
+MyStruct { foo: 3, bar: 4 }
+
+foo(bar, baz);
+```
+
+* Use a space after the opening and before the closing brace for
+ single line blocks or `struct` expressions:
+
+``` rust
+spawn(proc() { do_something(); })
+
+Point { x: 0.1, y: 0.3 }
+```
+
+### Line wrapping
+
+* For multiline function signatures, each new line should align with the
+ first parameter. Multiple parameters per line are permitted:
+
+``` rust
+fn frobnicate(a: Bar, b: Bar,
+ c: Bar, d: Bar)
+ -> Bar {
+ ...
+}
+
+fn foo<T: This,
+ U: That>(
+ a: Bar,
+ b: Bar)
+ -> Baz {
+ ...
+}
+```
+
+* Multiline function invocations generally follow the same rule as for
+ signatures. However, if the final argument begins a new block, the
+ contents of the block may begin on a new line, indented one level:
+
+``` rust
+fn foo_bar(a: Bar, b: Bar,
+ c: |Bar|) -> Bar {
+ ...
+}
+
+// Same line is fine:
+foo_bar(x, y, |z| { z.transpose(y) });
+
+// Indented body on new line is also fine:
+foo_bar(x, y, |z| {
+ z.quux();
+ z.rotate(x)
+})
+```
+
+> **[FIXME]** Do we also want to allow the following?
+>
+> ```rust
+> frobnicate(
+> arg1,
+> arg2,
+> arg3)
+> ```
+>
+> This style could ease the conflict between line length and functions
+> with many parameters (or long method chains).
+
+### Matches
+
+> * **[Deprecated]** If you have multiple patterns in a single `match`
+> arm, write each pattern on a separate line:
+>
+> ``` rust
+> match foo {
+> bar(_)
+> | baz => quux,
+> x
+> | y
+> | z => {
+> quuux
+> }
+> }
+> ```
+
+### Alignment
+
+Idiomatic code should not use extra whitespace in the middle of a line
+to provide alignment.
+
+
+``` rust
+// Good
+struct Foo {
+ short: f64,
+ really_long: f64,
+}
+
+// Bad
+struct Bar {
+ short: f64,
+ really_long: f64,
+}
+
+// Good
+let a = 0;
+let radius = 7;
+
+// Bad
+let b = 0;
+let diameter = 7;
+```
--- /dev/null
+% Testing
+
+> **[FIXME]** Add some general remarks about when and how to unit
+> test, versus other kinds of testing. What are our expectations for
+> Rust's core libraries?
--- /dev/null
+% Unit testing
+
+Unit tests should live in a `test` submodule at the bottom of the module they
+test. Mark the `test` submodule with `#[cfg(test)]` so it is only compiled when
+testing.
+
+The `test` module should contain:
+
+* Imports needed only for testing.
+* Functions marked with `#[test]` striving for full coverage of the parent module's
+ definitions.
+* Auxiliary functions needed for writing the tests.
+
+For example:
+
+``` rust
+// Excerpt from std::str
+
+#[cfg(test)]
+mod test {
+ #[test]
+ fn test_eq() {
+ assert!((eq(&"".to_owned(), &"".to_owned())));
+ assert!((eq(&"foo".to_owned(), &"foo".to_owned())));
+ assert!((!eq(&"foo".to_owned(), &"bar".to_owned())));
+ }
+}
+```
+
+> **[FIXME]** add details about useful macros for testing, e.g. `assert!`
--- /dev/null
+* [Containers and iteration]()
+* [The visitor pattern]()
+* [Concurrency]()
+* [Documentation]()
+* [Macros]()
* [Generics](generics.md)
* [Traits](traits.md)
* [Static and Dynamic Dispatch](static-and-dynamic-dispatch.md)
+ * [Macros](macros.md)
* [Concurrency](concurrency.md)
* [Error Handling](error-handling.md)
* [Documentation](documentation.md)
* [III: Advanced Topics](advanced.md)
* [FFI](ffi.md)
* [Unsafe Code](unsafe.md)
- * [Macros](macros.md)
+ * [Advanced Macros](advanced-macros.md)
* [Compiler Plugins](plugins.md)
* [Conclusion](conclusion.md)
* [Glossary](glossary.md)
--- /dev/null
+% Advanced macros
+
+This chapter picks up where the [introductory macro chapter](macros.html) left
+off.
+
+# Syntactic requirements
+
+Even when Rust code contains un-expanded macros, it can be parsed as a full
+syntax tree. This property can be very useful for editors and other tools that
+process code. It also has a few consequences for the design of Rust's macro
+system.
+
+One consequence is that Rust must determine, when it parses a macro invocation,
+whether the macro stands in for
+
+* zero or more items,
+* zero or more methods,
+* an expression,
+* a statement, or
+* a pattern.
+
+A macro invocation within a block could stand for some items, or for an
+expression / statement. Rust uses a simple rule to resolve this ambiguity. A
+macro invocation that stands for items must be either
+
+* delimited by curly braces, e.g. `foo! { ... }`, or
+* terminated by a semicolon, e.g. `foo!(...);`
+
+Another consequence of pre-expansion parsing is that the macro invocation must
+consist of valid Rust tokens. Furthermore, parentheses, brackets, and braces
+must be balanced within a macro invocation. For example, `foo!([)` is
+forbidden. This allows Rust to know where the macro invocation ends.
+
+More formally, the macro invocation body must be a sequence of *token trees*.
+A token tree is defined recursively as either
+
+* a sequence of token trees surrounded by matching `()`, `[]`, or `{}`, or
+* any other single token.
+
+Within a matcher, each metavariable has a *fragment specifier*, identifying
+which syntactic form it matches.
+
+* `ident`: an identifier. Examples: `x`; `foo`.
+* `path`: a qualified name. Example: `T::SpecialA`.
+* `expr`: an expression. Examples: `2 + 2`; `if true then { 1 } else { 2 }`; `f(42)`.
+* `ty`: a type. Examples: `i32`; `Vec<(char, String)>`; `&T`.
+* `pat`: a pattern. Examples: `Some(t)`; `(17, 'a')`; `_`.
+* `stmt`: a single statement. Example: `let x = 3`.
+* `block`: a brace-delimited sequence of statements. Example:
+ `{ log(error, "hi"); return 12; }`.
+* `item`: an [item][]. Examples: `fn foo() { }`; `struct Bar;`.
+* `meta`: a "meta item", as found in attributes. Example: `cfg(target_os = "windows")`.
+* `tt`: a single token tree.
+
+There are additional rules regarding the next token after a metavariable:
+
+* `expr` variables must be followed by one of: `=> , ;`
+* `ty` and `path` variables must be followed by one of: `=> , : = > as`
+* `pat` variables must be followed by one of: `=> , =`
+* Other variables may be followed by any token.
+
+These rules provide some flexibility for Rust's syntax to evolve without
+breaking existing macros.
+
+The macro system does not deal with parse ambiguity at all. For example, the
+grammar `$($t:ty)* $e:expr` will always fail to parse, because the parser would
+be forced to choose between parsing `$t` and parsing `$e`. Changing the
+invocation syntax to put a distinctive token in front can solve the problem. In
+this case, you can write `$(T $t:ty)* E $e:exp`.
+
+[item]: ../reference.html#items
+
+# Scoping and macro import/export
+
+Macros are expanded at an early stage in compilation, before name resolution.
+One downside is that scoping works differently for macros, compared to other
+constructs in the language.
+
+Definition and expansion of macros both happen in a single depth-first,
+lexical-order traversal of a crate's source. So a macro defined at module scope
+is visible to any subsequent code in the same module, which includes the body
+of any subsequent child `mod` items.
+
+A macro defined within the body of a single `fn`, or anywhere else not at
+module scope, is visible only within that item.
+
+If a module has the `macro_use` attribute, its macros are also visible in its
+parent module after the child's `mod` item. If the parent also has `macro_use`
+then the macros will be visible in the grandparent after the parent's `mod`
+item, and so forth.
+
+The `macro_use` attribute can also appear on `extern crate`. In this context
+it controls which macros are loaded from the external crate, e.g.
+
+```rust,ignore
+#[macro_use(foo, bar)]
+extern crate baz;
+```
+
+If the attribute is given simply as `#[macro_use]`, all macros are loaded. If
+there is no `#[macro_use]` attribute then no macros are loaded. Only macros
+defined with the `#[macro_export]` attribute may be loaded.
+
+To load a crate's macros *without* linking it into the output, use `#[no_link]`
+as well.
+
+An example:
+
+```rust
+macro_rules! m1 { () => (()) }
+
+// visible here: m1
+
+mod foo {
+ // visible here: m1
+
+ #[macro_export]
+ macro_rules! m2 { () => (()) }
+
+ // visible here: m1, m2
+}
+
+// visible here: m1
+
+macro_rules! m3 { () => (()) }
+
+// visible here: m1, m3
+
+#[macro_use]
+mod bar {
+ // visible here: m1, m3
+
+ macro_rules! m4 { () => (()) }
+
+ // visible here: m1, m3, m4
+}
+
+// visible here: m1, m3, m4
+# fn main() { }
+```
+
+When this library is loaded with `#[macro_use] extern crate`, only `m2` will
+be imported.
+
+The Rust Reference has a [listing of macro-related
+attributes](../reference.html#macro--and-plugin-related-attributes).
+
+# The variable `$crate`
+
+A further difficulty occurs when a macro is used in multiple crates. Say that
+`mylib` defines
+
+```rust
+pub fn increment(x: u32) -> u32 {
+ x + 1
+}
+
+#[macro_export]
+macro_rules! inc_a {
+ ($x:expr) => ( ::increment($x) )
+}
+
+#[macro_export]
+macro_rules! inc_b {
+ ($x:expr) => ( ::mylib::increment($x) )
+}
+# fn main() { }
+```
+
+`inc_a` only works within `mylib`, while `inc_b` only works outside the
+library. Furthermore, `inc_b` will break if the user imports `mylib` under
+another name.
+
+Rust does not (yet) have a hygiene system for crate references, but it does
+provide a simple workaround for this problem. Within a macro imported from a
+crate named `foo`, the special macro variable `$crate` will expand to `::foo`.
+By contrast, when a macro is defined and then used in the same crate, `$crate`
+will expand to nothing. This means we can write
+
+```rust
+#[macro_export]
+macro_rules! inc {
+ ($x:expr) => ( $crate::increment($x) )
+}
+# fn main() { }
+```
+
+to define a single macro that works both inside and outside our library. The
+function name will expand to either `::increment` or `::mylib::increment`.
+
+To keep this system simple and correct, `#[macro_use] extern crate ...` may
+only appear at the root of your crate, not inside `mod`. This ensures that
+`$crate` is a single identifier.
+
+# A final note
+
+Macros, as currently implemented, are not for the faint of heart. Even
+ordinary syntax errors can be more difficult to debug when they occur inside a
+macro, and errors caused by parse problems in generated code can be very
+tricky. Invoking the `log_syntax!` macro can help elucidate intermediate
+states, invoking `trace_macros!(true)` will automatically print those
+intermediate states out, and passing the flag `--pretty expanded` as a
+command-line argument to the compiler will show the result of expansion.
+
+If Rust's macro system can't do what you need, you may want to write a
+[compiler plugin](plugins.html) instead. Compared to `macro_rules!`
+macros, this is significantly more work, the interfaces are much less stable,
+and the warnings about debugging apply ten-fold. In exchange you get the
+flexibility of running arbitrary Rust code within the compiler. Syntax
+extension plugins are sometimes called *procedural macros* for this reason.
three values. We then do a bunch of `if`/`else` comparisons to check which
one it is.
-This `Ordering::Greater` notation is too long. Lets use `use` to import can
-the `enum` variants instead. This will avoid full scoping:
+This `Ordering::Greater` notation is too long. Let's use `use` to import the
+`enum` variants instead. This will avoid full scoping:
```{rust}
use std::cmp::Ordering::{self, Equal, Less, Greater};
## Threads
Rust's standard library provides a library for 'threads', which allow you to
-run Rust code in parallel. Here's a basic example of using `Thread`:
+run Rust code in parallel. Here's a basic example of using `std::thread`:
```
-use std::thread::Thread;
+use std::thread;
fn main() {
- Thread::scoped(|| {
+ thread::scoped(|| {
println!("Hello from a thread!");
});
}
thread. It's called `scoped` because this thread returns a join guard:
```
-use std::thread::Thread;
+use std::thread;
fn main() {
- let guard = Thread::scoped(|| {
+ let guard = thread::scoped(|| {
println!("Hello from a thread!");
});
```
When `guard` goes out of scope, it will block execution until the thread is
-finished. If we didn't want this behaviour, we could use `Thread::spawn()`:
+finished. If we didn't want this behaviour, we could use `thread::spawn()`:
```
-use std::thread::Thread;
+use std::thread;
use std::old_io::timer;
use std::time::Duration;
fn main() {
- Thread::spawn(|| {
+ thread::spawn(|| {
println!("Hello from a thread!");
});
}
```
-Or call `.detach()`:
-
-```
-use std::thread::Thread;
-use std::old_io::timer;
-use std::time::Duration;
-
-fn main() {
- let guard = Thread::scoped(|| {
- println!("Hello from a thread!");
- });
-
- guard.detach();
-
- timer::sleep(Duration::milliseconds(50));
-}
-```
-
We need to `sleep` here because when `main()` ends, it kills all of the
running threads.
languages. It will not compile:
```ignore
-use std::thread::Thread;
+use std::thread;
use std::old_io::timer;
use std::time::Duration;
let mut data = vec![1u32, 2, 3];
for i in 0..2 {
- Thread::spawn(move || {
+ thread::spawn(move || {
data[i] += 1;
});
}
but for a different reason:
```ignore
-use std::thread::Thread;
+use std::thread;
use std::old_io::timer;
use std::time::Duration;
use std::sync::Mutex;
for i in 0..2 {
let data = data.lock().unwrap();
- Thread::spawn(move || {
+ thread::spawn(move || {
data[i] += 1;
});
}
```
use std::sync::{Arc, Mutex};
-use std::thread::Thread;
+use std::thread;
use std::old_io::timer;
use std::time::Duration;
for i in 0us..2 {
let data = data.clone();
- Thread::spawn(move || {
+ thread::spawn(move || {
let mut data = data.lock().unwrap();
data[i] += 1;
});
```
# use std::sync::{Arc, Mutex};
-# use std::thread::Thread;
+# use std::thread;
# use std::old_io::timer;
# use std::time::Duration;
# fn main() {
# let data = Arc::new(Mutex::new(vec![1u32, 2, 3]));
# for i in 0us..2 {
# let data = data.clone();
-Thread::spawn(move || {
+thread::spawn(move || {
let mut data = data.lock().unwrap();
data[i] += 1;
});
```
use std::sync::{Arc, Mutex};
-use std::thread::Thread;
+use std::thread;
use std::sync::mpsc;
fn main() {
for _ in 0..10 {
let (data, tx) = (data.clone(), tx.clone());
- Thread::spawn(move || {
+ thread::spawn(move || {
let mut data = data.lock().unwrap();
*data += 1;
```
use std::sync::{Arc, Mutex};
-use std::thread::Thread;
+use std::thread;
use std::sync::mpsc;
fn main() {
for _ in 0..10 {
let tx = tx.clone();
- Thread::spawn(move || {
+ thread::spawn(move || {
let answer = 42u32;
tx.send(answer);
threads as a simple isolation mechanism:
```
-use std::thread::Thread;
+use std::thread;
-let result = Thread::scoped(move || {
+let result = thread::spawn(move || {
panic!("oops!");
}).join();
// the "link" crate attribute is currently required for rustdoc, but normally
// isn't needed.
#![crate_id = "universe"]
-#![crate_type="lib"]
+#![crate_type= "lib"]
//! Tools for dealing with universes (this is a doc comment, and is shown on
//! the crate index page. The ! makes it apply to the parent of the comment,
Remember Rust's `for` loop? Here's an example:
-```{rust}
+```rust
for x in 0..10 {
println!("{}", x);
}
```
-Now that you know more Rust, we can talk in detail about how this works. The
-`range` function returns an *iterator*. An iterator is something that we can
+Now that you know more Rust, we can talk in detail about how this works.
+Ranges (the `0..10`) are 'iterators'. An iterator is something that we can
call the `.next()` method on repeatedly, and it gives us a sequence of things.
Like this:
-```{rust}
+```rust
let mut range = 0..10;
loop {
}
```
-We make a mutable binding to the return value of `range`, which is our iterator.
-We then `loop`, with an inner `match`. This `match` is used on the result of
-`range.next()`, which gives us a reference to the next value of the iterator.
-`next` returns an `Option<i32>`, in this case, which will be `Some(i32)` when
-we have a value and `None` once we run out. If we get `Some(i32)`, we print it
-out, and if we get `None`, we `break` out of the loop.
+We make a mutable binding to the range, which is our iterator. We then `loop`,
+with an inner `match`. This `match` is used on the result of `range.next()`,
+which gives us a reference to the next value of the iterator. `next` returns an
+`Option<i32>`, in this case, which will be `Some(i32)` when we have a value and
+`None` once we run out. If we get `Some(i32)`, we print it out, and if we get
+`None`, we `break` out of the loop.
This code sample is basically the same as our `for` loop version. The `for`
loop is just a handy way to write this `loop`/`match`/`break` construct.
own iterator involves implementing the `Iterator` trait. While doing that is
outside of the scope of this guide, Rust provides a number of useful iterators
to accomplish various tasks. Before we talk about those, we should talk about a
-Rust anti-pattern. And that's `range`.
+Rust anti-pattern. And that's using ranges like this.
-Yes, we just talked about how `range` is cool. But `range` is also very
-primitive. For example, if you needed to iterate over the contents of
-a vector, you may be tempted to write this:
+Yes, we just talked about how ranges are cool. But ranges are also very
+primitive. For example, if you needed to iterate over the contents of a vector,
+you may be tempted to write this:
-```{rust}
+```rust
let nums = vec![1, 2, 3];
for i in 0..nums.len() {
vectors returns an iterator which iterates through a reference to each element
of the vector in turn. So write this:
-```{rust}
+```rust
let nums = vec![1, 2, 3];
for num in nums.iter() {
not an `i32` itself. `println!` handles the dereferencing for us, so we don't
see it. This code works fine too:
-```{rust}
+```rust
let nums = vec![1, 2, 3];
for num in nums.iter() {
we're just borrowing a reference to the data, and so it's just passing
a reference, without needing to do the copy.
-So, now that we've established that `range` is often not what you want, let's
+So, now that we've established that ranges are often not what you want, let's
talk about what you do want instead.
There are three broad classes of things that are relevant here: iterators,
different output sequence.
* *consumers* operate on an iterator, producing some final set of values.
-Let's talk about consumers first, since you've already seen an iterator,
-`range`.
+Let's talk about consumers first, since you've already seen an iterator, ranges.
## Consumers
but it shows the intention:
```{rust,ignore}
-let one_to_one_hundred = (1..101i32).collect();
+let one_to_one_hundred = (1..101).collect();
```
As you can see, we call `collect()` on our iterator. `collect()` takes
type of things you want to collect, and so you need to let it know.
Here's the version that does compile:
-```{rust}
-let one_to_one_hundred = (1..101i32).collect::<Vec<i32>>();
+```rust
+let one_to_one_hundred = (1..101).collect::<Vec<i32>>();
```
If you remember, the `::<>` syntax allows us to give a type hint,
a partial hint:
```rust
-let one_to_one_hundred = range(1, 101).collect::<Vec<_>>();
+let one_to_one_hundred = (1..101).collect::<Vec<_>>();
```
This says "Collect into a `Vec<T>`, please, but infer what the `T` is for me."
`collect()` is the most common consumer, but there are others too. `find()`
is one:
-```{rust}
-let greater_than_forty_two = (0..100i32)
+```rust
+let greater_than_forty_two = (0..100)
.find(|x| *x > 42);
match greater_than_forty_two {
Another important consumer is `fold`. Here's what it looks like:
-```{rust}
-let sum = (1..4)
- .fold(0, |sum, x| sum + x);
+```rust
+let sum = (1..4).fold(0, |sum, x| sum + x);
```
`fold()` is a consumer that looks like this:
We called `fold()` with these arguments:
-```{rust}
+```rust
# (1..4)
.fold(0, |sum, x| sum + x);
```
This code, for example, does not actually generate the numbers
`1-100`, and just creates a value that represents the sequence:
-```{rust}
+```rust
let nums = 1..100;
```
Since we didn't do anything with the range, it didn't generate the sequence.
Let's add the consumer:
-```{rust}
+```rust
let nums = (1..100).collect::<Vec<i32>>();
```
Now, `collect()` will require that the range gives it some numbers, and so
it will do the work of generating the sequence.
-A range is one of two basic iterators that you'll see. The other is `iter()`,
+Ranges are one of two basic iterators that you'll see. The other is `iter()`,
which you've used before. `iter()` can turn a vector into a simple iterator
that gives you each element in turn:
-```{rust}
+```rust
let nums = [1, 2, 3];
for num in nums.iter() {
These two basic iterators should serve you well. There are some more
advanced iterators, including ones that are infinite. Like `count`:
-```{rust}
+```rust
std::iter::count(1, 5);
```
a new iterator. The simplest one is called `map`:
```{rust,ignore}
-(1..100i32).map(|x| x + 1);
+(1..100).map(|x| x + 1);
```
`map` is called upon another iterator, and produces a new iterator where each
So this would give us the numbers from `2-100`. Well, almost! If you
compile the example, you'll get a warning:
-```{notrust,ignore}
+```text
warning: unused result which must be used: iterator adaptors are lazy and
do nothing unless consumed, #[warn(unused_must_use)] on by default
(1..100).map(|x| x + 1);
has no side effect on the original iterator. Let's try it out with our infinite
iterator from before, `count()`:
-```{rust}
+```rust
for i in std::iter::count(1, 5).take(5) {
println!("{}", i);
}
This will print
-```{notrust,ignore}
+```text
1
6
11
returns `true` or `false`. The new iterator `filter()` produces
only the elements that that closure returns `true` for:
-```{rust}
-for i in (1..100i32).filter(|&x| x % 2 == 0) {
+```rust
+for i in (1..100).filter(|&x| x % 2 == 0) {
println!("{}", i);
}
```
You can chain all three things together: start with an iterator, adapt it
a few times, and then consume the result. Check it out:
-```{rust}
-(1..1000i32)
+```rust
+(1..1000)
.filter(|&x| x % 2 == 0)
.filter(|&x| x % 3 == 0)
.take(5)
% Macros
-# Introduction
-
-Functions are the primary tool that programmers can use to build abstractions.
-Sometimes, however, programmers want to abstract over compile-time syntax
-rather than run-time values.
-Macros provide syntactic abstraction.
-For an example of how this can be useful, consider the following two code fragments,
-which both pattern-match on their input and both return early in one case,
-doing nothing otherwise:
-
-~~~~
-# enum T { SpecialA(u32), SpecialB(u32) }
-# fn f() -> u32 {
-# let input_1 = T::SpecialA(0);
-# let input_2 = T::SpecialA(0);
-match input_1 {
- T::SpecialA(x) => { return x; }
- _ => {}
-}
-// ...
-match input_2 {
- T::SpecialB(x) => { return x; }
- _ => {}
-}
-# return 0;
-# }
-~~~~
-
-This code could become tiresome if repeated many times.
-However, no function can capture its functionality to make it possible
-to abstract the repetition away.
-Rust's macro system, however, can eliminate the repetition. Macros are
-lightweight custom syntax extensions, themselves defined using the
-`macro_rules!` syntax extension. The following `early_return` macro captures
-the pattern in the above code:
-
-~~~~
-# enum T { SpecialA(u32), SpecialB(u32) }
-# fn f() -> u32 {
-# let input_1 = T::SpecialA(0);
-# let input_2 = T::SpecialA(0);
-macro_rules! early_return {
- ($inp:expr, $sp:path) => ( // invoke it like `(input_5, SpecialE)`
- match $inp {
- $sp(x) => { return x; }
- _ => {}
- }
- );
-}
-// ...
-early_return!(input_1, T::SpecialA);
-// ...
-early_return!(input_2, T::SpecialB);
-# return 0;
-# }
-# fn main() {}
-~~~~
-
-Macros are defined in pattern-matching style: in the above example, the text
-`($inp:expr, $sp:path)` that appears on the left-hand side of the `=>` is the
-*macro invocation syntax*, a pattern denoting how to write a call to the
-macro. The text on the right-hand side of the `=>`, beginning with `match
-$inp`, is the *macro transcription syntax*: what the macro expands to.
-
-# Invocation syntax
-
-The macro invocation syntax specifies the syntax for the arguments to the
-macro. It appears on the left-hand side of the `=>` in a macro definition. It
-conforms to the following rules:
-
-1. It must be surrounded by parentheses.
-2. `$` has special meaning (described below).
-3. The `()`s, `[]`s, and `{}`s it contains must balance. For example, `([)` is
-forbidden.
-4. Some arguments can be followed only by a limited set of separators, to
-avoid ambiguity (described below).
-
-Otherwise, the invocation syntax is free-form.
-
-To take a fragment of Rust code as an argument, write `$` followed by a name
- (for use on the right-hand side), followed by a `:`, followed by a *fragment
- specifier*. The fragment specifier denotes the sort of fragment to match. The
- most common fragment specifiers are:
-
-* `ident` (an identifier, referring to a variable or item. Examples: `f`, `x`,
- `foo`.)
-* `expr` (an expression. Examples: `2 + 2`; `if true then { 1 } else { 2 }`;
- `f(42)`.)
-* `ty` (a type. Examples: `i32`, `Vec<(char, String)>`, `&T`.)
-* `path` (a path to struct or enum variant. Example: `T::SpecialA`)
-* `pat` (a pattern, usually appearing in a `match` or on the left-hand side of
- a declaration. Examples: `Some(t)`; `(17, 'a')`; `_`.)
-* `block` (a sequence of actions. Example: `{ log(error, "hi"); return 12; }`)
-
-The parser interprets any token that's not preceded by a `$` literally. Rust's usual
-rules of tokenization apply,
-
-So `($x:ident -> (($e:expr)))`, though excessively fancy, would designate a macro
-that could be invoked like: `my_macro!(i->(( 2+2 )))`.
-
-To avoid ambiguity, macro invocation syntax must conform to the following rules:
-
-* `expr` must be followed by `=>`, `,` or `;`.
-* `ty` and `path` must be followed by `=>`, `,`, `:`, `=`, `>` or `as`.
-* `pat` must be followed by `=>`, `,` or `=`.
-* `ident` and `block` can be followed by any token.
-
-## Invocation location
-
-A macro invocation may take the place of (and therefore expand to) an
-expression, item, statement, or pattern. The Rust parser will parse the macro
-invocation as a "placeholder" for whichever syntactic form is appropriate for
-the location.
-
-At expansion time, the output of the macro will be parsed as whichever of the
-three nonterminals it stands in for. This means that a single macro might,
-for example, expand to an item or an expression, depending on its arguments
-(and cause a syntax error if it is called with the wrong argument for its
-location). Although this behavior sounds excessively dynamic, it is known to
-be useful under some circumstances.
-
-
-# Transcription syntax
-
-The right-hand side of the `=>` follows the same rules as the left-hand side,
-except that a `$` need only be followed by the name of the syntactic fragment
-to transcribe into the macro expansion; its type need not be repeated.
-
-The right-hand side must be enclosed by delimiters, which the transcriber ignores.
-Therefore `() => ((1,2,3))` is a macro that expands to a tuple expression,
-`() => (let $x=$val)` is a macro that expands to a statement,
-and `() => (1,2,3)` is a macro that expands to a syntax error
-(since the transcriber interprets the parentheses on the right-hand-size as delimiters,
-and `1,2,3` is not a valid Rust expression on its own).
-
-Except for permissibility of `$name` (and `$(...)*`, discussed below), the
-right-hand side of a macro definition is ordinary Rust syntax. In particular,
-macro invocations (including invocations of the macro currently being defined)
-are permitted in expression, statement, and item locations. However, nothing
-else about the code is examined or executed by the macro system; execution
-still has to wait until run-time.
-
-## Interpolation location
-
-The interpolation `$argument_name` may appear in any location consistent with
-its fragment specifier (i.e., if it is specified as `ident`, it may be used
-anywhere an identifier is permitted).
-
-# Multiplicity
-
-## Invocation
-
-Going back to the motivating example, recall that `early_return` expanded into
-a `match` that would `return` if the `match`'s scrutinee matched the
-"special case" identifier provided as the second argument to `early_return`,
-and do nothing otherwise. Now suppose that we wanted to write a
-version of `early_return` that could handle a variable number of "special"
-cases.
-
-The syntax `$(...)*` on the left-hand side of the `=>` in a macro definition
-accepts zero or more occurrences of its contents. It works much
-like the `*` operator in regular expressions. It also supports a
-separator token (a comma-separated list could be written `$(...),*`), and `+`
-instead of `*` to mean "at least one".
-
-~~~~
-# enum T { SpecialA(u32), SpecialB(u32), SpecialC(u32), SpecialD(u32) }
-# fn f() -> u32 {
-# let input_1 = T::SpecialA(0);
-# let input_2 = T::SpecialA(0);
-macro_rules! early_return {
- ($inp:expr, [ $($sp:path),+ ]) => (
- match $inp {
+By now you've learned about many of the tools Rust provides for abstracting and
+reusing code. These units of code reuse have a rich semantic structure. For
+example, functions have a type signature, type parameters have trait bounds,
+and overloaded functions must belong to a particular trait.
+
+This structure means that Rust's core abstractions have powerful compile-time
+correctness checking. But this comes at the price of reduced flexibility. If
+you visually identify a pattern of repeated code, you may find it's difficult
+or cumbersome to express that pattern as a generic function, a trait, or
+anything else within Rust's semantics.
+
+Macros allow us to abstract at a *syntactic* level. A macro invocation is
+shorthand for an "expanded" syntactic form. This expansion happens early in
+compilation, before any static checking. As a result, macros can capture many
+patterns of code reuse that Rust's core abstractions cannot.
+
+The drawback is that macro-based code can be harder to understand, because
+fewer of the built-in rules apply. Like an ordinary function, a well-behaved
+macro can be used without understanding its implementation. However, it can be
+difficult to design a well-behaved macro! Additionally, compiler errors in
+macro code are harder to interpret, because they describe problems in the
+expanded code, not the source-level form that developers use.
+
+These drawbacks make macros something of a "feature of last resort". That's not
+to say that macros are bad; they are part of Rust because sometimes they're
+needed for truly concise, well-abstracted code. Just keep this tradeoff in
+mind.
+
+# Defining a macro
+
+You may have seen the `vec!` macro, used to initialize a [vector][] with any
+number of elements.
+
+[vector]: arrays-vectors-and-slices.html
+
+```rust
+let x: Vec<u32> = vec![1, 2, 3];
+# assert_eq!(&[1,2,3], &x);
+```
+
+This can't be an ordinary function, because it takes any number of arguments.
+But we can imagine it as syntactic shorthand for
+
+```rust
+let x: Vec<u32> = {
+ let mut temp_vec = Vec::new();
+ temp_vec.push(1);
+ temp_vec.push(2);
+ temp_vec.push(3);
+ temp_vec
+};
+# assert_eq!(&[1,2,3], &x);
+```
+
+We can implement this shorthand, using a macro: [^actual]
+
+[^actual]: The actual definition of `vec!` in libcollections differs from the
+ one presented here, for reasons of efficiency and reusability. Some
+ of these are mentioned in the [advanced macros chapter][].
+
+```rust
+macro_rules! vec {
+ ( $( $x:expr ),* ) => {
+ {
+ let mut temp_vec = Vec::new();
$(
- $sp(x) => { return x; }
- )+
- _ => {}
+ temp_vec.push($x);
+ )*
+ temp_vec
}
- )
-}
-// ...
-early_return!(input_1, [T::SpecialA,T::SpecialC,T::SpecialD]);
-// ...
-early_return!(input_2, [T::SpecialB]);
-# return 0;
-# }
-# fn main() {}
-~~~~
-
-### Transcription
-
-As the above example demonstrates, `$(...)*` is also valid on the right-hand
-side of a macro definition. The behavior of `*` in transcription,
-especially in cases where multiple `*`s are nested, and multiple different
-names are involved, can seem somewhat magical and unintuitive at first. The
-system that interprets them is called "Macro By Example". The two rules to
-keep in mind are (1) the behavior of `$(...)*` is to walk through one "layer"
-of repetitions for all of the `$name`s it contains in lockstep, and (2) each
-`$name` must be under at least as many `$(...)*`s as it was matched against.
-If it is under more, it'll be repeated, as appropriate.
-
-## Parsing limitations
-
-
-For technical reasons, there are two limitations to the treatment of syntax
-fragments by the macro parser:
-
-1. The parser will always parse as much as possible of a Rust syntactic
-fragment. For example, if the comma were omitted from the syntax of
-`early_return!` above, `input_1 [` would've been interpreted as the beginning
-of an array index. In fact, invoking the macro would have been impossible.
-2. The parser must have eliminated all ambiguity by the time it reaches a
-`$name:fragment_specifier` declaration. This limitation can result in parse
-errors when declarations occur at the beginning of, or immediately after,
-a `$(...)*`. For example, the grammar `$($t:ty)* $e:expr` will always fail to
-parse because the parser would be forced to choose between parsing `t` and
-parsing `e`. Changing the invocation syntax to require a distinctive token in
-front can solve the problem. In the above example, `$(T $t:ty)* E $e:exp`
-solves the problem.
-
-# Macro argument pattern matching
-
-## Motivation
-
-Now consider code like the following:
-
-~~~~
-# enum T1 { Good1(T2, u32), Bad1}
-# struct T2 { body: T3 }
-# enum T3 { Good2(u32), Bad2}
-# fn f(x: T1) -> u32 {
-match x {
- T1::Good1(g1, val) => {
- match g1.body {
- T3::Good2(result) => {
- // complicated stuff goes here
- return result + val;
- },
- _ => panic!("Didn't get good_2")
- }
- }
- _ => return 0 // default value
+ };
}
+# fn main() {
+# assert_eq!(&[1,2,3], &vec![1,2,3]);
# }
-# fn main() {}
-~~~~
-
-All the complicated stuff is deeply indented, and the error-handling code is
-separated from matches that fail. We'd like to write a macro that performs
-a match, but with a syntax that suits the problem better. The following macro
-can solve the problem:
-
-~~~~
-macro_rules! biased_match {
- // special case: `let (x) = ...` is illegal, so use `let x = ...` instead
- ( ($e:expr) -> ($p:pat) else $err:stmt ;
- binds $bind_res:ident
- ) => (
- let $bind_res = match $e {
- $p => ( $bind_res ),
- _ => { $err }
- };
- );
- // more than one name; use a tuple
- ( ($e:expr) -> ($p:pat) else $err:stmt ;
- binds $( $bind_res:ident ),*
- ) => (
- let ( $( $bind_res ),* ) = match $e {
- $p => ( $( $bind_res ),* ),
- _ => { $err }
- };
- )
-}
+```
-# enum T1 { Good1(T2, u32), Bad1}
-# struct T2 { body: T3 }
-# enum T3 { Good2(u32), Bad2}
-# fn f(x: T1) -> u32 {
-biased_match!((x) -> (T1::Good1(g1, val)) else { return 0 };
- binds g1, val );
-biased_match!((g1.body) -> (T3::Good2(result) )
- else { panic!("Didn't get good_2") };
- binds result );
-// complicated stuff goes here
-return result + val;
-# }
-# fn main() {}
-~~~~
-
-This solves the indentation problem. But if we have a lot of chained matches
-like this, we might prefer to write a single macro invocation. The input
-pattern we want is clear:
-
-~~~~
-# fn main() {}
-# macro_rules! b {
- ( $( ($e:expr) -> ($p:pat) else $err:stmt ; )*
- binds $( $bind_res:ident ),*
- )
-# => (0) }
-~~~~
-
-However, it's not possible to directly expand to nested match statements. But
-there is a solution.
-
-## The recursive approach to macro writing
-
-A macro may accept multiple different input grammars. The first one to
-successfully match the actual argument to a macro invocation is the one that
-"wins".
-
-In the case of the example above, we want to write a recursive macro to
-process the semicolon-terminated lines, one-by-one. So, we want the following
-input patterns:
-
-~~~~
-# macro_rules! b {
- ( binds $( $bind_res:ident ),* )
-# => (0) }
-# fn main() {}
-~~~~
-
-...and:
-
-~~~~
-# fn main() {}
-# macro_rules! b {
- ( ($e :expr) -> ($p :pat) else $err :stmt ;
- $( ($e_rest:expr) -> ($p_rest:pat) else $err_rest:stmt ; )*
- binds $( $bind_res:ident ),*
- )
-# => (0) }
-~~~~
-
-The resulting macro looks like this. Note that the separation into
-`biased_match!` and `biased_match_rec!` occurs only because we have an outer
-piece of syntax (the `let`) which we only want to transcribe once.
-
-~~~~
-# fn main() {
+Whoa, that's a lot of new syntax! Let's break it down.
-macro_rules! biased_match_rec {
- // Handle the first layer
- ( ($e :expr) -> ($p :pat) else $err :stmt ;
- $( ($e_rest:expr) -> ($p_rest:pat) else $err_rest:stmt ; )*
- binds $( $bind_res:ident ),*
- ) => (
- match $e {
- $p => {
- // Recursively handle the next layer
- biased_match_rec!($( ($e_rest) -> ($p_rest) else $err_rest ; )*
- binds $( $bind_res ),*
- )
- }
- _ => { $err }
- }
- );
- // Produce the requested values
- ( binds $( $bind_res:ident ),* ) => ( ($( $bind_res ),*) )
-}
+```ignore
+macro_rules! vec { ... }
+```
-// Wrap the whole thing in a `let`.
-macro_rules! biased_match {
- // special case: `let (x) = ...` is illegal, so use `let x = ...` instead
- ( $( ($e:expr) -> ($p:pat) else $err:stmt ; )*
- binds $bind_res:ident
- ) => (
- let $bind_res = biased_match_rec!(
- $( ($e) -> ($p) else $err ; )*
- binds $bind_res
- );
- );
- // more than one name: use a tuple
- ( $( ($e:expr) -> ($p:pat) else $err:stmt ; )*
- binds $( $bind_res:ident ),*
- ) => (
- let ( $( $bind_res ),* ) = biased_match_rec!(
- $( ($e) -> ($p) else $err ; )*
- binds $( $bind_res ),*
- );
- )
-}
+This says we're defining a macro named `vec`, much as `fn vec` would define a
+function named `vec`. In prose, we informally write a macro's name with an
+exclamation point, e.g. `vec!`. The exclamation point is part of the invocation
+syntax and serves to distinguish a macro from an ordinary function.
+## Matching
-# enum T1 { Good1(T2, u32), Bad1}
-# struct T2 { body: T3 }
-# enum T3 { Good2(u32), Bad2}
-# fn f(x: T1) -> u32 {
-biased_match!(
- (x) -> (T1::Good1(g1, val)) else { return 0 };
- (g1.body) -> (T3::Good2(result) ) else { panic!("Didn't get Good2") };
- binds val, result );
-// complicated stuff goes here
-return result + val;
-# }
-# }
-~~~~
-
-This technique applies to many cases where transcribing a result all at once is not possible.
-The resulting code resembles ordinary functional programming in some respects,
-but has some important differences from functional programming.
-
-The first difference is important, but also easy to forget: the transcription
-(right-hand) side of a `macro_rules!` rule is literal syntax, which can only
-be executed at run-time. If a piece of transcription syntax does not itself
-appear inside another macro invocation, it will become part of the final
-program. If it is inside a macro invocation (for example, the recursive
-invocation of `biased_match_rec!`), it does have the opportunity to affect
-transcription, but only through the process of attempted pattern matching.
-
-The second, related, difference is that the evaluation order of macros feels
-"backwards" compared to ordinary programming. Given an invocation
-`m1!(m2!())`, the expander first expands `m1!`, giving it as input the literal
-syntax `m2!()`. If it transcribes its argument unchanged into an appropriate
-position (in particular, not as an argument to yet another macro invocation),
-the expander will then proceed to evaluate `m2!()` (along with any other macro
-invocations `m1!(m2!())` produced).
+The macro is defined through a series of *rules*, which are pattern-matching
+cases. Above, we had
-# Hygiene
+```ignore
+( $( $x:expr ),* ) => { ... };
+```
-To prevent clashes, rust implements
-[hygienic macros](http://en.wikipedia.org/wiki/Hygienic_macro).
+This is like a `match` expression arm, but the matching happens on Rust syntax
+trees, at compile time. The semicolon is optional on the last (here, only)
+case. The "pattern" on the left-hand side of `=>` is known as a *matcher*.
+These have [their own little grammar] within the language.
-As an example, `loop` and `for-loop` labels (discussed in the lifetimes guide)
-will not clash. The following code will print "Hello!" only once:
+[their own little grammar]: ../reference.html#macros
-~~~
-macro_rules! loop_x {
- ($e: expr) => (
- // $e will not interact with this 'x
- 'x: loop {
- println!("Hello!");
- $e
- }
- );
+The matcher `$x:expr` will match any Rust expression, binding that syntax tree
+to the *metavariable* `$x`. The identifier `expr` is a *fragment specifier*;
+the full possibilities are enumerated in the [advanced macros chapter][].
+Surrounding the matcher with `$(...),*` will match zero or more expressions,
+separated by commas.
+
+Aside from the special matcher syntax, any Rust tokens that appear in a matcher
+must match exactly. For example,
+
+```rust
+macro_rules! foo {
+ (x => $e:expr) => (println!("mode X: {}", $e));
+ (y => $e:expr) => (println!("mode Y: {}", $e));
}
fn main() {
- 'x: loop {
- loop_x!(break 'x);
- println!("I am never printed.");
- }
+ foo!(y => 3);
}
-~~~
+```
-The two `'x` names did not clash, which would have caused the loop
-to print "I am never printed" and to run forever.
+will print
-# Scoping and macro import/export
+```text
+mode Y: 3
+```
+
+With
-Macros are expanded at an early stage in compilation, before name resolution.
-One downside is that scoping works differently for macros, compared to other
-constructs in the language.
+```rust,ignore
+foo!(z => 3);
+```
-Definition and expansion of macros both happen in a single depth-first,
-lexical-order traversal of a crate's source. So a macro defined at module scope
-is visible to any subsequent code in the same module, which includes the body
-of any subsequent child `mod` items.
+we get the compiler error
-A macro defined within the body of a single `fn`, or anywhere else not at
-module scope, is visible only within that item.
+```text
+error: no rules expected the token `z`
+```
-If a module has the `macro_use` attribute, its macros are also visible in its
-parent module after the child's `mod` item. If the parent also has `macro_use`
-then the macros will be visible in the grandparent after the parent's `mod`
-item, and so forth.
+## Expansion
-The `macro_use` attribute can also appear on `extern crate`. In this context
-it controls which macros are loaded from the external crate, e.g.
+The right-hand side of a macro rule is ordinary Rust syntax, for the most part.
+But we can splice in bits of syntax captured by the matcher. From the original
+example:
-```rust,ignore
-#[macro_use(foo, bar)]
-extern crate baz;
+```ignore
+$(
+ temp_vec.push($x);
+)*
```
-If the attribute is given simply as `#[macro_use]`, all macros are loaded. If
-there is no `#[macro_use]` attribute then no macros are loaded. Only macros
-defined with the `#[macro_export]` attribute may be loaded.
+Each matched expression `$x` will produce a single `push` statement in the
+macro expansion. The repetition in the expansion proceeds in "lockstep" with
+repetition in the matcher (more on this in a moment).
-To load a crate's macros *without* linking it into the output, use `#[no_link]`
-as well.
+Because `$x` was already declared as matching an expression, we don't repeat
+`:expr` on the right-hand side. Also, we don't include a separating comma as
+part of the repetition operator. Instead, we have a terminating semicolon
+within the repeated block.
-An example:
+Another detail: the `vec!` macro has *two* pairs of braces on the right-hand
+side. They are often combined like so:
-```rust
-macro_rules! m1 { () => (()) }
+```ignore
+macro_rules! foo {
+ () => {{
+ ...
+ }}
+}
+```
+
+The outer braces are part of the syntax of `macro_rules!`. In fact, you can use
+`()` or `[]` instead. They simply delimit the right-hand side as a whole.
+
+The inner braces are part of the expanded syntax. Remember, the `vec!` macro is
+used in an expression context. To write an expression with multiple statements,
+including `let`-bindings, we use a block. If your macro expands to a single
+expression, you don't need this extra layer of braces.
+
+Note that we never *declared* that the macro produces an expression. In fact,
+this is not determined until we use the macro as an expression. With care, you
+can write a macro whose expansion works in several contexts. For example,
+shorthand for a data type could be valid as either an expression or a pattern.
+
+## Repetition
-// visible here: m1
+The repetition behavior can seem somewhat magical, especially when multiple
+names are bound at multiple nested levels of repetition. The two rules to keep
+in mind are:
-mod foo {
- // visible here: m1
+1. the behavior of `$(...)*` is to walk through one "layer" of repetitions, for
+all of the `$name`s it contains, in lockstep, and
+2. each `$name` must be under at least as many `$(...)*`s as it was matched
+against. If it is under more, it'll be duplicated, as appropriate.
- #[macro_export]
- macro_rules! m2 { () => (()) }
+This baroque macro illustrates the duplication of variables from outer
+repetition levels.
+
+```rust
+macro_rules! o_O {
+ (
+ $(
+ $x:expr; [ $( $y:expr ),* ]
+ );*
+ ) => {
+ &[ $($( $x + $y ),*),* ]
+ }
+}
+
+fn main() {
+ let a: &[i32]
+ = o_O!(10; [1, 2, 3];
+ 20; [4, 5, 6]);
- // visible here: m1, m2
+ assert_eq!(a, [11, 12, 13, 24, 25, 26]);
}
+```
-// visible here: m1
+That's most of the matcher syntax. These examples use `$(...)*`, which is a
+"zero or more" match. Alternatively you can write `$(...)+` for a "one or
+more" match. Both forms optionally include a separator, which can be any token
+except `+` or `*`.
-macro_rules! m3 { () => (()) }
+# Hygiene
-// visible here: m1, m3
+Some languages implement macros using simple text substitution, which leads to
+various problems. For example, this C program prints `13` instead of the
+expected `25`.
-#[macro_use]
-mod bar {
- // visible here: m1, m3
+```text
+#define FIVE_TIMES(x) 5 * x
- macro_rules! m4 { () => (()) }
+int main() {
+ printf("%d\n", FIVE_TIMES(2 + 3));
+ return 0;
+}
+```
- // visible here: m1, m3, m4
+After expansion we have `5 * 2 + 3`, and multiplication has greater precedence
+than addition. If you've used C macros a lot, you probably know the standard
+idioms for avoiding this problem, as well as five or six others. In Rust, we
+don't have to worry about it.
+
+```rust
+macro_rules! five_times {
+ ($x:expr) => (5 * $x);
}
-// visible here: m1, m3, m4
-# fn main() { }
+fn main() {
+ assert_eq!(25, five_times!(2 + 3));
+}
+```
+
+The metavariable `$x` is parsed as a single expression node, and keeps its
+place in the syntax tree even after substitution.
+
+Another common problem in macro systems is *variable capture*. Here's a C
+macro, using [a GNU C extension] to emulate Rust's expression blocks.
+
+[a GNU C extension]: https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html
+
+```text
+#define LOG(msg) ({ \
+ int state = get_log_state(); \
+ if (state > 0) { \
+ printf("log(%d): %s\n", state, msg); \
+ } \
+})
```
-When this library is loaded with `#[use_macros] extern crate`, only `m2` will
-be imported.
+This looks reasonable, but watch what happens in this example:
-The Rust Reference has a [listing of macro-related
-attributes](../reference.html#macro--and-plugin-related-attributes).
+```text
+const char *state = "reticulating splines";
+LOG(state);
+```
+
+The program will likely segfault, after it tries to execute
-# The variable `$crate`
+```text
+printf("log(%d): %s\n", state, state);
+```
-A further difficulty occurs when a macro is used in multiple crates. Say that
-`mylib` defines
+The equivalent Rust macro has the desired behavior.
```rust
-pub fn increment(x: u32) -> u32 {
- x + 1
+# fn get_log_state() -> i32 { 3 }
+macro_rules! log {
+ ($msg:expr) => {{
+ let state: i32 = get_log_state();
+ if state > 0 {
+ println!("log({}): {}", state, $msg);
+ }
+ }};
}
-#[macro_export]
-macro_rules! inc_a {
- ($x:expr) => ( ::increment($x) )
+fn main() {
+ let state: &str = "reticulating splines";
+ log!(state);
}
+```
+
+This works because Rust has a [hygienic macro system][]. Each macro expansion
+happens in a distinct *syntax context*, and each variable is tagged with the
+syntax context where it was introduced. It's as though the variable `state`
+inside `main` is painted a different "color" from the variable `state` inside
+the macro, and therefore they don't conflict.
-#[macro_export]
-macro_rules! inc_b {
- ($x:expr) => ( ::mylib::increment($x) )
+[hygienic macro system]: http://en.wikipedia.org/wiki/Hygienic_macro
+
+This also restricts the ability of macros to introduce new bindings at the
+invocation site. Code such as the following will not work:
+
+```rust,ignore
+macro_rules! foo {
+ () => (let x = 3);
+}
+
+fn main() {
+ foo!();
+ println!("{}", x);
}
-# fn main() { }
```
-`inc_a` only works within `mylib`, while `inc_b` only works outside the
-library. Furthermore, `inc_b` will break if the user imports `mylib` under
-another name.
+Instead you need to pass the variable name into the invocation, so it's tagged
+with the right syntax context.
-Rust does not (yet) have a hygiene system for crate references, but it does
-provide a simple workaround for this problem. Within a macro imported from a
-crate named `foo`, the special macro variable `$crate` will expand to `::foo`.
-By contrast, when a macro is defined and then used in the same crate, `$crate`
-will expand to nothing. This means we can write
+```rust
+macro_rules! foo {
+ ($v:ident) => (let $v = 3);
+}
+
+fn main() {
+ foo!(x);
+ println!("{}", x);
+}
+```
+
+This holds for `let` bindings and loop labels, but not for [items][].
+So the following code does compile:
```rust
-#[macro_export]
-macro_rules! inc {
- ($x:expr) => ( $crate::increment($x) )
+macro_rules! foo {
+ () => (fn x() { });
+}
+
+fn main() {
+ foo!();
+ x();
}
-# fn main() { }
```
-to define a single macro that works both inside and outside our library. The
-function name will expand to either `::increment` or `::mylib::increment`.
-
-To keep this system simple and correct, `#[macro_use] extern crate ...` may
-only appear at the root of your crate, not inside `mod`. This ensures that
-`$crate` is a single identifier.
-
-# A final note
-
-Macros, as currently implemented, are not for the faint of heart. Even
-ordinary syntax errors can be more difficult to debug when they occur inside a
-macro, and errors caused by parse problems in generated code can be very
-tricky. Invoking the `log_syntax!` macro can help elucidate intermediate
-states, invoking `trace_macros!(true)` will automatically print those
-intermediate states out, and passing the flag `--pretty expanded` as a
-command-line argument to the compiler will show the result of expansion.
-
-If Rust's macro system can't do what you need, you may want to write a
-[compiler plugin](plugins.html) instead. Compared to `macro_rules!`
-macros, this is significantly more work, the interfaces are much less stable,
-and the warnings about debugging apply ten-fold. In exchange you get the
-flexibility of running arbitrary Rust code within the compiler. Syntax
-extension plugins are sometimes called *procedural macros* for this reason.
+[items]: ../reference.html#items
+
+# Further reading
+
+The [advanced macros chapter][] goes into more detail about macro syntax. It
+also describes how to share macros between different modules or crates.
+
+[advanced macros chapter]: advanced-macros.html
# Circle } }
```
-We just say we're returning a `Circle`. With this, we can grow a new circle
-that's twice as big as the old one.
+We just say we're returning a `Circle`. With this method, we can grow a new
+circle with an area that's 100 times larger than the old one.
## Static methods
}
fn main() {
- let y = &5; // this is the same as `let _y = 5; let y = &_y;
+ let y = &5; // this is the same as `let _y = 5; let y = &_y;`
let f = Foo { x: y };
println!("{}", f.x);
dispatched. What's that mean? Check out the chapter on [static and dynamic
dispatch](static-and-dynamic-dispatch.html) for more.
+## Where clause
+
+Writing functions with only a few generic types and a small number of trait
+bounds isn't too bad, but as the number increases, the syntax gets increasingly
+awkward:
+
+```
+use std::fmt::Debug;
+
+fn foo<T: Clone, K: Clone + Debug>(x: T, y: K) {
+ x.clone();
+ y.clone();
+ println!("{:?}", y);
+}
+```
+
+The name of the function is on the far left, and the parameter list is on the
+far right. The bounds are getting in the way.
+
+Rust has a solution, and it's called a '`where` clause':
+
+```
+use std::fmt::Debug;
+
+fn foo<T: Clone, K: Clone + Debug>(x: T, y: K) {
+ x.clone();
+ y.clone();
+ println!("{:?}", y);
+}
+
+fn bar<T, K>(x: T, y: K) where T: Clone, K: Clone + Debug {
+ x.clone();
+ y.clone();
+ println!("{:?}", y);
+}
+
+fn main() {
+ foo("Hello", "world");
+ bar("Hello", "workd");
+}
+```
+
+`foo()` uses the syntax we showed earlier, and `bar()` uses a `where` clause.
+All you need to do is leave off the bounds when defining your type parameters,
+and then add `where` after the parameter list. For longer lists, whitespace can
+be added:
+
+```
+use std::fmt::Debug;
+
+fn bar<T, K>(x: T, y: K)
+ where T: Clone,
+ K: Clone + Debug {
+
+ x.clone();
+ y.clone();
+ println!("{:?}", y);
+}
+```
+
+This flexibility can add clarity in complex situations.
+
+`where` is also more powerful than the simpler syntax. For example:
+
+```
+trait ConvertTo<Output> {
+ fn convert(&self) -> Output;
+}
+
+impl ConvertTo<i64> for i32 {
+ fn convert(&self) -> i64 { *self as i64 }
+}
+
+// can be called with T == i32
+fn normal<T: ConvertTo<i64>>(x: &T) -> i64 {
+ x.convert()
+}
+
+// can be called with T == i64
+fn inverse<T>() -> T
+ // this is using ConvertTo as if it were "ConvertFrom<i32>"
+ where i32: ConvertTo<T> {
+ 1i32.convert()
+}
+```
+
+This shows off the additional feature of `where` clauses: they allow bounds
+where the left-hand side is an arbitrary type (`i32` in this case), not just a
+plain type parameter (like `T`).
+
## Our `inverse` Example
Back in [Generics](generics.html), we were trying to write code like this:
## Assembly template
The `assembly template` is the only required parameter and must be a
-literal string (i.e `""`)
+literal string (i.e. `""`)
```
#![feature(asm)]
## Options
The last section, `options` is specific to Rust. The format is comma
-separated literal strings (i.e `:"foo", "bar", "baz"`). It's used to
+separated literal strings (i.e. `:"foo", "bar", "baz"`). It's used to
specify some extra info about the inline assembly:
Current valid options are:
1. *volatile* - specifying this is analogous to
`__asm__ __volatile__ (...)` in gcc/clang.
2. *alignstack* - certain instructions expect the stack to be
- aligned a certain way (i.e SSE) and specifying this indicates to
+ aligned a certain way (i.e. SSE) and specifying this indicates to
the compiler to insert its usual stack alignment code
3. *intel* - use intel syntax instead of the default AT&T.
functionality that isn't hard-coded into the language, but is
implemented in libraries, with a special marker to tell the compiler
it exists. The marker is the attribute `#[lang="..."]` and there are
-various different values of `...`, i.e. various different "lang
-items".
+various different values of `...`, i.e. various different 'lang
+items'.
For example, `Box` pointers require two lang items, one for allocation
and one for deallocation. A freestanding program that uses the `Box`
then
shift
+ # The length of binary path (i.e. ./$RUN) should be shorter than 128 characters.
cd $TEST_PATH
- TEST_EXEC_ENV=22 LD_LIBRARY_PATH=$TEST_PATH PATH=$BIN_PATH:$TEST_PATH $TEST_PATH/$RUN $@ 1>$TEST_PATH/$RUN.stdout 2>$TEST_PATH/$RUN.stderr
+ TEST_EXEC_ENV=22 LD_LIBRARY_PATH=$TEST_PATH PATH=$BIN_PATH:$TEST_PATH ./$RUN $@ 1>$TEST_PATH/$RUN.stdout 2>$TEST_PATH/$RUN.stderr
L_RET=$?
echo $L_RET > $TEST_PATH/$RUN.exitcode
//!
//! ```
//! use std::sync::Arc;
-//! use std::thread::Thread;
+//! use std::thread;
//!
//! let five = Arc::new(5);
//!
//! for _ in 0..10 {
//! let five = five.clone();
//!
-//! Thread::spawn(move || {
+//! thread::spawn(move || {
//! println!("{:?}", five);
//! });
//! }
//!
//! ```
//! use std::sync::{Arc, Mutex};
-//! use std::thread::Thread;
+//! use std::thread;
//!
//! let five = Arc::new(Mutex::new(5));
//!
//! for _ in 0..10 {
//! let five = five.clone();
//!
-//! Thread::spawn(move || {
+//! thread::spawn(move || {
//! let mut number = five.lock().unwrap();
//!
//! *number += 1;
///
/// ```rust
/// use std::sync::Arc;
-/// use std::thread::Thread;
+/// use std::thread;
///
/// fn main() {
/// let numbers: Vec<_> = (0..100u32).map(|i| i as f32).collect();
/// for _ in 0..10 {
/// let child_numbers = shared_numbers.clone();
///
-/// Thread::spawn(move || {
+/// thread::spawn(move || {
/// let local_numbers = child_numbers.as_slice();
///
/// // Work with the local numbers
use std::option::Option::{Some, None};
use std::sync::atomic;
use std::sync::atomic::Ordering::{Acquire, SeqCst};
- use std::thread::Thread;
+ use std::thread;
use std::vec::Vec;
use super::{Arc, Weak, weak_count, strong_count};
use std::sync::Mutex;
let (tx, rx) = channel();
- let _t = Thread::spawn(move || {
+ let _t = thread::spawn(move || {
let arc_v: Arc<Vec<i32>> = rx.recv().unwrap();
assert_eq!((*arc_v)[3], 4);
});
// optimize it out).
#[doc(hidden)]
pub fn fixme_14344_be_sure_to_link_to_collections() {}
-
-// NOTE: remove after next snapshot
-#[cfg(all(stage0, not(test)))]
-#[doc(hidden)]
-mod std {
- pub use core::fmt;
- pub use core::option;
-}
weak: Cell<usize>
}
-/// An immutable reference-counted pointer type.
+/// A reference-counted pointer type over an immutable value.
///
/// See the [module level documentation](./index.html) for more details.
#[unsafe_no_drop_flag]
// the contract anyway.
// This allows the null check to be elided in the destructor if we
// manipulated the reference count in the same function.
- if cfg!(not(stage0)) { // NOTE remove cfg after next snapshot
- assume(!self._ptr.is_null());
- }
+ assume(!self._ptr.is_null());
&(**self._ptr)
}
}
// the contract anyway.
// This allows the null check to be elided in the destructor if we
// manipulated the reference count in the same function.
- if cfg!(not(stage0)) { // NOTE remove cfg after next snapshot
- assume(!self._ptr.is_null());
- }
+ assume(!self._ptr.is_null());
&(**self._ptr)
}
}
}
}
-// NOTE(stage0): remove impl after a snapshot
-#[cfg(stage0)]
-impl<T: Ord> IntoIterator for BinaryHeap<T> {
- type IntoIter = IntoIter<T>;
-
- fn into_iter(self) -> IntoIter<T> {
- self.into_iter()
- }
-}
-
-#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
+#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Ord> IntoIterator for BinaryHeap<T> {
type Item = T;
type IntoIter = IntoIter<T>;
}
}
-// NOTE(stage0): remove impl after a snapshot
-#[cfg(stage0)]
-impl<'a, T> IntoIterator for &'a BinaryHeap<T> where T: Ord {
- type IntoIter = Iter<'a, T>;
-
- fn into_iter(self) -> Iter<'a, T> {
- self.iter()
- }
-}
-
-#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
+#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> IntoIterator for &'a BinaryHeap<T> where T: Ord {
type Item = &'a T;
type IntoIter = Iter<'a, T>;
}
}
-// NOTE(stage0): remove impl after a snapshot
-#[cfg(stage0)]
-impl<'a> IntoIterator for &'a Bitv {
- type IntoIter = Iter<'a>;
-
- fn into_iter(self) -> Iter<'a> {
- self.iter()
- }
-}
-
-#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
+#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> IntoIterator for &'a Bitv {
type Item = bool;
type IntoIter = Iter<'a>;
#[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.0.size_hint() }
}
-// NOTE(stage0): remove impl after a snapshot
-#[cfg(stage0)]
-impl<'a> IntoIterator for &'a BitvSet {
- type IntoIter = SetIter<'a>;
-
- fn into_iter(self) -> SetIter<'a> {
- self.iter()
- }
-}
-
-#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
+#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> IntoIterator for &'a BitvSet {
type Item = usize;
type IntoIter = SetIter<'a>;
#[test]
fn test_from_bools() {
let bools = vec![true, false, true, true];
- let bitv: Bitv = bools.iter().map(|n| *n).collect();
+ let bitv: Bitv = bools.iter().cloned().collect();
assert_eq!(format!("{:?}", bitv), "1011");
}
#[test]
fn test_bitv_iterator() {
let bools = vec![true, false, true, true];
- let bitv: Bitv = bools.iter().map(|n| *n).collect();
+ let bitv: Bitv = bools.iter().cloned().collect();
assert_eq!(bitv.iter().collect::<Vec<bool>>(), bools);
let long: Vec<_> = (0i32..10000).map(|i| i % 2 == 0).collect();
- let bitv: Bitv = long.iter().map(|n| *n).collect();
+ let bitv: Bitv = long.iter().cloned().collect();
assert_eq!(bitv.iter().collect::<Vec<bool>>(), long)
}
}
}
-// NOTE(stage0): remove impl after a snapshot
-#[cfg(stage0)]
-impl<K, V> IntoIterator for BTreeMap<K, V> {
- type IntoIter = IntoIter<K, V>;
-
- fn into_iter(self) -> IntoIter<K, V> {
- self.into_iter()
- }
-}
-
-#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
+#[stable(feature = "rust1", since = "1.0.0")]
impl<K, V> IntoIterator for BTreeMap<K, V> {
type Item = (K, V);
type IntoIter = IntoIter<K, V>;
}
}
-// NOTE(stage0): remove impl after a snapshot
-#[cfg(stage0)]
-impl<'a, K, V> IntoIterator for &'a BTreeMap<K, V> {
- type IntoIter = Iter<'a, K, V>;
-
- fn into_iter(self) -> Iter<'a, K, V> {
- self.iter()
- }
-}
-
-#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
+#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, K, V> IntoIterator for &'a BTreeMap<K, V> {
type Item = (&'a K, &'a V);
type IntoIter = Iter<'a, K, V>;
}
}
-// NOTE(stage0): remove impl after a snapshot
-#[cfg(stage0)]
-impl<'a, K, V> IntoIterator for &'a mut BTreeMap<K, V> {
- type IntoIter = IterMut<'a, K, V>;
-
- fn into_iter(mut self) -> IterMut<'a, K, V> {
- self.iter_mut()
- }
-}
-
-#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
+#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, K, V> IntoIterator for &'a mut BTreeMap<K, V> {
type Item = (&'a K, &'a mut V);
type IntoIter = IterMut<'a, K, V>;
}
}
-// NOTE(stage0): remove impl after a snapshot
-#[cfg(stage0)]
-impl<T> IntoIterator for BTreeSet<T> {
- type IntoIter = IntoIter<T>;
-
- fn into_iter(self) -> IntoIter<T> {
- self.into_iter()
- }
-}
-
-#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
+#[stable(feature = "rust1", since = "1.0.0")]
impl<T> IntoIterator for BTreeSet<T> {
type Item = T;
type IntoIter = IntoIter<T>;
}
}
-// NOTE(stage0): remove impl after a snapshot
-#[cfg(stage0)]
-impl<'a, T> IntoIterator for &'a BTreeSet<T> {
- type IntoIter = Iter<'a, T>;
-
- fn into_iter(self) -> Iter<'a, T> {
- self.iter()
- }
-}
-
-#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
+#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> IntoIterator for &'a BTreeSet<T> {
type Item = &'a T;
type IntoIter = Iter<'a, T>;
}
}
-// NOTE(stage0): remove impl after a snapshot
-#[cfg(stage0)]
-impl<T> IntoIterator for DList<T> {
- type IntoIter = IntoIter<T>;
-
- fn into_iter(self) -> IntoIter<T> {
- self.into_iter()
- }
-}
-
-#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
+#[stable(feature = "rust1", since = "1.0.0")]
impl<T> IntoIterator for DList<T> {
type Item = T;
type IntoIter = IntoIter<T>;
}
}
-// NOTE(stage0): remove impl after a snapshot
-#[cfg(stage0)]
-impl<'a, T> IntoIterator for &'a DList<T> {
- type IntoIter = Iter<'a, T>;
-
- fn into_iter(self) -> Iter<'a, T> {
- self.iter()
- }
-}
-
-#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
+#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> IntoIterator for &'a DList<T> {
type Item = &'a T;
type IntoIter = Iter<'a, T>;
}
}
-// NOTE(stage0): remove impl after a snapshot
-#[cfg(stage0)]
-impl<'a, T> IntoIterator for &'a mut DList<T> {
- type IntoIter = IterMut<'a, T>;
-
- fn into_iter(mut self) -> IterMut<'a, T> {
- self.iter_mut()
- }
-}
-
-#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
impl<'a, T> IntoIterator for &'a mut DList<T> {
type Item = &'a mut T;
type IntoIter = IterMut<'a, T>;
#[stable(feature = "rust1", since = "1.0.0")]
impl<A: Clone> Clone for DList<A> {
fn clone(&self) -> DList<A> {
- self.iter().map(|x| x.clone()).collect()
+ self.iter().cloned().collect()
}
}
use prelude::*;
use std::rand;
use std::hash::{self, SipHasher};
- use std::thread::Thread;
+ use std::thread;
use test::Bencher;
use test;
#[cfg(test)]
fn list_from<T: Clone>(v: &[T]) -> DList<T> {
- v.iter().map(|x| (*x).clone()).collect()
+ v.iter().cloned().collect()
}
#[test]
#[test]
fn test_send() {
let n = list_from(&[1,2,3]);
- Thread::scoped(move || {
+ thread::spawn(move || {
check_links(&n);
let a: &[_] = &[&1,&2,&3];
assert_eq!(a, n.iter().collect::<Vec<_>>());
}
}
-// NOTE(stage0): remove impl after a snapshot
-#[cfg(stage0)]
-impl<'a, E> IntoIterator for &'a EnumSet<E> where E: CLike {
- type IntoIter = Iter<E>;
-
- fn into_iter(self) -> Iter<E> {
- self.iter()
- }
-}
-
-#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
+#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, E> IntoIterator for &'a EnumSet<E> where E: CLike {
type Item = E;
type IntoIter = Iter<E>;
//!
//! impl fmt::Display for Vector2D {
//! fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-//! // The `f` value implements the `Writer` trait, which is what the
+//! // The `f` value implements the `Write` trait, which is what the
//! // write! macro is expecting. Note that this formatting ignores the
//! // various flags provided to format strings.
//! write!(f, "({}, {})", self.x, self.y)
#![stable(feature = "rust1", since = "1.0.0")]
-pub use core::fmt::{Formatter, Result, Writer, rt};
+pub use core::fmt::{Formatter, Result, Write, rt};
pub use core::fmt::{Show, String, Octal, Binary};
pub use core::fmt::{Display, Debug};
pub use core::fmt::{LowerHex, UpperHex, Pointer};
#[cfg(not(test))]
mod std {
- // NOTE: remove after next snapshot
- #[cfg(stage0)] pub use core::clone; // derive(Clone)
- #[cfg(stage0)] pub use core::cmp; // derive(Eq, Ord, etc.)
- #[cfg(stage0)] pub use core::marker; // derive(Copy)
- #[cfg(stage0)] pub use core::hash; // derive(Hash)
- #[cfg(stage0)] pub use core::iter;
- #[cfg(stage0)] pub use core::fmt; // necessary for panic!()
- #[cfg(stage0)] pub use core::option; // necessary for panic!()
-
pub use core::ops; // RangeFull
}
// except according to those terms.
/// Creates a `Vec` containing the arguments.
+///
+/// `vec!` allows `Vec`s to be defined with the same syntax as array expressions.
+/// There are two forms of this macro:
+///
+/// - Create a `Vec` containing a given list of elements:
+///
+/// ```
+/// let v = vec![1, 2, 3];
+/// assert_eq!(v[0], 1);
+/// assert_eq!(v[1], 2);
+/// assert_eq!(v[2], 3);
+/// ```
+///
+/// - Create a `Vec` from a given element and size:
+///
+/// ```
+/// let v = vec![1; 3];
+/// assert_eq!(v, vec![1, 1, 1]);
+/// ```
+///
+/// Note that unlike array expressions this syntax supports all elements
+/// which implement `Clone` and the number of elements doesn't have to be
+/// a constant.
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
macro_rules! vec {
- ($x:expr; $y:expr) => (
- <[_] as $crate::slice::SliceExt>::into_vec(
- $crate::boxed::Box::new([$x; $y]))
+ ($elem:expr; $n:expr) => (
+ $crate::vec::from_elem($elem, $n)
);
($($x:expr),*) => (
<[_] as $crate::slice::SliceExt>::into_vec(
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-//! This crate implements a double-ended queue with `O(1)` amortized inserts and removals from both
-//! ends of the container. It also has `O(1)` indexing like a vector. The contained elements are
-//! not required to be copyable, and the queue will be sendable if the contained type is sendable.
+//! RingBuf is a double-ended queue, which is implemented with the help of a
+//! growing circular buffer.
+//!
+//! This queue has `O(1)` amortized inserts and removals from both ends of the
+//! container. It also has `O(1)` indexing like a vector. The contained elements
+//! are not required to be copyable, and the queue will be sendable if the
+//! contained type is sendable.
#![stable(feature = "rust1", since = "1.0.0")]
#[inline]
fn is_full(&self) -> bool { self.cap - self.len() == 1 }
- /// Returns the index in the underlying buffer for a given logical element index.
+ /// Returns the index in the underlying buffer for a given logical element
+ /// index.
#[inline]
fn wrap_index(&self, idx: usize) -> usize { wrap_index(idx, self.cap) }
}
}
-// NOTE(stage0): remove impl after a snapshot
-#[cfg(stage0)]
-impl<T> IntoIterator for RingBuf<T> {
- type IntoIter = IntoIter<T>;
-
- fn into_iter(self) -> IntoIter<T> {
- self.into_iter()
- }
-}
-
-#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
+#[stable(feature = "rust1", since = "1.0.0")]
impl<T> IntoIterator for RingBuf<T> {
type Item = T;
type IntoIter = IntoIter<T>;
}
}
-// NOTE(stage0): remove impl after a snapshot
-#[cfg(stage0)]
-impl<'a, T> IntoIterator for &'a RingBuf<T> {
- type IntoIter = Iter<'a, T>;
-
- fn into_iter(self) -> Iter<'a, T> {
- self.iter()
- }
-}
-
-#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
+#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> IntoIterator for &'a RingBuf<T> {
type Item = &'a T;
type IntoIter = Iter<'a, T>;
}
}
-// NOTE(stage0): remove impl after a snapshot
-#[cfg(stage0)]
-impl<'a, T> IntoIterator for &'a mut RingBuf<T> {
- type IntoIter = IterMut<'a, T>;
-
- fn into_iter(mut self) -> IterMut<'a, T> {
- self.iter_mut()
- }
-}
-
-#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
+#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> IntoIterator for &'a mut RingBuf<T> {
type Item = &'a mut T;
type IntoIter = IterMut<'a, T>;
impl<T: fmt::Display + ?Sized> ToString for T {
#[inline]
fn to_string(&self) -> String {
- use core::fmt::Writer;
+ use core::fmt::Write;
let mut buf = String::new();
let _ = buf.write_fmt(format_args!("{}", self));
buf.shrink_to_fit();
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl fmt::Writer for String {
+impl fmt::Write for String {
#[inline]
fn write_str(&mut self, s: &str) -> fmt::Result {
self.push_str(s);
use core::default::Default;
use core::fmt;
use core::hash::{self, Hash};
+use core::intrinsics::assume;
use core::iter::{repeat, FromIterator, IntoIterator};
use core::marker::{self, ContravariantLifetime, InvariantType};
use core::mem;
}
}
+#[doc(hidden)]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub fn from_elem<T: Clone>(elem: T, n: usize) -> Vec<T> {
+ unsafe {
+ let mut v = Vec::with_capacity(n);
+ let mut ptr = v.as_mut_ptr();
+
+ // Write all elements except the last one
+ for i in 1..n {
+ ptr::write(ptr, Clone::clone(&elem));
+ ptr = ptr.offset(1);
+ v.set_len(i); // Increment the length in every step in case Clone::clone() panics
+ }
+
+ if n > 0 {
+ // We can write the last element directly without cloning needlessly
+ ptr::write(ptr, elem);
+ v.set_len(n);
+ }
+
+ v
+ }
+}
+
////////////////////////////////////////////////////////////////////////////////
// Common trait implementations for Vec
////////////////////////////////////////////////////////////////////////////////
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> FromIterator<T> for Vec<T> {
#[inline]
- fn from_iter<I:Iterator<Item=T>>(iterator: I) -> Vec<T> {
+ fn from_iter<I:Iterator<Item=T>>(mut iterator: I) -> Vec<T> {
let (lower, _) = iterator.size_hint();
let mut vector = Vec::with_capacity(lower);
// vector.push(item);
// }
//
- // This equivalent crucially runs the iterator precisely once. The
- // optimization below (eliding bound/growth checks) means that we
- // actually run the iterator twice. To ensure the "moral equivalent" we
- // do a `fuse()` operation to ensure that the iterator continues to
- // return `None` after seeing the first `None`.
- let mut i = iterator.fuse();
- for element in i.by_ref().take(vector.capacity()) {
+ // This equivalent crucially runs the iterator precisely once. Below we
+ // actually in theory run the iterator twice (one without bounds checks
+ // and one with). To achieve the "moral equivalent", we use the `if`
+ // statement below to break out early.
+ //
+ // If the first loop has terminated, then we have one of two conditions.
+ //
+ // 1. The underlying iterator returned `None`. In this case we are
+ // guaranteed that less than `vector.capacity()` elements have been
+ // returned, so we break out early.
+ // 2. The underlying iterator yielded `vector.capacity()` elements and
+ // has not yielded `None` yet. In this case we run the iterator to
+ // its end below.
+ for element in iterator.by_ref().take(vector.capacity()) {
let len = vector.len();
unsafe {
ptr::write(vector.get_unchecked_mut(len), element);
}
}
- for element in i {
- vector.push(element)
+ if vector.len() == vector.capacity() {
+ for element in iterator {
+ vector.push(element);
+ }
}
vector
}
}
-// NOTE(stage0): remove impl after a snapshot
-#[cfg(stage0)]
-impl<T> IntoIterator for Vec<T> {
- type IntoIter = IntoIter<T>;
-
- fn into_iter(self) -> IntoIter<T> {
- self.into_iter()
- }
-}
-
-#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
+#[stable(feature = "rust1", since = "1.0.0")]
impl<T> IntoIterator for Vec<T> {
type Item = T;
type IntoIter = IntoIter<T>;
}
}
-// NOTE(stage0): remove impl after a snapshot
-#[cfg(stage0)]
-impl<'a, T> IntoIterator for &'a Vec<T> {
- type IntoIter = slice::Iter<'a, T>;
-
- fn into_iter(self) -> slice::Iter<'a, T> {
- self.iter()
- }
-}
-
-#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
+#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> IntoIterator for &'a Vec<T> {
type Item = &'a T;
type IntoIter = slice::Iter<'a, T>;
}
}
-// NOTE(stage0): remove impl after a snapshot
-#[cfg(stage0)]
-impl<'a, T> IntoIterator for &'a mut Vec<T> {
- type IntoIter = slice::IterMut<'a, T>;
-
- fn into_iter(mut self) -> slice::IterMut<'a, T> {
- self.iter_mut()
- }
-}
-
-#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
+#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> IntoIterator for &'a mut Vec<T> {
type Item = &'a mut T;
type IntoIter = slice::IterMut<'a, T>;
#[stable(feature = "rust1", since = "1.0.0")]
fn as_slice(&self) -> &[T] {
unsafe {
+ let p = *self.ptr;
+ if cfg!(not(stage0)) { // NOTE remove cfg after next snapshot
+ assume(p != 0 as *mut T);
+ }
mem::transmute(RawSlice {
- data: *self.ptr,
+ data: p,
len: self.len
})
}
}
}
-// NOTE(stage0): remove impl after a snapshot
-#[cfg(stage0)]
-impl<T> IntoIterator for VecMap<T> {
- type IntoIter = IntoIter<T>;
-
- fn into_iter(self) -> IntoIter<T> {
- self.into_iter()
- }
-}
-
-#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
+#[stable(feature = "rust1", since = "1.0.0")]
impl<T> IntoIterator for VecMap<T> {
type Item = (usize, T);
type IntoIter = IntoIter<T>;
}
}
-// NOTE(stage0): remove impl after a snapshot
-#[cfg(stage0)]
-impl<'a, T> IntoIterator for &'a VecMap<T> {
- type IntoIter = Iter<'a, T>;
-
- fn into_iter(self) -> Iter<'a, T> {
- self.iter()
- }
-}
-
-#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
+#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> IntoIterator for &'a VecMap<T> {
type Item = (usize, &'a T);
type IntoIter = Iter<'a, T>;
}
}
-// NOTE(stage0): remove impl after a snapshot
-#[cfg(stage0)]
-impl<'a, T> IntoIterator for &'a mut VecMap<T> {
- type IntoIter = IterMut<'a, T>;
-
- fn into_iter(mut self) -> IterMut<'a, T> {
- self.iter_mut()
- }
-}
-
-#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
+#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> IntoIterator for &'a mut VecMap<T> {
type Item = (usize, &'a mut T);
type IntoIter = IterMut<'a, T>;
}
}
- // NOTE(stage0): remove impl after a snapshot
- #[cfg(stage0)]
- impl<'a, T> IntoIterator for &'a [T; $N] {
- type IntoIter = Iter<'a, T>;
-
- fn into_iter(self) -> Iter<'a, T> {
- self.iter()
- }
- }
-
- #[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
+ #[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> IntoIterator for &'a [T; $N] {
type Item = &'a T;
type IntoIter = Iter<'a, T>;
}
}
- // NOTE(stage0): remove impl after a snapshot
- #[cfg(stage0)]
- impl<'a, T> IntoIterator for &'a mut [T; $N] {
- type IntoIter = IterMut<'a, T>;
-
- fn into_iter(self) -> IterMut<'a, T> {
- self.iter_mut()
- }
- }
-
- #[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
+ #[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> IntoIterator for &'a mut [T; $N] {
type Item = &'a mut T;
type IntoIter = IterMut<'a, T>;
//! ```
//! use std::sync::Arc;
//! use std::sync::atomic::{AtomicUsize, Ordering};
-//! use std::thread::Thread;
+//! use std::thread;
//!
//! fn main() {
//! let spinlock = Arc::new(AtomicUsize::new(1));
//!
//! let spinlock_clone = spinlock.clone();
-//! Thread::spawn(move|| {
+//! thread::spawn(move|| {
//! spinlock_clone.store(0, Ordering::SeqCst);
//! });
//!
//! use std::cell::RefCell;
//!
//! struct Graph {
-//! edges: Vec<(uint, uint)>,
-//! span_tree_cache: RefCell<Option<Vec<(uint, uint)>>>
+//! edges: Vec<(i32, i32)>,
+//! span_tree_cache: RefCell<Option<Vec<(i32, i32)>>>
//! }
//!
//! impl Graph {
-//! fn minimum_spanning_tree(&self) -> Vec<(uint, uint)> {
+//! fn minimum_spanning_tree(&self) -> Vec<(i32, i32)> {
//! // Create a new scope to contain the lifetime of the
//! // dynamic borrow
//! {
//! // This is the major hazard of using `RefCell`.
//! self.minimum_spanning_tree()
//! }
-//! # fn calc_span_tree(&self) -> Vec<(uint, uint)> { vec![] }
+//! # fn calc_span_tree(&self) -> Vec<(i32, i32)> { vec![] }
//! }
//! ```
//!
//!
//! struct RcBox<T> {
//! value: T,
-//! refcount: Cell<uint>
+//! refcount: Cell<usize>
//! }
//!
//! impl<T> Clone for Rc<T> {
}
// Values [1, MAX-1] represent the number of `Ref` active
-// (will not outgrow its range since `uint` is the size of the address space)
-type BorrowFlag = uint;
+// (will not outgrow its range since `usize` is the size of the address space)
+type BorrowFlag = usize;
const UNUSED: BorrowFlag = 0;
const WRITING: BorrowFlag = -1;
///
/// ```
/// use std::cell::RefCell;
- /// use std::thread::Thread;
+ /// use std::thread;
///
- /// let result = Thread::scoped(move || {
+ /// let result = thread::spawn(move || {
/// let c = RefCell::new(5);
/// let m = c.borrow_mut();
///
///
/// ```
/// use std::cell::RefCell;
- /// use std::thread::Thread;
+ /// use std::thread;
///
- /// let result = Thread::scoped(move || {
+ /// let result = thread::spawn(move || {
/// let c = RefCell::new(5);
/// let m = c.borrow_mut();
///
///
/// **NOTE:** `UnsafeCell<T>`'s fields are public to allow static initializers. It is not
/// recommended to access its fields directly, `get` should be used instead.
-#[cfg_attr(stage0, lang="unsafe")] // NOTE: remove after next snapshot
-#[cfg_attr(not(stage0), lang="unsafe_cell")]
+#[lang="unsafe_cell"]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct UnsafeCell<T> {
/// Wrapped value
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-//! Defines the `PartialOrd` and `PartialEq` comparison traits.
+//! Functionality for ordering and comparison.
//!
-//! This module defines both `PartialOrd` and `PartialEq` traits which are used by the
-//! compiler to implement comparison operators. Rust programs may implement
-//!`PartialOrd` to overload the `<`, `<=`, `>`, and `>=` operators, and may implement
-//! `PartialEq` to overload the `==` and `!=` operators.
+//! This module defines both `PartialOrd` and `PartialEq` traits which are used by the compiler to
+//! implement comparison operators. Rust programs may implement `PartialOrd` to overload the `<`,
+//! `<=`, `>`, and `>=` operators, and may implement `PartialEq` to overload the `==` and `!=`
+//! operators.
//!
-//! For example, to define a type with a customized definition for the PartialEq
-//! operators, you could do the following:
+//! For example, to define a type with a customized definition for the PartialEq operators, you
+//! could do the following:
//!
-//! ```rust
+//! ```
//! use core::num::SignedInt;
//!
-//! // Our type.
-//! struct SketchyNum {
-//! num : int
+//! struct FuzzyNum {
+//! num: i32,
//! }
//!
-//! // Our implementation of `PartialEq` to support `==` and `!=`.
-//! impl PartialEq for SketchyNum {
+//! impl PartialEq for FuzzyNum {
//! // Our custom eq allows numbers which are near each other to be equal! :D
-//! fn eq(&self, other: &SketchyNum) -> bool {
+//! fn eq(&self, other: &FuzzyNum) -> bool {
//! (self.num - other.num).abs() < 5
//! }
//! }
//!
//! // Now these binary operators will work when applied!
-//! assert!(SketchyNum {num: 37} == SketchyNum {num: 34});
-//! assert!(SketchyNum {num: 25} != SketchyNum {num: 57});
+//! assert!(FuzzyNum { num: 37 } == FuzzyNum { num: 34 });
+//! assert!(FuzzyNum { num: 25 } != FuzzyNum { num: 57 });
//! ```
#![stable(feature = "rust1", since = "1.0.0")]
/// Trait for equality comparisons which are [partial equivalence relations](
/// http://en.wikipedia.org/wiki/Partial_equivalence_relation).
///
-/// This trait allows for partial equality, for types that do not have a full
-/// equivalence relation. For example, in floating point numbers `NaN != NaN`,
-/// so floating point types implement `PartialEq` but not `Eq`.
+/// This trait allows for partial equality, for types that do not have a full equivalence relation.
+/// For example, in floating point numbers `NaN != NaN`, so floating point types implement
+/// `PartialEq` but not `Eq`.
///
/// Formally, the equality must be (for all `a`, `b` and `c`):
///
/// - symmetric: `a == b` implies `b == a`; and
/// - transitive: `a == b` and `b == c` implies `a == c`.
///
-/// Note that these requirements mean that the trait itself must be
-/// implemented symmetrically and transitively: if `T: PartialEq<U>`
-/// and `U: PartialEq<V>` then `U: PartialEq<T>` and `T:
+/// Note that these requirements mean that the trait itself must be implemented symmetrically and
+/// transitively: if `T: PartialEq<U>` and `U: PartialEq<V>` then `U: PartialEq<T>` and `T:
/// PartialEq<V>`.
///
-/// PartialEq only requires the `eq` method to be implemented; `ne` is defined
-/// in terms of it by default. Any manual implementation of `ne` *must* respect
-/// the rule that `eq` is a strict inverse of `ne`; that is, `!(a == b)` if and
-/// only if `a != b`.
+/// PartialEq only requires the `eq` method to be implemented; `ne` is defined in terms of it by
+/// default. Any manual implementation of `ne` *must* respect the rule that `eq` is a strict
+/// inverse of `ne`; that is, `!(a == b)` if and only if `a != b`.
#[lang="eq"]
#[stable(feature = "rust1", since = "1.0.0")]
#[old_orphan_check]
/// Trait for equality comparisons which are [equivalence relations](
/// https://en.wikipedia.org/wiki/Equivalence_relation).
///
-/// This means, that in addition to `a == b` and `a != b` being strict
-/// inverses, the equality must be (for all `a`, `b` and `c`):
+/// This means, that in addition to `a == b` and `a != b` being strict inverses, the equality must
+/// be (for all `a`, `b` and `c`):
///
/// - reflexive: `a == a`;
/// - symmetric: `a == b` implies `b == a`; and
/// - transitive: `a == b` and `b == c` implies `a == c`.
+///
+/// This property cannot be checked by the compiler, and therefore `Eq` implies
+/// `PartialEq`, and has no extra methods.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Eq: PartialEq<Self> {
// FIXME #13101: this method is used solely by #[deriving] to
// This should never be implemented by hand.
#[doc(hidden)]
#[inline(always)]
+ #[stable(feature = "rust1", since = "1.0.0")]
fn assert_receiver_is_total_eq(&self) {}
}
-/// An ordering is, e.g, a result of a comparison between two values.
+/// An `Ordering` is the result of a comparison between two values.
+///
+/// # Examples
+///
+/// ```
+/// use std::cmp::Ordering;
+///
+/// let result = 1.cmp(&2);
+/// assert_eq!(Ordering::Less, result);
+///
+/// let result = 1.cmp(&1);
+/// assert_eq!(Ordering::Equal, result);
+///
+/// let result = 2.cmp(&1);
+/// assert_eq!(Ordering::Greater, result);
+/// ```
#[derive(Clone, Copy, PartialEq, Debug)]
#[stable(feature = "rust1", since = "1.0.0")]
pub enum Ordering {
}
impl Ordering {
- /// Reverse the `Ordering`, so that `Less` becomes `Greater` and
- /// vice versa.
+ /// Reverse the `Ordering`.
///
- /// # Example
+ /// * `Less` becomes `Greater`.
+ /// * `Greater` becomes `Less`.
+ /// * `Equal` becomes `Equal`.
///
- /// ```rust
- /// use std::cmp::Ordering::{Less, Equal, Greater};
+ /// # Examples
///
- /// assert_eq!(Less.reverse(), Greater);
- /// assert_eq!(Equal.reverse(), Equal);
- /// assert_eq!(Greater.reverse(), Less);
+ /// Basic behavior:
+ ///
+ /// ```
+ /// use std::cmp::Ordering;
+ ///
+ /// assert_eq!(Ordering::Less.reverse(), Ordering::Greater);
+ /// assert_eq!(Ordering::Equal.reverse(), Ordering::Equal);
+ /// assert_eq!(Ordering::Greater.reverse(), Ordering::Less);
+ /// ```
+ ///
+ /// This method can be used to reverse a comparison:
+ ///
+ /// ```
+ /// use std::cmp::Ordering;
///
/// let mut data: &mut [_] = &mut [2, 10, 5, 8];
///
}
}
-/// Trait for types that form a [total order](
-/// https://en.wikipedia.org/wiki/Total_order).
+/// Trait for types that form a [total order](https://en.wikipedia.org/wiki/Total_order).
///
/// An order is a total order if it is (for all `a`, `b` and `c`):
///
-/// - total and antisymmetric: exactly one of `a < b`, `a == b` or `a > b` is
-/// true; and
-/// - transitive, `a < b` and `b < c` implies `a < c`. The same must hold for
-/// both `==` and `>`.
+/// - total and antisymmetric: exactly one of `a < b`, `a == b` or `a > b` is true; and
+/// - transitive, `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Ord: Eq + PartialOrd<Self> {
- /// This method returns an ordering between `self` and `other` values.
+ /// This method returns an `Ordering` between `self` and `other`.
///
- /// By convention, `self.cmp(&other)` returns the ordering matching
- /// the expression `self <operator> other` if true. For example:
+ /// By convention, `self.cmp(&other)` returns the ordering matching the expression
+ /// `self <operator> other` if true.
+ ///
+ /// # Examples
///
/// ```
- /// use std::cmp::Ordering::{Less, Equal, Greater};
+ /// use std::cmp::Ordering;
///
- /// assert_eq!( 5.cmp(&10), Less); // because 5 < 10
- /// assert_eq!(10.cmp(&5), Greater); // because 10 > 5
- /// assert_eq!( 5.cmp(&5), Equal); // because 5 == 5
+ /// assert_eq!(5.cmp(&10), Ordering::Less);
+ /// assert_eq!(10.cmp(&5), Ordering::Greater);
+ /// assert_eq!(5.cmp(&5), Ordering::Equal);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn cmp(&self, other: &Self) -> Ordering;
/// The comparison must satisfy, for all `a`, `b` and `c`:
///
/// - antisymmetry: if `a < b` then `!(a > b)` and vice versa; and
-/// - transitivity: `a < b` and `b < c` implies `a < c`. The same must hold for
-/// both `==` and `>`.
+/// - transitivity: `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`.
///
-/// Note that these requirements mean that the trait itself must be
-/// implemented symmetrically and transitively: if `T: PartialOrd<U>`
-/// and `U: PartialOrd<V>` then `U: PartialOrd<T>` and `T:
+/// Note that these requirements mean that the trait itself must be implemented symmetrically and
+/// transitively: if `T: PartialOrd<U>` and `U: PartialOrd<V>` then `U: PartialOrd<T>` and `T:
/// PartialOrd<V>`.
///
-/// PartialOrd only requires implementation of the `partial_cmp` method,
-/// with the others generated from default implementations.
+/// PartialOrd only requires implementation of the `partial_cmp` method, with the others generated
+/// from default implementations.
///
-/// However it remains possible to implement the others separately for types
-/// which do not have a total order. For example, for floating point numbers,
-/// `NaN < 0 == false` and `NaN >= 0 == false` (cf. IEEE 754-2008 section
-/// 5.11).
+/// However it remains possible to implement the others separately for types which do not have a
+/// total order. For example, for floating point numbers, `NaN < 0 == false` and `NaN >= 0 ==
+/// false` (cf. IEEE 754-2008 section 5.11).
#[lang="ord"]
#[stable(feature = "rust1", since = "1.0.0")]
pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
- /// This method returns an ordering between `self` and `other` values
- /// if one exists.
+ /// This method returns an ordering between `self` and `other` values if one exists.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::cmp::Ordering;
+ ///
+ /// let result = 1.0.partial_cmp(&2.0);
+ /// assert_eq!(result, Some(Ordering::Less));
+ ///
+ /// let result = 1.0.partial_cmp(&1.0);
+ /// assert_eq!(result, Some(Ordering::Equal));
+ ///
+ /// let result = 2.0.partial_cmp(&1.0);
+ /// assert_eq!(result, Some(Ordering::Greater));
+ /// ```
+ ///
+ /// When comparison is impossible:
+ ///
+ /// ```
+ /// let result = std::f64::NAN.partial_cmp(&1.0);
+ /// assert_eq!(result, None);
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>;
/// This method tests less than (for `self` and `other`) and is used by the `<` operator.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::cmp::Ordering;
+ ///
+ /// let result = 1.0 < 2.0;
+ /// assert_eq!(result, true);
+ ///
+ /// let result = 2.0 < 1.0;
+ /// assert_eq!(result, false);
+ /// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
fn lt(&self, other: &Rhs) -> bool {
}
}
- /// This method tests less than or equal to (`<=`).
+ /// This method tests less than or equal to (for `self` and `other`) and is used by the `<=`
+ /// operator.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let result = 1.0 <= 2.0;
+ /// assert_eq!(result, true);
+ ///
+ /// let result = 2.0 <= 2.0;
+ /// assert_eq!(result, true);
+ /// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
fn le(&self, other: &Rhs) -> bool {
}
}
- /// This method tests greater than (`>`).
+ /// This method tests greater than (for `self` and `other`) and is used by the `>` operator.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let result = 1.0 > 2.0;
+ /// assert_eq!(result, false);
+ ///
+ /// let result = 2.0 > 2.0;
+ /// assert_eq!(result, false);
+ /// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
fn gt(&self, other: &Rhs) -> bool {
}
}
- /// This method tests greater than or equal to (`>=`).
+ /// This method tests greater than or equal to (for `self` and `other`) and is used by the `>=`
+ /// operator.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let result = 2.0 >= 1.0;
+ /// assert_eq!(result, true);
+ ///
+ /// let result = 2.0 >= 2.0;
+ /// assert_eq!(result, true);
+ /// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
fn ge(&self, other: &Rhs) -> bool {
}
/// Compare and return the minimum of two values.
+///
+/// # Examples
+///
+/// ```
+/// use std::cmp;
+///
+/// assert_eq!(1, cmp::min(1, 2));
+/// assert_eq!(2, cmp::min(2, 2));
+/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn min<T: Ord>(v1: T, v2: T) -> T {
}
/// Compare and return the maximum of two values.
+///
+/// # Examples
+///
+/// ```
+/// use std::cmp;
+///
+/// assert_eq!(2, cmp::max(1, 2));
+/// assert_eq!(2, cmp::max(2, 2));
+/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn max<T: Ord>(v1: T, v2: T) -> T {
/// Compare and return the minimum of two values if there is one.
///
/// Returns the first argument if the comparison determines them to be equal.
+///
+/// # Examples
+///
+/// ```
+/// use std::cmp;
+///
+/// assert_eq!(Some(1), cmp::partial_min(1, 2));
+/// assert_eq!(Some(2), cmp::partial_min(2, 2));
+/// ```
+///
+/// When comparison is impossible:
+///
+/// ```
+/// use std::cmp;
+///
+/// let result = cmp::partial_min(std::f64::NAN, 1.0);
+/// assert_eq!(result, None);
+/// ```
#[inline]
#[unstable(feature = "core")]
pub fn partial_min<T: PartialOrd>(v1: T, v2: T) -> Option<T> {
/// Compare and return the maximum of two values if there is one.
///
/// Returns the first argument if the comparison determines them to be equal.
+///
+/// # Examples
+///
+/// ```
+/// use std::cmp;
+///
+/// assert_eq!(Some(2), cmp::partial_max(1, 2));
+/// assert_eq!(Some(2), cmp::partial_max(2, 2));
+/// ```
+///
+/// When comparison is impossible:
+///
+/// ```
+/// use std::cmp;
+///
+/// let result = cmp::partial_max(std::f64::NAN, 1.0);
+/// assert_eq!(result, None);
+/// ```
#[inline]
#[unstable(feature = "core")]
pub fn partial_max<T: PartialOrd>(v1: T, v2: T) -> Option<T> {
end: &'a mut uint,
}
- impl<'a> fmt::Writer for Filler<'a> {
+ impl<'a> fmt::Write for Filler<'a> {
fn write_str(&mut self, s: &str) -> fmt::Result {
slice::bytes::copy_memory(&mut self.buf[(*self.end)..],
s.as_bytes());
/// A collection of methods that are required to format a message into a stream.
///
/// This trait is the type which this modules requires when formatting
-/// information. This is similar to the standard library's `io::Writer` trait,
+/// information. This is similar to the standard library's `io::Write` trait,
/// but it is only intended for use in libcore.
///
/// This trait should generally not be implemented by consumers of the standard
-/// library. The `write!` macro accepts an instance of `io::Writer`, and the
-/// `io::Writer` trait is favored over implementing this trait.
+/// library. The `write!` macro accepts an instance of `io::Write`, and the
+/// `io::Write` trait is favored over implementing this trait.
#[stable(feature = "rust1", since = "1.0.0")]
-pub trait Writer {
+pub trait Write {
/// Writes a slice of bytes into this writer, returning whether the write
/// succeeded.
///
#[stable(feature = "rust1", since = "1.0.0")]
fn write_fmt(&mut self, args: Arguments) -> Result {
// This Adapter is needed to allow `self` (of type `&mut
- // Self`) to be cast to a FormatWriter (below) without
+ // Self`) to be cast to a Write (below) without
// requiring a `Sized` bound.
struct Adapter<'a,T: ?Sized +'a>(&'a mut T);
- impl<'a, T: ?Sized> Writer for Adapter<'a, T>
- where T: Writer
+ impl<'a, T: ?Sized> Write for Adapter<'a, T>
+ where T: Write
{
fn write_str(&mut self, s: &str) -> Result {
self.0.write_str(s)
width: Option<uint>,
precision: Option<uint>,
- buf: &'a mut (Writer+'a),
+ buf: &'a mut (Write+'a),
curarg: slice::Iter<'a, ArgumentV1<'a>>,
args: &'a [ArgumentV1<'a>],
}
/// created with `argumentuint`. However, failing to do so doesn't cause
/// unsafety, but will ignore invalid .
#[doc(hidden)] #[inline]
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn new_v1_formatted(pieces: &'a [&'a str],
args: &'a [ArgumentV1<'a>],
fmt: &'a [rt::v1::Argument]) -> Arguments<'a> {
/// * output - the buffer to write output to
/// * args - the precompiled arguments generated by `format_args!`
#[stable(feature = "rust1", since = "1.0.0")]
-pub fn write(output: &mut Writer, args: Arguments) -> Result {
+pub fn write(output: &mut Write, args: Arguments) -> Result {
let mut formatter = Formatter {
flags: 0,
width: None,
fn from_iter<T: Iterator<Item=A>>(iterator: T) -> Self;
}
-// NOTE(stage0): remove trait after a snapshot
-#[cfg(stage0)]
/// Conversion into an `Iterator`
+#[stable(feature = "rust1", since = "1.0.0")]
pub trait IntoIterator {
- type IntoIter: Iterator;
-
- /// Consumes `Self` and returns an iterator over it
#[stable(feature = "rust1", since = "1.0.0")]
- fn into_iter(self) -> Self::IntoIter;
-}
-
-#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
-/// Conversion into an `Iterator`
-pub trait IntoIterator {
type Item;
+
+ #[stable(feature = "rust1", since = "1.0.0")]
type IntoIter: Iterator<Item=Self::Item>;
/// Consumes `Self` and returns an iterator over it
fn into_iter(self) -> Self::IntoIter;
}
-// NOTE(stage0): remove impl after a snapshot
-#[cfg(stage0)]
-impl<I> IntoIterator for I where I: Iterator {
- type IntoIter = I;
-
- fn into_iter(self) -> I {
- self
- }
-}
-
-#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
+#[stable(feature = "rust1", since = "1.0.0")]
impl<I: Iterator> IntoIterator for I {
type Item = I::Item;
type IntoIter = I;
///
/// ```
/// let xs = [100, 200, 300];
- /// let mut it = xs.iter().map(|x| *x).peekable();
+ /// let mut it = xs.iter().cloned().peekable();
/// assert_eq!(*it.peek().unwrap(), 100);
/// assert_eq!(it.next().unwrap(), 100);
/// assert_eq!(it.next().unwrap(), 200);
///
/// let a = [1, 4, 2, 3, 8, 9, 6];
/// let sum = a.iter()
- /// .map(|&x| x)
+ /// .cloned()
/// .inspect(|&x| println!("filtering {}", x))
/// .filter(|&x| x % 2 == 0)
/// .inspect(|&x| println!("{} made it through", x))
///
/// ```
/// let a = [1, 2, 3, 4, 5];
- /// let b: Vec<_> = a.iter().map(|&x| x).collect();
+ /// let b: Vec<_> = a.iter().cloned().collect();
/// assert_eq!(a, b);
/// ```
#[inline]
///
/// ```
/// let a = [(1, 2), (3, 4)];
- /// let (left, right): (Vec<_>, Vec<_>) = a.iter().map(|&x| x).unzip();
+ /// let (left, right): (Vec<_>, Vec<_>) = a.iter().cloned().unzip();
/// assert_eq!([1, 3], left);
/// assert_eq!([2, 4], right);
/// ```
/// use std::iter::AdditiveIterator;
///
/// let a = [1i32, 2, 3, 4, 5];
- /// let mut it = a.iter().map(|&x| x);
+ /// let mut it = a.iter().cloned();
/// assert!(it.sum() == 15);
/// ```
fn sum(self) -> A;
I: ExactSizeIterator<Item=D>,
{}
+#[unstable(feature = "core", reason = "trait is experimental")]
+impl<T, D, I> RandomAccessIterator for Cloned<I> where
+ T: Clone,
+ D: Deref<Target=T>,
+ I: RandomAccessIterator<Item=D>
+{
+ #[inline]
+ fn indexable(&self) -> usize {
+ self.it.indexable()
+ }
+
+ #[inline]
+ fn idx(&mut self, index: usize) -> Option<T> {
+ self.it.idx(index).cloned()
+ }
+}
+
/// An iterator that repeats endlessly
#[derive(Clone)]
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
/// iteration
#[derive(Clone)]
#[unstable(feature = "core",
- reason = "may be renamed or replaced by range notation adapaters")]
+ reason = "may be renamed or replaced by range notation adapters")]
pub struct Counter<A> {
/// The current state the counter is at (next value to be yielded)
state: A,
/// Creates a new counter with the specified start/step
#[inline]
#[unstable(feature = "core",
- reason = "may be renamed or replaced by range notation adapaters")]
+ reason = "may be renamed or replaced by range notation adapters")]
pub fn count<A>(start: A, step: A) -> Counter<A> {
Counter{state: start, step: step}
}
#![feature(simd, unsafe_destructor)]
#![feature(staged_api)]
#![feature(unboxed_closures)]
+#![feature(rustc_attrs)]
#[macro_use]
mod macros;
mod core {
pub use panicking;
pub use fmt;
- #[cfg(not(stage0))] pub use clone;
- #[cfg(not(stage0))] pub use cmp;
- #[cfg(not(stage0))] pub use hash;
- #[cfg(not(stage0))] pub use marker;
- #[cfg(not(stage0))] pub use option;
- #[cfg(not(stage0))] pub use iter;
+ pub use clone;
+ pub use cmp;
+ pub use hash;
+ pub use marker;
+ pub use option;
+ pub use iter;
}
#[doc(hidden)]
mod std {
- // NOTE: remove after next snapshot
- #[cfg(stage0)] pub use clone;
- #[cfg(stage0)] pub use cmp;
- #[cfg(stage0)] pub use hash;
- #[cfg(stage0)] pub use marker;
- #[cfg(stage0)] pub use option;
- #[cfg(stage0)] pub use fmt;
- #[cfg(stage0)] pub use iter;
-
// range syntax
pub use ops;
}
reason = "will be overhauled with new lifetime rules; see RFC 458")]
#[lang="send"]
#[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"]
+#[cfg(stage0)]
pub unsafe trait Send: 'static {
// empty.
}
+/// Types able to be transferred across thread boundaries.
+#[unstable(feature = "core",
+ reason = "will be overhauled with new lifetime rules; see RFC 458")]
+#[lang="send"]
+#[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"]
+#[cfg(not(stage0))]
+pub unsafe trait Send {
+ // empty.
+}
/// Types with a constant size known at compile-time.
#[stable(feature = "rust1", since = "1.0.0")]
#[lang="managed_bound"]
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct Managed;
+
+#[cfg(not(stage0))]
+mod impls {
+ use super::{Send, Sync, Sized};
+
+ unsafe impl<'a, T: Sync + ?Sized> Send for &'a T {}
+ unsafe impl<'a, T: Send + ?Sized> Send for &'a mut T {}
+}
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
-pub fn size_of<T>() -> uint {
+pub fn size_of<T>() -> usize {
unsafe { intrinsics::size_of::<T>() }
}
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
-pub fn size_of_val<T>(_val: &T) -> uint {
+pub fn size_of_val<T>(_val: &T) -> usize {
size_of::<T>()
}
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
-pub fn min_align_of<T>() -> uint {
+pub fn min_align_of<T>() -> usize {
unsafe { intrinsics::min_align_of::<T>() }
}
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
-pub fn min_align_of_val<T>(_val: &T) -> uint {
+pub fn min_align_of_val<T>(_val: &T) -> usize {
min_align_of::<T>()
}
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
-pub fn align_of<T>() -> uint {
+pub fn align_of<T>() -> usize {
// We use the preferred alignment as the default alignment for a type. This
// appears to be what clang migrated towards as well:
//
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
-pub fn align_of_val<T>(_val: &T) -> uint {
+pub fn align_of_val<T>(_val: &T) -> usize {
align_of::<T>()
}
/// ```
/// use std::mem;
///
-/// let x: int = unsafe { mem::zeroed() };
+/// let x: i32 = unsafe { mem::zeroed() };
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
/// ```
/// use std::mem;
///
-/// let x: int = unsafe { mem::uninitialized() };
+/// let x: i32 = unsafe { mem::uninitialized() };
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
unsafe impl<T> Zeroable for *const T {}
unsafe impl<T> Zeroable for *mut T {}
unsafe impl<T> Zeroable for Unique<T> { }
-unsafe impl Zeroable for int {}
-unsafe impl Zeroable for uint {}
+unsafe impl Zeroable for isize {}
+unsafe impl Zeroable for usize {}
unsafe impl Zeroable for i8 {}
unsafe impl Zeroable for u8 {}
unsafe impl Zeroable for i16 {}
/// Returns `None` if the option is `None`, otherwise calls `f` with the
/// wrapped value and returns the result.
///
+ /// Some languages call this operation flatmap.
+ ///
/// # Example
///
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
- fn is_null(self) -> bool { self as usize == 0 }
+ fn is_null(self) -> bool { self == 0 as *const T }
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
- fn is_null(self) -> bool { self as usize == 0 }
+ fn is_null(self) -> bool { self == 0 as *mut T }
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
// Iterators
//
-// NOTE(stage0): remove impl after a snapshot
-#[cfg(stage0)]
-impl<'a, T> IntoIterator for &'a [T] {
- type IntoIter = Iter<'a, T>;
-
- fn into_iter(self) -> Iter<'a, T> {
- self.iter()
- }
-}
-
-#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
+#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> IntoIterator for &'a [T] {
type Item = &'a T;
type IntoIter = Iter<'a, T>;
}
}
-// NOTE(stage0): remove impl after a snapshot
-#[cfg(stage0)]
-impl<'a, T> IntoIterator for &'a mut [T] {
- type IntoIter = IterMut<'a, T>;
-
- fn into_iter(self) -> IterMut<'a, T> {
- self.iter_mut()
- }
-}
-
-#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
+#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> IntoIterator for &'a mut [T] {
type Item = &'a mut T;
type IntoIter = IterMut<'a, T>;
#![allow(deprecated)]
use core::finally::{try_finally, Finally};
-use std::thread::Thread;
+use std::thread;
#[test]
fn test_success() {
*i = 10;
},
|i| {
- assert!(!Thread::panicking());
+ assert!(!thread::panicking());
assert_eq!(*i, 10);
*i = 20;
});
panic!();
},
|i| {
- assert!(Thread::panicking());
+ assert!(thread::panicking());
assert_eq!(*i, 10);
})
}
assert_eq!(i, expected.len());
let ys = count(30, 10).take(4);
- let mut it = xs.iter().map(|&x| x).chain(ys);
+ let mut it = xs.iter().cloned().chain(ys);
let mut i = 0;
for x in it {
assert_eq!(x, expected[i]);
#[test]
fn test_iterator_peekable() {
let xs = vec![0, 1, 2, 3, 4, 5];
- let mut it = xs.iter().map(|&x|x).peekable();
+ let mut it = xs.iter().cloned().peekable();
assert_eq!(it.len(), 6);
assert_eq!(it.peek().unwrap(), &0);
let mut n = 0;
let ys = xs.iter()
- .map(|&x| x)
+ .cloned()
.inspect(|_| n += 1)
.collect::<Vec<uint>>();
#[test]
fn test_iterator_sum() {
let v: &[i32] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
- assert_eq!(v[..4].iter().map(|&x| x).sum(), 6);
- assert_eq!(v.iter().map(|&x| x).sum(), 55);
- assert_eq!(v[..0].iter().map(|&x| x).sum(), 0);
+ assert_eq!(v[..4].iter().cloned().sum(), 6);
+ assert_eq!(v.iter().cloned().sum(), 55);
+ assert_eq!(v[..0].iter().cloned().sum(), 0);
}
#[test]
fn test_iterator_product() {
let v: &[i32] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
- assert_eq!(v[..4].iter().map(|&x| x).product(), 0);
- assert_eq!(v[1..5].iter().map(|&x| x).product(), 24);
- assert_eq!(v[..0].iter().map(|&x| x).product(), 1);
+ assert_eq!(v[..4].iter().cloned().product(), 0);
+ assert_eq!(v[1..5].iter().cloned().product(), 24);
+ assert_eq!(v[..0].iter().cloned().product(), 1);
}
#[test]
fn test_iterator_max() {
let v: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
- assert_eq!(v[..4].iter().map(|&x| x).max(), Some(3));
- assert_eq!(v.iter().map(|&x| x).max(), Some(10));
- assert_eq!(v[..0].iter().map(|&x| x).max(), None);
+ assert_eq!(v[..4].iter().cloned().max(), Some(3));
+ assert_eq!(v.iter().cloned().max(), Some(10));
+ assert_eq!(v[..0].iter().cloned().max(), None);
}
#[test]
fn test_iterator_min() {
let v: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
- assert_eq!(v[..4].iter().map(|&x| x).min(), Some(0));
- assert_eq!(v.iter().map(|&x| x).min(), Some(0));
- assert_eq!(v[..0].iter().map(|&x| x).min(), None);
+ assert_eq!(v[..4].iter().cloned().min(), Some(0));
+ assert_eq!(v.iter().cloned().min(), Some(0));
+ assert_eq!(v[..0].iter().cloned().min(), None);
}
#[test]
assert_eq!(c.clone().take_while(|_| false).size_hint(), (0, None));
assert_eq!(c.clone().skip_while(|_| false).size_hint(), (0, None));
assert_eq!(c.clone().enumerate().size_hint(), (uint::MAX, None));
- assert_eq!(c.clone().chain(vi.clone().map(|&i| i)).size_hint(), (uint::MAX, None));
+ assert_eq!(c.clone().chain(vi.clone().cloned()).size_hint(), (uint::MAX, None));
assert_eq!(c.clone().zip(vi.clone()).size_hint(), (10, Some(10)));
assert_eq!(c.clone().scan(0, |_,_| Some(0)).size_hint(), (0, None));
assert_eq!(c.clone().filter(|_| false).size_hint(), (0, None));
#[test]
fn test_collect() {
let a = vec![1, 2, 3, 4, 5];
- let b: Vec<int> = a.iter().map(|&x| x).collect();
+ let b: Vec<int> = a.iter().cloned().collect();
assert!(a == b);
}
let mut it = xs.iter();
it.next();
it.next();
- assert!(it.rev().map(|&x| x).collect::<Vec<int>>() ==
+ assert!(it.rev().cloned().collect::<Vec<int>>() ==
vec![16, 14, 12, 10, 8, 6]);
}
#[test]
fn test_double_ended_enumerate() {
let xs = [1, 2, 3, 4, 5, 6];
- let mut it = xs.iter().map(|&x| x).enumerate();
+ let mut it = xs.iter().cloned().enumerate();
assert_eq!(it.next(), Some((0, 1)));
assert_eq!(it.next(), Some((1, 2)));
assert_eq!(it.next_back(), Some((5, 6)));
fn test_double_ended_zip() {
let xs = [1, 2, 3, 4, 5, 6];
let ys = [1, 2, 3, 7];
- let a = xs.iter().map(|&x| x);
- let b = ys.iter().map(|&x| x);
+ let a = xs.iter().cloned();
+ let b = ys.iter().cloned();
let mut it = a.zip(b);
assert_eq!(it.next(), Some((1, 1)));
assert_eq!(it.next(), Some((2, 2)));
fn test_random_access_map() {
let xs = [1, 2, 3, 4, 5];
- let mut it = xs.iter().map(|x| *x);
+ let mut it = xs.iter().cloned();
assert_eq!(xs.len(), it.indexable());
for (i, elt) in xs.iter().enumerate() {
assert_eq!(Some(*elt), it.idx(i));
#![feature(collections)]
#![feature(int_uint)]
#![feature(staged_api)]
+#![feature(str_words)]
#![cfg_attr(test, feature(rustc_private))]
#[cfg(test)] #[macro_use] extern crate log;
#![feature(int_uint)]
#![feature(collections)]
#![feature(core)]
-#![feature(io)]
+#![feature(old_io)]
use self::LabelText::*;
use types::os::arch::c95::{c_uchar, c_int, size_t};
extern {
+ #[cfg(not(all(target_os = "android", target_arch = "aarch64")))]
pub fn getdtablesize() -> c_int;
pub fn ioctl(d: c_int, request: c_int, ...) -> c_int;
pub fn madvise(addr: *mut c_void, len: size_t, advice: c_int)
pub fn issue_14344_workaround() {} // FIXME #14344 force linkage to happen correctly
#[test] fn work_on_windows() { } // FIXME #10872 needed for a happy windows
-
-// NOTE: remove after next snapshot
-#[doc(hidden)]
-#[cfg(all(stage0, not(test)))]
-mod std {
- pub use core::marker;
-}
#![feature(box_syntax)]
#![feature(int_uint)]
#![feature(core)]
-#![feature(io)]
+#![feature(old_io)]
#![feature(std_misc)]
#![feature(env)]
fn reseed(&mut self, seed: &'a [u32]) {
// make the seed into [seed[0], seed[1], ..., seed[seed.len()
// - 1], 0, 0, ...], to fill rng.rsl.
- let seed_iter = seed.iter().map(|&x| x).chain(repeat(0u32));
+ let seed_iter = seed.iter().cloned().chain(repeat(0u32));
for (rsl_elem, seed_elem) in self.rsl.iter_mut().zip(seed_iter) {
*rsl_elem = seed_elem;
fn reseed(&mut self, seed: &'a [u64]) {
// make the seed into [seed[0], seed[1], ..., seed[seed.len()
// - 1], 0, 0, ...], to fill rng.rsl.
- let seed_iter = seed.iter().map(|&x| x).chain(repeat(0u64));
+ let seed_iter = seed.iter().cloned().chain(repeat(0u64));
for (rsl_elem, seed_elem) in self.rsl.iter_mut().zip(seed_iter) {
*rsl_elem = seed_elem;
/// ```
pub struct Closed01<F>(pub F);
-// NOTE: remove after next snapshot
-#[cfg(all(stage0, not(test)))]
-mod std {
- pub use core::{option, fmt}; // panic!()
- pub use core::clone; // derive Clone
- pub use core::marker;
- // for-loops
- pub use core::iter;
- pub use core::ops; // slicing syntax
-}
-
#[cfg(test)]
mod test {
use std::rand;
#![feature(collections)]
#![feature(core)]
#![feature(int_uint)]
-#![feature(io)]
+#![feature(old_io)]
#![feature(rustc_private)]
#![feature(staged_api)]
If you wish to expand on this document, or have a more experienced
Rust contributor add anything else to it, please get in touch:
-https://github.com/rust-lang/rust/wiki/Note-development-policy
-("Communication" subheading)
+* http://internals.rust-lang.org/
+* https://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust
or file a bug:
#![feature(core)]
#![feature(hash)]
#![feature(int_uint)]
-#![feature(io)]
+#![feature(old_io)]
#![feature(libc)]
#![feature(env)]
-#![feature(path)]
+#![feature(old_path)]
#![feature(quote)]
#![feature(rustc_diagnostic_macros)]
#![feature(rustc_private)]
use syntax::ast_util::is_shift_binop;
use syntax::attr::{self, AttrMetaMethods};
use syntax::codemap::{self, Span};
+use syntax::feature_gate::{KNOWN_ATTRIBUTES, AttributeType};
use syntax::parse::token;
use syntax::ast::{TyIs, TyUs, TyI8, TyU8, TyI16, TyU16, TyI32, TyU32, TyI64, TyU64};
use syntax::ast_util;
}
fn check_attribute(&mut self, cx: &Context, attr: &ast::Attribute) {
- static ATTRIBUTE_WHITELIST: &'static [&'static str] = &[
- // FIXME: #14408 whitelist docs since rustdoc looks at them
- "doc",
-
- // FIXME: #14406 these are processed in trans, which happens after the
- // lint pass
- "cold",
- "export_name",
- "inline",
- "link",
- "link_name",
- "link_section",
- "linkage",
- "no_builtins",
- "no_mangle",
- "no_split_stack",
- "no_stack_check",
- "packed",
- "static_assert",
- "thread_local",
- "no_debug",
- "omit_gdb_pretty_printer_section",
- "unsafe_no_drop_flag",
-
- // used in resolve
- "prelude_import",
-
- // FIXME: #14407 these are only looked at on-demand so we can't
- // guarantee they'll have already been checked
- "deprecated",
- "must_use",
- "stable",
- "unstable",
- "rustc_on_unimplemented",
- "rustc_error",
-
- // FIXME: #19470 this shouldn't be needed forever
- "old_orphan_check",
- "old_impl_check",
- "rustc_paren_sugar", // FIXME: #18101 temporary unboxed closure hack
- ];
-
- static CRATE_ATTRS: &'static [&'static str] = &[
- "crate_name",
- "crate_type",
- "feature",
- "no_start",
- "no_main",
- "no_std",
- "no_builtins",
- ];
-
- for &name in ATTRIBUTE_WHITELIST {
- if attr.check_name(name) {
- break;
+ for &(ref name, ty) in KNOWN_ATTRIBUTES {
+ match ty {
+ AttributeType::Whitelisted
+ | AttributeType::Gated(_, _) if attr.check_name(name) => {
+ break;
+ },
+ _ => ()
}
}
if !attr::is_used(attr) {
cx.span_lint(UNUSED_ATTRIBUTES, attr.span, "unused attribute");
- if CRATE_ATTRS.contains(&&attr.name()[]) {
+ if KNOWN_ATTRIBUTES.contains(&(&attr.name()[], AttributeType::CrateLevel)) {
let msg = match attr.node.style {
ast::AttrOuter => "crate-level attribute should be an inner \
attribute: add an exclamation mark: #![foo]",
}
fn check_item(&mut self, cx: &Context, item: &ast::Item) {
- stability::check_item(cx.tcx, item,
+ stability::check_item(cx.tcx, item, false,
&mut |id, sp, stab| self.lint(cx, id, sp, stab));
}
pub fn get_used_crate_source(&self, cnum: ast::CrateNum)
-> Option<CrateSource> {
self.used_crate_sources.borrow_mut()
- .iter().find(|source| source.cnum == cnum)
- .map(|source| source.clone())
+ .iter().find(|source| source.cnum == cnum).cloned()
}
pub fn reset(&self) {
pub fn find_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId)
-> Option<ast::CrateNum> {
- self.extern_mod_crate_map.borrow().get(&emod_id).map(|x| *x)
+ self.extern_mod_crate_map.borrow().get(&emod_id).cloned()
}
}
pretty_printed_matrix.iter().map(|row| row[col].len()).max().unwrap_or(0)
}).collect();
- let total_width = column_widths.iter().map(|n| *n).sum() + column_count * 3 + 1;
+ let total_width = column_widths.iter().cloned().sum() + column_count * 3 + 1;
let br = repeat('+').take(total_width).collect::<String>();
try!(write!(f, "{}\n", br));
for row in pretty_printed_matrix {
match lit.node {
ast::LitStr(ref s, _) => const_str((*s).clone()),
ast::LitBinary(ref data) => {
- const_binary(Rc::new(data.iter().map(|x| *x).collect()))
+ const_binary(data.clone())
}
ast::LitByte(n) => const_uint(n as u64),
ast::LitChar(n) => const_uint(n as u64),
}
fn to_cfgidx_or_die(id: ast::NodeId, index: &NodeMap<CFGIndex>) -> CFGIndex {
- let opt_cfgindex = index.get(&id).map(|&i|i);
+ let opt_cfgindex = index.get(&id).cloned();
opt_cfgindex.unwrap_or_else(|| {
panic!("nodeid_to_index does not have entry for NodeId {}", id);
})
let mut changed = false;
for &node_id in &edge.data.exiting_scopes {
- let opt_cfg_idx = self.nodeid_to_index.get(&node_id).map(|&i|i);
+ let opt_cfg_idx = self.nodeid_to_index.get(&node_id).cloned();
match opt_cfg_idx {
Some(cfg_idx) => {
let (start, end) = self.compute_id_range(cfg_idx);
// Collect what we've got so far in the return vector.
let mut ret = (1..sess.cstore.next_crate_num()).map(|i| {
- match formats.get(&i).map(|v| *v) {
+ match formats.get(&i).cloned() {
v @ Some(cstore::RequireDynamic) => v,
_ => None,
}
// the method call infrastructure should have
// replaced all late-bound regions with variables:
let self_ty = ty::ty_fn_sig(method_ty).input(0);
- let self_ty = ty::assert_no_late_bound_regions(self.tcx(), &self_ty);
+ let self_ty = ty::no_late_bound_regions(self.tcx(), &self_ty).unwrap();
let (m, r) = match self_ty.sty {
ty::ty_rptr(r, ref m) => (m.mutbl, r),
fn rebuild(&self)
-> (ast::FnDecl, Option<ast::ExplicitSelf_>, ast::Generics) {
- let mut expl_self_opt = self.expl_self_opt.map(|x| x.clone());
+ let mut expl_self_opt = self.expl_self_opt.cloned();
let mut inputs = self.fn_decl.inputs.clone();
let mut output = self.fn_decl.output.clone();
let mut ty_params = self.generics.ty_params.clone();
}
}
-impl<K> sv::SnapshotVecDelegate for Delegate<K> {
+impl<K:UnifyKey> sv::SnapshotVecDelegate for Delegate<K> {
type Value = VarValue<K>;
type Undo = ();
impl<'a, 'v> Visitor<'v> for LanguageItemCollector<'a> {
fn visit_item(&mut self, item: &ast::Item) {
- match extract(&item.attrs) {
- Some(value) => {
- let item_index = self.item_refs.get(&value[]).map(|x| *x);
-
- match item_index {
- Some(item_index) => {
- self.collect_item(item_index, local_def(item.id), item.span)
- }
- None => {}
- }
+ if let Some(value) = extract(&item.attrs) {
+ let item_index = self.item_refs.get(&value[]).cloned();
+
+ if let Some(item_index) = item_index {
+ self.collect_item(item_index, local_def(item.id), item.span)
}
- None => {}
}
visit::walk_item(self, item);
/// know that no errors have occurred, so we simply consult the tcx and we
/// can be sure that only `Ok` results will occur.
pub trait Typer<'tcx> : ty::ClosureTyper<'tcx> {
- fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx>;
fn node_ty(&self, id: ast::NodeId) -> McResult<Ty<'tcx>>;
fn expr_ty_adjusted(&self, expr: &ast::Expr) -> McResult<Ty<'tcx>>;
fn type_moves_by_default(&self, span: Span, ty: Ty<'tcx>) -> bool;
let base_cmt = match method_ty {
Some(method_ty) => {
let ref_ty =
- ty::assert_no_late_bound_regions(
- self.tcx(), &ty::ty_fn_ret(method_ty)).unwrap();
+ ty::no_late_bound_regions(
+ self.tcx(), &ty::ty_fn_ret(method_ty)).unwrap().unwrap();
self.cat_rvalue_node(node.id(), node.span(), ref_ty)
}
None => base_cmt
// FIXME(#20649) -- why are we using the `self_ty` as the element type...?
let self_ty = ty::ty_fn_sig(method_ty).input(0);
- ty::assert_no_late_bound_regions(self.tcx(), &self_ty)
+ ty::no_late_bound_regions(self.tcx(), &self_ty).unwrap()
}
None => {
match ty::array_element_ty(self.tcx(), base_cmt.ty) {
// types are generated by method resolution and always have
// all late-bound regions fully instantiated, so we just want
// to skip past the binder.
- ty::assert_no_late_bound_regions(self.tcx(), &ty::ty_fn_ret(method_ty))
- .unwrap() // overloaded ops do not diverge, either
+ ty::no_late_bound_regions(self.tcx(), &ty::ty_fn_ret(method_ty))
+ .unwrap()
+ .unwrap() // overloaded ops do not diverge, either
}
}
pub fn opt_encl_scope(&self, id: CodeExtent) -> Option<CodeExtent> {
//! Returns the narrowest scope that encloses `id`, if any.
- self.scope_map.borrow().get(&id).map(|x| *x)
+ self.scope_map.borrow().get(&id).cloned()
}
#[allow(dead_code)] // used in middle::cfg
generics.lifetimes.iter()
.filter(|l| referenced_idents.iter().any(|&i| i == l.lifetime.name))
- .map(|l| (*l).clone())
+ .cloned()
.collect()
}
if self.tcx.sess.features.borrow().unmarked_api {
self.tcx.sess.span_warn(span, "use of unmarked library feature");
self.tcx.sess.span_note(span, "this is either a bug in the library you are \
- using and a bug in the compiler - please \
+ using or a bug in the compiler - please \
report it in both places");
} else {
self.tcx.sess.span_err(span, "use of unmarked library feature");
self.tcx.sess.span_note(span, "this is either a bug in the library you are \
- using and a bug in the compiler - please \
+ using or a bug in the compiler - please \
report it in both places");
self.tcx.sess.span_note(span, "use #![feature(unmarked_api)] in the \
crate attributes to override this");
// name `__test`
if item.span == DUMMY_SP && item.ident.as_str() == "__test" { return }
- check_item(self.tcx, item,
+ check_item(self.tcx, item, true,
&mut |id, sp, stab| self.check(id, sp, stab));
visit::walk_item(self, item);
}
}
/// Helper for discovering nodes to check for stability
-pub fn check_item(tcx: &ty::ctxt, item: &ast::Item,
+pub fn check_item(tcx: &ty::ctxt, item: &ast::Item, warn_about_defns: bool,
cb: &mut FnMut(ast::DefId, Span, &Option<Stability>)) {
match item.node {
ast::ItemExternCrate(_) => {
let id = ast::DefId { krate: cnum, node: ast::CRATE_NODE_ID };
maybe_do_stability_check(tcx, id, item.span, cb);
}
+
+ // For implementations of traits, check the stability of each item
+ // individually as it's possible to have a stable trait with unstable
+ // items.
+ ast::ItemImpl(_, _, _, Some(ref t), _, ref impl_items) => {
+ let trait_did = tcx.def_map.borrow()[t.ref_id].def_id();
+ let trait_items = ty::trait_items(tcx, trait_did);
+
+ for impl_item in impl_items {
+ let (ident, span) = match *impl_item {
+ ast::MethodImplItem(ref method) => {
+ (match method.node {
+ ast::MethDecl(ident, _, _, _, _, _, _, _) => ident,
+ ast::MethMac(..) => unreachable!(),
+ }, method.span)
+ }
+ ast::TypeImplItem(ref typedef) => {
+ (typedef.ident, typedef.span)
+ }
+ };
+ let item = trait_items.iter().find(|item| {
+ item.name() == ident.name
+ }).unwrap();
+ if warn_about_defns {
+ maybe_do_stability_check(tcx, item.def_id(), span, cb);
+ }
+ }
+ }
+
_ => (/* pass */)
}
}
}
pub fn self_ty(&self) -> Option<Ty<'tcx>> {
- self.types.get_self().map(|&t| t)
+ self.types.get_self().cloned()
}
pub fn with_self_ty(&self, self_ty: Ty<'tcx>) -> Substs<'tcx> {
}
}
-// NOTE(stage0): remove impl after a snapshot
-#[cfg(stage0)]
-impl<T> IntoIterator for VecPerParamSpace<T> {
- type IntoIter = IntoIter<T>;
-
- fn into_iter(self) -> IntoIter<T> {
- self.into_vec().into_iter()
- }
-}
-
-#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
impl<T> IntoIterator for VecPerParamSpace<T> {
type Item = T;
type IntoIter = IntoIter<T>;
}
}
-// NOTE(stage0): remove impl after a snapshot
-#[cfg(stage0)]
-impl<'a,T> IntoIterator for &'a VecPerParamSpace<T> {
- type IntoIter = Iter<'a, T>;
-
- fn into_iter(self) -> Iter<'a, T> {
- self.as_slice().into_iter()
- }
-}
-
-#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
impl<'a,T> IntoIterator for &'a VecPerParamSpace<T> {
type Item = &'a T;
type IntoIter = Iter<'a, T>;
// except according to those terms.
use middle::infer::{InferCtxt};
-use middle::mem_categorization::Typer;
use middle::ty::{self, RegionEscape, Ty};
use std::collections::HashSet;
use std::collections::hash_map::Entry::{Occupied, Vacant};
pub use self::Vtable::*;
pub use self::ObligationCauseCode::*;
-use middle::mem_categorization::Typer;
use middle::subst;
-use middle::ty::{self, Ty};
+use middle::ty::{self, HasProjectionTypes, Ty};
+use middle::ty_fold::TypeFoldable;
use middle::infer::{self, InferCtxt};
use std::slice::Iter;
use std::rc::Rc;
debug!("normalize_param_env(param_env={})",
param_env.repr(tcx));
- let predicates: Vec<ty::Predicate<'tcx>> = {
- let infcx = infer::new_infer_ctxt(tcx);
- let mut selcx = &mut SelectionContext::new(&infcx, param_env);
- let mut fulfill_cx = FulfillmentContext::new();
- let Normalized { value: predicates, obligations } =
- project::normalize(selcx, cause, ¶m_env.caller_bounds);
- for obligation in obligations {
- fulfill_cx.register_predicate_obligation(selcx.infcx(), obligation);
- }
- try!(fulfill_cx.select_all_or_error(selcx.infcx(), param_env));
- predicates.iter().map(|p| infcx.resolve_type_vars_if_possible(p)).collect()
- };
+ let infcx = infer::new_infer_ctxt(tcx);
+ let predicates = try!(fully_normalize(&infcx, param_env, cause, ¶m_env.caller_bounds));
debug!("normalize_param_env: predicates={}",
predicates.repr(tcx));
Ok(param_env.with_caller_bounds(predicates))
}
+pub fn fully_normalize<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
+ closure_typer: &ty::ClosureTyper<'tcx>,
+ cause: ObligationCause<'tcx>,
+ value: &T)
+ -> Result<T, Vec<FulfillmentError<'tcx>>>
+ where T : TypeFoldable<'tcx> + HasProjectionTypes + Clone + Repr<'tcx>
+{
+ let tcx = closure_typer.tcx();
+
+ debug!("normalize_param_env(value={})",
+ value.repr(tcx));
+
+ let mut selcx = &mut SelectionContext::new(infcx, closure_typer);
+ let mut fulfill_cx = FulfillmentContext::new();
+ let Normalized { value: normalized_value, obligations } =
+ project::normalize(selcx, cause, value);
+ debug!("normalize_param_env: normalized_value={} obligations={}",
+ normalized_value.repr(tcx),
+ obligations.repr(tcx));
+ for obligation in obligations {
+ fulfill_cx.register_predicate_obligation(selcx.infcx(), obligation);
+ }
+ try!(fulfill_cx.select_all_or_error(infcx, closure_typer));
+ let resolved_value = infcx.resolve_type_vars_if_possible(&normalized_value);
+ debug!("normalize_param_env: resolved_value={}",
+ resolved_value.repr(tcx));
+ Ok(resolved_value)
+}
+
impl<'tcx,O> Obligation<'tcx,O> {
pub fn new(cause: ObligationCause<'tcx>,
trait_ref: O)
{
// Because we query yes/no results frequently, we keep a cache:
let cached_result =
- tcx.object_safety_cache.borrow().get(&trait_ref.def_id()).map(|&r| r);
+ tcx.object_safety_cache.borrow().get(&trait_ref.def_id()).cloned();
let result =
cached_result.unwrap_or_else(|| {
use super::{DerivedObligationCause};
use super::{project};
use super::project::Normalized;
-use super::{PredicateObligation, Obligation, TraitObligation, ObligationCause};
+use super::{PredicateObligation, TraitObligation, ObligationCause};
use super::{ObligationCauseCode, BuiltinDerivedObligation};
use super::{SelectionError, Unimplemented, Overflow, OutputTypeParameterMismatch};
use super::{Selection};
use super::{util};
use middle::fast_reject;
-use middle::mem_categorization::Typer;
use middle::subst::{Subst, Substs, TypeSpace, VecPerParamSpace};
-use middle::ty::{self, AsPredicate, RegionEscape, ToPolyTraitRef, Ty};
+use middle::ty::{self, RegionEscape, ToPolyTraitRef, Ty};
use middle::infer;
use middle::infer::{InferCtxt, TypeFreshener};
use middle::ty_fold::TypeFoldable;
let is_dup =
(0..candidates.len())
.filter(|&j| i != j)
- .any(|j| self.candidate_should_be_dropped_in_favor_of(stack,
- &candidates[i],
+ .any(|j| self.candidate_should_be_dropped_in_favor_of(&candidates[i],
&candidates[j]));
if is_dup {
debug!("Dropping candidate #{}/{}: {}",
{
let cache = self.pick_candidate_cache();
let hashmap = cache.hashmap.borrow();
- hashmap.get(&cache_fresh_trait_pred.0.trait_ref).map(|c| (*c).clone())
+ hashmap.get(&cache_fresh_trait_pred.0.trait_ref).cloned()
}
fn insert_candidate_cache(&mut self,
self.evaluate_predicates_recursively(stack, selection.iter_nested())
}
- /// Returns true if `candidate_i` should be dropped in favor of `candidate_j`.
- ///
- /// This is generally true if either:
- /// - candidate i and candidate j are equivalent; or,
- /// - candidate i is a concrete impl and candidate j is a where clause bound,
- /// and the concrete impl is applicable to the types in the where clause bound.
- ///
- /// The last case refers to cases where there are blanket impls (often conditional
- /// blanket impls) as well as a where clause. This can come down to one of two cases:
- ///
- /// - The impl is truly unconditional (it has no where clauses
- /// of its own), in which case the where clause is
- /// unnecessary, because coherence requires that we would
- /// pick that particular impl anyhow (at least so long as we
- /// don't have specialization).
- ///
- /// - The impl is conditional, in which case we may not have winnowed it out
- /// because we don't know if the conditions apply, but the where clause is basically
- /// telling us that there is some impl, though not necessarily the one we see.
- ///
- /// In both cases we prefer to take the where clause, which is
- /// essentially harmless. See issue #18453 for more details of
- /// a case where doing the opposite caused us harm.
+ /// Returns true if `candidate_i` should be dropped in favor of
+ /// `candidate_j`. Generally speaking we will drop duplicate
+ /// candidates and prefer where-clause candidates.
fn candidate_should_be_dropped_in_favor_of<'o>(&mut self,
- stack: &TraitObligationStack<'o, 'tcx>,
candidate_i: &SelectionCandidate<'tcx>,
candidate_j: &SelectionCandidate<'tcx>)
-> bool
}
match (candidate_i, candidate_j) {
- (&ImplCandidate(impl_def_id), &ParamCandidate(ref bound)) => {
- debug!("Considering whether to drop param {} in favor of impl {}",
- candidate_i.repr(self.tcx()),
- candidate_j.repr(self.tcx()));
-
- self.infcx.probe(|snapshot| {
- let (skol_obligation_trait_ref, skol_map) =
- self.infcx().skolemize_late_bound_regions(
- &stack.obligation.predicate, snapshot);
- let impl_substs =
- self.rematch_impl(impl_def_id, stack.obligation, snapshot,
- &skol_map, skol_obligation_trait_ref.trait_ref.clone());
- let impl_trait_ref =
- ty::impl_trait_ref(self.tcx(), impl_def_id).unwrap();
- let impl_trait_ref =
- impl_trait_ref.subst(self.tcx(), &impl_substs.value);
- let poly_impl_trait_ref =
- ty::Binder(impl_trait_ref);
- let origin =
- infer::RelateOutputImplTypes(stack.obligation.cause.span);
- self.infcx
- .sub_poly_trait_refs(false, origin, poly_impl_trait_ref, bound.clone())
- .is_ok()
- })
- }
- (&BuiltinCandidate(_), &ParamCandidate(_)) => {
- // If we have a where-clause like `Option<K> : Send`,
- // then we wind up in a situation where there is a
- // default rule (`Option<K>:Send if K:Send) and the
- // where-clause that both seem applicable. Just take
- // the where-clause in that case.
+ (&ImplCandidate(..), &ParamCandidate(..)) |
+ (&ClosureCandidate(..), &ParamCandidate(..)) |
+ (&FnPointerCandidate(..), &ParamCandidate(..)) |
+ (&BuiltinCandidate(..), &ParamCandidate(..)) => {
+ // We basically prefer always prefer to use a
+ // where-clause over another option. Where clauses
+ // impose the burden of finding the exact match onto
+ // the caller. Using an impl in preference of a where
+ // clause can also lead us to "overspecialize", as in
+ // #18453.
true
}
(&ProjectionCandidate, &ParamCandidate(_)) => {
ty::BoundSync |
ty::BoundSend => {
- // Note: technically, a region pointer is only
- // sendable if it has lifetime
- // `'static`. However, we don't take regions
- // into account when doing trait matching:
- // instead, when we decide that `T : Send`, we
- // will register a separate constraint with
- // the region inferencer that `T : 'static`
- // holds as well (because the trait `Send`
- // requires it). This will ensure that there
- // is no borrowed data in `T` (or else report
- // an inference error). The reason we do it
- // this way is that we do not yet *know* what
- // lifetime the borrowed reference has, since
- // we haven't finished running inference -- in
- // other words, there's a kind of
- // chicken-and-egg problem.
Ok(If(vec![referent_ty]))
}
}
ty::substd_enum_variants(self.tcx(), def_id, substs)
.iter()
.flat_map(|variant| variant.args.iter())
- .map(|&ty| ty)
+ .cloned()
.collect();
nominal(self, bound, def_id, types)
}
}
})
}).collect::<Result<_, _>>();
- let mut obligations = match obligations {
+ let obligations = match obligations {
Ok(o) => o,
Err(ErrorReported) => Vec::new()
};
- // as a special case, `Send` requires `'static`
- if bound == ty::BoundSend {
- obligations.push(Obligation {
- cause: obligation.cause.clone(),
- recursion_depth: obligation.recursion_depth+1,
- predicate: ty::Binder(ty::OutlivesPredicate(obligation.self_ty(),
- ty::ReStatic)).as_predicate(),
- });
- }
-
let obligations = VecPerParamSpace::new(obligations, Vec::new(), Vec::new());
debug!("vtable_builtin_data: obligations={}",
use std::cmp;
use std::fmt;
use std::hash::{Hash, Writer, SipHasher, Hasher};
-#[cfg(stage0)]
-use std::marker;
use std::mem;
use std::ops;
use std::rc::Rc;
// the maximal depth of any bound regions appearing in this type.
region_depth: u32,
-
- // force the lifetime to be invariant to work-around
- // region-inference issues with a covariant lifetime.
- #[cfg(stage0)]
- marker: ShowInvariantLifetime<'tcx>,
-}
-
-#[cfg(stage0)]
-struct ShowInvariantLifetime<'a>(marker::InvariantLifetime<'a>);
-#[cfg(stage0)]
-impl<'a> ShowInvariantLifetime<'a> {
- fn new() -> ShowInvariantLifetime<'a> {
- ShowInvariantLifetime(marker::InvariantLifetime)
- }
-}
-#[cfg(stage0)]
-impl<'a> fmt::Debug for ShowInvariantLifetime<'a> {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "InvariantLifetime")
- }
}
impl fmt::Debug for TypeFlags {
}
}
-#[cfg(stage0)]
-impl<'tcx> PartialEq for TyS<'tcx> {
- fn eq<'a,'b>(&'a self, other: &'b TyS<'tcx>) -> bool {
- let other: &'a TyS<'tcx> = unsafe { mem::transmute(other) };
- (self as *const _) == (other as *const _)
- }
-}
-#[cfg(not(stage0))]
impl<'tcx> PartialEq for TyS<'tcx> {
fn eq(&self, other: &TyS<'tcx>) -> bool {
// (self as *const _) == (other as *const _)
}
pub trait ClosureTyper<'tcx> {
+ fn tcx(&self) -> &ty::ctxt<'tcx> {
+ self.param_env().tcx
+ }
+
fn param_env<'a>(&'a self) -> &'a ty::ParameterEnvironment<'a, 'tcx>;
/// Is this a `Fn`, `FnMut` or `FnOnce` closure? During typeck,
let flags = FlagComputation::for_sty(&st);
let ty = match () {
- #[cfg(stage0)]
- () => type_arena.alloc(TyS { sty: st,
- flags: flags.flags,
- region_depth: flags.depth,
- marker: ShowInvariantLifetime::new(), }),
- #[cfg(not(stage0))]
() => type_arena.alloc(TyS { sty: st,
flags: flags.flags,
region_depth: flags.depth, }),
def_id: ast::DefId,
input_tys: &[Ty<'tcx>],
output: Ty<'tcx>) -> Ty<'tcx> {
- let input_args = input_tys.iter().map(|ty| *ty).collect();
+ let input_args = input_tys.iter().cloned().collect();
mk_bare_fn(cx,
Some(def_id),
cx.mk_bare_fn(BareFnTy {
-> Representability {
match ty.sty {
ty_tup(ref ts) => {
- find_nonrepresentable(cx, sp, seen, ts.iter().map(|ty| *ty))
+ find_nonrepresentable(cx, sp, seen, ts.iter().cloned())
}
// Fixed-length vectors.
// FIXME(#11924) Behavior undecided for zero-length vectors.
variant: Option<ast::DefId>) -> Option<Ty<'tcx>> {
match (&ty.sty, variant) {
- (&ty_tup(ref v), None) => v.get(i).map(|&t| t),
+ (&ty_tup(ref v), None) => v.get(i).cloned(),
(&ty_struct(def_id, substs), None) => lookup_struct_fields(cx, def_id)
// overloaded deref operators have all late-bound
// regions fully instantiated and coverge
let fn_ret =
- ty::assert_no_late_bound_regions(cx,
- &ty_fn_ret(method_ty));
+ ty::no_late_bound_regions(cx,
+ &ty_fn_ret(method_ty)).unwrap();
adjusted_ty = fn_ret.unwrap();
}
None => {}
}
pub fn provided_source(cx: &ctxt, id: ast::DefId) -> Option<ast::DefId> {
- cx.provided_method_sources.borrow().get(&id).map(|x| *x)
+ cx.provided_method_sources.borrow().get(&id).cloned()
}
pub fn provided_trait_methods<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
let arg_tys = if args.len() > 0 {
// the regions in the argument types come from the
// enum def'n, and hence will all be early bound
- ty::assert_no_late_bound_regions(cx, &ty_fn_args(ctor_ty))
+ ty::no_late_bound_regions(cx, &ty_fn_args(ctor_ty)).unwrap()
} else {
Vec::new()
};
}
impl<'a,'tcx> mc::Typer<'tcx> for ParameterEnvironment<'a,'tcx> {
- fn tcx(&self) -> &ty::ctxt<'tcx> {
- self.tcx
- }
-
fn node_ty(&self, id: ast::NodeId) -> mc::McResult<Ty<'tcx>> {
Ok(ty::node_id_to_type(self.tcx, id))
}
}
/// A free variable referred to in a function.
-#[derive(Copy, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
pub struct Freevar {
/// The variable being accessed free.
pub def: def::Def,
count_late_bound_regions(tcx, value) > 0
}
-pub fn assert_no_late_bound_regions<'tcx, T>(
+pub fn no_late_bound_regions<'tcx, T>(
tcx: &ty::ctxt<'tcx>,
value: &Binder<T>)
- -> T
+ -> Option<T>
where T : TypeFoldable<'tcx> + Repr<'tcx> + Clone
{
- assert!(!binds_late_bound_regions(tcx, value));
- value.0.clone()
+ if binds_late_bound_regions(tcx, value) {
+ None
+ } else {
+ Some(value.0.clone())
+ }
}
/// Replace any late-bound regions bound in `value` with `'static`. Useful in trans but also
"32" => (ast::TyI32, ast::TyU32),
"64" => (ast::TyI64, ast::TyU64),
w => sp.handler().fatal(&format!("target specification was invalid: unrecognized \
- target-word-size {}", w)[])
+ target-pointer-width {}", w)[])
};
Config {
F: FnOnce(T) -> U,
{
let key = arg.clone();
- let result = cache.borrow().get(&key).map(|result| result.clone());
+ let result = cache.borrow().get(&key).cloned();
match result {
Some(result) => result,
None => {
}
// Region, if not obviously implied by builtin bounds.
- if bounds.region_bound != ty::ReStatic ||
- !bounds.builtin_bounds.contains(&ty::BoundSend)
- { // Region bound is implied by builtin bounds:
+ if bounds.region_bound != ty::ReStatic {
+ // Region bound is implied by builtin bounds:
components.push(bounds.region_bound.user_string(tcx));
}
#![feature(core)]
#![feature(hash)]
#![feature(int_uint)]
-#![feature(io)]
+#![feature(old_io)]
#![feature(os)]
-#![feature(path)]
+#![feature(old_path)]
#![feature(rustc_private)]
#![feature(staged_api)]
#![feature(env)]
debug!("preparing the RPATH!");
let libs = config.used_crates.clone();
- let libs = libs.into_iter().filter_map(|(_, l)| {
- l.map(|p| p.clone())
- }).collect::<Vec<_>>();
-
+ let libs = libs.into_iter().filter_map(|(_, l)| l).collect::<Vec<_>>();
let rpaths = get_rpaths(config, &libs[]);
flags.push_all(&rpaths_to_flags(&rpaths[])[]);
flags
pub fn target() -> Target {
let mut base = super::linux_base::opts();
base.pre_link_args.push("-Wl,--allow-multiple-definition".to_string());
+ base.is_like_android = true;
base.position_independent_executables = true;
Target {
data_layout: "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\
// Many of the symbols defined in compiler-rt are also defined in libgcc. Android
// linker doesn't like that by default.
base.pre_link_args.push("-Wl,--allow-multiple-definition".to_string());
+ base.is_like_android = true;
// FIXME #17437 (and #17448): Android doesn't support position dependent executables anymore.
base.position_independent_executables = false;
//! this module defines the format the JSON file should take, though each
//! underscore in the field names should be replaced with a hyphen (`-`) in the
//! JSON file. Some fields are required in every target specification, such as
-//! `data-layout`, `llvm-target`, `target-endian`, `target-word-size`, and
+//! `data-layout`, `llvm-target`, `target-endian`, `target-pointer-width`, and
//! `arch`. In general, options passed to rustc with `-C` override the target's
//! settings, though `target-feature` and `link-args` will *add* to the list
//! specified by the target, rather than replace.
/// only realy used for figuring out how to find libraries, since Windows uses its own
/// library naming convention. Defaults to false.
pub is_like_windows: bool,
+ /// Whether the target toolchain is like Android's. Only useful for compiling against Android.
+ /// Defaults to false.
+ pub is_like_android: bool,
/// Whether the linker support GNU-like arguments such as -O. Defaults to false.
pub linker_is_gnu: bool,
/// Whether the linker support rpaths or not. Defaults to false.
staticlib_suffix: ".a".to_string(),
is_like_osx: false,
is_like_windows: false,
+ is_like_android: false,
linker_is_gnu: false,
has_rpath: false,
no_compiler_rt: false,
data_layout: get_req_field("data-layout"),
llvm_target: get_req_field("llvm-target"),
target_endian: get_req_field("target-endian"),
- target_pointer_width: get_req_field("target-word-size"),
+ target_pointer_width: get_req_field("target-pointer-width"),
arch: get_req_field("arch"),
target_os: get_req_field("os"),
options: Default::default(),
mips_unknown_linux_gnu,
mipsel_unknown_linux_gnu,
powerpc_unknown_linux_gnu,
- arm_linux_androideabi,
arm_unknown_linux_gnueabi,
arm_unknown_linux_gnueabihf,
aarch64_unknown_linux_gnu,
+ arm_linux_androideabi,
+ aarch64_linux_android,
+
x86_64_unknown_freebsd,
i686_unknown_dragonfly,
i386_apple_ios,
x86_64_apple_ios,
aarch64_apple_ios,
- aarch64_linux_android,
armv7_apple_ios,
armv7s_apple_ios,
use borrowck::move_data::*;
use rustc::middle::expr_use_visitor as euv;
use rustc::middle::mem_categorization as mc;
-use rustc::middle::mem_categorization::Typer;
use rustc::middle::mem_categorization::InteriorOffsetKind as Kind;
use rustc::middle::ty;
use rustc::util::ppaux::Repr;
use borrowck::BorrowckCtxt;
use rustc::middle::mem_categorization as mc;
-use rustc::middle::mem_categorization::Typer;
use rustc::middle::mem_categorization::InteriorOffsetKind as Kind;
use rustc::middle::ty;
use rustc::util::ppaux::UserString;
new_path.extend(env::split_paths(&_old_path));
env::set_var("PATH", &env::join_paths(new_path.iter()).unwrap());
}
+ let features = sess.features.borrow();
let cfg = syntax::ext::expand::ExpansionConfig {
crate_name: crate_name.to_string(),
- enable_quotes: sess.features.borrow().quote,
+ features: Some(&features),
recursion_limit: sess.recursion_limit.get(),
};
let ret = syntax::ext::expand::expand_crate(&sess.parse_sess,
#![feature(core)]
#![feature(env)]
#![feature(int_uint)]
-#![feature(io)]
+#![feature(old_io)]
#![feature(libc)]
#![feature(os)]
-#![feature(path)]
+#![feature(old_path)]
#![feature(quote)]
#![feature(rustc_diagnostic_macros)]
#![feature(rustc_private)]
#![feature(unsafe_destructor)]
#![feature(staged_api)]
-#![feature(std_misc)]
#![feature(unicode)]
extern crate arena;
use rustc::util::common::time;
use std::cmp::Ordering::Equal;
-use std::old_io;
+use std::old_io::{self, stdio};
use std::iter::repeat;
use std::env;
use std::sync::mpsc::channel;
static BUG_REPORT_URL: &'static str =
- "http://doc.rust-lang.org/complement-bugreport.html";
+ "https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports";
pub fn run(args: Vec<String>) -> int {
///
/// The diagnostic emitter yielded to the procedure should be used for reporting
/// errors of the compiler.
-pub fn monitor<F:FnOnce()+Send>(f: F) {
+pub fn monitor<F:FnOnce()+Send+'static>(f: F) {
static STACK_SIZE: uint = 8 * 1024 * 1024; // 8MB
let (tx, rx) = channel();
cfg = cfg.stack_size(STACK_SIZE);
}
- match cfg.scoped(move || { std::old_io::stdio::set_stderr(box w); f() }).join() {
+ match cfg.spawn(move || { stdio::set_stderr(box w); f() }).unwrap().join() {
Ok(()) => { /* fallthrough */ }
Err(value) => {
// Thread panicked without emitting a fatal diagnostic
output_ty: Ty<'tcx>)
-> Ty<'tcx>
{
- let input_args = input_tys.iter().map(|ty| *ty).collect();
+ let input_args = input_tys.iter().cloned().collect();
ty::mk_bare_fn(self.infcx.tcx,
None,
self.infcx.tcx.mk_bare_fn(ty::BareFnTy {
#![feature(int_uint)]
#![feature(libc)]
#![feature(link_args)]
-#![feature(path)]
+#![feature(old_path)]
#![feature(staged_api)]
#![feature(std_misc)]
use std::ffi::CString;
use std::cell::RefCell;
-use std::{raw, mem, ptr};
+use std::{raw, mem};
use libc::{c_uint, c_ushort, uint64_t, c_int, size_t, c_char};
use libc::{c_longlong, c_ulonglong, c_void};
use debuginfo::{DIBuilderRef, DIDescriptor,
.expect("got a non-UTF8 DebugLoc from LLVM")
}
-// FIXME #15460 - create a public function that actually calls our
-// static LLVM symbols. Otherwise the linker will just throw llvm
-// away. We're just calling lots of stuff until we transitively get
-// all of LLVM. This is worse than anything.
-pub unsafe fn static_link_hack_this_sucks() {
- LLVMInitializePasses();
-
- LLVMInitializeX86TargetInfo();
- LLVMInitializeX86Target();
- LLVMInitializeX86TargetMC();
- LLVMInitializeX86AsmPrinter();
- LLVMInitializeX86AsmParser();
-
- LLVMInitializeARMTargetInfo();
- LLVMInitializeARMTarget();
- LLVMInitializeARMTargetMC();
- LLVMInitializeARMAsmPrinter();
- LLVMInitializeARMAsmParser();
-
- LLVMInitializeAArch64TargetInfo();
- LLVMInitializeAArch64Target();
- LLVMInitializeAArch64TargetMC();
- LLVMInitializeAArch64AsmPrinter();
- LLVMInitializeAArch64AsmParser();
-
- LLVMInitializeMipsTargetInfo();
- LLVMInitializeMipsTarget();
- LLVMInitializeMipsTargetMC();
- LLVMInitializeMipsAsmPrinter();
- LLVMInitializeMipsAsmParser();
-
- LLVMInitializePowerPCTargetInfo();
- LLVMInitializePowerPCTarget();
- LLVMInitializePowerPCTargetMC();
- LLVMInitializePowerPCAsmPrinter();
- LLVMInitializePowerPCAsmParser();
-
- LLVMRustSetLLVMOptions(0 as c_int, ptr::null());
-
- LLVMPassManagerBuilderPopulateModulePassManager(ptr::null_mut(), ptr::null_mut());
- LLVMPassManagerBuilderPopulateLTOPassManager(ptr::null_mut(), ptr::null_mut(), False, False);
- LLVMPassManagerBuilderPopulateFunctionPassManager(ptr::null_mut(), ptr::null_mut());
- LLVMPassManagerBuilderSetOptLevel(ptr::null_mut(), 0 as c_uint);
- LLVMPassManagerBuilderUseInlinerWithThreshold(ptr::null_mut(), 0 as c_uint);
- LLVMWriteBitcodeToFile(ptr::null_mut(), ptr::null());
- LLVMPassManagerBuilderCreate();
- LLVMPassManagerBuilderDispose(ptr::null_mut());
-
- LLVMRustLinkInExternalBitcode(ptr::null_mut(), ptr::null(), 0 as size_t);
-
- LLVMLinkInMCJIT();
- LLVMLinkInInterpreter();
-
- extern {
- fn LLVMLinkInMCJIT();
- fn LLVMLinkInInterpreter();
- }
-}
-
// The module containing the native LLVM dependencies, generated by the build system
// Note that this must come after the rustllvm extern declaration so that
// parts of LLVM that rustllvm depends on aren't thrown away by the linker.
-> ResolveResult<(Rc<Module>, LastPrivate)> {
fn search_parent_externals(needle: Name, module: &Rc<Module>)
-> Option<Rc<Module>> {
- module.external_module_children.borrow()
- .get(&needle).cloned()
- .map(|_| module.clone())
- .or_else(|| {
- match module.parent_link.clone() {
- ModuleParentLink(parent, _) => {
- search_parent_externals(needle,
- &parent.upgrade().unwrap())
+ match module.external_module_children.borrow().get(&needle) {
+ Some(_) => Some(module.clone()),
+ None => match module.parent_link {
+ ModuleParentLink(ref parent, _) => {
+ search_parent_externals(needle, &parent.upgrade().unwrap())
}
_ => None
}
- })
+ }
}
let mut search_module = module_;
}
tx.take().unwrap().send(()).unwrap();
- });
+ }).unwrap();
}
let mut panicked = false;
#![feature(core)]
#![feature(hash)]
#![feature(int_uint)]
-#![feature(io)]
+#![feature(old_io)]
#![feature(env)]
#![feature(libc)]
-#![feature(path)]
+#![feature(old_path)]
#![feature(quote)]
#![feature(rustc_diagnostic_macros)]
#![feature(rustc_private)]
&format!("comparison of `{}`",
cx.ty_to_string(rhs_t))[],
StrEqFnLangItem);
- callee::trans_lang_call(cx, did, &[lhs, rhs], None, debug_loc)
+ let t = ty::mk_str_slice(cx.tcx(), cx.tcx().mk_region(ty::ReStatic), ast::MutImmutable);
+ // The comparison function gets the slices by value, so we have to make copies here. Even
+ // if the function doesn't write through the pointer, things like lifetime intrinsics
+ // require that we do this properly
+ let lhs_arg = alloc_ty(cx, t, "lhs");
+ let rhs_arg = alloc_ty(cx, t, "rhs");
+ memcpy_ty(cx, lhs_arg, lhs, t);
+ memcpy_ty(cx, rhs_arg, rhs, t);
+ let res = callee::trans_lang_call(cx, did, &[lhs_arg, rhs_arg], None, debug_loc);
+ call_lifetime_end(res.bcx, lhs_arg);
+ call_lifetime_end(res.bcx, rhs_arg);
+
+ res
}
let _icx = push_ctxt("compare_values");
reachable.push("rust_eh_personality_catch".to_string());
if codegen_units > 1 {
- internalize_symbols(&shared_ccx, &reachable.iter().map(|x| x.clone()).collect());
+ internalize_symbols(&shared_ccx, &reachable.iter().cloned().collect());
}
let metadata_module = ModuleTranslation {
let function_type = typer.closure_type(closure_id, param_substs);
let freevars: Vec<ty::Freevar> =
- ty::with_freevars(tcx, id, |fv| fv.iter().map(|&fv| fv).collect());
+ ty::with_freevars(tcx, id, |fv| fv.iter().cloned().collect());
let sig = ty::erase_late_bound_regions(tcx, &function_type.sig);
}
impl<'blk, 'tcx> mc::Typer<'tcx> for BlockS<'blk, 'tcx> {
- fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> {
- self.tcx()
- }
-
fn node_ty(&self, id: ast::NodeId) -> mc::McResult<Ty<'tcx>> {
Ok(node_id_type(self, id))
}
// instruct LLVM to emit an older version of dwarf, however,
// for OS X to understand. For more info see #11352
// This can be overridden using --llvm-opts -dwarf-version,N.
- if cx.sess().target.target.options.is_like_osx {
+ // Android has the same issue (#22398)
+ if cx.sess().target.target.options.is_like_osx ||
+ cx.sess().target.target.options.is_like_android {
llvm::LLVMRustAddModuleFlag(cx.llmod(),
"Dwarf Version\0".as_ptr() as *const _,
2)
let ix_datum = unpack_datum!(bcx, trans(bcx, idx));
let ref_ty = // invoked methods have LB regions instantiated:
- ty::assert_no_late_bound_regions(
- bcx.tcx(), &ty::ty_fn_ret(method_ty)).unwrap();
+ ty::no_late_bound_regions(
+ bcx.tcx(), &ty::ty_fn_ret(method_ty)).unwrap().unwrap();
let elt_ty = match ty::deref(ref_ty, true) {
None => {
bcx.tcx().sess.span_bug(index_expr.span,
let trait_ref =
bcx.tcx().object_cast_map.borrow()
.get(&expr.id)
- .map(|t| (*t).clone())
+ .cloned()
.unwrap();
let trait_ref = bcx.monomorphize(&trait_ref);
let datum = unpack_datum!(bcx, trans(bcx, &**val));
};
let ref_ty = // invoked methods have their LB regions instantiated
- ty::assert_no_late_bound_regions(
- ccx.tcx(), &ty::ty_fn_ret(method_ty)).unwrap();
+ ty::no_late_bound_regions(
+ ccx.tcx(), &ty::ty_fn_ret(method_ty)).unwrap().unwrap();
let scratch = rvalue_scratch_datum(bcx, ref_ty, "overloaded_deref");
unpack_result!(bcx, trans_overloaded_op(bcx, expr, method_call,
abi: abi::Abi)
-> Vec<Ty<'tcx>> {
if abi != abi::RustCall {
- return inputs.iter().map(|x| (*x).clone()).collect()
+ return inputs.iter().cloned().collect()
}
if inputs.len() == 0 {
let ctor_scheme = ty::lookup_item_type(tcx, enum_def);
let ctor_predicates = ty::lookup_predicates(tcx, enum_def);
let path_scheme = if ty::is_fn_ty(ctor_scheme.ty) {
- let fn_ret = ty::assert_no_late_bound_regions(tcx, &ty::ty_fn_ret(ctor_scheme.ty));
+ let fn_ret = ty::no_late_bound_regions(tcx, &ty::ty_fn_ret(ctor_scheme.ty)).unwrap();
ty::TypeScheme {
ty: fn_ret.unwrap(),
generics: ctor_scheme.generics,
// (This always bites me, should find a way to
// refactor it.)
let method_sig =
- ty::assert_no_late_bound_regions(fcx.tcx(),
- ty::ty_fn_sig(method_callee.ty));
+ ty::no_late_bound_regions(fcx.tcx(),
+ ty::ty_fn_sig(method_callee.ty)).unwrap();
debug!("attempt_resolution: method_callee={}",
method_callee.repr(fcx.tcx()));
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// #![warn(deprecated_mode)]
+
+use astconv::object_region_bounds;
+use middle::infer::{InferCtxt, GenericKind};
+use middle::subst::{Substs};
+use middle::traits;
+use middle::ty::{self, ToPolyTraitRef, Ty};
+use middle::ty_fold::{TypeFoldable, TypeFolder};
+
+use std::rc::Rc;
+use syntax::ast;
+use syntax::codemap::Span;
+
+use util::common::ErrorReported;
+use util::ppaux::Repr;
+
+// Helper functions related to manipulating region types.
+
+pub enum Implication<'tcx> {
+ RegionSubRegion(Option<Ty<'tcx>>, ty::Region, ty::Region),
+ RegionSubGeneric(Option<Ty<'tcx>>, ty::Region, GenericKind<'tcx>),
+ Predicate(ast::DefId, ty::Predicate<'tcx>),
+}
+
+struct Implicator<'a, 'tcx: 'a> {
+ infcx: &'a InferCtxt<'a,'tcx>,
+ closure_typer: &'a (ty::ClosureTyper<'tcx>+'a),
+ body_id: ast::NodeId,
+ stack: Vec<(ty::Region, Option<Ty<'tcx>>)>,
+ span: Span,
+ out: Vec<Implication<'tcx>>,
+}
+
+/// This routine computes the well-formedness constraints that must hold for the type `ty` to
+/// appear in a context with lifetime `outer_region`
+pub fn implications<'a,'tcx>(
+ infcx: &'a InferCtxt<'a,'tcx>,
+ closure_typer: &ty::ClosureTyper<'tcx>,
+ body_id: ast::NodeId,
+ ty: Ty<'tcx>,
+ outer_region: ty::Region,
+ span: Span)
+ -> Vec<Implication<'tcx>>
+{
+ debug!("implications(body_id={}, ty={}, outer_region={})",
+ body_id,
+ ty.repr(closure_typer.tcx()),
+ outer_region.repr(closure_typer.tcx()));
+
+ let mut stack = Vec::new();
+ stack.push((outer_region, None));
+ let mut wf = Implicator { closure_typer: closure_typer,
+ infcx: infcx,
+ body_id: body_id,
+ span: span,
+ stack: stack,
+ out: Vec::new() };
+ wf.accumulate_from_ty(ty);
+ debug!("implications: out={}", wf.out.repr(closure_typer.tcx()));
+ wf.out
+}
+
+impl<'a, 'tcx> Implicator<'a, 'tcx> {
+ fn tcx(&self) -> &'a ty::ctxt<'tcx> {
+ self.infcx.tcx
+ }
+
+ fn accumulate_from_ty(&mut self, ty: Ty<'tcx>) {
+ debug!("accumulate_from_ty(ty={})",
+ ty.repr(self.tcx()));
+
+ match ty.sty {
+ ty::ty_bool |
+ ty::ty_char |
+ ty::ty_int(..) |
+ ty::ty_uint(..) |
+ ty::ty_float(..) |
+ ty::ty_bare_fn(..) |
+ ty::ty_err |
+ ty::ty_str => {
+ // No borrowed content reachable here.
+ }
+
+ ty::ty_closure(_, region, _) => {
+ // An "closure type" is basically
+ // modeled here as equivalent to a struct like
+ //
+ // struct TheClosure<'b> {
+ // ...
+ // }
+ //
+ // where the `'b` is the lifetime bound of the
+ // contents (i.e., all contents must outlive 'b).
+ //
+ // Even though closures are glorified structs
+ // of upvars, we do not need to consider them as they
+ // can't generate any new constraints. The
+ // substitutions on the closure are equal to the free
+ // substitutions of the enclosing parameter
+ // environment. An upvar captured by value has the
+ // same type as the original local variable which is
+ // already checked for consistency. If the upvar is
+ // captured by reference it must also outlive the
+ // region bound on the closure, but this is explicitly
+ // handled by logic in regionck.
+ self.push_region_constraint_from_top(*region);
+ }
+
+ ty::ty_trait(ref t) => {
+ let required_region_bounds =
+ object_region_bounds(self.tcx(), &t.principal, t.bounds.builtin_bounds);
+ self.accumulate_from_object_ty(ty, t.bounds.region_bound, required_region_bounds)
+ }
+
+ ty::ty_enum(def_id, substs) |
+ ty::ty_struct(def_id, substs) => {
+ let item_scheme = ty::lookup_item_type(self.tcx(), def_id);
+ self.accumulate_from_adt(ty, def_id, &item_scheme.generics, substs)
+ }
+
+ ty::ty_vec(t, _) |
+ ty::ty_ptr(ty::mt { ty: t, .. }) |
+ ty::ty_uniq(t) => {
+ self.accumulate_from_ty(t)
+ }
+
+ ty::ty_rptr(r_b, mt) => {
+ self.accumulate_from_rptr(ty, *r_b, mt.ty);
+ }
+
+ ty::ty_param(p) => {
+ self.push_param_constraint_from_top(p);
+ }
+
+ ty::ty_projection(ref data) => {
+ // `<T as TraitRef<..>>::Name`
+
+ self.push_projection_constraint_from_top(data);
+ }
+
+ ty::ty_tup(ref tuptys) => {
+ for &tupty in tuptys {
+ self.accumulate_from_ty(tupty);
+ }
+ }
+
+ ty::ty_infer(_) => {
+ // This should not happen, BUT:
+ //
+ // Currently we uncover region relationships on
+ // entering the fn check. We should do this after
+ // the fn check, then we can call this case a bug().
+ }
+
+ ty::ty_open(_) => {
+ self.tcx().sess.bug(
+ &format!("Unexpected type encountered while doing wf check: {}",
+ ty.repr(self.tcx()))[]);
+ }
+ }
+ }
+
+ fn accumulate_from_rptr(&mut self,
+ ty: Ty<'tcx>,
+ r_b: ty::Region,
+ ty_b: Ty<'tcx>) {
+ // We are walking down a type like this, and current
+ // position is indicated by caret:
+ //
+ // &'a &'b ty_b
+ // ^
+ //
+ // At this point, top of stack will be `'a`. We must
+ // require that `'a <= 'b`.
+
+ self.push_region_constraint_from_top(r_b);
+
+ // Now we push `'b` onto the stack, because it must
+ // constrain any borrowed content we find within `T`.
+
+ self.stack.push((r_b, Some(ty)));
+ self.accumulate_from_ty(ty_b);
+ self.stack.pop().unwrap();
+ }
+
+ /// Pushes a constraint that `r_b` must outlive the top region on the stack.
+ fn push_region_constraint_from_top(&mut self,
+ r_b: ty::Region) {
+
+ // Indicates that we have found borrowed content with a lifetime
+ // of at least `r_b`. This adds a constraint that `r_b` must
+ // outlive the region `r_a` on top of the stack.
+ //
+ // As an example, imagine walking a type like:
+ //
+ // &'a &'b T
+ // ^
+ //
+ // when we hit the inner pointer (indicated by caret), `'a` will
+ // be on top of stack and `'b` will be the lifetime of the content
+ // we just found. So we add constraint that `'a <= 'b`.
+
+ let &(r_a, opt_ty) = self.stack.last().unwrap();
+ self.push_sub_region_constraint(opt_ty, r_a, r_b);
+ }
+
+ /// Pushes a constraint that `r_a <= r_b`, due to `opt_ty`
+ fn push_sub_region_constraint(&mut self,
+ opt_ty: Option<Ty<'tcx>>,
+ r_a: ty::Region,
+ r_b: ty::Region) {
+ self.out.push(Implication::RegionSubRegion(opt_ty, r_a, r_b));
+ }
+
+ /// Pushes a constraint that `param_ty` must outlive the top region on the stack.
+ fn push_param_constraint_from_top(&mut self,
+ param_ty: ty::ParamTy) {
+ let &(region, opt_ty) = self.stack.last().unwrap();
+ self.push_param_constraint(region, opt_ty, param_ty);
+ }
+
+ /// Pushes a constraint that `projection_ty` must outlive the top region on the stack.
+ fn push_projection_constraint_from_top(&mut self,
+ projection_ty: &ty::ProjectionTy<'tcx>) {
+ let &(region, opt_ty) = self.stack.last().unwrap();
+ self.out.push(Implication::RegionSubGeneric(
+ opt_ty, region, GenericKind::Projection(projection_ty.clone())));
+ }
+
+ /// Pushes a constraint that `region <= param_ty`, due to `opt_ty`
+ fn push_param_constraint(&mut self,
+ region: ty::Region,
+ opt_ty: Option<Ty<'tcx>>,
+ param_ty: ty::ParamTy) {
+ self.out.push(Implication::RegionSubGeneric(
+ opt_ty, region, GenericKind::Param(param_ty)));
+ }
+
+ fn accumulate_from_adt(&mut self,
+ ty: Ty<'tcx>,
+ def_id: ast::DefId,
+ _generics: &ty::Generics<'tcx>,
+ substs: &Substs<'tcx>)
+ {
+ let predicates =
+ ty::lookup_predicates(self.tcx(), def_id).instantiate(self.tcx(), substs);
+ let predicates = match self.fully_normalize(&predicates) {
+ Ok(predicates) => predicates,
+ Err(ErrorReported) => { return; }
+ };
+
+ for predicate in predicates.predicates.as_slice() {
+ match *predicate {
+ ty::Predicate::Trait(ref data) => {
+ self.accumulate_from_assoc_types_transitive(data);
+ }
+ ty::Predicate::Equate(..) => { }
+ ty::Predicate::Projection(..) => { }
+ ty::Predicate::RegionOutlives(ref data) => {
+ match ty::no_late_bound_regions(self.tcx(), data) {
+ None => { }
+ Some(ty::OutlivesPredicate(r_a, r_b)) => {
+ self.push_sub_region_constraint(Some(ty), r_b, r_a);
+ }
+ }
+ }
+ ty::Predicate::TypeOutlives(ref data) => {
+ match ty::no_late_bound_regions(self.tcx(), data) {
+ None => { }
+ Some(ty::OutlivesPredicate(ty_a, r_b)) => {
+ self.stack.push((r_b, Some(ty)));
+ self.accumulate_from_ty(ty_a);
+ self.stack.pop().unwrap();
+ }
+ }
+ }
+ }
+ }
+
+ let obligations = predicates.predicates
+ .into_iter()
+ .map(|pred| Implication::Predicate(def_id, pred));
+ self.out.extend(obligations);
+
+ let variances = ty::item_variances(self.tcx(), def_id);
+
+ for (®ion, &variance) in substs.regions().iter().zip(variances.regions.iter()) {
+ match variance {
+ ty::Contravariant | ty::Invariant => {
+ // If any data with this lifetime is reachable
+ // within, it must be at least contravariant.
+ self.push_region_constraint_from_top(region)
+ }
+ ty::Covariant | ty::Bivariant => { }
+ }
+ }
+
+ for (&ty, &variance) in substs.types.iter().zip(variances.types.iter()) {
+ match variance {
+ ty::Covariant | ty::Invariant => {
+ // If any data of this type is reachable within,
+ // it must be at least covariant.
+ self.accumulate_from_ty(ty);
+ }
+ ty::Contravariant | ty::Bivariant => { }
+ }
+ }
+ }
+
+ /// Given that there is a requirement that `Foo<X> : 'a`, where
+ /// `Foo` is declared like `struct Foo<T> where T : SomeTrait`,
+ /// this code finds all the associated types defined in
+ /// `SomeTrait` (and supertraits) and adds a requirement that `<X
+ /// as SomeTrait>::N : 'a` (where `N` is some associated type
+ /// defined in `SomeTrait`). This rule only applies to
+ /// trait-bounds that are not higher-ranked, because we cannot
+ /// project out of a HRTB. This rule helps code using associated
+ /// types to compile, see Issue #22246 for an example.
+ fn accumulate_from_assoc_types_transitive(&mut self,
+ data: &ty::PolyTraitPredicate<'tcx>)
+ {
+ for poly_trait_ref in traits::supertraits(self.tcx(), data.to_poly_trait_ref()) {
+ match ty::no_late_bound_regions(self.tcx(), &poly_trait_ref) {
+ Some(trait_ref) => { self.accumulate_from_assoc_types(trait_ref); }
+ None => { }
+ }
+ }
+ }
+
+ fn accumulate_from_assoc_types(&mut self,
+ trait_ref: Rc<ty::TraitRef<'tcx>>)
+ {
+ let trait_def_id = trait_ref.def_id;
+ let trait_def = ty::lookup_trait_def(self.tcx(), trait_def_id);
+ let assoc_type_projections: Vec<_> =
+ trait_def.associated_type_names
+ .iter()
+ .map(|&name| ty::mk_projection(self.tcx(), trait_ref.clone(), name))
+ .collect();
+ let tys = match self.fully_normalize(&assoc_type_projections) {
+ Ok(tys) => { tys }
+ Err(ErrorReported) => { return; }
+ };
+ for ty in tys {
+ self.accumulate_from_ty(ty);
+ }
+ }
+
+ fn accumulate_from_object_ty(&mut self,
+ ty: Ty<'tcx>,
+ region_bound: ty::Region,
+ required_region_bounds: Vec<ty::Region>)
+ {
+ // Imagine a type like this:
+ //
+ // trait Foo { }
+ // trait Bar<'c> : 'c { }
+ //
+ // &'b (Foo+'c+Bar<'d>)
+ // ^
+ //
+ // In this case, the following relationships must hold:
+ //
+ // 'b <= 'c
+ // 'd <= 'c
+ //
+ // The first conditions is due to the normal region pointer
+ // rules, which say that a reference cannot outlive its
+ // referent.
+ //
+ // The final condition may be a bit surprising. In particular,
+ // you may expect that it would have been `'c <= 'd`, since
+ // usually lifetimes of outer things are conservative
+ // approximations for inner things. However, it works somewhat
+ // differently with trait objects: here the idea is that if the
+ // user specifies a region bound (`'c`, in this case) it is the
+ // "master bound" that *implies* that bounds from other traits are
+ // all met. (Remember that *all bounds* in a type like
+ // `Foo+Bar+Zed` must be met, not just one, hence if we write
+ // `Foo<'x>+Bar<'y>`, we know that the type outlives *both* 'x and
+ // 'y.)
+ //
+ // Note: in fact we only permit builtin traits, not `Bar<'d>`, I
+ // am looking forward to the future here.
+
+ // The content of this object type must outlive
+ // `bounds.region_bound`:
+ let r_c = region_bound;
+ self.push_region_constraint_from_top(r_c);
+
+ // And then, in turn, to be well-formed, the
+ // `region_bound` that user specified must imply the
+ // region bounds required from all of the trait types:
+ for &r_d in &required_region_bounds {
+ // Each of these is an instance of the `'c <= 'b`
+ // constraint above
+ self.out.push(Implication::RegionSubRegion(Some(ty), r_d, r_c));
+ }
+ }
+
+ fn fully_normalize<T>(&self, value: &T) -> Result<T,ErrorReported>
+ where T : TypeFoldable<'tcx> + ty::HasProjectionTypes + Clone + Repr<'tcx>
+ {
+ let value =
+ traits::fully_normalize(self.infcx,
+ self.closure_typer,
+ traits::ObligationCause::misc(self.span, self.body_id),
+ value);
+ match value {
+ Ok(value) => Ok(value),
+ Err(errors) => {
+ // I don't like reporting these errors here, but I
+ // don't know where else to report them just now. And
+ // I don't really expect errors to arise here
+ // frequently. I guess the best option would be to
+ // propagate them out.
+ traits::report_fulfillment_errors(self.infcx, &errors);
+ Err(ErrorReported)
+ }
+ }
+ }
+}
+
+impl<'tcx> Repr<'tcx> for Implication<'tcx> {
+ fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
+ match *self {
+ Implication::RegionSubRegion(_, ref r_a, ref r_b) => {
+ format!("RegionSubRegion({}, {})",
+ r_a.repr(tcx),
+ r_b.repr(tcx))
+ }
+
+ Implication::RegionSubGeneric(_, ref r, ref p) => {
+ format!("RegionSubGeneric({}, {})",
+ r.repr(tcx),
+ p.repr(tcx))
+ }
+
+ Implication::Predicate(ref def_id, ref p) => {
+ format!("Predicate({}, {})",
+ def_id.repr(tcx),
+ p.repr(tcx))
+ }
+ }
+ }
+}
pub mod _match;
pub mod vtable;
pub mod writeback;
-pub mod regionmanip;
+pub mod implicator;
pub mod regionck;
pub mod coercion;
pub mod demand;
}
impl<'a, 'tcx> mc::Typer<'tcx> for FnCtxt<'a, 'tcx> {
- fn tcx(&self) -> &ty::ctxt<'tcx> {
- self.ccx.tcx
- }
fn node_ty(&self, id: ast::NodeId) -> McResult<Ty<'tcx>> {
let ty = self.node_ty(id);
self.resolve_type_vars_or_error(&ty)
fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
decl: &'tcx ast::FnDecl,
body: &'tcx ast::Block,
- id: ast::NodeId,
+ fn_id: ast::NodeId,
+ fn_span: Span,
raw_fty: Ty<'tcx>,
param_env: ty::ParameterEnvironment<'a, 'tcx>)
{
let fn_sig =
inh.normalize_associated_types_in(&inh.param_env, body.span, body.id, &fn_sig);
- let fcx = check_fn(ccx, fn_ty.unsafety, id, &fn_sig,
- decl, id, body, &inh);
+ let fcx = check_fn(ccx, fn_ty.unsafety, fn_id, &fn_sig,
+ decl, fn_id, body, &inh);
vtable::select_all_fcx_obligations_and_apply_defaults(&fcx);
- upvar::closure_analyze_fn(&fcx, id, decl, body);
+ upvar::closure_analyze_fn(&fcx, fn_id, decl, body);
vtable::select_all_fcx_obligations_or_error(&fcx);
- regionck::regionck_fn(&fcx, id, decl, body);
+ regionck::regionck_fn(&fcx, fn_id, fn_span, decl, body);
writeback::resolve_type_vars_in_fn(&fcx, decl, body);
}
_ => ccx.tcx.sess.impossible_case(body.span,
// Remember return type so that regionck can access it later.
let mut fn_sig_tys: Vec<Ty> =
arg_tys.iter()
- .map(|&ty| ty)
+ .cloned()
.collect();
if let ty::FnConverging(ret_ty) = ret_ty {
ast::ItemFn(ref decl, _, _, _, ref body) => {
let fn_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
let param_env = ParameterEnvironment::for_item(ccx.tcx, it.id);
- check_bare_fn(ccx, &**decl, &**body, it.id, fn_pty.ty, param_env);
+ check_bare_fn(ccx, &**decl, &**body, it.id, it.span, fn_pty.ty, param_env);
}
ast::ItemImpl(_, _, _, _, _, ref impl_items) => {
debug!("ItemImpl {} with id {}", token::get_ident(it.ident), it.id);
&*method.pe_fn_decl(),
&*method.pe_body(),
method.id,
+ method.span,
fty,
param_env);
}
match method {
Some(method) => {
let ref_ty = // invoked methods have all LB regions instantiated
- ty::assert_no_late_bound_regions(
- fcx.tcx(), &ty::ty_fn_ret(method.ty));
+ ty::no_late_bound_regions(
+ fcx.tcx(), &ty::ty_fn_ret(method.ty)).unwrap();
match method_call {
Some(method_call) => {
fcx.inh.method_map.borrow_mut().insert(method_call,
for field in ast_fields {
let mut expected_field_type = tcx.types.err;
- let pair = class_field_map.get(&field.ident.node.name).map(|x| *x);
+ let pair = class_field_map.get(&field.ident.node.name).cloned();
match pair {
None => {
fcx.type_error_message(
}
ast::ExprStruct(ref path, ref fields, ref base_expr) => {
// Resolve the path.
- let def = tcx.def_map.borrow().get(&id).map(|i| *i);
+ let def = tcx.def_map.borrow().get(&id).cloned();
let struct_id = match def {
Some(def::DefVariant(enum_id, variant_id, true)) => {
check_struct_enum_variant(fcx, id, expr.span, enum_id,
use astconv::AstConv;
use check::dropck;
use check::FnCtxt;
-use check::regionmanip;
+use check::implicator;
use check::vtable;
use middle::def;
use middle::mem_categorization as mc;
use middle::pat_util;
use util::ppaux::{ty_to_string, Repr};
+use std::mem;
use syntax::{ast, ast_util};
use syntax::codemap::Span;
use syntax::visit;
use syntax::visit::Visitor;
-use self::RepeatingScope::Repeating;
use self::SubjectNode::Subject;
// a variation on try that just returns unit
// PUBLIC ENTRY POINTS
pub fn regionck_expr(fcx: &FnCtxt, e: &ast::Expr) {
- let mut rcx = Rcx::new(fcx, Repeating(e.id), Subject(e.id));
+ let mut rcx = Rcx::new(fcx, RepeatingScope(e.id), e.id, Subject(e.id));
if fcx.err_count_since_creation() == 0 {
// regionck assumes typeck succeeded
rcx.visit_expr(e);
}
pub fn regionck_item(fcx: &FnCtxt, item: &ast::Item) {
- let mut rcx = Rcx::new(fcx, Repeating(item.id), Subject(item.id));
+ let mut rcx = Rcx::new(fcx, RepeatingScope(item.id), item.id, Subject(item.id));
rcx.visit_region_obligations(item.id);
rcx.resolve_regions_and_report_errors();
}
-pub fn regionck_fn(fcx: &FnCtxt, id: ast::NodeId, decl: &ast::FnDecl, blk: &ast::Block) {
- let mut rcx = Rcx::new(fcx, Repeating(blk.id), Subject(id));
+pub fn regionck_fn(fcx: &FnCtxt,
+ fn_id: ast::NodeId,
+ fn_span: Span,
+ decl: &ast::FnDecl,
+ blk: &ast::Block) {
+ debug!("regionck_fn(id={})", fn_id);
+ let mut rcx = Rcx::new(fcx, RepeatingScope(blk.id), blk.id, Subject(fn_id));
if fcx.err_count_since_creation() == 0 {
// regionck assumes typeck succeeded
- rcx.visit_fn_body(id, decl, blk);
+ rcx.visit_fn_body(fn_id, decl, blk, fn_span);
}
- // Region checking a fn can introduce new trait obligations,
- // particularly around closure bounds.
- vtable::select_all_fcx_obligations_or_error(fcx);
-
rcx.resolve_regions_and_report_errors();
}
pub fn regionck_ensure_component_tys_wf<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
span: Span,
component_tys: &[Ty<'tcx>]) {
- let mut rcx = Rcx::new(fcx, Repeating(0), SubjectNode::None);
+ let mut rcx = Rcx::new(fcx, RepeatingScope(0), 0, SubjectNode::None);
for &component_ty in component_tys {
// Check that each type outlives the empty region. Since the
// empty region is a subregion of all others, this can't fail
region_bound_pairs: Vec<(ty::Region, GenericKind<'tcx>)>,
+ // id of innermost fn body id
+ body_id: ast::NodeId,
+
// id of innermost fn or loop
repeating_scope: ast::NodeId,
}
}
-pub enum RepeatingScope { Repeating(ast::NodeId) }
+struct RepeatingScope(ast::NodeId);
pub enum SubjectNode { Subject(ast::NodeId), None }
impl<'a, 'tcx> Rcx<'a, 'tcx> {
pub fn new(fcx: &'a FnCtxt<'a, 'tcx>,
initial_repeating_scope: RepeatingScope,
+ initial_body_id: ast::NodeId,
subject: SubjectNode) -> Rcx<'a, 'tcx> {
- let Repeating(initial_repeating_scope) = initial_repeating_scope;
+ let RepeatingScope(initial_repeating_scope) = initial_repeating_scope;
Rcx { fcx: fcx,
repeating_scope: initial_repeating_scope,
+ body_id: initial_body_id,
subject: subject,
region_bound_pairs: Vec::new()
}
self.fcx.ccx.tcx
}
- pub fn set_repeating_scope(&mut self, scope: ast::NodeId) -> ast::NodeId {
- let old_scope = self.repeating_scope;
- self.repeating_scope = scope;
- old_scope
+ fn set_body_id(&mut self, body_id: ast::NodeId) -> ast::NodeId {
+ mem::replace(&mut self.body_id, body_id)
+ }
+
+ fn set_repeating_scope(&mut self, scope: ast::NodeId) -> ast::NodeId {
+ mem::replace(&mut self.repeating_scope, scope)
}
/// Try to resolve the type for the given node, returning t_err if an error results. Note that
fn visit_fn_body(&mut self,
id: ast::NodeId,
fn_decl: &ast::FnDecl,
- body: &ast::Block)
+ body: &ast::Block,
+ span: Span)
{
// When we enter a function, we can derive
+ debug!("visit_fn_body(id={})", id);
let fn_sig_map = self.fcx.inh.fn_sig_map.borrow();
let fn_sig = match fn_sig_map.get(&id) {
};
let len = self.region_bound_pairs.len();
- self.relate_free_regions(&fn_sig[], body.id);
+ let old_body_id = self.set_body_id(body.id);
+ self.relate_free_regions(&fn_sig[], body.id, span);
link_fn_args(self, CodeExtent::from_node_id(body.id), &fn_decl.inputs[]);
self.visit_block(body);
self.visit_region_obligations(body.id);
self.region_bound_pairs.truncate(len);
+ self.set_body_id(old_body_id);
}
fn visit_region_obligations(&mut self, node_id: ast::NodeId)
{
debug!("visit_region_obligations: node_id={}", node_id);
+ // region checking can introduce new pending obligations
+ // which, when processed, might generate new region
+ // obligations. So make sure we process those.
+ vtable::select_all_fcx_obligations_or_error(self.fcx);
+
// Make a copy of the region obligations vec because we'll need
// to be able to borrow the fulfillment-cx below when projecting.
let region_obligations =
/// Tests: `src/test/compile-fail/regions-free-region-ordering-*.rs`
fn relate_free_regions(&mut self,
fn_sig_tys: &[Ty<'tcx>],
- body_id: ast::NodeId) {
+ body_id: ast::NodeId,
+ span: Span) {
debug!("relate_free_regions >>");
let tcx = self.tcx();
debug!("relate_free_regions(t={})", ty.repr(tcx));
let body_scope = CodeExtent::from_node_id(body_id);
let body_scope = ty::ReScope(body_scope);
- let constraints =
- regionmanip::region_wf_constraints(
- tcx,
- ty,
- body_scope);
- for constraint in &constraints {
- debug!("constraint: {}", constraint.repr(tcx));
- match *constraint {
- regionmanip::RegionSubRegionConstraint(_,
- ty::ReFree(free_a),
- ty::ReFree(free_b)) => {
+ let implications = implicator::implications(self.fcx.infcx(), self.fcx, body_id,
+ ty, body_scope, span);
+ for implication in implications {
+ debug!("implication: {}", implication.repr(tcx));
+ match implication {
+ implicator::Implication::RegionSubRegion(_,
+ ty::ReFree(free_a),
+ ty::ReFree(free_b)) => {
tcx.region_maps.relate_free_regions(free_a, free_b);
}
- regionmanip::RegionSubRegionConstraint(_,
- ty::ReFree(free_a),
- ty::ReInfer(ty::ReVar(vid_b))) => {
+ implicator::Implication::RegionSubRegion(_,
+ ty::ReFree(free_a),
+ ty::ReInfer(ty::ReVar(vid_b))) => {
self.fcx.inh.infcx.add_given(free_a, vid_b);
}
- regionmanip::RegionSubRegionConstraint(..) => {
+ implicator::Implication::RegionSubRegion(..) => {
// In principle, we could record (and take
// advantage of) every relationship here, but
// we are also free not to -- it simply means
// relationship that arises here, but
// presently we do not.)
}
- regionmanip::RegionSubGenericConstraint(_, r_a, ref generic_b) => {
- debug!("RegionSubGenericConstraint: {} <= {}",
+ implicator::Implication::RegionSubGeneric(_, r_a, ref generic_b) => {
+ debug!("RegionSubGeneric: {} <= {}",
r_a.repr(tcx), generic_b.repr(tcx));
self.region_bound_pairs.push((r_a, generic_b.clone()));
}
+ implicator::Implication::Predicate(..) => { }
}
}
}
// regions, until regionck, as described in #3238.
fn visit_fn(&mut self, _fk: visit::FnKind<'v>, fd: &'v ast::FnDecl,
- b: &'v ast::Block, _s: Span, id: ast::NodeId) {
- self.visit_fn_body(id, fd, b)
+ b: &'v ast::Block, span: Span, id: ast::NodeId) {
+ self.visit_fn_body(id, fd, b, span)
}
fn visit_item(&mut self, i: &ast::Item) { visit_item(self, i); }
constrain_call(rcx, expr, Some(&**base),
None::<ast::Expr>.iter(), true);
let fn_ret = // late-bound regions in overloaded method calls are instantiated
- ty::assert_no_late_bound_regions(rcx.tcx(), &ty::ty_fn_ret(method.ty));
+ ty::no_late_bound_regions(rcx.tcx(), &ty::ty_fn_ret(method.ty)).unwrap();
fn_ret.unwrap()
}
None => rcx.resolve_node_type(base.id)
// was applied on the base type, as that is always the case.
let fn_sig = ty::ty_fn_sig(method.ty);
let fn_sig = // late-bound regions should have been instantiated
- ty::assert_no_late_bound_regions(rcx.tcx(), fn_sig);
+ ty::no_late_bound_regions(rcx.tcx(), fn_sig).unwrap();
let self_ty = fn_sig.inputs[0];
let (m, r) = match self_ty.sty {
ty::ty_rptr(r, ref m) => (m.mutbl, r),
ty.repr(rcx.tcx()),
region.repr(rcx.tcx()));
- let constraints =
- regionmanip::region_wf_constraints(
- rcx.tcx(),
- ty,
- region);
- for constraint in &constraints {
- debug!("constraint: {}", constraint.repr(rcx.tcx()));
- match *constraint {
- regionmanip::RegionSubRegionConstraint(None, r_a, r_b) => {
+ let implications = implicator::implications(rcx.fcx.infcx(), rcx.fcx, rcx.body_id,
+ ty, region, origin.span());
+ for implication in implications {
+ debug!("implication: {}", implication.repr(rcx.tcx()));
+ match implication {
+ implicator::Implication::RegionSubRegion(None, r_a, r_b) => {
rcx.fcx.mk_subr(origin.clone(), r_a, r_b);
}
- regionmanip::RegionSubRegionConstraint(Some(ty), r_a, r_b) => {
+ implicator::Implication::RegionSubRegion(Some(ty), r_a, r_b) => {
let o1 = infer::ReferenceOutlivesReferent(ty, origin.span());
rcx.fcx.mk_subr(o1, r_a, r_b);
}
- regionmanip::RegionSubGenericConstraint(None, r_a, ref generic_b) => {
+ implicator::Implication::RegionSubGeneric(None, r_a, ref generic_b) => {
generic_must_outlive(rcx, origin.clone(), r_a, generic_b);
}
- regionmanip::RegionSubGenericConstraint(Some(ty), r_a, ref generic_b) => {
+ implicator::Implication::RegionSubGeneric(Some(ty), r_a, ref generic_b) => {
let o1 = infer::ReferenceOutlivesReferent(ty, origin.span());
generic_must_outlive(rcx, o1, r_a, generic_b);
}
+ implicator::Implication::Predicate(def_id, predicate) => {
+ let cause = traits::ObligationCause::new(origin.span(),
+ rcx.body_id,
+ traits::ItemObligation(def_id));
+ let obligation = traits::Obligation::new(cause, predicate);
+ rcx.fcx.register_predicate(obligation);
+ }
}
}
}
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// #![warn(deprecated_mode)]
-
-pub use self::WfConstraint::*;
-
-use astconv::object_region_bounds;
-use middle::infer::GenericKind;
-use middle::subst::{ParamSpace, Subst, Substs};
-use middle::ty::{self, Ty};
-use middle::ty_fold::{TypeFolder};
-
-use syntax::ast;
-
-use util::ppaux::Repr;
-
-// Helper functions related to manipulating region types.
-
-pub enum WfConstraint<'tcx> {
- RegionSubRegionConstraint(Option<Ty<'tcx>>, ty::Region, ty::Region),
- RegionSubGenericConstraint(Option<Ty<'tcx>>, ty::Region, GenericKind<'tcx>),
-}
-
-struct Wf<'a, 'tcx: 'a> {
- tcx: &'a ty::ctxt<'tcx>,
- stack: Vec<(ty::Region, Option<Ty<'tcx>>)>,
- out: Vec<WfConstraint<'tcx>>,
-}
-
-/// This routine computes the well-formedness constraints that must hold for the type `ty` to
-/// appear in a context with lifetime `outer_region`
-pub fn region_wf_constraints<'tcx>(
- tcx: &ty::ctxt<'tcx>,
- ty: Ty<'tcx>,
- outer_region: ty::Region)
- -> Vec<WfConstraint<'tcx>>
-{
- let mut stack = Vec::new();
- stack.push((outer_region, None));
- let mut wf = Wf { tcx: tcx,
- stack: stack,
- out: Vec::new() };
- wf.accumulate_from_ty(ty);
- wf.out
-}
-
-impl<'a, 'tcx> Wf<'a, 'tcx> {
- fn accumulate_from_ty(&mut self, ty: Ty<'tcx>) {
- debug!("Wf::accumulate_from_ty(ty={})",
- ty.repr(self.tcx));
-
- match ty.sty {
- ty::ty_bool |
- ty::ty_char |
- ty::ty_int(..) |
- ty::ty_uint(..) |
- ty::ty_float(..) |
- ty::ty_bare_fn(..) |
- ty::ty_err |
- ty::ty_str => {
- // No borrowed content reachable here.
- }
-
- ty::ty_closure(_, region, _) => {
- // An "closure type" is basically
- // modeled here as equivalent to a struct like
- //
- // struct TheClosure<'b> {
- // ...
- // }
- //
- // where the `'b` is the lifetime bound of the
- // contents (i.e., all contents must outlive 'b).
- //
- // Even though closures are glorified structs
- // of upvars, we do not need to consider them as they
- // can't generate any new constraints. The
- // substitutions on the closure are equal to the free
- // substitutions of the enclosing parameter
- // environment. An upvar captured by value has the
- // same type as the original local variable which is
- // already checked for consistency. If the upvar is
- // captured by reference it must also outlive the
- // region bound on the closure, but this is explicitly
- // handled by logic in regionck.
- self.push_region_constraint_from_top(*region);
- }
-
- ty::ty_trait(ref t) => {
- let required_region_bounds =
- object_region_bounds(self.tcx, &t.principal, t.bounds.builtin_bounds);
- self.accumulate_from_object_ty(ty, t.bounds.region_bound, required_region_bounds)
- }
-
- ty::ty_enum(def_id, substs) |
- ty::ty_struct(def_id, substs) => {
- let item_scheme = ty::lookup_item_type(self.tcx, def_id);
- self.accumulate_from_adt(ty, def_id, &item_scheme.generics, substs)
- }
-
- ty::ty_vec(t, _) |
- ty::ty_ptr(ty::mt { ty: t, .. }) |
- ty::ty_uniq(t) => {
- self.accumulate_from_ty(t)
- }
-
- ty::ty_rptr(r_b, mt) => {
- self.accumulate_from_rptr(ty, *r_b, mt.ty);
- }
-
- ty::ty_param(p) => {
- self.push_param_constraint_from_top(p);
- }
-
- ty::ty_projection(ref data) => {
- // `<T as TraitRef<..>>::Name`
-
- self.push_projection_constraint_from_top(data);
- }
-
- ty::ty_tup(ref tuptys) => {
- for &tupty in tuptys {
- self.accumulate_from_ty(tupty);
- }
- }
-
- ty::ty_infer(_) => {
- // This should not happen, BUT:
- //
- // Currently we uncover region relationships on
- // entering the fn check. We should do this after
- // the fn check, then we can call this case a bug().
- }
-
- ty::ty_open(_) => {
- self.tcx.sess.bug(
- &format!("Unexpected type encountered while doing wf check: {}",
- ty.repr(self.tcx))[]);
- }
- }
- }
-
- fn accumulate_from_rptr(&mut self,
- ty: Ty<'tcx>,
- r_b: ty::Region,
- ty_b: Ty<'tcx>) {
- // We are walking down a type like this, and current
- // position is indicated by caret:
- //
- // &'a &'b ty_b
- // ^
- //
- // At this point, top of stack will be `'a`. We must
- // require that `'a <= 'b`.
-
- self.push_region_constraint_from_top(r_b);
-
- // Now we push `'b` onto the stack, because it must
- // constrain any borrowed content we find within `T`.
-
- self.stack.push((r_b, Some(ty)));
- self.accumulate_from_ty(ty_b);
- self.stack.pop().unwrap();
- }
-
- /// Pushes a constraint that `r_b` must outlive the top region on the stack.
- fn push_region_constraint_from_top(&mut self,
- r_b: ty::Region) {
-
- // Indicates that we have found borrowed content with a lifetime
- // of at least `r_b`. This adds a constraint that `r_b` must
- // outlive the region `r_a` on top of the stack.
- //
- // As an example, imagine walking a type like:
- //
- // &'a &'b T
- // ^
- //
- // when we hit the inner pointer (indicated by caret), `'a` will
- // be on top of stack and `'b` will be the lifetime of the content
- // we just found. So we add constraint that `'a <= 'b`.
-
- let &(r_a, opt_ty) = self.stack.last().unwrap();
- self.push_sub_region_constraint(opt_ty, r_a, r_b);
- }
-
- /// Pushes a constraint that `r_a <= r_b`, due to `opt_ty`
- fn push_sub_region_constraint(&mut self,
- opt_ty: Option<Ty<'tcx>>,
- r_a: ty::Region,
- r_b: ty::Region) {
- self.out.push(RegionSubRegionConstraint(opt_ty, r_a, r_b));
- }
-
- /// Pushes a constraint that `param_ty` must outlive the top region on the stack.
- fn push_param_constraint_from_top(&mut self,
- param_ty: ty::ParamTy) {
- let &(region, opt_ty) = self.stack.last().unwrap();
- self.push_param_constraint(region, opt_ty, param_ty);
- }
-
- /// Pushes a constraint that `projection_ty` must outlive the top region on the stack.
- fn push_projection_constraint_from_top(&mut self,
- projection_ty: &ty::ProjectionTy<'tcx>) {
- let &(region, opt_ty) = self.stack.last().unwrap();
- self.out.push(RegionSubGenericConstraint(
- opt_ty, region, GenericKind::Projection(projection_ty.clone())));
- }
-
- /// Pushes a constraint that `region <= param_ty`, due to `opt_ty`
- fn push_param_constraint(&mut self,
- region: ty::Region,
- opt_ty: Option<Ty<'tcx>>,
- param_ty: ty::ParamTy) {
- self.out.push(RegionSubGenericConstraint(
- opt_ty, region, GenericKind::Param(param_ty)));
- }
-
- fn accumulate_from_adt(&mut self,
- ty: Ty<'tcx>,
- def_id: ast::DefId,
- generics: &ty::Generics<'tcx>,
- substs: &Substs<'tcx>)
- {
- // The generic declarations from the type, appropriately
- // substituted for the actual substitutions.
- let generics = generics.subst(self.tcx, substs);
-
- // Variance of each type/region parameter.
- let variances = ty::item_variances(self.tcx, def_id);
-
- for &space in &ParamSpace::all() {
- let region_params = substs.regions().get_slice(space);
- let region_variances = variances.regions.get_slice(space);
- let region_param_defs = generics.regions.get_slice(space);
- assert_eq!(region_params.len(), region_variances.len());
- for (®ion_param, (®ion_variance, region_param_def)) in
- region_params.iter().zip(
- region_variances.iter().zip(
- region_param_defs.iter()))
- {
- match region_variance {
- ty::Covariant | ty::Bivariant => {
- // Ignore covariant or bivariant region
- // parameters. To understand why, consider a
- // struct `Foo<'a>`. If `Foo` contains any
- // references with lifetime `'a`, then `'a` must
- // be at least contravariant (and possibly
- // invariant). The only way to have a covariant
- // result is if `Foo` contains only a field with a
- // type like `fn() -> &'a T`; i.e., a bare
- // function that can produce a reference of
- // lifetime `'a`. In this case, there is no
- // *actual data* with lifetime `'a` that is
- // reachable. (Presumably this bare function is
- // really returning static data.)
- }
-
- ty::Contravariant | ty::Invariant => {
- // If the parameter is contravariant or
- // invariant, there may indeed be reachable
- // data with this lifetime. See other case for
- // more details.
- self.push_region_constraint_from_top(region_param);
- }
- }
-
- for ®ion_bound in ®ion_param_def.bounds {
- // The type declared a constraint like
- //
- // 'b : 'a
- //
- // which means that `'a <= 'b` (after
- // substitution). So take the region we
- // substituted for `'a` (`region_bound`) and make
- // it a subregion of the region we substituted
- // `'b` (`region_param`).
- self.push_sub_region_constraint(
- Some(ty), region_bound, region_param);
- }
- }
-
- let types = substs.types.get_slice(space);
- let type_variances = variances.types.get_slice(space);
- let type_param_defs = generics.types.get_slice(space);
- assert_eq!(types.len(), type_variances.len());
- for (&type_param_ty, (&variance, type_param_def)) in
- types.iter().zip(
- type_variances.iter().zip(
- type_param_defs.iter()))
- {
- debug!("type_param_ty={} variance={}",
- type_param_ty.repr(self.tcx),
- variance.repr(self.tcx));
-
- match variance {
- ty::Contravariant | ty::Bivariant => {
- // As above, except that in this it is a
- // *contravariant* reference that indices that no
- // actual data of type T is reachable.
- }
-
- ty::Covariant | ty::Invariant => {
- self.accumulate_from_ty(type_param_ty);
- }
- }
-
- // Inspect bounds on this type parameter for any
- // region bounds.
- for &r in &type_param_def.bounds.region_bounds {
- self.stack.push((r, Some(ty)));
- self.accumulate_from_ty(type_param_ty);
- self.stack.pop().unwrap();
- }
- }
- }
- }
-
- fn accumulate_from_object_ty(&mut self,
- ty: Ty<'tcx>,
- region_bound: ty::Region,
- required_region_bounds: Vec<ty::Region>)
- {
- // Imagine a type like this:
- //
- // trait Foo { }
- // trait Bar<'c> : 'c { }
- //
- // &'b (Foo+'c+Bar<'d>)
- // ^
- //
- // In this case, the following relationships must hold:
- //
- // 'b <= 'c
- // 'd <= 'c
- //
- // The first conditions is due to the normal region pointer
- // rules, which say that a reference cannot outlive its
- // referent.
- //
- // The final condition may be a bit surprising. In particular,
- // you may expect that it would have been `'c <= 'd`, since
- // usually lifetimes of outer things are conservative
- // approximations for inner things. However, it works somewhat
- // differently with trait objects: here the idea is that if the
- // user specifies a region bound (`'c`, in this case) it is the
- // "master bound" that *implies* that bounds from other traits are
- // all met. (Remember that *all bounds* in a type like
- // `Foo+Bar+Zed` must be met, not just one, hence if we write
- // `Foo<'x>+Bar<'y>`, we know that the type outlives *both* 'x and
- // 'y.)
- //
- // Note: in fact we only permit builtin traits, not `Bar<'d>`, I
- // am looking forward to the future here.
-
- // The content of this object type must outlive
- // `bounds.region_bound`:
- let r_c = region_bound;
- self.push_region_constraint_from_top(r_c);
-
- // And then, in turn, to be well-formed, the
- // `region_bound` that user specified must imply the
- // region bounds required from all of the trait types:
- for &r_d in &required_region_bounds {
- // Each of these is an instance of the `'c <= 'b`
- // constraint above
- self.out.push(RegionSubRegionConstraint(Some(ty), r_d, r_c));
- }
- }
-}
-
-impl<'tcx> Repr<'tcx> for WfConstraint<'tcx> {
- fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
- match *self {
- RegionSubRegionConstraint(_, ref r_a, ref r_b) => {
- format!("RegionSubRegionConstraint({}, {})",
- r_a.repr(tcx),
- r_b.repr(tcx))
- }
-
- RegionSubGenericConstraint(_, ref r, ref p) => {
- format!("RegionSubGenericConstraint({}, {})",
- r.repr(tcx),
- p.repr(tcx))
- }
- }
- }
-}
self.check_item_type(item);
}
ast::ItemStruct(ref struct_def, _) => {
- self.check_type_defn(item, |fcx| {
- vec![struct_variant(fcx, &**struct_def)]
- });
+ self.check_type_defn(item, |fcx| vec![struct_variant(fcx, &**struct_def)]);
}
ast::ItemEnum(ref enum_def, _) => {
- self.check_type_defn(item, |fcx| {
- enum_variants(fcx, enum_def)
- });
+ self.check_type_defn(item, |fcx| enum_variants(fcx, enum_def));
}
ast::ItemTrait(..) => {
let trait_predicates =
// the regions in the argument types come from the
// enum def'n, and hence will all be early bound
let arg_tys =
- ty::assert_no_late_bound_regions(
- fcx.tcx(), &ty::ty_fn_args(ctor_ty));
+ ty::no_late_bound_regions(
+ fcx.tcx(), &ty::ty_fn_args(ctor_ty)).unwrap();
AdtVariant {
fields: args.iter().enumerate().map(|(index, arg)| {
let arg_ty = arg_tys[index];
#![feature(env)]
#![feature(hash)]
#![feature(int_uint)]
-#![feature(io)]
+#![feature(old_io)]
#![feature(libc)]
#![feature(os)]
-#![feature(path)]
+#![feature(old_path)]
#![feature(rustc_private)]
#![feature(staged_api)]
#![feature(std_misc)]
#![feature(test)]
#![feature(unicode)]
+#![feature(str_words)]
extern crate arena;
extern crate getopts;
use std::old_io::File;
use std::old_io;
use std::rc::Rc;
+use std::sync::mpsc::channel;
use externalfiles::ExternalHtml;
use serialize::Decodable;
use serialize::json::{self, Json};
let res = std::thread::Builder::new().stack_size(STACK_SIZE).scoped(move || {
let s = env::args().collect::<Vec<_>>();
main_args(&s)
- }).join();
- env::set_exit_status(res.ok().unwrap() as i32);
+ }).unwrap().join();
+ env::set_exit_status(res as i32);
}
pub fn opts() -> Vec<getopts::OptGroup> {
let cr = Path::new(cratefile);
info!("starting to run rustc");
- let (mut krate, analysis) = std::thread::Thread::scoped(move || {
+ let (tx, rx) = channel();
+ std::thread::spawn(move || {
use rustc::session::config::Input;
let cr = cr;
- core::run_core(paths, cfgs, externs, Input::File(cr), triple)
+ tx.send(core::run_core(paths, cfgs, externs, Input::File(cr), triple)).unwrap();
}).join().map_err(|_| "rustc failed").unwrap();
+ let (mut krate, analysis) = rx.recv().unwrap();
info!("finished with rustc");
let mut analysis = Some(analysis);
ANALYSISKEY.with(|s| {
let mut a: Vec<clean::Attribute> = i.attrs.iter().filter(|&a| match a {
&clean::NameValue(ref x, _) if "doc" == *x => false,
_ => true
- }).map(|x| x.clone()).collect();
+ }).cloned().collect();
if docstr.len() > 0 {
a.push(clean::NameValue("doc".to_string(), docstr));
}
use std::old_io;
use std::env;
use std::str;
-use std::thread::Thread;
+use std::thread;
use std::thunk::Thunk;
use std::collections::{HashSet, HashMap};
let w1 = old_io::ChanWriter::new(tx);
let w2 = w1.clone();
let old = old_io::stdio::set_stderr(box w1);
- Thread::spawn(move || {
+ thread::spawn(move || {
let mut p = old_io::ChanReader::new(rx);
let mut err = match old {
Some(old) => {
name: name,
items: items.clone(),
generics: gen.clone(),
- bounds: b.iter().map(|x| (*x).clone()).collect(),
+ bounds: b.iter().cloned().collect(),
id: item.id,
attrs: item.attrs.clone(),
whence: item.span,
pub type EncodeResult = Result<(), EncoderError>;
pub type DecodeResult<T> = Result<T, DecoderError>;
-fn escape_str(wr: &mut fmt::Writer, v: &str) -> EncodeResult {
+fn escape_str(wr: &mut fmt::Write, v: &str) -> EncodeResult {
try!(wr.write_str("\""));
let mut start = 0;
Ok(())
}
-fn escape_char(writer: &mut fmt::Writer, v: char) -> EncodeResult {
+fn escape_char(writer: &mut fmt::Write, v: char) -> EncodeResult {
let mut buf = [0; 4];
let n = v.encode_utf8(&mut buf).unwrap();
let buf = unsafe { str::from_utf8_unchecked(&buf[..n]) };
escape_str(writer, buf)
}
-fn spaces(wr: &mut fmt::Writer, mut n: uint) -> EncodeResult {
+fn spaces(wr: &mut fmt::Write, mut n: uint) -> EncodeResult {
const BUF: &'static str = " ";
while n >= BUF.len() {
/// A structure for implementing serialization to JSON.
pub struct Encoder<'a> {
- writer: &'a mut (fmt::Writer+'a),
+ writer: &'a mut (fmt::Write+'a),
is_emitting_map_key: bool,
}
impl<'a> Encoder<'a> {
/// Creates a new JSON encoder whose output will be written to the writer
/// specified.
- pub fn new(writer: &'a mut fmt::Writer) -> Encoder<'a> {
+ pub fn new(writer: &'a mut fmt::Write) -> Encoder<'a> {
Encoder { writer: writer, is_emitting_map_key: false, }
}
}
/// Another encoder for JSON, but prints out human-readable JSON instead of
/// compact data
pub struct PrettyEncoder<'a> {
- writer: &'a mut (fmt::Writer+'a),
+ writer: &'a mut (fmt::Write+'a),
curr_indent: uint,
indent: uint,
is_emitting_map_key: bool,
impl<'a> PrettyEncoder<'a> {
/// Creates a new encoder whose output will be written to the specified writer
- pub fn new(writer: &'a mut fmt::Writer) -> PrettyEncoder<'a> {
+ pub fn new(writer: &'a mut fmt::Write) -> PrettyEncoder<'a> {
PrettyEncoder {
writer: writer,
curr_indent: 0,
inner: &'a mut fmt::Formatter<'b>,
}
-impl<'a, 'b> fmt::Writer for FormatShim<'a, 'b> {
+impl<'a, 'b> fmt::Write for FormatShim<'a, 'b> {
fn write_str(&mut self, s: &str) -> fmt::Result {
match self.inner.write_str(s) {
Ok(_) => Ok(()),
#![feature(collections)]
#![feature(core)]
#![feature(int_uint)]
-#![feature(io)]
-#![feature(path)]
+#![feature(old_io)]
+#![feature(old_path)]
#![feature(hash)]
#![feature(rustc_private)]
#![feature(staged_api)]
//! Operations on ASCII strings and characters
-#![unstable(feature = "std_misc",
- reason = "unsure about placement and naming")]
+#![stable(feature = "rust1", since = "1.0.0")]
-use iter::IteratorExt;
-use ops::FnMut;
-use slice::SliceExt;
-use str::StrExt;
-use string::String;
-use vec::Vec;
+use prelude::v1::*;
+
+use mem;
+use iter::Range;
/// Extension methods for ASCII-subset only operations on owned strings
#[unstable(feature = "std_misc",
}
/// Extension methods for ASCII-subset only operations on string slices
-#[unstable(feature = "std_misc",
- reason = "would prefer to do this in a more general way")]
-pub trait AsciiExt<T = Self> {
+#[stable(feature = "rust1", since = "1.0.0")]
+pub trait AsciiExt {
+ #[stable(feature = "rust1", since = "1.0.0")]
+ type Owned;
+
/// Check if within the ASCII range.
+ #[stable(feature = "rust1", since = "1.0.0")]
fn is_ascii(&self) -> bool;
/// Makes a copy of the string in ASCII upper case:
/// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
/// but non-ASCII letters are unchanged.
- fn to_ascii_uppercase(&self) -> T;
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn to_ascii_uppercase(&self) -> Self::Owned;
/// Makes a copy of the string in ASCII lower case:
/// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
/// but non-ASCII letters are unchanged.
- fn to_ascii_lowercase(&self) -> T;
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn to_ascii_lowercase(&self) -> Self::Owned;
/// Check that two strings are an ASCII case-insensitive match.
/// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`,
/// but without allocating and copying temporary strings.
+ #[stable(feature = "rust1", since = "1.0.0")]
fn eq_ignore_ascii_case(&self, other: &Self) -> bool;
+
+ /// Convert this type to its ASCII upper case equivalent in-place.
+ ///
+ /// See `to_ascii_uppercase` for more information.
+ #[unstable(feature = "ascii")]
+ fn make_ascii_uppercase(&mut self);
+
+ /// Convert this type to its ASCII lower case equivalent in-place.
+ ///
+ /// See `to_ascii_lowercase` for more information.
+ #[unstable(feature = "ascii")]
+ fn make_ascii_lowercase(&mut self);
}
-#[unstable(feature = "std_misc",
- reason = "would prefer to do this in a more general way")]
-impl AsciiExt<String> for str {
+#[stable(feature = "rust1", since = "1.0.0")]
+impl AsciiExt for str {
+ type Owned = String;
+
#[inline]
fn is_ascii(&self) -> bool {
self.bytes().all(|b| b.is_ascii())
#[inline]
fn to_ascii_uppercase(&self) -> String {
- // Vec<u8>::to_ascii_uppercase() preserves the UTF-8 invariant.
- unsafe { String::from_utf8_unchecked(self.as_bytes().to_ascii_uppercase()) }
+ self.to_string().into_ascii_uppercase()
}
#[inline]
fn to_ascii_lowercase(&self) -> String {
- // Vec<u8>::to_ascii_lowercase() preserves the UTF-8 invariant.
- unsafe { String::from_utf8_unchecked(self.as_bytes().to_ascii_lowercase()) }
+ self.to_string().into_ascii_lowercase()
}
#[inline]
fn eq_ignore_ascii_case(&self, other: &str) -> bool {
self.as_bytes().eq_ignore_ascii_case(other.as_bytes())
}
+
+ fn make_ascii_uppercase(&mut self) {
+ let me: &mut [u8] = unsafe { mem::transmute(self) };
+ me.make_ascii_uppercase()
+ }
+
+ fn make_ascii_lowercase(&mut self) {
+ let me: &mut [u8] = unsafe { mem::transmute(self) };
+ me.make_ascii_lowercase()
+ }
}
#[unstable(feature = "std_misc",
}
}
-#[unstable(feature = "std_misc",
- reason = "would prefer to do this in a more general way")]
-impl AsciiExt<Vec<u8>> for [u8] {
+#[stable(feature = "rust1", since = "1.0.0")]
+impl AsciiExt for [u8] {
+ type Owned = Vec<u8>;
#[inline]
fn is_ascii(&self) -> bool {
self.iter().all(|b| b.is_ascii())
#[inline]
fn to_ascii_uppercase(&self) -> Vec<u8> {
- self.iter().map(|b| b.to_ascii_uppercase()).collect()
+ self.to_vec().into_ascii_uppercase()
}
#[inline]
fn to_ascii_lowercase(&self) -> Vec<u8> {
- self.iter().map(|b| b.to_ascii_lowercase()).collect()
+ self.to_vec().into_ascii_lowercase()
}
#[inline]
a.eq_ignore_ascii_case(b)
})
}
+
+ fn make_ascii_uppercase(&mut self) {
+ for byte in self {
+ byte.make_ascii_uppercase();
+ }
+ }
+
+ fn make_ascii_lowercase(&mut self) {
+ for byte in self {
+ byte.make_ascii_lowercase();
+ }
+ }
}
#[unstable(feature = "std_misc",
impl OwnedAsciiExt for Vec<u8> {
#[inline]
fn into_ascii_uppercase(mut self) -> Vec<u8> {
- for byte in &mut self {
- *byte = byte.to_ascii_uppercase();
- }
+ self.make_ascii_uppercase();
self
}
#[inline]
fn into_ascii_lowercase(mut self) -> Vec<u8> {
- for byte in &mut self {
- *byte = byte.to_ascii_lowercase();
- }
+ self.make_ascii_lowercase();
self
}
}
-#[unstable(feature = "std_misc",
- reason = "would prefer to do this in a more general way")]
+#[stable(feature = "rust1", since = "1.0.0")]
impl AsciiExt for u8 {
+ type Owned = u8;
#[inline]
- fn is_ascii(&self) -> bool {
- *self & 128 == 0u8
- }
-
+ fn is_ascii(&self) -> bool { *self & 128 == 0u8 }
#[inline]
- fn to_ascii_uppercase(&self) -> u8 {
- ASCII_UPPERCASE_MAP[*self as usize]
- }
-
+ fn to_ascii_uppercase(&self) -> u8 { ASCII_UPPERCASE_MAP[*self as usize] }
#[inline]
- fn to_ascii_lowercase(&self) -> u8 {
- ASCII_LOWERCASE_MAP[*self as usize]
- }
-
+ fn to_ascii_lowercase(&self) -> u8 { ASCII_LOWERCASE_MAP[*self as usize] }
#[inline]
fn eq_ignore_ascii_case(&self, other: &u8) -> bool {
self.to_ascii_lowercase() == other.to_ascii_lowercase()
}
+ #[inline]
+ fn make_ascii_uppercase(&mut self) { *self = self.to_ascii_uppercase(); }
+ #[inline]
+ fn make_ascii_lowercase(&mut self) { *self = self.to_ascii_lowercase(); }
}
-#[unstable(feature = "std_misc",
- reason = "would prefer to do this in a more general way")]
+#[stable(feature = "rust1", since = "1.0.0")]
impl AsciiExt for char {
+ type Owned = char;
#[inline]
fn is_ascii(&self) -> bool {
*self as u32 <= 0x7F
fn eq_ignore_ascii_case(&self, other: &char) -> bool {
self.to_ascii_lowercase() == other.to_ascii_lowercase()
}
+
+ #[inline]
+ fn make_ascii_uppercase(&mut self) { *self = self.to_ascii_uppercase(); }
+ #[inline]
+ fn make_ascii_lowercase(&mut self) { *self = self.to_ascii_lowercase(); }
+}
+
+/// An iterator over the escaped version of a byte, constructed via
+/// `std::ascii::escape_default`.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct EscapeDefault {
+ range: Range<usize>,
+ data: [u8; 4],
}
/// Returns a 'default' ASCII and C++11-like literal escape of a `u8`
/// - Tab, CR and LF are escaped as '\t', '\r' and '\n' respectively.
/// - Single-quote, double-quote and backslash chars are backslash-escaped.
/// - Any other chars in the range [0x20,0x7e] are not escaped.
-/// - Any other chars are given hex escapes.
+/// - Any other chars are given hex escapes of the form '\xNN'.
/// - Unicode escapes are never generated by this function.
-#[unstable(feature = "std_misc",
- reason = "needs to be updated to use an iterator")]
-pub fn escape_default<F>(c: u8, mut f: F) where
- F: FnMut(u8),
-{
- match c {
- b'\t' => { f(b'\\'); f(b't'); }
- b'\r' => { f(b'\\'); f(b'r'); }
- b'\n' => { f(b'\\'); f(b'n'); }
- b'\\' => { f(b'\\'); f(b'\\'); }
- b'\'' => { f(b'\\'); f(b'\''); }
- b'"' => { f(b'\\'); f(b'"'); }
- b'\x20' ... b'\x7e' => { f(c); }
- _ => {
- f(b'\\');
- f(b'x');
- for &offset in &[4u, 0u] {
- match ((c as i32) >> offset) & 0xf {
- i @ 0 ... 9 => f(b'0' + (i as u8)),
- i => f(b'a' + (i as u8 - 10)),
- }
- }
+#[stable(feature = "rust1", since = "1.0.0")]
+pub fn escape_default(c: u8) -> EscapeDefault {
+ let (data, len) = match c {
+ b'\t' => ([b'\\', b't', 0, 0], 2),
+ b'\r' => ([b'\\', b'r', 0, 0], 2),
+ b'\n' => ([b'\\', b'n', 0, 0], 2),
+ b'\\' => ([b'\\', b'\\', 0, 0], 2),
+ b'\'' => ([b'\\', b'\'', 0, 0], 2),
+ b'"' => ([b'\\', b'"', 0, 0], 2),
+ b'\x20' ... b'\x7e' => ([c, 0, 0, 0], 1),
+ _ => ([b'\\', b'x', hexify(c >> 4), hexify(c & 0xf)], 4),
+ };
+
+ return EscapeDefault { range: range(0, len), data: data };
+
+ fn hexify(b: u8) -> u8 {
+ match b {
+ 0 ... 9 => b'0' + b,
+ _ => b'a' + b - 10,
}
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Iterator for EscapeDefault {
+ type Item = u8;
+ fn next(&mut self) -> Option<u8> { self.range.next().map(|i| self.data[i]) }
+ fn size_hint(&self) -> (usize, Option<usize>) { self.range.size_hint() }
+}
+#[stable(feature = "rust1", since = "1.0.0")]
+impl DoubleEndedIterator for EscapeDefault {
+ fn next_back(&mut self) -> Option<u8> {
+ self.range.next_back().map(|i| self.data[i])
+ }
+}
+#[stable(feature = "rust1", since = "1.0.0")]
+impl ExactSizeIterator for EscapeDefault {}
+
static ASCII_LOWERCASE_MAP: [u8; 256] = [
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
NoElem(EmptyBucket<K, V, M>),
}
-// NOTE(stage0): remove impl after a snapshot
-#[cfg(stage0)]
-impl<'a, K, V, S, H> IntoIterator for &'a HashMap<K, V, S>
- where K: Eq + Hash<H>,
- S: HashState<Hasher=H>,
- H: hash::Hasher<Output=u64>
-{
- type IntoIter = Iter<'a, K, V>;
-
- fn into_iter(self) -> Iter<'a, K, V> {
- self.iter()
- }
-}
-
-#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
+#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, K, V, S, H> IntoIterator for &'a HashMap<K, V, S>
where K: Eq + Hash<H>,
S: HashState<Hasher=H>,
}
}
-// NOTE(stage0): remove impl after a snapshot
-#[cfg(stage0)]
-impl<'a, K, V, S, H> IntoIterator for &'a mut HashMap<K, V, S>
- where K: Eq + Hash<H>,
- S: HashState<Hasher=H>,
- H: hash::Hasher<Output=u64>
-{
- type IntoIter = IterMut<'a, K, V>;
-
- fn into_iter(mut self) -> IterMut<'a, K, V> {
- self.iter_mut()
- }
-}
-
-#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
+#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, K, V, S, H> IntoIterator for &'a mut HashMap<K, V, S>
where K: Eq + Hash<H>,
S: HashState<Hasher=H>,
}
}
-// NOTE(stage0): remove impl after a snapshot
-#[cfg(stage0)]
-impl<K, V, S, H> IntoIterator for HashMap<K, V, S>
- where K: Eq + Hash<H>,
- S: HashState<Hasher=H>,
- H: hash::Hasher<Output=u64>
-{
- type IntoIter = IntoIter<K, V>;
-
- fn into_iter(self) -> IntoIter<K, V> {
- self.into_iter()
- }
-}
-
-#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
+#[stable(feature = "rust1", since = "1.0.0")]
impl<K, V, S, H> IntoIterator for HashMap<K, V, S>
where K: Eq + Hash<H>,
S: HashState<Hasher=H>,
iter: Chain<Iter<'a, T>, Difference<'a, T, S>>
}
-// NOTE(stage0): remove impl after a snapshot
-#[cfg(stage0)]
-impl<'a, T, S, H> IntoIterator for &'a HashSet<T, S>
- where T: Eq + Hash<H>,
- S: HashState<Hasher=H>,
- H: hash::Hasher<Output=u64>
-{
- type IntoIter = Iter<'a, T>;
-
- fn into_iter(self) -> Iter<'a, T> {
- self.iter()
- }
-}
-
-#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
+#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T, S, H> IntoIterator for &'a HashSet<T, S>
where T: Eq + Hash<H>,
S: HashState<Hasher=H>,
}
}
-// NOTE(stage0): remove impl after a snapshot
-#[cfg(stage0)]
-impl<T, S, H> IntoIterator for HashSet<T, S>
- where T: Eq + Hash<H>,
- S: HashState<Hasher=H>,
- H: hash::Hasher<Output=u64>
-{
- type IntoIter = IntoIter<T>;
-
- fn into_iter(self) -> IntoIter<T> {
- self.into_iter()
- }
-}
-
-#[cfg(not(stage0))] // NOTE(stage0): remove cfg after a snapshot
+#[stable(feature = "rust1", since = "1.0.0")]
impl<T, S, H> IntoIterator for HashSet<T, S>
where T: Eq + Hash<H>,
S: HashState<Hasher=H>,
fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
}
+impl ExactSizeIterator for Args {
+ fn len(&self) -> usize { self.inner.len() }
+}
+
impl Iterator for ArgsOs {
type Item = OsString;
fn next(&mut self) -> Option<OsString> { self.inner.next() }
fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
}
+impl ExactSizeIterator for ArgsOs {
+ fn len(&self) -> usize { self.inner.len() }
+}
+
/// Returns the page size of the current architecture in bytes.
pub fn page_size() -> usize {
os_imp::page_size()
#[cfg(unix)]
fn join_paths_unix() {
fn test_eq(input: &[&str], output: &str) -> bool {
- &*join_paths(input.iter().map(|s| *s)).unwrap() ==
+ &*join_paths(input.iter().cloned()).unwrap() ==
OsStr::from_str(output)
}
"/bin:/usr/bin:/usr/local/bin"));
assert!(test_eq(&["", "/bin", "", "", "/usr/bin", ""],
":/bin:::/usr/bin:"));
- assert!(join_paths(["/te:st"].iter().map(|s| *s)).is_err());
+ assert!(join_paths(["/te:st"].iter().cloned()).is_err());
}
#[test]
#[cfg(windows)]
fn join_paths_windows() {
fn test_eq(input: &[&str], output: &str) -> bool {
- &*join_paths(input.iter().map(|s| *s)).unwrap() ==
+ &*join_paths(input.iter().cloned()).unwrap() ==
OsStr::from_str(output)
}
r";c:\windows;;;c:\;"));
assert!(test_eq(&[r"c:\te;st", r"c:\"],
r#""c:\te;st";c:\"#));
- assert!(join_paths([r#"c:\te"st"#].iter().map(|s| *s)).is_err());
+ assert!(join_paths([r#"c:\te"st"#].iter().cloned()).is_err());
}
}
/// Open a file in write-only mode.
///
- /// This function will create a file it it does not exist,
+ /// This function will create a file if it does not exist,
/// and will truncate it if it does.
///
/// See the `OpenOptions::open` function for more details.
///
/// This function will return any I/O error reported while formatting.
fn write_fmt(&mut self, fmt: fmt::Arguments) -> Result<()> {
- // Create a shim which translates a Writer to a fmt::Writer and saves
+ // Create a shim which translates a Write to a fmt::Write and saves
// off I/O errors. instead of discarding them
struct Adaptor<'a, T: ?Sized + 'a> {
inner: &'a mut T,
error: Result<()>,
}
- impl<'a, T: Write + ?Sized> fmt::Writer for Adaptor<'a, T> {
+ impl<'a, T: Write + ?Sized> fmt::Write for Adaptor<'a, T> {
fn write_str(&mut self, s: &str) -> fmt::Result {
match self.inner.write_all(s.as_bytes()) {
Ok(()) => Ok(()),
/// A seek beyond the end of a stream is allowed, but seeking before offset
/// 0 is an error.
///
- /// Seeking past the end of the stream does not modify the underlying
- /// stream, but the next write may cause the previous data to be filled in
- /// with a bit pattern.
+ /// The behavior when seeking past the end of the stream is implementation
+ /// defined.
///
/// This method returns the new position within the stream if the seek
/// operation completed successfully.
// can be resolved within libstd.
#[doc(hidden)]
mod std {
- // NOTE: remove after next snapshot
- // mods used for deriving
- #[cfg(stage0)] pub use clone;
- #[cfg(stage0)] pub use cmp;
- #[cfg(stage0)] pub use hash;
- #[cfg(stage0)] pub use default;
-
pub use sync; // used for select!()
pub use error; // used for try!()
pub use fmt; // used for any formatting strings
pub use slice;
pub use boxed; // used for vec![]
- // for-loops
- // NOTE: remove after next snapshot
- #[cfg(stage0)] pub use iter;
}
});
}
-/// Use the syntax described in `std::fmt` to create a value of type `String`.
-/// See `std::fmt` for more information.
-///
-/// # Example
-///
-/// ```
-/// format!("test");
-/// format!("hello {}", "world!");
-/// format!("x = {}, y = {y}", 10, y = 30);
-/// ```
-#[cfg(stage0)] // NOTE: remove after snapshot
-#[macro_export]
-#[stable(feature = "rust1", since = "1.0.0")]
-macro_rules! format {
- ($($arg:tt)*) => ($crate::fmt::format(format_args!($($arg)*)))
-}
-
/// Equivalent to the `println!` macro except that a newline is not printed at
/// the end of the message.
#[macro_export]
/// # Examples
///
/// ```
-/// use std::thread::Thread;
+/// use std::thread;
/// use std::sync::mpsc;
///
/// // two placeholder functions for now
/// let (tx1, rx1) = mpsc::channel();
/// let (tx2, rx2) = mpsc::channel();
///
-/// Thread::spawn(move|| { long_running_task(); tx1.send(()).unwrap(); });
-/// Thread::spawn(move|| { tx2.send(calculate_the_answer()).unwrap(); });
+/// thread::spawn(move|| { long_running_task(); tx1.send(()).unwrap(); });
+/// thread::spawn(move|| { tx2.send(calculate_the_answer()).unwrap(); });
///
/// select! (
/// _ = rx1.recv() => println!("the long running task finished first"),
///
/// ```no_run
/// use std::net::{TcpListener, TcpStream};
-/// use std::thread::Thread;
+/// use std::thread;
///
/// let listener = TcpListener::bind("127.0.0.1:80").unwrap();
///
/// for stream in listener.incoming() {
/// match stream {
/// Ok(stream) => {
-/// Thread::spawn(move|| {
+/// thread::spawn(move|| {
/// // connection succeeded
/// handle_client(stream)
/// });
use net::*;
use net::test::{next_test_ip4, next_test_ip6};
use sync::mpsc::channel;
- use thread::Thread;
+ use thread;
fn each_ip(f: &mut FnMut(SocketAddr)) {
f(next_test_ip4());
fn connect_error() {
match TcpStream::connect("0.0.0.0:1") {
Ok(..) => panic!(),
- Err(e) => assert_eq!(e.kind(), ErrorKind::ConnectionRefused),
+ Err(e) => assert!((e.kind() == ErrorKind::ConnectionRefused)
+ || (e.kind() == ErrorKind::InvalidInput)),
}
}
let socket_addr = next_test_ip4();
let listener = t!(TcpListener::bind(&socket_addr));
- let _t = Thread::scoped(move || {
+ let _t = thread::spawn(move || {
let mut stream = t!(TcpStream::connect(&("localhost",
socket_addr.port())));
t!(stream.write(&[144]));
let addr = next_test_ip4();
let acceptor = t!(TcpListener::bind(&addr));
- let _t = Thread::scoped(move|| {
+ let _t = thread::spawn(move|| {
let mut stream = t!(TcpStream::connect(&("127.0.0.1", addr.port())));
t!(stream.write(&[44]));
});
let addr = next_test_ip6();
let acceptor = t!(TcpListener::bind(&addr));
- let _t = Thread::scoped(move|| {
+ let _t = thread::spawn(move|| {
let mut stream = t!(TcpStream::connect(&("::1", addr.port())));
t!(stream.write(&[66]));
});
let acceptor = t!(TcpListener::bind(&addr));
let (tx, rx) = channel();
- let _t = Thread::scoped(move|| {
+ let _t = thread::spawn(move|| {
let mut stream = t!(TcpStream::connect(&addr));
t!(stream.write(&[99]));
tx.send(t!(stream.socket_addr())).unwrap();
each_ip(&mut |addr| {
let acceptor = t!(TcpListener::bind(&addr));
- let _t = Thread::scoped(move|| {
+ let _t = thread::spawn(move|| {
let _stream = t!(TcpStream::connect(&addr));
// Close
});
let acceptor = t!(TcpListener::bind(&addr));
let (tx, rx) = channel();
- let _t = Thread::scoped(move|| {
+ let _t = thread::spawn(move|| {
drop(t!(TcpStream::connect(&addr)));
tx.send(()).unwrap();
});
let max = 10;
let acceptor = t!(TcpListener::bind(&addr));
- let _t = Thread::scoped(move|| {
+ let _t = thread::spawn(move|| {
for _ in 0..max {
let mut stream = t!(TcpStream::connect(&addr));
t!(stream.write(&[99]));
each_ip(&mut |addr| {
let acceptor = t!(TcpListener::bind(&addr));
- let _t = Thread::scoped(move|| {
+ let _t = thread::spawn(move|| {
let acceptor = acceptor;
for (i, stream) in acceptor.incoming().enumerate().take(MAX) {
// Start another task to handle the connection
- let _t = Thread::scoped(move|| {
+ let _t = thread::spawn(move|| {
let mut stream = t!(stream);
let mut buf = [0];
t!(stream.read(&mut buf));
fn connect(i: usize, addr: SocketAddr) {
if i == MAX { return }
- let t = Thread::scoped(move|| {
+ let t = thread::spawn(move|| {
let mut stream = t!(TcpStream::connect(&addr));
// Connect again before writing
connect(i + 1, addr);
each_ip(&mut |addr| {
let acceptor = t!(TcpListener::bind(&addr));
- let _t = Thread::scoped(move|| {
+ let _t = thread::spawn(move|| {
for stream in acceptor.incoming().take(MAX) {
// Start another task to handle the connection
- let _t = Thread::scoped(move|| {
+ let _t = thread::spawn(move|| {
let mut stream = t!(stream);
let mut buf = [0];
t!(stream.read(&mut buf));
fn connect(i: usize, addr: SocketAddr) {
if i == MAX { return }
- let t = Thread::scoped(move|| {
+ let t = thread::spawn(move|| {
let mut stream = t!(TcpStream::connect(&addr));
connect(i + 1, addr);
t!(stream.write(&[99]));
let listener = t!(TcpListener::bind(&addr));
let so_name = t!(listener.socket_addr());
assert_eq!(addr, so_name);
- let _t = Thread::scoped(move|| {
+ let _t = thread::spawn(move|| {
t!(listener.accept());
});
each_ip(&mut |addr| {
let (tx, rx) = channel();
let srv = t!(TcpListener::bind(&addr));
- let _t = Thread::scoped(move|| {
+ let _t = thread::spawn(move|| {
let mut cl = t!(srv.accept()).0;
cl.write(&[10]).unwrap();
let mut b = [0];
each_ip(&mut |addr| {
let acceptor = t!(TcpListener::bind(&addr));
- let _t = Thread::scoped(move|| {
+ let _t = thread::spawn(move|| {
t!(TcpStream::connect(&addr));
});
each_ip(&mut |addr| {
let acceptor = t!(TcpListener::bind(&addr));
- let _t = Thread::scoped(move|| {
+ let _t = thread::spawn(move|| {
let mut s = t!(TcpStream::connect(&addr));
let mut buf = [0, 0];
assert_eq!(s.read(&mut buf), Ok(1));
let (tx1, rx1) = channel();
let (tx2, rx2) = channel();
- let _t = Thread::scoped(move|| {
+ let _t = thread::spawn(move|| {
let mut s2 = s2;
rx1.recv().unwrap();
t!(s2.write(&[1]));
let (tx1, rx) = channel();
let tx2 = tx1.clone();
- let _t = Thread::scoped(move|| {
+ let _t = thread::spawn(move|| {
let mut s = t!(TcpStream::connect(&addr));
t!(s.write(&[1]));
rx.recv().unwrap();
let s2 = t!(s1.try_clone());
let (done, rx) = channel();
- let _t = Thread::scoped(move|| {
+ let _t = thread::spawn(move|| {
let mut s2 = s2;
let mut buf = [0, 0];
t!(s2.read(&mut buf));
each_ip(&mut |addr| {
let acceptor = t!(TcpListener::bind(&addr));
- let _t = Thread::scoped(move|| {
+ let _t = thread::spawn(move|| {
let mut s = t!(TcpStream::connect(&addr));
let mut buf = [0, 1];
t!(s.read(&mut buf));
let s2 = t!(s1.try_clone());
let (done, rx) = channel();
- let _t = Thread::scoped(move|| {
+ let _t = thread::spawn(move|| {
let mut s2 = s2;
t!(s2.write(&[1]));
done.send(()).unwrap();
fn shutdown_smoke() {
each_ip(&mut |addr| {
let a = t!(TcpListener::bind(&addr));
- let _t = Thread::scoped(move|| {
+ let _t = thread::spawn(move|| {
let mut c = t!(a.accept()).0;
let mut b = [0];
assert_eq!(c.read(&mut b), Ok(0));
each_ip(&mut |addr| {
let a = t!(TcpListener::bind(&addr));
let (tx, rx) = channel::<()>();
- let _t = Thread::scoped(move|| {
+ let _t = thread::spawn(move|| {
let _s = t!(a.accept());
let _ = rx.recv();
});
each_ip(&mut |addr| {
let a = t!(TcpListener::bind(&addr));
let (tx1, rx) = channel::<()>();
- let _t = Thread::scoped(move|| {
+ let _t = thread::spawn(move|| {
let _s = t!(a.accept());
let _ = rx.recv();
});
let s = t!(TcpStream::connect(&addr));
let s2 = t!(s.try_clone());
let (tx, rx) = channel();
- let _t = Thread::scoped(move|| {
+ let _t = thread::spawn(move|| {
let mut s2 = s2;
assert_eq!(t!(s2.read(&mut [0])), 0);
tx.send(()).unwrap();
let (tx, rx) = channel();
let (txdone, rxdone) = channel();
let txdone2 = txdone.clone();
- let _t = Thread::scoped(move|| {
+ let _t = thread::spawn(move|| {
let mut tcp = t!(TcpStream::connect(&addr));
rx.recv().unwrap();
t!(tcp.write(&[0]));
let tcp = t!(accept.accept()).0;
let tcp2 = t!(tcp.try_clone());
let txdone3 = txdone.clone();
- let _t = Thread::scoped(move|| {
+ let _t = thread::spawn(move|| {
let mut tcp2 = tcp2;
t!(tcp2.read(&mut [0]));
txdone3.send(()).unwrap();
// Try to ensure that the reading clone is indeed reading
for _ in 0..50 {
- Thread::yield_now();
+ thread::yield_now();
}
// clone the handle again while it's reading, then let it finish the
let a = t!(TcpListener::bind(&addr));
let a2 = t!(a.try_clone());
- let _t = Thread::scoped(move|| {
+ let _t = thread::spawn(move|| {
let _ = TcpStream::connect(&addr);
});
- let _t = Thread::scoped(move|| {
+ let _t = thread::spawn(move|| {
let _ = TcpStream::connect(&addr);
});
let (tx, rx) = channel();
let tx2 = tx.clone();
- let _t = Thread::scoped(move|| {
+ let _t = thread::spawn(move|| {
tx.send(t!(a.accept())).unwrap();
});
- let _t = Thread::scoped(move|| {
+ let _t = thread::spawn(move|| {
tx2.send(t!(a2.accept())).unwrap();
});
- let _t = Thread::scoped(move|| {
+ let _t = thread::spawn(move|| {
let _ = TcpStream::connect(&addr);
});
- let _t = Thread::scoped(move|| {
+ let _t = thread::spawn(move|| {
let _ = TcpStream::connect(&addr);
});
use net::*;
use net::test::{next_test_ip4, next_test_ip6};
use sync::mpsc::channel;
- use thread::Thread;
+ use thread;
fn each_ip(f: &mut FnMut(SocketAddr, SocketAddr)) {
f(next_test_ip4(), next_test_ip4());
let (tx1, rx1) = channel();
let (tx2, rx2) = channel();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let client = t!(UdpSocket::bind(&client_ip));
rx1.recv().unwrap();
t!(client.send_to(&[99], &server_ip));
let sock1 = t!(UdpSocket::bind(&addr1));
let sock2 = t!(UdpSocket::bind(&addr2));
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let mut buf = [0, 0];
assert_eq!(sock2.recv_from(&mut buf), Ok((1, addr1)));
assert_eq!(buf[0], 1);
let (tx1, rx1) = channel();
let (tx2, rx2) = channel();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
rx1.recv().unwrap();
t!(sock3.send_to(&[1], &addr2));
tx2.send(()).unwrap();
let (tx1, rx) = channel();
let tx2 = tx1.clone();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
t!(sock2.send_to(&[1], &addr1));
rx.recv().unwrap();
t!(sock2.send_to(&[2], &addr1));
let sock3 = t!(sock1.try_clone());
let (done, rx) = channel();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let mut buf = [0, 0];
t!(sock3.recv_from(&mut buf));
tx2.send(()).unwrap();
let (tx, rx) = channel();
let (serv_tx, serv_rx) = channel();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let mut buf = [0, 1];
rx.recv().unwrap();
t!(sock2.recv_from(&mut buf));
let (done, rx) = channel();
let tx2 = tx.clone();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
match sock3.send_to(&[1], &addr2) {
Ok(..) => { let _ = tx2.send(()); }
Err(..) => {}
+ Rem<Output=Self>
{
// inlined methods from `num::Float`
- /// Returns the NaN value.
+ /// Returns the `NaN` value.
+ ///
+ /// ```
+ /// use std::num::Float;
+ ///
+ /// let nan: f32 = Float::nan();
+ ///
+ /// assert!(nan.is_nan());
+ /// ```
#[unstable(feature = "std_misc",
reason = "unsure about its place in the world")]
fn nan() -> Self;
/// Returns the infinite value.
+ ///
+ /// ```
+ /// use std::num::Float;
+ /// use std::f32;
+ ///
+ /// let infinity: f32 = Float::infinity();
+ ///
+ /// assert!(infinity.is_infinite());
+ /// assert!(!infinity.is_finite());
+ /// assert!(infinity > f32::MAX);
+ /// ```
#[unstable(feature = "std_misc",
reason = "unsure about its place in the world")]
fn infinity() -> Self;
/// Returns the negative infinite value.
+ ///
+ /// ```
+ /// use std::num::Float;
+ /// use std::f32;
+ ///
+ /// let neg_infinity: f32 = Float::neg_infinity();
+ ///
+ /// assert!(neg_infinity.is_infinite());
+ /// assert!(!neg_infinity.is_finite());
+ /// assert!(neg_infinity < f32::MIN);
+ /// ```
#[unstable(feature = "std_misc",
reason = "unsure about its place in the world")]
fn neg_infinity() -> Self;
- /// Returns the `0` value.
+ /// Returns `0.0`.
+ ///
+ /// ```
+ /// use std::num::Float;
+ ///
+ /// let inf: f32 = Float::infinity();
+ /// let zero: f32 = Float::zero();
+ /// let neg_zero: f32 = Float::neg_zero();
+ ///
+ /// assert_eq!(zero, neg_zero);
+ /// assert_eq!(7.0f32/inf, zero);
+ /// assert_eq!(zero * 10.0, zero);
+ /// ```
#[unstable(feature = "std_misc",
reason = "unsure about its place in the world")]
fn zero() -> Self;
- /// Returns -0.0.
+ /// Returns `-0.0`.
+ ///
+ /// ```
+ /// use std::num::Float;
+ ///
+ /// let inf: f32 = Float::infinity();
+ /// let zero: f32 = Float::zero();
+ /// let neg_zero: f32 = Float::neg_zero();
+ ///
+ /// assert_eq!(zero, neg_zero);
+ /// assert_eq!(7.0f32/inf, zero);
+ /// assert_eq!(zero * 10.0, zero);
+ /// ```
#[unstable(feature = "std_misc",
reason = "unsure about its place in the world")]
fn neg_zero() -> Self;
- /// Returns the `1` value.
+ /// Returns `1.0`.
+ ///
+ /// ```
+ /// use std::num::Float;
+ ///
+ /// let one: f32 = Float::one();
+ ///
+ /// assert_eq!(one, 1.0f32);
+ /// ```
#[unstable(feature = "std_misc",
reason = "unsure about its place in the world")]
fn one() -> Self;
// FIXME (#5527): These should be associated constants
- /// Returns the number of binary digits of mantissa that this type supports.
+ /// Deprecated: use `std::f32::MANTISSA_DIGITS` or `std::f64::MANTISSA_DIGITS`
+ /// instead.
#[unstable(feature = "std_misc")]
#[deprecated(since = "1.0.0",
reason = "use `std::f32::MANTISSA_DIGITS` or \
`std::f64::MANTISSA_DIGITS` as appropriate")]
fn mantissa_digits(unused_self: Option<Self>) -> uint;
- /// Returns the number of base-10 digits of precision that this type supports.
+ /// Deprecated: use `std::f32::DIGITS` or `std::f64::DIGITS` instead.
#[unstable(feature = "std_misc")]
#[deprecated(since = "1.0.0",
reason = "use `std::f32::DIGITS` or `std::f64::DIGITS` as appropriate")]
fn digits(unused_self: Option<Self>) -> uint;
- /// Returns the difference between 1.0 and the smallest representable number larger than 1.0.
+ /// Deprecated: use `std::f32::EPSILON` or `std::f64::EPSILON` instead.
#[unstable(feature = "std_misc")]
#[deprecated(since = "1.0.0",
reason = "use `std::f32::EPSILON` or `std::f64::EPSILON` as appropriate")]
fn epsilon() -> Self;
- /// Returns the minimum binary exponent that this type can represent.
+ /// Deprecated: use `std::f32::MIN_EXP` or `std::f64::MIN_EXP` instead.
#[unstable(feature = "std_misc")]
#[deprecated(since = "1.0.0",
reason = "use `std::f32::MIN_EXP` or `std::f64::MIN_EXP` as appropriate")]
fn min_exp(unused_self: Option<Self>) -> int;
- /// Returns the maximum binary exponent that this type can represent.
+ /// Deprecated: use `std::f32::MAX_EXP` or `std::f64::MAX_EXP` instead.
#[unstable(feature = "std_misc")]
#[deprecated(since = "1.0.0",
reason = "use `std::f32::MAX_EXP` or `std::f64::MAX_EXP` as appropriate")]
fn max_exp(unused_self: Option<Self>) -> int;
- /// Returns the minimum base-10 exponent that this type can represent.
+ /// Deprecated: use `std::f32::MIN_10_EXP` or `std::f64::MIN_10_EXP` instead.
#[unstable(feature = "std_misc")]
#[deprecated(since = "1.0.0",
reason = "use `std::f32::MIN_10_EXP` or `std::f64::MIN_10_EXP` as appropriate")]
fn min_10_exp(unused_self: Option<Self>) -> int;
- /// Returns the maximum base-10 exponent that this type can represent.
+ /// Deprecated: use `std::f32::MAX_10_EXP` or `std::f64::MAX_10_EXP` instead.
#[unstable(feature = "std_misc")]
#[deprecated(since = "1.0.0",
reason = "use `std::f32::MAX_10_EXP` or `std::f64::MAX_10_EXP` as appropriate")]
fn max_10_exp(unused_self: Option<Self>) -> int;
/// Returns the smallest finite value that this type can represent.
+ ///
+ /// ```
+ /// use std::num::Float;
+ /// use std::f64;
+ ///
+ /// let x: f64 = Float::min_value();
+ ///
+ /// assert_eq!(x, f64::MIN);
+ /// ```
#[unstable(feature = "std_misc",
reason = "unsure about its place in the world")]
fn min_value() -> Self;
reason = "unsure about its place in the world")]
fn min_pos_value(unused_self: Option<Self>) -> Self;
/// Returns the largest finite value that this type can represent.
+ ///
+ /// ```
+ /// use std::num::Float;
+ /// use std::f64;
+ ///
+ /// let x: f64 = Float::max_value();
+ /// assert_eq!(x, f64::MAX);
+ /// ```
#[unstable(feature = "std_misc",
reason = "unsure about its place in the world")]
fn max_value() -> Self;
-
- /// Returns true if this value is NaN and false otherwise.
+ /// Returns `true` if this value is `NaN` and false otherwise.
+ ///
+ /// ```
+ /// use std::num::Float;
+ /// use std::f64;
+ ///
+ /// let nan = f64::NAN;
+ /// let f = 7.0;
+ ///
+ /// assert!(nan.is_nan());
+ /// assert!(!f.is_nan());
+ /// ```
#[unstable(feature = "std_misc", reason = "position is undecided")]
fn is_nan(self) -> bool;
- /// Returns true if this value is positive infinity or negative infinity and
+ /// Returns `true` if this value is positive infinity or negative infinity and
/// false otherwise.
+ ///
+ /// ```
+ /// use std::num::Float;
+ /// use std::f32;
+ ///
+ /// let f = 7.0f32;
+ /// let inf: f32 = Float::infinity();
+ /// let neg_inf: f32 = Float::neg_infinity();
+ /// let nan: f32 = f32::NAN;
+ ///
+ /// assert!(!f.is_infinite());
+ /// assert!(!nan.is_infinite());
+ ///
+ /// assert!(inf.is_infinite());
+ /// assert!(neg_inf.is_infinite());
+ /// ```
#[unstable(feature = "std_misc", reason = "position is undecided")]
fn is_infinite(self) -> bool;
- /// Returns true if this number is neither infinite nor NaN.
+ /// Returns `true` if this number is neither infinite nor `NaN`.
+ ///
+ /// ```
+ /// use std::num::Float;
+ /// use std::f32;
+ ///
+ /// let f = 7.0f32;
+ /// let inf: f32 = Float::infinity();
+ /// let neg_inf: f32 = Float::neg_infinity();
+ /// let nan: f32 = f32::NAN;
+ ///
+ /// assert!(f.is_finite());
+ ///
+ /// assert!(!nan.is_finite());
+ /// assert!(!inf.is_finite());
+ /// assert!(!neg_inf.is_finite());
+ /// ```
#[unstable(feature = "std_misc", reason = "position is undecided")]
fn is_finite(self) -> bool;
- /// Returns true if this number is neither zero, infinite, denormal, or NaN.
+ /// Returns `true` if the number is neither zero, infinite,
+ /// [subnormal][subnormal], or `NaN`.
+ ///
+ /// ```
+ /// use std::num::Float;
+ /// use std::f32;
+ ///
+ /// let min = f32::MIN_POSITIVE; // 1.17549435e-38f32
+ /// let max = f32::MAX;
+ /// let lower_than_min = 1.0e-40_f32;
+ /// let zero = 0.0f32;
+ ///
+ /// assert!(min.is_normal());
+ /// assert!(max.is_normal());
+ ///
+ /// assert!(!zero.is_normal());
+ /// assert!(!f32::NAN.is_normal());
+ /// assert!(!f32::INFINITY.is_normal());
+ /// // Values between `0` and `min` are Subnormal.
+ /// assert!(!lower_than_min.is_normal());
+ /// ```
+ /// [subnormal]: http://en.wikipedia.org/wiki/Denormal_number
#[unstable(feature = "std_misc", reason = "position is undecided")]
fn is_normal(self) -> bool;
- /// Returns the category that this number falls into.
+
+ /// Returns the floating point category of the number. If only one property
+ /// is going to be tested, it is generally faster to use the specific
+ /// predicate instead.
+ ///
+ /// ```
+ /// use std::num::{Float, FpCategory};
+ /// use std::f32;
+ ///
+ /// let num = 12.4f32;
+ /// let inf = f32::INFINITY;
+ ///
+ /// assert_eq!(num.classify(), FpCategory::Normal);
+ /// assert_eq!(inf.classify(), FpCategory::Infinite);
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn classify(self) -> FpCategory;
- /// Returns the mantissa, exponent and sign as integers, respectively.
+ /// Returns the mantissa, base 2 exponent, and sign as integers, respectively.
+ /// The original number can be recovered by `sign * mantissa * 2 ^ exponent`.
+ /// The floating point encoding is documented in the [Reference][floating-point].
+ ///
+ /// ```
+ /// use std::num::Float;
+ ///
+ /// let num = 2.0f32;
+ ///
+ /// // (8388608u64, -22i16, 1i8)
+ /// let (mantissa, exponent, sign) = num.integer_decode();
+ /// let sign_f = sign as f32;
+ /// let mantissa_f = mantissa as f32;
+ /// let exponent_f = num.powf(exponent as f32);
+ ///
+ /// // 1 * 8388608 * 2^(-22) == 2
+ /// let abs_difference = (sign_f * mantissa_f * exponent_f - num).abs();
+ ///
+ /// assert!(abs_difference < 1e-10);
+ /// ```
+ /// [floating-point]: ../../../../../reference.html#machine-types
#[unstable(feature = "std_misc", reason = "signature is undecided")]
fn integer_decode(self) -> (u64, i16, i8);
- /// Return the largest integer less than or equal to a number.
+ /// Returns the largest integer less than or equal to a number.
+ ///
+ /// ```
+ /// use std::num::Float;
+ ///
+ /// let f = 3.99;
+ /// let g = 3.0;
+ ///
+ /// assert_eq!(f.floor(), 3.0);
+ /// assert_eq!(g.floor(), 3.0);
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn floor(self) -> Self;
- /// Return the smallest integer greater than or equal to a number.
+ /// Returns the smallest integer greater than or equal to a number.
+ ///
+ /// ```
+ /// use std::num::Float;
+ ///
+ /// let f = 3.01;
+ /// let g = 4.0;
+ ///
+ /// assert_eq!(f.ceil(), 4.0);
+ /// assert_eq!(g.ceil(), 4.0);
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn ceil(self) -> Self;
- /// Return the nearest integer to a number. Round half-way cases away from
+ /// Returns the nearest integer to a number. Round half-way cases away from
/// `0.0`.
+ ///
+ /// ```
+ /// use std::num::Float;
+ ///
+ /// let f = 3.3;
+ /// let g = -3.3;
+ ///
+ /// assert_eq!(f.round(), 3.0);
+ /// assert_eq!(g.round(), -3.0);
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn round(self) -> Self;
/// Return the integer part of a number.
+ ///
+ /// ```
+ /// use std::num::Float;
+ ///
+ /// let f = 3.3;
+ /// let g = -3.7;
+ ///
+ /// assert_eq!(f.trunc(), 3.0);
+ /// assert_eq!(g.trunc(), -3.0);
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn trunc(self) -> Self;
- /// Return the fractional part of a number.
+ /// Returns the fractional part of a number.
+ ///
+ /// ```
+ /// use std::num::Float;
+ ///
+ /// let x = 3.5;
+ /// let y = -3.5;
+ /// let abs_difference_x = (x.fract() - 0.5).abs();
+ /// let abs_difference_y = (y.fract() - (-0.5)).abs();
+ ///
+ /// assert!(abs_difference_x < 1e-10);
+ /// assert!(abs_difference_y < 1e-10);
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn fract(self) -> Self;
-
/// Computes the absolute value of `self`. Returns `Float::nan()` if the
/// number is `Float::nan()`.
+ ///
+ /// ```
+ /// use std::num::Float;
+ /// use std::f64;
+ ///
+ /// let x = 3.5;
+ /// let y = -3.5;
+ ///
+ /// let abs_difference_x = (x.abs() - x).abs();
+ /// let abs_difference_y = (y.abs() - (-y)).abs();
+ ///
+ /// assert!(abs_difference_x < 1e-10);
+ /// assert!(abs_difference_y < 1e-10);
+ ///
+ /// assert!(f64::NAN.abs().is_nan());
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn abs(self) -> Self;
/// Returns a number that represents the sign of `self`.
/// - `1.0` if the number is positive, `+0.0` or `Float::infinity()`
/// - `-1.0` if the number is negative, `-0.0` or `Float::neg_infinity()`
/// - `Float::nan()` if the number is `Float::nan()`
+ ///
+ /// ```
+ /// use std::num::Float;
+ /// use std::f64;
+ ///
+ /// let f = 3.5;
+ ///
+ /// assert_eq!(f.signum(), 1.0);
+ /// assert_eq!(f64::NEG_INFINITY.signum(), -1.0);
+ ///
+ /// assert!(f64::NAN.signum().is_nan());
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn signum(self) -> Self;
/// Returns `true` if `self` is positive, including `+0.0` and
/// `Float::infinity()`.
+ ///
+ /// ```
+ /// use std::num::Float;
+ /// use std::f64;
+ ///
+ /// let nan: f64 = f64::NAN;
+ ///
+ /// let f = 7.0;
+ /// let g = -7.0;
+ ///
+ /// assert!(f.is_positive());
+ /// assert!(!g.is_positive());
+ /// // Requires both tests to determine if is `NaN`
+ /// assert!(!nan.is_positive() && !nan.is_negative());
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn is_positive(self) -> bool;
/// Returns `true` if `self` is negative, including `-0.0` and
/// `Float::neg_infinity()`.
+ ///
+ /// ```
+ /// use std::num::Float;
+ /// use std::f64;
+ ///
+ /// let nan = f64::NAN;
+ ///
+ /// let f = 7.0;
+ /// let g = -7.0;
+ ///
+ /// assert!(!f.is_negative());
+ /// assert!(g.is_negative());
+ /// // Requires both tests to determine if is `NaN`.
+ /// assert!(!nan.is_positive() && !nan.is_negative());
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn is_negative(self) -> bool;
/// Fused multiply-add. Computes `(self * a) + b` with only one rounding
/// error. This produces a more accurate result with better performance than
/// a separate multiplication operation followed by an add.
+ ///
+ /// ```
+ /// use std::num::Float;
+ ///
+ /// let m = 10.0;
+ /// let x = 4.0;
+ /// let b = 60.0;
+ ///
+ /// // 100.0
+ /// let abs_difference = (m.mul_add(x, b) - (m*x + b)).abs();
+ ///
+ /// assert!(abs_difference < 1e-10);
+ /// ```
#[unstable(feature = "std_misc",
reason = "unsure about its place in the world")]
fn mul_add(self, a: Self, b: Self) -> Self;
/// Take the reciprocal (inverse) of a number, `1/x`.
+ ///
+ /// ```
+ /// use std::num::Float;
+ ///
+ /// let x = 2.0;
+ /// let abs_difference = (x.recip() - (1.0/x)).abs();
+ ///
+ /// assert!(abs_difference < 1e-10);
+ /// ```
#[unstable(feature = "std_misc",
reason = "unsure about its place in the world")]
fn recip(self) -> Self;
/// Raise a number to an integer power.
///
/// Using this function is generally faster than using `powf`
+ ///
+ /// ```
+ /// use std::num::Float;
+ ///
+ /// let x = 2.0;
+ /// let abs_difference = (x.powi(2) - x*x).abs();
+ ///
+ /// assert!(abs_difference < 1e-10);
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn powi(self, n: i32) -> Self;
/// Raise a number to a floating point power.
+ ///
+ /// ```
+ /// use std::num::Float;
+ ///
+ /// let x = 2.0;
+ /// let abs_difference = (x.powf(2.0) - x*x).abs();
+ ///
+ /// assert!(abs_difference < 1e-10);
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn powf(self, n: Self) -> Self;
-
/// Take the square root of a number.
///
/// Returns NaN if `self` is a negative number.
+ ///
+ /// ```
+ /// use std::num::Float;
+ ///
+ /// let positive = 4.0;
+ /// let negative = -4.0;
+ ///
+ /// let abs_difference = (positive.sqrt() - 2.0).abs();
+ ///
+ /// assert!(abs_difference < 1e-10);
+ /// assert!(negative.sqrt().is_nan());
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn sqrt(self) -> Self;
+
/// Take the reciprocal (inverse) square root of a number, `1/sqrt(x)`.
+ ///
+ /// ```
+ /// use std::num::Float;
+ ///
+ /// let f = 4.0;
+ ///
+ /// let abs_difference = (f.rsqrt() - 0.5).abs();
+ ///
+ /// assert!(abs_difference < 1e-10);
+ /// ```
#[unstable(feature = "std_misc",
reason = "unsure about its place in the world")]
fn rsqrt(self) -> Self;
/// Returns `e^(self)`, (the exponential function).
+ ///
+ /// ```
+ /// use std::num::Float;
+ ///
+ /// let one = 1.0;
+ /// // e^1
+ /// let e = one.exp();
+ ///
+ /// // ln(e) - 1 == 0
+ /// let abs_difference = (e.ln() - 1.0).abs();
+ ///
+ /// assert!(abs_difference < 1e-10);
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn exp(self) -> Self;
- /// Returns 2 raised to the power of the number, `2^(self)`.
+ /// Returns `2^(self)`.
+ ///
+ /// ```
+ /// use std::num::Float;
+ ///
+ /// let f = 2.0;
+ ///
+ /// // 2^2 - 4 == 0
+ /// let abs_difference = (f.exp2() - 4.0).abs();
+ ///
+ /// assert!(abs_difference < 1e-10);
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn exp2(self) -> Self;
/// Returns the natural logarithm of the number.
+ ///
+ /// ```
+ /// use std::num::Float;
+ ///
+ /// let one = 1.0;
+ /// // e^1
+ /// let e = one.exp();
+ ///
+ /// // ln(e) - 1 == 0
+ /// let abs_difference = (e.ln() - 1.0).abs();
+ ///
+ /// assert!(abs_difference < 1e-10);
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn ln(self) -> Self;
/// Returns the logarithm of the number with respect to an arbitrary base.
+ ///
+ /// ```
+ /// use std::num::Float;
+ ///
+ /// let ten = 10.0;
+ /// let two = 2.0;
+ ///
+ /// // log10(10) - 1 == 0
+ /// let abs_difference_10 = (ten.log(10.0) - 1.0).abs();
+ ///
+ /// // log2(2) - 1 == 0
+ /// let abs_difference_2 = (two.log(2.0) - 1.0).abs();
+ ///
+ /// assert!(abs_difference_10 < 1e-10);
+ /// assert!(abs_difference_2 < 1e-10);
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn log(self, base: Self) -> Self;
/// Returns the base 2 logarithm of the number.
+ ///
+ /// ```
+ /// use std::num::Float;
+ ///
+ /// let two = 2.0;
+ ///
+ /// // log2(2) - 1 == 0
+ /// let abs_difference = (two.log2() - 1.0).abs();
+ ///
+ /// assert!(abs_difference < 1e-10);
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn log2(self) -> Self;
/// Returns the base 10 logarithm of the number.
+ ///
+ /// ```
+ /// use std::num::Float;
+ ///
+ /// let ten = 10.0;
+ ///
+ /// // log10(10) - 1 == 0
+ /// let abs_difference = (ten.log10() - 1.0).abs();
+ ///
+ /// assert!(abs_difference < 1e-10);
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn log10(self) -> Self;
/// Convert radians to degrees.
+ ///
+ /// ```
+ /// use std::num::Float;
+ /// use std::f64::consts;
+ ///
+ /// let angle = consts::PI;
+ ///
+ /// let abs_difference = (angle.to_degrees() - 180.0).abs();
+ ///
+ /// assert!(abs_difference < 1e-10);
+ /// ```
#[unstable(feature = "std_misc", reason = "desirability is unclear")]
fn to_degrees(self) -> Self;
/// Convert degrees to radians.
+ ///
+ /// ```
+ /// use std::num::Float;
+ /// use std::f64::consts;
+ ///
+ /// let angle = 180.0;
+ ///
+ /// let abs_difference = (angle.to_radians() - consts::PI).abs();
+ ///
+ /// assert!(abs_difference < 1e-10);
+ /// ```
#[unstable(feature = "std_misc", reason = "desirability is unclear")]
fn to_radians(self) -> Self;
-
- /// Constructs a floating point number created by multiplying `x` by 2
- /// raised to the power of `exp`.
+ /// Constructs a floating point number of `x*2^exp`.
+ ///
+ /// ```
+ /// use std::num::Float;
+ ///
+ /// // 3*2^2 - 12 == 0
+ /// let abs_difference = (Float::ldexp(3.0, 2) - 12.0).abs();
+ ///
+ /// assert!(abs_difference < 1e-10);
+ /// ```
#[unstable(feature = "std_misc",
reason = "pending integer conventions")]
fn ldexp(x: Self, exp: int) -> Self;
/// Breaks the number into a normalized fraction and a base-2 exponent,
/// satisfying:
///
- /// * `self = x * pow(2, exp)`
- ///
+ /// * `self = x * 2^exp`
/// * `0.5 <= abs(x) < 1.0`
+ ///
+ /// ```
+ /// use std::num::Float;
+ ///
+ /// let x = 4.0;
+ ///
+ /// // (1/2)*2^3 -> 1 * 8/2 -> 4.0
+ /// let f = x.frexp();
+ /// let abs_difference_0 = (f.0 - 0.5).abs();
+ /// let abs_difference_1 = (f.1 as f64 - 3.0).abs();
+ ///
+ /// assert!(abs_difference_0 < 1e-10);
+ /// assert!(abs_difference_1 < 1e-10);
+ /// ```
#[unstable(feature = "std_misc",
reason = "pending integer conventions")]
fn frexp(self) -> (Self, int);
-
/// Returns the next representable floating-point value in the direction of
/// `other`.
+ ///
+ /// ```
+ /// use std::num::Float;
+ ///
+ /// let x = 1.0f32;
+ ///
+ /// let abs_diff = (x.next_after(2.0) - 1.00000011920928955078125_f32).abs();
+ ///
+ /// assert!(abs_diff < 1e-10);
+ /// ```
#[unstable(feature = "std_misc",
reason = "unsure about its place in the world")]
fn next_after(self, other: Self) -> Self;
/// Returns the maximum of the two numbers.
+ ///
+ /// ```
+ /// use std::num::Float;
+ ///
+ /// let x = 1.0;
+ /// let y = 2.0;
+ ///
+ /// assert_eq!(x.max(y), y);
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn max(self, other: Self) -> Self;
/// Returns the minimum of the two numbers.
+ ///
+ /// ```
+ /// use std::num::Float;
+ ///
+ /// let x = 1.0;
+ /// let y = 2.0;
+ ///
+ /// assert_eq!(x.min(y), x);
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn min(self, other: Self) -> Self;
- /// The positive difference of two numbers. Returns `0.0` if the number is
- /// less than or equal to `other`, otherwise the difference between`self`
- /// and `other` is returned.
+ /// The positive difference of two numbers.
+ ///
+ /// * If `self <= other`: `0:0`
+ /// * Else: `self - other`
+ ///
+ /// ```
+ /// use std::num::Float;
+ ///
+ /// let x = 3.0;
+ /// let y = -3.0;
+ ///
+ /// let abs_difference_x = (x.abs_sub(1.0) - 2.0).abs();
+ /// let abs_difference_y = (y.abs_sub(1.0) - 0.0).abs();
+ ///
+ /// assert!(abs_difference_x < 1e-10);
+ /// assert!(abs_difference_y < 1e-10);
+ /// ```
#[unstable(feature = "std_misc", reason = "may be renamed")]
fn abs_sub(self, other: Self) -> Self;
-
/// Take the cubic root of a number.
+ ///
+ /// ```
+ /// use std::num::Float;
+ ///
+ /// let x = 8.0;
+ ///
+ /// // x^(1/3) - 2 == 0
+ /// let abs_difference = (x.cbrt() - 2.0).abs();
+ ///
+ /// assert!(abs_difference < 1e-10);
+ /// ```
#[unstable(feature = "std_misc", reason = "may be renamed")]
fn cbrt(self) -> Self;
/// Calculate the length of the hypotenuse of a right-angle triangle given
/// legs of length `x` and `y`.
+ ///
+ /// ```
+ /// use std::num::Float;
+ ///
+ /// let x = 2.0;
+ /// let y = 3.0;
+ ///
+ /// // sqrt(x^2 + y^2)
+ /// let abs_difference = (x.hypot(y) - (x.powi(2) + y.powi(2)).sqrt()).abs();
+ ///
+ /// assert!(abs_difference < 1e-10);
+ /// ```
#[unstable(feature = "std_misc",
reason = "unsure about its place in the world")]
fn hypot(self, other: Self) -> Self;
/// Computes the sine of a number (in radians).
+ ///
+ /// ```
+ /// use std::num::Float;
+ /// use std::f64;
+ ///
+ /// let x = f64::consts::PI/2.0;
+ ///
+ /// let abs_difference = (x.sin() - 1.0).abs();
+ ///
+ /// assert!(abs_difference < 1e-10);
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn sin(self) -> Self;
/// Computes the cosine of a number (in radians).
+ ///
+ /// ```
+ /// use std::num::Float;
+ /// use std::f64;
+ ///
+ /// let x = 2.0*f64::consts::PI;
+ ///
+ /// let abs_difference = (x.cos() - 1.0).abs();
+ ///
+ /// assert!(abs_difference < 1e-10);
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn cos(self) -> Self;
/// Computes the tangent of a number (in radians).
+ ///
+ /// ```
+ /// use std::num::Float;
+ /// use std::f64;
+ ///
+ /// let x = f64::consts::PI/4.0;
+ /// let abs_difference = (x.tan() - 1.0).abs();
+ ///
+ /// assert!(abs_difference < 1e-14);
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn tan(self) -> Self;
-
/// Computes the arcsine of a number. Return value is in radians in
/// the range [-pi/2, pi/2] or NaN if the number is outside the range
/// [-1, 1].
+ ///
+ /// ```
+ /// use std::num::Float;
+ /// use std::f64;
+ ///
+ /// let f = f64::consts::PI / 2.0;
+ ///
+ /// // asin(sin(pi/2))
+ /// let abs_difference = (f.sin().asin() - f64::consts::PI / 2.0).abs();
+ ///
+ /// assert!(abs_difference < 1e-10);
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn asin(self) -> Self;
/// Computes the arccosine of a number. Return value is in radians in
/// the range [0, pi] or NaN if the number is outside the range
/// [-1, 1].
+ ///
+ /// ```
+ /// use std::num::Float;
+ /// use std::f64;
+ ///
+ /// let f = f64::consts::PI / 4.0;
+ ///
+ /// // acos(cos(pi/4))
+ /// let abs_difference = (f.cos().acos() - f64::consts::PI / 4.0).abs();
+ ///
+ /// assert!(abs_difference < 1e-10);
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn acos(self) -> Self;
/// Computes the arctangent of a number. Return value is in radians in the
/// range [-pi/2, pi/2];
+ ///
+ /// ```
+ /// use std::num::Float;
+ ///
+ /// let f = 1.0;
+ ///
+ /// // atan(tan(1))
+ /// let abs_difference = (f.tan().atan() - 1.0).abs();
+ ///
+ /// assert!(abs_difference < 1e-10);
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn atan(self) -> Self;
- /// Computes the four quadrant arctangent of a number, `y`, and another
- /// number `x`. Return value is in radians in the range [-pi, pi].
+ /// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`).
+ ///
+ /// * `x = 0`, `y = 0`: `0`
+ /// * `x >= 0`: `arctan(y/x)` -> `[-pi/2, pi/2]`
+ /// * `y >= 0`: `arctan(y/x) + pi` -> `(pi/2, pi]`
+ /// * `y < 0`: `arctan(y/x) - pi` -> `(-pi, -pi/2)`
+ ///
+ /// ```
+ /// use std::num::Float;
+ /// use std::f64;
+ ///
+ /// let pi = f64::consts::PI;
+ /// // All angles from horizontal right (+x)
+ /// // 45 deg counter-clockwise
+ /// let x1 = 3.0;
+ /// let y1 = -3.0;
+ ///
+ /// // 135 deg clockwise
+ /// let x2 = -3.0;
+ /// let y2 = 3.0;
+ ///
+ /// let abs_difference_1 = (y1.atan2(x1) - (-pi/4.0)).abs();
+ /// let abs_difference_2 = (y2.atan2(x2) - 3.0*pi/4.0).abs();
+ ///
+ /// assert!(abs_difference_1 < 1e-10);
+ /// assert!(abs_difference_2 < 1e-10);
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn atan2(self, other: Self) -> Self;
/// Simultaneously computes the sine and cosine of the number, `x`. Returns
/// `(sin(x), cos(x))`.
+ ///
+ /// ```
+ /// use std::num::Float;
+ /// use std::f64;
+ ///
+ /// let x = f64::consts::PI/4.0;
+ /// let f = x.sin_cos();
+ ///
+ /// let abs_difference_0 = (f.0 - x.sin()).abs();
+ /// let abs_difference_1 = (f.1 - x.cos()).abs();
+ ///
+ /// assert!(abs_difference_0 < 1e-10);
+ /// assert!(abs_difference_0 < 1e-10);
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn sin_cos(self) -> (Self, Self);
- /// Returns the exponential of the number, minus 1, in a way that is
- /// accurate even if the number is close to zero.
+ /// Returns `e^(self) - 1` in a way that is accurate even if the
+ /// number is close to zero.
+ ///
+ /// ```
+ /// use std::num::Float;
+ ///
+ /// let x = 7.0;
+ ///
+ /// // e^(ln(7)) - 1
+ /// let abs_difference = (x.ln().exp_m1() - 6.0).abs();
+ ///
+ /// assert!(abs_difference < 1e-10);
+ /// ```
#[unstable(feature = "std_misc", reason = "may be renamed")]
fn exp_m1(self) -> Self;
- /// Returns the natural logarithm of the number plus 1 (`ln(1+n)`) more
- /// accurately than if the operations were performed separately.
+ /// Returns `ln(1+n)` (natural logarithm) more accurately than if
+ /// the operations were performed separately.
+ ///
+ /// ```
+ /// use std::num::Float;
+ /// use std::f64;
+ ///
+ /// let x = f64::consts::E - 1.0;
+ ///
+ /// // ln(1 + (e - 1)) == ln(e) == 1
+ /// let abs_difference = (x.ln_1p() - 1.0).abs();
+ ///
+ /// assert!(abs_difference < 1e-10);
+ /// ```
#[unstable(feature = "std_misc", reason = "may be renamed")]
fn ln_1p(self) -> Self;
/// Hyperbolic sine function.
+ ///
+ /// ```
+ /// use std::num::Float;
+ /// use std::f64;
+ ///
+ /// let e = f64::consts::E;
+ /// let x = 1.0;
+ ///
+ /// let f = x.sinh();
+ /// // Solving sinh() at 1 gives `(e^2-1)/(2e)`
+ /// let g = (e*e - 1.0)/(2.0*e);
+ /// let abs_difference = (f - g).abs();
+ ///
+ /// assert!(abs_difference < 1e-10);
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn sinh(self) -> Self;
/// Hyperbolic cosine function.
+ ///
+ /// ```
+ /// use std::num::Float;
+ /// use std::f64;
+ ///
+ /// let e = f64::consts::E;
+ /// let x = 1.0;
+ /// let f = x.cosh();
+ /// // Solving cosh() at 1 gives this result
+ /// let g = (e*e + 1.0)/(2.0*e);
+ /// let abs_difference = (f - g).abs();
+ ///
+ /// // Same result
+ /// assert!(abs_difference < 1.0e-10);
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn cosh(self) -> Self;
/// Hyperbolic tangent function.
+ ///
+ /// ```
+ /// use std::num::Float;
+ /// use std::f64;
+ ///
+ /// let e = f64::consts::E;
+ /// let x = 1.0;
+ ///
+ /// let f = x.tanh();
+ /// // Solving tanh() at 1 gives `(1 - e^(-2))/(1 + e^(-2))`
+ /// let g = (1.0 - e.powi(-2))/(1.0 + e.powi(-2));
+ /// let abs_difference = (f - g).abs();
+ ///
+ /// assert!(abs_difference < 1.0e-10);
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn tanh(self) -> Self;
/// Inverse hyperbolic sine function.
+ ///
+ /// ```
+ /// use std::num::Float;
+ ///
+ /// let x = 1.0;
+ /// let f = x.sinh().asinh();
+ ///
+ /// let abs_difference = (f - x).abs();
+ ///
+ /// assert!(abs_difference < 1.0e-10);
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn asinh(self) -> Self;
/// Inverse hyperbolic cosine function.
+ ///
+ /// ```
+ /// use std::num::Float;
+ ///
+ /// let x = 1.0;
+ /// let f = x.cosh().acosh();
+ ///
+ /// let abs_difference = (f - x).abs();
+ ///
+ /// assert!(abs_difference < 1.0e-10);
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn acosh(self) -> Self;
/// Inverse hyperbolic tangent function.
+ ///
+ /// ```
+ /// use std::num::Float;
+ /// use std::f64;
+ ///
+ /// let e = f64::consts::E;
+ /// let f = e.tanh().atanh();
+ ///
+ /// let abs_difference = (f - e).abs();
+ ///
+ /// assert!(abs_difference < 1.0e-10);
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn atanh(self) -> Self;
}
use sync::mpsc::channel;
use super::*;
use old_io;
- use thread::Thread;
+ use thread;
#[test]
fn test_rx_reader() {
let (tx, rx) = channel();
- Thread::spawn(move|| {
+ thread::spawn(move|| {
tx.send(vec![1u8, 2u8]).unwrap();
tx.send(vec![]).unwrap();
tx.send(vec![3u8, 4u8]).unwrap();
#[test]
fn test_rx_buffer() {
let (tx, rx) = channel();
- Thread::spawn(move|| {
+ thread::spawn(move|| {
tx.send(b"he".to_vec()).unwrap();
tx.send(b"llo wo".to_vec()).unwrap();
tx.send(b"".to_vec()).unwrap();
writer.write_be_u32(42).unwrap();
let wanted = vec![0u8, 0u8, 0u8, 42u8];
- let got = match Thread::scoped(move|| { rx.recv().unwrap() }).join() {
- Ok(got) => got,
- Err(_) => panic!(),
- };
+ let got = thread::scoped(move|| { rx.recv().unwrap() }).join();
assert_eq!(wanted, got);
match writer.write_u8(1) {
//! # #![allow(dead_code)]
//! use std::old_io::{TcpListener, TcpStream};
//! use std::old_io::{Acceptor, Listener};
-//! use std::thread::Thread;
+//! use std::thread;
//!
//! let listener = TcpListener::bind("127.0.0.1:80");
//!
//! match stream {
//! Err(e) => { /* connection failed */ }
//! Ok(stream) => {
-//! Thread::spawn(move|| {
+//! thread::spawn(move|| {
//! // connection succeeded
//! handle_client(stream)
//! });
//! concerned with error handling; instead its caller is responsible for
//! responding to errors that may occur while attempting to read the numbers.
-#![unstable(feature = "io")]
+#![unstable(feature = "old_io")]
#![deny(unused_must_use)]
pub use self::SeekStyle::*;
///
/// This function will return any I/O error reported while formatting.
fn write_fmt(&mut self, fmt: fmt::Arguments) -> IoResult<()> {
- // Create a shim which translates a Writer to a fmt::Writer and saves
+ // Create a shim which translates a Writer to a fmt::Write and saves
// off I/O errors. instead of discarding them
struct Adaptor<'a, T: ?Sized +'a> {
inner: &'a mut T,
error: IoResult<()>,
}
- impl<'a, T: ?Sized + Writer> fmt::Writer for Adaptor<'a, T> {
+ impl<'a, T: ?Sized + Writer> fmt::Write for Adaptor<'a, T> {
fn write_str(&mut self, s: &str) -> fmt::Result {
match self.inner.write_all(s.as_bytes()) {
Ok(()) => Ok(()),
use old_io::test::*;
use super::*;
use sync::mpsc::channel;
- use thread::Thread;
+ use thread;
use time::Duration;
pub fn smalltest<F,G>(server: F, client: G)
where F : FnOnce(UnixStream), F : Send,
- G : FnOnce(UnixStream), G : Send
+ G : FnOnce(UnixStream), G : Send + 'static
{
let path1 = next_test_unix();
let path2 = path1.clone();
let mut acceptor = UnixListener::bind(&path1).listen();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
match UnixStream::connect(&path2) {
Ok(c) => client(c),
Err(e) => panic!("failed connect: {}", e),
Err(e) => panic!("failed listen: {}", e),
};
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
for _ in 0u..times {
let mut stream = UnixStream::connect(&path2);
match stream.write(&[100]) {
let addr = next_test_unix();
let mut acceptor = UnixListener::bind(&addr).listen();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let mut s = UnixStream::connect(&addr);
let mut buf = [0, 0];
debug!("client reading");
let (tx1, rx1) = channel();
let (tx2, rx2) = channel();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let mut s2 = s2;
rx1.recv().unwrap();
debug!("writer writing");
let (tx1, rx) = channel();
let tx2 = tx1.clone();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let mut s = UnixStream::connect(&addr);
s.write(&[1]).unwrap();
rx.recv().unwrap();
let s2 = s1.clone();
let (done, rx) = channel();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let mut s2 = s2;
let mut buf = [0, 0];
s2.read(&mut buf).unwrap();
let addr = next_test_unix();
let mut acceptor = UnixListener::bind(&addr).listen();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let mut s = UnixStream::connect(&addr);
let buf = &mut [0, 1];
s.read(buf).unwrap();
let s2 = s1.clone();
let (tx, rx) = channel();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let mut s2 = s2;
s2.write(&[1]).unwrap();
tx.send(()).unwrap();
// continue to receive any pending connections.
let (tx, rx) = channel();
let addr2 = addr.clone();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
tx.send(UnixStream::connect(&addr2).unwrap()).unwrap();
});
let l = rx.recv().unwrap();
Err(ref e) if e.kind == TimedOut => {}
Err(e) => panic!("error: {}", e),
}
- ::thread::Thread::yield_now();
+ ::thread::yield_now();
if i == 1000 { panic!("should have a pending connection") }
}
drop(l);
// Unset the timeout and make sure that this always blocks.
a.set_timeout(None);
let addr2 = addr.clone();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
drop(UnixStream::connect(&addr2).unwrap());
});
a.accept().unwrap();
let addr = next_test_unix();
let a = UnixListener::bind(&addr).listen().unwrap();
let (_tx, rx) = channel::<()>();
- Thread::spawn(move|| {
+ thread::spawn(move|| {
let mut a = a;
let _s = a.accept().unwrap();
let _ = rx.recv();
let addr = next_test_unix();
let a = UnixListener::bind(&addr).listen().unwrap();
let (_tx, rx) = channel::<()>();
- Thread::spawn(move|| {
+ thread::spawn(move|| {
let mut a = a;
let _s = a.accept().unwrap();
let _ = rx.recv();
let mut s = UnixStream::connect(&addr).unwrap();
let s2 = s.clone();
let (tx, rx) = channel();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let mut s2 = s2;
assert!(s2.read(&mut [0]).is_err());
tx.send(()).unwrap();
let addr = next_test_unix();
let mut a = UnixListener::bind(&addr).listen().unwrap();
let (tx, rx) = channel::<()>();
- Thread::spawn(move|| {
+ thread::spawn(move|| {
let mut s = UnixStream::connect(&addr).unwrap();
rx.recv().unwrap();
assert!(s.write(&[0]).is_ok());
let addr = next_test_unix();
let mut a = UnixListener::bind(&addr).listen().unwrap();
let (tx, rx) = channel::<()>();
- Thread::spawn(move|| {
+ thread::spawn(move|| {
let mut s = UnixStream::connect(&addr).unwrap();
rx.recv().unwrap();
let mut amt = 0;
let addr = next_test_unix();
let mut a = UnixListener::bind(&addr).listen().unwrap();
let (tx, rx) = channel::<()>();
- Thread::spawn(move|| {
+ thread::spawn(move|| {
let mut s = UnixStream::connect(&addr).unwrap();
rx.recv().unwrap();
assert!(s.write(&[0]).is_ok());
let addr = next_test_unix();
let mut a = UnixListener::bind(&addr).listen().unwrap();
let (tx, rx) = channel::<()>();
- Thread::spawn(move|| {
+ thread::spawn(move|| {
let mut s = UnixStream::connect(&addr).unwrap();
rx.recv().unwrap();
assert!(s.write(&[0]).is_ok());
let mut s = a.accept().unwrap();
let s2 = s.clone();
let (tx2, rx2) = channel();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let mut s2 = s2;
assert!(s2.read(&mut [0]).is_ok());
tx2.send(()).unwrap();
let mut a2 = a.clone();
let addr2 = addr.clone();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let _ = UnixStream::connect(&addr2);
});
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let _ = UnixStream::connect(&addr);
});
let (tx, rx) = channel();
let tx2 = tx.clone();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let mut a = a;
tx.send(a.accept()).unwrap()
});
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let mut a = a2;
tx2.send(a.accept()).unwrap()
});
let addr2 = addr.clone();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let _ = UnixStream::connect(&addr2);
});
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let _ = UnixStream::connect(&addr);
});
let mut a2 = a.clone();
let (tx, rx) = channel();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let mut a = a;
tx.send(a.accept()).unwrap();
});
/// use std::old_io::timer;
/// use std::old_io::TcpStream;
/// use std::time::Duration;
- /// use std::thread::Thread;
+ /// use std::thread;
///
/// let mut stream = TcpStream::connect("127.0.0.1:34254").unwrap();
/// let stream2 = stream.clone();
///
- /// let _t = Thread::spawn(move|| {
+ /// let _t = thread::spawn(move|| {
/// // close this stream after one second
/// timer::sleep(Duration::seconds(1));
/// let mut stream = stream2;
/// # fn foo() {
/// use std::old_io::{TcpListener, TcpStream};
/// use std::old_io::{Acceptor, Listener};
-/// use std::thread::Thread;
+/// use std::thread;
///
/// let listener = TcpListener::bind("127.0.0.1:80").unwrap();
///
/// match stream {
/// Err(e) => { /* connection failed */ }
/// Ok(stream) => {
-/// Thread::spawn(move|| {
+/// thread::spawn(move|| {
/// // connection succeeded
/// handle_client(stream)
/// });
///
/// ```
/// use std::old_io::{TcpListener, Listener, Acceptor, EndOfFile};
- /// use std::thread::Thread;
+ /// use std::thread;
///
/// let mut a = TcpListener::bind("127.0.0.1:8482").listen().unwrap();
/// let a2 = a.clone();
///
- /// let _t = Thread::spawn(move|| {
+ /// let _t = thread::spawn(move|| {
/// let mut a2 = a2;
/// for socket in a2.incoming() {
/// match socket {
use prelude::v1::*;
use sync::mpsc::channel;
- use thread::Thread;
+ use thread;
use old_io::net::tcp::*;
use old_io::net::ip::*;
use old_io::test::*;
use old_io::{EndOfFile, TimedOut, ShortWrite, IoError};
use old_io::{ConnectionRefused, BrokenPipe, ConnectionAborted};
use old_io::{ConnectionReset, NotConnected, PermissionDenied, OtherIoError};
+ use old_io::{InvalidInput};
use old_io::{Acceptor, Listener};
// FIXME #11530 this fails on android because tests are run as root
fn connect_error() {
match TcpStream::connect("0.0.0.0:1") {
Ok(..) => panic!(),
- Err(e) => assert_eq!(e.kind, ConnectionRefused),
+ Err(e) => assert!((e.kind == ConnectionRefused)
+ || (e.kind == InvalidInput)),
}
}
let listener = TcpListener::bind(socket_addr);
let mut acceptor = listener.listen();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let mut stream = TcpStream::connect(("localhost", socket_addr.port));
stream.write(&[144]).unwrap();
});
let addr = next_test_ip4();
let mut acceptor = TcpListener::bind(addr).listen();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let mut stream = TcpStream::connect(("localhost", addr.port));
stream.write(&[64]).unwrap();
});
let addr = next_test_ip4();
let mut acceptor = TcpListener::bind(addr).listen();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let mut stream = TcpStream::connect(("127.0.0.1", addr.port));
stream.write(&[44]).unwrap();
});
let addr = next_test_ip6();
let mut acceptor = TcpListener::bind(addr).listen();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let mut stream = TcpStream::connect(("::1", addr.port));
stream.write(&[66]).unwrap();
});
let addr = next_test_ip4();
let mut acceptor = TcpListener::bind(addr).listen();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let mut stream = TcpStream::connect(addr);
stream.write(&[99]).unwrap();
});
let addr = next_test_ip6();
let mut acceptor = TcpListener::bind(addr).listen();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let mut stream = TcpStream::connect(addr);
stream.write(&[99]).unwrap();
});
let addr = next_test_ip4();
let mut acceptor = TcpListener::bind(addr).listen();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let _stream = TcpStream::connect(addr);
// Close
});
let addr = next_test_ip6();
let mut acceptor = TcpListener::bind(addr).listen();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let _stream = TcpStream::connect(addr);
// Close
});
let addr = next_test_ip4();
let mut acceptor = TcpListener::bind(addr).listen();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let _stream = TcpStream::connect(addr);
// Close
});
let addr = next_test_ip6();
let mut acceptor = TcpListener::bind(addr).listen();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let _stream = TcpStream::connect(addr);
// Close
});
let mut acceptor = TcpListener::bind(addr).listen();
let (tx, rx) = channel();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
drop(TcpStream::connect(addr));
tx.send(()).unwrap();
});
let mut acceptor = TcpListener::bind(addr).listen();
let (tx, rx) = channel();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
drop(TcpStream::connect(addr));
tx.send(()).unwrap();
});
let max = 10u;
let mut acceptor = TcpListener::bind(addr).listen();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
for _ in 0..max {
let mut stream = TcpStream::connect(addr);
stream.write(&[99]).unwrap();
let max = 10u;
let mut acceptor = TcpListener::bind(addr).listen();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
for _ in 0..max {
let mut stream = TcpStream::connect(addr);
stream.write(&[99]).unwrap();
static MAX: int = 10;
let acceptor = TcpListener::bind(addr).listen();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let mut acceptor = acceptor;
for (i, stream) in acceptor.incoming().enumerate().take(MAX as uint) {
// Start another task to handle the connection
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let mut stream = stream;
let mut buf = [0];
stream.read(&mut buf).unwrap();
fn connect(i: int, addr: SocketAddr) {
if i == MAX { return }
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
debug!("connecting");
let mut stream = TcpStream::connect(addr);
// Connect again before writing
static MAX: int = 10;
let acceptor = TcpListener::bind(addr).listen();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let mut acceptor = acceptor;
for (i, stream) in acceptor.incoming().enumerate().take(MAX as uint) {
// Start another task to handle the connection
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let mut stream = stream;
let mut buf = [0];
stream.read(&mut buf).unwrap();
fn connect(i: int, addr: SocketAddr) {
if i == MAX { return }
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
debug!("connecting");
let mut stream = TcpStream::connect(addr);
// Connect again before writing
let addr = next_test_ip4();
let acceptor = TcpListener::bind(addr).listen();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let mut acceptor = acceptor;
for stream in acceptor.incoming().take(MAX as uint) {
// Start another task to handle the connection
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let mut stream = stream;
let mut buf = [0];
stream.read(&mut buf).unwrap();
fn connect(i: int, addr: SocketAddr) {
if i == MAX { return }
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
debug!("connecting");
let mut stream = TcpStream::connect(addr);
// Connect again before writing
let addr = next_test_ip6();
let acceptor = TcpListener::bind(addr).listen();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let mut acceptor = acceptor;
for stream in acceptor.incoming().take(MAX as uint) {
// Start another task to handle the connection
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let mut stream = stream;
let mut buf = [0];
stream.read(&mut buf).unwrap();
fn connect(i: int, addr: SocketAddr) {
if i == MAX { return }
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
debug!("connecting");
let mut stream = TcpStream::connect(addr);
// Connect again before writing
pub fn peer_name(addr: SocketAddr) {
let acceptor = TcpListener::bind(addr).listen();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let mut acceptor = acceptor;
acceptor.accept().unwrap();
});
fn partial_read() {
let addr = next_test_ip4();
let (tx, rx) = channel();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let mut srv = TcpListener::bind(addr).listen().unwrap();
tx.send(()).unwrap();
let mut cl = srv.accept().unwrap();
let addr = next_test_ip4();
let (tx, rx) = channel();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
rx.recv().unwrap();
let _stream = TcpStream::connect(addr).unwrap();
// Close
let addr = next_test_ip4();
let mut acceptor = TcpListener::bind(addr).listen();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let mut s = TcpStream::connect(addr);
let mut buf = [0, 0];
assert_eq!(s.read(&mut buf), Ok(1));
let (tx1, rx1) = channel();
let (tx2, rx2) = channel();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let mut s2 = s2;
rx1.recv().unwrap();
s2.write(&[1]).unwrap();
let (tx1, rx) = channel();
let tx2 = tx1.clone();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let mut s = TcpStream::connect(addr);
s.write(&[1]).unwrap();
rx.recv().unwrap();
let s2 = s1.clone();
let (done, rx) = channel();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let mut s2 = s2;
let mut buf = [0, 0];
s2.read(&mut buf).unwrap();
let addr = next_test_ip4();
let mut acceptor = TcpListener::bind(addr).listen();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let mut s = TcpStream::connect(addr);
let mut buf = [0, 1];
s.read(&mut buf).unwrap();
let s2 = s1.clone();
let (done, rx) = channel();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let mut s2 = s2;
s2.write(&[1]).unwrap();
done.send(()).unwrap();
fn shutdown_smoke() {
let addr = next_test_ip4();
let a = TcpListener::bind(addr).unwrap().listen();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let mut a = a;
let mut c = a.accept().unwrap();
assert_eq!(c.read_to_end(), Ok(vec!()));
// flakiness.
if !cfg!(target_os = "freebsd") {
let (tx, rx) = channel();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
tx.send(TcpStream::connect(addr).unwrap()).unwrap();
});
let _l = rx.recv().unwrap();
Err(ref e) if e.kind == TimedOut => {}
Err(e) => panic!("error: {}", e),
}
- ::thread::Thread::yield_now();
+ ::thread::yield_now();
if i == 1000 { panic!("should have a pending connection") }
}
}
// Unset the timeout and make sure that this always blocks.
a.set_timeout(None);
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
drop(TcpStream::connect(addr).unwrap());
});
a.accept().unwrap();
let addr = next_test_ip4();
let a = TcpListener::bind(addr).listen().unwrap();
let (_tx, rx) = channel::<()>();
- Thread::spawn(move|| {
+ thread::spawn(move|| {
let mut a = a;
let _s = a.accept().unwrap();
let _ = rx.recv().unwrap();
let addr = next_test_ip4();
let a = TcpListener::bind(addr).listen().unwrap();
let (_tx, rx) = channel::<()>();
- Thread::spawn(move|| {
+ thread::spawn(move|| {
let mut a = a;
let _s = a.accept().unwrap();
let _ = rx.recv().unwrap();
let mut s = TcpStream::connect(addr).unwrap();
let s2 = s.clone();
let (tx, rx) = channel();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let mut s2 = s2;
assert!(s2.read(&mut [0]).is_err());
tx.send(()).unwrap();
let addr = next_test_ip6();
let mut a = TcpListener::bind(addr).listen().unwrap();
let (tx, rx) = channel::<()>();
- Thread::spawn(move|| {
+ thread::spawn(move|| {
let mut s = TcpStream::connect(addr).unwrap();
rx.recv().unwrap();
assert!(s.write(&[0]).is_ok());
let addr = next_test_ip6();
let mut a = TcpListener::bind(addr).listen().unwrap();
let (tx, rx) = channel::<()>();
- Thread::spawn(move|| {
+ thread::spawn(move|| {
let mut s = TcpStream::connect(addr).unwrap();
rx.recv().unwrap();
let mut amt = 0;
let addr = next_test_ip6();
let mut a = TcpListener::bind(addr).listen().unwrap();
let (tx, rx) = channel::<()>();
- Thread::spawn(move|| {
+ thread::spawn(move|| {
let mut s = TcpStream::connect(addr).unwrap();
rx.recv().unwrap();
assert!(s.write(&[0]).is_ok());
let addr = next_test_ip6();
let mut a = TcpListener::bind(addr).listen().unwrap();
let (tx, rx) = channel::<()>();
- Thread::spawn(move|| {
+ thread::spawn(move|| {
let mut s = TcpStream::connect(addr).unwrap();
rx.recv().unwrap();
assert_eq!(s.write(&[0]), Ok(()));
let mut s = a.accept().unwrap();
let s2 = s.clone();
let (tx2, rx2) = channel();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let mut s2 = s2;
assert_eq!(s2.read(&mut [0]), Ok(1));
tx2.send(()).unwrap();
let (tx, rx) = channel();
let (txdone, rxdone) = channel();
let txdone2 = txdone.clone();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let mut tcp = TcpStream::connect(addr).unwrap();
rx.recv().unwrap();
tcp.write_u8(0).unwrap();
let tcp = accept.accept().unwrap();
let tcp2 = tcp.clone();
let txdone3 = txdone.clone();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let mut tcp2 = tcp2;
tcp2.read_u8().unwrap();
txdone3.send(()).unwrap();
// Try to ensure that the reading clone is indeed reading
for _ in 0..50 {
- ::thread::Thread::yield_now();
+ ::thread::yield_now();
}
// clone the handle again while it's reading, then let it finish the
let mut a = l.listen().unwrap();
let mut a2 = a.clone();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let _ = TcpStream::connect(addr);
});
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let _ = TcpStream::connect(addr);
});
let (tx, rx) = channel();
let tx2 = tx.clone();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let mut a = a;
tx.send(a.accept()).unwrap();
});
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let mut a = a2;
tx2.send(a.accept()).unwrap();
});
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let _ = TcpStream::connect(addr);
});
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let _ = TcpStream::connect(addr);
});
let mut a2 = a.clone();
let (tx, rx) = channel();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let mut a = a;
tx.send(a.accept()).unwrap();
});
use old_io::test::*;
use old_io::{IoError, TimedOut, PermissionDenied, ShortWrite};
use super::*;
- use thread::Thread;
+ use thread;
// FIXME #11530 this fails on android because tests are run as root
#[cfg_attr(any(windows, target_os = "android"), ignore)]
let (tx1, rx1) = channel();
let (tx2, rx2) = channel();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
match UdpSocket::bind(client_ip) {
Ok(ref mut client) => {
rx1.recv().unwrap();
let client_ip = next_test_ip6();
let (tx, rx) = channel::<()>();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
match UdpSocket::bind(client_ip) {
Ok(ref mut client) => {
rx.recv().unwrap();
let mut sock1 = UdpSocket::bind(addr1).unwrap();
let sock2 = UdpSocket::bind(addr2).unwrap();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let mut sock2 = sock2;
let mut buf = [0, 0];
assert_eq!(sock2.recv_from(&mut buf), Ok((1, addr1)));
let (tx1, rx1) = channel();
let (tx2, rx2) = channel();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let mut sock3 = sock3;
rx1.recv().unwrap();
sock3.send_to(&[1], addr2).unwrap();
let (tx1, rx) = channel();
let tx2 = tx1.clone();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let mut sock2 = sock2;
sock2.send_to(&[1], addr1).unwrap();
rx.recv().unwrap();
let sock3 = sock1.clone();
let (done, rx) = channel();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let mut sock3 = sock3;
let mut buf = [0, 0];
sock3.recv_from(&mut buf).unwrap();
let (tx, rx) = channel();
let (serv_tx, serv_rx) = channel();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let mut sock2 = sock2;
let mut buf = [0, 1];
let (done, rx) = channel();
let tx2 = tx.clone();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let mut sock3 = sock3;
match sock3.send_to(&[1], addr2) {
Ok(..) => { let _ = tx2.send(()); }
let (tx, rx) = channel();
let (tx2, rx2) = channel();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let mut a = a2;
assert_eq!(a.recv_from(&mut [0]), Ok((1, addr1)));
assert_eq!(a.send_to(&[0], addr1), Ok(()));
use prelude::v1::*;
use sync::mpsc::channel;
- use thread::Thread;
+ use thread;
#[test]
fn partial_read() {
let out = PipeStream::open(writer);
let mut input = PipeStream::open(reader);
let (tx, rx) = channel();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let mut out = out;
out.write(&[10]).unwrap();
rx.recv().unwrap(); // don't close the pipe until the other read has finished
use sys::fs::FileDesc;
use sys::process::Process as ProcessImp;
use sys;
-use thread::Thread;
+use thread;
#[cfg(windows)] use hash;
#[cfg(windows)] use str;
let (tx, rx) = channel();
match stream {
Some(stream) => {
- Thread::spawn(move || {
+ thread::spawn(move || {
let mut stream = stream;
tx.send(stream.read_to_end()).unwrap();
});
use super::{CreatePipe};
use super::{InheritFd, Process, PleaseExitSignal, Command, ProcessOutput};
use sync::mpsc::channel;
- use thread::Thread;
+ use thread;
use time::Duration;
// FIXME(#10380) these tests should not all be ignored on android.
#[cfg(all(unix, not(target_os="android")))]
#[test]
fn signal_reported_right() {
- let p = Command::new("/bin/sh").arg("-c").arg("kill -1 $$").spawn();
+ let p = Command::new("/bin/sh").arg("-c").arg("kill -9 $$").spawn();
assert!(p.is_ok());
let mut p = p.unwrap();
match p.wait().unwrap() {
- process::ExitSignal(1) => {},
- result => panic!("not terminated by signal 1 (instead, {})", result),
+ process::ExitSignal(9) => {},
+ result => panic!("not terminated by signal 9 (instead, {})", result),
}
}
fn wait_timeout2() {
let (tx, rx) = channel();
let tx2 = tx.clone();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let mut p = sleeper();
p.set_timeout(Some(10));
assert_eq!(p.wait().err().unwrap().kind, TimedOut);
p.signal_kill().unwrap();
tx.send(()).unwrap();
});
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let mut p = sleeper();
p.set_timeout(Some(10));
assert_eq!(p.wait().err().unwrap().kind, TimedOut);
use super::*;
use sync::mpsc::channel;
- use thread::Thread;
+ use thread;
#[test]
fn smoke() {
let (tx, rx) = channel();
let (mut r, w) = (ChanReader::new(rx), ChanWriter::new(tx));
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
set_stdout(box w);
println!("hello!");
});
let (tx, rx) = channel();
let (mut r, w) = (ChanReader::new(rx), ChanWriter::new(tx));
- let _t = Thread::spawn(move || -> () {
+ let _t = thread::spawn(move || -> () {
set_stderr(box w);
panic!("my special message");
});
#[cfg(test)]
mod test {
use super::Timer;
- use thread::Thread;
+ use thread;
use time::Duration;
#[test]
fn test_timer_send() {
let mut timer = Timer::new().unwrap();
- Thread::spawn(move || timer.sleep(Duration::milliseconds(1)));
+ thread::spawn(move || timer.sleep(Duration::milliseconds(1)));
}
#[test]
let mut timer = Timer::new().unwrap();
let timer_rx = timer.periodic(Duration::milliseconds(1000));
- Thread::spawn(move|| {
+ thread::spawn(move|| {
let _ = timer_rx.recv();
});
let mut timer = Timer::new().unwrap();
let timer_rx = timer.periodic(Duration::milliseconds(1000));
- Thread::spawn(move|| {
+ thread::spawn(move|| {
let _ = timer_rx.recv();
});
let mut timer = Timer::new().unwrap();
let timer_rx = timer.periodic(Duration::milliseconds(1000));
- Thread::spawn(move|| {
+ thread::spawn(move|| {
let _ = timer_rx.recv();
});
//! println!("path exists: {}", path.exists());
//! ```
-#![unstable(feature = "path")]
+#![unstable(feature = "old_path")]
use core::marker::Sized;
use ffi::CString;
#[test]
fn test_null_byte() {
- use thread::Thread;
- let result = Thread::scoped(move|| {
- Path::new(b"foo/bar\0")
+ use thread;
+ let result = thread::spawn(move|| {
+ Path::new(b"foo/bar\0");
}).join();
assert!(result.is_err());
- let result = Thread::scoped(move|| {
+ let result = thread::spawn(move|| {
Path::new("test").set_filename(b"f\0o")
}).join();
assert!(result.is_err());
- let result = Thread::scoped(move|| {
+ let result = thread::spawn(move|| {
Path::new("test").push(b"f\0o");
}).join();
assert!(result.is_err());
let exp: &[&[u8]] = &[$($exp),*];
assert_eq!(comps, exp);
let comps = path.components().rev().collect::<Vec<&[u8]>>();
- let exp = exp.iter().rev().map(|&x|x).collect::<Vec<&[u8]>>();
+ let exp = exp.iter().rev().cloned().collect::<Vec<&[u8]>>();
assert_eq!(comps, exp)
}
)
let exp: &[Option<&str>] = &$exp;
assert_eq!(comps, exp);
let comps = path.str_components().rev().collect::<Vec<Option<&str>>>();
- let exp = exp.iter().rev().map(|&x|x).collect::<Vec<Option<&str>>>();
+ let exp = exp.iter().rev().cloned().collect::<Vec<Option<&str>>>();
assert_eq!(comps, exp);
}
)
#[test]
fn test_null_byte() {
- use thread::Thread;
- let result = Thread::scoped(move|| {
- Path::new(b"foo/bar\0")
+ use thread;
+ let result = thread::spawn(move|| {
+ Path::new(b"foo/bar\0");
}).join();
assert!(result.is_err());
- let result = Thread::scoped(move|| {
+ let result = thread::spawn(move|| {
Path::new("test").set_filename(b"f\0o")
}).join();
assert!(result.is_err());
- let result = Thread::scoped(move || {
+ let result = thread::spawn(move || {
Path::new("test").push(b"f\0o");
}).join();
assert!(result.is_err());
assert_eq!(comps, exp);
let comps = path.str_components().rev().map(|x|x.unwrap())
.collect::<Vec<&str>>();
- let exp = exp.iter().rev().map(|&x|x).collect::<Vec<&str>>();
+ let exp = exp.iter().rev().cloned().collect::<Vec<&str>>();
assert_eq!(comps, exp);
}
);
let exp: &[&[u8]] = &$exp;
assert_eq!(comps, exp);
let comps = path.components().rev().collect::<Vec<&[u8]>>();
- let exp = exp.iter().rev().map(|&x|x).collect::<Vec<&[u8]>>();
+ let exp = exp.iter().rev().cloned().collect::<Vec<&[u8]>>();
assert_eq!(comps, exp);
}
)
use old_io::IoResult;
use rt::{backtrace, unwind};
use rt::util::{Stderr, Stdio};
-use thread::Thread;
+use thread;
// Defined in this module instead of old_io::stdio so that the unwinding
thread_local! {
}
};
let mut err = Stderr;
- let thread = Thread::current();
+ let thread = thread::current();
let name = thread.name().unwrap_or("<unnamed>");
let prev = LOCAL_STDERR.with(|s| s.borrow_mut().take());
match prev {
use core::prelude::*;
+use ascii::*;
use borrow::BorrowFrom;
use cmp;
use iter;
use ffi::{OsStr, OsString, AsOsStr};
-use self::platform::{is_sep, is_verbatim_sep, MAIN_SEP_STR, parse_prefix, Prefix};
+use self::platform::{is_sep_byte, is_verbatim_sep, MAIN_SEP_STR, parse_prefix};
////////////////////////////////////////////////////////////////////////////////
// GENERAL NOTES
#[cfg(unix)]
mod platform {
+ use super::Prefix;
use core::prelude::*;
use ffi::OsStr;
#[inline]
- pub fn is_sep(b: u8) -> bool {
+ pub fn is_sep_byte(b: u8) -> bool {
b == b'/'
}
None
}
- #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
- pub struct Prefix<'a>;
-
- impl<'a> Prefix<'a> {
- #[inline]
- pub fn len(&self) -> usize { 0 }
- #[inline]
- pub fn is_verbatim(&self) -> bool { false }
- #[inline]
- pub fn is_drive(&self) -> bool { false }
- #[inline]
- pub fn has_implicit_root(&self) -> bool { false }
- }
-
pub const MAIN_SEP_STR: &'static str = "/";
+ pub const MAIN_SEP: char = '/';
}
#[cfg(windows)]
mod platform {
use core::prelude::*;
+ use ascii::*;
use char::CharExt as UnicodeCharExt;
- use super::{os_str_as_u8_slice, u8_slice_as_os_str};
- use ascii::*;
+ use super::{os_str_as_u8_slice, u8_slice_as_os_str, Prefix};
use ffi::OsStr;
#[inline]
- pub fn is_sep(b: u8) -> bool {
+ pub fn is_sep_byte(b: u8) -> bool {
b == b'/' || b == b'\\'
}
}
pub fn parse_prefix<'a>(path: &'a OsStr) -> Option<Prefix> {
- use self::Prefix::*;
+ use super::Prefix::*;
unsafe {
// The unsafety here stems from converting between &OsStr and &[u8]
// and back. This is safe to do because (1) we only look at ASCII
let c = path[0];
if c.is_ascii() && (c as char).is_alphabetic() {
// \\?\C:\ path
- let slice = u8_slice_as_os_str(&path[0..1]);
- return Some(VerbatimDisk(slice));
+ return Some(VerbatimDisk(c.to_ascii_uppercase()));
}
}
let slice = &path[.. idx.unwrap_or(path.len())];
let slice = &path[.. path.position_elem(&b'\\').unwrap_or(path.len())];
return Some(DeviceNS(u8_slice_as_os_str(slice)));
}
- match parse_two_comps(path, is_sep) {
+ match parse_two_comps(path, is_sep_byte) {
Some((server, share)) if server.len() > 0 && share.len() > 0 => {
// \\server\share
return Some(UNC(u8_slice_as_os_str(server),
// C:
let c = path[0];
if c.is_ascii() && (c as char).is_alphabetic() {
- return Some(Disk(u8_slice_as_os_str(&path[0..1])));
+ return Some(Disk(c.to_ascii_uppercase()));
}
}
return None;
}
}
- /// Windows path prefixes.
- ///
- /// Windows uses a variety of path styles, including references to drive
- /// volumes (like `C:`), network shared (like `\\server\share`) and
- /// others. In addition, some path prefixes are "verbatim", in which case
- /// `/` is *not* treated as a separator and essentially no normalization is
- /// performed.
- #[derive(Copy, Clone, Debug, Hash, Eq)]
- pub enum Prefix<'a> {
- /// Prefix `\\?\`, together with the given component immediately following it.
- Verbatim(&'a OsStr),
-
- /// Prefix `\\?\UNC\`, with the "server" and "share" components following it.
- VerbatimUNC(&'a OsStr, &'a OsStr),
-
- /// Prefix like `\\?\C:\`, for the given drive letter
- VerbatimDisk(&'a OsStr),
-
- /// Prefix `\\.\`, together with the given component immediately following it.
- DeviceNS(&'a OsStr),
-
- /// Prefix `\\server\share`, with the given "server" and "share" components.
- UNC(&'a OsStr, &'a OsStr),
-
- /// Prefix `C:` for the given disk drive.
- Disk(&'a OsStr),
- }
-
- impl<'a> Prefix<'a> {
- #[inline]
- pub fn len(&self) -> usize {
- use self::Prefix::*;
- fn os_str_len(s: &OsStr) -> usize {
- os_str_as_u8_slice(s).len()
- }
- match *self {
- Verbatim(x) => 4 + os_str_len(x),
- VerbatimUNC(x,y) => 8 + os_str_len(x) +
- if os_str_len(y) > 0 { 1 + os_str_len(y) }
- else { 0 },
- VerbatimDisk(_) => 6,
- UNC(x,y) => 2 + os_str_len(x) +
- if os_str_len(y) > 0 { 1 + os_str_len(y) }
- else { 0 },
- DeviceNS(x) => 4 + os_str_len(x),
- Disk(_) => 2
- }
+ pub const MAIN_SEP_STR: &'static str = "\\";
+ pub const MAIN_SEP: char = '\\';
+}
- }
+////////////////////////////////////////////////////////////////////////////////
+// Windows Prefixes
+////////////////////////////////////////////////////////////////////////////////
- #[inline]
- pub fn is_verbatim(&self) -> bool {
- use self::Prefix::*;
- match *self {
- Verbatim(_) | VerbatimDisk(_) | VerbatimUNC(_, _) => true,
- _ => false
- }
- }
+/// Path prefixes (Windows only).
+///
+/// Windows uses a variety of path styles, including references to drive
+/// volumes (like `C:`), network shared (like `\\server\share`) and
+/// others. In addition, some path prefixes are "verbatim", in which case
+/// `/` is *not* treated as a separator and essentially no normalization is
+/// performed.
+#[derive(Copy, Clone, Debug, Hash, PartialOrd, Ord, PartialEq, Eq)]
+pub enum Prefix<'a> {
+ /// Prefix `\\?\`, together with the given component immediately following it.
+ Verbatim(&'a OsStr),
+
+ /// Prefix `\\?\UNC\`, with the "server" and "share" components following it.
+ VerbatimUNC(&'a OsStr, &'a OsStr),
+
+ /// Prefix like `\\?\C:\`, for the given drive letter
+ VerbatimDisk(u8),
+
+ /// Prefix `\\.\`, together with the given component immediately following it.
+ DeviceNS(&'a OsStr),
+
+ /// Prefix `\\server\share`, with the given "server" and "share" components.
+ UNC(&'a OsStr, &'a OsStr),
+
+ /// Prefix `C:` for the given disk drive.
+ Disk(u8),
+}
- #[inline]
- pub fn is_drive(&self) -> bool {
- match *self {
- Prefix::Disk(_) => true,
- _ => false,
- }
+impl<'a> Prefix<'a> {
+ #[inline]
+ fn len(&self) -> usize {
+ use self::Prefix::*;
+ fn os_str_len(s: &OsStr) -> usize {
+ os_str_as_u8_slice(s).len()
+ }
+ match *self {
+ Verbatim(x) => 4 + os_str_len(x),
+ VerbatimUNC(x,y) => 8 + os_str_len(x) +
+ if os_str_len(y) > 0 { 1 + os_str_len(y) }
+ else { 0 },
+ VerbatimDisk(_) => 6,
+ UNC(x,y) => 2 + os_str_len(x) +
+ if os_str_len(y) > 0 { 1 + os_str_len(y) }
+ else { 0 },
+ DeviceNS(x) => 4 + os_str_len(x),
+ Disk(_) => 2
}
- #[inline]
- pub fn has_implicit_root(&self) -> bool {
- !self.is_drive()
+ }
+
+ /// Determine if the prefix is verbatim, i.e. begins `\\?\`.
+ #[inline]
+ pub fn is_verbatim(&self) -> bool {
+ use self::Prefix::*;
+ match *self {
+ Verbatim(_) | VerbatimDisk(_) | VerbatimUNC(_, _) => true,
+ _ => false
}
}
- impl<'a> PartialEq for Prefix<'a> {
- fn eq(&self, other: &Prefix<'a>) -> bool {
- use self::Prefix::*;
- match (*self, *other) {
- (Verbatim(x), Verbatim(y)) => x == y,
- (VerbatimUNC(x1, x2), VerbatimUNC(y1, y2)) => x1 == y1 && x2 == y2,
- (VerbatimDisk(x), VerbatimDisk(y)) =>
- os_str_as_u8_slice(x).eq_ignore_ascii_case(os_str_as_u8_slice(y)),
- (DeviceNS(x), DeviceNS(y)) => x == y,
- (UNC(x1, x2), UNC(y1, y2)) => x1 == y1 && x2 == y2,
- (Disk(x), Disk(y)) =>
- os_str_as_u8_slice(x).eq_ignore_ascii_case(os_str_as_u8_slice(y)),
- _ => false,
- }
+ #[inline]
+ fn is_drive(&self) -> bool {
+ match *self {
+ Prefix::Disk(_) => true,
+ _ => false,
}
}
- pub const MAIN_SEP_STR: &'static str = "\\";
+ #[inline]
+ fn has_implicit_root(&self) -> bool {
+ !self.is_drive()
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Exposed parsing helpers
+////////////////////////////////////////////////////////////////////////////////
+
+/// Determine whether the character is one of the permitted path
+/// separators for the current platform.
+pub fn is_separator(c: char) -> bool {
+ use ascii::*;
+ c.is_ascii() && is_sep_byte(c as u8)
}
+/// The primary sperator for the current platform
+pub const MAIN_SEPARATOR: char = platform::MAIN_SEP;
+
////////////////////////////////////////////////////////////////////////////////
// Misc helpers
////////////////////////////////////////////////////////////////////////////////
(p.len(), p.is_verbatim())
} else { (0, false) };
if prefix_len > 0 && prefix_len == s.len() && !verbatim { return true; }
- let mut splits = s[prefix_len..].split(|b| is_sep(*b));
+ let mut splits = s[prefix_len..].split(|b| is_sep_byte(*b));
let last = splits.next_back().unwrap();
let more = splits.next_back().is_some();
more && last == b""
/// Says whether the first byte after the prefix is a separator.
fn has_physical_root(s: &[u8], prefix: Option<Prefix>) -> bool {
let path = if let Some(p) = prefix { &s[p.len()..] } else { s };
- path.len() > 0 && is_sep(path[0])
+ path.len() > 0 && is_sep_byte(path[0])
}
fn parse_single_component(comp: &[u8]) -> Option<Component> {
/// their role in the API.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub enum Component<'a> {
- /// A Windows path prefix, e.g. `C:` or `\server\share`
- Prefix(&'a OsStr),
+ /// A Windows path prefix, e.g. `C:` or `\server\share`.
+ ///
+ /// Does not occur on Unix.
+ Prefix {
+ /// The prefix as an unparsed `OsStr` slice.
+ raw: &'a OsStr,
+
+ /// The parsed prefix data.
+ parsed: Prefix<'a>
+ },
/// An empty component. Only used on Windows for the last component of
/// verbatim paths ending with a separator (e.g. the last component of
/// Extract the underlying `OsStr` slice
pub fn as_os_str(self) -> &'a OsStr {
match self {
- Component::Prefix(path) => path,
+ Component::Prefix { raw, .. } => &raw,
Component::Empty => OsStr::from_str(""),
Component::RootDir => OsStr::from_str(MAIN_SEP_STR),
Component::CurDir => OsStr::from_str("."),
}
#[inline]
- fn is_sep(&self, b: u8) -> bool {
+ fn is_sep_byte(&self, b: u8) -> bool {
if self.prefix_verbatim() {
is_verbatim_sep(b)
} else {
- is_sep(b)
+ is_sep_byte(b)
}
}
// remove the component
fn parse_next_component(&self) -> (usize, Option<Component<'a>>) {
debug_assert!(self.front == State::Body);
- let (extra, comp) = match self.path.iter().position(|b| self.is_sep(*b)) {
+ let (extra, comp) = match self.path.iter().position(|b| self.is_sep_byte(*b)) {
None => (0, self.path),
Some(i) => (1, &self.path[.. i]),
};
fn parse_next_component_back(&self) -> (usize, Option<Component<'a>>) {
debug_assert!(self.back == State::Body);
let start = self.prefix_and_root();
- let (extra, comp) = match self.path[start..].iter().rposition(|b| self.is_sep(*b)) {
+ let (extra, comp) = match self.path[start..].iter().rposition(|b| self.is_sep_byte(*b)) {
None => (0, &self.path[start ..]),
Some(i) => (1, &self.path[start + i + 1 ..]),
};
State::Prefix if self.prefix_len() > 0 => {
self.front = State::Root;
debug_assert!(self.prefix_len() <= self.path.len());
- let prefix = &self.path[.. self.prefix_len()];
+ let raw = &self.path[.. self.prefix_len()];
self.path = &self.path[self.prefix_len() .. ];
- return Some(Component::Prefix(unsafe { u8_slice_as_os_str(prefix) }))
+ return Some(Component::Prefix {
+ raw: unsafe { u8_slice_as_os_str(raw) },
+ parsed: self.prefix.unwrap()
+ })
}
State::Prefix => {
self.front = State::Root;
}
State::Prefix if self.prefix_len() > 0 => {
self.back = State::Done;
- return Some(Component::Prefix(unsafe {
- u8_slice_as_os_str(self.path)
- }))
+ return Some(Component::Prefix {
+ raw: unsafe { u8_slice_as_os_str(self.path) },
+ parsed: self.prefix.unwrap()
+ })
}
State::Prefix => {
self.back = State::Done;
/// * if `path` has a prefix but no root, it replaces `self.
pub fn push<P: ?Sized>(&mut self, path: &P) where P: AsPath {
// in general, a separator is needed if the rightmost byte is not a separator
- let mut need_sep = self.as_mut_vec().last().map(|c| !is_sep(*c)).unwrap_or(false);
+ let mut need_sep = self.as_mut_vec().last().map(|c| !is_sep_byte(*c)).unwrap_or(false);
// in the special case of `C:` on Windows, do *not* add a separator
{
match (comp, comps.next_back()) {
(Some(Component::CurDir), Some(Component::RootDir)) => None,
- (Some(Component::CurDir), Some(Component::Prefix(_))) => None,
+ (Some(Component::CurDir), Some(Component::Prefix { .. })) => None,
(Some(Component::Empty), Some(Component::RootDir)) => None,
- (Some(Component::Empty), Some(Component::Prefix(_))) => None,
- (Some(Component::Prefix(_)), None) => None,
- (Some(Component::RootDir), Some(Component::Prefix(_))) => None,
+ (Some(Component::Empty), Some(Component::Prefix { .. })) => None,
+ (Some(Component::Prefix { .. }), None) => None,
+ (Some(Component::RootDir), Some(Component::Prefix { .. })) => None,
_ => rest
}
}
use sys::process2::Command as CommandImp;
use sys::process2::ExitStatus as ExitStatusImp;
use sys_common::{AsInner, AsInnerMut};
-use thread::Thread;
+use thread;
/// Representation of a running or exited child process.
///
/// the parent waits for the child to exit.
pub fn wait_with_output(mut self) -> io::Result<Output> {
drop(self.stdin.take());
- fn read<T: Read + Send>(stream: Option<T>) -> Receiver<io::Result<Vec<u8>>> {
+ fn read<T: Read + Send + 'static>(stream: Option<T>) -> Receiver<io::Result<Vec<u8>>> {
let (tx, rx) = channel();
match stream {
Some(stream) => {
- Thread::spawn(move || {
+ thread::spawn(move || {
let mut stream = stream;
let mut ret = Vec::new();
let res = stream.read_to_end(&mut ret);
use str;
use super::{Child, Command, Output, ExitStatus, Stdio};
use sync::mpsc::channel;
- use thread::Thread;
+ use thread;
use time::Duration;
// FIXME(#10380) these tests should not all be ignored on android.
fn signal_reported_right() {
use os::unix::ExitStatusExt;
- let p = Command::new("/bin/sh").arg("-c").arg("kill -1 $$").spawn();
+ let p = Command::new("/bin/sh").arg("-c").arg("kill -9 $$").spawn();
assert!(p.is_ok());
let mut p = p.unwrap();
match p.wait().unwrap().signal() {
- Some(1) => {},
- result => panic!("not terminated by signal 1 (instead, {:?})", result),
+ Some(9) => {},
+ result => panic!("not terminated by signal 9 (instead, {:?})", result),
}
}
#[test]
fn test_choose() {
let mut r = thread_rng();
- assert_eq!(r.choose(&[1, 1, 1]).map(|&x|x), Some(1));
+ assert_eq!(r.choose(&[1, 1, 1]).cloned(), Some(1));
let v: &[int] = &[];
assert_eq!(r.choose(v), None);
use sync::mpsc::channel;
use rand::Rng;
use super::OsRng;
- use thread::Thread;
+ use thread;
#[test]
fn test_os_rng() {
let (tx, rx) = channel();
txs.push(tx);
- Thread::spawn(move|| {
+ thread::spawn(move|| {
// wait until all the tasks are ready to go.
rx.recv().unwrap();
// deschedule to attempt to interleave things as much
// as possible (XXX: is this a good test?)
let mut r = OsRng::new().unwrap();
- Thread::yield_now();
+ thread::yield_now();
let mut v = [0u8; 1000];
for _ in 0u..100 {
r.next_u32();
- Thread::yield_now();
+ thread::yield_now();
r.next_u64();
- Thread::yield_now();
+ thread::yield_now();
r.fill_bytes(&mut v);
- Thread::yield_now();
+ thread::yield_now();
}
});
}
use thunk::Thunk;
use sys_common::mutex::{Mutex, MUTEX_INIT};
-type Queue = Vec<Thunk>;
+type Queue = Vec<Thunk<'static>>;
// NB these are specifically not types from `std::sync` as they currently rely
// on poisoning and this module needs to operate at a lower level than requiring
}
}
-pub fn push(f: Thunk) {
+pub fn push(f: Thunk<'static>) {
unsafe {
LOCK.lock();
init();
///
/// It is forbidden for procedures to register more `at_exit` handlers when they
/// are running, and doing so will lead to a process abort.
-pub fn at_exit<F:FnOnce()+Send>(f: F) {
+pub fn at_exit<F:FnOnce()+Send+'static>(f: F) {
at_exit_imp::push(Thunk::new(f));
}
struct Exception {
uwe: uw::_Unwind_Exception,
- cause: Option<Box<Any + Send>>,
+ cause: Option<Box<Any + Send + 'static>>,
}
pub type Callback = fn(msg: &(Any + Send), file: &'static str, line: uint);
#[inline(never)]
#[no_mangle]
#[allow(private_no_mangle_fns)]
-fn rust_panic(cause: Box<Any + Send>) -> ! {
+fn rust_panic(cause: Box<Any + Send + 'static>) -> ! {
rtdebug!("begin_unwind()");
unsafe {
#[inline(never)] #[cold]
#[stable(since = "1.0.0", feature = "rust1")]
pub fn begin_unwind_fmt(msg: fmt::Arguments, file_line: &(&'static str, uint)) -> ! {
- use fmt::Writer;
+ use fmt::Write;
// We do two allocations here, unfortunately. But (a) they're
// required with the current scheme, and (b) we don't handle
}
}
-impl fmt::Writer for Stdio {
+impl fmt::Write for Stdio {
fn write_str(&mut self, data: &str) -> fmt::Result {
self.write_bytes(data.as_bytes());
Ok(()) // yes, we're lying
}
pub fn abort(args: fmt::Arguments) -> ! {
- use fmt::Writer;
+ use fmt::Write;
struct BufWriter<'a> {
buf: &'a mut [u8],
pos: uint,
}
- impl<'a> fmt::Writer for BufWriter<'a> {
+ impl<'a> fmt::Write for BufWriter<'a> {
fn write_str(&mut self, bytes: &str) -> fmt::Result {
let left = &mut self.buf[self.pos..];
let to_write = &bytes.as_bytes()[..cmp::min(bytes.len(), left.len())];
}
pub unsafe fn report_overflow() {
- use thread::Thread;
+ use thread;
// See the message below for why this is not emitted to the
// ^ Where did the message below go?
// and the FFI call needs 2MB of stack when we just ran out.
rterrln!("\nthread '{}' has overflowed its stack",
- Thread::current().name().unwrap_or("<unknown>"));
+ thread::current().name().unwrap_or("<unknown>"));
}
///
/// ```rust
/// use std::sync::{Arc, Barrier};
-/// use std::thread::Thread;
+/// use std::thread;
///
/// let barrier = Arc::new(Barrier::new(10));
/// for _ in 0u..10 {
/// let c = barrier.clone();
/// // The same messages will be printed together.
/// // You will NOT see any interleaving.
-/// Thread::spawn(move|| {
+/// thread::spawn(move|| {
/// println!("before wait");
/// c.wait();
/// println!("after wait");
use sync::{Arc, Barrier};
use sync::mpsc::{channel, TryRecvError};
- use thread::Thread;
+ use thread;
#[test]
fn test_barrier() {
for _ in 0u..N - 1 {
let c = barrier.clone();
let tx = tx.clone();
- Thread::spawn(move|| {
+ thread::spawn(move|| {
tx.send(c.wait().is_leader()).unwrap();
});
}
///
/// ```
/// use std::sync::{Arc, Mutex, Condvar};
-/// use std::thread::Thread;
+/// use std::thread;
///
/// let pair = Arc::new((Mutex::new(false), Condvar::new()));
/// let pair2 = pair.clone();
///
/// // Inside of our lock, spawn a new thread, and then wait for it to start
-/// Thread::spawn(move|| {
+/// thread::spawn(move|| {
/// let &(ref lock, ref cvar) = &*pair2;
/// let mut started = lock.lock().unwrap();
/// *started = true;
use sync::mpsc::channel;
use sync::{StaticMutex, MUTEX_INIT, Condvar, Mutex, Arc};
use sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
- use thread::Thread;
+ use thread;
use time::Duration;
#[test]
static M: StaticMutex = MUTEX_INIT;
let g = M.lock().unwrap();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let _g = M.lock().unwrap();
C.notify_one();
});
for _ in 0..N {
let data = data.clone();
let tx = tx.clone();
- Thread::spawn(move|| {
+ thread::spawn(move|| {
let &(ref lock, ref cond) = &*data;
let mut cnt = lock.lock().unwrap();
*cnt += 1;
let (g, _no_timeout) = C.wait_timeout(g, Duration::nanoseconds(1000)).unwrap();
// spurious wakeups mean this isn't necessarily true
// assert!(!no_timeout);
- let _t = Thread::spawn(move || {
+ let _t = thread::spawn(move || {
let _g = M.lock().unwrap();
C.notify_one();
});
assert!(!success);
let (tx, rx) = channel();
- let _t = Thread::scoped(move || {
+ let _t = thread::spawn(move || {
rx.recv().unwrap();
let g = M.lock().unwrap();
S.store(1, Ordering::SeqCst);
static C: StaticCondvar = CONDVAR_INIT;
let mut g = M1.lock().unwrap();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let _g = M1.lock().unwrap();
C.notify_one();
});
use self::FutureState::*;
use sync::mpsc::{Receiver, channel};
use thunk::{Thunk};
-use thread::Thread;
+use thread;
/// A type encapsulating the result of a computation which may not be complete
pub struct Future<A> {
}
enum FutureState<A> {
- Pending(Thunk<(),A>),
+ Pending(Thunk<'static,(),A>),
Evaluating,
Forced(A)
}
}
pub fn from_fn<F>(f: F) -> Future<A>
- where F : FnOnce() -> A, F : Send
+ where F : FnOnce() -> A, F : Send + 'static
{
/*!
* Create a future from a function.
}
}
-impl<A:Send> Future<A> {
+impl<A:Send+'static> Future<A> {
pub fn from_receiver(rx: Receiver<A>) -> Future<A> {
/*!
* Create a future from a port
}
pub fn spawn<F>(blk: F) -> Future<A>
- where F : FnOnce() -> A, F : Send
+ where F : FnOnce() -> A, F : Send + 'static
{
/*!
* Create a future from a unique closure.
let (tx, rx) = channel();
- Thread::spawn(move || {
+ thread::spawn(move || {
// Don't panic if the other end has hung up
let _ = tx.send(blk());
});
use prelude::v1::*;
use sync::mpsc::channel;
use sync::Future;
- use thread::Thread;
+ use thread;
#[test]
fn test_from_value() {
let expected = "schlorf";
let (tx, rx) = channel();
let f = Future::spawn(move|| { expected });
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let mut f = f;
tx.send(f.get()).unwrap();
});
//! Generic support for building blocking abstractions.
-use thread::Thread;
+use thread::{self, Thread};
use sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering};
use sync::Arc;
use marker::{Sync, Send};
pub fn tokens() -> (WaitToken, SignalToken) {
let inner = Arc::new(Inner {
- thread: Thread::current(),
+ thread: thread::current(),
woken: ATOMIC_BOOL_INIT,
});
let wait_token = WaitToken {
impl WaitToken {
pub fn wait(self) {
while !self.inner.woken.load(Ordering::SeqCst) {
- Thread::park()
+ thread::park()
}
}
}
//! Simple usage:
//!
//! ```
-//! use std::thread::Thread;
+//! use std::thread;
//! use std::sync::mpsc::channel;
//!
//! // Create a simple streaming channel
//! let (tx, rx) = channel();
-//! Thread::spawn(move|| {
+//! thread::spawn(move|| {
//! tx.send(10).unwrap();
//! });
//! assert_eq!(rx.recv().unwrap(), 10);
//! Shared usage:
//!
//! ```
-//! use std::thread::Thread;
+//! use std::thread;
//! use std::sync::mpsc::channel;
//!
//! // Create a shared channel that can be sent along from many threads
//! let (tx, rx) = channel();
//! for i in 0..10 {
//! let tx = tx.clone();
-//! Thread::spawn(move|| {
+//! thread::spawn(move|| {
//! tx.send(i).unwrap();
//! });
//! }
//! Synchronous channels:
//!
//! ```
-//! use std::thread::Thread;
+//! use std::thread;
//! use std::sync::mpsc::sync_channel;
//!
//! let (tx, rx) = sync_channel::<int>(0);
-//! Thread::spawn(move|| {
+//! thread::spawn(move|| {
//! // This will wait for the parent task to start receiving
//! tx.send(53).unwrap();
//! });
// The receiver port can be sent from place to place, so long as it
// is not used to receive non-sendable things.
-unsafe impl<T:Send> Send for Receiver<T> { }
+unsafe impl<T: Send + 'static> Send for Receiver<T> { }
/// An iterator over messages on a receiver, this iterator will block
/// whenever `next` is called, waiting for a new message, and `None` will be
// The send port can be sent from place to place, so long as it
// is not used to send non-sendable things.
-unsafe impl<T:Send> Send for Sender<T> { }
+unsafe impl<T: Send + 'static> Send for Sender<T> { }
/// The sending-half of Rust's synchronous channel type. This half can only be
/// owned by one task, but it can be cloned to send to other tasks.
inner: Arc<UnsafeCell<sync::Packet<T>>>,
}
-unsafe impl<T:Send> Send for SyncSender<T> {}
+unsafe impl<T: Send + 'static> Send for SyncSender<T> {}
impl<T> !Sync for SyncSender<T> {}
///
/// ```
/// use std::sync::mpsc::channel;
-/// use std::thread::Thread;
+/// use std::thread;
///
/// // tx is is the sending half (tx for transmission), and rx is the receiving
/// // half (rx for receiving).
/// let (tx, rx) = channel();
///
/// // Spawn off an expensive computation
-/// Thread::spawn(move|| {
+/// thread::spawn(move|| {
/// # fn expensive_computation() {}
/// tx.send(expensive_computation()).unwrap();
/// });
/// println!("{:?}", rx.recv().unwrap());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
-pub fn channel<T: Send>() -> (Sender<T>, Receiver<T>) {
+pub fn channel<T: Send + 'static>() -> (Sender<T>, Receiver<T>) {
let a = Arc::new(UnsafeCell::new(oneshot::Packet::new()));
(Sender::new(Flavor::Oneshot(a.clone())), Receiver::new(Flavor::Oneshot(a)))
}
///
/// ```
/// use std::sync::mpsc::sync_channel;
-/// use std::thread::Thread;
+/// use std::thread;
///
/// let (tx, rx) = sync_channel(1);
///
/// // this returns immediately
/// tx.send(1).unwrap();
///
-/// Thread::spawn(move|| {
+/// thread::spawn(move|| {
/// // this will block until the previous message has been received
/// tx.send(2).unwrap();
/// });
/// assert_eq!(rx.recv().unwrap(), 2);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
-pub fn sync_channel<T: Send>(bound: uint) -> (SyncSender<T>, Receiver<T>) {
+pub fn sync_channel<T: Send + 'static>(bound: uint) -> (SyncSender<T>, Receiver<T>) {
let a = Arc::new(UnsafeCell::new(sync::Packet::new(bound)));
(SyncSender::new(a.clone()), Receiver::new(Flavor::Sync(a)))
}
// Sender
////////////////////////////////////////////////////////////////////////////////
-impl<T: Send> Sender<T> {
+impl<T: Send + 'static> Sender<T> {
fn new(inner: Flavor<T>) -> Sender<T> {
Sender {
inner: UnsafeCell::new(inner),
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Send> Clone for Sender<T> {
+impl<T: Send + 'static> Clone for Sender<T> {
fn clone(&self) -> Sender<T> {
let (packet, sleeper, guard) = match *unsafe { self.inner() } {
Flavor::Oneshot(ref p) => {
#[unsafe_destructor]
#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Send> Drop for Sender<T> {
+impl<T: Send + 'static> Drop for Sender<T> {
fn drop(&mut self) {
match *unsafe { self.inner_mut() } {
Flavor::Oneshot(ref mut p) => unsafe { (*p.get()).drop_chan(); },
// SyncSender
////////////////////////////////////////////////////////////////////////////////
-impl<T: Send> SyncSender<T> {
+impl<T: Send + 'static> SyncSender<T> {
fn new(inner: Arc<UnsafeCell<sync::Packet<T>>>) -> SyncSender<T> {
SyncSender { inner: inner }
}
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Send> Clone for SyncSender<T> {
+impl<T: Send + 'static> Clone for SyncSender<T> {
fn clone(&self) -> SyncSender<T> {
unsafe { (*self.inner.get()).clone_chan(); }
return SyncSender::new(self.inner.clone());
#[unsafe_destructor]
#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Send> Drop for SyncSender<T> {
+impl<T: Send + 'static> Drop for SyncSender<T> {
fn drop(&mut self) {
unsafe { (*self.inner.get()).drop_chan(); }
}
// Receiver
////////////////////////////////////////////////////////////////////////////////
-impl<T: Send> Receiver<T> {
+impl<T: Send + 'static> Receiver<T> {
fn new(inner: Flavor<T>) -> Receiver<T> {
Receiver { inner: UnsafeCell::new(inner) }
}
}
}
-impl<T: Send> select::Packet for Receiver<T> {
+impl<T: Send + 'static> select::Packet for Receiver<T> {
fn can_recv(&self) -> bool {
loop {
let new_port = match *unsafe { self.inner() } {
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T: Send> Iterator for Iter<'a, T> {
+impl<'a, T: Send + 'static> Iterator for Iter<'a, T> {
type Item = T;
fn next(&mut self) -> Option<T> { self.rx.recv().ok() }
#[unsafe_destructor]
#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Send> Drop for Receiver<T> {
+impl<T: Send + 'static> Drop for Receiver<T> {
fn drop(&mut self) {
match *unsafe { self.inner_mut() } {
Flavor::Oneshot(ref mut p) => unsafe { (*p.get()).drop_port(); },
use std::env;
use super::*;
- use thread::Thread;
+ use thread;
pub fn stress_factor() -> uint {
match env::var("RUST_TEST_STRESS") {
#[test]
fn smoke_threads() {
let (tx, rx) = channel::<int>();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
tx.send(1).unwrap();
});
assert_eq!(rx.recv().unwrap(), 1);
#[test]
fn port_gone_concurrent() {
let (tx, rx) = channel::<int>();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
rx.recv().unwrap();
});
while tx.send(1).is_ok() {}
fn port_gone_concurrent_shared() {
let (tx, rx) = channel::<int>();
let tx2 = tx.clone();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
rx.recv().unwrap();
});
while tx.send(1).is_ok() && tx2.send(1).is_ok() {}
#[test]
fn chan_gone_concurrent() {
let (tx, rx) = channel::<int>();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
tx.send(1).unwrap();
tx.send(1).unwrap();
});
#[test]
fn stress() {
let (tx, rx) = channel::<int>();
- let t = Thread::scoped(move|| {
+ let t = thread::spawn(move|| {
for _ in 0u..10000 { tx.send(1).unwrap(); }
});
for _ in 0u..10000 {
static NTHREADS: uint = 8;
let (tx, rx) = channel::<int>();
- let t = Thread::scoped(move|| {
+ let t = thread::spawn(move|| {
for _ in 0..AMT * NTHREADS {
assert_eq!(rx.recv().unwrap(), 1);
}
for _ in 0..NTHREADS {
let tx = tx.clone();
- Thread::spawn(move|| {
+ thread::spawn(move|| {
for _ in 0..AMT { tx.send(1).unwrap(); }
});
}
fn send_from_outside_runtime() {
let (tx1, rx1) = channel::<()>();
let (tx2, rx2) = channel::<int>();
- let t1 = Thread::scoped(move|| {
+ let t1 = thread::spawn(move|| {
tx1.send(()).unwrap();
for _ in 0..40 {
assert_eq!(rx2.recv().unwrap(), 1);
}
});
rx1.recv().unwrap();
- let t2 = Thread::scoped(move|| {
+ let t2 = thread::spawn(move|| {
for _ in 0..40 {
tx2.send(1).unwrap();
}
#[test]
fn recv_from_outside_runtime() {
let (tx, rx) = channel::<int>();
- let t = Thread::scoped(move|| {
+ let t = thread::spawn(move|| {
for _ in 0..40 {
assert_eq!(rx.recv().unwrap(), 1);
}
fn no_runtime() {
let (tx1, rx1) = channel::<int>();
let (tx2, rx2) = channel::<int>();
- let t1 = Thread::scoped(move|| {
+ let t1 = thread::spawn(move|| {
assert_eq!(rx1.recv().unwrap(), 1);
tx2.send(2).unwrap();
});
- let t2 = Thread::scoped(move|| {
+ let t2 = thread::spawn(move|| {
tx1.send(1).unwrap();
assert_eq!(rx2.recv().unwrap(), 2);
});
#[test]
fn oneshot_single_thread_recv_chan_close() {
// Receiving on a closed chan will panic
- let res = Thread::scoped(move|| {
+ let res = thread::spawn(move|| {
let (tx, rx) = channel::<int>();
drop(tx);
rx.recv().unwrap();
#[test]
fn oneshot_multi_task_recv_then_send() {
let (tx, rx) = channel::<Box<int>>();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
assert!(rx.recv().unwrap() == box 10);
});
#[test]
fn oneshot_multi_task_recv_then_close() {
let (tx, rx) = channel::<Box<int>>();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
drop(tx);
});
- let res = Thread::scoped(move|| {
+ let res = thread::spawn(move|| {
assert!(rx.recv().unwrap() == box 10);
}).join();
assert!(res.is_err());
fn oneshot_multi_thread_close_stress() {
for _ in 0..stress_factor() {
let (tx, rx) = channel::<int>();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
drop(rx);
});
drop(tx);
fn oneshot_multi_thread_send_close_stress() {
for _ in 0..stress_factor() {
let (tx, rx) = channel::<int>();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
drop(rx);
});
- let _ = Thread::scoped(move|| {
+ let _ = thread::spawn(move|| {
tx.send(1).unwrap();
}).join();
}
fn oneshot_multi_thread_recv_close_stress() {
for _ in 0..stress_factor() {
let (tx, rx) = channel::<int>();
- Thread::spawn(move|| {
- let res = Thread::scoped(move|| {
+ thread::spawn(move|| {
+ let res = thread::spawn(move|| {
rx.recv().unwrap();
}).join();
assert!(res.is_err());
});
- let _t = Thread::spawn(move|| {
- Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
+ thread::spawn(move|| {
drop(tx);
});
});
fn oneshot_multi_thread_send_recv_stress() {
for _ in 0..stress_factor() {
let (tx, rx) = channel();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
tx.send(box 10).unwrap();
});
assert!(rx.recv().unwrap() == box 10);
fn send(tx: Sender<Box<int>>, i: int) {
if i == 10 { return }
- Thread::spawn(move|| {
+ thread::spawn(move|| {
tx.send(box i).unwrap();
send(tx, i + 1);
});
fn recv(rx: Receiver<Box<int>>, i: int) {
if i == 10 { return }
- Thread::spawn(move|| {
+ thread::spawn(move|| {
assert!(rx.recv().unwrap() == box i);
recv(rx, i + 1);
});
let total = stress_factor() + 100;
for _ in 0..total {
let tx = tx.clone();
- Thread::spawn(move|| {
+ thread::spawn(move|| {
tx.send(()).unwrap();
});
}
let (tx, rx) = channel::<int>();
let (total_tx, total_rx) = channel::<int>();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let mut acc = 0;
for x in rx.iter() {
acc += x;
let (tx, rx) = channel::<int>();
let (count_tx, count_rx) = channel();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let mut count = 0;
for x in rx.iter() {
if count >= 3 {
let (tx1, rx1) = channel::<int>();
let (tx2, rx2) = channel::<()>();
let (tx3, rx3) = channel::<()>();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
rx2.recv().unwrap();
tx1.send(1).unwrap();
tx3.send(()).unwrap();
fn destroy_upgraded_shared_port_when_sender_still_active() {
let (tx, rx) = channel();
let (tx2, rx2) = channel();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
rx.recv().unwrap(); // wait on a oneshot
drop(rx); // destroy a shared
tx2.send(()).unwrap();
});
// make sure the other task has gone to sleep
- for _ in 0u..5000 { Thread::yield_now(); }
+ for _ in 0u..5000 { thread::yield_now(); }
// upgrade to a shared chan and send a message
let t = tx.clone();
use prelude::v1::*;
use std::env;
- use thread::Thread;
+ use thread;
use super::*;
pub fn stress_factor() -> uint {
#[test]
fn smoke_threads() {
let (tx, rx) = sync_channel::<int>(0);
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
tx.send(1).unwrap();
});
assert_eq!(rx.recv().unwrap(), 1);
#[test]
fn port_gone_concurrent() {
let (tx, rx) = sync_channel::<int>(0);
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
rx.recv().unwrap();
});
while tx.send(1).is_ok() {}
fn port_gone_concurrent_shared() {
let (tx, rx) = sync_channel::<int>(0);
let tx2 = tx.clone();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
rx.recv().unwrap();
});
while tx.send(1).is_ok() && tx2.send(1).is_ok() {}
#[test]
fn chan_gone_concurrent() {
let (tx, rx) = sync_channel::<int>(0);
- Thread::spawn(move|| {
+ thread::spawn(move|| {
tx.send(1).unwrap();
tx.send(1).unwrap();
});
#[test]
fn stress() {
let (tx, rx) = sync_channel::<int>(0);
- Thread::spawn(move|| {
+ thread::spawn(move|| {
for _ in 0u..10000 { tx.send(1).unwrap(); }
});
for _ in 0u..10000 {
let (tx, rx) = sync_channel::<int>(0);
let (dtx, drx) = sync_channel::<()>(0);
- Thread::spawn(move|| {
+ thread::spawn(move|| {
for _ in 0..AMT * NTHREADS {
assert_eq!(rx.recv().unwrap(), 1);
}
for _ in 0..NTHREADS {
let tx = tx.clone();
- Thread::spawn(move|| {
+ thread::spawn(move|| {
for _ in 0..AMT { tx.send(1).unwrap(); }
});
}
#[test]
fn oneshot_single_thread_recv_chan_close() {
// Receiving on a closed chan will panic
- let res = Thread::scoped(move|| {
+ let res = thread::spawn(move|| {
let (tx, rx) = sync_channel::<int>(0);
drop(tx);
rx.recv().unwrap();
#[test]
fn oneshot_multi_task_recv_then_send() {
let (tx, rx) = sync_channel::<Box<int>>(0);
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
assert!(rx.recv().unwrap() == box 10);
});
#[test]
fn oneshot_multi_task_recv_then_close() {
let (tx, rx) = sync_channel::<Box<int>>(0);
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
drop(tx);
});
- let res = Thread::scoped(move|| {
+ let res = thread::spawn(move|| {
assert!(rx.recv().unwrap() == box 10);
}).join();
assert!(res.is_err());
fn oneshot_multi_thread_close_stress() {
for _ in 0..stress_factor() {
let (tx, rx) = sync_channel::<int>(0);
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
drop(rx);
});
drop(tx);
fn oneshot_multi_thread_send_close_stress() {
for _ in 0..stress_factor() {
let (tx, rx) = sync_channel::<int>(0);
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
drop(rx);
});
- let _ = Thread::scoped(move || {
+ let _ = thread::spawn(move || {
tx.send(1).unwrap();
}).join();
}
fn oneshot_multi_thread_recv_close_stress() {
for _ in 0..stress_factor() {
let (tx, rx) = sync_channel::<int>(0);
- let _t = Thread::spawn(move|| {
- let res = Thread::scoped(move|| {
+ let _t = thread::spawn(move|| {
+ let res = thread::spawn(move|| {
rx.recv().unwrap();
}).join();
assert!(res.is_err());
});
- let _t = Thread::spawn(move|| {
- Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
+ thread::spawn(move|| {
drop(tx);
});
});
fn oneshot_multi_thread_send_recv_stress() {
for _ in 0..stress_factor() {
let (tx, rx) = sync_channel::<Box<int>>(0);
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
tx.send(box 10).unwrap();
});
assert!(rx.recv().unwrap() == box 10);
fn send(tx: SyncSender<Box<int>>, i: int) {
if i == 10 { return }
- Thread::spawn(move|| {
+ thread::spawn(move|| {
tx.send(box i).unwrap();
send(tx, i + 1);
});
fn recv(rx: Receiver<Box<int>>, i: int) {
if i == 10 { return }
- Thread::spawn(move|| {
+ thread::spawn(move|| {
assert!(rx.recv().unwrap() == box i);
recv(rx, i + 1);
});
let total = stress_factor() + 100;
for _ in 0..total {
let tx = tx.clone();
- Thread::spawn(move|| {
+ thread::spawn(move|| {
tx.send(()).unwrap();
});
}
let (tx, rx) = sync_channel::<int>(0);
let (total_tx, total_rx) = sync_channel::<int>(0);
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let mut acc = 0;
for x in rx.iter() {
acc += x;
let (tx, rx) = sync_channel::<int>(0);
let (count_tx, count_rx) = sync_channel(0);
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let mut count = 0;
for x in rx.iter() {
if count >= 3 {
let (tx1, rx1) = sync_channel::<int>(1);
let (tx2, rx2) = sync_channel::<()>(1);
let (tx3, rx3) = sync_channel::<()>(1);
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
rx2.recv().unwrap();
tx1.send(1).unwrap();
tx3.send(()).unwrap();
fn destroy_upgraded_shared_port_when_sender_still_active() {
let (tx, rx) = sync_channel::<()>(0);
let (tx2, rx2) = sync_channel::<()>(0);
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
rx.recv().unwrap(); // wait on a oneshot
drop(rx); // destroy a shared
tx2.send(()).unwrap();
});
// make sure the other task has gone to sleep
- for _ in 0u..5000 { Thread::yield_now(); }
+ for _ in 0u..5000 { thread::yield_now(); }
// upgrade to a shared chan and send a message
let t = tx.clone();
#[test]
fn send1() {
let (tx, rx) = sync_channel::<int>(0);
- let _t = Thread::spawn(move|| { rx.recv().unwrap(); });
+ let _t = thread::spawn(move|| { rx.recv().unwrap(); });
assert_eq!(tx.send(1), Ok(()));
}
#[test]
fn send2() {
let (tx, rx) = sync_channel::<int>(0);
- let _t = Thread::spawn(move|| { drop(rx); });
+ let _t = thread::spawn(move|| { drop(rx); });
assert!(tx.send(1).is_err());
}
fn send3() {
let (tx, rx) = sync_channel::<int>(1);
assert_eq!(tx.send(1), Ok(()));
- let _t =Thread::spawn(move|| { drop(rx); });
+ let _t =thread::spawn(move|| { drop(rx); });
assert!(tx.send(1).is_err());
}
let tx2 = tx.clone();
let (done, donerx) = channel();
let done2 = done.clone();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
assert!(tx.send(1).is_err());
done.send(()).unwrap();
});
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
assert!(tx2.send(2).is_err());
done2.send(()).unwrap();
});
let (tx1, rx1) = sync_channel::<()>(3);
let (tx2, rx2) = sync_channel::<()>(3);
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
rx1.recv().unwrap();
tx2.try_send(()).unwrap();
});
}
unsafe impl<T:Send> Send for Queue<T> { }
-unsafe impl<T:Send> Sync for Queue<T> { }
+unsafe impl<T: Send + 'static> Sync for Queue<T> { }
impl<T> Node<T> {
unsafe fn new(v: Option<T>) -> *mut Node<T> {
}
}
-impl<T: Send> Queue<T> {
+impl<T: Send + 'static> Queue<T> {
/// Creates a new queue that is safe to share among multiple producers and
/// one consumer.
pub fn new() -> Queue<T> {
#[unsafe_destructor]
#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Send> Drop for Queue<T> {
+impl<T: Send + 'static> Drop for Queue<T> {
fn drop(&mut self) {
unsafe {
let mut cur = *self.tail.get();
use sync::mpsc::channel;
use super::{Queue, Data, Empty, Inconsistent};
use sync::Arc;
- use thread::Thread;
+ use thread;
#[test]
fn test_full() {
for _ in 0..nthreads {
let tx = tx.clone();
let q = q.clone();
- Thread::spawn(move|| {
+ thread::spawn(move|| {
for i in 0..nmsgs {
q.push(i);
}
GoUp(Receiver<T>),
}
-impl<T: Send> Packet<T> {
+impl<T: Send + 'static> Packet<T> {
pub fn new() -> Packet<T> {
Packet {
data: None,
}
#[unsafe_destructor]
-impl<T: Send> Drop for Packet<T> {
+impl<T: Send + 'static> Drop for Packet<T> {
fn drop(&mut self) {
assert_eq!(self.state.load(Ordering::SeqCst), DISCONNECTED);
}
/// Creates a new handle into this receiver set for a new receiver. Note
/// that this does *not* add the receiver to the receiver set, for that you
/// must call the `add` method on the handle itself.
- pub fn handle<'a, T: Send>(&'a self, rx: &'a Receiver<T>) -> Handle<'a, T> {
+ pub fn handle<'a, T: Send + 'static>(&'a self, rx: &'a Receiver<T>) -> Handle<'a, T> {
let id = self.next_id.get();
self.next_id.set(id + 1);
Handle {
fn iter(&self) -> Packets { Packets { cur: self.head } }
}
-impl<'rx, T: Send> Handle<'rx, T> {
+impl<'rx, T: Send + 'static> Handle<'rx, T> {
/// Retrieve the id of this handle.
#[inline]
pub fn id(&self) -> uint { self.id }
}
#[unsafe_destructor]
-impl<'rx, T: Send> Drop for Handle<'rx, T> {
+impl<'rx, T: Send + 'static> Drop for Handle<'rx, T> {
fn drop(&mut self) {
unsafe { self.remove() }
}
mod test {
use prelude::v1::*;
- use thread::Thread;
+ use thread;
use sync::mpsc::*;
// Don't use the libstd version so we can pull in the right Select structure
let (_tx2, rx2) = channel::<int>();
let (tx3, rx3) = channel::<int>();
- let _t = Thread::spawn(move|| {
- for _ in 0u..20 { Thread::yield_now(); }
+ let _t = thread::spawn(move|| {
+ for _ in 0u..20 { thread::yield_now(); }
tx1.send(1).unwrap();
rx3.recv().unwrap();
- for _ in 0u..20 { Thread::yield_now(); }
+ for _ in 0u..20 { thread::yield_now(); }
});
select! {
let (tx2, rx2) = channel::<int>();
let (tx3, rx3) = channel::<()>();
- let _t = Thread::spawn(move|| {
- for _ in 0u..20 { Thread::yield_now(); }
+ let _t = thread::spawn(move|| {
+ for _ in 0u..20 { thread::yield_now(); }
tx1.send(1).unwrap();
tx2.send(2).unwrap();
rx3.recv().unwrap();
let (tx2, rx2) = channel::<int>();
let (tx3, rx3) = channel::<()>();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
for i in 0..AMT {
if i % 2 == 0 {
tx1.send(i).unwrap();
let (_tx2, rx2) = channel::<int>();
let (tx3, rx3) = channel::<()>();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
rx3.recv().unwrap();
tx1.clone();
assert_eq!(rx3.try_recv(), Err(TryRecvError::Empty));
let (_tx2, rx2) = channel::<int>();
let (tx3, rx3) = channel::<()>();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
rx3.recv().unwrap();
tx1.clone();
assert_eq!(rx3.try_recv(), Err(TryRecvError::Empty));
let (tx1, rx1) = channel::<()>();
let (tx2, rx2) = channel::<()>();
let (tx3, rx3) = channel::<()>();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let s = Select::new();
let mut h1 = s.handle(&rx1);
let mut h2 = s.handle(&rx2);
tx3.send(()).unwrap();
});
- for _ in 0u..1000 { Thread::yield_now(); }
+ for _ in 0u..1000 { thread::yield_now(); }
drop(tx1.clone());
tx2.send(()).unwrap();
rx3.recv().unwrap();
fn oneshot_data_waiting() {
let (tx1, rx1) = channel();
let (tx2, rx2) = channel();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
select! {
_n = rx1.recv() => {}
}
tx2.send(()).unwrap();
});
- for _ in 0u..100 { Thread::yield_now() }
+ for _ in 0u..100 { thread::yield_now() }
tx1.send(()).unwrap();
rx2.recv().unwrap();
}
tx1.send(()).unwrap();
rx1.recv().unwrap();
rx1.recv().unwrap();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
select! {
_n = rx1.recv() => {}
}
tx2.send(()).unwrap();
});
- for _ in 0u..100 { Thread::yield_now() }
+ for _ in 0u..100 { thread::yield_now() }
tx1.send(()).unwrap();
rx2.recv().unwrap();
}
drop(tx1.clone());
tx1.send(()).unwrap();
rx1.recv().unwrap();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
select! {
_n = rx1.recv() => {}
}
tx2.send(()).unwrap();
});
- for _ in 0u..100 { Thread::yield_now() }
+ for _ in 0u..100 { thread::yield_now() }
tx1.send(()).unwrap();
rx2.recv().unwrap();
}
#[test]
fn sync2() {
let (tx, rx) = sync_channel::<int>(0);
- let _t = Thread::spawn(move|| {
- for _ in 0u..100 { Thread::yield_now() }
+ let _t = thread::spawn(move|| {
+ for _ in 0u..100 { thread::yield_now() }
tx.send(1).unwrap();
});
select! {
fn sync3() {
let (tx1, rx1) = sync_channel::<int>(0);
let (tx2, rx2): (Sender<int>, Receiver<int>) = channel();
- let _t = Thread::spawn(move|| { tx1.send(1).unwrap(); });
- let _t = Thread::spawn(move|| { tx2.send(2).unwrap(); });
+ let _t = thread::spawn(move|| { tx1.send(1).unwrap(); });
+ let _t = thread::spawn(move|| { tx2.send(2).unwrap(); });
select! {
n = rx1.recv() => {
let n = n.unwrap();
use sync::mpsc::select::StartResult::*;
use sync::mpsc::select::StartResult;
use sync::{Mutex, MutexGuard};
-use thread::Thread;
+use thread;
const DISCONNECTED: isize = isize::MIN;
const FUDGE: isize = 1024;
Disconnected,
}
-impl<T: Send> Packet<T> {
+impl<T: Send + 'static> Packet<T> {
// Creation of a packet *must* be followed by a call to postinit_lock
// and later by inherit_blocker
pub fn new() -> Packet<T> {
match self.queue.pop() {
mpsc::Data(..) => {}
mpsc::Empty => break,
- mpsc::Inconsistent => Thread::yield_now(),
+ mpsc::Inconsistent => thread::yield_now(),
}
}
// maybe we're done, if we're not the last ones
mpsc::Inconsistent => {
let data;
loop {
- Thread::yield_now();
+ thread::yield_now();
match self.queue.pop() {
mpsc::Data(t) => { data = t; break }
mpsc::Empty => panic!("inconsistent => empty"),
drop(self.take_to_wake());
} else {
while self.to_wake.load(Ordering::SeqCst) != 0 {
- Thread::yield_now();
+ thread::yield_now();
}
}
// if the number of steals is -1, it was the pre-emptive -1 steal
}
#[unsafe_destructor]
-impl<T: Send> Drop for Packet<T> {
+impl<T: Send + 'static> Drop for Packet<T> {
fn drop(&mut self) {
// Note that this load is not only an assert for correctness about
// disconnection, but also a proper fence before the read of
cache_subtractions: AtomicUsize,
}
-unsafe impl<T: Send> Send for Queue<T> { }
+unsafe impl<T: Send + 'static> Send for Queue<T> { }
-unsafe impl<T: Send> Sync for Queue<T> { }
+unsafe impl<T: Send + 'static> Sync for Queue<T> { }
-impl<T: Send> Node<T> {
+impl<T: Send + 'static> Node<T> {
fn new() -> *mut Node<T> {
unsafe {
mem::transmute(box Node {
}
}
-impl<T: Send> Queue<T> {
+impl<T: Send + 'static> Queue<T> {
/// Creates a new queue.
///
/// This is unsafe as the type system doesn't enforce a single
}
#[unsafe_destructor]
-impl<T: Send> Drop for Queue<T> {
+impl<T: Send + 'static> Drop for Queue<T> {
fn drop(&mut self) {
unsafe {
let mut cur = *self.first.get();
use sync::Arc;
use super::Queue;
- use thread::Thread;
+ use thread;
use sync::mpsc::channel;
#[test]
let (tx, rx) = channel();
let q2 = q.clone();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
for _ in 0u..100000 {
loop {
match q2.pop() {
use core::cmp;
use core::isize;
-use thread::Thread;
+use thread;
use sync::atomic::{AtomicIsize, AtomicUsize, Ordering, AtomicBool};
use sync::mpsc::Receiver;
GoUp(Receiver<T>),
}
-impl<T: Send> Packet<T> {
+impl<T: Send + 'static> Packet<T> {
pub fn new() -> Packet<T> {
Packet {
queue: unsafe { spsc::Queue::new(128) },
drop(self.take_to_wake());
} else {
while self.to_wake.load(Ordering::SeqCst) != 0 {
- Thread::yield_now();
+ thread::yield_now();
}
}
assert_eq!(self.steals, 0);
}
#[unsafe_destructor]
-impl<T: Send> Drop for Packet<T> {
+impl<T: Send + 'static> Drop for Packet<T> {
fn drop(&mut self) {
// Note that this load is not only an assert for correctness about
// disconnection, but also a proper fence before the read of
lock: Mutex<State<T>>,
}
-unsafe impl<T:Send> Send for Packet<T> { }
+unsafe impl<T: Send + 'static> Send for Packet<T> { }
-unsafe impl<T:Send> Sync for Packet<T> { }
+unsafe impl<T: Send + 'static> Sync for Packet<T> { }
struct State<T> {
disconnected: bool, // Is the channel disconnected yet?
canceled: Option<&'static mut bool>,
}
-unsafe impl<T: Send> Send for State<T> {}
+unsafe impl<T: Send + 'static> Send for State<T> {}
/// Possible flavors of threads who can be blocked on this channel.
enum Blocker {
/// Atomically blocks the current thread, placing it into `slot`, unlocking `lock`
/// in the meantime. This re-locks the mutex upon returning.
-fn wait<'a, 'b, T: Send>(lock: &'a Mutex<State<T>>,
+fn wait<'a, 'b, T: Send + 'static>(lock: &'a Mutex<State<T>>,
mut guard: MutexGuard<'b, State<T>>,
f: fn(SignalToken) -> Blocker)
-> MutexGuard<'a, State<T>>
token.signal();
}
-impl<T: Send> Packet<T> {
+impl<T: Send + 'static> Packet<T> {
pub fn new(cap: uint) -> Packet<T> {
Packet {
channels: AtomicUsize::new(1),
}
#[unsafe_destructor]
-impl<T: Send> Drop for Packet<T> {
+impl<T: Send + 'static> Drop for Packet<T> {
fn drop(&mut self) {
assert_eq!(self.channels.load(Ordering::SeqCst), 0);
let mut guard = self.lock.lock().unwrap();
///
/// ```rust
/// use std::sync::{Arc, Mutex};
-/// use std::thread::Thread;
+/// use std::thread;
/// use std::sync::mpsc::channel;
///
/// const N: uint = 10;
/// let (tx, rx) = channel();
/// for _ in 0u..10 {
/// let (data, tx) = (data.clone(), tx.clone());
-/// Thread::spawn(move || {
+/// thread::spawn(move || {
/// // The shared static can only be accessed once the lock is held.
/// // Our non-atomic increment is safe because we're the only thread
/// // which can access the shared state when the lock is held.
///
/// ```rust
/// use std::sync::{Arc, Mutex};
-/// use std::thread::Thread;
+/// use std::thread;
///
/// let lock = Arc::new(Mutex::new(0u));
/// let lock2 = lock.clone();
///
-/// let _ = Thread::scoped(move || -> () {
+/// let _ = thread::spawn(move || -> () {
/// // This thread will acquire the mutex first, unwrapping the result of
/// // `lock` because the lock has not been poisoned.
/// let _lock = lock2.lock().unwrap();
data: UnsafeCell<T>,
}
-unsafe impl<T:Send> Send for Mutex<T> { }
+unsafe impl<T: Send + 'static> Send for Mutex<T> { }
-unsafe impl<T:Send> Sync for Mutex<T> { }
+unsafe impl<T: Send + 'static> Sync for Mutex<T> { }
/// The static mutex type is provided to allow for static allocation of mutexes.
///
poison: poison::FLAG_INIT,
};
-impl<T: Send> Mutex<T> {
+impl<T: Send + 'static> Mutex<T> {
/// Creates a new mutex in an unlocked state ready for use.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn new(t: T) -> Mutex<T> {
#[unsafe_destructor]
#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Send> Drop for Mutex<T> {
+impl<T: Send + 'static> Drop for Mutex<T> {
fn drop(&mut self) {
// This is actually safe b/c we know that there is no further usage of
// this mutex (it's up to the user to arrange for a mutex to get
use sync::mpsc::channel;
use sync::{Arc, Mutex, StaticMutex, MUTEX_INIT, Condvar};
- use thread::Thread;
+ use thread;
struct Packet<T>(Arc<(Mutex<T>, Condvar)>);
let (tx, rx) = channel();
for _ in 0..K {
let tx2 = tx.clone();
- Thread::spawn(move|| { inc(); tx2.send(()).unwrap(); });
+ thread::spawn(move|| { inc(); tx2.send(()).unwrap(); });
let tx2 = tx.clone();
- Thread::spawn(move|| { inc(); tx2.send(()).unwrap(); });
+ thread::spawn(move|| { inc(); tx2.send(()).unwrap(); });
}
drop(tx);
let packet = Packet(Arc::new((Mutex::new(false), Condvar::new())));
let packet2 = Packet(packet.0.clone());
let (tx, rx) = channel();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
// wait until parent gets in
rx.recv().unwrap();
let &(ref lock, ref cvar) = &*packet2.0;
let packet2 = Packet(packet.0.clone());
let (tx, rx) = channel();
- let _t = Thread::spawn(move || -> () {
+ let _t = thread::spawn(move || -> () {
rx.recv().unwrap();
let &(ref lock, ref cvar) = &*packet2.0;
let _g = lock.lock().unwrap();
let arc = Arc::new(Mutex::new(1));
assert!(!arc.is_poisoned());
let arc2 = arc.clone();
- let _ = Thread::scoped(move|| {
+ let _ = thread::spawn(move|| {
let lock = arc2.lock().unwrap();
assert_eq!(*lock, 2);
}).join();
let arc = Arc::new(Mutex::new(1));
let arc2 = Arc::new(Mutex::new(arc));
let (tx, rx) = channel();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let lock = arc2.lock().unwrap();
let lock2 = lock.lock().unwrap();
assert_eq!(*lock2, 1);
fn test_mutex_arc_access_in_unwind() {
let arc = Arc::new(Mutex::new(1));
let arc2 = arc.clone();
- let _ = Thread::scoped(move|| -> () {
+ let _ = thread::spawn(move|| -> () {
struct Unwinder {
i: Arc<Mutex<int>>,
}
mod test {
use prelude::v1::*;
- use thread::Thread;
+ use thread;
use super::{ONCE_INIT, Once};
use sync::mpsc::channel;
let (tx, rx) = channel();
for _ in 0u..10 {
let tx = tx.clone();
- Thread::spawn(move|| {
- for _ in 0u..4 { Thread::yield_now() }
+ thread::spawn(move|| {
+ for _ in 0u..4 { thread::yield_now() }
unsafe {
O.call_once(|| {
assert!(!run);
use cell::UnsafeCell;
use error::{Error, FromError};
use fmt;
-use thread::Thread;
+use thread;
pub struct Flag { failed: UnsafeCell<bool> }
pub const FLAG_INIT: Flag = Flag { failed: UnsafeCell { value: false } };
impl Flag {
#[inline]
pub fn borrow(&self) -> LockResult<Guard> {
- let ret = Guard { panicking: Thread::panicking() };
+ let ret = Guard { panicking: thread::panicking() };
if unsafe { *self.failed.get() } {
Err(PoisonError::new(ret))
} else {
#[inline]
pub fn done(&self, guard: &Guard) {
- if !guard.panicking && Thread::panicking() {
+ if !guard.panicking && thread::panicking() {
unsafe { *self.failed.get() = true; }
}
}
use rand::{self, Rng};
use sync::mpsc::channel;
- use thread::Thread;
+ use thread;
use sync::{Arc, RwLock, StaticRwLock, RW_LOCK_INIT};
#[test]
#[test]
fn frob() {
static R: StaticRwLock = RW_LOCK_INIT;
- static N: uint = 10;
- static M: uint = 1000;
+ static N: usize = 10;
+ static M: usize = 1000;
let (tx, rx) = channel::<()>();
for _ in 0..N {
let tx = tx.clone();
- Thread::spawn(move|| {
+ thread::spawn(move|| {
let mut rng = rand::thread_rng();
for _ in 0..M {
if rng.gen_weighted_bool(N) {
fn test_rw_arc_poison_wr() {
let arc = Arc::new(RwLock::new(1));
let arc2 = arc.clone();
- let _: Result<uint, _> = Thread::scoped(move|| {
+ let _: Result<(), _> = thread::spawn(move|| {
let _lock = arc2.write().unwrap();
panic!();
}).join();
let arc = Arc::new(RwLock::new(1));
assert!(!arc.is_poisoned());
let arc2 = arc.clone();
- let _: Result<uint, _> = Thread::scoped(move|| {
+ let _: Result<(), _> = thread::spawn(move|| {
let _lock = arc2.write().unwrap();
panic!();
}).join();
fn test_rw_arc_no_poison_rr() {
let arc = Arc::new(RwLock::new(1));
let arc2 = arc.clone();
- let _: Result<uint, _> = Thread::scoped(move|| {
+ let _: Result<(), _> = thread::spawn(move|| {
let _lock = arc2.read().unwrap();
panic!();
}).join();
fn test_rw_arc_no_poison_rw() {
let arc = Arc::new(RwLock::new(1));
let arc2 = arc.clone();
- let _: Result<uint, _> = Thread::scoped(move|| {
+ let _: Result<(), _> = thread::spawn(move|| {
let _lock = arc2.read().unwrap();
panic!()
}).join();
let arc2 = arc.clone();
let (tx, rx) = channel();
- Thread::spawn(move|| {
+ thread::spawn(move|| {
let mut lock = arc2.write().unwrap();
for _ in 0u..10 {
let tmp = *lock;
*lock = -1;
- Thread::yield_now();
+ thread::yield_now();
*lock = tmp + 1;
}
tx.send(()).unwrap();
let mut children = Vec::new();
for _ in 0u..5 {
let arc3 = arc.clone();
- children.push(Thread::scoped(move|| {
+ children.push(thread::spawn(move|| {
let lock = arc3.read().unwrap();
assert!(*lock >= 0);
}));
fn test_rw_arc_access_in_unwind() {
let arc = Arc::new(RwLock::new(1));
let arc2 = arc.clone();
- let _ = Thread::scoped(move|| -> () {
+ let _ = thread::spawn(move|| -> () {
struct Unwinder {
i: Arc<RwLock<int>>,
}
use sync::Arc;
use super::Semaphore;
use sync::mpsc::channel;
- use thread::Thread;
+ use thread;
#[test]
fn test_sem_acquire_release() {
fn test_sem_as_mutex() {
let s = Arc::new(Semaphore::new(1));
let s2 = s.clone();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let _g = s2.access();
});
let _g = s.access();
let (tx, rx) = channel();
let s = Arc::new(Semaphore::new(0));
let s2 = s.clone();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
s2.acquire();
tx.send(()).unwrap();
});
let (tx, rx) = channel();
let s = Arc::new(Semaphore::new(0));
let s2 = s.clone();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
s2.release();
let _ = rx.recv();
});
let s2 = s.clone();
let (tx1, rx1) = channel();
let (tx2, rx2) = channel();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let _g = s2.access();
let _ = rx2.recv();
tx1.send(()).unwrap();
let (tx, rx) = channel();
{
let _g = s.access();
- Thread::spawn(move|| {
+ thread::spawn(move|| {
tx.send(()).unwrap();
drop(s2.access());
tx.send(()).unwrap();
use sync::{Arc, Mutex};
use sync::mpsc::{channel, Sender, Receiver};
-use thread::Thread;
+use thread;
use thunk::Thunk;
struct Sentinel<'a> {
- jobs: &'a Arc<Mutex<Receiver<Thunk>>>,
+ jobs: &'a Arc<Mutex<Receiver<Thunk<'static>>>>,
active: bool
}
impl<'a> Sentinel<'a> {
- fn new(jobs: &Arc<Mutex<Receiver<Thunk>>>) -> Sentinel {
+ fn new(jobs: &'a Arc<Mutex<Receiver<Thunk<'static>>>>) -> Sentinel<'a> {
Sentinel {
jobs: jobs,
active: true
//
// This is the only such Sender, so when it is dropped all subthreads will
// quit.
- jobs: Sender<Thunk>
+ jobs: Sender<Thunk<'static>>
}
impl TaskPool {
/// Executes the function `job` on a thread in the pool.
pub fn execute<F>(&self, job: F)
- where F : FnOnce(), F : Send
+ where F : FnOnce(), F : Send + 'static
{
self.jobs.send(Thunk::new(job)).unwrap();
}
}
-fn spawn_in_pool(jobs: Arc<Mutex<Receiver<Thunk>>>) {
- Thread::spawn(move || {
+fn spawn_in_pool(jobs: Arc<Mutex<Receiver<Thunk<'static>>>>) {
+ thread::spawn(move || {
// Will spawn a new thread on panic unless it is cancelled.
let sentinel = Sentinel::new(&jobs);
use sync::mpsc::{channel, Sender, Receiver};
use sys::helper_signal;
-use thread::Thread;
+use thread;
/// A structure for management of a helper thread.
///
///
/// This function is safe to be called many times.
pub fn boot<T, F>(&'static self, f: F, helper: fn(helper_signal::signal, Receiver<M>, T)) where
- T: Send,
+ T: Send + 'static,
F: FnOnce() -> T,
{
unsafe {
let receive = RaceBox(receive);
let t = f();
- Thread::spawn(move || {
+ thread::spawn(move || {
helper(receive.0, rx, t);
let _g = self.lock.lock().unwrap();
*self.shutdown.get() = true;
impl ThreadInfo {
fn with<R, F>(f: F) -> R where F: FnOnce(&mut ThreadInfo) -> R {
if THREAD_INFO.state() == State::Destroyed {
- panic!("Use of std::thread::Thread::current() is not possible after \
+ panic!("Use of std::thread::current() is not possible after \
the thread's local data has been destroyed");
}
}));
}
-// a hack to get around privacy restrictions; implemented by `std::thread::Thread`
+// a hack to get around privacy restrictions; implemented by `std::thread`
pub trait NewThread {
fn new(name: Option<String>) -> Self;
}
//! # Usage
//!
//! This module should likely not be used directly unless other primitives are
-//! being built on. types such as `thread_local::scoped::Key` are likely much
+//! being built on. types such as `thread_local::spawn::Key` are likely much
//! more useful in practice than this OS-based version which likely requires
//! unsafe code to interoperate with.
//!
}
}
-impl AsciiExt<Wtf8Buf> for Wtf8 {
+impl AsciiExt for Wtf8 {
+ type Owned = Wtf8Buf;
+
fn is_ascii(&self) -> bool {
self.bytes.is_ascii()
}
fn eq_ignore_ascii_case(&self, other: &Wtf8) -> bool {
self.bytes.eq_ignore_ascii_case(&other.bytes)
}
+
+ fn make_ascii_uppercase(&mut self) { self.bytes.make_ascii_uppercase() }
+ fn make_ascii_lowercase(&mut self) { self.bytes.make_ascii_lowercase() }
}
#[cfg(test)]
fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
}
+impl ExactSizeIterator for Args {
+ fn len(&self) -> usize { self.iter.len() }
+}
+
/// Returns the command line arguments
///
/// Returns a list of the command line arguments.
K: BytesContainer + Eq + Hash<Hasher>, V: BytesContainer
{
use libc::funcs::posix88::unistd::{fork, dup2, close, chdir, execvp};
- use libc::funcs::bsd44::getdtablesize;
mod rustrt {
extern {
}
}
+ #[cfg(all(target_os = "android", target_arch = "aarch64"))]
+ unsafe fn getdtablesize() -> c_int {
+ libc::sysconf(libc::consts::os::sysconf::_SC_OPEN_MAX) as c_int
+ }
+ #[cfg(not(all(target_os = "android", target_arch = "aarch64")))]
+ unsafe fn getdtablesize() -> c_int {
+ libc::funcs::bsd44::getdtablesize()
+ }
+
unsafe fn set_cloexec(fd: c_int) {
let ret = c::ioctl(fd, c::FIOCLEX);
assert_eq!(ret, 0);
use core::prelude::*;
+use io;
use boxed::Box;
use cmp;
use mem;
}
}
-pub unsafe fn create(stack: uint, p: Thunk) -> rust_thread {
+pub unsafe fn create(stack: uint, p: Thunk) -> io::Result<rust_thread> {
let mut native: libc::pthread_t = mem::zeroed();
let mut attr: libc::pthread_attr_t = mem::zeroed();
assert_eq!(pthread_attr_init(&mut attr), 0);
if ret != 0 {
// be sure to not leak the closure
let _p: Box<Box<FnOnce()+Send>> = mem::transmute(arg);
- panic!("failed to spawn native thread: {}", ret);
+ Err(io::Error::from_os_error(ret))
+ } else {
+ Ok(native)
}
- native
}
#[cfg(any(target_os = "linux", target_os = "android"))]
use error::Error as StdError;
use ffi::{OsString, OsStr, AsOsStr};
use fmt;
-use iter::Range;
+use ops::Range;
use libc::types::os::arch::extra::LPWCH;
use libc::{self, c_int, c_void};
use mem;
fn size_hint(&self) -> (usize, Option<usize>) { self.range.size_hint() }
}
+impl ExactSizeIterator for Args {
+ fn len(&self) -> usize { self.range.len() }
+}
+
impl Drop for Args {
fn drop(&mut self) {
unsafe { c::LocalFree(self.cur as *mut c_void); }
let lpCmdLine = c::GetCommandLineW();
let szArgList = c::CommandLineToArgvW(lpCmdLine, &mut nArgs);
- Args { cur: szArgList, range: range(0, nArgs as isize) }
+ Args { cur: szArgList, range: 0..(nArgs as isize) }
}
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use boxed::Box;
+use prelude::v1::*;
+
use cmp;
+use io;
use mem;
use ptr;
use libc;
}
}
-pub unsafe fn create(stack: uint, p: Thunk) -> rust_thread {
+pub unsafe fn create(stack: uint, p: Thunk) -> io::Result<rust_thread> {
let arg: *mut libc::c_void = mem::transmute(box p);
// FIXME On UNIX, we guard against stack sizes that are too small but
// that's because pthreads enforces that stacks are at least
if ret as uint == 0 {
// be sure to not leak the closure
let _p: Box<Thunk> = mem::transmute(arg);
- panic!("failed to spawn native thread: {:?}", ret);
+ Err(io::Error::last_os_error())
+ } else {
+ Ok(ret)
}
- return ret;
}
pub unsafe fn set_name(_name: &str) {
//! Already-running threads are represented via the `Thread` type, which you can
//! get in one of two ways:
//!
-//! * By spawning a new thread, e.g. using the `Thread::spawn` constructor;
-//! * By requesting the current thread, using the `Thread::current` function.
+//! * By spawning a new thread, e.g. using the `thread::spawn` constructor;
+//! * By requesting the current thread, using the `thread::current` function.
//!
//! Threads can be named, and provide some built-in support for low-level
//! synchronization described below.
//!
-//! The `Thread::current()` function is available even for threads not spawned
+//! The `thread::current()` function is available even for threads not spawned
//! by the APIs of this module.
//!
//! ## Spawning a thread
//!
-//! A new thread can be spawned using the `Thread::spawn` function:
+//! A new thread can be spawned using the `thread::spawn` function:
//!
//! ```rust
-//! use std::thread::Thread;
+//! use std::thread;
//!
-//! let thread = Thread::spawn(move || {
+//! thread::spawn(move || {
//! println!("Hello, World!");
//! // some computation here
//! });
//! ```
//!
-//! The spawned thread is "detached" from the current thread, meaning that it
-//! can outlive the thread that spawned it. (Note, however, that when the main
-//! thread terminates all detached threads are terminated as well.) The returned
-//! `Thread` handle can be used for low-level synchronization as described below.
+//! In this example, the spawned thread is "detached" from the current
+//! thread, meaning that it can outlive the thread that spawned
+//! it. (Note, however, that when the main thread terminates all
+//! detached threads are terminated as well.)
//!
//! ## Scoped threads
//!
//! For this scenario, use the `scoped` constructor:
//!
//! ```rust
-//! use std::thread::Thread;
+//! use std::thread;
//!
-//! let guard = Thread::scoped(move || {
+//! let guard = thread::scoped(move || {
//! println!("Hello, World!");
//! // some computation here
//! });
//! // do some other work in the meantime
-//! let result = guard.join();
+//! let output = guard.join();
//! ```
//!
-//! The `scoped` function doesn't return a `Thread` directly; instead, it
-//! returns a *join guard* from which a `Thread` can be extracted. The join
-//! guard is an RAII-style guard that will automatically join the child thread
-//! (block until it terminates) when it is dropped. You can join the child
-//! thread in advance by calling the `join` method on the guard, which will also
-//! return the result produced by the thread. A handle to the thread itself is
-//! available via the `thread` method on the join guard.
+//! The `scoped` function doesn't return a `Thread` directly; instead,
+//! it returns a *join guard*. The join guard is an RAII-style guard
+//! that will automatically join the child thread (block until it
+//! terminates) when it is dropped. You can join the child thread in
+//! advance by calling the `join` method on the guard, which will also
+//! return the result produced by the thread. A handle to the thread
+//! itself is available via the `thread` method on the join guard.
//!
//! (Note: eventually, the `scoped` constructor will allow the parent and child
//! threads to data that lives on the parent thread's stack, but some language
//! Conceptually, each `Thread` handle has an associated token, which is
//! initially not present:
//!
-//! * The `Thread::park()` function blocks the current thread unless or until
+//! * The `thread::park()` function blocks the current thread unless or until
//! the token is available for its thread handle, at which point It atomically
//! consumes the token. It may also return *spuriously*, without consuming the
-//! token. `Thread::park_timeout()` does the same, but allows specifying a
+//! token. `thread::park_timeout()` does the same, but allows specifying a
//! maximum time to block the thread for.
//!
//! * The `unpark()` method on a `Thread` atomically makes the token available
#![stable(feature = "rust1", since = "1.0.0")]
+use prelude::v1::*;
+
use any::Any;
-use boxed::Box;
use cell::UnsafeCell;
-use clone::Clone;
-use marker::{Send, Sync};
-use ops::{Drop, FnOnce};
-use option::Option::{self, Some, None};
-use result::Result::{Err, Ok};
-use sync::{Mutex, Condvar, Arc};
-use str::Str;
-use string::String;
+use fmt;
+use io;
+use marker;
+use old_io::stdio;
use rt::{self, unwind};
-use old_io::{Writer, stdio};
+use sync::{Mutex, Condvar, Arc};
use thunk::Thunk;
use time::Duration;
// The size of the stack for the spawned thread
stack_size: Option<uint>,
// Thread-local stdout
- stdout: Option<Box<Writer + Send>>,
+ stdout: Option<Box<Writer + Send + 'static>>,
// Thread-local stderr
- stderr: Option<Box<Writer + Send>>,
+ stderr: Option<Box<Writer + Send + 'static>>,
}
impl Builder {
/// Redirect thread-local stdout.
#[unstable(feature = "std_misc",
reason = "Will likely go away after proc removal")]
- pub fn stdout(mut self, stdout: Box<Writer + Send>) -> Builder {
+ pub fn stdout(mut self, stdout: Box<Writer + Send + 'static>) -> Builder {
self.stdout = Some(stdout);
self
}
/// Redirect thread-local stderr.
#[unstable(feature = "std_misc",
reason = "Will likely go away after proc removal")]
- pub fn stderr(mut self, stderr: Box<Writer + Send>) -> Builder {
+ pub fn stderr(mut self, stderr: Box<Writer + Send + 'static>) -> Builder {
self.stderr = Some(stderr);
self
}
- /// Spawn a new detached thread, and return a handle to it.
+ /// Spawn a new thread, and return a join handle for it.
///
- /// See `Thead::spawn` and the module doc for more details.
- #[unstable(feature = "std_misc",
- reason = "may change with specifics of new Send semantics")]
- pub fn spawn<F>(self, f: F) -> Thread where F: FnOnce(), F: Send + 'static {
- let (native, thread) = self.spawn_inner(Thunk::new(f), Thunk::with_arg(|_| {}));
- unsafe { imp::detach(native) };
- thread
+ /// The child thread may outlive the parent (unless the parent thread
+ /// is the main thread; the whole process is terminated when the main
+ /// thread finishes.) The join handle can be used to block on
+ /// termination of the child thread, including recovering its panics.
+ ///
+ /// # Errors
+ ///
+ /// Unlike the `spawn` free function, this method yields an
+ /// `io::Result` to capture any failure to create the thread at
+ /// the OS level.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn spawn<F>(self, f: F) -> io::Result<JoinHandle> where
+ F: FnOnce(), F: Send + 'static
+ {
+ self.spawn_inner(Thunk::new(f)).map(|i| JoinHandle(i))
}
/// Spawn a new child thread that must be joined within a given
/// scope, and return a `JoinGuard`.
///
- /// See `Thead::scoped` and the module doc for more details.
- #[unstable(feature = "std_misc",
- reason = "may change with specifics of new Send semantics")]
- pub fn scoped<'a, T, F>(self, f: F) -> JoinGuard<'a, T> where
+ /// The join guard can be used to explicitly join the child thread (via
+ /// `join`), returning `Result<T>`, or it will implicitly join the child
+ /// upon being dropped. Because the child thread may refer to data on the
+ /// current thread's stack (hence the "scoped" name), it cannot be detached;
+ /// it *must* be joined before the relevant stack frame is popped. See the
+ /// module documentation for additional details.
+ ///
+ /// # Errors
+ ///
+ /// Unlike the `scoped` free function, this method yields an
+ /// `io::Result` to capture any failure to create the thread at
+ /// the OS level.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn scoped<'a, T, F>(self, f: F) -> io::Result<JoinGuard<'a, T>> where
T: Send + 'a, F: FnOnce() -> T, F: Send + 'a
{
- let my_packet = Packet(Arc::new(UnsafeCell::new(None)));
- let their_packet = Packet(my_packet.0.clone());
- let (native, thread) = self.spawn_inner(Thunk::new(f), Thunk::with_arg(move |ret| unsafe {
- *their_packet.0.get() = Some(ret);
- }));
-
- JoinGuard {
- native: native,
- joined: false,
- packet: my_packet,
- thread: thread,
- }
+ self.spawn_inner(Thunk::new(f)).map(|inner| {
+ JoinGuard { inner: inner, _marker: marker::CovariantType }
+ })
}
- fn spawn_inner<T: Send>(self, f: Thunk<(), T>, finish: Thunk<Result<T>, ()>)
- -> (imp::rust_thread, Thread)
- {
+ fn spawn_inner<T: Send>(self, f: Thunk<(), T>) -> io::Result<JoinInner<T>> {
let Builder { name, stack_size, stdout, stderr } = self;
let stack_size = stack_size.unwrap_or(rt::min_stack());
+
let my_thread = Thread::new(name);
let their_thread = my_thread.clone();
+ let my_packet = Packet(Arc::new(UnsafeCell::new(None)));
+ let their_packet = Packet(my_packet.0.clone());
+
// Spawning a new OS thread guarantees that __morestack will never get
// triggered, but we must manually set up the actual stack bounds once
// this function starts executing. This raises the lower limit by a bit
unwind::try(move || *ptr = Some(f.invoke(())))
}
};
- finish.invoke(match (output, try_result) {
- (Some(data), Ok(_)) => Ok(data),
- (None, Err(cause)) => Err(cause),
- _ => unreachable!()
- });
+ unsafe {
+ *their_packet.0.get() = Some(match (output, try_result) {
+ (Some(data), Ok(_)) => Ok(data),
+ (None, Err(cause)) => Err(cause),
+ _ => unreachable!()
+ });
+ }
};
- (unsafe { imp::create(stack_size, Thunk::new(main)) }, my_thread)
+ Ok(JoinInner {
+ native: try!(unsafe { imp::create(stack_size, Thunk::new(main)) }),
+ thread: my_thread,
+ packet: my_packet,
+ joined: false,
+ })
+ }
+}
+
+/// Spawn a new, returning a join handle for it.
+///
+/// The child thread may outlive the parent (unless the parent thread
+/// is the main thread; the whole process is terminated when the main
+/// thread finishes.) The join handle can be used to block on
+/// termination of the child thread, including recovering its panics.
+///
+/// # Panics
+///
+/// Panicks if the OS fails to create a thread; use `Builder::spawn`
+/// to recover from such errors.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub fn spawn<F>(f: F) -> JoinHandle where F: FnOnce(), F: Send + 'static {
+ Builder::new().spawn(f).unwrap()
+}
+
+/// Spawn a new *scoped* thread, returning a `JoinGuard` for it.
+///
+/// The join guard can be used to explicitly join the child thread (via
+/// `join`), returning `Result<T>`, or it will implicitly join the child
+/// upon being dropped. Because the child thread may refer to data on the
+/// current thread's stack (hence the "scoped" name), it cannot be detached;
+/// it *must* be joined before the relevant stack frame is popped. See the
+/// module documentation for additional details.
+///
+/// # Panics
+///
+/// Panicks if the OS fails to create a thread; use `Builder::scoped`
+/// to recover from such errors.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub fn scoped<'a, T, F>(f: F) -> JoinGuard<'a, T> where
+ T: Send + 'a, F: FnOnce() -> T, F: Send + 'a
+{
+ Builder::new().scoped(f).unwrap()
+}
+
+/// Gets a handle to the thread that invokes it.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub fn current() -> Thread {
+ thread_info::current_thread()
+}
+
+/// Cooperatively give up a timeslice to the OS scheduler.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub fn yield_now() {
+ unsafe { imp::yield_now() }
+}
+
+/// Determines whether the current thread is unwinding because of panic.
+#[inline]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub fn panicking() -> bool {
+ unwind::panicking()
+}
+
+/// Block unless or until the current thread's token is made available (may wake spuriously).
+///
+/// See the module doc for more detail.
+//
+// The implementation currently uses the trivial strategy of a Mutex+Condvar
+// with wakeup flag, which does not actually allow spurious wakeups. In the
+// future, this will be implemented in a more efficient way, perhaps along the lines of
+// http://cr.openjdk.java.net/~stefank/6989984.1/raw_files/new/src/os/linux/vm/os_linux.cpp
+// or futuxes, and in either case may allow spurious wakeups.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub fn park() {
+ let thread = current();
+ let mut guard = thread.inner.lock.lock().unwrap();
+ while !*guard {
+ guard = thread.inner.cvar.wait(guard).unwrap();
}
+ *guard = false;
+}
+
+/// Block unless or until the current thread's token is made available or
+/// the specified duration has been reached (may wake spuriously).
+///
+/// The semantics of this function are equivalent to `park()` except that the
+/// thread will be blocked for roughly no longer than dur. This method
+/// should not be used for precise timing due to anomalies such as
+/// preemption or platform differences that may not cause the maximum
+/// amount of time waited to be precisely dur
+///
+/// See the module doc for more detail.
+#[unstable(feature = "std_misc", reason = "recently introduced, depends on Duration")]
+pub fn park_timeout(dur: Duration) {
+ let thread = current();
+ let mut guard = thread.inner.lock.lock().unwrap();
+ if !*guard {
+ let (g, _) = thread.inner.cvar.wait_timeout(guard, dur).unwrap();
+ guard = g;
+ }
+ *guard = false;
}
+/// The internal representation of a `Thread` handle
struct Inner {
name: Option<String>,
lock: Mutex<bool>, // true when there is a buffered unpark
}
}
- /// Spawn a new detached thread, returning a handle to it.
- ///
- /// The child thread may outlive the parent (unless the parent thread is the
- /// main thread; the whole process is terminated when the main thread
- /// finishes.) The thread handle can be used for low-level
- /// synchronization. See the module documentation for additional details.
+ /// Deprecated: use module-level free fucntion.
+ #[deprecated(since = "1.0.0", reason = "use module-level free fucntion")]
#[unstable(feature = "std_misc",
reason = "may change with specifics of new Send semantics")]
pub fn spawn<F>(f: F) -> Thread where F: FnOnce(), F: Send + 'static {
- Builder::new().spawn(f)
+ Builder::new().spawn(f).unwrap().thread().clone()
}
- /// Spawn a new *scoped* thread, returning a `JoinGuard` for it.
- ///
- /// The join guard can be used to explicitly join the child thread (via
- /// `join`), returning `Result<T>`, or it will implicitly join the child
- /// upon being dropped. Because the child thread may refer to data on the
- /// current thread's stack (hence the "scoped" name), it cannot be detached;
- /// it *must* be joined before the relevant stack frame is popped. See the
- /// module documentation for additional details.
+ /// Deprecated: use module-level free fucntion.
+ #[deprecated(since = "1.0.0", reason = "use module-level free fucntion")]
#[unstable(feature = "std_misc",
reason = "may change with specifics of new Send semantics")]
pub fn scoped<'a, T, F>(f: F) -> JoinGuard<'a, T> where
T: Send + 'a, F: FnOnce() -> T, F: Send + 'a
{
- Builder::new().scoped(f)
+ Builder::new().scoped(f).unwrap()
}
- /// Gets a handle to the thread that invokes it.
+ /// Deprecated: use module-level free fucntion.
+ #[deprecated(since = "1.0.0", reason = "use module-level free fucntion")]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn current() -> Thread {
thread_info::current_thread()
}
- /// Cooperatively give up a timeslice to the OS scheduler.
+ /// Deprecated: use module-level free fucntion.
+ #[deprecated(since = "1.0.0", reason = "use module-level free fucntion")]
#[unstable(feature = "std_misc", reason = "name may change")]
pub fn yield_now() {
unsafe { imp::yield_now() }
}
- /// Determines whether the current thread is unwinding because of panic.
+ /// Deprecated: use module-level free fucntion.
+ #[deprecated(since = "1.0.0", reason = "use module-level free fucntion")]
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn panicking() -> bool {
unwind::panicking()
}
- /// Block unless or until the current thread's token is made available (may wake spuriously).
- ///
- /// See the module doc for more detail.
- //
- // The implementation currently uses the trivial strategy of a Mutex+Condvar
- // with wakeup flag, which does not actually allow spurious wakeups. In the
- // future, this will be implemented in a more efficient way, perhaps along the lines of
- // http://cr.openjdk.java.net/~stefank/6989984.1/raw_files/new/src/os/linux/vm/os_linux.cpp
- // or futuxes, and in either case may allow spurious wakeups.
+ /// Deprecated: use module-level free fucntion.
+ #[deprecated(since = "1.0.0", reason = "use module-level free fucntion")]
#[unstable(feature = "std_misc", reason = "recently introduced")]
pub fn park() {
- let thread = Thread::current();
+ let thread = current();
let mut guard = thread.inner.lock.lock().unwrap();
while !*guard {
guard = thread.inner.cvar.wait(guard).unwrap();
*guard = false;
}
- /// Block unless or until the current thread's token is made available or
- /// the specified duration has been reached (may wake spuriously).
- ///
- /// The semantics of this function are equivalent to `park()` except that the
- /// thread will be blocked for roughly no longer than dur. This method
- /// should not be used for precise timing due to anomalies such as
- /// preemption or platform differences that may not cause the maximum
- /// amount of time waited to be precisely dur
- ///
- /// See the module doc for more detail.
+ /// Deprecated: use module-level free fucntion.
+ #[deprecated(since = "1.0.0", reason = "use module-level free fucntion")]
#[unstable(feature = "std_misc", reason = "recently introduced")]
pub fn park_timeout(dur: Duration) {
- let thread = Thread::current();
+ let thread = current();
let mut guard = thread.inner.lock.lock().unwrap();
if !*guard {
let (g, _) = thread.inner.cvar.wait_timeout(guard, dur).unwrap();
/// Atomically makes the handle's token available if it is not already.
///
/// See the module doc for more detail.
- #[unstable(feature = "std_misc", reason = "recently introduced")]
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn unpark(&self) {
let mut guard = self.inner.lock.lock().unwrap();
if !*guard {
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
+impl fmt::Debug for Thread {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ fmt::Debug::fmt(&self.name(), f)
+ }
+}
+
// a hack to get around privacy restrictions
impl thread_info::NewThread for Thread {
fn new(name: Option<String>) -> Thread { Thread::new(name) }
///
/// A thread that completes without panicking is considered to exit successfully.
#[stable(feature = "rust1", since = "1.0.0")]
-pub type Result<T> = ::result::Result<T, Box<Any + Send>>;
+pub type Result<T> = ::result::Result<T, Box<Any + Send + 'static>>;
struct Packet<T>(Arc<UnsafeCell<Option<Result<T>>>>);
-unsafe impl<T:'static+Send> Send for Packet<T> {}
+unsafe impl<T:Send> Send for Packet<T> {}
unsafe impl<T> Sync for Packet<T> {}
+/// Inner representation for JoinHandle and JoinGuard
+struct JoinInner<T> {
+ native: imp::rust_thread,
+ thread: Thread,
+ packet: Packet<T>,
+ joined: bool,
+}
+
+impl<T> JoinInner<T> {
+ fn join(&mut self) -> Result<T> {
+ assert!(!self.joined);
+ unsafe { imp::join(self.native) };
+ self.joined = true;
+ unsafe {
+ (*self.packet.0.get()).take().unwrap()
+ }
+ }
+}
+
+/// An owned permission to join on a thread (block on its termination).
+///
+/// Unlike a `JoinGuard`, a `JoinHandle` *detaches* the child thread
+/// when it is dropped, rather than automatically joining on drop.
+///
+/// Due to platform restrictions, it is not possible to `Clone` this
+/// handle: the ability to join a child thread is a uniquely-owned
+/// permission.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct JoinHandle(JoinInner<()>);
+
+impl JoinHandle {
+ /// Extract a handle to the underlying thread
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn thread(&self) -> &Thread {
+ &self.0.thread
+ }
+
+ /// Wait for the associated thread to finish.
+ ///
+ /// If the child thread panics, `Err` is returned with the parameter given
+ /// to `panic`.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn join(mut self) -> Result<()> {
+ self.0.join()
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Drop for JoinHandle {
+ fn drop(&mut self) {
+ if !self.0.joined {
+ unsafe { imp::detach(self.0.native) }
+ }
+ }
+}
+
/// An RAII-style guard that will block until thread termination when dropped.
///
/// The type `T` is the return type for the thread's main function.
+///
+/// Joining on drop is necessary to ensure memory safety when stack
+/// data is shared between a parent and child thread.
+///
+/// Due to platform restrictions, it is not possible to `Clone` this
+/// handle: the ability to join a child thread is a uniquely-owned
+/// permission.
#[must_use]
-#[unstable(feature = "std_misc",
- reason = "may change with specifics of new Send semantics")]
+#[stable(feature = "rust1", since = "1.0.0")]
pub struct JoinGuard<'a, T: 'a> {
- native: imp::rust_thread,
- thread: Thread,
- joined: bool,
- packet: Packet<T>,
+ inner: JoinInner<T>,
+ _marker: marker::CovariantType<&'a T>,
}
#[stable(feature = "rust1", since = "1.0.0")]
/// Extract a handle to the thread this guard will join on.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn thread(&self) -> &Thread {
- &self.thread
+ &self.inner.thread
}
/// Wait for the associated thread to finish, returning the result of the thread's
/// calculation.
///
- /// If the child thread panics, `Err` is returned with the parameter given
- /// to `panic`.
+ /// # Panics
+ ///
+ /// Panics on the child thread are propagated by panicking the parent.
#[stable(feature = "rust1", since = "1.0.0")]
- pub fn join(mut self) -> Result<T> {
- assert!(!self.joined);
- unsafe { imp::join(self.native) };
- self.joined = true;
- unsafe {
- (*self.packet.0.get()).take().unwrap()
+ pub fn join(mut self) -> T {
+ match self.inner.join() {
+ Ok(res) => res,
+ Err(_) => panic!("child thread {:?} panicked", self.thread()),
}
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Send> JoinGuard<'static, T> {
/// Detaches the child thread, allowing it to outlive its parent.
- #[unstable(feature = "std_misc",
- reason = "unsure whether this API imposes limitations elsewhere")]
+ #[deprecated(since = "1.0.0", reason = "use spawn instead")]
+ #[unstable(feature = "std_misc")]
pub fn detach(mut self) {
- unsafe { imp::detach(self.native) };
- self.joined = true; // avoid joining in the destructor
+ unsafe { imp::detach(self.inner.native) };
+ self.inner.joined = true; // avoid joining in the destructor
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: Send + 'a> Drop for JoinGuard<'a, T> {
fn drop(&mut self) {
- if !self.joined {
- unsafe { imp::join(self.native) };
+ if !self.inner.joined {
+ if self.inner.join().is_err() {
+ panic!("child thread {:?} panicked", self.thread());
+ }
}
}
}
use result;
use std::old_io::{ChanReader, ChanWriter};
use super::{Thread, Builder};
+ use thread;
use thunk::Thunk;
use time::Duration;
#[test]
fn test_unnamed_thread() {
- Thread::scoped(move|| {
- assert!(Thread::current().name().is_none());
+ thread::spawn(move|| {
+ assert!(thread::current().name().is_none());
}).join().ok().unwrap();
}
#[test]
fn test_named_thread() {
Builder::new().name("ada lovelace".to_string()).scoped(move|| {
- assert!(Thread::current().name().unwrap() == "ada lovelace".to_string());
- }).join().ok().unwrap();
+ assert!(thread::current().name().unwrap() == "ada lovelace".to_string());
+ }).unwrap().join();
}
#[test]
fn test_run_basic() {
let (tx, rx) = channel();
- Thread::spawn(move|| {
+ thread::spawn(move|| {
tx.send(()).unwrap();
});
rx.recv().unwrap();
#[test]
fn test_join_success() {
- match Thread::scoped(move|| -> String {
+ assert!(thread::scoped(move|| -> String {
"Success!".to_string()
- }).join().as_ref().map(|s| &**s) {
- result::Result::Ok("Success!") => (),
- _ => panic!()
- }
+ }).join() == "Success!");
}
#[test]
fn test_join_panic() {
- match Thread::scoped(move|| {
+ match thread::spawn(move|| {
panic!()
}).join() {
result::Result::Err(_) => (),
}
}
+ #[test]
+ fn test_scoped_success() {
+ let res = thread::scoped(move|| -> String {
+ "Success!".to_string()
+ }).join();
+ assert!(res == "Success!");
+ }
+
+ #[test]
+ #[should_fail]
+ fn test_scoped_panic() {
+ thread::scoped(|| panic!()).join();
+ }
+
+ #[test]
+ #[should_fail]
+ fn test_scoped_implicit_panic() {
+ thread::scoped(|| panic!());
+ }
+
#[test]
fn test_spawn_sched() {
use clone::Clone;
fn f(i: int, tx: Sender<()>) {
let tx = tx.clone();
- Thread::spawn(move|| {
+ thread::spawn(move|| {
if i == 0 {
tx.send(()).unwrap();
} else {
fn test_spawn_sched_childs_on_default_sched() {
let (tx, rx) = channel();
- Thread::spawn(move|| {
- Thread::spawn(move|| {
+ thread::spawn(move|| {
+ thread::spawn(move|| {
tx.send(()).unwrap();
});
});
rx.recv().unwrap();
}
- fn avoid_copying_the_body<F>(spawnfn: F) where F: FnOnce(Thunk) {
+ fn avoid_copying_the_body<F>(spawnfn: F) where F: FnOnce(Thunk<'static>) {
let (tx, rx) = channel::<uint>();
let x = box 1;
#[test]
fn test_avoid_copying_the_body_spawn() {
avoid_copying_the_body(|v| {
- Thread::spawn(move || v.invoke(()));
+ thread::spawn(move || v.invoke(()));
});
}
#[test]
fn test_avoid_copying_the_body_thread_spawn() {
avoid_copying_the_body(|f| {
- Thread::spawn(move|| {
+ thread::spawn(move|| {
f.invoke(());
});
})
#[test]
fn test_avoid_copying_the_body_join() {
avoid_copying_the_body(|f| {
- let _ = Thread::scoped(move|| {
+ let _ = thread::spawn(move|| {
f.invoke(())
}).join();
})
// (well, it would if the constant were 8000+ - I lowered it to be more
// valgrind-friendly. try this at home, instead..!)
static GENERATIONS: uint = 16;
- fn child_no(x: uint) -> Thunk {
+ fn child_no(x: uint) -> Thunk<'static> {
return Thunk::new(move|| {
if x < GENERATIONS {
- Thread::spawn(move|| child_no(x+1).invoke(()));
+ thread::spawn(move|| child_no(x+1).invoke(()));
}
});
}
- Thread::spawn(|| child_no(0).invoke(()));
+ thread::spawn(|| child_no(0).invoke(()));
}
#[test]
fn test_simple_newsched_spawn() {
- Thread::spawn(move || {});
+ thread::spawn(move || {});
}
#[test]
fn test_try_panic_message_static_str() {
- match Thread::scoped(move|| {
+ match thread::spawn(move|| {
panic!("static string");
}).join() {
Err(e) => {
#[test]
fn test_try_panic_message_owned_str() {
- match Thread::scoped(move|| {
+ match thread::spawn(move|| {
panic!("owned string".to_string());
}).join() {
Err(e) => {
#[test]
fn test_try_panic_message_any() {
- match Thread::scoped(move|| {
+ match thread::spawn(move|| {
panic!(box 413u16 as Box<Any + Send>);
}).join() {
Err(e) => {
fn test_try_panic_message_unit_struct() {
struct Juju;
- match Thread::scoped(move|| {
+ match thread::spawn(move|| {
panic!(Juju)
}).join() {
Err(ref e) if e.is::<Juju>() => {}
let mut reader = ChanReader::new(rx);
let stdout = ChanWriter::new(tx);
- let r = Builder::new().stdout(box stdout as Box<Writer + Send>).scoped(move|| {
+ Builder::new().stdout(box stdout as Box<Writer + Send>).scoped(move|| {
print!("Hello, world!");
- }).join();
- assert!(r.is_ok());
+ }).unwrap().join();
let output = reader.read_to_string().unwrap();
assert_eq!(output, "Hello, world!".to_string());
#[test]
fn test_park_timeout_unpark_before() {
for _ in 0..10 {
- Thread::current().unpark();
- Thread::park_timeout(Duration::seconds(10_000_000));
+ thread::current().unpark();
+ thread::park_timeout(Duration::seconds(10_000_000));
}
}
#[test]
fn test_park_timeout_unpark_not_called() {
for _ in 0..10 {
- Thread::park_timeout(Duration::milliseconds(10));
+ thread::park_timeout(Duration::milliseconds(10));
}
}
use std::old_io;
for _ in 0..10 {
- let th = Thread::current();
+ let th = thread::current();
- let _guard = Thread::scoped(move || {
+ let _guard = thread::spawn(move || {
old_io::timer::sleep(Duration::milliseconds(50));
th.unpark();
});
- Thread::park_timeout(Duration::seconds(10_000_000));
+ thread::park_timeout(Duration::seconds(10_000_000));
}
}
///
/// ```
/// use std::cell::RefCell;
-/// use std::thread::Thread;
+/// use std::thread;
///
/// thread_local!(static FOO: RefCell<uint> = RefCell::new(1));
///
/// });
///
/// // each thread starts out with the initial value of 1
-/// Thread::spawn(move|| {
+/// thread::spawn(move|| {
/// FOO.with(|f| {
/// assert_eq!(*f.borrow(), 1);
/// *f.borrow_mut() = 3;
use sync::mpsc::{channel, Sender};
use cell::UnsafeCell;
use super::State;
- use thread::Thread;
+ use thread;
struct Foo(Sender<()>);
*f.get() = 2;
});
let (tx, rx) = channel();
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
FOO.with(|f| unsafe {
assert_eq!(*f.get(), 1);
});
}
thread_local!(static FOO: Foo = foo());
- Thread::scoped(|| {
+ thread::spawn(|| {
assert!(FOO.state() == State::Uninitialized);
FOO.with(|_| {
assert!(FOO.state() == State::Valid);
});
let (tx, rx) = channel();
- let _t = Thread::spawn(move|| unsafe {
+ let _t = thread::spawn(move|| unsafe {
let mut tx = Some(tx);
FOO.with(|f| {
*f.get() = Some(Foo(tx.take().unwrap()));
}
}
- Thread::scoped(move|| {
+ thread::spawn(move|| {
drop(S1);
}).join().ok().unwrap();
}
}
}
- Thread::scoped(move|| unsafe {
+ thread::spawn(move|| unsafe {
K1.with(|s| *s.get() = Some(S1));
}).join().ok().unwrap();
}
}
let (tx, rx) = channel();
- let _t = Thread::spawn(move|| unsafe {
+ let _t = thread::spawn(move|| unsafe {
let mut tx = Some(tx);
K1.with(|s| *s.get() = Some(S1(tx.take().unwrap())));
});
use core::marker::Send;
use core::ops::FnOnce;
-pub struct Thunk<A=(),R=()> {
- invoke: Box<Invoke<A,R>+Send>
+pub struct Thunk<'a, A=(),R=()> {
+ #[cfg(stage0)]
+ invoke: Box<Invoke<A,R>+Send>,
+ #[cfg(not(stage0))]
+ invoke: Box<Invoke<A,R>+Send + 'a>,
}
-impl<R> Thunk<(),R> {
- pub fn new<F>(func: F) -> Thunk<(),R>
- where F : FnOnce() -> R, F : Send
+impl<'a, R> Thunk<'a,(),R> {
+ pub fn new<F>(func: F) -> Thunk<'a,(),R>
+ where F : FnOnce() -> R, F : Send + 'a
{
Thunk::with_arg(move|()| func())
}
}
-impl<A,R> Thunk<A,R> {
- pub fn with_arg<F>(func: F) -> Thunk<A,R>
- where F : FnOnce(A) -> R, F : Send
+impl<'a,A,R> Thunk<'a,A,R> {
+ pub fn with_arg<F>(func: F) -> Thunk<'a,A,R>
+ where F : FnOnce(A) -> R, F : Send + 'a
{
Thunk {
invoke: box func
}
fn find_entry(&self, id: NodeId) -> Option<MapEntry<'ast>> {
- self.map.borrow().get(id as usize).map(|e| *e)
+ self.map.borrow().get(id as usize).cloned()
}
pub fn krate(&self) -> &'ast Crate {
impl Registry {
pub fn new(descriptions: &[(&'static str, &'static str)]) -> Registry {
- Registry { descriptions: descriptions.iter().map(|&tuple| tuple).collect() }
+ Registry { descriptions: descriptions.iter().cloned().collect() }
}
pub fn find_description(&self, code: &str) -> Option<&'static str> {
- self.descriptions.get(code).map(|desc| *desc)
+ self.descriptions.get(code).cloned()
}
}
use codemap::Span;
use ext::base;
use ext::base::*;
+use feature_gate;
use parse::token::InternedString;
use parse::token;
use ptr::P;
pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
-> Box<base::MacResult+'cx> {
+ if !cx.ecfg.enable_asm() {
+ feature_gate::emit_feature_err(
+ &cx.parse_sess.span_diagnostic, "asm", sp, feature_gate::EXPLAIN_ASM);
+ return DummyResult::expr(sp);
+ }
+
let mut p = cx.new_parser_from_tts(tts);
let mut asm = InternedString::new("");
let mut asm_str_style = None;
/// The base map of methods for expanding syntax extension
/// AST nodes into full ASTs
-fn initial_syntax_expander_table(ecfg: &expand::ExpansionConfig) -> SyntaxEnv {
+fn initial_syntax_expander_table<'feat>(ecfg: &expand::ExpansionConfig<'feat>)
+ -> SyntaxEnv {
// utility function to simplify creating NormalTT syntax extensions
fn builtin_normal_expander(f: MacroExpanderFn) -> SyntaxExtension {
NormalTT(box f, None)
syntax_expanders.insert(intern("deriving"),
Decorator(box ext::deriving::expand_deprecated_deriving));
- if ecfg.enable_quotes {
+ if ecfg.enable_quotes() {
// Quasi-quoting expanders
syntax_expanders.insert(intern("quote_tokens"),
builtin_normal_expander(
pub parse_sess: &'a parse::ParseSess,
pub cfg: ast::CrateConfig,
pub backtrace: ExpnId,
- pub ecfg: expand::ExpansionConfig,
+ pub ecfg: expand::ExpansionConfig<'a>,
pub use_std: bool,
pub mod_path: Vec<ast::Ident> ,
impl<'a> ExtCtxt<'a> {
pub fn new(parse_sess: &'a parse::ParseSess, cfg: ast::CrateConfig,
- ecfg: expand::ExpansionConfig) -> ExtCtxt<'a> {
+ ecfg: expand::ExpansionConfig<'a>) -> ExtCtxt<'a> {
let env = initial_syntax_expander_table(&ecfg);
ExtCtxt {
parse_sess: parse_sess,
pub fn mod_path(&self) -> Vec<ast::Ident> {
let mut v = Vec::new();
v.push(token::str_to_ident(&self.ecfg.crate_name[]));
- v.extend(self.mod_path.iter().map(|a| *a));
+ v.extend(self.mod_path.iter().cloned());
return v;
}
pub fn bt_push(&mut self, ei: ExpnInfo) {
use codemap::Span;
use ext::base::*;
use ext::base;
+use feature_gate;
use parse::token;
use parse::token::{str_to_ident};
use ptr::P;
pub fn expand_syntax_ext<'cx>(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
-> Box<base::MacResult+'cx> {
+ if !cx.ecfg.enable_concat_idents() {
+ feature_gate::emit_feature_err(&cx.parse_sess.span_diagnostic,
+ "concat_idents",
+ sp,
+ feature_gate::EXPLAIN_CONCAT_IDENTS);
+ return base::DummyResult::expr(sp);
+ }
+
let mut res_str = String::new();
for (i, e) in tts.iter().enumerate() {
if i & 1 == 1 {
"allow" | "warn" | "deny" | "forbid" => true,
_ => false,
}
- }).map(|a| a.clone()));
+ }).cloned());
push(P(ast::Item {
attrs: attrs,
..(*newitem).clone()
let mut ty_params = ty_params.into_vec();
// Copy the lifetimes
- lifetimes.extend(generics.lifetimes.iter().map(|l| (*l).clone()));
+ lifetimes.extend(generics.lifetimes.iter().cloned());
// Create the type parameters.
ty_params.extend(generics.ty_params.iter().map(|ty_param| {
span: self.span,
bound_lifetimes: wb.bound_lifetimes.clone(),
bounded_ty: wb.bounded_ty.clone(),
- bounds: OwnedSlice::from_vec(wb.bounds.iter().map(|b| b.clone()).collect())
+ bounds: OwnedSlice::from_vec(wb.bounds.iter().cloned().collect())
})
}
ast::WherePredicate::RegionPredicate(ref rb) => {
ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate {
span: self.span,
lifetime: rb.lifetime,
- bounds: rb.bounds.iter().map(|b| b.clone()).collect()
+ bounds: rb.bounds.iter().cloned().collect()
})
}
ast::WherePredicate::EqPredicate(ref we) => {
let opt_trait_ref = Some(trait_ref);
let ident = ast_util::impl_pretty_name(&opt_trait_ref, &*self_type);
let mut a = vec![attr];
- a.extend(self.attributes.iter().map(|a| a.clone()));
+ a.extend(self.attributes.iter().cloned());
cx.item(
self.span,
ident,
use codemap;
use codemap::{Span, Spanned, ExpnInfo, NameAndSpan, MacroBang, MacroAttribute};
use ext::base::*;
+use feature_gate::{Features};
use fold;
use fold::*;
use parse;
}
}
-pub struct ExpansionConfig {
+pub struct ExpansionConfig<'feat> {
pub crate_name: String,
- pub enable_quotes: bool,
+ pub features: Option<&'feat Features>,
pub recursion_limit: usize,
}
-impl ExpansionConfig {
- pub fn default(crate_name: String) -> ExpansionConfig {
+impl<'feat> ExpansionConfig<'feat> {
+ pub fn default(crate_name: String) -> ExpansionConfig<'static> {
ExpansionConfig {
crate_name: crate_name,
- enable_quotes: false,
+ features: None,
recursion_limit: 64,
}
}
+
+ pub fn enable_quotes(&self) -> bool {
+ match self.features {
+ Some(&Features { allow_quote: true, .. }) => true,
+ _ => false,
+ }
+ }
+
+ pub fn enable_asm(&self) -> bool {
+ match self.features {
+ Some(&Features { allow_asm: true, .. }) => true,
+ _ => false,
+ }
+ }
+
+ pub fn enable_log_syntax(&self) -> bool {
+ match self.features {
+ Some(&Features { allow_log_syntax: true, .. }) => true,
+ _ => false,
+ }
+ }
+
+ pub fn enable_concat_idents(&self) -> bool {
+ match self.features {
+ Some(&Features { allow_concat_idents: true, .. }) => true,
+ _ => false,
+ }
+ }
+
+ pub fn enable_trace_macros(&self) -> bool {
+ match self.features {
+ Some(&Features { allow_trace_macros: true, .. }) => true,
+ _ => false,
+ }
+ }
}
-pub fn expand_crate(parse_sess: &parse::ParseSess,
- cfg: ExpansionConfig,
- // these are the macros being imported to this crate:
- imported_macros: Vec<ast::MacroDef>,
- user_exts: Vec<NamedSyntaxExtension>,
- c: Crate) -> Crate {
+pub fn expand_crate<'feat>(parse_sess: &parse::ParseSess,
+ cfg: ExpansionConfig<'feat>,
+ // these are the macros being imported to this crate:
+ imported_macros: Vec<ast::MacroDef>,
+ user_exts: Vec<NamedSyntaxExtension>,
+ c: Crate) -> Crate {
let mut cx = ExtCtxt::new(parse_sess, c.config.clone(), cfg);
cx.use_std = std_inject::use_std(&c);
// these following tests are quite fragile, in that they don't test what
// *kind* of failure occurs.
- fn test_ecfg() -> ExpansionConfig {
+ fn test_ecfg() -> ExpansionConfig<'static> {
ExpansionConfig::default("test".to_string())
}
use ast;
use codemap;
use ext::base;
+use feature_gate;
use print;
pub fn expand_syntax_ext<'cx>(cx: &'cx mut base::ExtCtxt,
sp: codemap::Span,
tts: &[ast::TokenTree])
-> Box<base::MacResult+'cx> {
+ if !cx.ecfg.enable_log_syntax() {
+ feature_gate::emit_feature_err(&cx.parse_sess.span_diagnostic,
+ "log_syntax",
+ sp,
+ feature_gate::EXPLAIN_LOG_SYNTAX);
+ return base::DummyResult::any(sp);
+ }
cx.print_backtrace();
return DummyResult::expr(sp);
}
Ok(bytes) => {
- let bytes = bytes.iter().map(|x| *x).collect();
+ let bytes = bytes.iter().cloned().collect();
base::MacExpr::new(cx.expr_lit(sp, ast::LitBinary(Rc::new(bytes))))
}
}
use codemap::Span;
use ext::base::ExtCtxt;
use ext::base;
+use feature_gate;
use parse::token::keywords;
sp: Span,
tt: &[ast::TokenTree])
-> Box<base::MacResult+'static> {
+ if !cx.ecfg.enable_trace_macros() {
+ feature_gate::emit_feature_err(&cx.parse_sess.span_diagnostic,
+ "trace_macros",
+ sp,
+ feature_gate::EXPLAIN_TRACE_MACROS);
+ return base::DummyResult::any(sp);
+ }
+
+
match tt {
[ast::TtToken(_, ref tok)] if tok.is_keyword(keywords::True) => {
cx.set_trace_macros(true);
-> ParseResult {
let mut cur_eis = Vec::new();
cur_eis.push(initial_matcher_pos(Rc::new(ms.iter()
- .map(|x| (*x).clone())
+ .cloned()
.collect()),
None,
rdr.peek().sp.lo));
None,
None,
arg.iter()
- .map(|x| (*x).clone())
+ .cloned()
.collect(),
true);
match parse(cx.parse_sess(), cx.cfg(), arg_rdr, lhs_tt) {
//! becomes stable.
use self::Status::*;
+use self::AttributeType::*;
use abi::RustIntrinsic;
use ast::NodeId;
use visit::Visitor;
use parse::token::{self, InternedString};
-use std::slice;
use std::ascii::AsciiExt;
// If you change this list without updating src/doc/reference.md, @cmr will be sad
// Allows using the unsafe_no_drop_flag attribute (unlikely to
// switch to Accepted; see RFC 320)
("unsafe_no_drop_flag", "1.0.0", Active),
+
+ // Allows the use of custom attributes; RFC 572
+ ("custom_attribute", "1.0.0", Active),
+
+ // Allows the use of rustc_* attributes; RFC 572
+ ("rustc_attrs", "1.0.0", Active),
];
// (changing above list without updating src/doc/reference.md makes @cmr sad)
Accepted,
}
+// Attributes that have a special meaning to rustc or rustdoc
+pub static KNOWN_ATTRIBUTES: &'static [(&'static str, AttributeType)] = &[
+ // Normal attributes
+
+ ("warn", Normal),
+ ("allow", Normal),
+ ("forbid", Normal),
+ ("deny", Normal),
+
+ ("macro_reexport", Normal),
+ ("macro_use", Normal),
+ ("macro_export", Normal),
+ ("plugin_registrar", Normal),
+
+ ("cfg", Normal),
+ ("main", Normal),
+ ("start", Normal),
+ ("test", Normal),
+ ("bench", Normal),
+ ("simd", Normal),
+ ("repr", Normal),
+ ("path", Normal),
+ ("abi", Normal),
+ ("unsafe_destructor", Normal),
+ ("automatically_derived", Normal),
+ ("no_mangle", Normal),
+ ("no_link", Normal),
+ ("derive", Normal),
+ ("should_fail", Normal),
+ ("ignore", Normal),
+ ("no_implicit_prelude", Normal),
+ ("reexport_test_harness_main", Normal),
+ ("link_args", Normal),
+ ("macro_escape", Normal),
+
+
+ ("staged_api", Gated("staged_api",
+ "staged_api is for use by rustc only")),
+ ("plugin", Gated("plugin",
+ "compiler plugins are experimental \
+ and possibly buggy")),
+ ("no_std", Gated("no_std",
+ "no_std is experimental")),
+ ("lang", Gated("lang_items",
+ "language items are subject to change")),
+ ("linkage", Gated("linkage",
+ "the `linkage` attribute is experimental \
+ and not portable across platforms")),
+ ("thread_local", Gated("thread_local",
+ "`#[thread_local]` is an experimental feature, and does not \
+ currently handle destructors. There is no corresponding \
+ `#[task_local]` mapping to the task model")),
+
+ ("rustc_on_unimplemented", Gated("on_unimplemented",
+ "the `#[rustc_on_unimplemented]` attribute \
+ is an experimental feature")),
+ ("rustc_variance", Gated("rustc_attrs",
+ "the `#[rustc_variance]` attribute \
+ is an experimental feature")),
+ ("rustc_error", Gated("rustc_attrs",
+ "the `#[rustc_error]` attribute \
+ is an experimental feature")),
+ ("rustc_move_fragments", Gated("rustc_attrs",
+ "the `#[rustc_move_fragments]` attribute \
+ is an experimental feature")),
+
+ // FIXME: #14408 whitelist docs since rustdoc looks at them
+ ("doc", Whitelisted),
+
+ // FIXME: #14406 these are processed in trans, which happens after the
+ // lint pass
+ ("cold", Whitelisted),
+ ("export_name", Whitelisted),
+ ("inline", Whitelisted),
+ ("link", Whitelisted),
+ ("link_name", Whitelisted),
+ ("link_section", Whitelisted),
+ ("no_builtins", Whitelisted),
+ ("no_mangle", Whitelisted),
+ ("no_split_stack", Whitelisted),
+ ("no_stack_check", Whitelisted),
+ ("packed", Whitelisted),
+ ("static_assert", Whitelisted),
+ ("no_debug", Whitelisted),
+ ("omit_gdb_pretty_printer_section", Whitelisted),
+ ("unsafe_no_drop_flag", Whitelisted),
+
+ // used in resolve
+ ("prelude_import", Whitelisted),
+
+ // FIXME: #14407 these are only looked at on-demand so we can't
+ // guarantee they'll have already been checked
+ ("deprecated", Whitelisted),
+ ("must_use", Whitelisted),
+ ("stable", Whitelisted),
+ ("unstable", Whitelisted),
+
+ // FIXME: #19470 this shouldn't be needed forever
+ ("old_orphan_check", Whitelisted),
+ ("old_impl_check", Whitelisted),
+ ("rustc_paren_sugar", Whitelisted), // FIXME: #18101 temporary unboxed closure hack
+
+ // Crate level attributes
+ ("crate_name", CrateLevel),
+ ("crate_type", CrateLevel),
+ ("crate_id", CrateLevel),
+ ("feature", CrateLevel),
+ ("no_start", CrateLevel),
+ ("no_main", CrateLevel),
+ ("no_builtins", CrateLevel),
+ ("recursion_limit", CrateLevel),
+];
+
+#[derive(PartialEq, Copy)]
+pub enum AttributeType {
+ /// Normal, builtin attribute that is consumed
+ /// by the compiler before the unused_attribute check
+ Normal,
+
+ /// Builtin attribute that may not be consumed by the compiler
+ /// before the unused_attribute check. These attributes
+ /// will be ignored by the unused_attribute lint
+ Whitelisted,
+
+ /// Is gated by a given feature gate and reason
+ /// These get whitelisted too
+ Gated(&'static str, &'static str),
+
+ /// Builtin attribute that is only allowed at the crate level
+ CrateLevel,
+}
+
/// A set of features to be used by later passes.
pub struct Features {
pub unboxed_closures: bool,
pub rustc_diagnostic_macros: bool,
pub visible_private_types: bool,
- pub quote: bool,
+ pub allow_quote: bool,
+ pub allow_asm: bool,
+ pub allow_log_syntax: bool,
+ pub allow_concat_idents: bool,
+ pub allow_trace_macros: bool,
pub old_orphan_check: bool,
pub simd_ffi: bool,
pub unmarked_api: bool,
unboxed_closures: false,
rustc_diagnostic_macros: false,
visible_private_types: false,
- quote: false,
+ allow_quote: false,
+ allow_asm: false,
+ allow_log_syntax: false,
+ allow_concat_idents: false,
+ allow_trace_macros: false,
old_orphan_check: false,
simd_ffi: false,
unmarked_api: false,
}
}
+pub const EXPLAIN_ASM: &'static str =
+ "inline assembly is not stable enough for use and is subject to change";
+
+pub const EXPLAIN_LOG_SYNTAX: &'static str =
+ "`log_syntax!` is not stable enough for use and is subject to change";
+
+pub const EXPLAIN_CONCAT_IDENTS: &'static str =
+ "`concat_idents` is not stable enough for use and is subject to change";
+
+pub const EXPLAIN_TRACE_MACROS: &'static str =
+ "`trace_macros` is not stable enough for use and is subject to change";
+
struct MacroVisitor<'a> {
context: &'a Context<'a>
}
let ast::MacInvocTT(ref path, _, _) = mac.node;
let id = path.segments.last().unwrap().identifier;
+ // Issue 22234: If you add a new case here, make sure to also
+ // add code to catch the macro during or after expansion.
+ //
+ // We still keep this MacroVisitor (rather than *solely*
+ // relying on catching cases during or after expansion) to
+ // catch uses of these macros within conditionally-compiled
+ // code, e.g. `#[cfg]`-guarded functions.
+
if id == token::str_to_ident("asm") {
- self.context.gate_feature("asm", path.span, "inline assembly is not \
- stable enough for use and is subject to change");
+ self.context.gate_feature("asm", path.span, EXPLAIN_ASM);
}
else if id == token::str_to_ident("log_syntax") {
- self.context.gate_feature("log_syntax", path.span, "`log_syntax!` is not \
- stable enough for use and is subject to change");
+ self.context.gate_feature("log_syntax", path.span, EXPLAIN_LOG_SYNTAX);
}
else if id == token::str_to_ident("trace_macros") {
- self.context.gate_feature("trace_macros", path.span, "`trace_macros` is not \
- stable enough for use and is subject to change");
+ self.context.gate_feature("trace_macros", path.span, EXPLAIN_TRACE_MACROS);
}
else if id == token::str_to_ident("concat_idents") {
- self.context.gate_feature("concat_idents", path.span, "`concat_idents` is not \
- stable enough for use and is subject to change");
+ self.context.gate_feature("concat_idents", path.span, EXPLAIN_CONCAT_IDENTS);
}
}
}
}
fn visit_item(&mut self, i: &ast::Item) {
- for attr in &i.attrs {
- if attr.name() == "thread_local" {
- self.gate_feature("thread_local", i.span,
- "`#[thread_local]` is an experimental feature, and does not \
- currently handle destructors. There is no corresponding \
- `#[task_local]` mapping to the task model");
- } else if attr.name() == "linkage" {
- self.gate_feature("linkage", i.span,
- "the `linkage` attribute is experimental \
- and not portable across platforms")
- } else if attr.name() == "rustc_on_unimplemented" {
- self.gate_feature("on_unimplemented", i.span,
- "the `#[rustc_on_unimplemented]` attribute \
- is an experimental feature")
- }
- }
match i.node {
ast::ItemExternCrate(_) => {
if attr::contains_name(&i.attrs[], "macro_reexport") {
}
fn visit_attribute(&mut self, attr: &ast::Attribute) {
- if attr.check_name("staged_api") {
- self.gate_feature("staged_api", attr.span,
- "staged_api is for use by rustc only");
- } else if attr.check_name("plugin") {
- self.gate_feature("plugin", attr.span,
- "compiler plugins are experimental \
- and possibly buggy");
- }
-
- if attr::contains_name(slice::ref_slice(attr), "lang") {
- self.gate_feature("lang_items",
- attr.span,
- "language items are subject to change");
- }
-
- if attr.check_name("no_std") {
- self.gate_feature("no_std", attr.span,
- "no_std is experimental");
+ let name = &*attr.name();
+ for &(n, ty) in KNOWN_ATTRIBUTES {
+ if n == name {
+ if let Gated(gate, desc) = ty {
+ self.gate_feature(gate, attr.span, desc);
+ }
+ return;
+ }
}
-
- if attr.check_name("unsafe_no_drop_flag") {
- self.gate_feature("unsafe_no_drop_flag", attr.span,
- "unsafe_no_drop_flag has unstable semantics \
- and may be removed in the future");
+ if name.starts_with("rustc_") {
+ self.gate_feature("rustc_attrs", attr.span,
+ "unless otherwise specified, attributes \
+ with the prefix `rustc_` \
+ are reserved for internal compiler diagnostics");
+ } else {
+ self.gate_feature("custom_attribute", attr.span,
+ format!("The attribute `{}` is currently \
+ unknown to the the compiler and \
+ may have meaning \
+ added to it in the future",
+ name).as_slice());
}
}
check(&mut cx, krate);
+ // FIXME (pnkfelix): Before adding the 99th entry below, change it
+ // to a single-pass (instead of N calls to `.has_feature`).
+
Features {
unboxed_closures: cx.has_feature("unboxed_closures"),
rustc_diagnostic_macros: cx.has_feature("rustc_diagnostic_macros"),
visible_private_types: cx.has_feature("visible_private_types"),
- quote: cx.has_feature("quote"),
+ allow_quote: cx.has_feature("quote"),
+ allow_asm: cx.has_feature("asm"),
+ allow_log_syntax: cx.has_feature("log_syntax"),
+ allow_concat_idents: cx.has_feature("concat_idents"),
+ allow_trace_macros: cx.has_feature("trace_macros"),
old_orphan_check: cx.has_feature("old_orphan_check"),
simd_ffi: cx.has_feature("simd_ffi"),
unmarked_api: cx.has_feature("unmarked_api"),
#![feature(env)]
#![feature(hash)]
#![feature(int_uint)]
-#![feature(io)]
+#![feature(old_io)]
#![feature(libc)]
-#![feature(path)]
+#![feature(old_path)]
#![feature(quote, unsafe_destructor)]
#![feature(rustc_private)]
#![feature(staged_api)]
pub fn strip_doc_comment_decoration(comment: &str) -> String {
/// remove whitespace-only lines from the start/end of lines
- fn vertical_trim(lines: Vec<String> ) -> Vec<String> {
+ fn vertical_trim(lines: Vec<String>) -> Vec<String> {
let mut i = 0;
let mut j = lines.len();
// first line of all-stars should be omitted
while j > i && lines[j - 1].trim().is_empty() {
j -= 1;
}
- return lines[i..j].iter().map(|x| (*x).clone()).collect();
+ lines[i..j].iter().cloned().collect()
}
/// remove a "[ \t]*\*" block from each line, if possible
fn maybe_append(mut lhs: Vec<Attribute>, rhs: Option<Vec<Attribute>>)
-> Vec<Attribute> {
- match rhs {
- Some(ref attrs) => lhs.extend(attrs.iter().map(|a| a.clone())),
- None => {}
+ if let Some(ref attrs) = rhs {
+ lhs.extend(attrs.iter().cloned())
}
lhs
}
debug!("commit_expr {:?}", e);
if let ExprPath(..) = e.node {
// might be unit-struct construction; check for recoverableinput error.
- let mut expected = edible.iter().map(|x| x.clone()).collect::<Vec<_>>();
+ let mut expected = edible.iter().cloned().collect::<Vec<_>>();
expected.push_all(inedible);
self.check_for_erroneous_unit_struct_expecting(&expected[]);
}
if self.last_token
.as_ref()
.map_or(false, |t| t.is_ident() || t.is_path()) {
- let mut expected = edible.iter().map(|x| x.clone()).collect::<Vec<_>>();
+ let mut expected = edible.iter().cloned().collect::<Vec<_>>();
expected.push_all(&inedible[]);
self.check_for_erroneous_unit_struct_expecting(
&expected[]);
(true, LitBinary(parse::binary_lit(i.as_str()))),
token::BinaryRaw(i, _) =>
(true,
- LitBinary(Rc::new(i.as_str().as_bytes().iter().map(|&x| x).collect()))),
+ LitBinary(Rc::new(i.as_str().as_bytes().iter().cloned().collect()))),
};
if suffix_illegal {
try!(self.word_nbsp("trait"));
try!(self.print_ident(item.ident));
try!(self.print_generics(generics));
- let bounds: Vec<_> = bounds.iter().map(|b| b.clone()).collect();
let mut real_bounds = Vec::with_capacity(bounds.len());
- for b in bounds {
- if let TraitTyParamBound(ref ptr, ast::TraitBoundModifier::Maybe) = b {
+ for b in bounds.iter() {
+ if let TraitTyParamBound(ref ptr, ast::TraitBoundModifier::Maybe) = *b {
try!(space(&mut self.s));
try!(self.word_space("for ?"));
try!(self.print_trait_ref(&ptr.trait_ref));
} else {
- real_bounds.push(b);
+ real_bounds.push(b.clone());
}
}
try!(self.print_bounds(":", &real_bounds[]));
ast::LitStr(ref st, style) => self.print_string(&st, style),
ast::LitByte(byte) => {
let mut res = String::from_str("b'");
- ascii::escape_default(byte, |c| res.push(c as char));
+ res.extend(ascii::escape_default(byte).map(|c| c as char));
res.push('\'');
word(&mut self.s, &res[])
}
ast::LitChar(ch) => {
let mut res = String::from_str("'");
- for c in ch.escape_default() {
- res.push(c);
- }
+ res.extend(ch.escape_default());
res.push('\'');
word(&mut self.s, &res[])
}
ast::LitBinary(ref v) => {
let mut escaped: String = String::new();
for &ch in &**v {
- ascii::escape_default(ch as u8,
- |ch| escaped.push(ch as char));
+ escaped.extend(ascii::escape_default(ch as u8)
+ .map(|c| c as char));
}
word(&mut self.s, &format!("b\"{}\"", escaped)[])
}
#![feature(box_syntax)]
#![feature(collections)]
#![feature(int_uint)]
-#![feature(io)]
-#![feature(path)]
+#![feature(old_io)]
+#![feature(old_path)]
#![feature(rustc_private)]
#![feature(staged_api)]
-#![feature(std_misc)]
#![feature(unicode)]
+#![feature(std_misc)]
#![feature(env)]
#![cfg_attr(windows, feature(libc))]
ti: Box<TermInfo>
}
-impl<T: Writer+Send> Terminal<T> for TerminfoTerminal<T> {
+impl<T: Writer+Send+'static> Terminal<T> for TerminfoTerminal<T> {
fn fg(&mut self, color: color::Color) -> IoResult<bool> {
let color = self.dim_if_necessary(color);
if self.num_colors > color {
fn get_mut<'a>(&'a mut self) -> &'a mut T { &mut self.out }
}
-impl<T: Writer+Send> UnwrappableTerminal<T> for TerminfoTerminal<T> {
+impl<T: Writer+Send+'static> UnwrappableTerminal<T> for TerminfoTerminal<T> {
fn unwrap(self) -> T { self.out }
}
-impl<T: Writer+Send> TerminfoTerminal<T> {
+impl<T: Writer+Send+'static> TerminfoTerminal<T> {
/// Returns `None` whenever the terminal cannot be created for some
/// reason.
pub fn new(out: T) -> Option<Box<Terminal<T>+Send+'static>> {
self.out.flush()
}
}
-
Result<Vec<u8>, String>
{
let mut u8v: Vec<_> = fmt.bytes().collect();
- u8v.extend(cap.as_bytes().iter().map(|&b| b));
+ u8v.extend(cap.bytes());
expand(&u8v, params, vars)
}
color | (bits & 0x8) // copy the hi-intensity bit
}
-impl<T: Writer+Send> WinConsole<T> {
+impl<T: Writer+Send+'static> WinConsole<T> {
fn apply(&mut self) {
let _unused = self.buf.flush();
let mut accum: libc::WORD = 0;
}
}
-impl<T: Writer+Send> Terminal<T> for WinConsole<T> {
+impl<T: Writer+Send+'static> Terminal<T> for WinConsole<T> {
fn fg(&mut self, color: color::Color) -> IoResult<bool> {
self.foreground = color;
self.apply();
fn get_mut<'a>(&'a mut self) -> &'a mut T { &mut self.buf }
}
-impl<T: Writer+Send> UnwrappableTerminal<T> for WinConsole<T> {
+impl<T: Writer+Send+'static> UnwrappableTerminal<T> for WinConsole<T> {
fn unwrap(self) -> T { self.buf }
}
#![feature(env)]
#![feature(hash)]
#![feature(int_uint)]
-#![feature(io)]
-#![feature(path)]
+#![feature(old_io)]
+#![feature(old_path)]
#![feature(rustc_private)]
#![feature(staged_api)]
#![feature(std_misc)]
use std::num::{Float, Int};
use std::env;
use std::sync::mpsc::{channel, Sender};
-use std::thread::{self, Thread};
+use std::thread;
use std::thunk::{Thunk, Invoke};
use std::time::Duration;
StaticTestFn(fn()),
StaticBenchFn(fn(&mut Bencher)),
StaticMetricFn(fn(&mut MetricMap)),
- DynTestFn(Thunk),
+ DynTestFn(Thunk<'static>),
DynMetricFn(Box<for<'a> Invoke<&'a mut MetricMap>+'static>),
DynBenchFn(Box<TDynBenchFn+'static>)
}
fn run_test_inner(desc: TestDesc,
monitor_ch: Sender<MonitorMsg>,
nocapture: bool,
- testfn: Thunk) {
- Thread::spawn(move || {
+ testfn: Thunk<'static>) {
+ thread::spawn(move || {
let (tx, rx) = channel();
let mut reader = ChanReader::new(rx);
let stdout = ChanWriter::new(tx.clone());
cfg = cfg.stderr(box stderr as Box<Writer + Send>);
}
- let result_guard = cfg.scoped(move || { testfn.invoke(()) });
+ let result_guard = cfg.spawn(move || { testfn.invoke(()) }).unwrap();
let stdout = reader.read_to_end().unwrap().into_iter().collect();
let test_result = calc_result(&desc, result_guard.join());
monitor_ch.send((desc.clone(), test_result, stdout)).unwrap();
pub use u_str::{utf8_char_width, is_utf16, Utf16Items, Utf16Item};
pub use u_str::{utf16_items, Utf16Encoder};
}
-
-// NOTE: remove after next snapshot
-// this lets us use #[derive(..)]
-#[cfg(stage0)]
-mod std {
- pub use core::clone;
- pub use core::cmp;
- pub use core::fmt;
- pub use core::marker;
- // for-loops
- pub use core::iter;
- pub use core::option;
-}
//! Implementation of the `build` subcommand, used to compile a book.
use std::os;
+use std::env;
use std::old_io;
use std::old_io::{fs, File, BufferedWriter, TempDir, IoResult};
let out_path = tgt.join(item.path.dirname());
let src;
- if os::args().len() < 3 {
+ if env::args().len() < 3 {
src = os::getcwd().unwrap().clone();
} else {
- src = Path::new(os::args()[2].clone());
+ src = Path::new(env::args().nth(2).unwrap().clone());
}
// preprocess the markdown, rerouting markdown references to html references
let markdown_data = try!(File::open(&src.join(&item.path)).read_to_string());
let src;
let tgt;
- if os::args().len() < 3 {
+ if env::args().len() < 3 {
src = cwd.clone();
} else {
- src = Path::new(os::args()[2].clone());
+ src = Path::new(env::args().nth(2).unwrap().clone());
}
- if os::args().len() < 4 {
+ if env::args().len() < 4 {
tgt = cwd.join("_book");
} else {
- tgt = Path::new(os::args()[3].clone());
+ tgt = Path::new(env::args().nth(3).unwrap().clone());
}
try!(fs::mkdir(&tgt, old_io::USER_DIR));
#![feature(box_syntax)]
#![feature(collections)]
#![feature(core)]
-#![feature(io)]
+#![feature(old_io)]
#![feature(os)]
-#![feature(path)]
+#![feature(env)]
+#![feature(old_path)]
#![feature(rustdoc)]
extern crate rustdoc;
-use std::os;
+use std::env;
use subcommand::Subcommand;
use term::Term;
#[cfg(not(test))] // thanks #12327
fn main() {
let mut term = Term::new();
- let cmd = os::args();
+ let cmd: Vec<_> = env::args().collect();
if cmd.len() <= 1 {
help::usage()
//! An abstraction of the terminal. Eventually, provide color and
//! verbosity support. For now, just a wrapper around stdout/stderr.
-use std::os;
+use std::env;
use std::old_io::stdio;
pub struct Term {
pub fn err(&mut self, msg: &str) {
// swallow any errors
let _ = self.err.write_line(msg);
- os::set_exit_status(101);
+ env::set_exit_status(101);
}
}
# If this file is modified, then llvm will be forcibly cleaned and then rebuilt.
# The actual contents of this file do not matter, but to trigger a change on the
# build bots then the contents should be changed so git updates the mtime.
-2015-02-12
+2015-02-13
+S 2015-02-17 f1bb6c2
+ freebsd-x86_64 59f3a2c6350c170804fb65838e1b504eeab89105
+ linux-i386 191ed5ec4f17e32d36abeade55a1c6085e51245c
+ linux-x86_64 acec86045632f4f3f085c072ba696f889906dffe
+ macos-i386 9d9e622584bfa318f32bcb5b9ce6a365febff595
+ macos-x86_64 e96c1e9860b186507cc75c186d1b96d44df12292
+ winnt-i386 3f43e0e71311636f9143ad6f2ee7a514e9fa3f8e
+ winnt-x86_64 26ef3d9098ea346e5ff8945d5b224bb10c24341d
+
S 2015-02-04 ac134f7
freebsd-x86_64 483e37a02a7ebc12a872e3146145e342ba4a5c04
linux-i386 8af64e5df839cc945399484380a8b2ebe05a6751
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use std::thread::Thread;
+use std::thread;
use std::sync::mpsc::{Receiver, channel};
-pub fn foo<T:Send + Clone>(x: T) -> Receiver<T> {
+pub fn foo<T:'static + Send + Clone>(x: T) -> Receiver<T> {
let (tx, rx) = channel();
- Thread::spawn(move|| {
+ thread::spawn(move|| {
tx.send(x.clone());
});
rx
pub fn method_stable(&self) {}
#[stable(feature = "rust1", since = "1.0.0", reason = "text")]
pub fn method_stable_text(&self) {}
-
- #[locked]
- pub fn method_locked(&self) {}
- #[locked="text"]
- pub fn method_locked_text(&self) {}
-
- #[frozen]
- pub fn method_frozen(&self) {}
- #[frozen="text"]
- pub fn method_frozen_text(&self) {}
}
#[stable(feature = "test_feature", since = "1.0.0")]
fn trait_stable(&self) {}
#[stable(feature = "rust1", since = "1.0.0", reason = "text")]
fn trait_stable_text(&self) {}
-
- #[locked]
- fn trait_locked(&self) {}
- #[locked="text"]
- fn trait_locked_text(&self) {}
-
- #[frozen]
- fn trait_frozen(&self) {}
- #[frozen="text"]
- fn trait_frozen_text(&self) {}
}
impl Trait for MethodTester {}
#![feature(unboxed_closures)]
use std::collections::{BTreeMap, HashMap, HashSet};
-use std::os;
+use std::env;
use std::rand::{Rng, IsaacRng, SeedableRng};
use std::time::Duration;
}
trait MutableMap {
- fn insert(&mut self, k: uint, v: uint);
- fn remove(&mut self, k: &uint) -> bool;
- fn find(&self, k: &uint) -> Option<&uint>;
+ fn insert(&mut self, k: usize, v: usize);
+ fn remove(&mut self, k: &usize) -> bool;
+ fn find(&self, k: &usize) -> Option<&usize>;
}
-impl MutableMap for BTreeMap<uint, uint> {
- fn insert(&mut self, k: uint, v: uint) { self.insert(k, v); }
- fn remove(&mut self, k: &uint) -> bool { self.remove(k).is_some() }
- fn find(&self, k: &uint) -> Option<&uint> { self.get(k) }
+impl MutableMap for BTreeMap<usize, usize> {
+ fn insert(&mut self, k: usize, v: usize) { self.insert(k, v); }
+ fn remove(&mut self, k: &usize) -> bool { self.remove(k).is_some() }
+ fn find(&self, k: &usize) -> Option<&usize> { self.get(k) }
}
-impl MutableMap for HashMap<uint, uint> {
- fn insert(&mut self, k: uint, v: uint) { self.insert(k, v); }
- fn remove(&mut self, k: &uint) -> bool { self.remove(k).is_some() }
- fn find(&self, k: &uint) -> Option<&uint> { self.get(k) }
+impl MutableMap for HashMap<usize, usize> {
+ fn insert(&mut self, k: usize, v: usize) { self.insert(k, v); }
+ fn remove(&mut self, k: &usize) -> bool { self.remove(k).is_some() }
+ fn find(&self, k: &usize) -> Option<&usize> { self.get(k) }
}
-fn ascending<M: MutableMap>(map: &mut M, n_keys: uint) {
+fn ascending<M: MutableMap>(map: &mut M, n_keys: usize) {
println!(" Ascending integers:");
timed("insert", || {
- for i in 0u..n_keys {
+ for i in 0..n_keys {
map.insert(i, i + 1);
}
});
timed("search", || {
- for i in 0u..n_keys {
+ for i in 0..n_keys {
assert_eq!(map.find(&i).unwrap(), &(i + 1));
}
});
});
}
-fn descending<M: MutableMap>(map: &mut M, n_keys: uint) {
+fn descending<M: MutableMap>(map: &mut M, n_keys: usize) {
println!(" Descending integers:");
timed("insert", || {
});
}
-fn vector<M: MutableMap>(map: &mut M, n_keys: uint, dist: &[uint]) {
+fn vector<M: MutableMap>(map: &mut M, n_keys: usize, dist: &[usize]) {
timed("insert", || {
- for i in 0u..n_keys {
+ for i in 0..n_keys {
map.insert(dist[i], i + 1);
}
});
timed("search", || {
- for i in 0u..n_keys {
+ for i in 0..n_keys {
assert_eq!(map.find(&dist[i]).unwrap(), &(i + 1));
}
});
timed("remove", || {
- for i in 0u..n_keys {
+ for i in 0..n_keys {
assert!(map.remove(&dist[i]));
}
});
}
fn main() {
- let args = os::args();
- let args = args;
+ let mut args = env::args();
let n_keys = {
if args.len() == 2 {
- args[1].parse::<uint>().unwrap()
+ args.nth(1).unwrap().parse::<usize>().unwrap()
} else {
1000000
}
println!("{}", "\nBTreeMap:");
{
- let mut map: BTreeMap<uint,uint> = BTreeMap::new();
+ let mut map: BTreeMap<usize,usize> = BTreeMap::new();
ascending(&mut map, n_keys);
}
{
- let mut map: BTreeMap<uint,uint> = BTreeMap::new();
+ let mut map: BTreeMap<usize,usize> = BTreeMap::new();
descending(&mut map, n_keys);
}
{
println!(" Random integers:");
- let mut map: BTreeMap<uint,uint> = BTreeMap::new();
+ let mut map: BTreeMap<usize,usize> = BTreeMap::new();
vector(&mut map, n_keys, &rand);
}
println!("{}", "\nHashMap:");
{
- let mut map: HashMap<uint,uint> = HashMap::new();
+ let mut map: HashMap<usize,usize> = HashMap::new();
ascending(&mut map, n_keys);
}
{
- let mut map: HashMap<uint,uint> = HashMap::new();
+ let mut map: HashMap<usize,usize> = HashMap::new();
descending(&mut map, n_keys);
}
{
println!(" Random integers:");
- let mut map: HashMap<uint,uint> = HashMap::new();
+ let mut map: HashMap<usize,usize> = HashMap::new();
vector(&mut map, n_keys, &rand);
}
}
use std::collections::HashSet;
use std::collections::hash_map::Hasher;
use std::hash::Hash;
-use std::os;
+use std::env;
use std::time::Duration;
struct Results {
fn remove(&mut self, k: &T) -> bool { self.remove(k) }
fn contains(&self, k: &T) -> bool { self.contains(k) }
}
-impl MutableSet<uint> for BitvSet {
- fn insert(&mut self, k: uint) { self.insert(k); }
- fn remove(&mut self, k: &uint) -> bool { self.remove(k) }
- fn contains(&self, k: &uint) -> bool { self.contains(k) }
+impl MutableSet<usize> for BitvSet {
+ fn insert(&mut self, k: usize) { self.insert(k); }
+ fn remove(&mut self, k: &usize) -> bool { self.remove(k) }
+ fn contains(&self, k: &usize) -> bool { self.contains(k) }
}
impl Results {
- pub fn bench_int<T:MutableSet<uint>,
+ pub fn bench_int<T:MutableSet<usize>,
R:rand::Rng,
F:FnMut() -> T>(
&mut self,
rng: &mut R,
- num_keys: uint,
- rand_cap: uint,
+ num_keys: usize,
+ rand_cap: usize,
mut f: F) {
{
let mut set = f();
timed(&mut self.sequential_ints, || {
- for i in 0u..num_keys {
+ for i in 0..num_keys {
set.insert(i);
}
- for i in 0u..num_keys {
+ for i in 0..num_keys {
assert!(set.contains(&i));
}
})
let mut set = f();
timed(&mut self.random_ints, || {
for _ in 0..num_keys {
- set.insert(rng.gen::<uint>() % rand_cap);
+ set.insert(rng.gen::<usize>() % rand_cap);
}
})
}
{
let mut set = f();
- for i in 0u..num_keys {
+ for i in 0..num_keys {
set.insert(i);
}
timed(&mut self.delete_ints, || {
- for i in 0u..num_keys {
+ for i in 0..num_keys {
assert!(set.remove(&i));
}
})
F:FnMut() -> T>(
&mut self,
rng: &mut R,
- num_keys: uint,
+ num_keys: usize,
mut f: F) {
{
let mut set = f();
timed(&mut self.sequential_strings, || {
- for i in 0u..num_keys {
+ for i in 0..num_keys {
set.insert(i.to_string());
}
- for i in 0u..num_keys {
+ for i in 0..num_keys {
assert!(set.contains(&i.to_string()));
}
})
let mut set = f();
timed(&mut self.random_strings, || {
for _ in 0..num_keys {
- let s = rng.gen::<uint>().to_string();
+ let s = rng.gen::<usize>().to_string();
set.insert(s);
}
})
{
let mut set = f();
- for i in 0u..num_keys {
+ for i in 0..num_keys {
set.insert(i.to_string());
}
timed(&mut self.delete_strings, || {
- for i in 0u..num_keys {
+ for i in 0..num_keys {
assert!(set.remove(&i.to_string()));
}
})
}
fn main() {
- let args = os::args();
- let args = args;
+ let mut args = env::args();
let num_keys = {
if args.len() == 2 {
- args[1].parse::<uint>().unwrap()
+ args.nth(1).unwrap().parse::<usize>().unwrap()
} else {
100 // woefully inadequate for any real measurement
}
let mut rng: rand::IsaacRng = rand::SeedableRng::from_seed(seed);
let mut results = empty_results();
results.bench_int(&mut rng, num_keys, max, || {
- let s: HashSet<uint> = HashSet::new();
+ let s: HashSet<usize> = HashSet::new();
s
});
results.bench_str(&mut rng, num_keys, || {
let mut rng: rand::IsaacRng = rand::SeedableRng::from_seed(seed);
let mut results = empty_results();
results.bench_int(&mut rng, num_keys, max, || {
- let s: BTreeSet<uint> = BTreeSet::new();
+ let s: BTreeSet<usize> = BTreeSet::new();
s
});
results.bench_str(&mut rng, num_keys, || {
use std::old_io::File;
use std::iter::repeat;
use std::mem::swap;
-use std::os;
use std::env;
use std::rand::Rng;
use std::rand;
use std::vec;
fn main() {
- let argv = os::args();
- let _tests = &argv[1..argv.len()];
+ let argv: Vec<String> = env::args().collect();
macro_rules! bench {
($id:ident) =>
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use std::os;
use std::env;
fn main() {
- let args = os::args();
+ let args = env::args();
let args = if env::var_os("RUST_BENCH").is_some() {
vec!("".to_string(), "10000000".to_string())
} else if args.len() <= 1u {
vec!("".to_string(), "100000".to_string())
} else {
- args.into_iter().collect()
+ args.collect()
};
let n = args[1].parse().unwrap();
// version.
use std::sync::mpsc::{channel, Sender, Receiver};
-use std::os;
use std::env;
-use std::thread::Thread;
+use std::thread;
use std::time::Duration;
fn move_out<T>(_x: T) {}
let mut worker_results = Vec::new();
for _ in 0u..workers {
let to_child = to_child.clone();
- worker_results.push(Thread::scoped(move|| {
+ worker_results.push(thread::spawn(move|| {
for _ in 0u..size / workers {
//println!("worker {}: sending {} bytes", i, num_bytes);
to_child.send(request::bytes(num_bytes)).unwrap();
//println!("worker {} exiting", i);
}));
}
- Thread::spawn(move|| {
+ thread::spawn(move|| {
server(&from_parent, &to_parent);
});
}
fn main() {
- let args = os::args();
+ let args = env::args();
let args = if env::var_os("RUST_BENCH").is_some() {
vec!("".to_string(), "1000000".to_string(), "10000".to_string())
- } else if args.len() <= 1u {
+ } else if args.len() <= 1 {
vec!("".to_string(), "10000".to_string(), "4".to_string())
} else {
- args.into_iter().map(|x| x.to_string()).collect()
+ args.map(|x| x.to_string()).collect()
};
println!("{:?}", args);
// I *think* it's the same, more or less.
use std::sync::mpsc::{channel, Sender, Receiver};
-use std::os;
use std::env;
-use std::thread::Thread;
+use std::thread;
use std::time::Duration;
enum request {
let mut worker_results = Vec::new();
let from_parent = if workers == 1 {
let (to_child, from_parent) = channel();
- worker_results.push(Thread::scoped(move|| {
+ worker_results.push(thread::spawn(move|| {
for _ in 0u..size / workers {
//println!("worker {}: sending {} bytes", i, num_bytes);
to_child.send(request::bytes(num_bytes));
let (to_child, from_parent) = channel();
for _ in 0u..workers {
let to_child = to_child.clone();
- worker_results.push(Thread::scoped(move|| {
+ worker_results.push(thread::spawn(move|| {
for _ in 0u..size / workers {
//println!("worker {}: sending {} bytes", i, num_bytes);
to_child.send(request::bytes(num_bytes));
}
from_parent
};
- Thread::spawn(move|| {
+ thread::spawn(move|| {
server(&from_parent, &to_parent);
});
}
fn main() {
- let args = os::args();
+ let args = env::args();
let args = if env::var_os("RUST_BENCH").is_some() {
vec!("".to_string(), "1000000".to_string(), "8".to_string())
- } else if args.len() <= 1u {
+ } else if args.len() <= 1 {
vec!("".to_string(), "10000".to_string(), "4".to_string())
} else {
- args.clone().into_iter().map(|x| x.to_string()).collect()
+ args.map(|x| x.to_string()).collect()
};
println!("{:?}", args);
// no-pretty-expanded FIXME #15189
// ignore-lexer-test FIXME #15679
-use std::os;
use std::env;
use std::sync::{Arc, Future, Mutex, Condvar};
use std::time::Duration;
}
fn main() {
- let args = os::args();
+ let args = env::args();
let args = if env::var_os("RUST_BENCH").is_some() {
vec!("".to_string(), "100".to_string(), "10000".to_string())
- } else if args.len() <= 1u {
+ } else if args.len() <= 1 {
vec!("".to_string(), "10".to_string(), "100".to_string())
} else {
- args.clone().into_iter().collect()
+ args.collect()
};
let num_tasks = args[1].parse::<uint>().unwrap();
// except according to those terms.
use std::sync::mpsc::channel;
-use std::os;
-use std::thread::Thread;
+use std::env;
+use std::thread;
// This is a simple bench that creates M pairs of tasks. These
// tasks ping-pong back and forth over a pair of streams. This is a
// canonical message-passing benchmark as it heavily strains message
// passing and almost nothing else.
-fn ping_pong_bench(n: uint, m: uint) {
+fn ping_pong_bench(n: usize, m: usize) {
// Create pairs of tasks that pingpong back and forth.
- fn run_pair(n: uint) {
+ fn run_pair(n: usize) {
// Create a channel: A->B
let (atx, arx) = channel();
// Create a channel: B->A
let (btx, brx) = channel();
- let guard_a = Thread::scoped(move|| {
+ let guard_a = thread::spawn(move|| {
let (tx, rx) = (atx, brx);
for _ in 0..n {
tx.send(()).unwrap();
}
});
- let guard_b = Thread::scoped(move|| {
+ let guard_b = thread::spawn(move|| {
let (tx, rx) = (btx, arx);
for _ in 0..n {
rx.recv().unwrap();
fn main() {
-
- let args = os::args();
- let args = args;
- let n = if args.len() == 3 {
- args[1].parse::<uint>().unwrap()
- } else {
- 10000
- };
-
- let m = if args.len() == 3 {
- args[2].parse::<uint>().unwrap()
+ let mut args = env::args();
+ let (n, m) = if args.len() == 3 {
+ let n = args.nth(1).unwrap().parse::<usize>().unwrap();
+ let m = args.next().unwrap().parse::<usize>().unwrap();
+ (n, m)
} else {
- 4
+ (10000, 4)
};
ping_pong_bench(n, m);
// except according to those terms.
use std::sync::mpsc::channel;
-use std::os;
-use std::thread::Thread;
+use std::env;
+use std::thread;
// A simple implementation of parfib. One subtree is found in a new
// task and communicated over a oneshot pipe, the other is found
// locally. There is no sequential-mode threshold.
-fn parfib(n: uint) -> uint {
+fn parfib(n: u64) -> u64 {
if n == 0 || n == 1 {
return 1;
}
let (tx, rx) = channel();
- Thread::spawn(move|| {
+ thread::spawn(move|| {
tx.send(parfib(n-1)).unwrap();
});
let m2 = parfib(n-2);
}
fn main() {
-
- let args = os::args();
- let args = args;
+ let mut args = env::args();
let n = if args.len() == 2 {
- args[1].parse::<uint>().unwrap()
+ args.nth(1).unwrap().parse::<u64>().unwrap()
} else {
10
};
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use std::os;
use std::env;
-fn ack(m: int, n: int) -> int {
+fn ack(m: i64, n: i64) -> i64 {
if m == 0 {
return n + 1
} else {
}
fn main() {
- let args = os::args();
+ let mut args = env::args();
let args = if env::var_os("RUST_BENCH").is_some() {
vec!("".to_string(), "12".to_string())
- } else if args.len() <= 1u {
+ } else if args.len() <= 1 {
vec!("".to_string(), "8".to_string())
} else {
- args.into_iter().collect()
+ args.collect()
};
let n = args[1].parse().unwrap();
println!("Ack(3,{}): {}\n", n, ack(3, n));
extern crate arena;
use std::iter::range_step;
-use std::thread::{Thread, JoinGuard};
+use std::thread;
use arena::TypedArena;
struct Tree<'a> {
}
fn main() {
- let args = std::os::args();
- let args = args;
+ let mut args = std::env::args();
let n = if std::env::var_os("RUST_BENCH").is_some() {
17
- } else if args.len() <= 1u {
+ } else if args.len() <= 1 {
8
} else {
- args[1].parse().unwrap()
+ args.nth(1).unwrap().parse().unwrap()
};
let min_depth = 4;
let max_depth = if min_depth + 2 > n {min_depth + 2} else {n};
let messages = range_step(min_depth, max_depth + 1, 2).map(|depth| {
use std::num::Int;
let iterations = 2.pow((max_depth - depth + min_depth) as usize);
- Thread::scoped(move || inner(depth, iterations))
+ thread::scoped(move || inner(depth, iterations))
}).collect::<Vec<_>>();
for message in messages {
- println!("{}", message.join().ok().unwrap());
+ println!("{}", message.join());
}
println!("long lived tree of depth {}\t check: {}",
use self::Color::{Red, Yellow, Blue};
use std::sync::mpsc::{channel, Sender, Receiver};
use std::fmt;
-use std::thread::Thread;
+use std::thread;
fn print_complements() {
let all = [Blue, Red, Yellow];
let to_rendezvous = to_rendezvous.clone();
let to_rendezvous_log = to_rendezvous_log.clone();
let (to_creature, from_rendezvous) = channel();
- Thread::spawn(move|| {
+ thread::spawn(move|| {
creature(ii,
col,
from_rendezvous,
let nn = if std::env::var_os("RUST_BENCH").is_some() {
200000
} else {
- std::os::args()
- .get(1)
+ std::env::args()
+ .nth(1)
.and_then(|arg| arg.parse().ok())
- .unwrap_or(600u)
+ .unwrap_or(600us)
};
print_complements();
// OF THE POSSIBILITY OF SUCH DAMAGE.
use std::{cmp, iter, mem};
-use std::thread::Thread;
+use std::thread;
fn rotate(x: &mut [i32]) {
let mut prev = x[0];
for (_, j) in (0..N).zip(iter::count(0, k)) {
let max = cmp::min(j+k, perm.max());
- futures.push(Thread::scoped(move|| {
+ futures.push(thread::scoped(move|| {
work(perm, j as uint, max as uint)
}))
}
let mut checksum = 0;
let mut maxflips = 0;
for fut in futures {
- let (cs, mf) = fut.join().ok().unwrap();
+ let (cs, mf) = fut.join();
checksum += cs;
maxflips = cmp::max(maxflips, mf);
}
}
fn main() {
- let n = std::os::args()
- .get(1)
+ let n = std::env::args()
+ .nth(1)
.and_then(|arg| arg.parse().ok())
.unwrap_or(2i32);
use std::cmp::min;
use std::old_io::{stdout, IoResult};
use std::iter::repeat;
-use std::os;
+use std::env;
use std::slice::bytes::copy_memory;
-const LINE_LEN: uint = 60;
-const LOOKUP_SIZE: uint = 4 * 1024;
+const LINE_LEN: usize = 60;
+const LOOKUP_SIZE: usize = 4 * 1024;
const LOOKUP_SCALE: f32 = (LOOKUP_SIZE - 1) as f32;
// Random number generator constants
RepeatFasta { alu: alu, out: w }
}
- fn make(&mut self, n: uint) -> IoResult<()> {
+ fn make(&mut self, n: usize) -> IoResult<()> {
let alu_len = self.alu.len();
let mut buf = repeat(0u8).take(alu_len + LINE_LEN).collect::<Vec<_>>();
let alu: &[u8] = self.alu.as_bytes();
0
}
- fn make(&mut self, n: uint) -> IoResult<()> {
+ fn make(&mut self, n: usize) -> IoResult<()> {
let lines = n / LINE_LEN;
let chars_left = n % LINE_LEN;
let mut buf = [0;LINE_LEN + 1];
for _ in 0..lines {
- for i in 0u..LINE_LEN {
+ for i in 0..LINE_LEN {
buf[i] = self.nextc();
}
buf[LINE_LEN] = '\n' as u8;
try!(self.out.write(&buf));
}
- for i in 0u..chars_left {
+ for i in 0..chars_left {
buf[i] = self.nextc();
}
self.out.write(&buf[..chars_left])
}
fn main() {
- let args = os::args();
- let args = args;
+ let mut args = env::args();
let n = if args.len() > 1 {
- args[1].parse::<uint>().unwrap()
+ args.nth(1).unwrap().parse::<usize>().unwrap()
} else {
5
};
use std::old_io::{BufferedWriter, File};
use std::old_io;
use std::num::Float;
-use std::os;
use std::env;
-const LINE_LENGTH: uint = 60;
+const LINE_LENGTH: usize = 60;
const IM: u32 = 139968;
struct MyRandom {
}
fn make_fasta<W: Writer, I: Iterator<Item=u8>>(
- wr: &mut W, header: &str, mut it: I, mut n: uint)
+ wr: &mut W, header: &str, mut it: I, mut n: usize)
-> std::old_io::IoResult<()>
{
try!(wr.write(header.as_bytes()));
}
fn run<W: Writer>(writer: &mut W) -> std::old_io::IoResult<()> {
- let args = os::args();
- let args = args;
+ let mut args = env::args();
let n = if env::var_os("RUST_BENCH").is_some() {
25000000
- } else if args.len() <= 1u {
+ } else if args.len() <= 1 {
1000
} else {
- args[1].parse().unwrap()
+ args.nth(1).unwrap().parse().unwrap()
};
let rng = &mut MyRandom::new();
('t', 0.3015094502008)];
try!(make_fasta(writer, ">ONE Homo sapiens alu\n",
- alu.as_bytes().iter().cycle().map(|c| *c), n * 2));
+ alu.as_bytes().iter().cycle().cloned(), n * 2));
try!(make_fasta(writer, ">TWO IUB ambiguity codes\n",
AAGen::new(rng, iub), n * 3));
try!(make_fasta(writer, ">THREE Homo sapiens frequency\n",
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use std::os;
use std::env;
-fn fib(n: int) -> int {
+fn fib(n: i64) -> i64 {
if n < 2 {
return 1;
} else {
}
fn main() {
- let args = os::args();
+ let args = env::args();
let args = if env::var_os("RUST_BENCH").is_some() {
vec!("".to_string(), "40".to_string())
- } else if args.len() <= 1u {
+ } else if args.len() <= 1 {
vec!("".to_string(), "30".to_string())
} else {
- args.into_iter().collect()
+ args.collect()
};
let n = args[1].parse().unwrap();
println!("{}\n", fib(n));
use std::os;
use std::env;
use std::sync::mpsc::{channel, Sender, Receiver};
-use std::thread::Thread;
+use std::thread;
fn f64_cmp(x: f64, y: f64) -> Ordering {
// arbitrarily decide that NaNs are larger than everything.
let (to_child, from_parent) = channel();
- Thread::spawn(move|| {
+ thread::spawn(move|| {
make_sequence_processor(sz, &from_parent, &to_parent_);
});
use std::ascii::OwnedAsciiExt;
use std::slice;
use std::sync::Arc;
-use std::thread::Thread;
+use std::thread;
static TABLE: [u8;4] = [ 'A' as u8, 'C' as u8, 'G' as u8, 'T' as u8 ];
static TABLE_SIZE: uint = 2 << 16;
let nb_freqs: Vec<_> = (1u..3).map(|i| {
let input = input.clone();
- (i, Thread::scoped(move|| generate_frequencies(&input, i)))
+ (i, thread::scoped(move|| generate_frequencies(&input, i)))
}).collect();
let occ_freqs: Vec<_> = OCCURRENCES.iter().map(|&occ| {
let input = input.clone();
- Thread::scoped(move|| generate_frequencies(&input, occ.len()))
+ thread::scoped(move|| generate_frequencies(&input, occ.len()))
}).collect();
for (i, freq) in nb_freqs {
- print_frequencies(&freq.join().ok().unwrap(), i);
+ print_frequencies(&freq.join(), i);
}
for (&occ, freq) in OCCURRENCES.iter().zip(occ_freqs.into_iter()) {
- print_occurrences(&mut freq.join().ok().unwrap(), occ);
+ print_occurrences(&mut freq.join(), occ);
}
}
// ignore-pretty very bad with line comments
use std::old_io;
-use std::os;
+use std::env;
use std::simd::f64x2;
use std::sync::Arc;
-use std::thread::Thread;
+use std::thread;
const ITER: usize = 50;
const LIMIT: f64 = 2.0;
let mut precalc_i = Vec::with_capacity(h);
let precalc_futures = (0..WORKERS).map(|i| {
- Thread::scoped(move|| {
+ thread::scoped(move|| {
let mut rs = Vec::with_capacity(w / WORKERS);
let mut is = Vec::with_capacity(w / WORKERS);
}).collect::<Vec<_>>();
for res in precalc_futures {
- let (rs, is) = res.join().ok().unwrap();
+ let (rs, is) = res.join();
precalc_r.extend(rs.into_iter());
precalc_i.extend(is.into_iter());
}
let vec_init_r = arc_init_r.clone();
let vec_init_i = arc_init_i.clone();
- Thread::scoped(move|| {
+ thread::scoped(move|| {
let mut res: Vec<u8> = Vec::with_capacity((chunk_size * w) / 8);
let init_r_slice = vec_init_r;
try!(writeln!(&mut out as &mut Writer, "P4\n{} {}", w, h));
for res in data {
- try!(out.write(&res.join().ok().unwrap()));
+ try!(out.write(&res.join()));
}
out.flush()
}
}
fn main() {
- let args = os::args();
+ let mut args = env::args();
let res = if args.len() < 2 {
println!("Test mode: do not dump the image because it's not utf8, \
which interferes with the test runner.");
mandelbrot(1000, old_io::util::NullWriter)
} else {
- mandelbrot(args[1].parse().unwrap(), old_io::stdout())
+ mandelbrot(args.nth(1).unwrap().parse().unwrap(), old_io::stdout())
};
res.unwrap();
}
use std::iter::repeat;
use std::sync::Arc;
use std::sync::mpsc::channel;
-use std::thread::Thread;
+use std::thread;
//
// Utilities.
for i in 0..masks.len() {
for j in 0..(*masks)[i].len() {
masks[i][j] =
- (*masks)[i][j].iter().map(|&m| m)
+ (*masks)[i][j].iter().cloned()
.filter(|&m| !is_board_unfeasible(m, masks))
.collect();
}
// reverse order, i.e. the board rotated by half a turn.
data.nb += 2;
let sol1 = to_vec(raw_sol);
- let sol2: Vec<u8> = sol1.iter().rev().map(|x| *x).collect();
+ let sol2: Vec<u8> = sol1.iter().rev().cloned().collect();
if data.nb == 2 {
data.min = sol1.clone();
let masks = masks.clone();
let tx = tx.clone();
let m = *m;
- Thread::spawn(move|| {
+ thread::spawn(move|| {
let mut data = Data::new();
search(&*masks, m, 1, List::Cons(m, &List::Nil), &mut data);
tx.send(data).unwrap();
let n = if std::env::var_os("RUST_BENCH").is_some() {
5000000
} else {
- std::os::args().get(1)
+ std::env::args().nth(1)
.and_then(|arg| arg.parse().ok())
.unwrap_or(1000)
};
extern crate getopts;
use std::sync::mpsc::{channel, Sender};
-use std::os;
use std::env;
use std::result::Result::{Ok, Err};
-use std::thread::Thread;
+use std::thread;
use std::time::Duration;
-fn fib(n: int) -> int {
- fn pfib(tx: &Sender<int>, n: int) {
+fn fib(n: isize) -> isize {
+ fn pfib(tx: &Sender<isize>, n: isize) {
if n == 0 {
tx.send(0).unwrap();
} else if n <= 2 {
} else {
let (tx1, rx) = channel();
let tx2 = tx1.clone();
- Thread::spawn(move|| pfib(&tx2, n - 1));
+ thread::spawn(move|| pfib(&tx2, n - 1));
let tx2 = tx1.clone();
- Thread::spawn(move|| pfib(&tx2, n - 2));
+ thread::spawn(move|| pfib(&tx2, n - 2));
tx.send(rx.recv().unwrap() + rx.recv().unwrap());
}
}
let (tx, rx) = channel();
- Thread::spawn(move|| pfib(&tx, n) );
+ thread::spawn(move|| pfib(&tx, n) );
rx.recv().unwrap()
}
}
}
-fn stress_task(id: int) {
+fn stress_task(id: isize) {
let mut i = 0;
loop {
let n = 15;
fn stress(num_tasks: int) {
let mut results = Vec::new();
for i in 0..num_tasks {
- results.push(Thread::scoped(move|| {
+ results.push(thread::spawn(move|| {
stress_task(i);
}));
}
}
fn main() {
- let args = os::args();
+ let args = env::args();
let args = if env::var_os("RUST_BENCH").is_some() {
vec!("".to_string(), "20".to_string())
- } else if args.len() <= 1u {
+ } else if args.len() <= 1 {
vec!("".to_string(), "8".to_string())
} else {
- args.into_iter().map(|x| x.to_string()).collect()
+ args.map(|x| x.to_string()).collect()
};
let opts = parse_opts(args.clone());
if opts.stress {
stress(2);
} else {
- let max = args[1].parse::<int>().unwrap();
+ let max = args[1].parse::<isize>().unwrap();
let num_trials = 10;
for n in 1..max + 1 {
- for _ in 0u..num_trials {
+ for _ in 0..num_trials {
let mut fibn = None;
let dur = Duration::span(|| fibn = Some(fib(n)));
let fibn = fibn.unwrap();
use std::old_io::stdio::{stdin_raw, stdout_raw};
use std::old_io::{IoResult, EndOfFile};
use std::ptr::{copy_memory, Unique};
-use std::thread::Thread;
+use std::thread;
struct Tables {
table8: [u8;1 << 8],
/// Executes a closure in parallel over the given iterator over mutable slice.
/// The closure `f` is run in parallel with an element of `iter`.
-fn parallel<'a, I, T, F>(iter: I, f: F)
- where T: 'a+Send + Sync,
- I: Iterator<Item=&'a mut [T]>,
- F: Fn(&mut [T]) + Sync {
- use std::mem;
- use std::raw::Repr;
-
- iter.map(|chunk| {
- // Need to convert `f` and `chunk` to something that can cross the task
- // boundary.
- let f = Racy(&f as *const F as *const uint);
- let raw = Racy(chunk.repr());
- Thread::scoped(move|| {
- let f = f.0 as *const F;
- unsafe { (*f)(mem::transmute(raw.0)) }
+fn parallel<'a, I: Iterator, F>(iter: I, ref f: F)
+ where I::Item: Send + 'a,
+ F: Fn(I::Item) + Sync + 'a {
+ iter.map(|x| {
+ thread::scoped(move|| {
+ f(x)
})
}).collect::<Vec<_>>();
}
#![feature(unboxed_closures)]
use std::iter::{repeat, AdditiveIterator};
-use std::thread::Thread;
+use std::thread;
use std::mem;
use std::num::Float;
use std::os;
use std::simd::f64x2;
fn main() {
- let args = os::args();
+ let mut args = env::args();
let answer = spectralnorm(if env::var_os("RUST_BENCH").is_some() {
5500
} else if args.len() < 2 {
2000
} else {
- args[1].parse().unwrap()
+ args.nth(1).unwrap().parse().unwrap()
});
println!("{:.9}", answer);
}
}
-struct Racy<T>(T);
-
-unsafe impl<T: 'static> Send for Racy<T> {}
-
// Executes a closure in parallel over the given mutable slice. The closure `f`
// is run in parallel and yielded the starting index within `v` as well as a
// sub-slice of `v`.
-fn parallel<T, F>(v: &mut [T], f: F)
- where T: Send + Sync,
- F: Fn(uint, &mut [T]) + Sync {
+fn parallel<'a,T, F>(v: &mut [T], ref f: F)
+ where T: Send + Sync + 'a,
+ F: Fn(uint, &mut [T]) + Sync + 'a {
let size = v.len() / os::num_cpus() + 1;
-
v.chunks_mut(size).enumerate().map(|(i, chunk)| {
- // Need to convert `f` and `chunk` to something that can cross the task
- // boundary.
- let f = Racy(&f as *const _ as *const uint);
- let raw = Racy(chunk.repr());
- Thread::scoped(move|| {
- let f = f.0 as *const F;
- unsafe { (*f)(i * size, mem::transmute(raw.0)) }
+ thread::scoped(move|| {
+ f(i * size, chunk)
})
}).collect::<Vec<_>>();
}
// OF THE POSSIBILITY OF SUCH DAMAGE.
use std::sync::mpsc::{channel, Sender, Receiver};
-use std::thread::Thread;
+use std::thread;
fn start(n_tasks: i32, token: i32) {
let (tx, mut rx) = channel();
for i in 2 .. n_tasks + 1 {
let (tx, next_rx) = channel();
let cur_rx = std::mem::replace(&mut rx, next_rx);
- guards.push(Thread::scoped(move|| roundtrip(i, tx, cur_rx)));
+ guards.push(thread::spawn(move|| roundtrip(i, tx, cur_rx)));
}
- let guard = Thread::scoped(move|| roundtrip(1, tx, rx));
+ let guard = thread::spawn(move|| roundtrip(1, tx, rx));
}
fn roundtrip(id: i32, tx: Sender<i32>, rx: Receiver<i32>) {
}
fn main() {
- let args = std::os::args();
+ let mut args = std::env::args();
let token = if std::env::var_os("RUST_BENCH").is_some() {
2000000
} else {
- args.get(1).and_then(|arg| arg.parse().ok()).unwrap_or(1000)
+ args.nth(1).and_then(|arg| arg.parse().ok()).unwrap_or(1000)
};
- let n_tasks = args.get(2)
+ let n_tasks = args.next()
.and_then(|arg| arg.parse().ok())
.unwrap_or(503);
// Microbenchmark for the smallintmap library
use std::collections::VecMap;
-use std::os;
use std::env;
use std::time::Duration;
-fn append_sequential(min: uint, max: uint, map: &mut VecMap<uint>) {
+fn append_sequential(min: usize, max: usize, map: &mut VecMap<usize>) {
for i in min..max {
- map.insert(i, i + 22u);
+ map.insert(i, i + 22);
}
}
-fn check_sequential(min: uint, max: uint, map: &VecMap<uint>) {
+fn check_sequential(min: usize, max: usize, map: &VecMap<usize>) {
for i in min..max {
- assert_eq!(map[i], i + 22u);
+ assert_eq!(map[i], i + 22);
}
}
fn main() {
- let args = os::args();
+ let args = env::args();
let args = if env::var_os("RUST_BENCH").is_some() {
vec!("".to_string(), "100000".to_string(), "100".to_string())
- } else if args.len() <= 1u {
+ } else if args.len() <= 1 {
vec!("".to_string(), "10000".to_string(), "50".to_string())
} else {
- args.into_iter().collect()
+ args.collect()
};
- let max = args[1].parse::<uint>().unwrap();
- let rep = args[2].parse::<uint>().unwrap();
+ let max = args[1].parse::<usize>().unwrap();
+ let rep = args[2].parse::<usize>().unwrap();
let mut checkf = Duration::seconds(0);
let mut appendf = Duration::seconds(0);
- for _ in 0u..rep {
+ for _ in 0..rep {
let mut map = VecMap::new();
- let d1 = Duration::span(|| append_sequential(0u, max, &mut map));
- let d2 = Duration::span(|| check_sequential(0u, max, &map));
+ let d1 = Duration::span(|| append_sequential(0, max, &mut map));
+ let d2 = Duration::span(|| check_sequential(0, max, &map));
checkf = checkf + d2;
appendf = appendf + d1;
use std::old_io;
use std::iter::repeat;
use std::num::Int;
-use std::os;
+use std::env;
// Computes a single solution to a given 9x9 sudoku
//
}
fn main() {
- let args = os::args();
- let use_default = args.len() == 1u;
+ let args = env::args();
+ let use_default = args.len() == 1;
let mut sudoku = if use_default {
Sudoku::from_vec(&DEFAULT_SUDOKU)
} else {
#![feature(unsafe_destructor, box_syntax)]
use std::env;
-use std::thread::Thread;
+use std::thread;
use std::time::Duration;
#[derive(Clone)]
fn run(repeat: int, depth: int) {
for _ in 0..repeat {
let dur = Duration::span(|| {
- let _ = Thread::scoped(move|| {
+ let _ = thread::spawn(move|| {
recurse_or_panic(depth, None)
}).join();
});
// ignore-pretty very bad with line comments
use std::sync::mpsc::{channel, Sender};
-use std::os;
use std::env;
-use std::thread::Thread;
+use std::thread;
fn child_generation(gens_left: uint, tx: Sender<()>) {
// This used to be O(n^2) in the number of generations that ever existed.
// With this code, only as many generations are alive at a time as tasks
// alive at a time,
- Thread::spawn(move|| {
+ thread::spawn(move|| {
if gens_left & 1 == 1 {
- Thread::yield_now(); // shake things up a bit
+ thread::yield_now(); // shake things up a bit
}
if gens_left > 0 {
child_generation(gens_left - 1, tx); // recurse
}
fn main() {
- let args = os::args();
+ let args = env::args();
let args = if env::var_os("RUST_BENCH").is_some() {
vec!("".to_string(), "100000".to_string())
} else if args.len() <= 1 {
vec!("".to_string(), "100".to_string())
} else {
- args.clone().into_iter().collect()
+ args.collect()
};
let (tx, rx) = channel();
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use std::os;
use std::env;
-use std::thread::Thread;
+use std::thread;
-fn f(n: uint) {
+fn f(n: usize) {
let mut i = 0u;
while i < n {
- let _ = Thread::scoped(move|| g()).join();
+ let _ = thread::spawn(move|| g()).join();
i += 1u;
}
}
fn g() { }
fn main() {
- let args = os::args();
+ let args = env::args();
let args = if env::var_os("RUST_BENCH").is_some() {
vec!("".to_string(), "400".to_string())
- } else if args.len() <= 1u {
+ } else if args.len() <= 1 {
vec!("".to_string(), "10".to_string())
} else {
- args.into_iter().collect()
+ args.collect()
};
let n = args[1].parse().unwrap();
- let mut i = 0u;
- while i < n { Thread::spawn(move|| f(n) ); i += 1u; }
+ let mut i = 0;
+ while i < n { thread::spawn(move|| f(n) ); i += 1; }
}
// aux-build:macro_crate_test.rs
// ignore-stage1
-// ignore-android
// error-pattern: unknown start of token: \u{0}
// Issue #15750 and #15962 : this test is checking that the standard
// aux-build:macro_crate_test.rs
// ignore-stage1
-// ignore-android
#[macro_use] #[no_link]
extern crate macro_crate_test;
// aux-build:macro_crate_test.rs
// ignore-stage1
-// ignore-android
#[macro_use] #[no_link]
extern crate macro_crate_test;
// aux-build:macro_crate_MacroRulesTT.rs
// ignore-stage1
-// ignore-android
// error-pattern: plugin tried to register a new MacroRulesTT
#![feature(plugin)]
+++ /dev/null
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn main() {
- let x = "\x80"; //~ ERROR may only be used
- let y = "\xff"; //~ ERROR may only be used
- let z = "\xe2"; //~ ERROR may only be used
- let a = b"\x00e2"; // ok because byte literal
-}
-
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ unsafe {
+ println!("{}", asm!("")); //~ ERROR inline assembly is not stable
+ }
+}
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#[derive(Debug)] //~ERROR expected item after attributes
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn main() {
- #[attr] //~ ERROR expected item after attributes
- println!("hi");
-}
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn main() {
- #[attr] //~ ERROR expected item
- let _i = 0;
-}
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// error-pattern:expected item
-
-fn f() {
- #[foo = "bar"]
- let x = 10;
-}
-
-fn main() {
-}
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// error-pattern:expected item
-
-fn f() {
- #[foo = "bar"]
-}
-
-fn main() {
-}
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// error-pattern:expected item
-
-fn main() {
-}
-
-#[foo = "bar"]
+++ /dev/null
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![feature(lang_items)]
-
-fn main() {}
-
-#![lang(foo)] //~ ERROR an inner attribute is not permitted in this context
-fn foo() {}
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// Constants (static variables) can be used to match in patterns, but mutable
-// statics cannot. This ensures that there's some form of error if this is
-// attempted.
-
-extern crate libc;
-
-extern {
- static mut rust_dbg_static_mut: libc::c_int;
- pub fn rust_dbg_static_mut_check_four();
- #[cfg(stage37)] //~ ERROR expected item after attributes
-}
-
-pub fn main() {}
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// ignore-tidy-cr
-// ignore-tidy-tab
-fn main() {
- // these literals are just silly.
- ''';
- //~^ ERROR: character constant must be escaped: \'
-
- // note that this is a literal "\n" byte
- '
-';
- //~^^ ERROR: character constant must be escaped: \n
-
- // note that this is a literal "\r" byte
- '\r'; //~ ERROR: character constant must be escaped: \r
-
- // note that this is a literal tab character here
- ' ';
- //~^ ERROR: character constant must be escaped: \t
-}
+++ /dev/null
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-
-extern crate
- "foo"suffix //~ ERROR extern crate name with a suffix is illegal
- as foo;
-
-extern
- "C"suffix //~ ERROR ABI spec with a suffix is illegal
- fn foo() {}
-
-extern
- "C"suffix //~ ERROR ABI spec with a suffix is illegal
-{}
-
-fn main() {
- ""suffix; //~ ERROR str literal with a suffix is illegal
- b""suffix; //~ ERROR binary str literal with a suffix is illegal
- r#""#suffix; //~ ERROR str literal with a suffix is illegal
- br#""#suffix; //~ ERROR binary str literal with a suffix is illegal
- 'a'suffix; //~ ERROR char literal with a suffix is illegal
- b'a'suffix; //~ ERROR byte literal with a suffix is illegal
-
- 1234u1024; //~ ERROR illegal width `1024` for integer literal
- 1234i1024; //~ ERROR illegal width `1024` for integer literal
- 1234f1024; //~ ERROR illegal width `1024` for float literal
- 1234.5f1024; //~ ERROR illegal width `1024` for float literal
-
- 1234suffix; //~ ERROR illegal suffix `suffix` for numeric literal
- 0b101suffix; //~ ERROR illegal suffix `suffix` for numeric literal
- 1.0suffix; //~ ERROR illegal suffix `suffix` for float literal
- 1.0e10suffix; //~ ERROR illegal suffix `suffix` for float literal
-}
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn false() { } //~ ERROR expected identifier, found keyword `false`
-fn main() { }
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn true() { } //~ ERROR expected identifier, found keyword `true`
-fn main() { }
#![feature(box_syntax)]
-use std::thread::Thread;
+use std::thread;
fn borrow<F>(v: &isize, f: F) where F: FnOnce(&isize) {
f(v);
fn box_imm() {
let v = box 3;
let _w = &v;
- Thread::spawn(move|| {
+ thread::spawn(move|| {
println!("v={}", *v);
//~^ ERROR cannot move `v` into closure
});
fn box_imm_explicit() {
let v = box 3;
let _w = &v;
- Thread::spawn(move|| {
+ thread::spawn(move|| {
println!("v={}", *v);
//~^ ERROR cannot move
});
#![feature(box_syntax)]
-use std::thread::Thread;
+use std::thread;
fn borrow<T>(_: &T) { }
let p1 = &x1;
let x2 = box 2;
let p2 = &x2;
- Thread::spawn(move|| {
+ thread::spawn(move|| {
drop(x1); //~ ERROR cannot move `x1` into closure because it is borrowed
drop(x2); //~ ERROR cannot move `x2` into closure because it is borrowed
});
drop(x1);
let x2 = box 2;
drop(x2);
- Thread::spawn(move|| {
+ thread::spawn(move|| {
drop(x1); //~ ERROR capture of moved value: `x1`
drop(x2); //~ ERROR capture of moved value: `x2`
});
fn same_var_after_borrow() {
let x = box 1;
let p = &x;
- Thread::spawn(move|| {
+ thread::spawn(move|| {
drop(x); //~ ERROR cannot move `x` into closure because it is borrowed
drop(x); //~ ERROR use of moved value: `x`
});
fn same_var_after_move() {
let x = box 1;
drop(x);
- Thread::spawn(move|| {
+ thread::spawn(move|| {
drop(x); //~ ERROR capture of moved value: `x`
drop(x); //~ ERROR use of moved value: `x`
});
trait Foo : Send { }
-impl <'a> Foo for &'a mut () { }
-//~^ ERROR the type `&'a mut ()` does not fulfill the required lifetime
+impl Foo for std::rc::Rc<i8> { }
+//~^ ERROR the trait `core::marker::Send` is not implemented
fn main() { }
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+#![feature(optin_builtin_traits)]
+
use std::marker::Send;
enum TestE {
struct MyType;
+struct NotSync;
+impl !Sync for NotSync {}
+
unsafe impl Send for TestE {}
unsafe impl Send for MyType {}
unsafe impl Send for (MyType, MyType) {}
//~^ ERROR builtin traits can only be implemented on structs or enums
-unsafe impl Send for &'static MyType {}
+unsafe impl Send for &'static NotSync {}
//~^ ERROR builtin traits can only be implemented on structs or enums
unsafe impl Send for [MyType] {}
//~^ ERROR builtin traits can only be implemented on structs or enums
-unsafe impl Send for &'static [MyType] {}
+unsafe impl Send for &'static [NotSync] {}
//~^ ERROR builtin traits can only be implemented on structs or enums
fn is_send<T: Send>() {}
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+const XY_1: i32 = 10;
+
+fn main() {
+ const XY_2: i32 = 20;
+ let a = concat_idents!(X, Y_1); //~ ERROR `concat_idents` is not stable
+ let b = concat_idents!(X, Y_2); //~ ERROR `concat_idents` is not stable
+ assert_eq!(a, 10);
+ assert_eq!(b, 20);
+}
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+const XY_1: i32 = 10;
+
+fn main() {
+ const XY_2: i32 = 20;
+ assert_eq!(10, concat_idents!(X, Y_1)); //~ ERROR `concat_idents` is not stable
+ assert_eq!(20, concat_idents!(X, Y_2)); //~ ERROR `concat_idents` is not stable
+}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[foo] //~ ERROR The attribute `foo`
+fn main() {
+
+}
\ No newline at end of file
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-/// hi
-#[derive(Debug)] //~ERROR expected item after attributes
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-/// hi //~ERROR expected item after doc comment
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-extern {
- /// hi
-}
-//~^^ ERROR expected item after doc comment
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn main() {
- /// hi
- println!("hi");
- //~^^ ERROR expected item after doc comment
-}
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn main() {
- println!("Hi"); /// hi
- //~^ ERROR expected item after doc comment
-}
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn main() {
- /// hi
- ;
- //~^^ ERROR expected item after doc comment
-}
+++ /dev/null
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// Tests that the proper help is displayed in the error message
-
-extern crate foo as bar;
-//~^ ERROR expected `;`, found `as`
-//~^^ HELP perhaps you meant to enclose the crate name `foo` in a string?
+++ /dev/null
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-struct Heap;
-
-struct Vec<A = Heap, T>; //~ ERROR type parameters with a default must be trailing
-
-struct Foo<A, B = Vec<C>, C>; //~ ERROR type parameters with a default must be trailing
-
-fn main() {}
+++ /dev/null
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// issue #17123
-
-fn main() {
- 100000000000000000000000000000000 //~ ERROR int literal is too large
-
- ; // the span shouldn't point to this.
-}
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-
-trait Serializable<'self, T> { //~ ERROR no longer a special lifetime
- fn serialize(val : &'self T) -> Vec<u8> ; //~ ERROR no longer a special lifetime
- fn deserialize(repr : &[u8]) -> &'self T; //~ ERROR no longer a special lifetime
-}
-
-impl<'self> Serializable<str> for &'self str { //~ ERROR no longer a special lifetime
- //~^ ERROR no longer a special lifetime
- fn serialize(val : &'self str) -> Vec<u8> { //~ ERROR no longer a special lifetime
- vec!(1)
- }
- fn deserialize(repr: &[u8]) -> &'self str { //~ ERROR no longer a special lifetime
- "hi"
- }
-}
-
-fn main() {
- println!("hello");
- let x = "foo".to_string();
- let y = x;
- println!("{}", y);
-}
// except according to those terms.
use std::sync::mpsc::channel;
-use std::thread::Thread;
+use std::thread;
fn main() {
let (tx, rx) = channel();
- let _t = Thread::spawn(move|| -> () {
+ let _t = thread::spawn(move|| -> () {
loop {
let tx = tx;
//~^ ERROR: use of moved value: `tx`
+++ /dev/null
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// For style and consistency reasons, non-parametrized enum variants must
-// be used simply as `ident` instead of `ident ()`.
-// This test-case covers enum declaration.
-
-enum Foo {
- Bar(), //~ ERROR nullary enum variants are written with no trailing `( )`
- Baz(), //~ ERROR nullary enum variants are written with no trailing `( )`
- Bazar
-}
-
-fn main() {
- println!("{}", match Bar { Bar => 1, Baz => 2, Bazar => 3 })
-}
+++ /dev/null
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// ignore-test FIXME(japari) remove test
-
-struct Foo {
- f: for <'b> |&'b isize|:
- 'b -> &'b isize //~ ERROR use of undeclared lifetime name `'b`
-}
-
-fn main() {
- let mut x: Vec< for <'a> ||
- :'a //~ ERROR use of undeclared lifetime name `'a`
- > = Vec::new();
- x.push(|| {});
-
- let foo = Foo {
- f: |x| x
- };
-}
+++ /dev/null
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-enum X {
- A =
- b'a' //~ ERROR discriminator values can only be used with a c-like enum
- ,
- B(isize)
-}
-
-fn main() {}
+++ /dev/null
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-const
-mut //~ ERROR: const globals cannot be mutable
-//~^ HELP did you mean to declare a static?
-FOO: usize = 3;
-
-fn main() {
-}
-
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// error-pattern:no valid digits found for number
-fn main() {
- log(error, 0bu);
-}
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn main() {
- let _i = 18446744073709551616; // 2^64
- //~^ ERROR int literal is too large
-}
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn main() {
- let _i = 0xff_ffff_ffff_ffff_ffff_is;
- //~^ ERROR int literal is too large
-}
// except according to those terms.
use std::{int, i8, i16, i32, i64};
-use std::thread::Thread;
+use std::thread;
fn main() {
- assert!(Thread::scoped(move|| int::MIN / -1).join().is_err());
+ assert!(thread::spawn(move|| { int::MIN / -1; }).join().is_err());
//~^ ERROR attempted to divide with overflow in a constant expression
- assert!(Thread::scoped(move|| i8::MIN / -1).join().is_err());
+ assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err());
//~^ ERROR attempted to divide with overflow in a constant expression
- assert!(Thread::scoped(move|| i16::MIN / -1).join().is_err());
+ assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err());
//~^ ERROR attempted to divide with overflow in a constant expression
- assert!(Thread::scoped(move|| i32::MIN / -1).join().is_err());
+ assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err());
//~^ ERROR attempted to divide with overflow in a constant expression
- assert!(Thread::scoped(move|| i64::MIN / -1).join().is_err());
+ assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err());
//~^ ERROR attempted to divide with overflow in a constant expression
- assert!(Thread::scoped(move|| 1is / 0).join().is_err());
+ assert!(thread::spawn(move|| { 1is / 0; }).join().is_err());
//~^ ERROR attempted to divide by zero in a constant expression
- assert!(Thread::scoped(move|| 1i8 / 0).join().is_err());
+ assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err());
//~^ ERROR attempted to divide by zero in a constant expression
- assert!(Thread::scoped(move|| 1i16 / 0).join().is_err());
+ assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err());
//~^ ERROR attempted to divide by zero in a constant expression
- assert!(Thread::scoped(move|| 1i32 / 0).join().is_err());
+ assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err());
//~^ ERROR attempted to divide by zero in a constant expression
- assert!(Thread::scoped(move|| 1i64 / 0).join().is_err());
+ assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err());
//~^ ERROR attempted to divide by zero in a constant expression
- assert!(Thread::scoped(move|| int::MIN % -1).join().is_err());
+ assert!(thread::spawn(move|| { int::MIN % -1; }).join().is_err());
//~^ ERROR attempted remainder with overflow in a constant expression
- assert!(Thread::scoped(move|| i8::MIN % -1).join().is_err());
+ assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err());
//~^ ERROR attempted remainder with overflow in a constant expression
- assert!(Thread::scoped(move|| i16::MIN % -1).join().is_err());
+ assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err());
//~^ ERROR attempted remainder with overflow in a constant expression
- assert!(Thread::scoped(move|| i32::MIN % -1).join().is_err());
+ assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err());
//~^ ERROR attempted remainder with overflow in a constant expression
- assert!(Thread::scoped(move|| i64::MIN % -1).join().is_err());
+ assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err());
//~^ ERROR attempted remainder with overflow in a constant expression
- assert!(Thread::scoped(move|| 1is % 0).join().is_err());
+ assert!(thread::spawn(move|| { 1is % 0; }).join().is_err());
//~^ ERROR attempted remainder with a divisor of zero in a constant expression
- assert!(Thread::scoped(move|| 1i8 % 0).join().is_err());
+ assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err());
//~^ ERROR attempted remainder with a divisor of zero in a constant expression
- assert!(Thread::scoped(move|| 1i16 % 0).join().is_err());
+ assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err());
//~^ ERROR attempted remainder with a divisor of zero in a constant expression
- assert!(Thread::scoped(move|| 1i32 % 0).join().is_err());
+ assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err());
//~^ ERROR attempted remainder with a divisor of zero in a constant expression
- assert!(Thread::scoped(move|| 1i64 % 0).join().is_err());
+ assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err());
//~^ ERROR attempted remainder with a divisor of zero in a constant expression
}
+++ /dev/null
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-pub extern
- "invalid-abi" //~ ERROR illegal ABI
-fn foo() {}
-
-fn main() {}
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// This file was auto-generated using 'src/etc/generate-keyword-tests.py as'
-
-fn main() {
- let as = "foo"; //~ error: ident
-}
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// This file was auto-generated using 'src/etc/generate-keyword-tests.py break'
-
-fn main() {
- let break = "foo"; //~ error: ident
-}
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// This file was auto-generated using 'src/etc/generate-keyword-tests.py else'
-
-fn main() {
- let else = "foo"; //~ error: ident
-}
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// This file was auto-generated using 'src/etc/generate-keyword-tests.py enum'
-
-fn main() {
- let enum = "foo"; //~ error: ident
-}
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// This file was auto-generated using 'src/etc/generate-keyword-tests.py extern'
-
-fn main() {
- let extern = "foo"; //~ error: ident
-}
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// This file was auto-generated using 'src/etc/generate-keyword-tests.py fn'
-
-fn main() {
- let fn = "foo"; //~ error: ident
-}
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// This file was auto-generated using 'src/etc/generate-keyword-tests.py for'
-
-fn main() {
- let for = "foo"; //~ error: ident
-}
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// This file was auto-generated using 'src/etc/generate-keyword-tests.py if'
-
-fn main() {
- let if = "foo"; //~ error: ident
-}
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// This file was auto-generated using 'src/etc/generate-keyword-tests.py impl'
-
-fn main() {
- let impl = "foo"; //~ error: ident
-}
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// This file was auto-generated using 'src/etc/generate-keyword-tests.py let'
-
-fn main() {
- let let = "foo"; //~ error: ident
-}
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// This file was auto-generated using 'src/etc/generate-keyword-tests.py loop'
-
-fn main() {
- let loop = "foo"; //~ error: ident
-}
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// This file was auto-generated using 'src/etc/generate-keyword-tests.py match'
-
-fn main() {
- let match = "foo"; //~ error: ident
-}
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// This file was auto-generated using 'src/etc/generate-keyword-tests.py mod'
-
-fn main() {
- let mod = "foo"; //~ error: ident
-}
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// This file was auto-generated using 'src/etc/generate-keyword-tests.py pub'
-
-fn main() {
- let pub = "foo"; //~ error: ident
-}
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// This file was auto-generated using 'src/etc/generate-keyword-tests.py return'
-
-fn main() {
- let return = "foo"; //~ error: ident
-}
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// This file was auto-generated using 'src/etc/generate-keyword-tests.py self'
-
-fn main() {
- let self = "foo"; //~ error: ident
-}
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// This file was auto-generated using 'src/etc/generate-keyword-tests.py static'
-
-fn main() {
- let static = "foo"; //~ error: ident
-}
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// This file was auto-generated using 'src/etc/generate-keyword-tests.py struct'
-
-fn main() {
- let struct = "foo"; //~ error: ident
-}
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// This file was auto-generated using 'src/etc/generate-keyword-tests.py super'
-
-fn main() {
- let super = "foo"; //~ error: ident
-}
+++ /dev/null
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn main() {
- let super: isize; //~ ERROR expected identifier, found keyword `super`
-}
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// This file was auto-generated using 'src/etc/generate-keyword-tests.py trait'
-
-fn main() {
- let trait = "foo"; //~ error: ident
-}
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// This file was auto-generated using 'src/etc/generate-keyword-tests.py type'
-
-fn main() {
- let type = "foo"; //~ error: ident
-}
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// This file was auto-generated using 'src/etc/generate-keyword-tests.py unsafe'
-
-fn main() {
- let unsafe = "foo"; //~ error: ident
-}
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// This file was auto-generated using 'src/etc/generate-keyword-tests.py use'
-
-fn main() {
- let use = "foo"; //~ error: ident
-}
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// This file was auto-generated using 'src/etc/generate-keyword-tests.py while'
-
-fn main() {
- let while = "foo"; //~ error: ident
-}
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-pub mod break {
- //~^ ERROR expected identifier, found keyword `break`
-}
+++ /dev/null
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn main() {
- struct::foo(); //~ ERROR expected identifier
- mut::baz(); //~ ERROR expected identifier
-}
-
trait Gettable<T> {}
-impl<T: Send + Copy> Gettable<T> for S<T> {}
+impl<T: Send + Copy + 'static> Gettable<T> for S<T> {}
fn f<T>(val: T) {
let t: S<T> = S;
fn object_ref_with_static_bound_not_ok() {
assert_send::<&'static (Dummy+'static)>();
- //~^ ERROR the trait `core::marker::Send` is not implemented
+ //~^ ERROR the trait `core::marker::Sync` is not implemented
}
fn box_object_with_no_bound_not_ok<'a>() {
}
fn object_with_send_bound_ok() {
- assert_send::<&'static (Dummy+Send)>();
+ assert_send::<&'static (Dummy+Sync)>();
assert_send::<Box<Dummy+Send>>();
}
// is broken into two parts because some errors occur in distinct
// phases in the compiler. See kindck-send-object2.rs as well!
-fn assert_send<T:Send>() { }
+fn assert_send<T:Send+'static>() { }
trait Dummy { }
// careful with object types, who knows what they close over...
fn test51<'a>() {
assert_send::<&'a Dummy>();
- //~^ ERROR the trait `core::marker::Send` is not implemented
+ //~^ ERROR the trait `core::marker::Sync` is not implemented
}
fn test52<'a>() {
- assert_send::<&'a (Dummy+Send)>();
+ assert_send::<&'a (Dummy+Sync)>();
//~^ ERROR does not fulfill the required lifetime
}
// ...unless they are properly bounded
fn test60() {
- assert_send::<&'static (Dummy+Send)>();
+ assert_send::<&'static (Dummy+Sync)>();
}
fn test61() {
assert_send::<Box<Dummy+Send>>();
trait Dummy { }
fn test50() {
- assert_send::<&'static Dummy>(); //~ ERROR the trait `core::marker::Send` is not implemented
+ assert_send::<&'static Dummy>(); //~ ERROR the trait `core::marker::Sync` is not implemented
}
fn test53() {
// ...unless they are properly bounded
fn test60() {
- assert_send::<&'static (Dummy+Send)>();
+ assert_send::<&'static (Dummy+Sync)>();
}
fn test61() {
assert_send::<Box<Dummy+Send>>();
fn test32() { assert_send::<Vec<isize> >(); }
// but not if they own a bad thing
-fn test40<'a>(_: &'a isize) {
- assert_send::<Box<&'a isize>>(); //~ ERROR does not fulfill the required lifetime
+fn test40() {
+ assert_send::<Box<*mut u8>>(); //~ ERROR `core::marker::Send` is not implemented
}
fn main() { }
+++ /dev/null
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// Test that borrowed pointers are not sendable unless 'static.
-
-fn assert_send<T:Send>() { }
-
-// lifetime pointers with 'static lifetime are ok
-fn test01() { assert_send::<&'static isize>(); }
-fn test02() { assert_send::<&'static str>(); }
-fn test03() { assert_send::<&'static [isize]>(); }
-
-// whether or not they are mutable
-fn test10() { assert_send::<&'static mut isize>(); }
-
-// otherwise lifetime pointers are not ok
-fn test20<'a>(_: &'a isize) {
- assert_send::<&'a isize>(); //~ ERROR does not fulfill the required lifetime
-}
-fn test21<'a>(_: &'a isize) {
- assert_send::<&'a str>(); //~ ERROR does not fulfill the required lifetime
-}
-fn test22<'a>(_: &'a isize) {
- assert_send::<&'a [isize]>(); //~ ERROR does not fulfill the required lifetime
-}
-
-fn main() { }
+++ /dev/null
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn main() {
- 0o1.0; //~ ERROR: octal float literal is not supported
- 0o2f32; //~ ERROR: octal float literal is not supported
- 0o3.0f32; //~ ERROR: octal float literal is not supported
- 0o4e4; //~ ERROR: octal float literal is not supported
- 0o5.0e5; //~ ERROR: octal float literal is not supported
- 0o6e6f32; //~ ERROR: octal float literal is not supported
- 0o7.0e7f64; //~ ERROR: octal float literal is not supported
- 0x8.0e+9; //~ ERROR: hexadecimal float literal is not supported
- 0x9.0e-9; //~ ERROR: hexadecimal float literal is not supported
- 0o; //~ ERROR: no valid digits
- 1e+; //~ ERROR: expected at least one digit in exponent
- 0x539.0; //~ ERROR: hexadecimal float literal is not supported
- 99999999999999999999999999999999; //~ ERROR: int literal is too large
- 99999999999999999999999999999999u32; //~ ERROR: int literal is too large
- 0x; //~ ERROR: no valid digits
- 0xu32; //~ ERROR: no valid digits
- 0ou32; //~ ERROR: no valid digits
- 0bu32; //~ ERROR: no valid digits
- 0b; //~ ERROR: no valid digits
- 0o123f64; //~ ERROR: octal float literal is not supported
- 0o123.456; //~ ERROR: octal float literal is not supported
- 0b101f64; //~ ERROR: binary float literal is not supported
- 0b111.101; //~ ERROR: binary float literal is not supported
-}
+++ /dev/null
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// ignore-tidy-cr
-
-/// doc comment with bare CR: '\r'
-pub fn foo() {}
-//~^^ ERROR: bare CR not allowed in doc-comment
-
-/** block doc comment with bare CR: '\r' */
-pub fn bar() {}
-//~^^ ERROR: bare CR not allowed in block doc-comment
-
-fn main() {
- // the following string literal has a bare CR in it
- let _s = "foo\rbar"; //~ ERROR: bare CR not allowed in string
-
- // the following string literal has a bare CR in it
- let _s = r"bar\rfoo"; //~ ERROR: bare CR not allowed in raw string
-
- // the following string literal has a bare CR in it
- let _s = "foo\\rbar"; //~ ERROR: unknown character escape: \r
-}
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn foo<'a>(a: &'a isize) { }
-fn bar(a: &'static isize) { }
-fn baz(a: &'let isize) { } //~ ERROR invalid lifetime name
-
-fn main() { }
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn baz(a: &'self isize) { } //~ ERROR invalid lifetime name: 'self is no longer a special lifetime
-
-fn main() { }
extern {
#[linkage = "extern_weak"] static foo: isize;
//~^ ERROR: the `linkage` attribute is experimental and not portable
+ //~^^ ERROR: the `linkage` attribute is experimental and not portable
}
#[linkage = "external"]
static foo: isize = 0;
-//~^ ERROR: the `linkage` attribute is experimental and not portable
+//~^^ ERROR: the `linkage` attribute is experimental and not portable
fn main() {}
#![deny(unused_attributes)]
#![allow(dead_code)]
+#![feature(custom_attribute)]
#[abi="stdcall"] extern {} //~ ERROR unused attribute
impl UnstableTrait for S { } //~ WARNING use of unstable library feature
trait LocalTrait : UnstableTrait { } //~ WARNING use of unstable library feature
+
+ impl Trait for S {
+ fn trait_stable(&self) {}
+ fn trait_unstable(&self) {} //~ WARNING use of unstable library feature
+ }
}
mod inheritance {
// When denying at the crate level, be sure to not get random warnings from the
// injected intrinsics by the compiler.
+#![feature(custom_attribute)]
#![deny(unused_attributes)]
#![mutable_doc] //~ ERROR unused attribute
#![allow(dead_code)]
#![deny(non_snake_case)]
-#![feature(path)]
-#![feature(io)]
-use std::old_io::File;
-use std::old_io::IoError;
+mod foo {
+ pub enum Foo { Foo }
+}
struct Something {
X: usize //~ ERROR structure field `X` should have a snake case name such as `x`
let Test: usize = 0; //~ ERROR variable `Test` should have a snake case name such as `test`
println!("{}", Test);
- let mut f = File::open(&Path::new("something.txt"));
- let mut buff = [0u8; 16];
- match f.read(&mut buff) {
- Ok(cnt) => println!("read this many bytes: {}", cnt),
- Err(IoError{ kind: EndOfFile, .. }) => println!("Got end of file: {:?}", EndOfFile),
-//~^ ERROR variable `EndOfFile` should have a snake case name such as `end_of_file`
-//~^^ WARN `EndOfFile` is named the same as one of the variants of the type `std::old_io::IoErrorKind`
+ match foo::Foo::Foo {
+ Foo => {}
+//~^ ERROR variable `Foo` should have a snake case name such as `foo`
+//~^^ WARN `Foo` is named the same as one of the variants of the type `foo::Foo`
+//~^^^ WARN unused variable: `Foo`
}
test(1);
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ println!("{}", log_syntax!()); //~ ERROR `log_syntax!` is not stable
+}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+#![feature(custom_attribute)]
+
macro_rules! test { ($nm:ident,
#[$a:meta],
$i:item) => (mod $nm { #![$a] $i }); }
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+#![feature(custom_attribute)]
+
macro_rules! test { ($nm:ident,
#[$a:meta],
$i:item) => (mod $nm { #[$a] $i }); }
+++ /dev/null
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-macro_rules! foo() //~ ERROR semicolon
-
-fn main() {
-}
// #[stable] is not inherited
pub fn unmarked() {}
//~^ ERROR This node does not have a stability attribute
-}
\ No newline at end of file
+}
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+mod mod_file_disambig_aux; //~ ERROR file for module `mod_file_disambig_aux` found at both
+
+fn main() {
+ assert_eq!(mod_file_aux::bar(), 10);
+}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// error-pattern: cannot declare a new module at this location
+
+mod mod_file_not_owning_aux1;
+
+fn main() {}
// These are all fairly trivial cases: unused variables or direct
// drops of substructure.
+#![feature(rustc_attrs)]
+
pub struct D { d: isize }
impl Drop for D { fn drop(&mut self) { } }
// These are checking that enums are tracked; note that their output
// paths include "downcasts" of the path to a particular enum.
+#![feature(rustc_attrs)]
+
use self::Lonely::{Zero, One, Two};
pub struct D { d: isize }
// This checks the handling of `_` within variants, especially when mixed
// with bindings.
+#![feature(rustc_attrs)]
+
use self::Lonely::{Zero, One, Two};
pub struct D { d: isize }
// early draft of the code did not properly traverse up through all of
// the parents of the leaf fragment.)
+#![feature(rustc_attrs)]
+
pub struct D { d: isize }
impl Drop for D { fn drop(&mut self) { } }
// This is the first test that checks moving into local variables.
+#![feature(rustc_attrs)]
+
pub struct D { d: isize }
impl Drop for D { fn drop(&mut self) { } }
// Test that moving into a field (i.e. overwriting it) fragments the
// receiver.
+#![feature(rustc_attrs)]
+
use std::mem::drop;
pub struct Pair<X,Y> { x: X, y: Y }
// both moving out of the structure (i.e. reading `*p.x`) and writing
// into the container (i.e. writing `*p.x`).
+#![feature(rustc_attrs)]
+
pub struct D { d: isize }
impl Drop for D { fn drop(&mut self) { } }
// also that in this case we cannot do a move out of `&T`, so we only
// test writing `*p.x` here.
+#![feature(rustc_attrs)]
+
pub struct D { d: isize }
impl Drop for D { fn drop(&mut self) { } }
// Note also that the `test_move_array_then_overwrite` tests represent
// cases that we probably should make illegal.
+#![feature(rustc_attrs)]
+
pub struct D { d: isize }
impl Drop for D { fn drop(&mut self) { } }
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use std::thread::Thread;
+use std::thread;
fn main() {
let x = "Hello world!".to_string();
- Thread::spawn(move|| {
+ thread::spawn(move|| {
println!("{}", x);
});
println!("{}", x); //~ ERROR use of moved value
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// error-pattern:binary float literal is not supported
-
-fn main() {
- 0b101010f64;
- 0b101.010;
- 0b101p4f64;
-}
// error-pattern: use of moved value
use std::sync::Arc;
-use std::thread::Thread;
+use std::thread;
fn main() {
let v = vec!(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
let arc_v = Arc::new(v);
- Thread::spawn(move|| {
+ thread::spawn(move|| {
assert_eq!((*arc_v)[3], 4);
});
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// error-pattern:hexadecimal float literal is not supported
-
-fn main() {
- 0xABC.Df;
- 0x567.89;
- 0xDEAD.BEEFp-2f;
-}
// except according to those terms.
use std::sync::Arc;
-use std::thread::Thread;
+use std::thread;
fn main() {
let v = vec!(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
let arc_v = Arc::new(v);
- Thread::spawn(move|| {
+ thread::spawn(move|| {
assert_eq!((*arc_v)[3], 4);
});
#![feature(unsafe_destructor)]
-use std::thread::Thread;
+use std::thread;
use std::rc::Rc;
#[derive(Debug)]
let x = foo(Port(Rc::new(())));
- Thread::spawn(move|| {
+ thread::spawn(move|| {
//~^ ERROR `core::marker::Send` is not implemented
let y = x;
println!("{:?}", y);
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-trait A {
- fn foo(*mut self); //~ ERROR cannot pass self by unsafe pointer
- fn bar(*self); //~ ERROR cannot pass self by unsafe pointer
-}
-
-struct X;
-impl A for X {
- fn foo(*mut self) { } //~ ERROR cannot pass self by unsafe pointer
- fn bar(*self) { } //~ ERROR cannot pass self by unsafe pointer
-}
-
-fn main() { }
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// Issue #623 - non-string meta items are not serialized correctly;
-// for now just forbid them
-
-#[foo = 1] //~ ERROR: non-string literals are not allowed in meta-items
-fn main() { }
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+#![feature(rustc_attrs)]
+
#[rustc_object_lifetime_default]
struct A<T>(T); //~ ERROR None
+++ /dev/null
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// Test that we generate obsolete syntax errors around usages of `for Sized?`
-
-trait Foo for Sized? {} //~ ERROR obsolete syntax: for Sized?
-
-trait Bar for ?Sized {} //~ ERROR obsolete syntax: for Sized?
-
-fn main() { }
+++ /dev/null
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// Test that we generate obsolete syntax errors around usages of `proc`.
-
-fn foo(p: proc()) { } //~ ERROR obsolete syntax: the `proc` type
-
-fn bar() { proc() 1; } //~ ERROR obsolete syntax: `proc` expression
-
-fn main() { }
+++ /dev/null
-// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// ignore-test Can't use syntax crate here
-
-#![feature(quote)]
-
-extern crate syntax;
-
-use io::*;
-
-use syntax::diagnostic;
-use syntax::ast;
-use syntax::codemap;
-use syntax::parse;
-use syntax::print::*;
-
-
-trait fake_ext_ctxt {
- fn cfg() -> ast::CrateConfig;
- fn parse_sess() -> parse::parse_sess;
- fn call_site() -> span;
- fn ident_of(st: &str) -> ast::ident;
-}
-
-type fake_session = parse::parse_sess;
-
-impl fake_ext_ctxt for fake_session {
- fn cfg() -> ast::CrateConfig { Vec::new() }
- fn parse_sess() -> parse::parse_sess { self }
- fn call_site() -> span {
- codemap::span {
- lo: codemap::BytePos(0),
- hi: codemap::BytePos(0),
- expn_id: NO_EXPANSION
- }
- }
- fn ident_of(st: &str) -> ast::ident {
- self.interner.intern(st)
- }
-}
-
-fn mk_ctxt() -> fake_ext_ctxt {
- parse::new_parse_sess(None) as fake_ext_ctxt
-}
-
-
-
-fn main() {
- let cx = mk_ctxt();
-
- let abc = quote_expr!(cx, 23);
- check_pp(abc, pprust::print_expr, "23");
-
- let expr3 = quote_expr!(cx, 2 - $abcd + 7); //~ ERROR unresolved name: abcd
- check_pp(expr3, pprust::print_expr, "2 - 23 + 7");
-}
-
-fn check_pp<T>(expr: T, f: |pprust::ps, T|, expect: str) {
- panic!();
-}
+++ /dev/null
-// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// ignore-test Can't use syntax crate here
-
-#![feature(quote)]
-
-extern crate syntax;
-
-use syntax::diagnostic;
-use syntax::ast;
-use syntax::codemap;
-use syntax::parse::parser;
-use syntax::print::*;
-
-trait fake_ext_ctxt {
- fn cfg() -> ast::CrateConfig;
- fn parse_sess() -> parse::parse_sess;
- fn call_site() -> span;
- fn ident_of(st: &str) -> ast::ident;
-}
-
-type fake_session = parse::parse_sess;
-
-impl fake_ext_ctxt for fake_session {
- fn cfg() -> ast::CrateConfig { Vec::new() }
- fn parse_sess() -> parse::parse_sess { self }
- fn call_site() -> span {
- codemap::span {
- lo: codemap::BytePos(0),
- hi: codemap::BytePos(0),
- expn_id: codemap::NO_EXPANSION
- }
- }
- fn ident_of(st: &str) -> ast::ident {
- self.interner.intern(st)
- }
-}
-
-fn mk_ctxt() -> fake_ext_ctxt {
- parse::new_parse_sess(None) as fake_ext_ctxt
-}
-
-
-fn main() {
- let cx = mk_ctxt();
-
- let stmt = quote_stmt!(cx, let x isize = 20;); //~ ERROR expected end-of-string
- check_pp(*stmt, pprust::print_stmt, "");
-}
-
-fn check_pp<T>(expr: T, f: |pprust::ps, T|, expect: str) {
- panic!();
-}
// Various tests related to testing how region inference works
// with respect to the object receivers.
+#![feature(rustc_attrs)]
#![allow(warnings)]
trait Foo {
// Various tests related to testing how region inference works
// with respect to the object receivers.
+#![feature(rustc_attrs)]
#![allow(warnings)]
trait Foo {
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that we are imposing the requirement that every associated
+// type of a bound that appears in the where clause on a struct must
+// outlive the location in which the type appears, even when the
+// associted type is in a supertype. Issue #22246.
+
+#![allow(dead_code)]
+
+use std::mem::transmute;
+use std::ops::Deref;
+
+///////////////////////////////////////////////////////////////////////////
+
+pub trait TheTrait {
+ type TheAssocType;
+
+ fn dummy(&self) { }
+}
+
+pub trait TheSubTrait : TheTrait {
+}
+
+pub struct TheType<'b> {
+ m: [fn(&'b()); 0]
+}
+
+impl<'b> TheTrait for TheType<'b> {
+ type TheAssocType = &'b ();
+}
+
+impl<'b> TheSubTrait for TheType<'b> {
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+pub struct WithAssoc<T:TheSubTrait> {
+ m: [T; 0]
+}
+
+fn with_assoc<'a,'b>() {
+ // For this type to be valid, the rules require that all
+ // associated types of traits that appear in `WithAssoc` must
+ // outlive 'a. In this case, that means TheType<'b>::TheAssocType,
+ // which is &'b (), must outlive 'a.
+
+ let _: &'a WithAssoc<TheType<'b>> = loop { }; //~ ERROR cannot infer
+}
+
+fn main() {
+}
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that structs with higher-ranked where clauses don't generate
+// "outlives" requirements. Issue #22246.
+
+#![allow(dead_code)]
+#![feature(rustc_attrs)]
+
+///////////////////////////////////////////////////////////////////////////
+
+pub trait TheTrait<'b> {
+ type TheAssocType;
+
+ fn dummy(&'b self) { }
+}
+
+pub struct TheType<'b> {
+ m: [fn(&'b()); 0]
+}
+
+impl<'a,'b> TheTrait<'a> for TheType<'b> {
+ type TheAssocType = &'b ();
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+pub struct WithHrAssoc<T>
+ where for<'a> T : TheTrait<'a>
+{
+ m: [T; 0]
+}
+
+fn with_assoc<'a,'b>() {
+ // We get no error here because the where clause has a higher-ranked assoc type,
+ // which could not be projected from.
+
+ let _: &'a WithHrAssoc<TheType<'b>> = loop { };
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+pub trait TheSubTrait : for<'a> TheTrait<'a> {
+}
+
+impl<'b> TheSubTrait for TheType<'b> { }
+
+pub struct WithHrAssocSub<T>
+ where T : TheSubTrait
+{
+ m: [T; 0]
+}
+
+fn with_assoc_sub<'a,'b>() {
+ // Same here, because although the where clause is not HR, it
+ // extends a trait in a HR way.
+
+ let _: &'a WithHrAssocSub<TheType<'b>> = loop { };
+}
+
+#[rustc_error]
+fn main() { //~ ERROR compilation successful
+}
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that we are imposing the requirement that every associated
+// type of a bound that appears in the where clause on a struct must
+// outlive the location in which the type appears, even when the
+// constraint is in a where clause not a bound. Issue #22246.
+
+#![allow(dead_code)]
+
+use std::mem::transmute;
+use std::ops::Deref;
+
+///////////////////////////////////////////////////////////////////////////
+
+pub trait TheTrait {
+ type TheAssocType;
+
+ fn dummy(&self) { }
+}
+
+pub struct TheType<'b> {
+ m: [fn(&'b()); 0]
+}
+
+impl<'b> TheTrait for TheType<'b> {
+ type TheAssocType = &'b ();
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+pub struct WithAssoc<T> where T : TheTrait {
+ m: [T; 0]
+}
+
+fn with_assoc<'a,'b>() {
+ // For this type to be valid, the rules require that all
+ // associated types of traits that appear in `WithAssoc` must
+ // outlive 'a. In this case, that means TheType<'b>::TheAssocType,
+ // which is &'b (), must outlive 'a.
+
+ let _: &'a WithAssoc<TheType<'b>> = loop { }; //~ ERROR cannot infer
+}
+
+fn main() {
+}
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that we are imposing the requirement that every associated
+// type of a bound that appears in the where clause on a struct must
+// outlive the location in which the type appears. Issue #22246.
+
+#![allow(dead_code)]
+
+use std::mem::transmute;
+use std::ops::Deref;
+
+///////////////////////////////////////////////////////////////////////////
+
+pub trait TheTrait {
+ type TheAssocType;
+
+ fn dummy(&self) { }
+}
+
+pub struct TheType<'b> {
+ m: [fn(&'b()); 0]
+}
+
+impl<'b> TheTrait for TheType<'b> {
+ type TheAssocType = &'b ();
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+pub struct WithAssoc<T:TheTrait> {
+ m: [T; 0]
+}
+
+pub struct WithoutAssoc<T> {
+ m: [T; 0]
+}
+
+fn with_assoc<'a,'b>() {
+ // For this type to be valid, the rules require that all
+ // associated types of traits that appear in `WithAssoc` must
+ // outlive 'a. In this case, that means TheType<'b>::TheAssocType,
+ // which is &'b (), must outlive 'a.
+
+ let _: &'a WithAssoc<TheType<'b>> = loop { }; //~ ERROR cannot infer
+}
+
+fn with_assoc1<'a,'b>() where 'b : 'a {
+ // For this type to be valid, the rules require that all
+ // associated types of traits that appear in `WithAssoc` must
+ // outlive 'a. In this case, that means TheType<'b>::TheAssocType,
+ // which is &'b (), must outlive 'a, so 'b : 'a must hold, and
+ // that is in the where clauses, so we're fine.
+
+ let _: &'a WithAssoc<TheType<'b>> = loop { };
+}
+
+fn without_assoc<'a,'b>() {
+ // Here there are no associated types and the `'b` appearing in
+ // `TheType<'b>` is purely covariant, so there is no requirement
+ // that `'b:'a` holds.
+
+ let _: &'a WithoutAssoc<TheType<'b>> = loop { };
+}
+
+fn call_with_assoc<'a,'b>() {
+ // As `with_assoc`, but just checking that we impose the same rule
+ // on the value supplied for the type argument, even when there is
+ // no data.
+
+ call::<&'a WithAssoc<TheType<'b>>>();
+ //~^ ERROR cannot infer
+}
+
+fn call_without_assoc<'a,'b>() {
+ // As `without_assoc`, but in a distinct scenario.
+
+ call::<&'a WithoutAssoc<TheType<'b>>>();
+}
+
+fn call<T>() { }
+
+fn main() {
+}
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// Test which of the builtin types are considered sendable. The tests
-// in this file all test region bound and lifetime violations that are
-// detected during type check.
-
-extern crate core;
-use core::ptr::Unique;
-
-fn assert_send<T:Send>() { }
-trait Dummy:Send { }
-
-// lifetime pointers with 'static lifetime are ok
-
-fn static_lifime_ok<'a,T,U:Send>(_: &'a isize) {
- assert_send::<&'static isize>();
- assert_send::<&'static str>();
- assert_send::<&'static [isize]>();
-
- // whether or not they are mutable
- assert_send::<&'static mut isize>();
-}
-
-// otherwise lifetime pointers are not ok
-
-fn param_not_ok<'a>(x: &'a isize) {
- assert_send::<&'a isize>(); //~ ERROR does not fulfill the required lifetime
-}
-
-fn param_not_ok1<'a>(_: &'a isize) {
- assert_send::<&'a str>(); //~ ERROR does not fulfill the required lifetime
-}
-
-fn param_not_ok2<'a>(_: &'a isize) {
- assert_send::<&'a [isize]>(); //~ ERROR does not fulfill the required lifetime
-}
-
-// boxes are ok
-
-fn box_ok() {
- assert_send::<Box<isize>>();
- assert_send::<String>();
- assert_send::<Vec<isize>>();
-}
-
-// but not if they own a bad thing
-
-fn box_with_region_not_ok<'a>() {
- assert_send::<Box<&'a isize>>(); //~ ERROR does not fulfill the required lifetime
-}
-
-// objects with insufficient bounds no ok
-
-fn object_with_random_bound_not_ok<'a>() {
- assert_send::<&'a (Dummy+'a)>();
- //~^ ERROR reference has a longer lifetime
-}
-
-fn object_with_send_bound_not_ok<'a>() {
- assert_send::<&'a (Dummy+Send)>();
- //~^ ERROR does not fulfill the required lifetime
-}
-
-// unsafe pointers are ok unless they point at unsendable things
-
-struct UniqueUnsafePtr(Unique<*const isize>);
-
-unsafe impl Send for UniqueUnsafePtr {}
-
-fn unsafe_ok1<'a>(_: &'a isize) {
- assert_send::<UniqueUnsafePtr>();
-}
-
-fn main() {
-}
+++ /dev/null
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// ignore-test
-// ignored because the first error does not show up.
-
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn of<T>() -> |T| { panic!(); }
-fn subtype<T>(x: |T|) { panic!(); }
-
-fn test_fn<'x, 'y, 'z, T>(_x: &'x T, _y: &'y T, _z: &'z T) {
- // Here, x, y, and z are free. Other letters
- // are bound. Note that the arrangement
- // subtype::<T1>(of::<T2>()) will typecheck
- // iff T1 <: T2.
-
- // should be the default:
- subtype::< ||:'static>(of::<||>());
- subtype::<||>(of::< ||:'static>());
-
- //
- subtype::< <'x> ||>(of::<||>()); //~ ERROR mismatched types
- subtype::< <'x> ||>(of::< <'y> ||>()); //~ ERROR mismatched types
-
- subtype::< <'x> ||>(of::< ||:'static>()); //~ ERROR mismatched types
- subtype::< ||:'static>(of::< <'x> ||>());
-
-}
-
-fn main() {}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-fn assert_send<T: Send>(_t: T) {}
+fn assert_static<T: 'static>(_t: T) {}
fn main() {
let line = String::new();
match [&*line] { //~ ERROR `line` does not live long enough
- [ word ] => { assert_send(word); }
+ [ word ] => { assert_static(word); }
}
}
+++ /dev/null
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn f<T>() {}
-
-fn main() {
- false == false == false;
- //~^ ERROR: chained comparison operators require parentheses
-
- false == 0 < 2;
- //~^ ERROR: chained comparison operators require parentheses
-
- f<X>();
- //~^ ERROR: chained comparison operators require parentheses
- //~^^ HELP: use `::<...>` instead of `<...>`
-}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+#![feature(rustc_attrs)]
+
#[rustc_error]
fn main() {
//~^ ERROR compilation successful
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::thread;
+
+fn main() {
+ let bad = {
+ let x = 1;
+ let y = &x;
+
+ thread::scoped(|| { //~ ERROR cannot infer an appropriate lifetime
+ let _z = y;
+ })
+ };
+
+ bad.join();
+}
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-struct Foo;
-
-fn f2() {
- let _end_stmt = Foo { };
- //~^ ERROR: structure literal must either have at least one field
-}
-
-fn main() {}
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-struct Foo;
-
-fn g3() {
- let _mid_tuple = (Foo { }, 2);
- //~^ ERROR: structure literal must either have at least one field
-}
-
-fn main() {}
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-struct Foo;
-
-fn h4() {
- let _end_of_tuple = (3, Foo { });
- //~^ ERROR: structure literal must either have at least one field
-}
-
-fn main() {}
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-struct Foo;
-
-fn i5() {
- let _end_of_block = { Foo { } };
- //~^ ERROR: structure literal must either have at least one field
-}
-
-fn main() {}
+++ /dev/null
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-enum Foo {
- Bar {} //~ ERROR unit-like struct variant should be written without braces, as `Bar,`
-}
+++ /dev/null
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-enum Foo {
- Bar {
- pub a: isize //~ ERROR: `pub` is not allowed here
- }
-}
-
-fn main() {}
+++ /dev/null
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![feature(optin_builtin_traits)]
-
-use std::marker::Send;
-
-struct TestType;
-
-impl !TestType {}
-//~^ ERROR inherent implementation can't be negated
-
-trait TestTrait {}
-
-unsafe impl !Send for TestType {}
-impl !TestTrait for TestType {}
-
-struct TestType2<T>;
-
-impl<T> !TestType2<T> {}
-//~^ ERROR inherent implementation can't be negated
-
-unsafe impl<T> !Send for TestType2<T> {}
-impl<T> !TestTrait for TestType2<T> {}
-
-fn main() {}
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//error-pattern: discriminator values can only be used with a c-like enum
-
-enum color {
- red = 0xff0000,
- green = 0x00ff00,
- blue = 0x0000ff,
- black = 0x000000,
- white = 0xffffff,
- other (str),
-}
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that the trace_macros feature gate is on.
+
+fn main() {
+ trace_macros!(); //~ ERROR `trace_macros` is not stable
+ trace_macros!(1); //~ ERROR `trace_macros` is not stable
+ trace_macros!(ident); //~ ERROR `trace_macros` is not stable
+ trace_macros!(for); //~ ERROR `trace_macros` is not stable
+ trace_macros!(true,); //~ ERROR `trace_macros` is not stable
+ trace_macros!(false 1); //~ ERROR `trace_macros` is not stable
+
+ // Errors are signalled early for the above, before expansion.
+ // See trace_macros-gate2 and trace_macros-gate3. for examples
+ // of the below being caught.
+
+ macro_rules! expando {
+ ($x: ident) => { trace_macros!($x) }
+ }
+
+ expando!(true);
+}
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that the trace_macros feature gate is on.
+
+fn main() {
+ // (Infrastructure does not attempt to detect uses in macro definitions.)
+ macro_rules! expando {
+ ($x: ident) => { trace_macros!($x) }
+ }
+
+ expando!(true); //~ ERROR `trace_macros` is not stable
+}
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that the trace_macros feature gate is on.
+
+pub fn main() {
+ println!("arg: {}", trace_macros!()); //~ ERROR `trace_macros` is not stable
+ println!("arg: {}", trace_macros!(1)); //~ ERROR `trace_macros` is not stable
+ println!("arg: {}", trace_macros!(ident)); //~ ERROR `trace_macros` is not stable
+ println!("arg: {}", trace_macros!(for)); //~ ERROR `trace_macros` is not stable
+ println!("arg: {}", trace_macros!(true,)); //~ ERROR `trace_macros` is not stable
+ println!("arg: {}", trace_macros!(false 1)); //~ ERROR `trace_macros` is not stable
+}
+++ /dev/null
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// ignore-tidy-cr
-// Issue #11669
-
-fn main() {
- // \r\n
- let ok = "This is \
- a test";
- // \r only
- let bad = "This is \\r a test";
- //~^ ERROR unknown character escape: \r
- //~^^ HELP this is an isolated carriage return
-
-}
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use std::fmt::Show;
-
-fn main() {
- let x: Box<Show+> = box 3 as Box<Show+>;
- //~^ ERROR at least one type parameter bound must be specified
- //~^^ ERROR at least one type parameter bound must be specified
-}
-
fn d(x: Box<Foo>) {
a(x); //~ ERROR mismatched types
//~| expected `Box<Foo + Send>`
- //~| found `Box<Foo + 'static>`
+ //~| found `Box<Foo>`
//~| expected bounds `Send`
//~| found no bounds
}
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-trait Foo {
-}
-
-struct Bar;
-
-impl Foo + Owned for Bar { //~ ERROR not a trait
-}
-
-fn main() { }
+++ /dev/null
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-struct Foo {
- x: isize,
- y: isize,
-}
-
-fn main() {
- let f = Foo {
- x: 1,
- y: 2,
- };
- f.x::<isize>;
- //~^ ERROR field expressions may not have type parameters
-}
-
+++ /dev/null
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// Test syntax checks for `type` keyword.
-
-fn f<X>() {}
-
-pub fn main() {
- f<type>();
- //~^ ERROR expected identifier, found keyword `type`
- //~^^ ERROR: chained comparison
- //~^^^ HELP: use `::<
-}
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
#![deny(unused_attributes)]
#![allow(dead_code, unused_imports)]
-#![feature(core)]
+#![feature(core, custom_attribute)]
#![foo] //~ ERROR unused attribute
// Test that the variance computation considers types/regions that
// appear in projections to be invariant.
+#![feature(rustc_attrs)]
+
trait Trait<'a> {
type Type;
// Test that Cell is considered invariant with respect to its
// type.
+#![feature(rustc_attrs)]
+
use std::cell::Cell;
// For better or worse, associated types are invariant, and hence we
// Test that we correctly infer variance for region parameters in
// various self-contained types.
+#![feature(rustc_attrs)]
+
// Regions that just appear in normal spots are contravariant:
#[rustc_variance]
// case that involve multiple intricate types.
// Try enums too.
+#![feature(rustc_attrs)]
+
#[rustc_variance]
enum Base<'a, 'b, 'c:'b, 'd> { //~ ERROR regions=[[+, -, o, *];[];[]]
Test8A(extern "Rust" fn(&'a isize)),
//
// Issue #18262.
+#![feature(rustc_attrs)]
+
use std::mem;
trait T { fn foo(); }
+++ /dev/null
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// Test diagnostics for the removed struct inheritance feature.
-#![feature(struct_inherit)]
-
-virtual struct SuperStruct { //~ ERROR `virtual` structs have been removed from the language
- f1: isize,
-}
-
-struct Struct : SuperStruct; //~ ERROR `virtual` structs have been removed from the language
-
-pub fn main() {}
+++ /dev/null
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn equal1<T>(_: &T, _: &T) -> bool where {
-//~^ ERROR a `where` clause must have at least one predicate in it
- true
-}
-
-fn equal2<T>(_: &T, _: &T) -> bool where T: {
-//~^ ERROR each predicate in a `where` clause must have at least one bound
- true
-}
-
-fn main() {
-}
-
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// about UTF-32 character encoding and will print a rust char as only
// its numerical value.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// about UTF-32 character encoding and will print a rust char as only
// its numerical value.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// about UTF-32 character encoding and will print a rust char as only
// its numerical value.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// Gdb doesn't know about UTF-32 character encoding and will print a rust char as only
// its numerical value.
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// compile-flags:-g
// min-lldb-version: 310
// except according to those terms.
// ignore-tidy-linelength
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// compile-flags:-g
// min-lldb-version: 310
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// Gdb doesn't know about UTF-32 character encoding and will print a rust char as only
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// except according to those terms.
// ignore-tidy-linelength
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// except according to those terms.
// ignore-tidy-linelength
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// aux-build:cross_crate_debuginfo_type_uniquing.rs
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// This test case checks if function arguments already have the correct value when breaking at the
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// compile-flags:-g
// min-lldb-version: 310
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// except according to those terms.
// ignore-tidy-linelength
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// except according to those terms.
// ignore-tidy-linelength
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// except according to those terms.
// ignore-tidy-linelength
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
::std::io::println(args[0]);
}
-// ignore-android: FIXME(#10381)
// ignore-lldb
// This test case checks whether compile unit names are set correctly, so that the correct default
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// ignore-windows failing on 64-bit bots FIXME #17638
// ignore-lldb
// gdb-command:run
// gdb-command:next
-// gdb-check:[...]34[...]s
+// gdb-check:[...]33[...]s
// gdb-command:continue
#![omit_gdb_pretty_printer_section]
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// aux-build:issue13213aux.rs
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-C debuginfo=1
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// ignore-lldb
// except according to those terms.
// ignore-tidy-linelength
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// LLDB can't handle zero-sized values
// ignore-lldb
-// ignore-android: FIXME(#10381)
// compile-flags:-g
// gdb-command:run
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// ignore-lldb
// compile-flags:-g
// except according to those terms.
// ignore-tidy-linelength
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// except according to those terms.
// ignore-tidy-linelength
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// except according to those terms.
// ignore-tidy-linelength
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// ignore-lldb
// compile-flags:-g
// except according to those terms.
// ignore-tidy-linelength
-// ignore-android: FIXME(#10381)
// ignore-lldb
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// Need a fix for LLDB first...
// ignore-lldb
-// ignore-android: FIXME(#10381)
// compile-flags:-g
// gdb-command:run
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// except according to those terms.
// ignore-tidy-linelength
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// except according to those terms.
// ignore-tidy-linelength
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// except according to those terms.
// ignore-tidy-linelength
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// except according to those terms.
// ignore-tidy-linelength
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// except according to those terms.
// ignore-tidy-linelength
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android: FIXME(#10381)
// min-lldb-version: 310
// compile-flags:-g
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ let x = "\x80"; //~ ERROR may only be used
+ let y = "\xff"; //~ ERROR may only be used
+ let z = "\xe2"; //~ ERROR may only be used
+ let a = b"\x00e2"; // ok because byte literal
+}
+
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[derive(Debug)] //~ERROR expected item after attributes
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ #[attr] //~ ERROR expected item after attributes
+ println!("hi");
+}
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ #[attr] //~ ERROR expected item
+ let _i = 0;
+}
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// error-pattern:expected item
+
+fn f() {
+ #[foo = "bar"]
+ let x = 10;
+}
+
+fn main() {
+}
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// error-pattern:expected item
+
+fn f() {
+ #[foo = "bar"]
+}
+
+fn main() {
+}
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// error-pattern:expected item
+
+fn main() {
+}
+
+#[foo = "bar"]
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(lang_items)]
+
+fn main() {}
+
+#![lang(foo)] //~ ERROR an inner attribute is not permitted in this context
+fn foo() {}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Constants (static variables) can be used to match in patterns, but mutable
+// statics cannot. This ensures that there's some form of error if this is
+// attempted.
+
+extern crate libc;
+
+extern {
+ static mut rust_dbg_static_mut: libc::c_int;
+ pub fn rust_dbg_static_mut_check_four();
+ #[cfg(stage37)] //~ ERROR expected item after attributes
+}
+
+pub fn main() {}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-tidy-cr
+// ignore-tidy-tab
+fn main() {
+ // these literals are just silly.
+ ''';
+ //~^ ERROR: character constant must be escaped: \'
+
+ // note that this is a literal "\n" byte
+ '
+';
+ //~^^ ERROR: character constant must be escaped: \n
+
+ // note that this is a literal "\r" byte
+ '\r'; //~ ERROR: character constant must be escaped: \r
+
+ // note that this is a literal tab character here
+ ' ';
+ //~^ ERROR: character constant must be escaped: \t
+}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+
+extern crate
+ "foo"suffix //~ ERROR extern crate name with a suffix is illegal
+ as foo;
+
+extern
+ "C"suffix //~ ERROR ABI spec with a suffix is illegal
+ fn foo() {}
+
+extern
+ "C"suffix //~ ERROR ABI spec with a suffix is illegal
+{}
+
+fn main() {
+ ""suffix; //~ ERROR str literal with a suffix is illegal
+ b""suffix; //~ ERROR binary str literal with a suffix is illegal
+ r#""#suffix; //~ ERROR str literal with a suffix is illegal
+ br#""#suffix; //~ ERROR binary str literal with a suffix is illegal
+ 'a'suffix; //~ ERROR char literal with a suffix is illegal
+ b'a'suffix; //~ ERROR byte literal with a suffix is illegal
+
+ 1234u1024; //~ ERROR illegal width `1024` for integer literal
+ 1234i1024; //~ ERROR illegal width `1024` for integer literal
+ 1234f1024; //~ ERROR illegal width `1024` for float literal
+ 1234.5f1024; //~ ERROR illegal width `1024` for float literal
+
+ 1234suffix; //~ ERROR illegal suffix `suffix` for numeric literal
+ 0b101suffix; //~ ERROR illegal suffix `suffix` for numeric literal
+ 1.0suffix; //~ ERROR illegal suffix `suffix` for float literal
+ 1.0e10suffix; //~ ERROR illegal suffix `suffix` for float literal
+}
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn false() { } //~ ERROR expected identifier, found keyword `false`
+fn main() { }
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn true() { } //~ ERROR expected identifier, found keyword `true`
+fn main() { }
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/// hi
+#[derive(Debug)] //~ERROR expected item after attributes
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/// hi //~ERROR expected item after doc comment
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+extern {
+ /// hi
+}
+//~^^ ERROR expected item after doc comment
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ /// hi
+ println!("hi");
+ //~^^ ERROR expected item after doc comment
+}
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ println!("Hi"); /// hi
+ //~^ ERROR expected item after doc comment
+}
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ /// hi
+ ;
+ //~^^ ERROR expected item after doc comment
+}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Tests that the proper help is displayed in the error message
+
+extern crate foo as bar;
+//~^ ERROR expected `;`, found `as`
+//~^^ HELP perhaps you meant to enclose the crate name `foo` in a string?
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+struct Heap;
+
+struct Vec<A = Heap, T>; //~ ERROR type parameters with a default must be trailing
+
+struct Foo<A, B = Vec<C>, C>; //~ ERROR type parameters with a default must be trailing
+
+fn main() {}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// issue #17123
+
+fn main() {
+ 100000000000000000000000000000000 //~ ERROR int literal is too large
+
+ ; // the span shouldn't point to this.
+}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+
+trait Serializable<'self, T> { //~ ERROR no longer a special lifetime
+ fn serialize(val : &'self T) -> Vec<u8> ; //~ ERROR no longer a special lifetime
+ fn deserialize(repr : &[u8]) -> &'self T; //~ ERROR no longer a special lifetime
+}
+
+impl<'self> Serializable<str> for &'self str { //~ ERROR no longer a special lifetime
+ //~^ ERROR no longer a special lifetime
+ fn serialize(val : &'self str) -> Vec<u8> { //~ ERROR no longer a special lifetime
+ vec!(1)
+ }
+ fn deserialize(repr: &[u8]) -> &'self str { //~ ERROR no longer a special lifetime
+ "hi"
+ }
+}
+
+fn main() {
+ println!("hello");
+ let x = "foo".to_string();
+ let y = x;
+ println!("{}", y);
+}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// For style and consistency reasons, non-parametrized enum variants must
+// be used simply as `ident` instead of `ident ()`.
+// This test-case covers enum declaration.
+
+enum Foo {
+ Bar(), //~ ERROR nullary enum variants are written with no trailing `( )`
+ Baz(), //~ ERROR nullary enum variants are written with no trailing `( )`
+ Bazar
+}
+
+fn main() {
+ println!("{}", match Bar { Bar => 1, Baz => 2, Bazar => 3 })
+}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-test FIXME(japari) remove test
+
+struct Foo {
+ f: for <'b> |&'b isize|:
+ 'b -> &'b isize //~ ERROR use of undeclared lifetime name `'b`
+}
+
+fn main() {
+ let mut x: Vec< for <'a> ||
+ :'a //~ ERROR use of undeclared lifetime name `'a`
+ > = Vec::new();
+ x.push(|| {});
+
+ let foo = Foo {
+ f: |x| x
+ };
+}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+enum X {
+ A =
+ b'a' //~ ERROR discriminator values can only be used with a c-like enum
+ ,
+ B(isize)
+}
+
+fn main() {}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+const
+mut //~ ERROR: const globals cannot be mutable
+//~^ HELP did you mean to declare a static?
+FOO: usize = 3;
+
+fn main() {
+}
+
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// error-pattern:no valid digits found for number
+fn main() {
+ log(error, 0bu);
+}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ let _i = 18446744073709551616; // 2^64
+ //~^ ERROR int literal is too large
+}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ let _i = 0xff_ffff_ffff_ffff_ffff_is;
+ //~^ ERROR int literal is too large
+}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub extern
+ "invalid-abi" //~ ERROR illegal ABI
+fn foo() {}
+
+fn main() {}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py as'
+
+fn main() {
+ let as = "foo"; //~ error: ident
+}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py break'
+
+fn main() {
+ let break = "foo"; //~ error: ident
+}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py else'
+
+fn main() {
+ let else = "foo"; //~ error: ident
+}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py enum'
+
+fn main() {
+ let enum = "foo"; //~ error: ident
+}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py extern'
+
+fn main() {
+ let extern = "foo"; //~ error: ident
+}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py fn'
+
+fn main() {
+ let fn = "foo"; //~ error: ident
+}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py for'
+
+fn main() {
+ let for = "foo"; //~ error: ident
+}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py if'
+
+fn main() {
+ let if = "foo"; //~ error: ident
+}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py impl'
+
+fn main() {
+ let impl = "foo"; //~ error: ident
+}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py let'
+
+fn main() {
+ let let = "foo"; //~ error: ident
+}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py loop'
+
+fn main() {
+ let loop = "foo"; //~ error: ident
+}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py match'
+
+fn main() {
+ let match = "foo"; //~ error: ident
+}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py mod'
+
+fn main() {
+ let mod = "foo"; //~ error: ident
+}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py pub'
+
+fn main() {
+ let pub = "foo"; //~ error: ident
+}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py return'
+
+fn main() {
+ let return = "foo"; //~ error: ident
+}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py self'
+
+fn main() {
+ let self = "foo"; //~ error: ident
+}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py static'
+
+fn main() {
+ let static = "foo"; //~ error: ident
+}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py struct'
+
+fn main() {
+ let struct = "foo"; //~ error: ident
+}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py super'
+
+fn main() {
+ let super = "foo"; //~ error: ident
+}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ let super: isize; //~ ERROR expected identifier, found keyword `super`
+}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py trait'
+
+fn main() {
+ let trait = "foo"; //~ error: ident
+}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py type'
+
+fn main() {
+ let type = "foo"; //~ error: ident
+}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py unsafe'
+
+fn main() {
+ let unsafe = "foo"; //~ error: ident
+}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py use'
+
+fn main() {
+ let use = "foo"; //~ error: ident
+}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py while'
+
+fn main() {
+ let while = "foo"; //~ error: ident
+}
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub mod break {
+ //~^ ERROR expected identifier, found keyword `break`
+}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ struct::foo(); //~ ERROR expected identifier
+ mut::baz(); //~ ERROR expected identifier
+}
+
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ 0o1.0; //~ ERROR: octal float literal is not supported
+ 0o2f32; //~ ERROR: octal float literal is not supported
+ 0o3.0f32; //~ ERROR: octal float literal is not supported
+ 0o4e4; //~ ERROR: octal float literal is not supported
+ 0o5.0e5; //~ ERROR: octal float literal is not supported
+ 0o6e6f32; //~ ERROR: octal float literal is not supported
+ 0o7.0e7f64; //~ ERROR: octal float literal is not supported
+ 0x8.0e+9; //~ ERROR: hexadecimal float literal is not supported
+ 0x9.0e-9; //~ ERROR: hexadecimal float literal is not supported
+ 0o; //~ ERROR: no valid digits
+ 1e+; //~ ERROR: expected at least one digit in exponent
+ 0x539.0; //~ ERROR: hexadecimal float literal is not supported
+ 99999999999999999999999999999999; //~ ERROR: int literal is too large
+ 99999999999999999999999999999999u32; //~ ERROR: int literal is too large
+ 0x; //~ ERROR: no valid digits
+ 0xu32; //~ ERROR: no valid digits
+ 0ou32; //~ ERROR: no valid digits
+ 0bu32; //~ ERROR: no valid digits
+ 0b; //~ ERROR: no valid digits
+ 0o123f64; //~ ERROR: octal float literal is not supported
+ 0o123.456; //~ ERROR: octal float literal is not supported
+ 0b101f64; //~ ERROR: binary float literal is not supported
+ 0b111.101; //~ ERROR: binary float literal is not supported
+}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-tidy-cr
+
+/// doc comment with bare CR: '\r'
+pub fn foo() {}
+//~^^ ERROR: bare CR not allowed in doc-comment
+
+/** block doc comment with bare CR: '\r' */
+pub fn bar() {}
+//~^^ ERROR: bare CR not allowed in block doc-comment
+
+fn main() {
+ // the following string literal has a bare CR in it
+ let _s = "foo\rbar"; //~ ERROR: bare CR not allowed in string
+
+ // the following string literal has a bare CR in it
+ let _s = r"bar\rfoo"; //~ ERROR: bare CR not allowed in raw string
+
+ // the following string literal has a bare CR in it
+ let _s = "foo\\rbar"; //~ ERROR: unknown character escape: \r
+}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn foo<'a>(a: &'a isize) { }
+fn bar(a: &'static isize) { }
+fn baz(a: &'let isize) { } //~ ERROR invalid lifetime name
+
+fn main() { }
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn baz(a: &'self isize) { } //~ ERROR invalid lifetime name: 'self is no longer a special lifetime
+
+fn main() { }
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+macro_rules! foo() //~ ERROR semicolon
+
+fn main() {
+}
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-mod mod_file_disambig_aux; //~ ERROR file for module `mod_file_disambig_aux` found at both
-
-fn main() {
- assert_eq!(mod_file_aux::bar(), 10);
-}
+++ /dev/null
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// error-pattern: cannot declare a new module at this location
-
-mod mod_file_not_owning_aux1;
-
-fn main() {}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// error-pattern:binary float literal is not supported
+
+fn main() {
+ 0b101010f64;
+ 0b101.010;
+ 0b101p4f64;
+}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// error-pattern:hexadecimal float literal is not supported
+
+fn main() {
+ 0xABC.Df;
+ 0x567.89;
+ 0xDEAD.BEEFp-2f;
+}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait A {
+ fn foo(*mut self); //~ ERROR cannot pass self by unsafe pointer
+ fn bar(*self); //~ ERROR cannot pass self by unsafe pointer
+}
+
+struct X;
+impl A for X {
+ fn foo(*mut self) { } //~ ERROR cannot pass self by unsafe pointer
+ fn bar(*self) { } //~ ERROR cannot pass self by unsafe pointer
+}
+
+fn main() { }
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Issue #623 - non-string meta items are not serialized correctly;
+// for now just forbid them
+
+#[foo = 1] //~ ERROR: non-string literals are not allowed in meta-items
+fn main() { }
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that we generate obsolete syntax errors around usages of `for Sized?`
+
+trait Foo for Sized? {} //~ ERROR obsolete syntax: for Sized?
+
+trait Bar for ?Sized {} //~ ERROR obsolete syntax: for Sized?
+
+fn main() { }
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that we generate obsolete syntax errors around usages of `proc`.
+
+fn foo(p: proc()) { } //~ ERROR obsolete syntax: the `proc` type
+
+fn bar() { proc() 1; } //~ ERROR obsolete syntax: `proc` expression
+
+fn main() { }
--- /dev/null
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-test Can't use syntax crate here
+
+#![feature(quote)]
+
+extern crate syntax;
+
+use io::*;
+
+use syntax::diagnostic;
+use syntax::ast;
+use syntax::codemap;
+use syntax::parse;
+use syntax::print::*;
+
+
+trait fake_ext_ctxt {
+ fn cfg() -> ast::CrateConfig;
+ fn parse_sess() -> parse::parse_sess;
+ fn call_site() -> span;
+ fn ident_of(st: &str) -> ast::ident;
+}
+
+type fake_session = parse::parse_sess;
+
+impl fake_ext_ctxt for fake_session {
+ fn cfg() -> ast::CrateConfig { Vec::new() }
+ fn parse_sess() -> parse::parse_sess { self }
+ fn call_site() -> span {
+ codemap::span {
+ lo: codemap::BytePos(0),
+ hi: codemap::BytePos(0),
+ expn_id: NO_EXPANSION
+ }
+ }
+ fn ident_of(st: &str) -> ast::ident {
+ self.interner.intern(st)
+ }
+}
+
+fn mk_ctxt() -> fake_ext_ctxt {
+ parse::new_parse_sess(None) as fake_ext_ctxt
+}
+
+
+
+fn main() {
+ let cx = mk_ctxt();
+
+ let abc = quote_expr!(cx, 23);
+ check_pp(abc, pprust::print_expr, "23");
+
+ let expr3 = quote_expr!(cx, 2 - $abcd + 7); //~ ERROR unresolved name: abcd
+ check_pp(expr3, pprust::print_expr, "2 - 23 + 7");
+}
+
+fn check_pp<T>(expr: T, f: |pprust::ps, T|, expect: str) {
+ panic!();
+}
--- /dev/null
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-test Can't use syntax crate here
+
+#![feature(quote)]
+
+extern crate syntax;
+
+use syntax::diagnostic;
+use syntax::ast;
+use syntax::codemap;
+use syntax::parse::parser;
+use syntax::print::*;
+
+trait fake_ext_ctxt {
+ fn cfg() -> ast::CrateConfig;
+ fn parse_sess() -> parse::parse_sess;
+ fn call_site() -> span;
+ fn ident_of(st: &str) -> ast::ident;
+}
+
+type fake_session = parse::parse_sess;
+
+impl fake_ext_ctxt for fake_session {
+ fn cfg() -> ast::CrateConfig { Vec::new() }
+ fn parse_sess() -> parse::parse_sess { self }
+ fn call_site() -> span {
+ codemap::span {
+ lo: codemap::BytePos(0),
+ hi: codemap::BytePos(0),
+ expn_id: codemap::NO_EXPANSION
+ }
+ }
+ fn ident_of(st: &str) -> ast::ident {
+ self.interner.intern(st)
+ }
+}
+
+fn mk_ctxt() -> fake_ext_ctxt {
+ parse::new_parse_sess(None) as fake_ext_ctxt
+}
+
+
+fn main() {
+ let cx = mk_ctxt();
+
+ let stmt = quote_stmt!(cx, let x isize = 20;); //~ ERROR expected end-of-string
+ check_pp(*stmt, pprust::print_stmt, "");
+}
+
+fn check_pp<T>(expr: T, f: |pprust::ps, T|, expect: str) {
+ panic!();
+}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-test
+// ignored because the first error does not show up.
+
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn of<T>() -> |T| { panic!(); }
+fn subtype<T>(x: |T|) { panic!(); }
+
+fn test_fn<'x, 'y, 'z, T>(_x: &'x T, _y: &'y T, _z: &'z T) {
+ // Here, x, y, and z are free. Other letters
+ // are bound. Note that the arrangement
+ // subtype::<T1>(of::<T2>()) will typecheck
+ // iff T1 <: T2.
+
+ // should be the default:
+ subtype::< ||:'static>(of::<||>());
+ subtype::<||>(of::< ||:'static>());
+
+ //
+ subtype::< <'x> ||>(of::<||>()); //~ ERROR mismatched types
+ subtype::< <'x> ||>(of::< <'y> ||>()); //~ ERROR mismatched types
+
+ subtype::< <'x> ||>(of::< ||:'static>()); //~ ERROR mismatched types
+ subtype::< ||:'static>(of::< <'x> ||>());
+
+}
+
+fn main() {}
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn f<T>() {}
+
+fn main() {
+ false == false == false;
+ //~^ ERROR: chained comparison operators require parentheses
+
+ false == 0 < 2;
+ //~^ ERROR: chained comparison operators require parentheses
+
+ f<X>();
+ //~^ ERROR: chained comparison operators require parentheses
+ //~^^ HELP: use `::<...>` instead of `<...>`
+}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+struct Foo;
+
+fn f2() {
+ let _end_stmt = Foo { };
+ //~^ ERROR: structure literal must either have at least one field
+}
+
+fn main() {}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+struct Foo;
+
+fn g3() {
+ let _mid_tuple = (Foo { }, 2);
+ //~^ ERROR: structure literal must either have at least one field
+}
+
+fn main() {}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+struct Foo;
+
+fn h4() {
+ let _end_of_tuple = (3, Foo { });
+ //~^ ERROR: structure literal must either have at least one field
+}
+
+fn main() {}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+struct Foo;
+
+fn i5() {
+ let _end_of_block = { Foo { } };
+ //~^ ERROR: structure literal must either have at least one field
+}
+
+fn main() {}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+enum Foo {
+ Bar {} //~ ERROR unit-like struct variant should be written without braces, as `Bar,`
+}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+enum Foo {
+ Bar {
+ pub a: isize //~ ERROR: `pub` is not allowed here
+ }
+}
+
+fn main() {}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(optin_builtin_traits)]
+
+use std::marker::Send;
+
+struct TestType;
+
+impl !TestType {}
+//~^ ERROR inherent implementation can't be negated
+
+trait TestTrait {}
+
+unsafe impl !Send for TestType {}
+impl !TestTrait for TestType {}
+
+struct TestType2<T>;
+
+impl<T> !TestType2<T> {}
+//~^ ERROR inherent implementation can't be negated
+
+unsafe impl<T> !Send for TestType2<T> {}
+impl<T> !TestTrait for TestType2<T> {}
+
+fn main() {}
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//error-pattern: discriminator values can only be used with a c-like enum
+
+enum color {
+ red = 0xff0000,
+ green = 0x00ff00,
+ blue = 0x0000ff,
+ black = 0x000000,
+ white = 0xffffff,
+ other (str),
+}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-tidy-cr
+// Issue #11669
+
+fn main() {
+ // \r\n
+ let ok = "This is \
+ a test";
+ // \r only
+ let bad = "This is \\r a test";
+ //~^ ERROR unknown character escape: \r
+ //~^^ HELP this is an isolated carriage return
+
+}
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::fmt::Show;
+
+fn main() {
+ let x: Box<Show+> = box 3 as Box<Show+>;
+ //~^ ERROR at least one type parameter bound must be specified
+ //~^^ ERROR at least one type parameter bound must be specified
+}
+
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait Foo {
+}
+
+struct Bar;
+
+impl Foo + Owned for Bar { //~ ERROR not a trait
+}
+
+fn main() { }
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+struct Foo {
+ x: isize,
+ y: isize,
+}
+
+fn main() {
+ let f = Foo {
+ x: 1,
+ y: 2,
+ };
+ f.x::<isize>;
+ //~^ ERROR field expressions may not have type parameters
+}
+
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test syntax checks for `type` keyword.
+
+fn f<X>() {}
+
+pub fn main() {
+ f<type>();
+ //~^ ERROR expected identifier, found keyword `type`
+ //~^^ ERROR: chained comparison
+ //~^^^ HELP: use `::<
+}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test diagnostics for the removed struct inheritance feature.
+#![feature(struct_inherit)]
+
+virtual struct SuperStruct { //~ ERROR `virtual` structs have been removed from the language
+ f1: isize,
+}
+
+struct Struct : SuperStruct; //~ ERROR `virtual` structs have been removed from the language
+
+pub fn main() {}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn equal1<T>(_: &T, _: &T) -> bool where {
+//~^ ERROR a `where` clause must have at least one predicate in it
+ true
+}
+
+fn equal2<T>(_: &T, _: &T) -> bool where T: {
+//~^ ERROR each predicate in a `where` clause must have at least one bound
+ true
+}
+
+fn main() {
+}
+
// preserved, and that the first outer item parsed in main is not
// accidentally carried over to each inner function
+#![feature(custom_attribute)]
+
fn main() {
#![inner_attr]
#[outer_attr]
// error-pattern:thread '<unnamed>' panicked at 'test'
-use std::thread::Thread;
+use std::thread;
fn main() {
- let r: Result<int,_> = Thread::scoped(move|| {
+ let r: Result<(),_> = thread::spawn(move|| {
panic!("test");
- 1
}).join();
assert!(r.is_ok());
}
use std::thread::Builder;
fn main() {
- let r: Result<int,_> = Builder::new().name("owned name".to_string()).scoped(move|| {
+ let r: () = Builder::new().name("owned name".to_string()).scoped(move|| {
panic!("test");
- 1
- }).join();
- assert!(r.is_ok());
+ ()
+ }).unwrap().join();
+ panic!();
}
#[macro_use] extern crate log;
use std::os;
-use std::thread::Thread;
+use std::thread;
struct r {
x:int,
fn main() {
error!("whatever");
- let _t = Thread::spawn(move|| {
+ let _t = thread::spawn(move|| {
let _i = r(5);
});
panic!();
// error-pattern:Ensure that the child task runs by panicking
-use std::thread::Thread;
+use std::thread;
fn main() {
// the purpose of this test is to make sure that task::spawn()
// works when provided with a bare function:
- let r = Thread::scoped(startfn).join();
+ let r = thread::spawn(startfn).join();
if r.is_err() {
panic!()
}
// error-pattern:nonzero
// exec-env:RUST_NEWRT=1
-use std::os;
+use std::env;
fn main() {
- os::args();
+ env::args();
panic!("please have a nonzero exit status");
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use std::os;
+use std::env;
use std::old_io::{File, Command};
// creates broken.rs, which has the Ident \x00name_0,ctxt_0\x00
// provided `rustc`
fn main() {
- let args = os::args();
+ let args: Vec<String> = env::args().collect();
let rustc = &args[1];
let tmpdir = Path::new(&args[2]);
fn main() {}
"#;
- let args = std::os::args();
+ let args: Vec<String> = std::env::args().collect();
if args.len() < 4 {
panic!("expected rustc path");
#![crate_type = "rlib"]
-pub static mut statik: int = 0;
+pub static mut statik: isize = 0;
struct A;
impl Drop for A {
extern crate lib;
-use std::thread::Thread;
+use std::thread;
-static mut statik: int = 0;
+static mut statik: isize = 0;
struct A;
impl Drop for A {
}
fn main() {
- Thread::scoped(move|| {
+ thread::spawn(move|| {
let _a = A;
lib::callback(|| panic!());
- 1
}).join().err().unwrap();
unsafe {
"data-layout": "e-p:32:32-f64:32:64-i64:32:64-f80:32:32-n8:16:32",
"llvm-target": "i686-unknown-linux-gnu",
"target-endian": "little",
- "target-word-size": "32",
+ "target-pointer-width": "32",
"arch": "x86",
"os": "linux",
"morestack": false
{
"data-layout": "e-p:32:32-f64:32:64-i64:32:64-f80:32:32-n8:16:32",
"target-endian": "little",
- "target-word-size": "32",
+ "target-pointer-width": "32",
"arch": "x86",
"os": "foo",
"morestack": false
"data-layout": "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128",
"llvm-target": "x86_64-unknown-linux-gnu",
"target-endian": "little",
- "target-word-size": "64",
+ "target-pointer-width": "64",
"arch": "x86_64",
"os": "linux",
"morestack": false
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use std::{char, os};
+use std::{char, env};
use std::old_io::{File, Command};
use std::rand::{thread_rng, Rng};
}
fn main() {
- let args = os::args();
+ let args: Vec<String> = env::args().collect();
let rustc = &args[1];
let tmpdir = Path::new(&args[2]);
use std::old_io::{File, Command};
use std::iter::repeat;
use std::rand::{thread_rng, Rng};
-use std::{char, os};
+use std::{char, env};
// creates a file with `fn main() { <random ident> }` and checks the
// compiler emits a span of the appropriate length (for the
}
fn main() {
- let args = os::args();
+ let args: Vec<String> = env::args().collect();
let rustc = &args[1];
let tmpdir = Path::new(&args[2]);
let main_file = tmpdir.join("span_main.rs");
// except according to those terms.
// ignore-stage1
-// ignore-android
// aux-build:issue_16723_multiple_items_syntax_ext.rs
#![feature(plugin)]
#![plugin(issue_16723_multiple_items_syntax_ext)]
// error-pattern:expected item
+#![feature(custom_attribute)]
+
#[foo = "bar"]
extern crate test;
// error-pattern:expected item
+#![feature(custom_attribute)]
+
mod m {
#[foo = "bar"]
extern crate test;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![allow(unused_attribute)]
+#![feature(custom_attribute)]
#[foo(bar)]
mod foo {
#![feature(unboxed_closures)]
#![feature(unsafe_destructor)]
-use std::os;
use std::env;
use std::old_io::process::Command;
use std::str;
}
fn main() {
- let args = os::args();
- let args = args;
+ let args: Vec<String> = env::args().collect();
if args.len() >= 2 && args[1] == "fail" {
foo();
} else if args.len() >= 2 && args[1] == "double-fail" {
impl <T: Send> Foo for T { }
impl <T: Send> Bar for T { }
-fn foo<T: Foo>(val: T, chan: Sender<T>) {
+fn foo<T: Foo + 'static>(val: T, chan: Sender<T>) {
chan.send(val).unwrap();
}
impl <T: Sync> RequiresShare for X<T> { }
impl <T: Sync+Send> RequiresRequiresShareAndSend for X<T> { }
-fn foo<T: RequiresRequiresShareAndSend>(val: T, chan: Sender<T>) {
+fn foo<T: RequiresRequiresShareAndSend + 'static>(val: T, chan: Sender<T>) {
chan.send(val).unwrap();
}
impl <T: Send> Foo for T { }
-fn foo<T: Foo>(val: T, chan: Sender<T>) {
+fn foo<T: Foo + 'static>(val: T, chan: Sender<T>) {
chan.send(val).unwrap();
}
use std::sync::mpsc::{Sender, channel};
-trait Foo : Send + Sized {
+trait Foo : Send + Sized + 'static {
fn foo(self, tx: Sender<Self>) {
tx.send(self).unwrap();
}
}
-impl <T: Send> Foo for T { }
+impl <T: Send + 'static> Foo for T { }
pub fn main() {
let (tx, rx) = channel();
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android (FIXME #11419)
// exec-env:RUST_LOG=info
#![allow(unknown_features)]
// Static recursion check shouldn't fail when given a foreign item (#18279)
// aux-build:check_static_recursion_foreign_helper.rs
+
+#![feature(custom_attribute)]
+
extern crate check_static_recursion_foreign_helper;
extern crate libc;
// pp-exact - Make sure we actually print the attributes
#![allow(unused_attribute)]
+#![feature(custom_attribute)]
struct cat {
name: String,
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![allow(unused_attribute)]
+#![feature(custom_attribute)]
struct cat {
name: String,
#![allow(unknown_features)]
#![feature(box_syntax)]
-use std::thread::Thread;
+use std::thread;
enum Conzabble {
Bickwick(Foo)
}
pub fn main() {
- Thread::scoped(fails).join();
+ thread::spawn(fails).join();
}
// Test that cleanups for the RHS of shortcircuiting operators work.
-use std::os;
+use std::env;
pub fn main() {
- let args = os::args();
- let args = args;
+ let args: Vec<String> = env::args().collect();
// Here, the rvalue `"signal".to_string()` requires cleanup. Older versions
// of the code had a problem that the cleanup scope for this
struct Bar;
-impl fmt::Writer for Bar {
+impl fmt::Write for Bar {
fn write_str(&mut self, _: &str) -> fmt::Result {
Ok(())
}
let mut s = Bar;
{
- use std::fmt::Writer;
+ use std::fmt::Write;
write!(&mut s, "test");
}
}
#![allow(unknown_features)]
#![feature(box_syntax)]
-use std::thread::Thread;
+use std::thread;
use std::sync::mpsc::{channel, Sender};
#[derive(PartialEq, Debug)]
assert_eq!(receiver.recv().ok(), None);
let (sender, receiver) = channel();
- let _t = Thread::scoped(move|| {
+ let t = thread::spawn(move|| {
let v = Foo::FailingVariant { on_drop: SendOnDrop { sender: sender } };
});
assert_eq!(receiver.recv().unwrap(), Message::Dropped);
assert_eq!(receiver.recv().ok(), None);
+ drop(t.join());
let (sender, receiver) = channel();
- let _t = {
- Thread::scoped(move|| {
+ let t = {
+ thread::spawn(move|| {
let mut v = Foo::NestedVariant(box 42u, SendOnDrop {
sender: sender.clone()
}, sender.clone());
assert_eq!(receiver.recv().unwrap(), Message::DestructorRan);
assert_eq!(receiver.recv().unwrap(), Message::Dropped);
assert_eq!(receiver.recv().ok(), None);
+ drop(t.join());
}
extern crate libc;
use std::mem;
-use std::thread::Thread;
+use std::thread;
#[link(name = "rust_test_helpers")]
extern {
pub fn main() {
unsafe {
- Thread::scoped(move|| {
- let i = &100;
- rust_dbg_call(callback, mem::transmute(i));
+ thread::spawn(move|| {
+ let i = 100;
+ rust_dbg_call(callback, mem::transmute(&i));
}).join();
}
}
}
// Basic test to make sure that we can invoke the `write!` macro with an
-// io::Writer instance.
+// fmt::Write instance.
fn test_write() {
- use std::fmt::Writer;
+ use std::fmt::Write;
let mut buf = String::new();
write!(&mut buf, "{}", 3);
{
// Just make sure that the macros are defined, there's not really a lot that we
// can do with them just yet (to test the output)
fn test_format_args() {
- use std::fmt::Writer;
+ use std::fmt::Write;
let mut buf = String::new();
{
let w = &mut buf;
#[cfg(target_os = "android")]
mod m {
#[main]
- #[cfg(target_arch = "arm")]
+ #[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
pub fn main() {
unsafe {
assert_eq!(::rusti::pref_align_of::<u64>(), 8u);
// Make sure that if a process doesn't have its stdio/stderr descriptors set up
// that we don't die in a large ball of fire
-use std::os;
+use std::env;
use std::old_io::process;
pub fn main () {
- let args = os::args();
- let args = args;
+ let args: Vec<String> = env::args().collect();
if args.len() > 1 && args[1] == "child" {
for _ in 0..1000 {
println!("hello?");
// except according to those terms.
use std::time::Duration;
-use std::thread::Thread;
+use std::thread;
fn main() {
- Thread::scoped(move|| customtask()).join().ok().unwrap();
+ thread::spawn(move|| customtask()).join().ok().unwrap();
}
fn customtask() {
// ignore-fast
-use std::os;
+use std::env;
use std::old_io;
use std::str;
fn main() {
- let args = os::args();
- let args = args;
+ let args: Vec<String> = env::args().collect();
if args.len() > 1 && args[1] == "child" {
child();
} else {
}
fn parent() {
- let args = os::args();
- let args = args;
+ let args: Vec<String> = env::args().collect();
let mut p = old_io::process::Command::new(&args[0])
.arg("child").spawn().unwrap();
p.stdin.as_mut().unwrap().write_str("test1\ntest2\ntest3").unwrap();
use std::old_io::process;
use std::old_io::Command;
use std::old_io;
-use std::os;
+use std::env;
fn main() {
- let args = os::args();
+ let args: Vec<String> = env::args().collect();
if args.len() > 1 && args[1] == "child" {
return child()
}
}
fn test() {
- let args = os::args();
+ let args: Vec<String> = env::args().collect();
let mut p = Command::new(&args[0]).arg("child")
.stdin(process::Ignored)
.stdout(process::Ignored)
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use std::os;
+use std::env;
use std::old_io::{stdio, Command};
fn main() {
- let args = os::args();
+ let mut args = env::args();
if args.len() > 1 {
let mut out = stdio::stdout();
out.write(&['a' as u8; 128 * 1024]).unwrap();
} else {
- let out = Command::new(&args[0]).arg("child").output();
+ let out = Command::new(&args.next().unwrap()).arg("child").output();
let out = out.unwrap();
assert!(out.status.success());
}
// except according to those terms.
use std::slice::SliceExt;
-use std::old_io::{Command, fs, USER_RWX};
-use std::os;
+use std::old_io::{fs, USER_RWX};
+use std::process;
use std::env;
use std::old_path::BytesContainer;
use std::rand::random;
fn main() {
// If we're the child, make sure we were invoked correctly
- let args = os::args();
+ let args: Vec<String> = env::args().collect();
if args.len() > 1 && args[1] == "child" {
// FIXME: This should check the whole `args[0]` instead of just
// checking that it ends_with the executable name. This
// is needed because of Windows, which has a different behavior.
// See #15149 for more info.
- return assert!(args[0].ends_with(&format!("mytest{}", os::consts::EXE_SUFFIX)[]));
+ return assert!(args[0].ends_with(&format!("mytest{}", env::consts::EXE_SUFFIX)[]));
}
test();
fn test() {
// If we're the parent, copy our own binary to a new directory.
- let my_path = os::self_exe_name().unwrap();
+ let my_path = env::current_exe().unwrap();
let my_dir = my_path.dir_path();
let random_u32: u32 = random();
fs::mkdir(&child_dir, USER_RWX).unwrap();
let child_path = child_dir.join(format!("mytest{}",
- os::consts::EXE_SUFFIX));
+ env::consts::EXE_SUFFIX));
fs::copy(&my_path, &child_path).unwrap();
// Append the new directory to our own PATH.
- let mut path = os::split_paths(env::var("PATH").ok().unwrap_or(String::new()));
- path.push(child_dir.clone());
- let path = os::join_paths(&path).unwrap();
+ let path = {
+ let mut paths: Vec<_> = env::split_paths(&env::var_os("PATH").unwrap()).collect();
+ paths.push(child_dir.clone());
+ env::join_paths(paths.iter()).unwrap()
+ };
- let child_output = Command::new("mytest").env("PATH", path)
- .arg("child")
- .output().unwrap();
+ let child_output = process::Command::new("mytest").env("PATH", &path)
+ .arg("child")
+ .output().unwrap();
assert!(child_output.status.success(),
format!("child assertion failed\n child stdout:\n {}\n child stderr:\n {}",
- child_output.output.container_as_str().unwrap(),
- child_output.error.container_as_str().unwrap()));
+ child_output.stdout.container_as_str().unwrap(),
+ child_output.stderr.container_as_str().unwrap()));
fs::rmdir_recursive(&child_dir).unwrap();
// except according to those terms.
use std::old_io::{process, Command};
-use std::os;
+use std::env;
fn main() {
- let len = os::args().len();
+ let len = env::args().len();
if len == 1 {
test();
}
fn test() {
- let status = Command::new(os::self_exe_name().unwrap())
+ let status = Command::new(env::current_exe().unwrap())
.arg("foo").arg("")
.stdout(process::InheritFd(1))
.stderr(process::InheritFd(2))
#![feature(unboxed_closures)]
-use std::thread::Thread;
+use std::thread;
use std::mem;
fn main() {
// Check that both closures are capturing by value
assert_eq!(1, mem::size_of_val(&closure));
- Thread::scoped(move|| {
+ thread::spawn(move|| {
let ok = closure;
}).join().ok().unwrap();
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android seems to block forever
#![forbid(warnings)]
// A var moved into a proc, that has a mutable loan path should
// not trigger a misleading unused_mut warning.
-use std::thread::Thread;
+use std::thread;
pub fn main() {
let mut stdin = std::old_io::stdin();
- Thread::spawn(move|| {
+ thread::spawn(move|| {
let _ = stdin.read_to_end();
});
}
pub trait Promisable: Send + Sync {}
impl<T: Send + Sync> Promisable for T {}
-pub fn propagate<T, E, F, G>(action: F) -> Thunk<Result<T, E>, Result<T, E>>
+pub fn propagate<'a, T, E, F, G>(action: F) -> Thunk<'a,Result<T, E>, Result<T, E>>
where
- T: Promisable + Clone,
- E: Promisable + Clone,
- F: FnOnce(&T) -> Result<T, E> + Send,
- G: FnOnce(Result<T, E>) -> Result<T, E> {
+ T: Promisable + Clone + 'a,
+ E: Promisable + Clone + 'a,
+ F: FnOnce(&T) -> Result<T, E> + Send + 'a,
+ G: FnOnce(Result<T, E>) -> Result<T, E> + 'a {
Thunk::with_arg(move |result: Result<T, E>| {
match result {
Ok(ref t) => action(t),
// ignore-windows currently windows requires UTF-8 for spawning processes
use std::old_io::Command;
-use std::os;
+use std::env;
fn main() {
- if os::args().len() == 1 {
- assert!(Command::new(os::self_exe_name().unwrap()).arg(b"\xff")
+ if env::args().len() == 1 {
+ assert!(Command::new(env::current_exe().unwrap()).arg(b"\xff")
.status().unwrap().success())
}
}
fn main() {
// get_tydesc should support unsized types
- assert!(unsafe {(
+ assert_eq!(unsafe {(
// Slice
(*std::intrinsics::get_tydesc::<[u8]>()).name,
// str
(*std::intrinsics::get_tydesc::<NT>()).name,
// DST
(*std::intrinsics::get_tydesc::<DST>()).name
- )} == ("[u8]", "str", "core::marker::Copy + 'static", "NT", "DST"));
+ )}, ("[u8]", "str", "core::marker::Copy", "NT", "DST"));
}
static generations: uint = 1024+256+128+49;
-fn spawn(f: Thunk) {
+fn spawn(f: Thunk<'static>) {
Builder::new().stack_size(32 * 1024).spawn(move|| f.invoke(()));
}
-fn child_no(x: uint) -> Thunk {
+fn child_no(x: uint) -> Thunk<'static> {
Thunk::new(move|| {
if x < generations {
spawn(child_no(x+1));
use std::old_io::println;
use std::sync::mpsc::channel;
-use std::thread::Thread;
+use std::thread;
pub fn main() {
let (tx, rx) = channel();
tx.send("hello, world").unwrap();
- Thread::scoped(move|| {
+ thread::spawn(move|| {
println(rx.recv().unwrap());
}).join().ok().unwrap();
}
// except according to those terms.
use std::sync::mpsc::channel;
-use std::thread::Thread;
+use std::thread;
pub fn main() {
let (tx, rx) = channel::<&'static str>();
- let t = Thread::scoped(move|| {
+ let t = thread::spawn(move|| {
assert_eq!(rx.recv().unwrap(), "hello, world");
});
// except according to those terms.
fn parse_args() -> String {
- let args = ::std::os::args();
- let args = args;
+ let args: Vec<_> = ::std::env::args().collect();
let mut n = 0;
while n < args.len() {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use std::os;
+use std::env;
pub fn main() {
- for arg in &os::args() {
- match (*arg).clone() {
+ for arg in env::args() {
+ match arg.clone() {
_s => { }
}
}
// except according to those terms.
use std::num::Int;
-use std::thread::Thread;
+use std::thread;
// Avoid using constants, which would trigger compile-time errors.
fn min_val<T: Int>() -> T { Int::min_value() }
fn zero<T: Int>() -> T { Int::zero() }
fn main() {
- assert!(Thread::scoped(move|| min_val::<isize>() / -1).join().is_err());
- assert!(Thread::scoped(move|| min_val::<i8>() / -1).join().is_err());
- assert!(Thread::scoped(move|| min_val::<i16>() / -1).join().is_err());
- assert!(Thread::scoped(move|| min_val::<i32>() / -1).join().is_err());
- assert!(Thread::scoped(move|| min_val::<i64>() / -1).join().is_err());
- assert!(Thread::scoped(move|| 1is / zero()).join().is_err());
- assert!(Thread::scoped(move|| 1i8 / zero()).join().is_err());
- assert!(Thread::scoped(move|| 1i16 / zero()).join().is_err());
- assert!(Thread::scoped(move|| 1i32 / zero()).join().is_err());
- assert!(Thread::scoped(move|| 1i64 / zero()).join().is_err());
- assert!(Thread::scoped(move|| min_val::<isize>() % -1).join().is_err());
- assert!(Thread::scoped(move|| min_val::<i8>() % -1).join().is_err());
- assert!(Thread::scoped(move|| min_val::<i16>() % -1).join().is_err());
- assert!(Thread::scoped(move|| min_val::<i32>() % -1).join().is_err());
- assert!(Thread::scoped(move|| min_val::<i64>() % -1).join().is_err());
- assert!(Thread::scoped(move|| 1is % zero()).join().is_err());
- assert!(Thread::scoped(move|| 1i8 % zero()).join().is_err());
- assert!(Thread::scoped(move|| 1i16 % zero()).join().is_err());
- assert!(Thread::scoped(move|| 1i32 % zero()).join().is_err());
- assert!(Thread::scoped(move|| 1i64 % zero()).join().is_err());
+ assert!(thread::spawn(move|| { min_val::<isize>() / -1; }).join().is_err());
+ assert!(thread::spawn(move|| { min_val::<i8>() / -1; }).join().is_err());
+ assert!(thread::spawn(move|| { min_val::<i16>() / -1; }).join().is_err());
+ assert!(thread::spawn(move|| { min_val::<i32>() / -1; }).join().is_err());
+ assert!(thread::spawn(move|| { min_val::<i64>() / -1; }).join().is_err());
+ assert!(thread::spawn(move|| { 1is / zero(); }).join().is_err());
+ assert!(thread::spawn(move|| { 1i8 / zero(); }).join().is_err());
+ assert!(thread::spawn(move|| { 1i16 / zero(); }).join().is_err());
+ assert!(thread::spawn(move|| { 1i32 / zero(); }).join().is_err());
+ assert!(thread::spawn(move|| { 1i64 / zero(); }).join().is_err());
+ assert!(thread::spawn(move|| { min_val::<isize>() % -1; }).join().is_err());
+ assert!(thread::spawn(move|| { min_val::<i8>() % -1; }).join().is_err());
+ assert!(thread::spawn(move|| { min_val::<i16>() % -1; }).join().is_err());
+ assert!(thread::spawn(move|| { min_val::<i32>() % -1; }).join().is_err());
+ assert!(thread::spawn(move|| { min_val::<i64>() % -1; }).join().is_err());
+ assert!(thread::spawn(move|| { 1is % zero(); }).join().is_err());
+ assert!(thread::spawn(move|| { 1i8 % zero(); }).join().is_err());
+ assert!(thread::spawn(move|| { 1i16 % zero(); }).join().is_err());
+ assert!(thread::spawn(move|| { 1i32 % zero(); }).join().is_err());
+ assert!(thread::spawn(move|| { 1i64 % zero(); }).join().is_err());
}
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub fn main() {
+ let command = "a";
+
+ match command {
+ "foo" => println!("foo"),
+ _ => println!("{}", command),
+ }
+}
// These are attributes of the implicit crate. Really this just needs to parse
// for completeness since .rs files linked from .rc files support this
// notation to specify their module's attributes
+
+#![feature(custom_attribute)]
#![allow(unused_attribute)]
#![attr1 = "val"]
#![attr2 = "val"]
// except according to those terms.
// ignore-windows
-// ignore-android
// ignore-macos
// aux-build:linkage1.rs
use std::cell::Cell;
use std::fmt;
-use std::thread::Thread;
+use std::thread;
struct Foo(Cell<int>);
}
pub fn main() {
- Thread::scoped(move|| {
+ thread::spawn(move|| {
let mut f = Foo(Cell::new(0));
println!("{:?}", f);
let Foo(ref mut f) = f;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android
// ignore-windows
// exec-env:RUST_LOG=debug
extern crate log;
use std::old_io::Command;
-use std::os;
+use std::env;
use std::str;
fn main() {
- let args = os::args();
- let args = args;
+ let args: Vec<String> = env::args().collect();
if args.len() > 1 && args[1] == "child" {
debug!("foo");
debug!("bar");
// pp-exact - Make sure we print all the attributes
#![allow(unused_attribute)]
+#![feature(custom_attribute)]
#[frobable]
trait frobable {
// compile-flags: -Z no-landing-pads
-use std::thread::Thread;
+use std::thread;
static mut HIT: bool = false;
}
fn main() {
- Thread::scoped(move|| -> () {
+ thread::spawn(move|| -> () {
let _a = A;
panic!();
}).join().err().unwrap();
#![feature(asm)]
use std::old_io::process::Command;
-use std::os;
+use std::env;
use std::thread::Thread;
// lifted from the test module
}
fn main() {
- let args = os::args();
- let args = args;
+ let args: Vec<String> = env::args().collect();
if args.len() > 1 && args[1] == "recurse" {
let _t = Thread::scoped(recurse);
} else {
#![feature(asm)]
use std::old_io::process::Command;
-use std::os;
+use std::env;
// lifted from the test module
// Inlining to avoid llvm turning the recursive functions into tail calls,
}
fn main() {
- let args = os::args();
+ let args: Vec<String> = env::args().collect();
if args.len() > 1 && args[1] == "recurse" {
recurse();
} else {
#![feature(asm)]
use std::old_io::process::Command;
-use std::os;
+use std::env;
// lifted from the test module
// Inlining to avoid llvm turning the recursive functions into tail calls,
}
fn main() {
- let args = os::args();
- let args = args;
+ let args: Vec<String> = env::args().collect();
if args.len() > 1 && args[1] == "silent" {
silent_recurse();
} else if args.len() > 1 && args[1] == "loud" {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use std::thread::Thread;
+use std::thread;
static mut dropped: bool = false;
}
pub fn main() {
- let ret = Thread::scoped(move|| {
+ let ret = thread::spawn(move|| {
let _a = A { b: B { foo: 3 } };
}).join();
assert!(ret.is_err());
use std::old_io::fs;
use std::old_io::Command;
use std::os;
+use std::env;
use std::old_path::Path;
fn main() {
- let my_args = os::args();
+ let my_args = env::args().collect::<Vec<_>>();
let my_cwd = os::getcwd().unwrap();
- let my_env = os::env();
+ let my_env = env::vars().collect::<Vec<_>>();
let my_path = Path::new(os::self_exe_name().unwrap());
let my_dir = my_path.dir_path();
let my_ext = my_path.extension_str().unwrap_or("");
#[cfg(target_os = "android")]
mod m {
- #[cfg(target_arch = "arm")]
+ #[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
pub mod m {
pub fn align() -> uint { 8u }
pub fn size() -> uint { 16u }
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Regression test for issue #22246 -- we should be able to deduce
+// that `&'a B::Owned` implies that `B::Owned : 'a`.
+
+#![allow(dead_code)]
+
+use std::ops::Deref;
+
+pub trait ToOwned {
+ type Owned: Borrow<Self>;
+ fn to_owned(&self) -> Self::Owned;
+}
+
+pub trait Borrow<Borrowed> {
+ fn borrow(&self) -> &Borrowed;
+}
+
+pub struct Foo<B:ToOwned> {
+ owned: B::Owned
+}
+
+fn foo<B:ToOwned>(this: &Foo<B>) -> &B {
+ this.owned.borrow()
+}
+
+fn main() { }
// except according to those terms.
use std::old_io::process::Command;
-use std::os;
+use std::env;
fn main() {
- let args = os::args();
+ let args: Vec<String> = env::args().collect();
if args.len() > 1 && args[1] == "segfault" {
unsafe { *(0 as *mut int) = 1 }; // trigger a segfault
} else {
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(core, std_misc)]
+use std::thread::Thread;
+use std::sync::Mutex;
+
+fn par_for<I, F>(iter: I, f: F)
+ where I: Iterator,
+ <I as Iterator>::Item: Send,
+ F: Fn(<I as Iterator>::Item) + Sync
+{
+ let f = &f;
+ let _guards: Vec<_> = iter.map(|elem| {
+ Thread::scoped(move || {
+ f(elem)
+ })
+ }).collect();
+
+}
+
+fn sum(x: &[i32]) {
+ let sum_lengths = Mutex::new(0);
+ par_for(x.windows(4), |x| {
+ *sum_lengths.lock().unwrap() += x.len()
+ });
+
+ assert_eq!(*sum_lengths.lock().unwrap(), (x.len() - 3) * 4);
+}
+
+fn main() {
+ let mut elements = [0; 20];
+
+ // iterators over references into this stack frame
+ par_for(elements.iter_mut().enumerate(), |(i, x)| {
+ *x = i as i32
+ });
+
+ sum(&elements)
+}
val: V
}
-fn cache_server<K:Send,V:Send>(mut tx: Sender<Sender<Command<K, V>>>) {
+fn cache_server<K:Send+'static,V:Send+'static>(mut tx: Sender<Sender<Command<K, V>>>) {
let (tx1, _rx) = channel();
tx.send(tx1);
}
#![allow(unknown_features)]
#![feature(box_syntax)]
-use std::thread::Thread;
+use std::thread;
pub fn main() { test05(); }
println!("{}", *three + n); // will copy x into the closure
assert_eq!(*three, 3);
};
- Thread::scoped(move|| {
+ thread::spawn(move|| {
test05_start(fn_to_send);
}).join().ok().unwrap();
}
// Check that we can use `-C lto` when linking against libraries that were
// separately compiled.
-// ignore-android linker weridness (see #18800)
// aux-build:sepcomp_lib.rs
// compile-flags: -C lto
// no-prefer-dynamic
// In any case, this test should let us know if enabling parallel codegen ever
// breaks unwinding.
-use std::thread::Thread;
+use std::thread;
fn pad() -> uint { 0 }
}
fn main() {
- Thread::scoped(move|| { ::b::g() }).join().err().unwrap();
+ thread::spawn(move|| { ::b::g() }).join().err().unwrap();
}
// ignore-windows
-use std::os;
+use std::env;
use std::old_io::process::{Command, ExitSignal, ExitStatus};
pub fn main() {
- let args = os::args();
- let args = args;
+ let args: Vec<String> = env::args().collect();
if args.len() >= 2 && args[1] == "signal" {
// Raise a segfault.
unsafe { *(0 as *mut int) = 0; }
// doesn't die in a ball of fire, but rather it's gracefully handled.
use std::os;
+use std::env;
use std::old_io::PipeStream;
use std::old_io::Command;
}
fn main() {
- let args = os::args();
- let args = args;
+ let args: Vec<String> = env::args().collect();
if args.len() > 1 && args[1] == "test" {
return test();
}
// Test that if a slicing expr[..] fails, the correct cleanups happen.
-use std::thread::Thread;
+use std::thread;
struct Foo;
}
fn main() {
- let _ = Thread::scoped(move|| foo()).join();
+ let _ = thread::spawn(move|| foo()).join();
unsafe { assert!(DTOR_COUNT == 2); }
}
// Test that if a slicing expr[..] fails, the correct cleanups happen.
-use std::thread::Thread;
+use std::thread;
struct Foo;
}
fn main() {
- let _ = Thread::scoped(move|| foo()).join();
+ let _ = thread::spawn(move|| foo()).join();
unsafe { assert!(DTOR_COUNT == 2); }
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android
-
// Smallest "hello world" with a libc runtime
#![feature(intrinsics, lang_items, start, no_std)]
return 0;
}
+#[cfg(target_os = "android")]
+#[link(name="gcc")]
+extern { }
Arnold.
*/
-use std::thread::Thread;
+use std::thread;
use std::sync::mpsc::{channel, Sender};
type ctx = Sender<int>;
pub fn main() {
let (tx, _rx) = channel::<int>();
- let t = Thread::scoped(move|| iotask(&tx, "localhost".to_string()) );
+ let t = thread::spawn(move|| iotask(&tx, "localhost".to_string()) );
t.join().ok().unwrap();
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use std::thread::Thread;
+use std::thread;
pub fn main() {
- Thread::scoped(move|| child(10)).join().ok().unwrap();
+ thread::spawn(move|| child(10)).join().ok().unwrap();
}
fn child(i: int) { println!("{}", i); assert!((i == 10)); }
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use std::thread::Thread;
+use std::thread;
pub fn main() {
- let t = Thread::scoped(move|| child((10, 20, 30, 40, 50, 60, 70, 80, 90)) );
+ let t = thread::spawn(move|| child((10, 20, 30, 40, 50, 60, 70, 80, 90)) );
t.join().ok().unwrap();
}
let mut reader = ChanReader::new(rx);
let stderr = ChanWriter::new(tx);
- let res = thread::Builder::new().stderr(box stderr as Box<Writer + Send>).scoped(move|| -> () {
+ let res = thread::Builder::new().stderr(box stderr as Box<Writer + Send>)
+ .spawn(move|| -> () {
panic!("Hello, world!")
- }).join();
+ }).unwrap().join();
assert!(res.is_err());
let output = reader.read_to_string().unwrap();
use std::old_io;
use std::os;
use std::sync::mpsc::channel;
-use std::thread::Thread;
+use std::thread;
fn test_tempdir() {
let path = {
tx.send(tmp.path().clone()).unwrap();
panic!("panic to unwind past `tmp`");
};
- let _ = Thread::scoped(f).join();
+ thread::spawn(f).join();
let path = rx.recv().unwrap();
assert!(!path.exists());
let _tmp = tmp;
panic!("panic to unwind past `tmp`");
};
- let _ = Thread::scoped(f).join();
+ thread::spawn(f).join();
assert!(!path.exists());
let path;
TempDir::new("test_rm_tempdir").unwrap()
};
// FIXME(#16640) `: TempDir` annotation shouldn't be necessary
- let tmp: TempDir = Thread::scoped(f).join().ok().expect("test_rm_tmdir");
+ let tmp: TempDir = thread::scoped(f).join();
path = tmp.path().clone();
assert!(path.exists());
}
tmp.close();
panic!("panic when unwinding past `tmp`");
};
- let _ = Thread::scoped(f).join();
+ thread::spawn(f).join();
let path = rx.recv().unwrap();
assert!(!path.exists());
tmp.close();
panic!("panic when unwinding past `tmp`");
};
- let _ = Thread::scoped(f).join();
+ thread::spawn(f).join();
assert!(!path.exists());
let path;
TempDir::new("test_rm_tempdir").unwrap()
};
// FIXME(#16640) `: TempDir` annotation shouldn't be necessary
- let tmp: TempDir = Thread::scoped(f).join().ok().expect("test_rm_tmdir");
+ let tmp: TempDir = thread::scoped(f).join();
path = tmp.path().clone();
assert!(path.exists());
tmp.close();
}
pub fn dont_double_panic() {
- let r: Result<(), _> = Thread::scoped(move|| {
+ let r: Result<(), _> = thread::spawn(move|| {
let tmpdir = TempDir::new("test").unwrap();
// Remove the temporary directory so that TempDir sees
// an error on drop
// Issue #787
// Don't try to clean up uninitialized locals
-use std::thread::Thread;
+use std::thread;
fn test_break() { loop { let _x: Box<int> = break; } }
fn test_panic() {
fn f() { let _x: Box<int> = panic!(); }
- Thread::scoped(move|| f() ).join().err().unwrap();
+ thread::spawn(move|| f() ).join().err().unwrap();
}
fn test_panic_indirect() {
fn f() -> ! { panic!(); }
fn g() { let _x: Box<int> = f(); }
- Thread::scoped(move|| g() ).join().err().unwrap();
+ thread::spawn(move|| g() ).join().err().unwrap();
}
pub fn main() {
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test an issue where we reported ambiguity between the where-clause
+// and the blanket impl. The only important thing is that compilation
+// succeeds here. Issue #22110.
+
+#![allow(dead_code)]
+
+trait Foo<A> {
+ fn foo(&self, a: A);
+}
+
+impl<A,F:Fn(A)> Foo<A> for F {
+ fn foo(&self, _: A) { }
+}
+
+fn baz<A,F:for<'a> Foo<(&'a A,)>>(_: F) { }
+
+fn components<T,A>(t: fn(&A))
+ where fn(&A) : for<'a> Foo<(&'a A,)>,
+{
+ baz(t)
+}
+
+fn main() {
+}
#![feature(box_syntax)]
use std::sync::mpsc::{channel, Sender};
-use std::thread::Thread;
+use std::thread;
fn child(tx: &Sender<Box<uint>>, i: uint) {
tx.send(box i).unwrap();
let _t = (0u..n).map(|i| {
expected += i;
let tx = tx.clone();
- Thread::scoped(move|| {
+ thread::spawn(move|| {
child(&tx, i)
})
}).collect::<Vec<_>>();
// Make sure the destructor is run for unit-like structs.
use std::boxed::BoxAny;
-use std::thread::Thread;
+use std::thread;
struct Foo;
}
pub fn main() {
- let x = Thread::scoped(move|| {
+ let x = thread::spawn(move|| {
let _b = Foo;
}).join();
// except according to those terms.
use std::sync::mpsc::{channel, Sender};
-use std::thread::Thread;
+use std::thread;
struct complainer {
tx: Sender<bool>,
pub fn main() {
let (tx, rx) = channel();
- let _t = Thread::scoped(move|| f(tx.clone()));
+ let _t = thread::spawn(move|| f(tx.clone()));
println!("hiiiiiiiii");
assert!(rx.recv().unwrap());
}
#![allow(unknown_features)]
#![feature(box_syntax)]
-use std::thread::Thread;
+use std::thread;
fn f() {
let _a = box 0;
}
pub fn main() {
- let _t = Thread::scoped(f);
+ let _t = thread::spawn(f);
}
// except according to those terms.
// pp-exact - Make sure we actually print the attributes
+#![feature(custom_attribute)]
enum crew_of_enterprise_d {
assert_eq!(vec![1; 2], vec![1, 1]);
assert_eq!(vec![1; 1], vec![1]);
assert_eq!(vec![1; 0], vec![]);
+
+ // from_elem syntax (see RFC 832)
+ let el = Box::new(1);
+ let n = 3;
+ assert_eq!(vec![el; n], vec![Box::new(1), Box::new(1), Box::new(1)]);
}
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
use std::rand::{thread_rng, Rng, Rand};
-use std::thread::Thread;
+use std::thread;
const REPEATS: usize = 5;
const MAX_LEN: usize = 32;
let v = main.clone();
- let _ = Thread::scoped(move|| {
+ let _ = thread::spawn(move|| {
let mut v = v;
let mut panic_countdown = panic_countdown;
v.sort_by(|a, b| {
extern crate "weak-lang-items" as other;
-use std::thread::Thread;
+use std::thread;
fn main() {
- let _ = Thread::scoped(move|| {
+ let _ = thread::spawn(move|| {
other::foo()
});
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use std::thread::Thread;
+use std::thread;
pub fn main() {
- let mut result = Thread::scoped(child);
+ let mut result = thread::spawn(child);
println!("1");
- Thread::yield_now();
+ thread::yield_now();
println!("2");
- Thread::yield_now();
+ thread::yield_now();
println!("3");
result.join();
}
fn child() {
- println!("4"); Thread::yield_now(); println!("5"); Thread::yield_now(); println!("6");
+ println!("4"); thread::yield_now(); println!("5"); thread::yield_now(); println!("6");
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use std::thread::Thread;
+use std::thread;
pub fn main() {
- let mut result = Thread::scoped(child);
+ let mut result = thread::spawn(child);
println!("1");
- Thread::yield_now();
+ thread::yield_now();
result.join();
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use std::thread::Thread;
+use std::thread;
pub fn main() {
let mut i: int = 0;
- while i < 100 { i = i + 1; println!("{}", i); Thread::yield_now(); }
+ while i < 100 { i = i + 1; println!("{}", i); thread::yield_now(); }
}