]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #49189 - GuillaumeGomez:fix-implied-shortcut-links, r=QuietMisdreavus
authorkennytm <kennytm@gmail.com>
Thu, 22 Mar 2018 09:51:30 +0000 (17:51 +0800)
committerkennytm <kennytm@gmail.com>
Thu, 22 Mar 2018 14:43:43 +0000 (22:43 +0800)
Fix automatic urls with backticks

Fixes #49164.

r? @QuietMisdreavus

225 files changed:
.travis.yml
RELEASES.md
config.toml.example
src/Cargo.lock
src/bootstrap/dist.rs
src/ci/docker/asmjs/Dockerfile
src/ci/docker/dist-i686-linux/build-gcc.sh
src/ci/docker/dist-i686-linux/build-git.sh
src/ci/docker/dist-x86_64-linux/build-gcc.sh
src/ci/docker/dist-x86_64-linux/build-git.sh
src/ci/init_repo.sh
src/ci/run.sh
src/doc/unstable-book/src/language-features/advanced-slice-patterns.md [deleted file]
src/doc/unstable-book/src/language-features/slice-patterns.md
src/liballoc/boxed.rs
src/liballoc/fmt.rs
src/liballoc/lib.rs
src/liballoc/tests/slice.rs
src/libcore/benches/lib.rs
src/libcore/borrow.rs
src/libcore/convert.rs
src/libcore/fmt/mod.rs
src/libcore/fmt/num.rs
src/libcore/hash/mod.rs
src/libcore/hash/sip.rs
src/libcore/iter/mod.rs
src/libcore/marker.rs
src/libcore/mem.rs
src/libcore/num/wrapping.rs
src/libcore/sync/atomic.rs
src/libcore/tests/ascii.rs
src/libcore/tests/fmt/num.rs
src/libcore/tests/hash/sip.rs
src/libcore/tests/lib.rs
src/libfmt_macros/lib.rs
src/librustc/benches/lib.rs
src/librustc/dep_graph/README.md
src/librustc/dep_graph/dep_node.rs
src/librustc/dep_graph/graph.rs
src/librustc/dep_graph/prev.rs
src/librustc/dep_graph/serialized.rs
src/librustc/diagnostics.rs
src/librustc/ich/impls_ty.rs
src/librustc/infer/anon_types/mod.rs
src/librustc/infer/canonical.rs
src/librustc/infer/higher_ranked/mod.rs
src/librustc/infer/lexical_region_resolve/README.md
src/librustc/infer/region_constraints/README.md
src/librustc/infer/region_constraints/mod.rs
src/librustc/lib.rs
src/librustc/macros.rs
src/librustc/middle/liveness.rs
src/librustc/middle/region.rs
src/librustc/mir/interpret/mod.rs
src/librustc/mir/mod.rs
src/librustc/traits/error_reporting.rs
src/librustc/traits/query/dropck_outlives.rs
src/librustc/traits/specialize/specialization_graph.rs
src/librustc/ty/fast_reject.rs
src/librustc/ty/maps/config.rs
src/librustc/ty/maps/mod.rs
src/librustc/ty/maps/on_disk_cache.rs
src/librustc/ty/maps/plumbing.rs
src/librustc/ty/mod.rs
src/librustc/ty/sty.rs
src/librustc/util/captures.rs [new file with mode: 0644]
src/librustc_apfloat/lib.rs
src/librustc_back/README.md
src/librustc_borrowck/borrowck/README.md
src/librustc_borrowck/borrowck/mod.rs
src/librustc_const_eval/lib.rs
src/librustc_data_structures/indexed_vec.rs
src/librustc_driver/README.md
src/librustc_incremental/persist/save.rs
src/librustc_lint/lib.rs
src/librustc_metadata/decoder.rs
src/librustc_metadata/encoder.rs
src/librustc_mir/build/block.rs
src/librustc_mir/util/borrowck_errors.rs
src/librustc_mir/util/elaborate_drops.rs
src/librustc_passes/ast_validation.rs
src/librustc_resolve/resolve_imports.rs
src/librustc_trans/README.md
src/librustc_trans/lib.rs
src/librustc_trans_utils/lib.rs
src/librustc_trans_utils/symbol_names_test.rs
src/librustc_typeck/check/demand.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/upvar.rs
src/librustc_typeck/check/wfcheck.rs
src/librustc_typeck/collect.rs
src/librustc_typeck/diagnostics.rs
src/librustc_typeck/lib.rs
src/librustdoc/clean/auto_trait.rs
src/librustdoc/clean/cfg.rs
src/librustdoc/clean/mod.rs
src/librustdoc/html/markdown.rs
src/librustdoc/html/static/main.js
src/librustdoc/lib.rs
src/librustdoc/markdown.rs
src/librustdoc/test.rs
src/libstd/ascii.rs
src/libstd/io/buffered.rs
src/libstd/lib.rs
src/libstd/num.rs
src/libstd/sys/windows/process.rs
src/libstd/sys_common/wtf8.rs
src/libsyntax/README.md
src/libsyntax/codemap.rs
src/libsyntax/feature_gate.rs
src/libsyntax/parse/attr.rs
src/libsyntax/parse/mod.rs
src/libsyntax/parse/parser.rs
src/libsyntax/test.rs
src/stage0.txt
src/test/codegen/abi-main-signature-16bit-c-int.rs
src/test/codegen/fastcall-inreg.rs
src/test/codegen/global_asm.rs
src/test/codegen/global_asm_include.rs
src/test/codegen/global_asm_x2.rs
src/test/codegen/repr-transparent-aggregates-1.rs
src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs
src/test/compile-fail/borrowck/borrowck-match-binding-is-assignment.rs
src/test/compile-fail/borrowck/borrowck-move-out-from-array.rs
src/test/compile-fail/borrowck/borrowck-vec-pattern-element-loan.rs
src/test/compile-fail/issue-12369.rs
src/test/compile-fail/issue-13482-2.rs
src/test/compile-fail/issue-13482.rs
src/test/compile-fail/issue-15381.rs
src/test/compile-fail/issue-41255.rs
src/test/compile-fail/issue-6804.rs
src/test/compile-fail/match-byte-array-patterns-2.rs
src/test/compile-fail/match-byte-array-patterns.rs
src/test/compile-fail/match-ref-ice.rs
src/test/compile-fail/match-slice-patterns.rs
src/test/compile-fail/match-vec-fixed.rs
src/test/compile-fail/match-vec-mismatch-2.rs
src/test/compile-fail/match-vec-unreachable.rs
src/test/compile-fail/move-out-of-slice-1.rs
src/test/compile-fail/regions-pattern-typing-issue-19552.rs
src/test/compile-fail/uninhabited-matches-feature-gated.rs
src/test/compile-fail/uninhabited-patterns.rs
src/test/incremental/extern_static/issue-49153.rs [new file with mode: 0644]
src/test/incremental/issue-49043.rs [new file with mode: 0644]
src/test/incremental/static_refering_to_other_static/issue-49081.rs [new file with mode: 0644]
src/test/mir-opt/end_region_8.rs
src/test/mir-opt/uniform_array_move_out.rs
src/test/run-make/tools.mk
src/test/run-pass-fulldeps/auxiliary/roman_numerals.rs
src/test/run-pass/deep.rs
src/test/run-pass/destructure-array-1.rs
src/test/run-pass/dynamic-drop.rs
src/test/run-pass/float-int-invalid-const-cast.rs
src/test/run-pass/ignore-all-the-things.rs
src/test/run-pass/intrinsics-integer.rs
src/test/run-pass/intrinsics-math.rs
src/test/run-pass/issue-10683.rs
src/test/run-pass/issue-13027.rs
src/test/run-pass/issue-15080.rs
src/test/run-pass/issue-15104.rs
src/test/run-pass/issue-16648.rs
src/test/run-pass/issue-17877.rs
src/test/run-pass/issue-27889.rs
src/test/run-pass/issue-28561.rs
src/test/run-pass/issue-32947.rs
src/test/run-pass/issue-37598.rs
src/test/run-pass/issue-38002.rs
src/test/run-pass/issue-38074.rs
src/test/run-pass/issue-39720.rs
src/test/run-pass/issue-46855.rs
src/test/run-pass/issue-7784.rs
src/test/run-pass/match-vec-alternatives.rs
src/test/run-pass/mir_heavy_promoted.rs
src/test/run-pass/next-power-of-two-overflow-debug.rs
src/test/run-pass/next-power-of-two-overflow-ndebug.rs
src/test/run-pass/packed-struct-borrow-element.rs
src/test/run-pass/rfc-2005-default-binding-mode/slice.rs
src/test/run-pass/simd-intrinsic-generic-arithmetic.rs
src/test/run-pass/simd-intrinsic-generic-comparison.rs
src/test/run-pass/simd-intrinsic-generic-elements.rs
src/test/run-pass/trailing-comma.rs
src/test/run-pass/vec-matching-autoslice.rs
src/test/run-pass/vec-matching-fixed.rs
src/test/run-pass/vec-matching-fold.rs
src/test/run-pass/vec-matching.rs
src/test/run-pass/vec-tail-matching.rs
src/test/rustdoc/doc-cfg.rs
src/test/ui/borrowck/borrowck-vec-pattern-nesting.rs
src/test/ui/borrowck/borrowck-vec-pattern-nesting.stderr
src/test/ui/error-codes/E0449.stderr
src/test/ui/error-codes/E0527.rs
src/test/ui/error-codes/E0527.stderr
src/test/ui/error-codes/E0529.rs
src/test/ui/error-codes/E0529.stderr
src/test/ui/feature-gate-advanced-slice-features.rs [deleted file]
src/test/ui/feature-gate-advanced-slice-features.stderr [deleted file]
src/test/ui/feature-gate-slice-patterns.rs
src/test/ui/feature-gate-slice-patterns.stderr
src/test/ui/generator/auto-trait-regions.stderr
src/test/ui/impl-trait/region-escape-via-bound-contravariant-closure.rs [new file with mode: 0644]
src/test/ui/impl-trait/region-escape-via-bound-contravariant.rs [new file with mode: 0644]
src/test/ui/impl-trait/region-escape-via-bound.rs [new file with mode: 0644]
src/test/ui/impl-trait/region-escape-via-bound.stderr [new file with mode: 0644]
src/test/ui/issue-49040.rs [new file with mode: 0644]
src/test/ui/issue-49040.stderr [new file with mode: 0644]
src/test/ui/mismatched_types/issue-38371.rs
src/test/ui/mismatched_types/issue-38371.stderr
src/test/ui/non-exhaustive-pattern-witness.rs
src/test/ui/non-exhaustive-pattern-witness.stderr
src/test/ui/pat-slice-old-style.rs
src/test/ui/rfc-2005-default-binding-mode/slice.rs
src/test/ui/suggest-remove-refs-1.rs [new file with mode: 0644]
src/test/ui/suggest-remove-refs-1.stderr [new file with mode: 0644]
src/test/ui/suggest-remove-refs-2.rs [new file with mode: 0644]
src/test/ui/suggest-remove-refs-2.stderr [new file with mode: 0644]
src/test/ui/suggest-remove-refs-3.rs [new file with mode: 0644]
src/test/ui/suggest-remove-refs-3.stderr [new file with mode: 0644]
src/test/ui/suggestions/const-type-mismatch.rs [new file with mode: 0644]
src/test/ui/suggestions/const-type-mismatch.stderr [new file with mode: 0644]
src/tools/cargo
src/tools/clippy
src/tools/compiletest/src/runtest.rs
src/tools/compiletest/src/util.rs
src/tools/rls
src/tools/rustfmt

index 41ea0c9afa87cc97c93973e6f3ad5109031393fc..b2aba305aedc4347a66dc626d5270bcc34071e33 100644 (file)
@@ -318,6 +318,8 @@ before_deploy:
 
 deploy:
   - provider: s3
+    edge:
+      branch: s3-eager-autoload
     bucket: rust-lang-ci2
     skip_cleanup: true
     local_dir: deploy
@@ -334,6 +336,8 @@ deploy:
   # this is the same as the above deployment provider except that it uploads to
   # a slightly different directory and has a different trigger
   - provider: s3
+    edge:
+      branch: s3-eager-autoload
     bucket: rust-lang-ci2
     skip_cleanup: true
     local_dir: deploy
@@ -351,6 +355,8 @@ deploy:
   # try branch. Travis does not appear to provide a way to use "or" in these
   # conditions.
   - provider: s3
+    edge:
+      branch: s3-eager-autoload
     bucket: rust-lang-ci2
     skip_cleanup: true
     local_dir: deploy
@@ -365,6 +371,8 @@ deploy:
       condition: $DEPLOY = 1
 
   - provider: s3
+    edge:
+      branch: s3-eager-autoload
     bucket: rust-lang-ci2
     skip_cleanup: true
     local_dir: deploy
index 64e2145e0f37b444953dfef48c7f1f28f6f69cfd..51c36c99858b8851892bcc103109944f94545d43 100644 (file)
@@ -1,3 +1,103 @@
+Version 1.25.0 (2018-03-29)
+==========================
+
+Language
+--------
+- [Stabilised `#[repr(align(x))]`.][47006] [RFC 1358]
+- [You can now use nested groups of imports.][47948]
+  e.g. `use std::{fs::File, io::Read, path::{Path, PathBuf}};`
+- [You can now have `|` at the start of a match arm.][47947] e.g.
+```rust
+enum Foo { A, B, C }
+
+fn main() {
+    let x = Foo::A;
+    match x {
+        | Foo::A
+        | Foo::B => println!("AB"),
+        | Foo::C => println!("C"),
+    }
+}
+```
+
+Compiler
+--------
+- [Upgraded to LLVM 6.][47828]
+- [Added `-C lto=val` option.][47521]
+- [Added `i586-unknown-linux-musl` target][47282]
+
+Libraries
+---------
+- [Impl Send for `process::Command` on Unix.][47760]
+- [Impl PartialEq and Eq for `ParseCharError`.][47790]
+- [`UnsafeCell::into_inner` is now safe.][47204]
+- [Implement libstd for CloudABI.][47268]
+- [`Float::{from_bits, to_bits}` is now available in libcore.][46931]
+- [Implement `AsRef<Path>` for Component][46985]
+- [Implemented `Write` for `Cursor<&mut Vec<T>>`][46830]
+- [Moved `Duration` to libcore.][46666]
+
+Stabilized APIs
+---------------
+- [`Location::column`]
+- [`ptr::NonNull`]
+
+The following functions can now be used in a constant expression.
+eg. `static MINUTE: Duration = Duration::from_secs(60);`
+- [`Duration::new`][47300]
+- [`Duration::from_secs`][47300]
+- [`Duration::from_millis`][47300]
+- [`Duration::from_micros`][47300]
+- [`Duration::from_nanos`][47300]
+
+Cargo
+-----
+- [`cargo new` no longer removes `rust` or `rs` prefixs/suffixs.][cargo/5013]
+- [`cargo new` now defaults to creating a binary crate, instead of a
+  library crate.][cargo/5029]
+
+Misc
+----
+- [Rust by example is now shipped with new releases][46196]
+
+Compatibility Notes
+-------------------
+- [Deprecated `net::lookup_host`.][47510]
+- [`rustdoc` has switched to pulldown as the default markdown renderer.][47398]
+- The borrow checker was sometimes incorrectly permitting overlapping borrows
+  around indexing operations (see [#47349][47349]). This has been fixed (which also
+  enabled some correct code that used to cause errors (e.g. [#33903][33903] and [#46095][46095]).
+- [Removed deprecated unstable attribute `#[simd]`.][47251]
+
+[33903]: https://github.com/rust-lang/rust/pull/33903
+[47947]: https://github.com/rust-lang/rust/pull/47947
+[47948]: https://github.com/rust-lang/rust/pull/47948
+[47760]: https://github.com/rust-lang/rust/pull/47760
+[47790]: https://github.com/rust-lang/rust/pull/47790
+[47828]: https://github.com/rust-lang/rust/pull/47828
+[47398]: https://github.com/rust-lang/rust/pull/47398
+[47510]: https://github.com/rust-lang/rust/pull/47510
+[47521]: https://github.com/rust-lang/rust/pull/47521
+[47204]: https://github.com/rust-lang/rust/pull/47204
+[47251]: https://github.com/rust-lang/rust/pull/47251
+[47268]: https://github.com/rust-lang/rust/pull/47268
+[47282]: https://github.com/rust-lang/rust/pull/47282
+[47300]: https://github.com/rust-lang/rust/pull/47300
+[47349]: https://github.com/rust-lang/rust/pull/47349
+[46931]: https://github.com/rust-lang/rust/pull/46931
+[46985]: https://github.com/rust-lang/rust/pull/46985
+[47006]: https://github.com/rust-lang/rust/pull/47006
+[46830]: https://github.com/rust-lang/rust/pull/46830
+[46095]: https://github.com/rust-lang/rust/pull/46095
+[46666]: https://github.com/rust-lang/rust/pull/46666
+[46196]: https://github.com/rust-lang/rust/pull/46196
+[cargo/5013]: https://github.com/rust-lang/cargo/pull/5013
+[cargo/5029]: https://github.com/rust-lang/cargo/pull/5029
+[RFC 1358]: https://github.com/rust-lang/rfcs/pull/1358
+[`Location::column`]: https://doc.rust-lang.org/std/panic/struct.Location.html#method.column
+[`ptr::NonNull`]: https://doc.rust-lang.org/std/ptr/struct.NonNull.html
+
+
 Version 1.24.0 (2018-02-15)
 ==========================
 
index aec5e5a0e2c800220da705d7101a96de198d8491..de7036db29f4afa5883a39e467731f8da575b764 100644 (file)
 # compiler.
 #codegen-units = 1
 
-# Whether to enable ThinLTO (and increase the codegen units to either a default
-# or the configured value). On by default. If we want the fastest possible
-# compiler, we should disable this.
-#thinlto = true
-
 # Whether or not debug assertions are enabled for the compiler and standard
 # library. Also enables compilation of debug! and trace! logging macros.
 #debug-assertions = false
index c82588e41125c5b822d89e44865bcac7974f6da3..675457905eade8de5dcb485c065c7461aec2066e 100644 (file)
@@ -184,7 +184,7 @@ version = "0.27.0"
 dependencies = [
  "atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "clap 2.31.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "crates-io 0.16.0",
  "crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -236,18 +236,6 @@ dependencies = [
  "serde_json 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
-[[package]]
-name = "cargo_metadata"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "semver 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "cargo_metadata"
 version = "0.5.3"
@@ -285,7 +273,7 @@ dependencies = [
 
 [[package]]
 name = "clap"
-version = "2.31.1"
+version = "2.31.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -588,15 +576,6 @@ dependencies = [
  "regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
-[[package]]
-name = "env_logger"
-version = "0.4.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "env_logger"
 version = "0.5.5"
@@ -861,7 +840,7 @@ version = "0.1.0"
 name = "installer"
 version = "0.0.0"
 dependencies = [
- "clap 2.31.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1054,7 +1033,7 @@ version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "chrono 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "clap 2.31.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "handlebars 0.29.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1343,7 +1322,7 @@ name = "racer"
 version = "2.0.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "clap 2.31.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1490,7 +1469,7 @@ dependencies = [
  "rls-rustc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-vfs 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustfmt-nightly 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustfmt-nightly 0.4.1",
  "serde 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1554,7 +1533,7 @@ dependencies = [
 name = "rustbook"
 version = "0.1.0"
 dependencies = [
- "clap 2.31.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "mdbook 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1585,7 +1564,7 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-rustc_cratesio_shim"
-version = "29.0.0"
+version = "67.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1594,57 +1573,62 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-rustc_data_structures"
-version = "29.0.0"
+version = "67.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ena 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot_core 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rustc-ap-rustc_errors"
-version = "29.0.0"
+version = "67.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "rustc-ap-rustc_data_structures 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-syntax_pos 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax_pos 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "termcolor 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rustc-ap-serialize"
-version = "29.0.0"
+version = "67.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "rustc-ap-syntax"
-version = "29.0.0"
+version = "67.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_cratesio_shim 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_data_structures 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_errors 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-syntax_pos 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_cratesio_shim 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_errors 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax_pos 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rustc-ap-syntax_pos"
-version = "29.0.0"
+version = "67.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "rustc-ap-rustc_data_structures 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -2066,52 +2050,26 @@ dependencies = [
 
 [[package]]
 name = "rustfmt-nightly"
-version = "0.3.8"
+version = "0.4.1"
 dependencies = [
- "cargo_metadata 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cargo_metadata 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "derive-new 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "env_logger 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "itertools 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_errors 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-syntax 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "rustfmt-nightly"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "cargo_metadata 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "derive-new 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_errors 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-syntax 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2146,15 +2104,6 @@ name = "scopeguard"
 version = "0.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
-[[package]]
-name = "semver"
-version = "0.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "semver"
 version = "0.9.0"
@@ -2424,6 +2373,15 @@ dependencies = [
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "term"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "termcolor"
 version = "0.3.5"
@@ -2737,12 +2695,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f382711e76b9de6c744cc00d0497baba02fb00a787f088c879f01d09468e32"
 "checksum byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "652805b7e73fada9d85e9a6682a4abd490cb52d96aeecc12e33a0de34dfd0d23"
 "checksum cargo_metadata 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "be1057b8462184f634c3a208ee35b0f935cfd94b694b26deadccd98732088d7b"
-"checksum cargo_metadata 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "20d6fb2b5574726329c85cdba0df0347fddfec3cf9c8b588f9931708280f5643"
 "checksum cargo_metadata 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b5caae26de3704081ef638f87f05a6891b04f2b7d5ce9429a3de21095528ae22"
 "checksum cc 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fedf677519ac9e865c4ff43ef8f930773b37ed6e6ea61b6b83b400a7b5787f49"
 "checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
 "checksum chrono 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7c20ebe0b2b08b0aeddba49c609fe7957ba2e33449882cb186a180bc60682fa9"
-"checksum clap 2.31.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5dc18f6f4005132120d9711636b32c46a233fad94df6217fa1d81c5e97a9f200"
+"checksum clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f0f16b89cbb9ee36d87483dc939fe9f1e13c05898d56d7b230a0d4dff033a536"
 "checksum cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)" = "56d741ea7a69e577f6d06b36b7dff4738f680593dc27a701ffa8506b73ce28bb"
 "checksum commoncrypto 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d056a8586ba25a1e4d61cb090900e495952c7886786fc55f909ab2f819b69007"
 "checksum commoncrypto-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1fed34f46747aa73dfaa578069fd8279d2818ade2b55f38f22a9401c7f4083e2"
@@ -2764,7 +2721,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum endian-type 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d"
 "checksum enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be4551092f4d519593039259a9ed8daedf0da12e5109c5280338073eaeb81180"
 "checksum env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "15abd780e45b3ea4f76b4e9a26ff4843258dd8a3eed2775a0e7368c2e7936c2f"
-"checksum env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3ddf21e73e016298f5cb37d6ef8e8da8e39f91f9ec8b0df44b7deb16a9f8cd5b"
 "checksum env_logger 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f0628f04f7c26ebccf40d7fc2c1cf92236c05ec88cf2132641cc956812312f0f"
 "checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3"
 "checksum failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "934799b6c1de475a012a02dab0ace1ace43789ee4b99bcfbf1a2e3e8ced5de82"
@@ -2858,21 +2814,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum rls-rustc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "885f66b92757420572cbb02e033d4a9558c7413ca9b7ac206f28fd58ffdb44ea"
 "checksum rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d7c7046dc6a92f2ae02ed302746db4382e75131b9ce20ce967259f6b5867a6a"
 "checksum rls-vfs 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "be231e1e559c315bc60ced5ad2cc2d7a9c208ed7d4e2c126500149836fda19bb"
-"checksum rustc-ap-rustc_cratesio_shim 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ad5e562044ea78a6764dd75ae8afe4b21fde49f4548024b5fdf6345c21fb524"
-"checksum rustc-ap-rustc_data_structures 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c0d65325492aba7db72899e3edbab34d39af98c42ab7c7e450c9a288ffe4ad"
-"checksum rustc-ap-rustc_errors 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "87d4ab2e06a671b5b5c5b0359dac346f164c99d059dce6a22feb08f2f56bd182"
-"checksum rustc-ap-serialize 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e0745fa445ff41c4b6699936cf35ce3ca49502377dd7b3929c829594772c3a7b"
-"checksum rustc-ap-syntax 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "82efedabe30f393161e11214a9130edfa01ad476372d1c6f3fec1f8d30488c9d"
-"checksum rustc-ap-syntax_pos 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "db9de2e927e280c75b8efab9c5f591ad31082d5d2c4c562c68fdba2ee77286b0"
+"checksum rustc-ap-rustc_cratesio_shim 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "adc16e4a6e50a4ffbd4633d737aedbdfcb565bdf658159e0544266908180a919"
+"checksum rustc-ap-rustc_data_structures 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5ec5f0a018fbec07f64b689ac20f7343ed77939055ca07d2aceb37c832245b1b"
+"checksum rustc-ap-rustc_errors 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8301221cc07002666eed552a089b15000bc954c94b14a460c0653363a7f42f4c"
+"checksum rustc-ap-serialize 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5212ee40fc332d791cacf202ae5fb99197341857c0a14bcdf60541fea7dfc5ed"
+"checksum rustc-ap-syntax 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "168571b3878c6c61aef4bacef95c86d30fa61fb1cff04395d9535c80c196e559"
+"checksum rustc-ap-syntax_pos 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cd7a0486f56db583caa665c8b4ff02c4774fe279db1741509437bc8a84c53361"
 "checksum rustc-demangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11fb43a206a04116ffd7cfcf9bcb941f8eb6cc7ff667272246b0a1c74259a3cb"
 "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
-"checksum rustfmt-nightly 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "554256054eae37ead2f799ffa9cf8be8249496c6c3cf005c28b7cfa55f4efaa5"
 "checksum same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cfb6eded0b06a0b512c8ddbcf04089138c9b4362c2f696f3c3d76039d68f3637"
 "checksum schannel 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "fbaffce35eb61c5b00846e73128b0cd62717e7c0ec46abbec132370d013975b4"
 "checksum scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8674d439c964889e2476f474a3bf198cc9e199e77499960893bac5de7e9218a4"
 "checksum scopeguard 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "59a076157c1e2dc561d8de585151ee6965d910dd4dcb5dabb7ae3e83981a6c57"
 "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
-"checksum semver 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bee2bc909ab2d8d60dab26e8cad85b25d795b14603a0dcb627b78b9d30b6454b"
 "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
 "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
 "checksum serde 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)" = "4763b773978e495252615e814d2ad04773b2c1f85421c7913869a537f35cb406"
@@ -2896,6 +2850,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum tar 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)" = "1605d3388ceb50252952ffebab4b5dc43017ead7e4481b175961c283bb951195"
 "checksum tempdir 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f73eebdb68c14bcb24aef74ea96079830e7fa7b31a6106e42ea7ee887c1e134e"
 "checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1"
+"checksum term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5e6b677dd1e8214ea1ef4297f85dbcbed8e8cdddb561040cc998ca2551c37561"
 "checksum termcolor 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "56c456352e44f9f91f774ddeeed27c1ec60a2455ed66d692059acfb1d731bda1"
 "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
 "checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693"
index dcb572416594ebcd1857b4da268dd14eb56520f5..eca06eac7f30788fc7d53e8b723fc53c479ed154 100644 (file)
@@ -221,6 +221,7 @@ fn make_win_dist(
         "libsecur32.a",
         "libsetupapi.a",
         "libshell32.a",
+        "libsynchronization.a",
         "libuser32.a",
         "libuserenv.a",
         "libuuid.a",
index 2a0901691a55ac6ed2ad7d734c9b3877949cda27..cb85cf3d9e9f094f87ba6617250e55ef68a7fd42 100644 (file)
@@ -29,6 +29,11 @@ ENV EM_CONFIG=/emsdk-portable/.emscripten
 
 ENV TARGETS=asmjs-unknown-emscripten
 
-ENV RUST_CONFIGURE_ARGS --enable-emscripten
+ENV RUST_CONFIGURE_ARGS --enable-emscripten --disable-optimize-tests
 
-ENV SCRIPT python2.7 ../x.py test --target $TARGETS
+ENV SCRIPT python2.7 ../x.py test --target $TARGETS \
+  src/test/run-pass \
+  src/test/run-fail \
+  src/libstd \
+  src/liballoc \
+  src/libcore
index 6b991bb59e4b0dcc5fd9018b51e70960afe9a6c9..08020e533ff191ca565868062cef8f7d5ab55967 100755 (executable)
@@ -17,6 +17,23 @@ GCC=4.8.5
 
 curl https://ftp.gnu.org/gnu/gcc/gcc-$GCC/gcc-$GCC.tar.bz2 | tar xjf -
 cd gcc-$GCC
+
+# FIXME(#49246): Remove the `sed` below.
+#
+# On 2018 March 21st, two Travis builders' cache for Docker are suddenly invalidated. Normally this
+# is fine, because we just need to rebuild the Docker image. However, it reveals a network issue:
+# downloading from `ftp://gcc.gnu.org/` from Travis (using passive mode) often leads to "Connection
+# timed out" error, and even when the download completed, the file is usually corrupted. This causes
+# nothing to be landed that day.
+#
+# We observed that the `gcc-4.8.5.tar.bz2` above can be downloaded successfully, so as a stability
+# improvement we try to download from the HTTPS mirror instead. Turns out this uncovered the third
+# bug: the host `gcc.gnu.org` and `cygwin.com` share the same IP, and the TLS certificate of the
+# latter host is presented to `wget`! Therefore, we choose to download from the insecure HTTP server
+# instead here.
+#
+sed -i'' 's|ftp://gcc\.gnu\.org/|http://gcc.gnu.org/|g' ./contrib/download_prerequisites
+
 ./contrib/download_prerequisites
 mkdir ../gcc-build
 cd ../gcc-build
index ff62a68629a8bfdb79bee9d727f35c6066030434..aa31f50ba0343134bfbece006ad3faf6c13afc72 100755 (executable)
@@ -12,7 +12,7 @@
 set -ex
 source shared.sh
 
-curl https://www.kernel.org/pub/software/scm/git/git-2.10.0.tar.gz | tar xzf -
+curl -L https://www.kernel.org/pub/software/scm/git/git-2.10.0.tar.gz | tar xzf -
 
 cd git-2.10.0
 make configure
index 6b991bb59e4b0dcc5fd9018b51e70960afe9a6c9..08020e533ff191ca565868062cef8f7d5ab55967 100755 (executable)
@@ -17,6 +17,23 @@ GCC=4.8.5
 
 curl https://ftp.gnu.org/gnu/gcc/gcc-$GCC/gcc-$GCC.tar.bz2 | tar xjf -
 cd gcc-$GCC
+
+# FIXME(#49246): Remove the `sed` below.
+#
+# On 2018 March 21st, two Travis builders' cache for Docker are suddenly invalidated. Normally this
+# is fine, because we just need to rebuild the Docker image. However, it reveals a network issue:
+# downloading from `ftp://gcc.gnu.org/` from Travis (using passive mode) often leads to "Connection
+# timed out" error, and even when the download completed, the file is usually corrupted. This causes
+# nothing to be landed that day.
+#
+# We observed that the `gcc-4.8.5.tar.bz2` above can be downloaded successfully, so as a stability
+# improvement we try to download from the HTTPS mirror instead. Turns out this uncovered the third
+# bug: the host `gcc.gnu.org` and `cygwin.com` share the same IP, and the TLS certificate of the
+# latter host is presented to `wget`! Therefore, we choose to download from the insecure HTTP server
+# instead here.
+#
+sed -i'' 's|ftp://gcc\.gnu\.org/|http://gcc.gnu.org/|g' ./contrib/download_prerequisites
+
 ./contrib/download_prerequisites
 mkdir ../gcc-build
 cd ../gcc-build
index ff62a68629a8bfdb79bee9d727f35c6066030434..aa31f50ba0343134bfbece006ad3faf6c13afc72 100755 (executable)
@@ -12,7 +12,7 @@
 set -ex
 source shared.sh
 
-curl https://www.kernel.org/pub/software/scm/git/git-2.10.0.tar.gz | tar xzf -
+curl -L https://www.kernel.org/pub/software/scm/git/git-2.10.0.tar.gz | tar xzf -
 
 cd git-2.10.0
 make configure
index 8ab4276fa3b059b38f1a3aba9479c89eba4e4603..f2664e6d196c7afcab810ab0ee15f5e30b14eb64 100755 (executable)
@@ -17,6 +17,7 @@ ci_dir=$(cd $(dirname $0) && pwd)
 . "$ci_dir/shared.sh"
 
 travis_fold start init_repo
+travis_time_start
 
 REPO_DIR="$1"
 CACHE_DIR="$2"
@@ -42,54 +43,39 @@ if grep -q RUST_RELEASE_CHANNEL=beta src/ci/run.sh; then
   git fetch origin --unshallow beta master
 fi
 
-travis_fold start update_cache
-travis_time_start
-
-# Update the cache (a pristine copy of the rust source master)
-retry sh -c "rm -rf $cache_src_dir && mkdir -p $cache_src_dir && \
-    git clone --depth 1 https://github.com/rust-lang/rust.git $cache_src_dir"
-if [ -d $cache_src_dir/src/llvm ]; then
-  (cd $cache_src_dir && git rm src/llvm)
-fi
-if [ -d $cache_src_dir/src/llvm-emscripten ]; then
-  (cd $cache_src_dir && git rm src/llvm-emscripten)
-fi
-retry sh -c "cd $cache_src_dir && \
-    git submodule deinit -f . && git submodule sync && git submodule update --init"
-
-travis_fold end update_cache
-travis_time_finish
+function fetch_submodule {
+    local module=$1
+    local cached="download-${module//\//-}.tar.gz"
+    retry sh -c "rm -f $cached && \
+        curl -sSL -o $cached $2"
+    mkdir $module
+    touch "$module/.git"
+    tar -C $module --strip-components=1 -xf $cached
+    rm $cached
+}
 
-travis_fold start update_submodules
-travis_time_start
-
-# Update the submodules of the repo we're in, using the pristine repo as
-# a cache for any object files
-# No, `git submodule foreach` won't work:
-# http://stackoverflow.com/questions/12641469/list-submodules-in-a-git-repository
+included="src/llvm src/llvm-emscripten src/doc/book src/doc/rust-by-example"
 modules="$(git config --file .gitmodules --get-regexp '\.path$' | cut -d' ' -f2)"
-for module in $modules; do
-    if [ "$module" = src/llvm ] || [ "$module" = src/llvm-emscripten ]; then
+modules=($modules)
+use_git=""
+urls="$(git config --file .gitmodules --get-regexp '\.url$' | cut -d' ' -f2)"
+urls=($urls)
+for i in ${!modules[@]}; do
+    module=${modules[$i]}
+    if [[ " $included " = *" $module "* ]]; then
         commit="$(git ls-tree HEAD $module | awk '{print $3}')"
         git rm $module
-        retry sh -c "rm -f $commit.tar.gz && \
-            curl -sSL -O https://github.com/rust-lang/llvm/archive/$commit.tar.gz"
-        tar -C src/ -xf "$commit.tar.gz"
-        rm "$commit.tar.gz"
-        mv "src/llvm-$commit" $module
-        continue
-    fi
-    if [ ! -e "$cache_src_dir/$module/.git" ]; then
-        echo "WARNING: $module not found in pristine repo"
-        retry sh -c "git submodule deinit -f $module && \
-            git submodule update --init --recursive $module"
+        url=${urls[$i]}
+        url=${url/\.git/}
+        fetch_submodule $module "$url/archive/$commit.tar.gz" &
         continue
+    else
+        use_git="$use_git $module"
     fi
-    retry sh -c "git submodule deinit -f $module && \
-        git submodule update --init --recursive --reference $cache_src_dir/$module $module"
 done
-
-travis_fold end update_submodules
-travis_time_finish
-
+retry sh -c "git submodule deinit -f $use_git && \
+    git submodule sync && \
+    git submodule update -j 16 --init --recursive $use_git"
+wait
 travis_fold end init_repo
+travis_time_finish
index e3f38e4834a92dcf86643532ed9df5930b66fa87..afa6d1fa0aea5e9d38aaecf67617dc3194528607 100755 (executable)
@@ -105,7 +105,15 @@ fi
 travis_fold end log-system-info
 
 if [ ! -z "$SCRIPT" ]; then
-  sh -x -c "$SCRIPT"
+  # FIXME(#49246): Re-enable these tools after #49246 has been merged and thus fixing the cache.
+  if [ "$DEPLOY_ALT" = 1 ]; then
+    sh -x -c "$SCRIPT \
+       --exclude src/tools/rls \
+       --exclude src/tools/rustfmt \
+       --exclude src/tools/clippy"
+  else
+    sh -x -c "$SCRIPT"
+  fi
 else
   do_make() {
     travis_fold start "make-$1"
diff --git a/src/doc/unstable-book/src/language-features/advanced-slice-patterns.md b/src/doc/unstable-book/src/language-features/advanced-slice-patterns.md
deleted file mode 100644 (file)
index e825646..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-# `advanced_slice_patterns`
-
-The tracking issue for this feature is: [#23121]
-
-[#23121]: https://github.com/rust-lang/rust/issues/23121
-
-See also [`slice_patterns`](language-features/slice-patterns.html).
-
-------------------------
-
-
-The `advanced_slice_patterns` gate lets you use `..` to indicate any number of
-elements inside a pattern matching a slice. This wildcard can only be used once
-for a given array. If there's an identifier before the `..`, the result of the
-slice will be bound to that name. For example:
-
-```rust
-#![feature(advanced_slice_patterns, slice_patterns)]
-
-fn is_symmetric(list: &[u32]) -> bool {
-    match list {
-        &[] | &[_] => true,
-        &[x, ref inside.., y] if x == y => is_symmetric(inside),
-        _ => false
-    }
-}
-
-fn main() {
-    let sym = &[0, 1, 4, 2, 4, 1, 0];
-    assert!(is_symmetric(sym));
-
-    let not_sym = &[0, 1, 7, 2, 4, 1, 0];
-    assert!(!is_symmetric(not_sym));
-}
-```
index 69857297582da4068b9c3c464d818657c7ce6877..133174268ef93f16fbfc191b9bd405751e81af04 100644 (file)
@@ -4,25 +4,29 @@ The tracking issue for this feature is: [#23121]
 
 [#23121]: https://github.com/rust-lang/rust/issues/23121
 
-See also
-[`advanced_slice_patterns`](language-features/advanced-slice-patterns.html).
-
 ------------------------
 
-
-If you want to match against a slice or array, you can use `&` with the
-`slice_patterns` feature:
+The `slice_patterns` feature gate lets you use `..` to indicate any number of
+elements inside a pattern matching a slice. This wildcard can only be used once
+for a given array. If there's an pattern before the `..`, the subslice will be
+matched against that pattern. For example:
 
 ```rust
 #![feature(slice_patterns)]
 
+fn is_symmetric(list: &[u32]) -> bool {
+    match list {
+        &[] | &[_] => true,
+        &[x, ref inside.., y] if x == y => is_symmetric(inside),
+        &[..] => false,
+    }
+}
+
 fn main() {
-    let v = vec!["match_this", "1"];
+    let sym = &[0, 1, 4, 2, 4, 1, 0];
+    assert!(is_symmetric(sym));
 
-    match &v[..] {
-        &["match_this", second] => println!("The second element is {}", second),
-        _ => {},
-    }
+    let not_sym = &[0, 1, 7, 2, 4, 1, 0];
+    assert!(!is_symmetric(not_sym));
 }
 ```
-
index b776556d59f11b033500d34cafd1ec13b4cf4435..abe2071973bc84a7f85de432794b0668531d84bf 100644 (file)
@@ -64,8 +64,8 @@
 use core::fmt;
 use core::hash::{self, Hash, Hasher};
 use core::iter::FusedIterator;
-use core::marker::{self, Unsize};
-use core::mem;
+use core::marker::{self, Unpin, Unsize};
+use core::mem::{self, Pin};
 use core::ops::{CoerceUnsized, Deref, DerefMut, Generator, GeneratorState};
 use core::ops::{BoxPlace, Boxed, InPlace, Place, Placer};
 use core::ptr::{self, NonNull, Unique};
@@ -896,3 +896,100 @@ fn resume(&mut self) -> GeneratorState<Self::Yield, Self::Return> {
         (**self).resume()
     }
 }
+
+/// A pinned, heap allocated reference.
+#[unstable(feature = "pin", issue = "49150")]
+#[fundamental]
+pub struct PinBox<T: ?Sized> {
+    inner: Box<T>,
+}
+
+#[unstable(feature = "pin", issue = "49150")]
+impl<T> PinBox<T> {
+    /// Allocate memory on the heap, move the data into it and pin it.
+    #[unstable(feature = "pin", issue = "49150")]
+    pub fn new(data: T) -> PinBox<T> {
+        PinBox { inner: Box::new(data) }
+    }
+}
+
+#[unstable(feature = "pin", issue = "49150")]
+impl<T: ?Sized> PinBox<T> {
+    /// Get a pinned reference to the data in this PinBox.
+    pub fn as_pin<'a>(&'a mut self) -> Pin<'a, T> {
+        unsafe { Pin::new_unchecked(&mut *self.inner) }
+    }
+
+    /// Get a mutable reference to the data inside this PinBox.
+    ///
+    /// This function is unsafe. Users must guarantee that the data is never
+    /// moved out of this reference.
+    pub unsafe fn get_mut<'a>(this: &'a mut PinBox<T>) -> &'a mut T {
+        &mut *this.inner
+    }
+
+    /// Convert this PinBox into an unpinned Box.
+    ///
+    /// This function is unsafe. Users must guarantee that the data is never
+    /// moved out of the box.
+    pub unsafe fn unpin(this: PinBox<T>) -> Box<T> {
+        this.inner
+    }
+}
+
+#[unstable(feature = "pin", issue = "49150")]
+impl<T: ?Sized> From<Box<T>> for PinBox<T> {
+    fn from(boxed: Box<T>) -> PinBox<T> {
+        PinBox { inner: boxed }
+    }
+}
+
+#[unstable(feature = "pin", issue = "49150")]
+impl<T: Unpin + ?Sized> From<PinBox<T>> for Box<T> {
+    fn from(pinned: PinBox<T>) -> Box<T> {
+        pinned.inner
+    }
+}
+
+#[unstable(feature = "pin", issue = "49150")]
+impl<T: ?Sized> Deref for PinBox<T> {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        &*self.inner
+    }
+}
+
+#[unstable(feature = "pin", issue = "49150")]
+impl<T: Unpin + ?Sized> DerefMut for PinBox<T> {
+    fn deref_mut(&mut self) -> &mut T {
+        &mut *self.inner
+    }
+}
+
+#[unstable(feature = "pin", issue = "49150")]
+impl<T: fmt::Display + ?Sized> fmt::Display for PinBox<T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Display::fmt(&*self.inner, f)
+    }
+}
+
+#[unstable(feature = "pin", issue = "49150")]
+impl<T: fmt::Debug + ?Sized> fmt::Debug for PinBox<T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Debug::fmt(&*self.inner, f)
+    }
+}
+
+#[unstable(feature = "pin", issue = "49150")]
+impl<T: ?Sized> fmt::Pointer for PinBox<T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        // It's not possible to extract the inner Uniq directly from the Box,
+        // instead we cast it to a *const which aliases the Unique
+        let ptr: *const T = &*self.inner;
+        fmt::Pointer::fmt(&ptr, f)
+    }
+}
+
+#[unstable(feature = "pin", issue = "49150")]
+impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<PinBox<U>> for PinBox<T> {}
index a092bfb3b0a8a5899da6d8d5955cd5101bc4cc6e..90043e1c716b6720545da4d8d8fa9ab5e50ec659 100644 (file)
 //!
 //! * *nothing* â‡’ [`Display`]
 //! * `?` â‡’ [`Debug`]
+//! * `x?` â‡’ [`Debug`] with lower-case hexadecimal integers
+//! * `X?` â‡’ [`Debug`] with upper-case hexadecimal integers
 //! * `o` â‡’ [`Octal`](trait.Octal.html)
 //! * `x` â‡’ [`LowerHex`](trait.LowerHex.html)
 //! * `X` â‡’ [`UpperHex`](trait.UpperHex.html)
index 2727bcaa28a9311c9f8d8d5bbdf5ced4ddde410c..f914b1a93a9162155f654a87befa812388005de4 100644 (file)
 #![feature(offset_to)]
 #![feature(optin_builtin_traits)]
 #![feature(pattern)]
+#![feature(pin)]
 #![feature(placement_in_syntax)]
 #![feature(placement_new_protocol)]
 #![feature(ptr_internals)]
 #![feature(rustc_attrs)]
 #![feature(slice_get_slice)]
-#![feature(slice_patterns)]
 #![feature(slice_rsplit)]
 #![feature(specialization)]
 #![feature(staged_api)]
index d9e9d91cea88a06d5a39d74363610a3991945477..3f679d81f08de9bd59a5019ddfd12033ebd59310 100644 (file)
@@ -1351,7 +1351,7 @@ fn test_copy_from_slice_dst_shorter() {
 const MAX_LEN: usize = 80;
 
 static DROP_COUNTS: [AtomicUsize; MAX_LEN] = [
-    // FIXME #5244: AtomicUsize is not Copy.
+    // FIXME(RFC 1109): AtomicUsize is not Copy.
     AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
     AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
     AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
index 201064e823b1e6ecee851126f444c408fed73063..c947b003ccbffaa697586bfb32b5bc528687c142 100644 (file)
@@ -11,7 +11,6 @@
 #![deny(warnings)]
 
 #![feature(flt2dec)]
-#![feature(slice_patterns)]
 #![feature(test)]
 
 extern crate core;
index 61558034e63eb765912b6f75015a0017ed0bd549..f45a32d4b94acd8a83f2da8643fb2823f9349c95 100644 (file)
 
 /// A trait for borrowing data.
 ///
-/// In general, there may be several ways to "borrow" a piece of data.  The
-/// typical ways of borrowing a type `T` are `&T` (a shared borrow) and `&mut T`
-/// (a mutable borrow). But types like `Vec<T>` provide additional kinds of
-/// borrows: the borrowed slices `&[T]` and `&mut [T]`.
+/// In Rust, it is common to provide different representations of a type for
+/// different use cases. For instance, storage location and management for a
+/// value can be specifically chosen as appropriate for a particular use via
+/// pointer types such as [`Box<T>`] or [`Rc<T>`]. Beyond these generic
+/// wrappers that can be used with any type, some types provide optional
+/// facets providing potentially costly functionality. An example for such a
+/// type is [`String`] which adds the ability to extend a string to the basic
+/// [`str`]. This requires keeping additional information unnecessary for a
+/// simple, immutable string.
 ///
-/// When writing generic code, it is often desirable to abstract over all ways
-/// of borrowing data from a given type. That is the role of the `Borrow`
-/// trait: if `T: Borrow<U>`, then `&U` can be borrowed from `&T`.  A given
-/// type can be borrowed as multiple different types. In particular, `Vec<T>:
-/// Borrow<Vec<T>>` and `Vec<T>: Borrow<[T]>`.
+/// These types provide access to the underlying data through references
+/// to the type of that data. They are said to be â€˜borrowed as’ that type.
+/// For instance, a [`Box<T>`] can be borrowed as `T` while a [`String`]
+/// can be borrowed as `str`.
 ///
-/// If you are implementing `Borrow` and both `Self` and `Borrowed` implement
-/// `Hash`, `Eq`, and/or `Ord`, they must produce the same result.
+/// Types express that they can be borrowed as some type `T` by implementing
+/// `Borrow<T>`, providing a reference to a `T` in the trait’s
+/// [`borrow`] method. A type is free to borrow as several different types.
+/// If it wishes to mutably borrow as the type â€“ allowing the underlying data
+/// to be modified, it can additionally implement [`BorrowMut<T>`].
 ///
-/// `Borrow` is very similar to, but different than, `AsRef`. See
-/// [the book][book] for more.
+/// Further, when providing implementations for additional traits, it needs
+/// to be considered whether they should behave identical to those of the
+/// underlying type as a consequence of acting as a representation of that
+/// underlying type. Generic code typically uses `Borrow<T>` when it relies
+/// on the identical behavior of these additional trait implementations.
+/// These traits will likely appear as additional trait bounds.
 ///
-/// [book]: ../../book/first-edition/borrow-and-asref.html
+/// If generic code merely needs to work for all types that can
+/// provide a reference to related type `T`, it is often better to use
+/// [`AsRef<T>`] as more types can safely implement it.
+///
+/// [`AsRef<T>`]: ../../std/convert/trait.AsRef.html
+/// [`BorrowMut<T>`]: trait.BorrowMut.html
+/// [`Box<T>`]: ../../std/boxed/struct.Box.html
+/// [`Mutex<T>`]: ../../std/sync/struct.Mutex.html
+/// [`Rc<T>`]: ../../std/rc/struct.Rc.html
+/// [`str`]: ../../std/primitive.str.html
+/// [`String`]: ../../std/string/struct.String.html
+/// [`borrow`]: #tymethod.borrow
+///
+/// # Examples
+///
+/// As a data collection, [`HashMap<K, V>`] owns both keys and values. If
+/// the key’s actual data is wrapped in a managing type of some kind, it
+/// should, however, still be possible to search for a value using a
+/// reference to the key’s data. For instance, if the key is a string, then
+/// it is likely stored with the hash map as a [`String`], while it should
+/// be possible to search using a [`&str`][`str`]. Thus, `insert` needs to
+/// operate on a `String` while `get` needs to be able to use a `&str`.
+///
+/// Slightly simplified, the relevant parts of `HashMap<K, V>` look like
+/// this:
+///
+/// ```
+/// use std::borrow::Borrow;
+/// use std::hash::Hash;
+///
+/// pub struct HashMap<K, V> {
+///     # marker: ::std::marker::PhantomData<(K, V)>,
+///     // fields omitted
+/// }
+///
+/// impl<K, V> HashMap<K, V> {
+///     pub fn insert(&self, key: K, value: V) -> Option<V>
+///     where K: Hash + Eq
+///     {
+///         # unimplemented!()
+///         // ...
+///     }
+///
+///     pub fn get<Q>(&self, k: &Q) -> Option<&V>
+///     where
+///         K: Borrow<Q>,
+///         Q: Hash + Eq + ?Sized
+///     {
+///         # unimplemented!()
+///         // ...
+///     }
+/// }
+/// ```
+///
+/// The entire hash map is generic over a key type `K`. Because these keys
+/// are stored with the hash map, this type has to own the key’s data.
+/// When inserting a key-value pair, the map is given such a `K` and needs
+/// to find the correct hash bucket and check if the key is already present
+/// based on that `K`. It therefore requires `K: Hash + Eq`.
+///
+/// When searching for a value in the map, however, having to provide a
+/// reference to a `K` as the key to search for would require to always
+/// create such an owned value. For string keys, this would mean a `String`
+/// value needs to be created just for the search for cases where only a
+/// `str` is available.
+///
+/// Instead, the `get` method is generic over the type of the underlying key
+/// data, called `Q` in the method signature above. It states that `K`
+/// borrows as a `Q` by requiring that `K: Borrow<Q>`. By additionally
+/// requiring `Q: Hash + Eq`, it signals the requirement that `K` and `Q`
+/// have implementations of the `Hash` and `Eq` traits that produce identical
+/// results.
+///
+/// The implementation of `get` relies in particular on identical
+/// implementations of `Hash` by determining the key’s hash bucket by calling
+/// `Hash::hash` on the `Q` value even though it inserted the key based on
+/// the hash value calculated from the `K` value.
+///
+/// As a consequence, the hash map breaks if a `K` wrapping a `Q` value
+/// produces a different hash than `Q`. For instance, imagine you have a
+/// type that wraps a string but compares ASCII letters ignoring their case:
+///
+/// ```
+/// pub struct CaseInsensitiveString(String);
+///
+/// impl PartialEq for CaseInsensitiveString {
+///     fn eq(&self, other: &Self) -> bool {
+///         self.0.eq_ignore_ascii_case(&other.0)
+///     }
+/// }
+///
+/// impl Eq for CaseInsensitiveString { }
+/// ```
+///
+/// Because two equal values need to produce the same hash value, the
+/// implementation of `Hash` needs to ignore ASCII case, too:
+///
+/// ```
+/// # use std::hash::{Hash, Hasher};
+/// # pub struct CaseInsensitiveString(String);
+/// impl Hash for CaseInsensitiveString {
+///     fn hash<H: Hasher>(&self, state: &mut H) {
+///         for c in self.0.as_bytes() {
+///             c.to_ascii_lowercase().hash(state)
+///         }
+///     }
+/// }
+/// ```
+///
+/// Can `CaseInsensitiveString` implement `Borrow<str>`? It certainly can
+/// provide a reference to a string slice via its contained owned string.
+/// But because its `Hash` implementation differs, it behaves differently
+/// from `str` and therefore must not, in fact, implement `Borrow<str>`.
+/// If it wants to allow others access to the underlying `str`, it can do
+/// that via `AsRef<str>` which doesn’t carry any extra requirements.
+///
+/// [`Hash`]: ../../std/hash/trait.Hash.html
+/// [`HashMap<K, V>`]: ../../std/collections/struct.HashMap.html
+/// [`String`]: ../../std/string/struct.String.html
+/// [`str`]: ../../std/primitive.str.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Borrow<Borrowed: ?Sized> {
     /// Immutably borrows from an owned value.
@@ -59,7 +189,11 @@ pub trait Borrow<Borrowed: ?Sized> {
 
 /// A trait for mutably borrowing data.
 ///
-/// Similar to `Borrow`, but for mutable borrows.
+/// As a companion to [`Borrow<T>`] this trait allows a type to borrow as
+/// an underlying type by providing a mutable reference. See [`Borrow<T>`]
+/// for more information on borrowing as another type.
+///
+/// [`Borrow<T>`]: trait.Borrow.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait BorrowMut<Borrowed: ?Sized> : Borrow<Borrowed> {
     /// Mutably borrows from an owned value.
index d3a83dc795c8577040b83b1c0e0440b826bf2880..2206910c93f61b66b18e5da619132c5d2ebe6721 100644 (file)
@@ -382,7 +382,7 @@ fn as_ref(&self) -> &U {
     }
 }
 
-// FIXME (#23442): replace the above impls for &/&mut with the following more general one:
+// FIXME (#45742): replace the above impls for &/&mut with the following more general one:
 // // As lifts over Deref
 // impl<D: ?Sized + Deref, U: ?Sized> AsRef<U> for D where D::Target: AsRef<U> {
 //     fn as_ref(&self) -> &U {
@@ -399,7 +399,7 @@ fn as_mut(&mut self) -> &mut U {
     }
 }
 
-// FIXME (#23442): replace the above impl for &mut with the following more general one:
+// FIXME (#45742): replace the above impl for &mut with the following more general one:
 // // AsMut lifts over DerefMut
 // impl<D: ?Sized + Deref, U: ?Sized> AsMut<U> for D where D::Target: AsMut<U> {
 //     fn as_mut(&mut self) -> &mut U {
index 67126b496e211c5e1ddb6d44c396f567168a702e..3ecd73873c09195a35bff6fadac166a9111b523e 100644 (file)
@@ -333,7 +333,7 @@ fn as_usize(&self) -> Option<usize> {
 
 // flags available in the v1 format of format_args
 #[derive(Copy, Clone)]
-enum FlagV1 { SignPlus, SignMinus, Alternate, SignAwareZeroPad, }
+enum FlagV1 { SignPlus, SignMinus, Alternate, SignAwareZeroPad, DebugLowerHex, DebugUpperHex }
 
 impl<'a> Arguments<'a> {
     /// When using the format_args!() macro, this function is used to generate the
@@ -1537,6 +1537,12 @@ pub fn sign_aware_zero_pad(&self) -> bool {
         self.flags & (1 << FlagV1::SignAwareZeroPad as u32) != 0
     }
 
+    // FIXME: Decide what public API we want for these two flags.
+    // https://github.com/rust-lang/rust/issues/48584
+    fn debug_lower_hex(&self) -> bool { self.flags & (1 << FlagV1::DebugLowerHex as u32) != 0 }
+
+    fn debug_upper_hex(&self) -> bool { self.flags & (1 << FlagV1::DebugUpperHex as u32) != 0 }
+
     /// Creates a [`DebugStruct`] builder designed to assist with creation of
     /// [`fmt::Debug`] implementations for structs.
     ///
index 2992e7cf8db341cf0fde7730212752b19ed70096..fcf06ea319d4382b05d88420bd96237557a7a709 100644 (file)
@@ -49,15 +49,13 @@ fn to_u128(&self) -> u128 { *self as u128 }
 #[doc(hidden)]
 trait GenericRadix {
     /// The number of digits.
-    fn base(&self) -> u8;
+    const BASE: u8;
 
     /// A radix-specific prefix string.
-    fn prefix(&self) -> &'static str {
-        ""
-    }
+    const PREFIX: &'static str;
 
     /// Converts an integer to corresponding radix digit.
-    fn digit(&self, x: u8) -> u8;
+    fn digit(x: u8) -> u8;
 
     /// Format an integer using the radix using a formatter.
     fn fmt_int<T: Int>(&self, mut x: T, f: &mut fmt::Formatter) -> fmt::Result {
@@ -67,14 +65,14 @@ fn fmt_int<T: Int>(&self, mut x: T, f: &mut fmt::Formatter) -> fmt::Result {
         let is_nonnegative = x >= zero;
         let mut buf = [0; 128];
         let mut curr = buf.len();
-        let base = T::from_u8(self.base());
+        let base = T::from_u8(Self::BASE);
         if is_nonnegative {
             // Accumulate each digit of the number from the least significant
             // to the most significant figure.
             for byte in buf.iter_mut().rev() {
-                let n = x % base;              // Get the current place value.
-                x = x / base;                  // Deaccumulate the number.
-                *byte = self.digit(n.to_u8()); // Store the digit in the buffer.
+                let n = x % base;               // Get the current place value.
+                x = x / base;                   // Deaccumulate the number.
+                *byte = Self::digit(n.to_u8()); // Store the digit in the buffer.
                 curr -= 1;
                 if x == zero {
                     // No more digits left to accumulate.
@@ -84,9 +82,9 @@ fn fmt_int<T: Int>(&self, mut x: T, f: &mut fmt::Formatter) -> fmt::Result {
         } else {
             // Do the same as above, but accounting for two's complement.
             for byte in buf.iter_mut().rev() {
-                let n = zero - (x % base);     // Get the current place value.
-                x = x / base;                  // Deaccumulate the number.
-                *byte = self.digit(n.to_u8()); // Store the digit in the buffer.
+                let n = zero - (x % base);      // Get the current place value.
+                x = x / base;                   // Deaccumulate the number.
+                *byte = Self::digit(n.to_u8()); // Store the digit in the buffer.
                 curr -= 1;
                 if x == zero {
                     // No more digits left to accumulate.
@@ -95,7 +93,7 @@ fn fmt_int<T: Int>(&self, mut x: T, f: &mut fmt::Formatter) -> fmt::Result {
             }
         }
         let buf = unsafe { str::from_utf8_unchecked(&buf[curr..]) };
-        f.pad_integral(is_nonnegative, self.prefix(), buf)
+        f.pad_integral(is_nonnegative, Self::PREFIX, buf)
     }
 }
 
@@ -122,12 +120,12 @@ fn fmt_int<T: Int>(&self, mut x: T, f: &mut fmt::Formatter) -> fmt::Result {
 macro_rules! radix {
     ($T:ident, $base:expr, $prefix:expr, $($x:pat => $conv:expr),+) => {
         impl GenericRadix for $T {
-            fn base(&self) -> u8 { $base }
-            fn prefix(&self) -> &'static str { $prefix }
-            fn digit(&self, x: u8) -> u8 {
+            const BASE: u8 = $base;
+            const PREFIX: &'static str = $prefix;
+            fn digit(x: u8) -> u8 {
                 match x {
                     $($x => $conv,)+
-                    x => panic!("number not in the range 0..{}: {}", self.base() - 1, x),
+                    x => panic!("number not in the range 0..{}: {}", Self::BASE - 1, x),
                 }
             }
         }
@@ -159,7 +157,13 @@ macro_rules! debug {
         impl fmt::Debug for $T {
             #[inline]
             fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-                fmt::Display::fmt(self, f)
+                if f.debug_lower_hex() {
+                    fmt::LowerHex::fmt(self, f)
+                } else if f.debug_upper_hex() {
+                    fmt::UpperHex::fmt(self, f)
+                } else {
+                    fmt::Display::fmt(self, f)
+                }
             }
         }
     }
index 15545a04b64de04e7b37e8115ad8d6b491a92cd4..ab714645675af153fb5473534cb4a0177694319a 100644 (file)
 #[allow(deprecated)]
 pub use self::sip::SipHasher;
 
-#[unstable(feature = "sip_hash_13", issue = "34767")]
+#[unstable(feature = "hashmap_internals", issue = "0")]
 #[allow(deprecated)]
-pub use self::sip::{SipHasher13, SipHasher24};
+#[doc(hidden)]
+pub use self::sip::SipHasher13;
 
 mod sip;
 
index 4e4d9b3f1e2f0585cfc9c3be3c366bb973268f27..e3bdecdc4b1fd714ede210948c373d048bf30abe 100644 (file)
 /// (eg. `collections::HashMap` uses it by default).
 ///
 /// See: <https://131002.net/siphash>
-#[unstable(feature = "sip_hash_13", issue = "34767")]
+#[unstable(feature = "hashmap_internals", issue = "0")]
 #[rustc_deprecated(since = "1.13.0",
                    reason = "use `std::collections::hash_map::DefaultHasher` instead")]
 #[derive(Debug, Clone, Default)]
+#[doc(hidden)]
 pub struct SipHasher13 {
     hasher: Hasher<Sip13Rounds>,
 }
@@ -34,11 +35,11 @@ pub struct SipHasher13 {
 /// An implementation of SipHash 2-4.
 ///
 /// See: <https://131002.net/siphash/>
-#[unstable(feature = "sip_hash_13", issue = "34767")]
+#[unstable(feature = "hashmap_internals", issue = "0")]
 #[rustc_deprecated(since = "1.13.0",
                    reason = "use `std::collections::hash_map::DefaultHasher` instead")]
 #[derive(Debug, Clone, Default)]
-pub struct SipHasher24 {
+struct SipHasher24 {
     hasher: Hasher<Sip24Rounds>,
 }
 
@@ -156,14 +157,16 @@ pub fn new() -> SipHasher {
     #[rustc_deprecated(since = "1.13.0",
                        reason = "use `std::collections::hash_map::DefaultHasher` instead")]
     pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher {
-        SipHasher(SipHasher24::new_with_keys(key0, key1))
+        SipHasher(SipHasher24 {
+            hasher: Hasher::new_with_keys(key0, key1)
+        })
     }
 }
 
 impl SipHasher13 {
     /// Creates a new `SipHasher13` with the two initial keys set to 0.
     #[inline]
-    #[unstable(feature = "sip_hash_13", issue = "34767")]
+    #[unstable(feature = "hashmap_internals", issue = "0")]
     #[rustc_deprecated(since = "1.13.0",
                        reason = "use `std::collections::hash_map::DefaultHasher` instead")]
     pub fn new() -> SipHasher13 {
@@ -172,7 +175,7 @@ pub fn new() -> SipHasher13 {
 
     /// Creates a `SipHasher13` that is keyed off the provided keys.
     #[inline]
-    #[unstable(feature = "sip_hash_13", issue = "34767")]
+    #[unstable(feature = "hashmap_internals", issue = "0")]
     #[rustc_deprecated(since = "1.13.0",
                        reason = "use `std::collections::hash_map::DefaultHasher` instead")]
     pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher13 {
@@ -182,28 +185,6 @@ pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher13 {
     }
 }
 
-impl SipHasher24 {
-    /// Creates a new `SipHasher24` with the two initial keys set to 0.
-    #[inline]
-    #[unstable(feature = "sip_hash_13", issue = "34767")]
-    #[rustc_deprecated(since = "1.13.0",
-                       reason = "use `std::collections::hash_map::DefaultHasher` instead")]
-    pub fn new() -> SipHasher24 {
-        SipHasher24::new_with_keys(0, 0)
-    }
-
-    /// Creates a `SipHasher24` that is keyed off the provided keys.
-    #[inline]
-    #[unstable(feature = "sip_hash_13", issue = "34767")]
-    #[rustc_deprecated(since = "1.13.0",
-                       reason = "use `std::collections::hash_map::DefaultHasher` instead")]
-    pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher24 {
-        SipHasher24 {
-            hasher: Hasher::new_with_keys(key0, key1)
-        }
-    }
-}
-
 impl<S: Sip> Hasher<S> {
     #[inline]
     fn new_with_keys(key0: u64, key1: u64) -> Hasher<S> {
@@ -271,16 +252,16 @@ fn short_write(&mut self, msg: &[u8]) {
 impl super::Hasher for SipHasher {
     #[inline]
     fn write(&mut self, msg: &[u8]) {
-        self.0.write(msg)
+        self.0.hasher.write(msg)
     }
 
     #[inline]
     fn finish(&self) -> u64 {
-        self.0.finish()
+        self.0.hasher.finish()
     }
 }
 
-#[unstable(feature = "sip_hash_13", issue = "34767")]
+#[unstable(feature = "hashmap_internals", issue = "0")]
 impl super::Hasher for SipHasher13 {
     #[inline]
     fn write(&mut self, msg: &[u8]) {
@@ -293,19 +274,6 @@ fn finish(&self) -> u64 {
     }
 }
 
-#[unstable(feature = "sip_hash_13", issue = "34767")]
-impl super::Hasher for SipHasher24 {
-    #[inline]
-    fn write(&mut self, msg: &[u8]) {
-        self.hasher.write(msg)
-    }
-
-    #[inline]
-    fn finish(&self) -> u64 {
-        self.hasher.finish()
-    }
-}
-
 impl<S: Sip> super::Hasher for Hasher<S> {
     // see short_write comment for explanation
     #[inline]
index b1b783b47c72b1b19dc0a70834c020e6aaf2cd69..1e8476d3880c8a4fc197c0c95e647ebca69ccf62 100644 (file)
@@ -1872,7 +1872,7 @@ fn count(mut self) -> usize {
 
     #[inline]
     fn nth(&mut self, n: usize) -> Option<I::Item> {
-        // FIXME(#6393): merge these when borrow-checking gets better.
+        // FIXME(#43234): merge these when borrow-checking gets better.
         if n == 0 {
             match self.peeked.take() {
                 Some(v) => v,
index 53b1d1cd12de33f3dfe602f42b9637796e3a24aa..f8a33961811c0ee3e9ac28bac3d6e16e265c0ab0 100644 (file)
@@ -578,3 +578,13 @@ unsafe impl<T: ?Sized> Freeze for *const T {}
 unsafe impl<T: ?Sized> Freeze for *mut T {}
 unsafe impl<'a, T: ?Sized> Freeze for &'a T {}
 unsafe impl<'a, T: ?Sized> Freeze for &'a mut T {}
+
+/// Types which can be moved out of a `Pin`.
+///
+/// The `Unpin` trait is used to control the behavior of the [`Pin`] type. If a
+/// type implements `Unpin`, it is safe to move a value of that type out of the
+/// `Pin` pointer.
+///
+/// This trait is automatically implemented for almost every type.
+#[unstable(feature = "pin", issue = "49150")]
+pub unsafe auto trait Unpin {}
index 21a0beccbf64d604e32dcfbfd86daa9da116197c..b2467c948b4b156506dabb8c771e73736e6569d0 100644 (file)
@@ -20,9 +20,9 @@
 use fmt;
 use hash;
 use intrinsics;
-use marker::{Copy, PhantomData, Sized};
+use marker::{Copy, PhantomData, Sized, Unpin, Unsize};
 use ptr;
-use ops::{Deref, DerefMut};
+use ops::{Deref, DerefMut, CoerceUnsized};
 
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use intrinsics::transmute;
@@ -1105,3 +1105,111 @@ fn hash<H: ::hash::Hasher>(&self, state: &mut H) {
 pub unsafe fn unreachable() -> ! {
     intrinsics::unreachable()
 }
+
+/// A pinned reference.
+///
+/// A pinned reference is a lot like a mutable reference, except that it is not
+/// safe to move a value out of a pinned reference unless the type of that
+/// value implements the `Unpin` trait.
+#[unstable(feature = "pin", issue = "49150")]
+#[fundamental]
+pub struct Pin<'a, T: ?Sized + 'a> {
+    inner: &'a mut T,
+}
+
+#[unstable(feature = "pin", issue = "49150")]
+impl<'a, T: ?Sized + Unpin> Pin<'a, T> {
+    /// Construct a new `Pin` around a reference to some data of a type that
+    /// implements `Unpin`.
+    #[unstable(feature = "pin", issue = "49150")]
+    pub fn new(reference: &'a mut T) -> Pin<'a, T> {
+        Pin { inner: reference }
+    }
+}
+
+
+#[unstable(feature = "pin", issue = "49150")]
+impl<'a, T: ?Sized> Pin<'a, T> {
+    /// Construct a new `Pin` around a reference to some data of a type that
+    /// may or may not implement `Unpin`.
+    ///
+    /// This constructor is unsafe because we do not know what will happen with
+    /// that data after the reference ends. If you cannot guarantee that the
+    /// data will never move again, calling this constructor is invalid.
+    #[unstable(feature = "pin", issue = "49150")]
+    pub unsafe fn new_unchecked(reference: &'a mut T) -> Pin<'a, T> {
+        Pin { inner: reference }
+    }
+
+    /// Borrow a Pin for a shorter lifetime than it already has.
+    #[unstable(feature = "pin", issue = "49150")]
+    pub fn borrow<'b>(this: &'b mut Pin<'a, T>) -> Pin<'b, T> {
+        Pin { inner: this.inner }
+    }
+
+    /// Get a mutable reference to the data inside of this `Pin`.
+    ///
+    /// This function is unsafe. You must guarantee that you will never move
+    /// the data out of the mutable reference you receive when you call this
+    /// function.
+    #[unstable(feature = "pin", issue = "49150")]
+    pub unsafe fn get_mut<'b>(this: &'b mut Pin<'a, T>) -> &'b mut T {
+        this.inner
+    }
+
+    /// Construct a new pin by mapping the interior value.
+    ///
+    /// For example, if you  wanted to get a `Pin` of a field of something, you
+    /// could use this to get access to that field in one line of code.
+    ///
+    /// This function is unsafe. You must guarantee that the data you return
+    /// will not move so long as the argument value does not move (for example,
+    /// because it is one of the fields of that value), and also that you do
+    /// not move out of the argument you receive to the interior function.
+    #[unstable(feature = "pin", issue = "49150")]
+    pub unsafe fn map<'b, U, F>(this: &'b mut Pin<'a, T>, f: F) -> Pin<'b, U> where
+        F: FnOnce(&mut T) -> &mut U
+    {
+        Pin { inner: f(this.inner) }
+    }
+}
+
+#[unstable(feature = "pin", issue = "49150")]
+impl<'a, T: ?Sized> Deref for Pin<'a, T> {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        &*self.inner
+    }
+}
+
+#[unstable(feature = "pin", issue = "49150")]
+impl<'a, T: ?Sized + Unpin> DerefMut for Pin<'a, T> {
+    fn deref_mut(&mut self) -> &mut T {
+        self.inner
+    }
+}
+
+#[unstable(feature = "pin", issue = "49150")]
+impl<'a, T: fmt::Debug + ?Sized> fmt::Debug for Pin<'a, T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Debug::fmt(&**self, f)
+    }
+}
+
+#[unstable(feature = "pin", issue = "49150")]
+impl<'a, T: fmt::Display + ?Sized> fmt::Display for Pin<'a, T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Display::fmt(&**self, f)
+    }
+}
+
+#[unstable(feature = "pin", issue = "49150")]
+impl<'a, T: ?Sized> fmt::Pointer for Pin<'a, T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Pointer::fmt(&(&*self.inner as *const T), f)
+    }
+}
+
+#[unstable(feature = "pin", issue = "49150")]
+impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Pin<'a, U>> for Pin<'a, T> {}
index ae1b0b3ce11b209cfff581408724b3a05a4c864f..826883fdc3f01de6bf0f3f08ae47f66d6893359a 100644 (file)
@@ -317,11 +317,320 @@ fn neg(self) -> Self {
         }
         forward_ref_unop! { impl Neg, neg for Wrapping<$t>,
                 #[stable(feature = "wrapping_ref", since = "1.14.0")] }
+
     )*)
 }
 
 wrapping_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 
+macro_rules! wrapping_int_impl {
+    ($($t:ty)*) => ($(
+        impl Wrapping<$t> {
+            /// Returns the number of ones in the binary representation of
+            /// `self`.
+            ///
+            /// # Examples
+            ///
+            /// Basic usage:
+            ///
+            /// ```
+            /// #![feature(wrapping_int_impl)]
+            /// use std::num::Wrapping;
+            ///
+            /// let n: Wrapping<i8> = Wrapping(-0b1000_0000);
+            ///
+            /// assert_eq!(n.count_ones(), 1);
+            /// ```
+            #[inline]
+            #[unstable(feature = "wrapping_int_impl", issue = "32463")]
+            pub fn count_ones(self) -> u32 {
+                self.0.count_ones()
+            }
+
+            /// Returns the number of zeros in the binary representation of
+            /// `self`.
+            ///
+            /// # Examples
+            ///
+            /// Basic usage:
+            ///
+            /// ```
+            /// #![feature(wrapping_int_impl)]
+            /// use std::num::Wrapping;
+            ///
+            /// let n: Wrapping<i8> = Wrapping(-0b1000_0000);
+            ///
+            /// assert_eq!(n.count_zeros(), 7);
+            /// ```
+            #[inline]
+            #[unstable(feature = "wrapping_int_impl", issue = "32463")]
+            pub fn count_zeros(self) -> u32 {
+                self.0.count_zeros()
+            }
+
+            /// Returns the number of leading zeros in the binary representation
+            /// of `self`.
+            ///
+            /// # Examples
+            ///
+            /// Basic usage:
+            ///
+            /// ```
+            /// #![feature(wrapping_int_impl)]
+            /// use std::num::Wrapping;
+            ///
+            /// let n: Wrapping<i16> = Wrapping(-1);
+            ///
+            /// assert_eq!(n.leading_zeros(), 0);
+            /// ```
+            #[inline]
+            #[unstable(feature = "wrapping_int_impl", issue = "32463")]
+            pub fn leading_zeros(self) -> u32 {
+                self.0.leading_zeros()
+            }
+
+            /// Returns the number of trailing zeros in the binary representation
+            /// of `self`.
+            ///
+            /// # Examples
+            ///
+            /// Basic usage:
+            ///
+            /// ```
+            /// #![feature(wrapping_int_impl)]
+            /// use std::num::Wrapping;
+            ///
+            /// let n: Wrapping<i8> = Wrapping(-4);
+            ///
+            /// assert_eq!(n.trailing_zeros(), 2);
+            /// ```
+            #[inline]
+            #[unstable(feature = "wrapping_int_impl", issue = "32463")]
+            pub fn trailing_zeros(self) -> u32 {
+                self.0.trailing_zeros()
+            }
+
+            /// Shifts the bits to the left by a specified amount, `n`,
+            /// wrapping the truncated bits to the end of the resulting
+            /// integer.
+            ///
+            /// Please note this isn't the same operation as `>>`!
+            ///
+            /// # Examples
+            ///
+            /// Basic usage:
+            ///
+            /// ```
+            /// #![feature(wrapping_int_impl)]
+            /// use std::num::Wrapping;
+            ///
+            /// let n: Wrapping<i64> = Wrapping(0x0123456789ABCDEF);
+            /// let m: Wrapping<i64> = Wrapping(-0x76543210FEDCBA99);
+            ///
+            /// assert_eq!(n.rotate_left(32), m);
+            /// ```
+            #[inline]
+            #[unstable(feature = "wrapping_int_impl", issue = "32463")]
+            pub fn rotate_left(self, n: u32) -> Self {
+                Wrapping(self.0.rotate_left(n))
+            }
+
+            /// Shifts the bits to the right by a specified amount, `n`,
+            /// wrapping the truncated bits to the beginning of the resulting
+            /// integer.
+            ///
+            /// Please note this isn't the same operation as `<<`!
+            ///
+            /// # Examples
+            ///
+            /// Basic usage:
+            ///
+            /// ```
+            /// #![feature(wrapping_int_impl)]
+            /// use std::num::Wrapping;
+            ///
+            /// let n: Wrapping<i64> = Wrapping(0x0123456789ABCDEF);
+            /// let m: Wrapping<i64> = Wrapping(-0xFEDCBA987654322);
+            ///
+            /// assert_eq!(n.rotate_right(4), m);
+            /// ```
+            #[inline]
+            #[unstable(feature = "wrapping_int_impl", issue = "32463")]
+            pub fn rotate_right(self, n: u32) -> Self {
+                Wrapping(self.0.rotate_right(n))
+            }
+
+            /// Reverses the byte order of the integer.
+            ///
+            /// # Examples
+            ///
+            /// Basic usage:
+            ///
+            /// ```
+            /// #![feature(wrapping_int_impl)]
+            /// use std::num::Wrapping;
+            ///
+            /// let n: Wrapping<i16> = Wrapping(0b0000000_01010101);
+            /// assert_eq!(n, Wrapping(85));
+            ///
+            /// let m = n.swap_bytes();
+            ///
+            /// assert_eq!(m, Wrapping(0b01010101_00000000));
+            /// assert_eq!(m, Wrapping(21760));
+            /// ```
+            #[inline]
+            #[unstable(feature = "wrapping_int_impl", issue = "32463")]
+            pub fn swap_bytes(self) -> Self {
+                Wrapping(self.0.swap_bytes())
+            }
+
+            /// Converts an integer from big endian to the target's endianness.
+            ///
+            /// On big endian this is a no-op. On little endian the bytes are
+            /// swapped.
+            ///
+            /// # Examples
+            ///
+            /// Basic usage:
+            ///
+            /// ```
+            /// #![feature(wrapping_int_impl)]
+            /// use std::num::Wrapping;
+            ///
+            /// let n: Wrapping<i64> = Wrapping(0x0123456789ABCDEF);
+            ///
+            /// if cfg!(target_endian = "big") {
+            ///     assert_eq!(Wrapping::<i64>::from_be(n), n);
+            /// } else {
+            ///     assert_eq!(Wrapping::<i64>::from_be(n), n.swap_bytes());
+            /// }
+            /// ```
+            #[inline]
+            #[unstable(feature = "wrapping_int_impl", issue = "32463")]
+            pub fn from_be(x: Self) -> Self {
+                Wrapping(<$t>::from_be(x.0))
+            }
+
+            /// Converts an integer from little endian to the target's endianness.
+            ///
+            /// On little endian this is a no-op. On big endian the bytes are
+            /// swapped.
+            ///
+            /// # Examples
+            ///
+            /// Basic usage:
+            ///
+            /// ```
+            /// #![feature(wrapping_int_impl)]
+            /// use std::num::Wrapping;
+            ///
+            /// let n: Wrapping<i64> = Wrapping(0x0123456789ABCDEF);
+            ///
+            /// if cfg!(target_endian = "little") {
+            ///     assert_eq!(Wrapping::<i64>::from_le(n), n);
+            /// } else {
+            ///     assert_eq!(Wrapping::<i64>::from_le(n), n.swap_bytes());
+            /// }
+            /// ```
+            #[inline]
+            #[unstable(feature = "wrapping_int_impl", issue = "32463")]
+            pub fn from_le(x: Self) -> Self {
+                Wrapping(<$t>::from_le(x.0))
+            }
+
+            /// Converts `self` to big endian from the target's endianness.
+            ///
+            /// On big endian this is a no-op. On little endian the bytes are
+            /// swapped.
+            ///
+            /// # Examples
+            ///
+            /// Basic usage:
+            ///
+            /// ```
+            /// #![feature(wrapping_int_impl)]
+            /// use std::num::Wrapping;
+            ///
+            /// let n: Wrapping<i64> = Wrapping(0x0123456789ABCDEF);
+            ///
+            /// if cfg!(target_endian = "big") {
+            ///     assert_eq!(n.to_be(), n);
+            /// } else {
+            ///     assert_eq!(n.to_be(), n.swap_bytes());
+            /// }
+            /// ```
+            #[inline]
+            #[unstable(feature = "wrapping_int_impl", issue = "32463")]
+            pub fn to_be(self) -> Self {
+                Wrapping(self.0.to_be())
+            }
+
+            /// Converts `self` to little endian from the target's endianness.
+            ///
+            /// On little endian this is a no-op. On big endian the bytes are
+            /// swapped.
+            ///
+            /// # Examples
+            ///
+            /// Basic usage:
+            ///
+            /// ```
+            /// #![feature(wrapping_int_impl)]
+            /// use std::num::Wrapping;
+            ///
+            /// let n: Wrapping<i64> = Wrapping(0x0123456789ABCDEF);
+            ///
+            /// if cfg!(target_endian = "little") {
+            ///     assert_eq!(n.to_le(), n);
+            /// } else {
+            ///     assert_eq!(n.to_le(), n.swap_bytes());
+            /// }
+            /// ```
+            #[inline]
+            #[unstable(feature = "wrapping_int_impl", issue = "32463")]
+            pub fn to_le(self) -> Self {
+                Wrapping(self.0.to_le())
+            }
+
+            /// Raises self to the power of `exp`, using exponentiation by
+            /// squaring.
+            ///
+            /// # Examples
+            ///
+            /// Basic usage:
+            ///
+            /// ```
+            /// #![feature(wrapping_int_impl)]
+            /// use std::num::Wrapping;
+            ///
+            /// let x: Wrapping<i32> = Wrapping(2); // or any other integer type
+            ///
+            /// assert_eq!(x.pow(4), Wrapping(16));
+            /// ```
+            ///
+            /// Results that are too large are wrapped:
+            ///
+            /// ```
+            /// #![feature(wrapping_int_impl)]
+            /// use std::num::Wrapping;
+            ///
+            /// // 5 ^ 4 = 625, which is too big for a u8
+            /// let x: Wrapping<u8> = Wrapping(5);
+            ///
+            /// assert_eq!(x.pow(4).0, 113);
+            /// ```
+            #[inline]
+            #[unstable(feature = "wrapping_int_impl", issue = "32463")]
+            pub fn pow(self, exp: u32) -> Self {
+                Wrapping(self.0.wrapping_pow(exp))
+            }
+        }
+    )*)
+}
+
+wrapping_int_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
+
+
 mod shift_max {
     #![allow(non_upper_case_globals)]
 
index 25827edee7d9343c0719fc30c4ebad784c35992e..fe5ed5d49422439147d860657366c6d16b061cd8 100644 (file)
@@ -948,6 +948,7 @@ macro_rules! atomic_int {
      $stable_from:meta,
      $stable_nand:meta,
      $s_int_type:expr, $int_ref:expr,
+     $extra_feature:expr,
      $int_type:ident $atomic_type:ident $atomic_init:ident) => {
         /// An integer type which can be safely shared between threads.
         ///
@@ -959,12 +960,7 @@ macro_rules! atomic_int {
         /// ). For more about the differences between atomic types and
         /// non-atomic types, please see the [module-level documentation].
         ///
-        /// Please note that examples are shared between atomic variants of
-        /// primitive integer types, so it's normal that they are all
-        /// demonstrating [`AtomicIsize`].
-        ///
         /// [module-level documentation]: index.html
-        /// [`AtomicIsize`]: struct.AtomicIsize.html
         #[$stable]
         pub struct $atomic_type {
             v: UnsafeCell<$int_type>,
@@ -1001,395 +997,426 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         unsafe impl Sync for $atomic_type {}
 
         impl $atomic_type {
-            /// Creates a new atomic integer.
-            ///
-            /// # Examples
-            ///
-            /// ```
-            /// use std::sync::atomic::AtomicIsize;
-            ///
-            /// let atomic_forty_two  = AtomicIsize::new(42);
-            /// ```
-            #[inline]
-            #[$stable]
-            pub const fn new(v: $int_type) -> Self {
-                $atomic_type {v: UnsafeCell::new(v)}
+            doc_comment! {
+                concat!("Creates a new atomic integer.
+
+# Examples
+
+```
+", $extra_feature, "use std::sync::atomic::", stringify!($atomic_type), ";
+
+let atomic_forty_two = ", stringify!($atomic_type), "::new(42);
+```"),
+                #[inline]
+                #[$stable]
+                pub const fn new(v: $int_type) -> Self {
+                    $atomic_type {v: UnsafeCell::new(v)}
+                }
             }
 
-            /// Returns a mutable reference to the underlying integer.
-            ///
-            /// This is safe because the mutable reference guarantees that no other threads are
-            /// concurrently accessing the atomic data.
-            ///
-            /// # Examples
-            ///
-            /// ```
-            /// use std::sync::atomic::{AtomicIsize, Ordering};
-            ///
-            /// let mut some_isize = AtomicIsize::new(10);
-            /// assert_eq!(*some_isize.get_mut(), 10);
-            /// *some_isize.get_mut() = 5;
-            /// assert_eq!(some_isize.load(Ordering::SeqCst), 5);
-            /// ```
-            #[inline]
-            #[$stable_access]
-            pub fn get_mut(&mut self) -> &mut $int_type {
-                unsafe { &mut *self.v.get() }
+            doc_comment! {
+                concat!("Returns a mutable reference to the underlying integer.
+
+This is safe because the mutable reference guarantees that no other threads are
+concurrently accessing the atomic data.
+
+# Examples
+
+```
+", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
+
+let mut some_var = ", stringify!($atomic_type), "::new(10);
+assert_eq!(*some_var.get_mut(), 10);
+*some_var.get_mut() = 5;
+assert_eq!(some_var.load(Ordering::SeqCst), 5);
+```"),
+                #[inline]
+                #[$stable_access]
+                pub fn get_mut(&mut self) -> &mut $int_type {
+                    unsafe { &mut *self.v.get() }
+                }
             }
 
-            /// Consumes the atomic and returns the contained value.
-            ///
-            /// This is safe because passing `self` by value guarantees that no other threads are
-            /// concurrently accessing the atomic data.
-            ///
-            /// # Examples
-            ///
-            /// ```
-            /// use std::sync::atomic::AtomicIsize;
-            ///
-            /// let some_isize = AtomicIsize::new(5);
-            /// assert_eq!(some_isize.into_inner(), 5);
-            /// ```
-            #[inline]
-            #[$stable_access]
-            pub fn into_inner(self) -> $int_type {
-                self.v.into_inner()
+            doc_comment! {
+                concat!("Consumes the atomic and returns the contained value.
+
+This is safe because passing `self` by value guarantees that no other threads are
+concurrently accessing the atomic data.
+
+# Examples
+
+```
+", $extra_feature, "use std::sync::atomic::", stringify!($atomic_type), ";
+
+let some_var = ", stringify!($atomic_type), "::new(5);
+assert_eq!(some_var.into_inner(), 5);
+```"),
+                #[inline]
+                #[$stable_access]
+                pub fn into_inner(self) -> $int_type {
+                    self.v.into_inner()
+                }
             }
 
-            /// Loads a value from the atomic integer.
-            ///
-            /// `load` takes an [`Ordering`] argument which describes the memory ordering of this
-            /// operation.
-            ///
-            /// # Panics
-            ///
-            /// Panics if `order` is [`Release`] or [`AcqRel`].
-            ///
-            /// [`Ordering`]: enum.Ordering.html
-            /// [`Release`]: enum.Ordering.html#variant.Release
-            /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
-            ///
-            /// # Examples
-            ///
-            /// ```
-            /// use std::sync::atomic::{AtomicIsize, Ordering};
-            ///
-            /// let some_isize = AtomicIsize::new(5);
-            ///
-            /// assert_eq!(some_isize.load(Ordering::Relaxed), 5);
-            /// ```
-            #[inline]
-            #[$stable]
-            pub fn load(&self, order: Ordering) -> $int_type {
-                unsafe { atomic_load(self.v.get(), order) }
+            doc_comment! {
+                concat!("Loads a value from the atomic integer.
+
+`load` takes an [`Ordering`] argument which describes the memory ordering of this operation.
+
+# Panics
+
+Panics if `order` is [`Release`] or [`AcqRel`].
+
+[`Ordering`]: enum.Ordering.html
+[`Release`]: enum.Ordering.html#variant.Release
+[`AcqRel`]: enum.Ordering.html#variant.AcqRel
+
+# Examples
+
+```
+", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
+
+let some_var = ", stringify!($atomic_type), "::new(5);
+
+assert_eq!(some_var.load(Ordering::Relaxed), 5);
+```"),
+                #[inline]
+                #[$stable]
+                pub fn load(&self, order: Ordering) -> $int_type {
+                    unsafe { atomic_load(self.v.get(), order) }
+                }
             }
 
-            /// Stores a value into the atomic integer.
-            ///
-            /// `store` takes an [`Ordering`] argument which describes the memory ordering of this
-            /// operation.
-            ///
-            /// [`Ordering`]: enum.Ordering.html
-            ///
-            /// # Examples
-            ///
-            /// ```
-            /// use std::sync::atomic::{AtomicIsize, Ordering};
-            ///
-            /// let some_isize = AtomicIsize::new(5);
-            ///
-            /// some_isize.store(10, Ordering::Relaxed);
-            /// assert_eq!(some_isize.load(Ordering::Relaxed), 10);
-            /// ```
-            ///
-            /// # Panics
-            ///
-            /// Panics if `order` is [`Acquire`] or [`AcqRel`].
-            ///
-            /// [`Acquire`]: enum.Ordering.html#variant.Acquire
-            /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
-            #[inline]
-            #[$stable]
-            pub fn store(&self, val: $int_type, order: Ordering) {
-                unsafe { atomic_store(self.v.get(), val, order); }
+            doc_comment! {
+                concat!("Stores a value into the atomic integer.
+
+`store` takes an [`Ordering`] argument which describes the memory ordering of this operation.
+
+[`Ordering`]: enum.Ordering.html
+
+# Examples
+
+```
+", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
+
+let some_var = ", stringify!($atomic_type), "::new(5);
+
+some_var.store(10, Ordering::Relaxed);
+assert_eq!(some_var.load(Ordering::Relaxed), 10);
+```
+
+# Panics
+
+Panics if `order` is [`Acquire`] or [`AcqRel`].
+
+[`Acquire`]: enum.Ordering.html#variant.Acquire
+[`AcqRel`]: enum.Ordering.html#variant.AcqRel"),
+                #[inline]
+                #[$stable]
+                pub fn store(&self, val: $int_type, order: Ordering) {
+                    unsafe { atomic_store(self.v.get(), val, order); }
+                }
             }
 
-            /// Stores a value into the atomic integer, returning the previous value.
-            ///
-            /// `swap` takes an [`Ordering`] argument which describes the memory ordering of this
-            /// operation.
-            ///
-            /// [`Ordering`]: enum.Ordering.html
-            ///
-            /// # Examples
-            ///
-            /// ```
-            /// use std::sync::atomic::{AtomicIsize, Ordering};
-            ///
-            /// let some_isize = AtomicIsize::new(5);
-            ///
-            /// assert_eq!(some_isize.swap(10, Ordering::Relaxed), 5);
-            /// ```
-            #[inline]
-            #[$stable]
-            pub fn swap(&self, val: $int_type, order: Ordering) -> $int_type {
-                unsafe { atomic_swap(self.v.get(), val, order) }
+            doc_comment! {
+                concat!("Stores a value into the atomic integer, returning the previous value.
+
+`swap` takes an [`Ordering`] argument which describes the memory ordering of this operation.
+
+[`Ordering`]: enum.Ordering.html
+
+# Examples
+
+```
+", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
+
+let some_var = ", stringify!($atomic_type), "::new(5);
+
+assert_eq!(some_var.swap(10, Ordering::Relaxed), 5);
+```"),
+                #[inline]
+                #[$stable]
+                pub fn swap(&self, val: $int_type, order: Ordering) -> $int_type {
+                    unsafe { atomic_swap(self.v.get(), val, order) }
+                }
             }
 
-            /// Stores a value into the atomic integer if the current value is the same as the
-            /// `current` value.
-            ///
-            /// The return value is always the previous value. If it is equal to `current`, then the
-            /// value was updated.
-            ///
-            /// `compare_and_swap` also takes an [`Ordering`] argument which describes the memory
-            /// ordering of this operation.
-            ///
-            /// [`Ordering`]: enum.Ordering.html
-            ///
-            /// # Examples
-            ///
-            /// ```
-            /// use std::sync::atomic::{AtomicIsize, Ordering};
-            ///
-            /// let some_isize = AtomicIsize::new(5);
-            ///
-            /// assert_eq!(some_isize.compare_and_swap(5, 10, Ordering::Relaxed), 5);
-            /// assert_eq!(some_isize.load(Ordering::Relaxed), 10);
-            ///
-            /// assert_eq!(some_isize.compare_and_swap(6, 12, Ordering::Relaxed), 10);
-            /// assert_eq!(some_isize.load(Ordering::Relaxed), 10);
-            /// ```
-            #[inline]
-            #[$stable]
-            pub fn compare_and_swap(&self,
-                                    current: $int_type,
-                                    new: $int_type,
-                                    order: Ordering) -> $int_type {
-                match self.compare_exchange(current,
-                                            new,
-                                            order,
-                                            strongest_failure_ordering(order)) {
-                    Ok(x) => x,
-                    Err(x) => x,
+            doc_comment! {
+                concat!("Stores a value into the atomic integer if the current value is the same as
+the `current` value.
+
+The return value is always the previous value. If it is equal to `current`, then the
+value was updated.
+
+`compare_and_swap` also takes an [`Ordering`] argument which describes the memory
+ordering of this operation.
+
+[`Ordering`]: enum.Ordering.html
+
+# Examples
+
+```
+", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
+
+let some_var = ", stringify!($atomic_type), "::new(5);
+
+assert_eq!(some_var.compare_and_swap(5, 10, Ordering::Relaxed), 5);
+assert_eq!(some_var.load(Ordering::Relaxed), 10);
+
+assert_eq!(some_var.compare_and_swap(6, 12, Ordering::Relaxed), 10);
+assert_eq!(some_var.load(Ordering::Relaxed), 10);
+```"),
+                #[inline]
+                #[$stable]
+                pub fn compare_and_swap(&self,
+                                        current: $int_type,
+                                        new: $int_type,
+                                        order: Ordering) -> $int_type {
+                    match self.compare_exchange(current,
+                                                new,
+                                                order,
+                                                strongest_failure_ordering(order)) {
+                        Ok(x) => x,
+                        Err(x) => x,
+                    }
                 }
             }
 
-            /// Stores a value into the atomic integer if the current value is the same as the
-            /// `current` value.
-            ///
-            /// The return value is a result indicating whether the new value was written and
-            /// containing the previous value. On success this value is guaranteed to be equal to
-            /// `current`.
-            ///
-            /// `compare_exchange` takes two [`Ordering`] arguments to describe the memory
-            /// ordering of this operation. The first describes the required ordering if
-            /// the operation succeeds while the second describes the required ordering when
-            /// the operation fails. The failure ordering can't be [`Release`] or [`AcqRel`] and
-            /// must be equivalent or weaker than the success ordering.
-            ///
-            /// [`Ordering`]: enum.Ordering.html
-            /// [`Release`]: enum.Ordering.html#variant.Release
-            /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
-            ///
-            /// # Examples
-            ///
-            /// ```
-            /// use std::sync::atomic::{AtomicIsize, Ordering};
-            ///
-            /// let some_isize = AtomicIsize::new(5);
-            ///
-            /// assert_eq!(some_isize.compare_exchange(5, 10,
-            ///                                        Ordering::Acquire,
-            ///                                        Ordering::Relaxed),
-            ///            Ok(5));
-            /// assert_eq!(some_isize.load(Ordering::Relaxed), 10);
-            ///
-            /// assert_eq!(some_isize.compare_exchange(6, 12,
-            ///                                        Ordering::SeqCst,
-            ///                                        Ordering::Acquire),
-            ///            Err(10));
-            /// assert_eq!(some_isize.load(Ordering::Relaxed), 10);
-            /// ```
-            #[inline]
-            #[$stable_cxchg]
-            pub fn compare_exchange(&self,
-                                    current: $int_type,
-                                    new: $int_type,
-                                    success: Ordering,
-                                    failure: Ordering) -> Result<$int_type, $int_type> {
-                unsafe { atomic_compare_exchange(self.v.get(), current, new, success, failure) }
+            doc_comment! {
+                concat!("Stores a value into the atomic integer if the current value is the same as
+the `current` value.
+
+The return value is a result indicating whether the new value was written and
+containing the previous value. On success this value is guaranteed to be equal to
+`current`.
+
+`compare_exchange` takes two [`Ordering`] arguments to describe the memory
+ordering of this operation. The first describes the required ordering if
+the operation succeeds while the second describes the required ordering when
+the operation fails. The failure ordering can't be [`Release`] or [`AcqRel`] and
+must be equivalent or weaker than the success ordering.
+
+[`Ordering`]: enum.Ordering.html
+[`Release`]: enum.Ordering.html#variant.Release
+[`AcqRel`]: enum.Ordering.html#variant.AcqRel
+
+# Examples
+
+```
+", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
+
+let some_var = ", stringify!($atomic_type), "::new(5);
+
+assert_eq!(some_var.compare_exchange(5, 10,
+                                     Ordering::Acquire,
+                                     Ordering::Relaxed),
+           Ok(5));
+assert_eq!(some_var.load(Ordering::Relaxed), 10);
+
+assert_eq!(some_var.compare_exchange(6, 12,
+                                     Ordering::SeqCst,
+                                     Ordering::Acquire),
+           Err(10));
+assert_eq!(some_var.load(Ordering::Relaxed), 10);
+```"),
+                #[inline]
+                #[$stable_cxchg]
+                pub fn compare_exchange(&self,
+                                        current: $int_type,
+                                        new: $int_type,
+                                        success: Ordering,
+                                        failure: Ordering) -> Result<$int_type, $int_type> {
+                    unsafe { atomic_compare_exchange(self.v.get(), current, new, success, failure) }
+                }
             }
 
-            /// Stores a value into the atomic integer if the current value is the same as the
-            /// `current` value.
-            ///
-            /// Unlike [`compare_exchange`], this function is allowed to spuriously fail even
-            /// when the comparison succeeds, which can result in more efficient code on some
-            /// platforms. The return value is a result indicating whether the new value was
-            /// written and containing the previous value.
-            ///
-            /// `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory
-            /// ordering of this operation. The first describes the required ordering if the
-            /// operation succeeds while the second describes the required ordering when the
-            /// operation fails. The failure ordering can't be [`Release`] or [`AcqRel`] and
-            /// must be equivalent or weaker than the success ordering.
-            ///
-            /// [`compare_exchange`]: #method.compare_exchange
-            /// [`Ordering`]: enum.Ordering.html
-            /// [`Release`]: enum.Ordering.html#variant.Release
-            /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
-            ///
-            /// # Examples
-            ///
-            /// ```
-            /// use std::sync::atomic::{AtomicIsize, Ordering};
-            ///
-            /// let val = AtomicIsize::new(4);
-            ///
-            /// let mut old = val.load(Ordering::Relaxed);
-            /// loop {
-            ///     let new = old * 2;
-            ///     match val.compare_exchange_weak(old, new, Ordering::SeqCst, Ordering::Relaxed) {
-            ///         Ok(_) => break,
-            ///         Err(x) => old = x,
-            ///     }
-            /// }
-            /// ```
-            #[inline]
-            #[$stable_cxchg]
-            pub fn compare_exchange_weak(&self,
-                                         current: $int_type,
-                                         new: $int_type,
-                                         success: Ordering,
-                                         failure: Ordering) -> Result<$int_type, $int_type> {
-                unsafe {
-                    atomic_compare_exchange_weak(self.v.get(), current, new, success, failure)
+            doc_comment! {
+                concat!("Stores a value into the atomic integer if the current value is the same as
+the `current` value.
+
+Unlike [`compare_exchange`], this function is allowed to spuriously fail even
+when the comparison succeeds, which can result in more efficient code on some
+platforms. The return value is a result indicating whether the new value was
+written and containing the previous value.
+
+`compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory
+ordering of this operation. The first describes the required ordering if the
+operation succeeds while the second describes the required ordering when the
+operation fails. The failure ordering can't be [`Release`] or [`AcqRel`] and
+must be equivalent or weaker than the success ordering.
+
+[`compare_exchange`]: #method.compare_exchange
+[`Ordering`]: enum.Ordering.html
+[`Release`]: enum.Ordering.html#variant.Release
+[`AcqRel`]: enum.Ordering.html#variant.AcqRel
+
+# Examples
+
+```
+", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
+
+let val = ", stringify!($atomic_type), "::new(4);
+
+let mut old = val.load(Ordering::Relaxed);
+loop {
+    let new = old * 2;
+    match val.compare_exchange_weak(old, new, Ordering::SeqCst, Ordering::Relaxed) {
+        Ok(_) => break,
+        Err(x) => old = x,
+    }
+}
+```"),
+                #[inline]
+                #[$stable_cxchg]
+                pub fn compare_exchange_weak(&self,
+                                             current: $int_type,
+                                             new: $int_type,
+                                             success: Ordering,
+                                             failure: Ordering) -> Result<$int_type, $int_type> {
+                    unsafe {
+                        atomic_compare_exchange_weak(self.v.get(), current, new, success, failure)
+                    }
                 }
             }
 
-            /// Adds to the current value, returning the previous value.
-            ///
-            /// This operation wraps around on overflow.
-            ///
-            /// # Examples
-            ///
-            /// ```
-            /// use std::sync::atomic::{AtomicIsize, Ordering};
-            ///
-            /// let foo = AtomicIsize::new(0);
-            /// assert_eq!(foo.fetch_add(10, Ordering::SeqCst), 0);
-            /// assert_eq!(foo.load(Ordering::SeqCst), 10);
-            /// ```
-            #[inline]
-            #[$stable]
-            pub fn fetch_add(&self, val: $int_type, order: Ordering) -> $int_type {
-                unsafe { atomic_add(self.v.get(), val, order) }
+            doc_comment! {
+                concat!("Adds to the current value, returning the previous value.
+
+This operation wraps around on overflow.
+
+# Examples
+
+```
+", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
+
+let foo = ", stringify!($atomic_type), "::new(0);
+assert_eq!(foo.fetch_add(10, Ordering::SeqCst), 0);
+assert_eq!(foo.load(Ordering::SeqCst), 10);
+```"),
+                #[inline]
+                #[$stable]
+                pub fn fetch_add(&self, val: $int_type, order: Ordering) -> $int_type {
+                    unsafe { atomic_add(self.v.get(), val, order) }
+                }
             }
 
-            /// Subtracts from the current value, returning the previous value.
-            ///
-            /// This operation wraps around on overflow.
-            ///
-            /// # Examples
-            ///
-            /// ```
-            /// use std::sync::atomic::{AtomicIsize, Ordering};
-            ///
-            /// let foo = AtomicIsize::new(0);
-            /// assert_eq!(foo.fetch_sub(10, Ordering::SeqCst), 0);
-            /// assert_eq!(foo.load(Ordering::SeqCst), -10);
-            /// ```
-            #[inline]
-            #[$stable]
-            pub fn fetch_sub(&self, val: $int_type, order: Ordering) -> $int_type {
-                unsafe { atomic_sub(self.v.get(), val, order) }
+            doc_comment! {
+                concat!("Subtracts from the current value, returning the previous value.
+
+This operation wraps around on overflow.
+
+# Examples
+
+```
+", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
+
+let foo = ", stringify!($atomic_type), "::new(20);
+assert_eq!(foo.fetch_sub(10, Ordering::SeqCst), 20);
+assert_eq!(foo.load(Ordering::SeqCst), 10);
+```"),
+                #[inline]
+                #[$stable]
+                pub fn fetch_sub(&self, val: $int_type, order: Ordering) -> $int_type {
+                    unsafe { atomic_sub(self.v.get(), val, order) }
+                }
             }
 
-            /// Bitwise "and" with the current value.
-            ///
-            /// Performs a bitwise "and" operation on the current value and the argument `val`, and
-            /// sets the new value to the result.
-            ///
-            /// Returns the previous value.
-            ///
-            /// # Examples
-            ///
-            /// ```
-            /// use std::sync::atomic::{AtomicIsize, Ordering};
-            ///
-            /// let foo = AtomicIsize::new(0b101101);
-            /// assert_eq!(foo.fetch_and(0b110011, Ordering::SeqCst), 0b101101);
-            /// assert_eq!(foo.load(Ordering::SeqCst), 0b100001);
-            #[inline]
-            #[$stable]
-            pub fn fetch_and(&self, val: $int_type, order: Ordering) -> $int_type {
-                unsafe { atomic_and(self.v.get(), val, order) }
+            doc_comment! {
+                concat!("Bitwise \"and\" with the current value.
+
+Performs a bitwise \"and\" operation on the current value and the argument `val`, and
+sets the new value to the result.
+
+Returns the previous value.
+
+# Examples
+
+```
+", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
+
+let foo = ", stringify!($atomic_type), "::new(0b101101);
+assert_eq!(foo.fetch_and(0b110011, Ordering::SeqCst), 0b101101);
+assert_eq!(foo.load(Ordering::SeqCst), 0b100001);
+```"),
+                #[inline]
+                #[$stable]
+                pub fn fetch_and(&self, val: $int_type, order: Ordering) -> $int_type {
+                    unsafe { atomic_and(self.v.get(), val, order) }
+                }
             }
 
-            /// Bitwise "nand" with the current value.
-            ///
-            /// Performs a bitwise "nand" operation on the current value and the argument `val`, and
-            /// sets the new value to the result.
-            ///
-            /// Returns the previous value.
-            ///
-            /// # Examples
-            ///
-            /// ```
-            /// #![feature(atomic_nand)]
-            ///
-            /// use std::sync::atomic::{AtomicIsize, Ordering};
-            ///
-            /// let foo = AtomicIsize::new(0xf731);
-            /// assert_eq!(foo.fetch_nand(0x137f, Ordering::SeqCst), 0xf731);
-            /// assert_eq!(foo.load(Ordering::SeqCst), !(0xf731 & 0x137f));
-            #[inline]
-            #[$stable_nand]
-            pub fn fetch_nand(&self, val: $int_type, order: Ordering) -> $int_type {
-                unsafe { atomic_nand(self.v.get(), val, order) }
+            doc_comment! {
+                concat!("Bitwise \"nand\" with the current value.
+
+Performs a bitwise \"nand\" operation on the current value and the argument `val`, and
+sets the new value to the result.
+
+Returns the previous value.
+
+# Examples
+
+```
+", $extra_feature, "#![feature(atomic_nand)]
+
+use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
+
+let foo = ", stringify!($atomic_type), "::new(0x13);
+assert_eq!(foo.fetch_nand(0x31, Ordering::SeqCst), 0x13);
+assert_eq!(foo.load(Ordering::SeqCst), !(0x13 & 0x31));
+```"),
+                #[inline]
+                #[$stable_nand]
+                pub fn fetch_nand(&self, val: $int_type, order: Ordering) -> $int_type {
+                    unsafe { atomic_nand(self.v.get(), val, order) }
+                }
             }
 
-            /// Bitwise "or" with the current value.
-            ///
-            /// Performs a bitwise "or" operation on the current value and the argument `val`, and
-            /// sets the new value to the result.
-            ///
-            /// Returns the previous value.
-            ///
-            /// # Examples
-            ///
-            /// ```
-            /// use std::sync::atomic::{AtomicIsize, Ordering};
-            ///
-            /// let foo = AtomicIsize::new(0b101101);
-            /// assert_eq!(foo.fetch_or(0b110011, Ordering::SeqCst), 0b101101);
-            /// assert_eq!(foo.load(Ordering::SeqCst), 0b111111);
-            #[inline]
-            #[$stable]
-            pub fn fetch_or(&self, val: $int_type, order: Ordering) -> $int_type {
-                unsafe { atomic_or(self.v.get(), val, order) }
+            doc_comment! {
+                concat!("Bitwise \"or\" with the current value.
+
+Performs a bitwise \"or\" operation on the current value and the argument `val`, and
+sets the new value to the result.
+
+Returns the previous value.
+
+# Examples
+
+```
+", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
+
+let foo = ", stringify!($atomic_type), "::new(0b101101);
+assert_eq!(foo.fetch_or(0b110011, Ordering::SeqCst), 0b101101);
+assert_eq!(foo.load(Ordering::SeqCst), 0b111111);
+```"),
+                #[inline]
+                #[$stable]
+                pub fn fetch_or(&self, val: $int_type, order: Ordering) -> $int_type {
+                    unsafe { atomic_or(self.v.get(), val, order) }
+                }
             }
 
-            /// Bitwise "xor" with the current value.
-            ///
-            /// Performs a bitwise "xor" operation on the current value and the argument `val`, and
-            /// sets the new value to the result.
-            ///
-            /// Returns the previous value.
-            ///
-            /// # Examples
-            ///
-            /// ```
-            /// use std::sync::atomic::{AtomicIsize, Ordering};
-            ///
-            /// let foo = AtomicIsize::new(0b101101);
-            /// assert_eq!(foo.fetch_xor(0b110011, Ordering::SeqCst), 0b101101);
-            /// assert_eq!(foo.load(Ordering::SeqCst), 0b011110);
-            #[inline]
-            #[$stable]
-            pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
-                unsafe { atomic_xor(self.v.get(), val, order) }
+            doc_comment! {
+                concat!("Bitwise \"xor\" with the current value.
+
+Performs a bitwise \"xor\" operation on the current value and the argument `val`, and
+sets the new value to the result.
+
+Returns the previous value.
+
+# Examples
+
+```
+", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
+
+let foo = ", stringify!($atomic_type), "::new(0b101101);
+assert_eq!(foo.fetch_xor(0b110011, Ordering::SeqCst), 0b101101);
+assert_eq!(foo.load(Ordering::SeqCst), 0b011110);
+```"),
+                #[inline]
+                #[$stable]
+                pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
+                    unsafe { atomic_xor(self.v.get(), val, order) }
+                }
             }
         }
     }
@@ -1404,6 +1431,7 @@ pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "atomic_nand", issue = "13226"),
     "i8", "../../../std/primitive.i8.html",
+    "#![feature(integer_atomics)]\n\n",
     i8 AtomicI8 ATOMIC_I8_INIT
 }
 #[cfg(target_has_atomic = "8")]
@@ -1415,6 +1443,7 @@ pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "atomic_nand", issue = "13226"),
     "u8", "../../../std/primitive.u8.html",
+    "#![feature(integer_atomics)]\n\n",
     u8 AtomicU8 ATOMIC_U8_INIT
 }
 #[cfg(target_has_atomic = "16")]
@@ -1426,6 +1455,7 @@ pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "atomic_nand", issue = "13226"),
     "i16", "../../../std/primitive.i16.html",
+    "#![feature(integer_atomics)]\n\n",
     i16 AtomicI16 ATOMIC_I16_INIT
 }
 #[cfg(target_has_atomic = "16")]
@@ -1437,6 +1467,7 @@ pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "atomic_nand", issue = "13226"),
     "u16", "../../../std/primitive.u16.html",
+    "#![feature(integer_atomics)]\n\n",
     u16 AtomicU16 ATOMIC_U16_INIT
 }
 #[cfg(target_has_atomic = "32")]
@@ -1448,6 +1479,7 @@ pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "atomic_nand", issue = "13226"),
     "i32", "../../../std/primitive.i32.html",
+    "#![feature(integer_atomics)]\n\n",
     i32 AtomicI32 ATOMIC_I32_INIT
 }
 #[cfg(target_has_atomic = "32")]
@@ -1459,6 +1491,7 @@ pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "atomic_nand", issue = "13226"),
     "u32", "../../../std/primitive.u32.html",
+    "#![feature(integer_atomics)]\n\n",
     u32 AtomicU32 ATOMIC_U32_INIT
 }
 #[cfg(target_has_atomic = "64")]
@@ -1470,6 +1503,7 @@ pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "atomic_nand", issue = "13226"),
     "i64", "../../../std/primitive.i64.html",
+    "#![feature(integer_atomics)]\n\n",
     i64 AtomicI64 ATOMIC_I64_INIT
 }
 #[cfg(target_has_atomic = "64")]
@@ -1481,6 +1515,7 @@ pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "atomic_nand", issue = "13226"),
     "u64", "../../../std/primitive.u64.html",
+    "#![feature(integer_atomics)]\n\n",
     u64 AtomicU64 ATOMIC_U64_INIT
 }
 #[cfg(target_has_atomic = "ptr")]
@@ -1492,6 +1527,7 @@ pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
     stable(feature = "atomic_from", since = "1.23.0"),
     unstable(feature = "atomic_nand", issue = "13226"),
     "isize", "../../../std/primitive.isize.html",
+    "",
     isize AtomicIsize ATOMIC_ISIZE_INIT
 }
 #[cfg(target_has_atomic = "ptr")]
@@ -1503,6 +1539,7 @@ pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
     stable(feature = "atomic_from", since = "1.23.0"),
     unstable(feature = "atomic_nand", issue = "13226"),
     "usize", "../../../std/primitive.usize.html",
+    "",
     usize AtomicUsize ATOMIC_USIZE_INIT
 }
 
index 4d43067ad2cf3e7b4467581b0d2e190af19d0a59..950222dbcfa3fe8d303097e6832e0af6af648196 100644 (file)
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 use core::char::from_u32;
-use std::ascii::AsciiExt;
 
 #[test]
 fn test_is_ascii() {
@@ -143,8 +142,6 @@ macro_rules! assert_all {
                            stringify!($what), b);
                 }
             }
-            assert!($str.$what());
-            assert!($str.as_bytes().$what());
         )+
     }};
     ($what:ident, $($str:tt),+,) => (assert_all!($what,$($str),+))
index 4ddedd9100486ea8640a712a390310f89b7305a2..bc205ec0582ea8c7ae1405c323494fa62eb67aff 100644 (file)
@@ -150,3 +150,9 @@ fn test_format_int_twos_complement() {
     assert!(format!("{}", i32::MIN) == "-2147483648");
     assert!(format!("{}", i64::MIN) == "-9223372036854775808");
 }
+
+#[test]
+fn test_format_debug_hex() {
+    assert!(format!("{:02x?}", b"Foo\0") == "[46, 6f, 6f, 00]");
+    assert!(format!("{:02X?}", b"Foo\0") == "[46, 6F, 6F, 00]");
+}
index c6dd41798f2a7ad388ee9b9b3c312a9019a68f9a..bad858011e960e4513fbe29a36ea5c9c4640de83 100644 (file)
@@ -11,7 +11,7 @@
 #![allow(deprecated)]
 
 use core::hash::{Hash, Hasher};
-use core::hash::{SipHasher, SipHasher13, SipHasher24};
+use core::hash::{SipHasher, SipHasher13};
 use core::{slice, mem};
 
 // Hash just the bytes of the slice, without length prefix
@@ -224,14 +224,14 @@ fn test_siphash_2_4() {
     let k1 = 0x_0f_0e_0d_0c_0b_0a_09_08;
     let mut buf = Vec::new();
     let mut t = 0;
-    let mut state_inc = SipHasher24::new_with_keys(k0, k1);
+    let mut state_inc = SipHasher::new_with_keys(k0, k1);
 
     while t < 64 {
         let vec = u8to64_le!(vecs[t], 0);
-        let out = hash_with(SipHasher24::new_with_keys(k0, k1), &Bytes(&buf));
+        let out = hash_with(SipHasher::new_with_keys(k0, k1), &Bytes(&buf));
         assert_eq!(vec, out);
 
-        let full = hash_with(SipHasher24::new_with_keys(k0, k1), &Bytes(&buf));
+        let full = hash_with(SipHasher::new_with_keys(k0, k1), &Bytes(&buf));
         let i = state_inc.finish();
 
         assert_eq!(full, i);
@@ -322,13 +322,13 @@ fn test_hash_no_concat_alias() {
 #[test]
 fn test_write_short_works() {
     let test_usize = 0xd0c0b0a0usize;
-    let mut h1 = SipHasher24::new();
+    let mut h1 = SipHasher::new();
     h1.write_usize(test_usize);
     h1.write(b"bytes");
     h1.write(b"string");
     h1.write_u8(0xFFu8);
     h1.write_u8(0x01u8);
-    let mut h2 = SipHasher24::new();
+    let mut h2 = SipHasher::new();
     h2.write(unsafe {
         slice::from_raw_parts(&test_usize as *const _ as *const u8,
                               mem::size_of::<usize>())
index e53964b5769bd4edce5a188651b1a1ed61ea0e78..e9a8113ef10707082fabe7f330729dbbec97e465 100644 (file)
@@ -21,6 +21,7 @@
 #![feature(fixed_size_array)]
 #![feature(flt2dec)]
 #![feature(fmt_internals)]
+#![feature(hashmap_internals)]
 #![feature(iterator_step_by)]
 #![feature(i128_type)]
 #![cfg_attr(stage0, feature(inclusive_range_syntax))]
@@ -35,8 +36,8 @@
 #![feature(range_is_empty)]
 #![feature(raw)]
 #![feature(refcell_replace_swap)]
-#![feature(sip_hash_13)]
 #![feature(slice_patterns)]
+#![feature(slice_rotate)]
 #![feature(sort_internals)]
 #![feature(specialization)]
 #![feature(step_trait)]
index 71519ab21fef99d60ae47e3f55a11b26d3f752d7..0f45f965104cadff7b8cce5e168e73a0036cf36b 100644 (file)
@@ -108,6 +108,10 @@ pub enum Flag {
     /// For numbers, this means that the number will be padded with zeroes,
     /// and the sign (`+` or `-`) will precede them.
     FlagSignAwareZeroPad,
+    /// For Debug / `?`, format integers in lower-case hexadecimal.
+    FlagDebugLowerHex,
+    /// For Debug / `?`, format integers in upper-case hexadecimal.
+    FlagDebugUpperHex,
 }
 
 /// A count is used for the precision and width parameters of an integer, and
@@ -377,8 +381,22 @@ fn format(&mut self) -> FormatSpec<'a> {
                 spec.precision = self.count();
             }
         }
-        // Finally the actual format specifier
-        if self.consume('?') {
+        // Optional radix followed by the actual format specifier
+        if self.consume('x') {
+            if self.consume('?') {
+                spec.flags |= 1 << (FlagDebugLowerHex as u32);
+                spec.ty = "?";
+            } else {
+                spec.ty = "x";
+            }
+        } else if self.consume('X') {
+            if self.consume('?') {
+                spec.flags |= 1 << (FlagDebugUpperHex as u32);
+                spec.ty = "?";
+            } else {
+                spec.ty = "X";
+            }
+        } else if self.consume('?') {
             spec.ty = "?";
         } else {
             spec.ty = self.word();
index 24294ec49ceed58e243f1029e3d4cd7fb6b8aaae..278e0f9a26e433d032a5d2c3a4c0ee8142f3c4a9 100644 (file)
@@ -10,7 +10,6 @@
 
 #![deny(warnings)]
 
-#![feature(slice_patterns)]
 #![feature(test)]
 
 extern crate test;
index c8d0362f17c8ed9a4f026a9e95b69bbe48f1319f..f1f383d7ad1262f5c5ae2cf30852d812286314fe 100644 (file)
@@ -1,295 +1,4 @@
-# Dependency graph for incremental compilation
+To learn more about how dependency tracking works in rustc, see the [rustc
+guide].
 
-This module contains the infrastructure for managing the incremental
-compilation dependency graph. This README aims to explain how it ought
-to be used. In this document, we'll first explain the overall
-strategy, and then share some tips for handling specific scenarios.
-
-The high-level idea is that we want to instrument the compiler to
-track which parts of the AST and other IR are read/written by what.
-This way, when we come back later, we can look at this graph and
-determine what work needs to be redone.
-
-### The dependency graph
-
-The nodes of the graph are defined by the enum `DepNode`. They represent
-one of three things:
-
-1. HIR nodes (like `Hir(DefId)`) represent the HIR input itself.
-2. Data nodes (like `TypeOfItem(DefId)`) represent some computed
-   information about a particular item.
-3. Procedure nodes (like `CoherenceCheckTrait(DefId)`) represent some
-   procedure that is executing. Usually this procedure is
-   performing some kind of check for errors. You can think of them as
-   computed values where the value being computed is `()` (and the
-   value may fail to be computed, if an error results).
-
-An edge `N1 -> N2` is added between two nodes if either:
-
-- the value of `N1` is used to compute `N2`;
-- `N1` is read by the procedure `N2`;
-- the procedure `N1` writes the value `N2`.
-
-The latter two conditions are equivalent to the first one if you think
-of procedures as values.
-
-### Basic tracking
-
-There is a very general strategy to ensure that you have a correct, if
-sometimes overconservative, dependency graph. The two main things you have
-to do are (a) identify shared state and (b) identify the current tasks.
-
-### Identifying shared state
-
-Identify "shared state" that will be written by one pass and read by
-another. In particular, we need to identify shared state that will be
-read "across items" -- that is, anything where changes in one item
-could invalidate work done for other items. So, for example:
-
-1. The signature for a function is "shared state".
-2. The computed type of some expression in the body of a function is
-   not shared state, because if it changes it does not itself
-   invalidate other functions (though it may be that it causes new
-   monomorphizations to occur, but that's handled independently).
-
-Put another way: if the HIR for an item changes, we are going to
-recompile that item for sure. But we need the dep tracking map to tell
-us what *else* we have to recompile. Shared state is anything that is
-used to communicate results from one item to another.
-
-### Identifying the current task, tracking reads/writes, etc
-
-FIXME(#42293). This text needs to be rewritten for the new red-green
-system, which doesn't fully exist yet.
-
-#### Dependency tracking map
-
-`DepTrackingMap` is a particularly convenient way to correctly store
-shared state. A `DepTrackingMap` is a special hashmap that will add
-edges automatically when `get` and `insert` are called. The idea is
-that, when you get/insert a value for the key `K`, we will add an edge
-from/to the node `DepNode::Variant(K)` (for some variant specific to
-the map).
-
-Each `DepTrackingMap` is parameterized by a special type `M` that
-implements `DepTrackingMapConfig`; this trait defines the key and value
-types of the map, and also defines a fn for converting from the key to
-a `DepNode` label. You don't usually have to muck about with this by
-hand, there is a macro for creating it. You can see the complete set
-of `DepTrackingMap` definitions in `librustc/middle/ty/maps.rs`.
-
-As an example, let's look at the `adt_defs` map. The `adt_defs` map
-maps from the def-id of a struct/enum to its `AdtDef`. It is defined
-using this macro:
-
-```rust
-dep_map_ty! { AdtDefs: ItemSignature(DefId) -> ty::AdtDefMaster<'tcx> }
-//            ~~~~~~~  ~~~~~~~~~~~~~ ~~~~~     ~~~~~~~~~~~~~~~~~~~~~~
-//               |           |      Key type       Value type
-//               |    DepNode variant
-//      Name of map id type
-```
-
-this indicates that a map id type `AdtDefs` will be created. The key
-of the map will be a `DefId` and value will be
-`ty::AdtDefMaster<'tcx>`. The `DepNode` will be created by
-`DepNode::ItemSignature(K)` for a given key.
-
-Once that is done, you can just use the `DepTrackingMap` like any
-other map:
-
-```rust
-let mut map: DepTrackingMap<M> = DepTrackingMap::new(dep_graph);
-map.insert(key, value); // registers dep_graph.write
-map.get(key; // registers dep_graph.read
-```
-
-#### Memoization
-
-One particularly interesting case is memoization. If you have some
-shared state that you compute in a memoized fashion, the correct thing
-to do is to define a `RefCell<DepTrackingMap>` for it and use the
-`memoize` helper:
-
-```rust
-map.memoize(key, || /* compute value */)
-```
-
-This will create a graph that looks like
-
-    ... -> MapVariant(key) -> CurrentTask
-
-where `MapVariant` is the `DepNode` variant that the map is associated with,
-and `...` are whatever edges the `/* compute value */` closure creates.
-
-In particular, using the memoize helper is much better than writing
-the obvious code yourself:
-
-```rust
-if let Some(result) = map.get(key) {
-    return result;
-}
-let value = /* compute value */;
-map.insert(key, value);
-```
-
-If you write that code manually, the dependency graph you get will
-include artificial edges that are not necessary. For example, imagine that
-two tasks, A and B, both invoke the manual memoization code, but A happens
-to go first. The resulting graph will be:
-
-    ... -> A -> MapVariant(key) -> B
-    ~~~~~~~~~~~~~~~~~~~~~~~~~~~       // caused by A writing to MapVariant(key)
-                ~~~~~~~~~~~~~~~~~~~~  // caused by B reading from MapVariant(key)
-
-This graph is not *wrong*, but it encodes a path from A to B that
-should not exist.  In contrast, using the memoized helper, you get:
-
-    ... -> MapVariant(key) -> A
-                 |
-                 +----------> B
-
-which is much cleaner.
-
-**Be aware though that the closure is executed with `MapVariant(key)`
-pushed onto the stack as the current task!** That means that you must
-add explicit `read` calls for any shared state that it accesses
-implicitly from its environment. See the section on "explicit calls to
-read and write when starting a new subtask" above for more details.
-
-### How to decide where to introduce a new task
-
-Certainly, you need at least one task on the stack: any attempt to
-`read` or `write` shared state will panic if there is no current
-task. But where does it make sense to introduce subtasks? The basic
-rule is that a subtask makes sense for any discrete unit of work you
-may want to skip in the future. Adding a subtask separates out the
-reads/writes from *that particular subtask* versus the larger
-context. An example: you might have a 'meta' task for all of borrow
-checking, and then subtasks for borrow checking individual fns.  (Seen
-in this light, memoized computations are just a special case where we
-may want to avoid redoing the work even within the context of one
-compilation.)
-
-The other case where you might want a subtask is to help with refining
-the reads/writes for some later bit of work that needs to be memoized.
-For example, we create a subtask for type-checking the body of each
-fn.  However, in the initial version of incr. comp. at least, we do
-not expect to actually *SKIP* type-checking -- we only expect to skip
-trans. However, it's still useful to create subtasks for type-checking
-individual items, because, otherwise, if a fn sig changes, we won't
-know which callers are affected -- in fact, because the graph would be
-so coarse, we'd just have to retrans everything, since we can't
-distinguish which fns used which fn sigs.
-
-### Testing the dependency graph
-
-There are various ways to write tests against the dependency graph.
-The simplest mechanism are the
-`#[rustc_if_this_changed]` and `#[rustc_then_this_would_need]`
-annotations. These are used in compile-fail tests to test whether the
-expected set of paths exist in the dependency graph. As an example,
-see `src/test/compile-fail/dep-graph-caller-callee.rs`.
-
-The idea is that you can annotate a test like:
-
-```rust
-#[rustc_if_this_changed]
-fn foo() { }
-
-#[rustc_then_this_would_need(TypeckTables)] //~ ERROR OK
-fn bar() { foo(); }
-
-#[rustc_then_this_would_need(TypeckTables)] //~ ERROR no path
-fn baz() { }
-```
-
-This will check whether there is a path in the dependency graph from
-`Hir(foo)` to `TypeckTables(bar)`. An error is reported for each
-`#[rustc_then_this_would_need]` annotation that indicates whether a
-path exists. `//~ ERROR` annotations can then be used to test if a
-path is found (as demonstrated above).
-
-### Debugging the dependency graph
-
-#### Dumping the graph
-
-The compiler is also capable of dumping the dependency graph for your
-debugging pleasure. To do so, pass the `-Z dump-dep-graph` flag. The
-graph will be dumped to `dep_graph.{txt,dot}` in the current
-directory.  You can override the filename with the `RUST_DEP_GRAPH`
-environment variable.
-
-Frequently, though, the full dep graph is quite overwhelming and not
-particularly helpful. Therefore, the compiler also allows you to filter
-the graph. You can filter in three ways:
-
-1. All edges originating in a particular set of nodes (usually a single node).
-2. All edges reaching a particular set of nodes.
-3. All edges that lie between given start and end nodes.
-
-To filter, use the `RUST_DEP_GRAPH_FILTER` environment variable, which should
-look like one of the following:
-
-```
-source_filter     // nodes originating from source_filter
--> target_filter  // nodes that can reach target_filter
-source_filter -> target_filter // nodes in between source_filter and target_filter
-```
-
-`source_filter` and `target_filter` are a `&`-separated list of strings.
-A node is considered to match a filter if all of those strings appear in its
-label. So, for example:
-
-```
-RUST_DEP_GRAPH_FILTER='-> TypeckTables'
-```
-
-would select the predecessors of all `TypeckTables` nodes. Usually though you
-want the `TypeckTables` node for some particular fn, so you might write:
-
-```
-RUST_DEP_GRAPH_FILTER='-> TypeckTables & bar'
-```
-
-This will select only the `TypeckTables` nodes for fns with `bar` in their name.
-
-Perhaps you are finding that when you change `foo` you need to re-type-check `bar`,
-but you don't think you should have to. In that case, you might do:
-
-```
-RUST_DEP_GRAPH_FILTER='Hir&foo -> TypeckTables & bar'
-```
-
-This will dump out all the nodes that lead from `Hir(foo)` to
-`TypeckTables(bar)`, from which you can (hopefully) see the source
-of the erroneous edge.
-
-#### Tracking down incorrect edges
-
-Sometimes, after you dump the dependency graph, you will find some
-path that should not exist, but you will not be quite sure how it came
-to be. **When the compiler is built with debug assertions,** it can
-help you track that down. Simply set the `RUST_FORBID_DEP_GRAPH_EDGE`
-environment variable to a filter. Every edge created in the dep-graph
-will be tested against that filter -- if it matches, a `bug!` is
-reported, so you can easily see the backtrace (`RUST_BACKTRACE=1`).
-
-The syntax for these filters is the same as described in the previous
-section. However, note that this filter is applied to every **edge**
-and doesn't handle longer paths in the graph, unlike the previous
-section.
-
-Example:
-
-You find that there is a path from the `Hir` of `foo` to the type
-check of `bar` and you don't think there should be. You dump the
-dep-graph as described in the previous section and open `dep-graph.txt`
-to see something like:
-
-    Hir(foo) -> Collect(bar)
-    Collect(bar) -> TypeckTables(bar)
-
-That first edge looks suspicious to you. So you set
-`RUST_FORBID_DEP_GRAPH_EDGE` to `Hir&foo -> Collect&bar`, re-run, and
-then observe the backtrace. Voila, bug fixed!
+[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/query.html
index 744e3a5eaabccb4c2dd346506152aecf55c64b79..1e2e4e5a69fa1ad0b9ef05757976eabc03b236bc 100644 (file)
@@ -579,6 +579,9 @@ pub fn fingerprint_needed_for_crate_hash(self) -> bool {
     [] GetPanicStrategy(CrateNum),
     [] IsNoBuiltins(CrateNum),
     [] ImplDefaultness(DefId),
+    [] CheckItemWellFormed(DefId),
+    [] CheckTraitItemWellFormed(DefId),
+    [] CheckImplItemWellFormed(DefId),
     [] ReachableNonGenerics(CrateNum),
     [] NativeLibraries(CrateNum),
     [] PluginRegistrarFn(CrateNum),
index 0ad79eacd2b03f9a04981bf5d2a4e9db918b7089..d60c22064d3a0cd0ee3900a1dec51d175e28ea58 100644 (file)
@@ -476,10 +476,8 @@ pub fn serialize(&self) -> SerializedDepGraph {
             fingerprints.resize(current_dep_graph.nodes.len(), Fingerprint::ZERO);
         }
 
-        let nodes: IndexVec<_, (DepNode, Fingerprint)> =
-            current_dep_graph.nodes.iter_enumerated().map(|(idx, &dep_node)| {
-            (dep_node, fingerprints[idx])
-        }).collect();
+        let fingerprints = fingerprints.clone().convert_index_type();
+        let nodes = current_dep_graph.nodes.clone().convert_index_type();
 
         let total_edge_count: usize = current_dep_graph.edges.iter()
                                                              .map(|v| v.len())
@@ -503,6 +501,7 @@ pub fn serialize(&self) -> SerializedDepGraph {
 
         SerializedDepGraph {
             nodes,
+            fingerprints,
             edge_list_indices,
             edge_list_data,
         }
index 504b60e763e23543fc9e5663acbe5bbf6a842429..669a99019aa60176de63f093266766a75d8638a4 100644 (file)
@@ -23,7 +23,7 @@ impl PreviousDepGraph {
     pub fn new(data: SerializedDepGraph) -> PreviousDepGraph {
         let index: FxHashMap<_, _> = data.nodes
             .iter_enumerated()
-            .map(|(idx, &(dep_node, _))| (dep_node, idx))
+            .map(|(idx, &dep_node)| (dep_node, idx))
             .collect();
         PreviousDepGraph { data, index }
     }
@@ -41,7 +41,7 @@ pub fn edges_from(&self,
 
     #[inline]
     pub fn index_to_node(&self, dep_node_index: SerializedDepNodeIndex) -> DepNode {
-        self.data.nodes[dep_node_index].0
+        self.data.nodes[dep_node_index]
     }
 
     #[inline]
@@ -58,14 +58,14 @@ pub fn node_to_index_opt(&self, dep_node: &DepNode) -> Option<SerializedDepNodeI
     pub fn fingerprint_of(&self, dep_node: &DepNode) -> Option<Fingerprint> {
         self.index
             .get(dep_node)
-            .map(|&node_index| self.data.nodes[node_index].1)
+            .map(|&node_index| self.data.fingerprints[node_index])
     }
 
     #[inline]
     pub fn fingerprint_by_index(&self,
                                 dep_node_index: SerializedDepNodeIndex)
                                 -> Fingerprint {
-        self.data.nodes[dep_node_index].1
+        self.data.fingerprints[dep_node_index]
     }
 
     pub fn node_count(&self) -> usize {
index c96040ab9b6e3eab996aafdb875c90fc6d3217a4..60fc813a25d51eda38da1293b1a8943a89c35225 100644 (file)
 #[derive(Debug, RustcEncodable, RustcDecodable)]
 pub struct SerializedDepGraph {
     /// The set of all DepNodes in the graph
-    pub nodes: IndexVec<SerializedDepNodeIndex, (DepNode, Fingerprint)>,
+    pub nodes: IndexVec<SerializedDepNodeIndex, DepNode>,
+    /// The set of all Fingerprints in the graph. Each Fingerprint corresponds to
+    /// the DepNode at the same index in the nodes vector.
+    pub fingerprints: IndexVec<SerializedDepNodeIndex, Fingerprint>,
     /// For each DepNode, stores the list of edges originating from that
     /// DepNode. Encoded as a [start, end) pair indexing into edge_list_data,
     /// which holds the actual DepNodeIndices of the target nodes.
@@ -35,6 +38,7 @@ impl SerializedDepGraph {
     pub fn new() -> SerializedDepGraph {
         SerializedDepGraph {
             nodes: IndexVec::new(),
+            fingerprints: IndexVec::new(),
             edge_list_indices: IndexVec::new(),
             edge_list_data: Vec::new(),
         }
index b3a904f2f5fec520598714aee8882b5642f33c12..2fd875c3447677b4d841b320535abbfe543b6917 100644 (file)
@@ -2074,6 +2074,58 @@ struct Foo {
 transparent wrapper around a float. This can make a difference for the ABI.
 "##,
 
+E0909: r##"
+The `impl Trait` return type captures lifetime parameters that do not
+appear within the `impl Trait` itself.
+
+Erroneous code example:
+
+```compile-fail,E0909
+#![feature(conservative_impl_trait)]
+
+use std::cell::Cell;
+
+trait Trait<'a> { }
+
+impl<'a, 'b> Trait<'b> for Cell<&'a u32> { }
+
+fn foo<'x, 'y>(x: Cell<&'x u32>) -> impl Trait<'y>
+where 'x: 'y
+{
+    x
+}
+```
+
+Here, the function `foo` returns a value of type `Cell<&'x u32>`,
+which references the lifetime `'x`. However, the return type is
+declared as `impl Trait<'y>` -- this indicates that `foo` returns
+"some type that implements `Trait<'y>`", but it also indicates that
+the return type **only captures data referencing the lifetime `'y`**.
+In this case, though, we are referencing data with lifetime `'x`, so
+this function is in error.
+
+To fix this, you must reference the lifetime `'x` from the return
+type. For example, changing the return type to `impl Trait<'y> + 'x`
+would work:
+
+```
+#![feature(conservative_impl_trait)]
+
+use std::cell::Cell;
+
+trait Trait<'a> { }
+
+impl<'a,'b> Trait<'b> for Cell<&'a u32> { }
+
+fn foo<'x, 'y>(x: Cell<&'x u32>) -> impl Trait<'y> + 'x
+where 'x: 'y
+{
+    x
+}
+```
+"##,
+
+
 }
 
 
index 7f91bbd6ea27c90af17e771b64e856b9fd5e1416..9a442e0529938e0a0eddc57b4f3b8cd19073e53b 100644 (file)
@@ -902,13 +902,59 @@ fn hash_stable<W: StableHasherResult>(&self,
             TyForeign(def_id) => {
                 def_id.hash_stable(hcx, hasher);
             }
-            TyInfer(..) => {
-                bug!("ty::TypeVariants::hash_stable() - Unexpected variant {:?}.", *self)
+            TyInfer(infer_ty) => {
+                infer_ty.hash_stable(hcx, hasher);
             }
         }
     }
 }
 
+impl_stable_hash_for!(enum ty::InferTy {
+    TyVar(a),
+    IntVar(a),
+    FloatVar(a),
+    FreshTy(a),
+    FreshIntTy(a),
+    FreshFloatTy(a),
+    CanonicalTy(a),
+});
+
+impl<'a, 'gcx> HashStable<StableHashingContext<'a>>
+for ty::TyVid
+{
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          _hcx: &mut StableHashingContext<'a>,
+                                          _hasher: &mut StableHasher<W>) {
+        // TyVid values are confined to an inference context and hence
+        // should not be hashed.
+        bug!("ty::TypeVariants::hash_stable() - can't hash a TyVid {:?}.", *self)
+    }
+}
+
+impl<'a, 'gcx> HashStable<StableHashingContext<'a>>
+for ty::IntVid
+{
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          _hcx: &mut StableHashingContext<'a>,
+                                          _hasher: &mut StableHasher<W>) {
+        // IntVid values are confined to an inference context and hence
+        // should not be hashed.
+        bug!("ty::TypeVariants::hash_stable() - can't hash an IntVid {:?}.", *self)
+    }
+}
+
+impl<'a, 'gcx> HashStable<StableHashingContext<'a>>
+for ty::FloatVid
+{
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          _hcx: &mut StableHashingContext<'a>,
+                                          _hasher: &mut StableHasher<W>) {
+        // FloatVid values are confined to an inference context and hence
+        // should not be hashed.
+        bug!("ty::TypeVariants::hash_stable() - can't hash a FloatVid {:?}.", *self)
+    }
+}
+
 impl_stable_hash_for!(struct ty::ParamTy {
     idx,
     name
index eb26f0c1188bf639bf8c0b31aa40a8c85e7cdf40..93e8745af1b57731318feea40405c51953944899 100644 (file)
 use rustc_data_structures::fx::FxHashMap;
 use syntax::ast;
 use traits::{self, PredicateObligation};
-use ty::{self, Ty};
-use ty::fold::{BottomUpFolder, TypeFoldable};
+use ty::{self, Ty, TyCtxt};
+use ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder};
 use ty::outlives::Component;
-use ty::subst::{Kind, UnpackedKind, Substs};
+use ty::subst::{Kind, Substs, UnpackedKind};
 use util::nodemap::DefIdMap;
 
 pub type AnonTypeMap<'tcx> = DefIdMap<AnonTypeDecl<'tcx>>;
@@ -113,10 +113,7 @@ pub fn instantiate_anon_types<T: TypeFoldable<'tcx>>(
     ) -> InferOk<'tcx, (T, AnonTypeMap<'tcx>)> {
         debug!(
             "instantiate_anon_types(value={:?}, parent_def_id={:?}, body_id={:?}, param_env={:?})",
-            value,
-            parent_def_id,
-            body_id,
-            param_env,
+            value, parent_def_id, body_id, param_env,
         );
         let mut instantiator = Instantiator {
             infcx: self,
@@ -458,55 +455,184 @@ pub fn infer_anon_definition_from_instantiation(
         // Convert the type from the function into a type valid outside
         // the function, by replacing invalid regions with 'static,
         // after producing an error for each of them.
-        let definition_ty = gcx.fold_regions(&instantiated_ty, &mut false, |r, _| {
-            match *r {
-                // 'static and early-bound regions are valid.
-                ty::ReStatic | ty::ReEmpty => r,
-
-                // All other regions, we map them appropriately to their adjusted
-                // indices, erroring if we find any lifetimes that were not mapped
-                // into the new set.
-                _ => if let Some(UnpackedKind::Lifetime(r1)) = map.get(&r.into())
-                                                                  .map(|k| k.unpack()) {
-                    r1
-                } else {
-                    // No mapping was found. This means that
-                    // it is either a disallowed lifetime,
-                    // which will be caught by regionck, or it
-                    // is a region in a non-upvar closure
-                    // generic, which is explicitly
-                    // allowed. If that surprises you, read
-                    // on.
-                    //
-                    // The case of closure is a somewhat
-                    // subtle (read: hacky) consideration. The
-                    // problem is that our closure types
-                    // currently include all the lifetime
-                    // parameters declared on the enclosing
-                    // function, even if they are unused by
-                    // the closure itself. We can't readily
-                    // filter them out, so here we replace
-                    // those values with `'empty`. This can't
-                    // really make a difference to the rest of
-                    // the compiler; those regions are ignored
-                    // for the outlives relation, and hence
-                    // don't affect trait selection or auto
-                    // traits, and they are erased during
-                    // trans.
-                    gcx.types.re_empty
-                },
-            }
-        });
-
+        let definition_ty =
+            instantiated_ty.fold_with(&mut ReverseMapper::new(
+                self.tcx,
+                self.is_tainted_by_errors(),
+                def_id,
+                map,
+                instantiated_ty,
+            ));
         debug!(
             "infer_anon_definition_from_instantiation: definition_ty={:?}",
             definition_ty
         );
 
+        // We can unwrap here because our reverse mapper always
+        // produces things with 'gcx lifetime, though the type folder
+        // obscures that.
+        let definition_ty = gcx.lift(&definition_ty).unwrap();
+
         definition_ty
     }
 }
 
+struct ReverseMapper<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
+    tcx: TyCtxt<'cx, 'gcx, 'tcx>,
+
+    /// If errors have already been reported in this fn, we suppress
+    /// our own errors because they are sometimes derivative.
+    tainted_by_errors: bool,
+
+    anon_type_def_id: DefId,
+    map: FxHashMap<Kind<'tcx>, Kind<'gcx>>,
+    map_missing_regions_to_empty: bool,
+
+    /// initially `Some`, set to `None` once error has been reported
+    hidden_ty: Option<Ty<'tcx>>,
+}
+
+impl<'cx, 'gcx, 'tcx> ReverseMapper<'cx, 'gcx, 'tcx> {
+    fn new(
+        tcx: TyCtxt<'cx, 'gcx, 'tcx>,
+        tainted_by_errors: bool,
+        anon_type_def_id: DefId,
+        map: FxHashMap<Kind<'tcx>, Kind<'gcx>>,
+        hidden_ty: Ty<'tcx>,
+    ) -> Self {
+        Self {
+            tcx,
+            tainted_by_errors,
+            anon_type_def_id,
+            map,
+            map_missing_regions_to_empty: false,
+            hidden_ty: Some(hidden_ty),
+        }
+    }
+
+    fn fold_kind_mapping_missing_regions_to_empty(&mut self, kind: Kind<'tcx>) -> Kind<'tcx> {
+        assert!(!self.map_missing_regions_to_empty);
+        self.map_missing_regions_to_empty = true;
+        let kind = kind.fold_with(self);
+        self.map_missing_regions_to_empty = false;
+        kind
+    }
+
+    fn fold_kind_normally(&mut self, kind: Kind<'tcx>) -> Kind<'tcx> {
+        assert!(!self.map_missing_regions_to_empty);
+        kind.fold_with(self)
+    }
+}
+
+impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for ReverseMapper<'cx, 'gcx, 'tcx> {
+    fn tcx(&self) -> TyCtxt<'_, 'gcx, 'tcx> {
+        self.tcx
+    }
+
+    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
+        match r {
+            // ignore bound regions that appear in the type (e.g., this
+            // would ignore `'r` in a type like `for<'r> fn(&'r u32)`.
+            ty::ReLateBound(..) => return r,
+
+            // ignore `'static`, as that can appear anywhere
+            ty::ReStatic => return r,
+
+            _ => { }
+        }
+
+        match self.map.get(&r.into()).map(|k| k.unpack()) {
+            Some(UnpackedKind::Lifetime(r1)) => r1,
+            Some(u) => panic!("region mapped to unexpected kind: {:?}", u),
+            None => {
+                if !self.map_missing_regions_to_empty && !self.tainted_by_errors {
+                    if let Some(hidden_ty) = self.hidden_ty.take() {
+                        let span = self.tcx.def_span(self.anon_type_def_id);
+                        let mut err = struct_span_err!(
+                            self.tcx.sess,
+                            span,
+                            E0909,
+                            "hidden type for `impl Trait` captures lifetime that \
+                             does not appear in bounds",
+                        );
+
+                        // Assuming regionck succeeded, then we must
+                        // be capturing *some* region from the fn
+                        // header, and hence it must be free, so it's
+                        // ok to invoke this fn (which doesn't accept
+                        // all regions, and would ICE if an
+                        // inappropriate region is given). We check
+                        // `is_tainted_by_errors` by errors above, so
+                        // we don't get in here unless regionck
+                        // succeeded. (Note also that if regionck
+                        // failed, then the regions we are attempting
+                        // to map here may well be giving errors
+                        // *because* the constraints were not
+                        // satisfiable.)
+                        self.tcx.note_and_explain_free_region(
+                            &mut err,
+                            &format!("hidden type `{}` captures ", hidden_ty),
+                            r,
+                            ""
+                        );
+
+                        err.emit();
+                    }
+                }
+                self.tcx.types.re_empty
+            },
+        }
+    }
+
+    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
+        match ty.sty {
+            ty::TyClosure(def_id, substs) => {
+                // I am a horrible monster and I pray for death. When
+                // we encounter a closure here, it is always a closure
+                // from within the function that we are currently
+                // type-checking -- one that is now being encapsulated
+                // in an existential abstract type. Ideally, we would
+                // go through the types/lifetimes that it references
+                // and treat them just like we would any other type,
+                // which means we would error out if we find any
+                // reference to a type/region that is not in the
+                // "reverse map".
+                //
+                // **However,** in the case of closures, there is a
+                // somewhat subtle (read: hacky) consideration. The
+                // problem is that our closure types currently include
+                // all the lifetime parameters declared on the
+                // enclosing function, even if they are unused by the
+                // closure itself. We can't readily filter them out,
+                // so here we replace those values with `'empty`. This
+                // can't really make a difference to the rest of the
+                // compiler; those regions are ignored for the
+                // outlives relation, and hence don't affect trait
+                // selection or auto traits, and they are erased
+                // during trans.
+
+                let generics = self.tcx.generics_of(def_id);
+                let parent_len = generics.parent_count();
+                let substs = self.tcx.mk_substs(substs.substs.iter().enumerate().map(
+                    |(index, &kind)| {
+                        if index < parent_len {
+                            // Accommodate missing regions in the parent kinds...
+                            self.fold_kind_mapping_missing_regions_to_empty(kind)
+                        } else {
+                            // ...but not elsewhere.
+                            self.fold_kind_normally(kind)
+                        }
+                    },
+                ));
+
+                self.tcx.mk_closure(def_id, ty::ClosureSubsts { substs })
+            }
+
+            _ => ty.super_fold_with(self),
+        }
+    }
+}
+
 struct Instantiator<'a, 'gcx: 'tcx, 'tcx: 'a> {
     infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
     parent_def_id: DefId,
@@ -565,12 +691,13 @@ fn instantiate_anon_types_in_map<T: TypeFoldable<'tcx>>(&mut self, value: &T) ->
                             return self.fold_anon_ty(ty, def_id, substs);
                         }
 
-                        debug!("instantiate_anon_types_in_map: \
-                                encountered anon with wrong parent \
-                                def_id={:?} \
-                                anon_parent_def_id={:?}",
-                               def_id,
-                               anon_parent_def_id);
+                        debug!(
+                            "instantiate_anon_types_in_map: \
+                             encountered anon with wrong parent \
+                             def_id={:?} \
+                             anon_parent_def_id={:?}",
+                            def_id, anon_parent_def_id
+                        );
                     }
                 }
 
@@ -590,8 +717,7 @@ fn fold_anon_ty(
 
         debug!(
             "instantiate_anon_types: TyAnon(def_id={:?}, substs={:?})",
-            def_id,
-            substs
+            def_id, substs
         );
 
         // Use the same type variable if the exact same TyAnon appears more
@@ -600,8 +726,10 @@ fn fold_anon_ty(
             return anon_defn.concrete_ty;
         }
         let span = tcx.def_span(def_id);
-        let ty_var = infcx.next_ty_var(ty::UniverseIndex::ROOT,
-                                       TypeVariableOrigin::TypeInference(span));
+        let ty_var = infcx.next_ty_var(
+            ty::UniverseIndex::ROOT,
+            TypeVariableOrigin::TypeInference(span),
+        );
 
         let predicates_of = tcx.predicates_of(def_id);
         let bounds = predicates_of.instantiate(tcx, substs);
index 4e0cf59e8a7fd7dc6db068c5f4d60ac62feaab49..22526c7751d5021dfb4809f3b5a1d061e164aa6f 100644 (file)
@@ -40,6 +40,7 @@
 use ty::{self, CanonicalVar, Lift, Region, Slice, Ty, TyCtxt, TypeFlags};
 use ty::subst::{Kind, UnpackedKind};
 use ty::fold::{TypeFoldable, TypeFolder};
+use util::captures::Captures;
 use util::common::CellUsizeExt;
 
 use rustc_data_structures::indexed_vec::IndexVec;
@@ -382,7 +383,7 @@ fn query_region_constraints_into_obligations<'a>(
         param_env: ty::ParamEnv<'tcx>,
         unsubstituted_region_constraints: &'a QueryRegionConstraints<'tcx>,
         result_subst: &'a CanonicalVarValues<'tcx>,
-    ) -> impl Iterator<Item = PredicateObligation<'tcx>> + 'a {
+    ) -> impl Iterator<Item = PredicateObligation<'tcx>> + Captures<'gcx> + 'a {
         let QueryRegionConstraints {
             region_outlives,
             ty_outlives,
index a317e0699b4bba29e755138815ef2036b24fcbd6..d44f2ec95492f9592456577a4158042ff2a74c90 100644 (file)
@@ -580,7 +580,10 @@ fn region_vars_confined_to_snapshot(&self,
     /// the pop occurs as part of the rollback, so an explicit call is not
     /// needed (but is also permitted).
     ///
-    /// See `README.md` for more details.
+    /// For more information about how skolemization for HRTBs works, see
+    /// the [rustc guide].
+    ///
+    /// [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/trait-hrtb.html
     pub fn skolemize_late_bound_regions<T>(&self,
                                            binder: &ty::Binder<T>,
                                            snapshot: &CombinedSnapshot<'a, 'tcx>)
index a90230870a6c0d77f05a7ecd70f07bf132a6f1b3..0086aed3e7c975b94b41d8b2646139b55be56dca 100644 (file)
@@ -1,14 +1,16 @@
 # Region inference
 
+> WARNING: This README is obsolete and will be removed soon! For
+> more info on how the current borrowck works, see the [rustc guide].
+
+[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/mir-borrowck.html
+
 ## Terminology
 
 Note that we use the terms region and lifetime interchangeably.
 
 ## Introduction
 
-See the [general inference README](../README.md) for an overview of
-how lexical-region-solving fits into the bigger picture.
-
 Region inference uses a somewhat more involved algorithm than type
 inference. It is not the most efficient thing ever written though it
 seems to work well enough in practice (famous last words).  The reason
index 95f9c8c835398e5ef09e15d9fa18a5cabb48b5d5..07b87e2012dde775df98f09d6c502d3ec8a8aed0 100644 (file)
@@ -1,18 +1,25 @@
 # Region constraint collection
 
+> WARNING: This README is obsolete and will be removed soon! For
+> more info on how the current borrowck works, see the [rustc guide].
+
+[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/mir-borrowck.html
+
 ## Terminology
 
 Note that we use the terms region and lifetime interchangeably.
 
 ## Introduction
 
-As described in the [inference README](../README.md), and unlike
+As described in the rustc guide [chapter on type inference][ti], and unlike
 normal type inference, which is similar in spirit to H-M and thus
 works progressively, the region type inference works by accumulating
 constraints over the course of a function.  Finally, at the end of
 processing a function, we process and solve the constraints all at
 once.
 
+[ti]: https://rust-lang-nursery.github.io/rustc-guide/type-inference.html
+
 The constraints are always of one of three possible forms:
 
 - `ConstrainVarSubVar(Ri, Rj)` states that region variable Ri must be
index 0c8e49fda1840d7cab10569ee946bfebd5be85e9..e864485539b2d65f3555966fabcd2d704b64e52b 100644 (file)
@@ -468,8 +468,10 @@ pub fn var_origin(&self, vid: RegionVid) -> RegionVariableOrigin {
     /// the APIs in `higher_ranked/mod.rs`, such as
     /// `skolemize_late_bound_regions` and `plug_leaks`, which will
     /// guide you on this path (ensure that the `SkolemizationMap` is
-    /// consumed and you are good).  There are also somewhat extensive
-    /// comments in `higher_ranked/README.md`.
+    /// consumed and you are good). For more info on how skolemization
+    /// for HRTBs works, see the [rustc guide].
+    ///
+    /// [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/trait-hrtb.html
     ///
     /// The `snapshot` argument to this function is not really used;
     /// it's just there to make it explicit which snapshot bounds the
index 77259f156e5e24ff37dd636365849030c56162c8..22b07c8cc044f55619255ee7edbfdcff18a4b843 100644 (file)
@@ -157,6 +157,7 @@ pub mod middle {
 pub mod ty;
 
 pub mod util {
+    pub mod captures;
     pub mod common;
     pub mod ppaux;
     pub mod nodemap;
index d8a723e184d2ca3f3d53c005c464434fba1ccbf6..7dc84b9ca29561bc2d754ea859d19f442edb36d4 100644 (file)
@@ -72,7 +72,7 @@ macro_rules! __impl_stable_hash_field {
 
 #[macro_export]
 macro_rules! impl_stable_hash_for {
-    (enum $enum_name:path { $( $variant:ident $( ( $($arg:ident),* ) )* ),* }) => {
+    (enum $enum_name:path { $( $variant:ident $( ( $($arg:ident),* ) )* ),* $(,)* }) => {
         impl<'a, 'tcx> ::rustc_data_structures::stable_hasher::HashStable<$crate::ich::StableHashingContext<'a>> for $enum_name {
             #[inline]
             fn hash_stable<W: ::rustc_data_structures::stable_hasher::StableHasherResult>(&self,
index d13b16dce89864f99ce699e5d1a842f213319dd1..966353b53a95aefa875399f02271ebdf8aee23a5 100644 (file)
@@ -402,12 +402,10 @@ fn visit_local<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, local: &'tcx hir::Local) {
 
 fn visit_arm<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, arm: &'tcx hir::Arm) {
     for pat in &arm.pats {
-        // for struct patterns, take note of which fields used shorthand (`x`
-        // rather than `x: x`)
+        // for struct patterns, take note of which fields used shorthand (`x` rather than `x: x`)
         //
-        // FIXME: according to the rust-lang-nursery/rustc-guide book and
-        // librustc/README.md, `NodeId`s are to be phased out in favor of
-        // `HirId`s; however, we need to match the signature of `each_binding`,
+        // FIXME: according to the rust-lang-nursery/rustc-guide book, `NodeId`s are to be phased
+        // out in favor of `HirId`s; however, we need to match the signature of `each_binding`,
         // which uses `NodeIds`.
         let mut shorthand_field_ids = NodeSet();
         if let hir::PatKind::Struct(_, ref fields, _) = pat.node {
index c73930553cdea679a69addc7499c105fe3e0218a..c7396b34c4689548bd413d4ec8e71b24268105a2 100644 (file)
 //! This file builds up the `ScopeTree`, which describes
 //! the parent links in the region hierarchy.
 //!
-//! Most of the documentation on regions can be found in
-//! `middle/infer/region_constraints/README.md`
+//! For more information about how MIR-based region-checking works,
+//! see the [rustc guide].
+//!
+//! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/mir-borrowck.html
 
 use ich::{StableHashingContext, NodeIdHashingMode};
 use util::nodemap::{FxHashMap, FxHashSet};
index 67f30f53a6810fb8feff799ca86cc57b12fbdeed..e242ec4985ab4ae838f7a974aef0776fcf4fc4d4 100644 (file)
@@ -15,11 +15,13 @@ macro_rules! err {
 use std::collections::BTreeMap;
 use std::fmt;
 use mir;
-use ty;
+use hir::def_id::DefId;
+use ty::{self, TyCtxt};
 use ty::layout::{self, Align, HasDataLayout};
 use middle::region;
 use std::iter;
 use syntax::ast::Mutability;
+use rustc_serialize::{Encoder, Decoder, Decodable, Encodable};
 
 #[derive(Clone, Debug, PartialEq)]
 pub enum Lock {
@@ -152,6 +154,98 @@ pub fn offset<C: HasDataLayout>(self, i: u64, cx: C) -> EvalResult<'tcx, Self> {
 impl ::rustc_serialize::UseSpecializedEncodable for AllocId {}
 impl ::rustc_serialize::UseSpecializedDecodable for AllocId {}
 
+pub const ALLOC_DISCRIMINANT: usize = 0;
+pub const FN_DISCRIMINANT: usize = 1;
+pub const EXTERN_STATIC_DISCRIMINANT: usize = 2;
+pub const SHORTHAND_START: usize = 3;
+
+pub fn specialized_encode_alloc_id<
+    'a, 'tcx,
+    E: Encoder,
+>(
+    encoder: &mut E,
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    alloc_id: AllocId,
+    shorthand: Option<usize>,
+) -> Result<(), E::Error> {
+    if let Some(shorthand) = shorthand {
+        return shorthand.encode(encoder);
+    }
+    if let Some(alloc) = tcx.interpret_interner.get_alloc(alloc_id) {
+        trace!("encoding {:?} with {:#?}", alloc_id, alloc);
+        ALLOC_DISCRIMINANT.encode(encoder)?;
+        alloc.encode(encoder)?;
+        // encode whether this allocation is the root allocation of a static
+        tcx.interpret_interner
+            .get_corresponding_static_def_id(alloc_id)
+            .encode(encoder)?;
+    } else if let Some(fn_instance) = tcx.interpret_interner.get_fn(alloc_id) {
+        trace!("encoding {:?} with {:#?}", alloc_id, fn_instance);
+        FN_DISCRIMINANT.encode(encoder)?;
+        fn_instance.encode(encoder)?;
+    } else if let Some(did) = tcx.interpret_interner.get_corresponding_static_def_id(alloc_id) {
+        // extern "C" statics don't have allocations, just encode its def_id
+        EXTERN_STATIC_DISCRIMINANT.encode(encoder)?;
+        did.encode(encoder)?;
+    } else {
+        bug!("alloc id without corresponding allocation: {}", alloc_id);
+    }
+    Ok(())
+}
+
+pub fn specialized_decode_alloc_id<
+    'a, 'tcx,
+    D: Decoder,
+    CACHE: FnOnce(&mut D, usize, AllocId),
+    SHORT: FnOnce(&mut D, usize) -> Result<AllocId, D::Error>
+>(
+    decoder: &mut D,
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    pos: usize,
+    cache: CACHE,
+    short: SHORT,
+) -> Result<AllocId, D::Error> {
+    match usize::decode(decoder)? {
+        ALLOC_DISCRIMINANT => {
+            let alloc_id = tcx.interpret_interner.reserve();
+            trace!("creating alloc id {:?} at {}", alloc_id, pos);
+            // insert early to allow recursive allocs
+            cache(decoder, pos, alloc_id);
+
+            let allocation = Allocation::decode(decoder)?;
+            trace!("decoded alloc {:?} {:#?}", alloc_id, allocation);
+            let allocation = tcx.intern_const_alloc(allocation);
+            tcx.interpret_interner.intern_at_reserved(alloc_id, allocation);
+
+            if let Some(glob) = Option::<DefId>::decode(decoder)? {
+                tcx.interpret_interner.cache(glob, alloc_id);
+            }
+
+            Ok(alloc_id)
+        },
+        FN_DISCRIMINANT => {
+            trace!("creating fn alloc id at {}", pos);
+            let instance = ty::Instance::decode(decoder)?;
+            trace!("decoded fn alloc instance: {:?}", instance);
+            let id = tcx.interpret_interner.create_fn_alloc(instance);
+            trace!("created fn alloc id: {:?}", id);
+            cache(decoder, pos, id);
+            Ok(id)
+        },
+        EXTERN_STATIC_DISCRIMINANT => {
+            trace!("creating extern static alloc id at {}", pos);
+            let did = DefId::decode(decoder)?;
+            let alloc_id = tcx.interpret_interner.reserve();
+            tcx.interpret_interner.cache(did, alloc_id);
+            Ok(alloc_id)
+        },
+        shorthand => {
+            trace!("loading shorthand {}", shorthand);
+            short(decoder, shorthand)
+        },
+    }
+}
+
 impl fmt::Display for AllocId {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "{}", self.0)
index 939710ffd2b86a53a7864b91241da4dfd41e84da..64a1729982a3168aae8757340c5fbfcc3da40ce5 100644 (file)
@@ -8,9 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! MIR datatypes and passes. See the module-level [README] for details.
+//! MIR datatypes and passes. See the [rustc guide] for more info.
 //!
-//! [README]: https://github.com/rust-lang/rust/blob/master/src/librustc/mir/README.md
+//! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/mir.html
 
 use graphviz::IntoCow;
 use middle::const_val::ConstVal;
index 7e5dc02798dff72ad6ca12d170cc092621aab5f0..ab3c619dcdcd0a42e209d72d6a8603855c1cc2d7 100644 (file)
@@ -606,6 +606,7 @@ pub fn report_selection_error(&self,
                         }
 
                         self.suggest_borrow_on_unsized_slice(&obligation.cause.code, &mut err);
+                        self.suggest_remove_reference(&obligation, &mut err, &trait_ref);
 
                         // Try to report a help message
                         if !trait_ref.has_infer_types() &&
@@ -844,6 +845,54 @@ fn suggest_borrow_on_unsized_slice(&self,
         }
     }
 
+    /// Whenever references are used by mistake, like `for (i, e) in &vec.iter().enumerate()`,
+    /// suggest removing these references until we reach a type that implements the trait.
+    fn suggest_remove_reference(&self,
+                                obligation: &PredicateObligation<'tcx>,
+                                err: &mut DiagnosticBuilder<'tcx>,
+                                trait_ref: &ty::Binder<ty::TraitRef<'tcx>>) {
+        let ty::Binder(trait_ref) = trait_ref;
+        let span = obligation.cause.span;
+
+        if let Ok(snippet) = self.tcx.sess.codemap().span_to_snippet(span) {
+            let refs_number = snippet.chars()
+                .filter(|c| !c.is_whitespace())
+                .take_while(|c| *c == '&')
+                .count();
+
+            let mut trait_type = trait_ref.self_ty();
+            let mut selcx = SelectionContext::new(self);
+
+            for refs_remaining in 0..refs_number {
+                if let ty::TypeVariants::TyRef(_, ty::TypeAndMut{ ty: t_type, mutbl: _ }) =
+                    trait_type.sty {
+
+                    trait_type = t_type;
+
+                    let substs = self.tcx.mk_substs_trait(trait_type, &[]);
+                    let new_trait_ref = ty::TraitRef::new(trait_ref.def_id, substs);
+                    let new_obligation = Obligation::new(ObligationCause::dummy(),
+                                                         obligation.param_env,
+                                                         new_trait_ref.to_predicate());
+
+                    if selcx.evaluate_obligation(&new_obligation) {
+                        let sp = self.tcx.sess.codemap()
+                            .span_take_while(span, |c| c.is_whitespace() || *c == '&');
+
+                        let remove_refs = refs_remaining + 1;
+                        let format_str = format!("consider removing {} leading `&`-references",
+                                                 remove_refs);
+
+                        err.span_suggestion_short(sp, &format_str, String::from(""));
+                        break;
+                    }
+                } else {
+                    break;
+                }
+            }
+        }
+    }
+
     /// Given some node representing a fn-like thing in the HIR map,
     /// returns a span and `ArgKind` information that describes the
     /// arguments it expects. This can be supplied to
index 1caab6fd89ef982da60af7ec036a874e46663b69..017c4f5262e255f095616409124d6e6278489d10 100644 (file)
@@ -51,6 +51,7 @@ pub fn dropck_outlives(&self, ty: Ty<'tcx>) -> InferOk<'tcx, Vec<Kind<'tcx>>> {
         let gcx = tcx.global_tcx();
         let (c_ty, orig_values) = self.infcx.canonicalize_query(&self.param_env.and(ty));
         let span = self.cause.span;
+        debug!("c_ty = {:?}", c_ty);
         match &gcx.dropck_outlives(c_ty) {
             Ok(result) if result.is_proven() => {
                 match self.infcx.instantiate_query_result(
index f8b895177f381dfa74c02ca0341ceabcde309361..e56a8662f3eb4346747c3ae36e083d49422c6a8d 100644 (file)
@@ -19,6 +19,7 @@
 use ty::fast_reject::{self, SimplifiedType};
 use rustc_data_structures::sync::Lrc;
 use syntax::ast::Name;
+use util::captures::Captures;
 use util::nodemap::{DefIdMap, FxHashMap};
 
 /// A per-trait graph of impls in specialization order. At the moment, this
@@ -36,6 +37,7 @@
 ///   parents of a given specializing impl, which is needed for extracting
 ///   default items amongst other things. In the simple "chain" rule, every impl
 ///   has at most one parent.
+#[derive(RustcEncodable, RustcDecodable)]
 pub struct Graph {
     // all impls have a parent; the "root" impls have as their parent the def_id
     // of the trait
@@ -47,6 +49,7 @@ pub struct Graph {
 
 /// Children of a given impl, grouped into blanket/non-blanket varieties as is
 /// done in `TraitDef`.
+#[derive(RustcEncodable, RustcDecodable)]
 struct Children {
     // Impls of a trait (or specializations of a given impl). To allow for
     // quicker lookup, the impls are indexed by a simplified version of their
@@ -311,9 +314,10 @@ pub fn is_from_trait(&self) -> bool {
     }
 
     /// Iterate over the items defined directly by the given (impl or trait) node.
-    #[inline] // FIXME(#35870) Avoid closures being unexported due to impl Trait.
-    pub fn items(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>)
-                 -> impl Iterator<Item = ty::AssociatedItem> + 'a {
+    pub fn items(
+        &self,
+        tcx: TyCtxt<'a, 'gcx, 'tcx>,
+    ) -> impl Iterator<Item = ty::AssociatedItem> + 'a {
         tcx.associated_items(self.def_id())
     }
 
@@ -365,9 +369,13 @@ impl<'a, 'gcx, 'tcx> Ancestors {
     /// Search the items from the given ancestors, returning each definition
     /// with the given name and the given kind.
     #[inline] // FIXME(#35870) Avoid closures being unexported due to impl Trait.
-    pub fn defs(self, tcx: TyCtxt<'a, 'gcx, 'tcx>, trait_item_name: Name,
-                trait_item_kind: ty::AssociatedKind, trait_def_id: DefId)
-                -> impl Iterator<Item = NodeItem<ty::AssociatedItem>> + 'a {
+    pub fn defs(
+        self,
+        tcx: TyCtxt<'a, 'gcx, 'tcx>,
+        trait_item_name: Name,
+        trait_item_kind: ty::AssociatedKind,
+        trait_def_id: DefId,
+    ) -> impl Iterator<Item = NodeItem<ty::AssociatedItem>> + Captures<'gcx> + Captures<'tcx> + 'a {
         self.flat_map(move |node| {
             node.items(tcx).filter(move |impl_item| {
                 impl_item.kind == trait_item_kind &&
index 6533a7440ac384a86ec3614da8f79f59773c511d..31b3ca44700e96676f076782f02d0af0797279f1 100644 (file)
@@ -28,7 +28,7 @@
 /// because we sometimes need to use SimplifiedTypeGen values as stable sorting
 /// keys (in which case we use a DefPathHash as id-type) but in the general case
 /// the non-stable but fast to construct DefId-version is the better choice.
-#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, RustcEncodable, RustcDecodable)]
 pub enum SimplifiedTypeGen<D>
     where D: Copy + Debug + Ord + Eq + Hash
 {
index a3a0e26a843ac02f010c6b822efa7824c94e6c02..117d92193123564fffb7365427601f2a0a81b0d1 100644 (file)
@@ -727,3 +727,4 @@ fn try_load_from_disk<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 impl_disk_cacheable_query!(predicates_of, |def_id| def_id.is_local());
 impl_disk_cacheable_query!(used_trait_imports, |def_id| def_id.is_local());
 impl_disk_cacheable_query!(trans_fn_attrs, |_| true);
+impl_disk_cacheable_query!(specialization_graph_of, |_| true);
index b6b7361bb2f72b2758851fc126a7b2d5b4466e9f..6c3b4efb932ad891923f0bce0c88fa90ec4a2c7c 100644 (file)
 
     [] fn impl_defaultness: ImplDefaultness(DefId) -> hir::Defaultness,
 
+    [] fn check_item_well_formed: CheckItemWellFormed(DefId) -> (),
+    [] fn check_trait_item_well_formed: CheckTraitItemWellFormed(DefId) -> (),
+    [] fn check_impl_item_well_formed: CheckImplItemWellFormed(DefId) -> (),
+
     // The DefIds of all non-generic functions and statics in the given crate
     // that can be reached from outside the crate.
     //
index 35e874b74d9ae3a70dc93078d92c098da4b8e860..c103d6e015aa4c37093a10ed548822dd2804eb5c 100644 (file)
@@ -75,6 +75,13 @@ pub struct OnDiskCache<'sess> {
     // A map from dep-node to the position of any associated diagnostics in
     // `serialized_data`.
     prev_diagnostics_index: FxHashMap<SerializedDepNodeIndex, AbsoluteBytePos>,
+
+    // A cache to ensure we don't read allocations twice
+    interpret_alloc_cache: RefCell<FxHashMap<usize, interpret::AllocId>>,
+
+    // A map from positions to size of the serialized allocation
+    // so we can skip over already processed allocations
+    interpret_alloc_size: RefCell<FxHashMap<usize, usize>>,
 }
 
 // This type is used only for (de-)serialization.
@@ -140,6 +147,8 @@ pub fn new(sess: &'sess Session, data: Vec<u8>, start_pos: usize) -> OnDiskCache
             query_result_index: footer.query_result_index.into_iter().collect(),
             prev_diagnostics_index: footer.diagnostics_index.into_iter().collect(),
             synthetic_expansion_infos: RefCell::new(FxHashMap()),
+            interpret_alloc_cache: RefCell::new(FxHashMap::default()),
+            interpret_alloc_size: RefCell::new(FxHashMap::default()),
         }
     }
 
@@ -155,6 +164,8 @@ pub fn new_empty(codemap: &'sess CodeMap) -> OnDiskCache<'sess> {
             query_result_index: FxHashMap(),
             prev_diagnostics_index: FxHashMap(),
             synthetic_expansion_infos: RefCell::new(FxHashMap()),
+            interpret_alloc_cache: RefCell::new(FxHashMap::default()),
+            interpret_alloc_size: RefCell::new(FxHashMap::default()),
         }
     }
 
@@ -221,6 +232,7 @@ pub fn serialize<'a, 'tcx, E>(&self,
                 encode_query_results::<symbol_name, _>(tcx, enc, qri)?;
                 encode_query_results::<check_match, _>(tcx, enc, qri)?;
                 encode_query_results::<trans_fn_attrs, _>(tcx, enc, qri)?;
+                encode_query_results::<specialization_graph_of, _>(tcx, enc, qri)?;
 
                 // const eval is special, it only encodes successfully evaluated constants
                 use ty::maps::plumbing::GetCacheInternal;
@@ -381,7 +393,8 @@ fn load_indexed<'tcx, T>(&self,
             file_index_to_file: &self.file_index_to_file,
             file_index_to_stable_id: &self.file_index_to_stable_id,
             synthetic_expansion_infos: &self.synthetic_expansion_infos,
-            interpret_alloc_cache: FxHashMap::default(),
+            interpret_alloc_cache: &self.interpret_alloc_cache,
+            interpret_alloc_size: &self.interpret_alloc_size,
         };
 
         match decode_tagged(&mut decoder, dep_node_index) {
@@ -443,7 +456,8 @@ struct CacheDecoder<'a, 'tcx: 'a, 'x> {
     synthetic_expansion_infos: &'x RefCell<FxHashMap<AbsoluteBytePos, SyntaxContext>>,
     file_index_to_file: &'x RefCell<FxHashMap<FileMapIndex, Lrc<FileMap>>>,
     file_index_to_stable_id: &'x FxHashMap<FileMapIndex, StableFilemapId>,
-    interpret_alloc_cache: FxHashMap<usize, interpret::AllocId>,
+    interpret_alloc_cache: &'x RefCell<FxHashMap<usize, interpret::AllocId>>,
+    interpret_alloc_size: &'x RefCell<FxHashMap<usize, usize>>,
 }
 
 impl<'a, 'tcx, 'x> CacheDecoder<'a, 'tcx, 'x> {
@@ -565,47 +579,37 @@ fn map_encoded_cnum_to_current(&self, cnum: CrateNum) -> CrateNum {
 
 impl<'a, 'tcx, 'x> SpecializedDecoder<interpret::AllocId> for CacheDecoder<'a, 'tcx, 'x> {
     fn specialized_decode(&mut self) -> Result<interpret::AllocId, Self::Error> {
-        const MAX1: usize = usize::max_value() - 1;
         let tcx = self.tcx;
         let pos = TyDecoder::position(self);
-        match usize::decode(self)? {
-            ::std::usize::MAX => {
-                let alloc_id = tcx.interpret_interner.reserve();
-                trace!("creating alloc id {:?} at {}", alloc_id, pos);
-                // insert early to allow recursive allocs
-                self.interpret_alloc_cache.insert(pos, alloc_id);
-
-                let allocation = interpret::Allocation::decode(self)?;
-                trace!("decoded alloc {:?} {:#?}", alloc_id, allocation);
-                let allocation = self.tcx.intern_const_alloc(allocation);
-                tcx.interpret_interner.intern_at_reserved(alloc_id, allocation);
-
-                if let Some(glob) = Option::<DefId>::decode(self)? {
-                    trace!("connecting alloc {:?} with {:?}", alloc_id, glob);
-                    tcx.interpret_interner.cache(glob, alloc_id);
-                }
-
-                Ok(alloc_id)
-            },
-            MAX1 => {
-                trace!("creating fn alloc id at {}", pos);
-                let instance = ty::Instance::decode(self)?;
-                trace!("decoded fn alloc instance: {:?}", instance);
-                let id = tcx.interpret_interner.create_fn_alloc(instance);
-                trace!("created fn alloc id: {:?}", id);
-                self.interpret_alloc_cache.insert(pos, id);
-                Ok(id)
+        trace!("specialized_decode_alloc_id: {:?}", pos);
+        if let Some(cached) = self.interpret_alloc_cache.borrow().get(&pos).cloned() {
+            // if there's no end position we are currently deserializing a recursive
+            // allocation
+            if let Some(end) = self.interpret_alloc_size.borrow().get(&pos).cloned() {
+                trace!("{} already cached as {:?}", pos, cached);
+                // skip ahead
+                self.opaque.set_position(end);
+                return Ok(cached)
+            }
+        }
+        let id = interpret::specialized_decode_alloc_id(
+            self,
+            tcx,
+            pos,
+            |this, pos, alloc_id| {
+                assert!(this.interpret_alloc_cache.borrow_mut().insert(pos, alloc_id).is_none());
             },
-            shorthand => {
-                trace!("loading shorthand {}", shorthand);
-                if let Some(&alloc_id) = self.interpret_alloc_cache.get(&shorthand) {
-                    return Ok(alloc_id);
-                }
-                trace!("shorthand {} not cached, loading entire allocation", shorthand);
+            |this, shorthand| {
                 // need to load allocation
-                self.with_position(shorthand, |this| interpret::AllocId::decode(this))
-            },
-        }
+                this.with_position(shorthand, |this| interpret::AllocId::decode(this))
+            }
+        )?;
+        assert!(self
+            .interpret_alloc_size
+            .borrow_mut()
+            .insert(pos, TyDecoder::position(self))
+            .is_none());
+        Ok(id)
     }
 }
 impl<'a, 'tcx, 'x> SpecializedDecoder<Span> for CacheDecoder<'a, 'tcx, 'x> {
@@ -806,30 +810,27 @@ impl<'enc, 'a, 'tcx, E> SpecializedEncoder<interpret::AllocId> for CacheEncoder<
     where E: 'enc + ty_codec::TyEncoder
 {
     fn specialized_encode(&mut self, alloc_id: &interpret::AllocId) -> Result<(), Self::Error> {
-        trace!("encoding {:?} at {}", alloc_id, self.position());
-        if let Some(shorthand) = self.interpret_alloc_shorthands.get(alloc_id).cloned() {
-            trace!("encoding {:?} as shorthand to {}", alloc_id, shorthand);
-            return shorthand.encode(self);
-        }
-        let start = self.position();
-        // cache the allocation shorthand now, because the allocation itself might recursively
-        // point to itself.
-        self.interpret_alloc_shorthands.insert(*alloc_id, start);
-        if let Some(alloc) = self.tcx.interpret_interner.get_alloc(*alloc_id) {
-            trace!("encoding {:?} with {:#?}", alloc_id, alloc);
-            usize::max_value().encode(self)?;
-            alloc.encode(self)?;
-            self.tcx.interpret_interner
-                .get_corresponding_static_def_id(*alloc_id)
-                .encode(self)?;
-        } else if let Some(fn_instance) = self.tcx.interpret_interner.get_fn(*alloc_id) {
-            trace!("encoding {:?} with {:#?}", alloc_id, fn_instance);
-            (usize::max_value() - 1).encode(self)?;
-            fn_instance.encode(self)?;
-        } else {
-            bug!("alloc id without corresponding allocation: {}", alloc_id);
-        }
-        Ok(())
+        use std::collections::hash_map::Entry;
+        let tcx = self.tcx;
+        let pos = self.position();
+        let shorthand = match self.interpret_alloc_shorthands.entry(*alloc_id) {
+            Entry::Occupied(entry) => Some(entry.get().clone()),
+            Entry::Vacant(entry) => {
+                // ensure that we don't place any AllocIds at the very beginning
+                // of the metadata file, because that would end up making our indices
+                // not special. It is essentially impossible for that to happen,
+                // but let's make sure
+                assert!(pos >= interpret::SHORTHAND_START);
+                entry.insert(pos);
+                None
+            },
+        };
+        interpret::specialized_encode_alloc_id(
+            self,
+            tcx,
+            *alloc_id,
+            shorthand,
+        )
     }
 }
 
index dd65d4b4190718ff5fbcfdf49bb1235bff36a1f7..4170fa7679716034468fdf9e8cb52d32403f1eed 100644 (file)
@@ -871,6 +871,9 @@ macro_rules! force {
         DepKind::GetPanicStrategy => { force!(panic_strategy, krate!()); }
         DepKind::IsNoBuiltins => { force!(is_no_builtins, krate!()); }
         DepKind::ImplDefaultness => { force!(impl_defaultness, def_id!()); }
+        DepKind::CheckItemWellFormed => { force!(check_item_well_formed, def_id!()); }
+        DepKind::CheckTraitItemWellFormed => { force!(check_trait_item_well_formed, def_id!()); }
+        DepKind::CheckImplItemWellFormed => { force!(check_impl_item_well_formed, def_id!()); }
         DepKind::ReachableNonGenerics => { force!(reachable_non_generics, krate!()); }
         DepKind::NativeLibraries => { force!(native_libraries, krate!()); }
         DepKind::PluginRegistrarFn => { force!(plugin_registrar_fn, krate!()); }
@@ -1003,4 +1006,5 @@ pub fn load_from_on_disk_cache(&self, tcx: TyCtxt) {
     PredicatesOfItem => predicates_of,
     UsedTraitImports => used_trait_imports,
     TransFnAttrs => trans_fn_attrs,
+    SpecializationGraph => specialization_graph_of,
 );
index c915022351925f835a8afc49de54dd2b082425f7..95c5cd377d71f4c190adf60e2eca2374be9d3f5a 100644 (file)
@@ -34,6 +34,7 @@
 use ty::subst::{Subst, Substs};
 use ty::util::{IntTypeExt, Discr};
 use ty::walk::TypeWalker;
+use util::captures::Captures;
 use util::nodemap::{NodeSet, DefIdMap, FxHashMap};
 
 use serialize::{self, Encodable, Encoder};
@@ -1942,8 +1943,10 @@ pub fn eval_explicit_discr(
     }
 
     #[inline]
-    pub fn discriminants(&'a self, tcx: TyCtxt<'a, 'gcx, 'tcx>)
-                         -> impl Iterator<Item=Discr<'tcx>> + 'a {
+    pub fn discriminants(
+        &'a self,
+        tcx: TyCtxt<'a, 'gcx, 'tcx>,
+    ) -> impl Iterator<Item=Discr<'tcx>> + Captures<'gcx> + 'a {
         let repr_type = self.repr.discr_type();
         let initial = repr_type.initial_discriminant(tcx.global_tcx());
         let mut prev_discr = None::<Discr<'tcx>>;
@@ -2290,7 +2293,9 @@ pub fn body_tables(self, body: hir::BodyId) -> &'gcx TypeckTables<'gcx> {
     /// Returns an iterator of the def-ids for all body-owners in this
     /// crate. If you would prefer to iterate over the bodies
     /// themselves, you can do `self.hir.krate().body_ids.iter()`.
-    pub fn body_owners(self) -> impl Iterator<Item = DefId> + 'a {
+    pub fn body_owners(
+        self,
+    ) -> impl Iterator<Item = DefId> + Captures<'tcx> + Captures<'gcx> + 'a {
         self.hir.krate()
                 .body_ids
                 .iter()
@@ -2394,11 +2399,13 @@ fn associated_item_from_impl_item_ref(self,
         }
     }
 
-    #[inline] // FIXME(#35870) Avoid closures being unexported due to impl Trait.
-    pub fn associated_items(self, def_id: DefId)
-                            -> impl Iterator<Item = ty::AssociatedItem> + 'a {
+    pub fn associated_items(
+        self,
+        def_id: DefId,
+    ) -> impl Iterator<Item = ty::AssociatedItem> + 'a {
         let def_ids = self.associated_item_def_ids(def_id);
-        (0..def_ids.len()).map(move |i| self.associated_item(def_ids[i]))
+        Box::new((0..def_ids.len()).map(move |i| self.associated_item(def_ids[i])))
+            as Box<dyn Iterator<Item = ty::AssociatedItem> + 'a>
     }
 
     /// Returns true if the impls are the same polarity and are implementing
index ae053d7f4f58db96dbe39d02edb1d0b729268b69..d7ab6e39ac5f082dbbd4103810abc3266d66a196 100644 (file)
@@ -18,6 +18,7 @@
 use ty::subst::{Substs, Subst, Kind, UnpackedKind};
 use ty::{self, AdtDef, TypeFlags, Ty, TyCtxt, TypeFoldable};
 use ty::{Slice, TyS};
+use util::captures::Captures;
 
 use std::iter;
 use std::cmp::Ordering;
@@ -384,9 +385,11 @@ impl<'a, 'gcx, 'tcx> ClosureSubsts<'tcx> {
     /// This returns the types of the MIR locals which had to be stored across suspension points.
     /// It is calculated in rustc_mir::transform::generator::StateTransform.
     /// All the types here must be in the tuple in GeneratorInterior.
-    pub fn state_tys(self, def_id: DefId, tcx: TyCtxt<'a, 'gcx, 'tcx>) ->
-        impl Iterator<Item=Ty<'tcx>> + 'a
-    {
+    pub fn state_tys(
+        self,
+        def_id: DefId,
+        tcx: TyCtxt<'a, 'gcx, 'tcx>,
+    ) -> impl Iterator<Item=Ty<'tcx>> + Captures<'gcx> + 'a {
         let state = tcx.generator_layout(def_id).fields.iter();
         state.map(move |d| d.ty.subst(tcx, self.substs))
     }
@@ -403,7 +406,7 @@ impl Iterator<Item=Ty<'tcx>> + 'a
     /// This is the types of all the fields stored in a generator.
     /// It includes the upvars, state types and the state discriminant which is u32.
     pub fn field_tys(self, def_id: DefId, tcx: TyCtxt<'a, 'gcx, 'tcx>) ->
-        impl Iterator<Item=Ty<'tcx>> + 'a
+        impl Iterator<Item=Ty<'tcx>> + Captures<'gcx> + 'a
     {
         self.pre_transforms_tys(def_id, tcx).chain(self.state_tys(def_id, tcx))
     }
@@ -991,10 +994,11 @@ pub struct DebruijnIndex {
 /// the inference variable is supposed to satisfy the relation
 /// *for every value of the skolemized region*. To ensure that doesn't
 /// happen, you can use `leak_check`. This is more clearly explained
-/// by infer/higher_ranked/README.md.
+/// by the [rustc guide].
 ///
 /// [1]: http://smallcultfollowing.com/babysteps/blog/2013/10/29/intermingled-parameter-lists/
 /// [2]: http://smallcultfollowing.com/babysteps/blog/2013/11/04/intermingled-parameter-lists/
+/// [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/trait-hrtb.html
 #[derive(Clone, PartialEq, Eq, Hash, Copy, RustcEncodable, RustcDecodable, PartialOrd, Ord)]
 pub enum RegionKind {
     // Region bound in a type or fn declaration which will be
diff --git a/src/librustc/util/captures.rs b/src/librustc/util/captures.rs
new file mode 100644 (file)
index 0000000..b68cfd2
--- /dev/null
@@ -0,0 +1,18 @@
+// 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.
+
+/// "Signaling" trait used in impl trait to tag lifetimes that you may
+/// need to capture but don't really need for other reasons.
+/// Basically a workaround; see [this comment] for details.
+///
+/// [this comment]: https://github.com/rust-lang/rust/issues/34511#issuecomment-373423999
+pub trait Captures<'a> { }
+
+impl<'a, T: ?Sized> Captures<'a> for T { }
index 3afc2f684009d41e8d23b113bd2d9a9a59fd2dd8..565658804b00134546f78dc4fa7341970b4cba86 100644 (file)
@@ -47,7 +47,7 @@
 #![forbid(unsafe_code)]
 
 #![feature(i128_type)]
-#![feature(slice_patterns)]
+#![cfg_attr(stage0, feature(slice_patterns))]
 #![feature(try_from)]
 
 // See librustc_cratesio_shim/Cargo.toml for a comment explaining this.
index bd99c687bb6ad91597414b3d491eecd40381ce82..3c01692c12b3c846957c15f44d2746158808e1f8 100644 (file)
@@ -1,6 +1,6 @@
-NB: This crate is part of the Rust compiler. For an overview of the
-compiler as a whole, see
-[the README.md file found in `librustc`](../librustc/README.md).
-
 `librustc_back` contains some very low-level details that are
 specific to different LLVM targets and so forth.
+
+For more information about how trans works, see the [rustc guide].
+
+[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/trans.html
index da2b1ef0b1c02a3aef7b1345945d3858285a1e11..29f03c06ab75999c5048b74340ee2a87b8cf60b0 100644 (file)
@@ -1,5 +1,10 @@
 % The Borrow Checker
 
+> WARNING: This README is more or less obsolete, and will be removed
+> soon! The new system is described in the [rustc guide].
+
+[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/mir-borrowck.html
+
 This pass has the job of enforcing memory safety. This is a subtle
 topic. This docs aim to explain both the practice and the theory
 behind the borrow checker. They start with a high-level overview of
index bb198adea4a6a6c88a0c304163a1da053747a04b..93d6247eeae47733af3b4f8833bbb248ceda400c 100644 (file)
@@ -253,28 +253,28 @@ pub struct BorrowckCtxt<'a, 'tcx: 'a> {
     used_mut_nodes: RefCell<FxHashSet<HirId>>,
 }
 
-impl<'b, 'tcx: 'b> BorrowckErrors for BorrowckCtxt<'b, 'tcx> {
-    fn struct_span_err_with_code<'a, S: Into<MultiSpan>>(&'a self,
-                                                         sp: S,
-                                                         msg: &str,
-                                                         code: DiagnosticId)
-                                                         -> DiagnosticBuilder<'a>
+impl<'a, 'b, 'tcx: 'b> BorrowckErrors<'a> for &'a BorrowckCtxt<'b, 'tcx> {
+    fn struct_span_err_with_code<S: Into<MultiSpan>>(self,
+                                                     sp: S,
+                                                     msg: &str,
+                                                     code: DiagnosticId)
+                                                     -> DiagnosticBuilder<'a>
     {
         self.tcx.sess.struct_span_err_with_code(sp, msg, code)
     }
 
-    fn struct_span_err<'a, S: Into<MultiSpan>>(&'a self,
-                                               sp: S,
-                                               msg: &str)
-                                               -> DiagnosticBuilder<'a>
+    fn struct_span_err<S: Into<MultiSpan>>(self,
+                                           sp: S,
+                                           msg: &str)
+                                           -> DiagnosticBuilder<'a>
     {
         self.tcx.sess.struct_span_err(sp, msg)
     }
 
-    fn cancel_if_wrong_origin<'a>(&'a self,
-                                mut diag: DiagnosticBuilder<'a>,
-                                o: Origin)
-                                -> DiagnosticBuilder<'a>
+    fn cancel_if_wrong_origin(self,
+                              mut diag: DiagnosticBuilder<'a>,
+                              o: Origin)
+                              -> DiagnosticBuilder<'a>
     {
         if !o.should_emit_errors(self.tcx.borrowck_mode()) {
             self.tcx.sess.diagnostic().cancel(&mut diag);
index 459aa9ea488fd808c924ca3ed04540d02e6fdb16..2b0775e86952bbad78af7a1e0e5bf3ad1800ed5c 100644 (file)
@@ -20,7 +20,6 @@
 #![deny(warnings)]
 
 #![feature(rustc_diagnostic_macros)]
-#![feature(slice_patterns)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
 #![feature(macro_lifetime_matcher)]
index a5b1a7e57ab4668167dc893fb2bbf003396138d2..cbb3ff5171592be599cc292b6e07b477c627a949 100644 (file)
@@ -503,6 +503,13 @@ pub fn pick2_mut(&mut self, a: I, b: I) -> (&mut T, &mut T) {
             (c1, c2)
         }
     }
+
+    pub fn convert_index_type<Ix: Idx>(self) -> IndexVec<Ix, T> {
+        IndexVec {
+            raw: self.raw,
+            _marker: PhantomData,
+        }
+    }
 }
 
 impl<I: Idx, T: Clone> IndexVec<I, T> {
index 839d1831f95443fe7e4105d5808eb8bf1e710c9a..fef249a9e4eb8e02936c99691908a8f20772965a 100644 (file)
@@ -1,7 +1,3 @@
-NB: This crate is part of the Rust compiler. For an overview of the
-compiler as a whole, see
-[the README.md file found in `librustc`](../librustc/README.md).
-
 The `driver` crate is effectively the "main" function for the rust
 compiler.  It orchestrates the compilation process and "knits together"
 the code from the other crates within rustc. This crate itself does
@@ -9,4 +5,6 @@ not contain any of the "main logic" of the compiler (though it does
 have some code related to pretty printing or other minor compiler
 options).
 
+For more information about how the driver works, see the [rustc guide].
 
+[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/rustc-driver.html
index ca1e3563089dbdfe226f2621604255d097d8b137..a5bc1106ba0b00fc24264b5378cd5711274e69ea 100644 (file)
@@ -162,7 +162,7 @@ struct Stat {
 
         let mut counts: FxHashMap<_, Stat> = FxHashMap();
 
-        for (i, &(node, _)) in serialized_graph.nodes.iter_enumerated() {
+        for (i, &node) in serialized_graph.nodes.iter_enumerated() {
             let stat = counts.entry(node.kind).or_insert(Stat {
                 kind: node.kind,
                 node_counter: 0,
index 8b86c90548952b50b4de890f7aeea7bbb1e16df0..ce896bfb701baf5385b7aaafda9532b4869c15b1 100644 (file)
@@ -31,7 +31,6 @@
 #![feature(macro_vis_matcher)]
 #![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
-#![feature(slice_patterns)]
 #![cfg_attr(stage0, feature(never_type))]
 
 #[macro_use]
index d83d6f26393d1ef2efde82e2dc1d68adf60c1c9a..b0c945fbf2a052f3f1f1027c3d62b03dc2b76451 100644 (file)
@@ -29,6 +29,7 @@
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::codec::TyDecoder;
 use rustc::mir::Mir;
+use rustc::util::captures::Captures;
 use rustc::util::nodemap::FxHashMap;
 
 use std::collections::BTreeMap;
@@ -57,6 +58,9 @@ pub struct DecodeContext<'a, 'tcx: 'a> {
 
     // interpreter allocation cache
     interpret_alloc_cache: FxHashMap<usize, interpret::AllocId>,
+    // a cache for sizes of interpreter allocations
+    // needed to skip already deserialized allocations
+    interpret_alloc_size: FxHashMap<usize, usize>,
 }
 
 /// Abstract over the various ways one can create metadata decoders.
@@ -76,6 +80,7 @@ fn decoder(self, pos: usize) -> DecodeContext<'a, 'tcx> {
             last_filemap_index: 0,
             lazy_state: LazyState::NoNode,
             interpret_alloc_cache: FxHashMap::default(),
+            interpret_alloc_size: FxHashMap::default(),
         }
     }
 }
@@ -142,7 +147,10 @@ pub fn decode<M: Metadata<'a, 'tcx>>(self, meta: M) -> T {
 }
 
 impl<'a, 'tcx: 'a, T: Decodable> LazySeq<T> {
-    pub fn decode<M: Metadata<'a, 'tcx>>(self, meta: M) -> impl Iterator<Item = T> + 'a {
+    pub fn decode<M: Metadata<'a, 'tcx>>(
+        self,
+        meta: M,
+    ) -> impl Iterator<Item = T> + Captures<'tcx> + 'a {
         let mut dcx = meta.decoder(self.position);
         dcx.lazy_state = LazyState::NodeStart(self.position);
         (0..self.len).map(move |_| T::decode(&mut dcx).unwrap())
@@ -281,46 +289,34 @@ fn specialized_decode(&mut self) -> Result<LocalDefId, Self::Error> {
 
 impl<'a, 'tcx> SpecializedDecoder<interpret::AllocId> for DecodeContext<'a, 'tcx> {
     fn specialized_decode(&mut self) -> Result<interpret::AllocId, Self::Error> {
-        const MAX1: usize = usize::max_value() - 1;
-        let tcx = self.tcx.unwrap();
+        let tcx = self.tcx.expect("need tcx for AllocId decoding");
         let pos = self.position();
-        match usize::decode(self)? {
-            ::std::usize::MAX => {
-                let alloc_id = tcx.interpret_interner.reserve();
-                trace!("creating alloc id {:?} at {}", alloc_id, pos);
-                // insert early to allow recursive allocs
-                self.interpret_alloc_cache.insert(pos, alloc_id);
-
-                let allocation = interpret::Allocation::decode(self)?;
-                trace!("decoded alloc {:?} {:#?}", alloc_id, allocation);
-                let allocation = self.tcx.unwrap().intern_const_alloc(allocation);
-                tcx.interpret_interner.intern_at_reserved(alloc_id, allocation);
-
-                if let Some(glob) = Option::<DefId>::decode(self)? {
-                    tcx.interpret_interner.cache(glob, alloc_id);
-                }
-
-                Ok(alloc_id)
-            },
-            MAX1 => {
-                trace!("creating fn alloc id at {}", pos);
-                let instance = ty::Instance::decode(self)?;
-                trace!("decoded fn alloc instance: {:?}", instance);
-                let id = tcx.interpret_interner.create_fn_alloc(instance);
-                trace!("created fn alloc id: {:?}", id);
-                self.interpret_alloc_cache.insert(pos, id);
-                Ok(id)
-            },
-            shorthand => {
-                trace!("loading shorthand {}", shorthand);
-                if let Some(&alloc_id) = self.interpret_alloc_cache.get(&shorthand) {
-                    return Ok(alloc_id);
-                }
-                trace!("shorthand {} not cached, loading entire allocation", shorthand);
-                // need to load allocation
-                self.with_position(shorthand, |this| interpret::AllocId::decode(this))
-            },
+        if let Some(cached) = self.interpret_alloc_cache.get(&pos).cloned() {
+            // if there's no end position we are currently deserializing a recursive
+            // allocation
+            if let Some(end) = self.interpret_alloc_size.get(&pos).cloned() {
+                trace!("{} already cached as {:?}", pos, cached);
+                // skip ahead
+                self.opaque.set_position(end);
+                return Ok(cached)
+            }
         }
+        let id = interpret::specialized_decode_alloc_id(
+            self,
+            tcx,
+            pos,
+            |this, pos, alloc_id| { this.interpret_alloc_cache.insert(pos, alloc_id); },
+            |this, shorthand| {
+                // need to load allocation
+                this.with_position(shorthand, |this| interpret::AllocId::decode(this))
+            }
+        )?;
+        let end_pos = self.position();
+        assert!(self
+            .interpret_alloc_size
+            .insert(pos, end_pos)
+            .is_none());
+        Ok(id)
     }
 }
 
index d959482417489a16b015c8c77f23e31737a791ff..6b3453f2c99e832d591bce45fd0c05270f8bf7a9 100644 (file)
@@ -196,30 +196,26 @@ fn specialized_encode(&mut self, ty: &Ty<'tcx>) -> Result<(), Self::Error> {
 
 impl<'a, 'tcx> SpecializedEncoder<interpret::AllocId> for EncodeContext<'a, 'tcx> {
     fn specialized_encode(&mut self, alloc_id: &interpret::AllocId) -> Result<(), Self::Error> {
-        trace!("encoding {:?} at {}", alloc_id, self.position());
-        if let Some(shorthand) = self.interpret_alloc_shorthands.get(alloc_id).cloned() {
-            trace!("encoding {:?} as shorthand to {}", alloc_id, shorthand);
-            return shorthand.encode(self);
-        }
-        let start = self.position();
-        // cache the allocation shorthand now, because the allocation itself might recursively
-        // point to itself.
-        self.interpret_alloc_shorthands.insert(*alloc_id, start);
-        if let Some(alloc) = self.tcx.interpret_interner.get_alloc(*alloc_id) {
-            trace!("encoding {:?} with {:#?}", alloc_id, alloc);
-            usize::max_value().encode(self)?;
-            alloc.encode(self)?;
-            self.tcx.interpret_interner
-                .get_corresponding_static_def_id(*alloc_id)
-                .encode(self)?;
-        } else if let Some(fn_instance) = self.tcx.interpret_interner.get_fn(*alloc_id) {
-            trace!("encoding {:?} with {:#?}", alloc_id, fn_instance);
-            (usize::max_value() - 1).encode(self)?;
-            fn_instance.encode(self)?;
-        } else {
-            bug!("alloc id without corresponding allocation: {}", alloc_id);
-        }
-        Ok(())
+        use std::collections::hash_map::Entry;
+        let tcx = self.tcx;
+        let pos = self.position();
+        let shorthand = match self.interpret_alloc_shorthands.entry(*alloc_id) {
+            Entry::Occupied(entry) => Some(entry.get().clone()),
+            Entry::Vacant(entry) => {
+                // ensure that we don't place any AllocIds at the very beginning
+                // of the metadata file, because that would end up making our indices
+                // not special. This is essentially impossible, but let's make sure
+                assert!(pos >= interpret::SHORTHAND_START);
+                entry.insert(pos);
+                None
+            },
+        };
+        interpret::specialized_encode_alloc_id(
+            self,
+            tcx,
+            *alloc_id,
+            shorthand,
+        )
     }
 }
 
index ef30b1e452230df786add31df2af97b9344bda0d..7281fb59663881ee222345491332af71b5721070 100644 (file)
@@ -117,10 +117,9 @@ fn ast_block_stmts(&mut self,
                     // Evaluate the initializer, if present.
                     if let Some(init) = initializer {
                         unpack!(block = this.in_opt_scope(
-                            opt_destruction_scope.map(|de|(de, source_info)), block, move |this| {
+                            opt_destruction_scope.map(|de|(de, source_info)), block, |this| {
                                 let scope = (init_scope, source_info);
-                                this.in_scope(scope, lint_level, block, move |this| {
-                                    // FIXME #30046                             ^~~~
+                                this.in_scope(scope, lint_level, block, |this| {
                                     this.expr_into_pattern(block, pattern, init)
                                 })
                             }));
index 89242ca32bcbfa1586ddb2541e3c13b9d8bc5fce..5e15348de5e718a76632bf2e11c1daeceb341e4b 100644 (file)
@@ -52,30 +52,30 @@ pub fn should_emit_errors(self, mode: BorrowckMode) -> bool {
     }
 }
 
-pub trait BorrowckErrors {
-    fn struct_span_err_with_code<'a, S: Into<MultiSpan>>(&'a self,
-                                                         sp: S,
-                                                         msg: &str,
-                                                         code: DiagnosticId)
-                                                         -> DiagnosticBuilder<'a>;
-
-    fn struct_span_err<'a, S: Into<MultiSpan>>(&'a self,
-                                               sp: S,
-                                               msg: &str)
-                                               -> DiagnosticBuilder<'a>;
+pub trait BorrowckErrors<'cx>: Sized + Copy {
+    fn struct_span_err_with_code<S: Into<MultiSpan>>(self,
+                                                     sp: S,
+                                                     msg: &str,
+                                                     code: DiagnosticId)
+                                                     -> DiagnosticBuilder<'cx>;
+
+    fn struct_span_err<S: Into<MultiSpan>>(self,
+                                           sp: S,
+                                           msg: &str)
+                                           -> DiagnosticBuilder<'cx>;
 
     /// Cancels the given error if we shouldn't emit errors for a given
     /// origin in the current mode.
     ///
     /// Always make sure that the error gets passed through this function
     /// before you return it.
-    fn cancel_if_wrong_origin<'a>(&'a self,
-                                diag: DiagnosticBuilder<'a>,
-                                o: Origin)
-                                -> DiagnosticBuilder<'a>;
+    fn cancel_if_wrong_origin(self,
+                              diag: DiagnosticBuilder<'cx>,
+                              o: Origin)
+                              -> DiagnosticBuilder<'cx>;
 
-    fn cannot_move_when_borrowed(&self, span: Span, desc: &str, o: Origin)
-                                 -> DiagnosticBuilder<'_>
+    fn cannot_move_when_borrowed(self, span: Span, desc: &str, o: Origin)
+                                 -> DiagnosticBuilder<'cx>
     {
         let err = struct_span_err!(self, span, E0505,
                                    "cannot move out of `{}` because it is borrowed{OGN}",
@@ -83,13 +83,13 @@ fn cannot_move_when_borrowed(&self, span: Span, desc: &str, o: Origin)
         self.cancel_if_wrong_origin(err, o)
     }
 
-    fn cannot_use_when_mutably_borrowed(&self,
+    fn cannot_use_when_mutably_borrowed(self,
                                         span: Span,
                                         desc: &str,
                                         borrow_span: Span,
                                         borrow_desc: &str,
                                         o: Origin)
-                                        -> DiagnosticBuilder<'_>
+                                        -> DiagnosticBuilder<'cx>
     {
         let mut err = struct_span_err!(self, span, E0503,
                          "cannot use `{}` because it was mutably borrowed{OGN}",
@@ -101,12 +101,12 @@ fn cannot_use_when_mutably_borrowed(&self,
         self.cancel_if_wrong_origin(err, o)
     }
 
-    fn cannot_act_on_uninitialized_variable(&self,
+    fn cannot_act_on_uninitialized_variable(self,
                                             span: Span,
                                             verb: &str,
                                             desc: &str,
                                             o: Origin)
-                                            -> DiagnosticBuilder
+                                            -> DiagnosticBuilder<'cx>
     {
         let err = struct_span_err!(self, span, E0381,
                                    "{} of possibly uninitialized variable: `{}`{OGN}",
@@ -114,7 +114,7 @@ fn cannot_act_on_uninitialized_variable(&self,
         self.cancel_if_wrong_origin(err, o)
     }
 
-    fn cannot_mutably_borrow_multiply(&self,
+    fn cannot_mutably_borrow_multiply(self,
                                       new_loan_span: Span,
                                       desc: &str,
                                       opt_via: &str,
@@ -122,7 +122,7 @@ fn cannot_mutably_borrow_multiply(&self,
                                       old_opt_via: &str,
                                       old_load_end_span: Option<Span>,
                                       o: Origin)
-                                      -> DiagnosticBuilder
+                                      -> DiagnosticBuilder<'cx>
     {
         let mut err = struct_span_err!(self, new_loan_span, E0499,
                          "cannot borrow `{}`{} as mutable more than once at a time{OGN}",
@@ -148,13 +148,13 @@ fn cannot_mutably_borrow_multiply(&self,
         self.cancel_if_wrong_origin(err, o)
     }
 
-    fn cannot_uniquely_borrow_by_two_closures(&self,
+    fn cannot_uniquely_borrow_by_two_closures(self,
                                               new_loan_span: Span,
                                               desc: &str,
                                               old_loan_span: Span,
                                               old_load_end_span: Option<Span>,
                                               o: Origin)
-                                              -> DiagnosticBuilder
+                                              -> DiagnosticBuilder<'cx>
     {
         let mut err = struct_span_err!(self, new_loan_span, E0524,
                          "two closures require unique access to `{}` at the same time{OGN}",
@@ -173,7 +173,7 @@ fn cannot_uniquely_borrow_by_two_closures(&self,
         self.cancel_if_wrong_origin(err, o)
     }
 
-    fn cannot_uniquely_borrow_by_one_closure(&self,
+    fn cannot_uniquely_borrow_by_one_closure(self,
                                              new_loan_span: Span,
                                              desc_new: &str,
                                              opt_via: &str,
@@ -182,7 +182,7 @@ fn cannot_uniquely_borrow_by_one_closure(&self,
                                              old_opt_via: &str,
                                              previous_end_span: Option<Span>,
                                              o: Origin)
-                                             -> DiagnosticBuilder
+                                             -> DiagnosticBuilder<'cx>
     {
         let mut err = struct_span_err!(self, new_loan_span, E0500,
                          "closure requires unique access to `{}` but {} is already borrowed{}{OGN}",
@@ -197,7 +197,7 @@ fn cannot_uniquely_borrow_by_one_closure(&self,
         self.cancel_if_wrong_origin(err, o)
     }
 
-    fn cannot_reborrow_already_uniquely_borrowed(&self,
+    fn cannot_reborrow_already_uniquely_borrowed(self,
                                                  new_loan_span: Span,
                                                  desc_new: &str,
                                                  opt_via: &str,
@@ -206,7 +206,7 @@ fn cannot_reborrow_already_uniquely_borrowed(&self,
                                                  old_opt_via: &str,
                                                  previous_end_span: Option<Span>,
                                                  o: Origin)
-                                                 -> DiagnosticBuilder
+                                                 -> DiagnosticBuilder<'cx>
     {
         let mut err = struct_span_err!(self, new_loan_span, E0501,
                          "cannot borrow `{}`{} as {} because previous closure \
@@ -222,7 +222,7 @@ fn cannot_reborrow_already_uniquely_borrowed(&self,
         self.cancel_if_wrong_origin(err, o)
     }
 
-    fn cannot_reborrow_already_borrowed(&self,
+    fn cannot_reborrow_already_borrowed(self,
                                         span: Span,
                                         desc_new: &str,
                                         msg_new: &str,
@@ -233,7 +233,7 @@ fn cannot_reborrow_already_borrowed(&self,
                                         msg_old: &str,
                                         old_load_end_span: Option<Span>,
                                         o: Origin)
-                                        -> DiagnosticBuilder
+                                        -> DiagnosticBuilder<'cx>
     {
         let mut err = struct_span_err!(self, span, E0502,
                          "cannot borrow `{}`{} as {} because {} is also borrowed as {}{}{OGN}",
@@ -246,8 +246,8 @@ fn cannot_reborrow_already_borrowed(&self,
         self.cancel_if_wrong_origin(err, o)
     }
 
-    fn cannot_assign_to_borrowed(&self, span: Span, borrow_span: Span, desc: &str, o: Origin)
-                                 -> DiagnosticBuilder
+    fn cannot_assign_to_borrowed(self, span: Span, borrow_span: Span, desc: &str, o: Origin)
+                                 -> DiagnosticBuilder<'cx>
     {
         let mut err = struct_span_err!(self, span, E0506,
                          "cannot assign to `{}` because it is borrowed{OGN}",
@@ -259,8 +259,8 @@ fn cannot_assign_to_borrowed(&self, span: Span, borrow_span: Span, desc: &str, o
         self.cancel_if_wrong_origin(err, o)
     }
 
-    fn cannot_move_into_closure(&self, span: Span, desc: &str, o: Origin)
-                                -> DiagnosticBuilder
+    fn cannot_move_into_closure(self, span: Span, desc: &str, o: Origin)
+                                -> DiagnosticBuilder<'cx>
     {
         let err = struct_span_err!(self, span, E0504,
                                    "cannot move `{}` into closure because it is borrowed{OGN}",
@@ -269,8 +269,8 @@ fn cannot_move_into_closure(&self, span: Span, desc: &str, o: Origin)
         self.cancel_if_wrong_origin(err, o)
     }
 
-    fn cannot_reassign_immutable(&self, span: Span, desc: &str, is_arg: bool, o: Origin)
-                                 -> DiagnosticBuilder
+    fn cannot_reassign_immutable(self, span: Span, desc: &str, is_arg: bool, o: Origin)
+                                 -> DiagnosticBuilder<'cx>
     {
         let msg = if is_arg {
             "to immutable argument"
@@ -284,7 +284,7 @@ fn cannot_reassign_immutable(&self, span: Span, desc: &str, is_arg: bool, o: Ori
         self.cancel_if_wrong_origin(err, o)
     }
 
-    fn cannot_assign(&self, span: Span, desc: &str, o: Origin) -> DiagnosticBuilder
+    fn cannot_assign(self, span: Span, desc: &str, o: Origin) -> DiagnosticBuilder<'cx>
     {
         let err = struct_span_err!(self, span, E0594,
                                   "cannot assign to {}{OGN}",
@@ -292,14 +292,14 @@ fn cannot_assign(&self, span: Span, desc: &str, o: Origin) -> DiagnosticBuilder
         self.cancel_if_wrong_origin(err, o)
     }
 
-    fn cannot_assign_static(&self, span: Span, desc: &str, o: Origin)
-                            -> DiagnosticBuilder
+    fn cannot_assign_static(self, span: Span, desc: &str, o: Origin)
+                            -> DiagnosticBuilder<'cx>
     {
         self.cannot_assign(span, &format!("immutable static item `{}`", desc), o)
     }
 
-    fn cannot_move_out_of(&self, move_from_span: Span, move_from_desc: &str, o: Origin)
-                          -> DiagnosticBuilder
+    fn cannot_move_out_of(self, move_from_span: Span, move_from_desc: &str, o: Origin)
+                          -> DiagnosticBuilder<'cx>
     {
         let mut err = struct_span_err!(self, move_from_span, E0507,
                                        "cannot move out of {}{OGN}",
@@ -311,12 +311,12 @@ fn cannot_move_out_of(&self, move_from_span: Span, move_from_desc: &str, o: Orig
         self.cancel_if_wrong_origin(err, o)
     }
 
-    fn cannot_move_out_of_interior_noncopy(&self,
+    fn cannot_move_out_of_interior_noncopy(self,
                                            move_from_span: Span,
                                            ty: ty::Ty,
                                            is_index: bool,
                                            o: Origin)
-                                           -> DiagnosticBuilder
+                                           -> DiagnosticBuilder<'cx>
     {
         let type_name = match (&ty.sty, is_index) {
             (&ty::TyArray(_, _), true) => "array",
@@ -332,11 +332,11 @@ fn cannot_move_out_of_interior_noncopy(&self,
         self.cancel_if_wrong_origin(err, o)
     }
 
-    fn cannot_move_out_of_interior_of_drop(&self,
+    fn cannot_move_out_of_interior_of_drop(self,
                                            move_from_span: Span,
                                            container_ty: ty::Ty,
                                            o: Origin)
-                                           -> DiagnosticBuilder
+                                           -> DiagnosticBuilder<'cx>
     {
         let mut err = struct_span_err!(self, move_from_span, E0509,
                                        "cannot move out of type `{}`, \
@@ -347,13 +347,13 @@ fn cannot_move_out_of_interior_of_drop(&self,
         self.cancel_if_wrong_origin(err, o)
     }
 
-    fn cannot_act_on_moved_value(&self,
+    fn cannot_act_on_moved_value(self,
                                  use_span: Span,
                                  verb: &str,
                                  optional_adverb_for_moved: &str,
                                  moved_path: &str,
                                  o: Origin)
-                                 -> DiagnosticBuilder
+                                 -> DiagnosticBuilder<'cx>
     {
         let err = struct_span_err!(self, use_span, E0382,
                                    "{} of {}moved value: `{}`{OGN}",
@@ -362,11 +362,11 @@ fn cannot_act_on_moved_value(&self,
         self.cancel_if_wrong_origin(err, o)
     }
 
-    fn cannot_partially_reinit_an_uninit_struct(&self,
+    fn cannot_partially_reinit_an_uninit_struct(self,
                                                 span: Span,
                                                 uninit_path: &str,
                                                 o: Origin)
-                                                -> DiagnosticBuilder
+                                                -> DiagnosticBuilder<'cx>
     {
         let err = struct_span_err!(self,
                                    span,
@@ -377,11 +377,11 @@ fn cannot_partially_reinit_an_uninit_struct(&self,
         self.cancel_if_wrong_origin(err, o)
     }
 
-    fn closure_cannot_assign_to_borrowed(&self,
+    fn closure_cannot_assign_to_borrowed(self,
                                          span: Span,
                                          descr: &str,
                                          o: Origin)
-                                         -> DiagnosticBuilder
+                                         -> DiagnosticBuilder<'cx>
     {
         let err = struct_span_err!(self, span, E0595, "closure cannot assign to {}{OGN}",
                                    descr, OGN=o);
@@ -389,11 +389,11 @@ fn closure_cannot_assign_to_borrowed(&self,
         self.cancel_if_wrong_origin(err, o)
     }
 
-    fn cannot_borrow_path_as_mutable(&self,
+    fn cannot_borrow_path_as_mutable(self,
                                      span: Span,
                                      path: &str,
                                      o: Origin)
-                                     -> DiagnosticBuilder
+                                     -> DiagnosticBuilder<'cx>
     {
         let err = struct_span_err!(self, span, E0596, "cannot borrow {} as mutable{OGN}",
                                    path, OGN=o);
@@ -401,11 +401,11 @@ fn cannot_borrow_path_as_mutable(&self,
         self.cancel_if_wrong_origin(err, o)
     }
 
-    fn cannot_borrow_across_generator_yield(&self,
+    fn cannot_borrow_across_generator_yield(self,
                                             span: Span,
                                             yield_span: Span,
                                             o: Origin)
-                                            -> DiagnosticBuilder
+                                            -> DiagnosticBuilder<'cx>
     {
         let mut err = struct_span_err!(self,
                                        span,
@@ -417,11 +417,11 @@ fn cannot_borrow_across_generator_yield(&self,
         self.cancel_if_wrong_origin(err, o)
     }
 
-    fn path_does_not_live_long_enough(&self,
+    fn path_does_not_live_long_enough(self,
                                       span: Span,
                                       path: &str,
                                       o: Origin)
-                                      -> DiagnosticBuilder
+                                      -> DiagnosticBuilder<'cx>
     {
         let err = struct_span_err!(self, span, E0597, "{} does not live long enough{OGN}",
                                    path, OGN=o);
@@ -429,11 +429,11 @@ fn path_does_not_live_long_enough(&self,
         self.cancel_if_wrong_origin(err, o)
     }
 
-    fn lifetime_too_short_for_reborrow(&self,
+    fn lifetime_too_short_for_reborrow(self,
                                        span: Span,
                                        path: &str,
                                        o: Origin)
-                                       -> DiagnosticBuilder
+                                       -> DiagnosticBuilder<'cx>
     {
         let err = struct_span_err!(self, span, E0598,
                                    "lifetime of {} is too short to guarantee \
@@ -443,12 +443,12 @@ fn lifetime_too_short_for_reborrow(&self,
         self.cancel_if_wrong_origin(err, o)
     }
 
-    fn cannot_act_on_capture_in_sharable_fn(&self,
+    fn cannot_act_on_capture_in_sharable_fn(self,
                                             span: Span,
                                             bad_thing: &str,
                                             help: (Span, &str),
                                             o: Origin)
-                                            -> DiagnosticBuilder
+                                            -> DiagnosticBuilder<'cx>
     {
         let (help_span, help_msg) = help;
         let mut err = struct_span_err!(self, span, E0387,
@@ -459,11 +459,11 @@ fn cannot_act_on_capture_in_sharable_fn(&self,
         self.cancel_if_wrong_origin(err, o)
     }
 
-    fn cannot_assign_into_immutable_reference(&self,
+    fn cannot_assign_into_immutable_reference(self,
                                               span: Span,
                                               bad_thing: &str,
                                               o: Origin)
-                                              -> DiagnosticBuilder
+                                              -> DiagnosticBuilder<'cx>
     {
         let mut err = struct_span_err!(self, span, E0389, "{} in a `&` reference{OGN}",
                                        bad_thing, OGN=o);
@@ -472,12 +472,12 @@ fn cannot_assign_into_immutable_reference(&self,
         self.cancel_if_wrong_origin(err, o)
     }
 
-    fn cannot_capture_in_long_lived_closure(&self,
+    fn cannot_capture_in_long_lived_closure(self,
                                             closure_span: Span,
                                             borrowed_path: &str,
                                             capture_span: Span,
                                             o: Origin)
-                                            -> DiagnosticBuilder
+                                            -> DiagnosticBuilder<'cx>
     {
         let mut err = struct_span_err!(self, closure_span, E0373,
                                        "closure may outlive the current function, \
@@ -491,28 +491,28 @@ fn cannot_capture_in_long_lived_closure(&self,
     }
 }
 
-impl<'b, 'gcx, 'tcx> BorrowckErrors for TyCtxt<'b, 'gcx, 'tcx> {
-    fn struct_span_err_with_code<'a, S: Into<MultiSpan>>(&'a self,
-                                                         sp: S,
-                                                         msg: &str,
-                                                         code: DiagnosticId)
-                                                         -> DiagnosticBuilder<'a>
+impl<'cx, 'gcx, 'tcx> BorrowckErrors<'cx> for TyCtxt<'cx, 'gcx, 'tcx> {
+    fn struct_span_err_with_code<S: Into<MultiSpan>>(self,
+                                                     sp: S,
+                                                     msg: &str,
+                                                     code: DiagnosticId)
+                                                     -> DiagnosticBuilder<'cx>
     {
         self.sess.struct_span_err_with_code(sp, msg, code)
     }
 
-    fn struct_span_err<'a, S: Into<MultiSpan>>(&'a self,
-                                               sp: S,
-                                               msg: &str)
-                                               -> DiagnosticBuilder<'a>
+    fn struct_span_err<S: Into<MultiSpan>>(self,
+                                           sp: S,
+                                           msg: &str)
+                                           -> DiagnosticBuilder<'cx>
     {
         self.sess.struct_span_err(sp, msg)
     }
 
-    fn cancel_if_wrong_origin<'a>(&'a self,
-                                mut diag: DiagnosticBuilder<'a>,
-                                o: Origin)
-                                -> DiagnosticBuilder<'a>
+    fn cancel_if_wrong_origin(self,
+                              mut diag: DiagnosticBuilder<'cx>,
+                              o: Origin)
+                              -> DiagnosticBuilder<'cx>
     {
         if !o.should_emit_errors(self.borrowck_mode()) {
             self.sess.diagnostic().cancel(&mut diag);
index e95126c8a1a0f555daf24fe575bf0f6743b14db7..19f33ef5d45a83f6a6b4b964c613f6574bfa924b 100644 (file)
@@ -177,7 +177,7 @@ pub fn elaborate_drop<'a>(&mut self, bb: BasicBlock) {
                 });
             }
             DropStyle::Conditional => {
-                let unwind = self.unwind; // FIXME(#6393)
+                let unwind = self.unwind; // FIXME(#43234)
                 let succ = self.succ;
                 let drop_bb = self.complete_drop(Some(DropFlagMode::Deep), succ, unwind);
                 self.elaborator.patch().patch_terminator(bb, TerminatorKind::Goto {
@@ -268,7 +268,7 @@ fn drop_ladder_bottom(&mut self) -> (BasicBlock, Unwind) {
         // Clear the "master" drop flag at the end. This is needed
         // because the "master" drop protects the ADT's discriminant,
         // which is invalidated after the ADT is dropped.
-        let (succ, unwind) = (self.succ, self.unwind); // FIXME(#6393)
+        let (succ, unwind) = (self.succ, self.unwind); // FIXME(#43234)
         (
             self.drop_flag_reset_block(DropFlagMode::Shallow, succ, unwind),
             unwind.map(|unwind| {
@@ -344,7 +344,7 @@ fn open_drop_for_box<'a>(&mut self, ty: Ty<'tcx>) -> BasicBlock
         let interior = self.place.clone().deref();
         let interior_path = self.elaborator.deref_subpath(self.path);
 
-        let succ = self.succ; // FIXME(#6393)
+        let succ = self.succ; // FIXME(#43234)
         let unwind = self.unwind;
         let succ = self.box_free_block(ty, succ, unwind);
         let unwind_succ = self.unwind.map(|unwind| {
@@ -717,7 +717,7 @@ fn drop_loop_pair(&mut self, ety: Ty<'tcx>, ptr_based: bool) -> BasicBlock {
                            ptr_based)
         });
 
-        let succ = self.succ; // FIXME(#6393)
+        let succ = self.succ; // FIXME(#43234)
         let loop_block = self.drop_loop(
             succ,
             cur,
@@ -798,7 +798,7 @@ fn open_drop<'a>(&mut self) -> BasicBlock {
                 self.open_drop_for_adt(def, substs)
             }
             ty::TyDynamic(..) => {
-                let unwind = self.unwind; // FIXME(#6393)
+                let unwind = self.unwind; // FIXME(#43234)
                 let succ = self.succ;
                 self.complete_drop(Some(DropFlagMode::Deep), succ, unwind)
             }
@@ -849,7 +849,7 @@ fn drop_flag_reset_block(&mut self,
 
     fn elaborated_drop_block<'a>(&mut self) -> BasicBlock {
         debug!("elaborated_drop_block({:?})", self);
-        let unwind = self.unwind; // FIXME(#6393)
+        let unwind = self.unwind; // FIXME(#43234)
         let succ = self.succ;
         let blk = self.drop_block(succ, unwind);
         self.elaborate_drop(blk);
@@ -882,7 +882,7 @@ fn unelaborated_free_block<'a>(
             args: vec![Operand::Move(self.place.clone())],
             destination: Some((unit_temp, target)),
             cleanup: None
-        }; // FIXME(#6393)
+        }; // FIXME(#43234)
         let free_block = self.new_block(unwind, call);
 
         let block_start = Location { block: free_block, statement_index: 0 };
index 4215bf306a4fd9306ea3f0e89bbcc45054d1e6ad..e5157a071bf0aa65df72e5ee9cda63508db9d272 100644 (file)
@@ -67,7 +67,7 @@ fn invalid_visibility(&self, vis: &Visibility, note: Option<&str>) {
                                            E0449,
                                            "unnecessary visibility qualifier");
             if vis.node == VisibilityKind::Public {
-                err.span_label(vis.span, "`pub` not needed here");
+                err.span_label(vis.span, "`pub` not permitted here because it's implied");
             }
             if let Some(note) = note {
                 err.note(note);
index 4cbebdc3c1c39f9458fb732e4e0da80bf471d2f7..644a2ffe3c379bfc9c7864bfe8e7c51502c0132e 100644 (file)
@@ -1025,28 +1025,9 @@ fn import_path_to_string(names: &[SpannedIdent],
         if names.is_empty() {
             import_directive_subclass_to_string(subclass)
         } else {
-            // FIXME: Remove this entire logic after #48116 is fixed.
-            //
-            // Note that this code looks a little wonky, it's currently here to
-            // hopefully help debug #48116, but otherwise isn't intended to
-            // cause any problems.
-            let x = format!(
-                "{}::{}",
-                names_to_string(names),
-                import_directive_subclass_to_string(subclass),
-            );
-            if names.is_empty() || x.starts_with("::") {
-                span_bug!(
-                    span,
-                    "invalid name `{}` at {:?}; global = {}, names = {:?}, subclass = {:?}",
-                    x,
-                    span,
-                    global,
-                    names,
-                    subclass
-                );
-            }
-            return x
+            format!("{}::{}",
+                    names_to_string(names),
+                    import_directive_subclass_to_string(subclass))
         }
     }
 }
index b69d632a6a0dfba36adbed00195a8b32583e04f2..d1868ba2abb1722760356eb4812c20173ebe063b 100644 (file)
@@ -1,7 +1,7 @@
-NB: This crate is part of the Rust compiler. For an overview of the
-compiler as a whole, see
-[the README.md file found in `librustc`](../librustc/README.md).
-
 The `trans` crate contains the code to convert from MIR into LLVM IR,
 and then from LLVM IR into machine code. In general it contains code
 that runs towards the end of the compilation process.
+
+For more information about how trans works, see the [rustc guide].
+
+[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/trans.html
index 3645e7288420873bdd48ca27db0f4ed69a46cf09..337f85a381399232aa8a9ab6734598862d7520c9 100644 (file)
@@ -30,7 +30,7 @@
 #![feature(libc)]
 #![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
-#![feature(slice_patterns)]
+#![cfg_attr(stage0, feature(slice_patterns))]
 #![feature(conservative_impl_trait)]
 #![feature(optin_builtin_traits)]
 #![feature(inclusive_range_fields)]
index 6a3fd21f3a771580390119ac49ff7e9ff7a02a9a..0af5f46793450afd5b5436a3497c4048c60042cb 100644 (file)
@@ -24,7 +24,6 @@
 #![feature(i128_type)]
 #![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
-#![feature(slice_patterns)]
 #![feature(conservative_impl_trait)]
 
 extern crate ar;
index 267c8d2bd03c861bcfac1d495c359c6fdfe1b8fd..47bbd67fb5c70840cc5fdf85e8cfca77338df991 100644 (file)
@@ -15,7 +15,6 @@
 //! paths etc in all kinds of annoying scenarios.
 
 use rustc::hir;
-use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
 use rustc::ty::TyCtxt;
 use syntax::ast;
 
@@ -34,8 +33,7 @@ pub fn report_symbol_names<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
 
     tcx.dep_graph.with_ignore(|| {
         let mut visitor = SymbolNamesTest { tcx: tcx };
-        // FIXME(#37712) could use ItemLikeVisitor if trait items were item-like
-        tcx.hir.krate().visit_all_item_likes(&mut visitor.as_deep_visitor());
+        tcx.hir.krate().visit_all_item_likes(&mut visitor);
     })
 }
 
@@ -66,23 +64,16 @@ fn process_attrs(&mut self,
     }
 }
 
-impl<'a, 'tcx> Visitor<'tcx> for SymbolNamesTest<'a, 'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
-        NestedVisitorMap::None
-    }
-
+impl<'a, 'tcx> hir::itemlikevisit::ItemLikeVisitor<'tcx> for SymbolNamesTest<'a, 'tcx> {
     fn visit_item(&mut self, item: &'tcx hir::Item) {
         self.process_attrs(item.id);
-        intravisit::walk_item(self, item);
     }
 
-    fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem) {
-        self.process_attrs(ti.id);
-        intravisit::walk_trait_item(self, ti)
+    fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
+        self.process_attrs(trait_item.id);
     }
 
-    fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem) {
-        self.process_attrs(ii.id);
-        intravisit::walk_impl_item(self, ii)
+    fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
+        self.process_attrs(impl_item.id);
     }
 }
index 634a7ee569917055345d8181840f9dc0585832e6..701b896b9057bc8b07c3853df3e053845abb6745 100644 (file)
@@ -18,8 +18,9 @@
 use syntax::util::parser::PREC_POSTFIX;
 use syntax_pos::{self, Span};
 use rustc::hir;
-use rustc::hir::print;
 use rustc::hir::def::Def;
+use rustc::hir::map::NodeItem;
+use rustc::hir::{Item, ItemConst, print};
 use rustc::ty::{self, Ty, AssociatedItem};
 use errors::{DiagnosticBuilder, CodeMapper};
 
@@ -318,6 +319,18 @@ fn check_for_cast(&self,
                       checked_ty: Ty<'tcx>,
                       expected_ty: Ty<'tcx>)
                       -> bool {
+        let parent_id = self.tcx.hir.get_parent_node(expr.id);
+        match self.tcx.hir.find(parent_id) {
+            Some(parent) => {
+                // Shouldn't suggest `.into()` on `const`s.
+                if let NodeItem(Item { node: ItemConst(_, _), .. }) = parent {
+                    // FIXME(estebank): modify once we decide to suggest `as` casts
+                    return false;
+                }
+            }
+            None => {}
+        };
+
         let will_truncate = "will truncate the source value";
         let depending_on_isize = "will truncate or zero-extend depending on the bit width of \
                                   `isize`";
index 4a685cfddb7a42f5e760d8a4427d26b622064335..69879bbe85d6e4e50d22af815d071c08be95a4f2 100644 (file)
@@ -718,6 +718,18 @@ fn typeck_item_bodies<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum
     })?)
 }
 
+fn check_item_well_formed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
+    wfcheck::check_item_well_formed(tcx, def_id);
+}
+
+fn check_trait_item_well_formed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
+    wfcheck::check_trait_item(tcx, def_id);
+}
+
+fn check_impl_item_well_formed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
+    wfcheck::check_impl_item(tcx, def_id);
+}
+
 pub fn provide(providers: &mut Providers) {
     *providers = Providers {
         typeck_item_bodies,
@@ -725,6 +737,9 @@ pub fn provide(providers: &mut Providers) {
         has_typeck_tables,
         adt_destructor,
         used_trait_imports,
+        check_item_well_formed,
+        check_trait_item_well_formed,
+        check_impl_item_well_formed,
         ..*providers
     };
 }
@@ -2869,7 +2884,7 @@ fn expected_inputs_for_expected_output(&self,
                 let origin = self.misc(call_span);
                 let ures = self.at(&origin, self.param_env).sup(ret_ty, formal_ret);
 
-                // FIXME(#15760) can't use try! here, FromError doesn't default
+                // FIXME(#27336) can't use ? here, Try::from_error doesn't default
                 // to identity so the resulting type is not constrained.
                 match ures {
                     Ok(ok) => {
@@ -2877,19 +2892,13 @@ fn expected_inputs_for_expected_output(&self,
                         // we can.  We don't care if some things turn
                         // out unconstrained or ambiguous, as we're
                         // just trying to get hints here.
-                        let result = self.save_and_restore_in_snapshot_flag(|_| {
+                        self.save_and_restore_in_snapshot_flag(|_| {
                             let mut fulfill = FulfillmentContext::new();
-                            let ok = ok; // FIXME(#30046)
                             for obligation in ok.obligations {
                                 fulfill.register_predicate_obligation(self, obligation);
                             }
                             fulfill.select_where_possible(self)
-                        });
-
-                        match result {
-                            Ok(()) => { }
-                            Err(_) => return Err(()),
-                        }
+                        }).map_err(|_| ())?;
                     }
                     Err(_) => return Err(()),
                 }
index ab148afafbe0909c300f0cbbcab5a773b3bfeb00..4fc3344dab2a919dd796d84de0e27e70fe9cdf8c 100644 (file)
@@ -217,7 +217,7 @@ fn analyze_closure(
             .upvar_tys(closure_def_id, self.tcx)
             .zip(final_upvar_tys)
         {
-            self.demand_eqtype(span, final_upvar_ty, upvar_ty);
+            self.demand_suptype(span, upvar_ty, final_upvar_ty);
         }
 
         // If we are also inferred the closure kind here,
index b94af0a1e0081d2b8ecbc8b7d1eb569577836165..406ff9463a03c314f4da185ca068dd0ae2c24a37 100644 (file)
 use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
 use rustc::hir;
 
-pub struct CheckTypeWellFormedVisitor<'a, 'tcx:'a> {
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    code: ObligationCauseCode<'tcx>,
-}
-
 /// Helper type of a temporary returned by .for_item(...).
 /// Necessary because we can't write the following bound:
 /// F: for<'b, 'tcx> where 'gcx: 'tcx FnOnce(FnCtxt<'b, 'gcx, 'tcx>).
 struct CheckWfFcxBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     inherited: super::InheritedBuilder<'a, 'gcx, 'tcx>,
-    code: ObligationCauseCode<'gcx>,
     id: ast::NodeId,
     span: Span,
     param_env: ty::ParamEnv<'tcx>,
@@ -45,585 +39,597 @@ struct CheckWfFcxBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
 impl<'a, 'gcx, 'tcx> CheckWfFcxBuilder<'a, 'gcx, 'tcx> {
     fn with_fcx<F>(&'tcx mut self, f: F) where
         F: for<'b> FnOnce(&FnCtxt<'b, 'gcx, 'tcx>,
-                          &mut CheckTypeWellFormedVisitor<'b, 'gcx>) -> Vec<Ty<'tcx>>
+                         TyCtxt<'b, 'gcx, 'gcx>) -> Vec<Ty<'tcx>>
     {
-        let code = self.code.clone();
         let id = self.id;
         let span = self.span;
         let param_env = self.param_env;
         self.inherited.enter(|inh| {
             let fcx = FnCtxt::new(&inh, param_env, id);
-            let wf_tys = f(&fcx, &mut CheckTypeWellFormedVisitor {
-                tcx: fcx.tcx.global_tcx(),
-                code,
-            });
+            let wf_tys = f(&fcx, fcx.tcx.global_tcx());
             fcx.select_all_obligations_or_error();
             fcx.regionck_item(id, span, &wf_tys);
         });
     }
 }
 
-impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
-    pub fn new(tcx: TyCtxt<'a, 'gcx, 'gcx>)
-               -> CheckTypeWellFormedVisitor<'a, 'gcx> {
-        CheckTypeWellFormedVisitor {
-            tcx,
-            code: ObligationCauseCode::MiscObligation
-        }
-    }
-
-    /// Checks that the field types (in a struct def'n) or argument types (in an enum def'n) are
-    /// well-formed, meaning that they do not require any constraints not declared in the struct
-    /// definition itself. For example, this definition would be illegal:
-    ///
-    ///     struct Ref<'a, T> { x: &'a T }
-    ///
-    /// because the type did not declare that `T:'a`.
-    ///
-    /// We do this check as a pre-pass before checking fn bodies because if these constraints are
-    /// not included it frequently leads to confusing errors in fn bodies. So it's better to check
-    /// the types first.
-    fn check_item_well_formed(&mut self, item: &hir::Item) {
-        let tcx = self.tcx;
-        debug!("check_item_well_formed(it.id={}, it.name={})",
-               item.id,
-               tcx.item_path_str(tcx.hir.local_def_id(item.id)));
-
-        match item.node {
-            // Right now we check that every default trait implementation
-            // has an implementation of itself. Basically, a case like:
-            //
-            // `impl Trait for T {}`
-            //
-            // has a requirement of `T: Trait` which was required for default
-            // method implementations. Although this could be improved now that
-            // there's a better infrastructure in place for this, it's being left
-            // for a follow-up work.
-            //
-            // Since there's such a requirement, we need to check *just* positive
-            // implementations, otherwise things like:
-            //
-            // impl !Send for T {}
-            //
-            // won't be allowed unless there's an *explicit* implementation of `Send`
-            // for `T`
-            hir::ItemImpl(_, polarity, defaultness, _, ref trait_ref, ref self_ty, _) => {
-                let is_auto = tcx.impl_trait_ref(tcx.hir.local_def_id(item.id))
-                                 .map_or(false, |trait_ref| tcx.trait_is_auto(trait_ref.def_id));
-                if let (hir::Defaultness::Default { .. }, true) = (defaultness, is_auto) {
-                    tcx.sess.span_err(item.span, "impls of auto traits cannot be default");
-                }
-                if polarity == hir::ImplPolarity::Positive {
-                    self.check_impl(item, self_ty, trait_ref);
-                } else {
-                    // FIXME(#27579) what amount of WF checking do we need for neg impls?
-                    if trait_ref.is_some() && !is_auto {
-                        span_err!(tcx.sess, item.span, E0192,
-                                  "negative impls are only allowed for \
-                                   auto traits (e.g., `Send` and `Sync`)")
-                    }
-                }
-            }
-            hir::ItemFn(..) => {
-                self.check_item_fn(item);
-            }
-            hir::ItemStatic(..) => {
-                self.check_item_type(item);
+/// Checks that the field types (in a struct def'n) or argument types (in an enum def'n) are
+/// well-formed, meaning that they do not require any constraints not declared in the struct
+/// definition itself. For example, this definition would be illegal:
+///
+///     struct Ref<'a, T> { x: &'a T }
+///
+/// because the type did not declare that `T:'a`.
+///
+/// We do this check as a pre-pass before checking fn bodies because if these constraints are
+/// not included it frequently leads to confusing errors in fn bodies. So it's better to check
+/// the types first.
+pub fn check_item_well_formed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
+    let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
+    let item = tcx.hir.expect_item(node_id);
+
+    debug!("check_item_well_formed(it.id={}, it.name={})",
+            item.id,
+            tcx.item_path_str(def_id));
+
+    match item.node {
+        // Right now we check that every default trait implementation
+        // has an implementation of itself. Basically, a case like:
+        //
+        // `impl Trait for T {}`
+        //
+        // has a requirement of `T: Trait` which was required for default
+        // method implementations. Although this could be improved now that
+        // there's a better infrastructure in place for this, it's being left
+        // for a follow-up work.
+        //
+        // Since there's such a requirement, we need to check *just* positive
+        // implementations, otherwise things like:
+        //
+        // impl !Send for T {}
+        //
+        // won't be allowed unless there's an *explicit* implementation of `Send`
+        // for `T`
+        hir::ItemImpl(_, polarity, defaultness, _, ref trait_ref, ref self_ty, _) => {
+            let is_auto = tcx.impl_trait_ref(tcx.hir.local_def_id(item.id))
+                                .map_or(false, |trait_ref| tcx.trait_is_auto(trait_ref.def_id));
+            if let (hir::Defaultness::Default { .. }, true) = (defaultness, is_auto) {
+                tcx.sess.span_err(item.span, "impls of auto traits cannot be default");
             }
-            hir::ItemConst(..) => {
-                self.check_item_type(item);
+            if polarity == hir::ImplPolarity::Positive {
+                check_impl(tcx, item, self_ty, trait_ref);
+            } else {
+                // FIXME(#27579) what amount of WF checking do we need for neg impls?
+                if trait_ref.is_some() && !is_auto {
+                    span_err!(tcx.sess, item.span, E0192,
+                                "negative impls are only allowed for \
+                                auto traits (e.g., `Send` and `Sync`)")
+                }
             }
-            hir::ItemStruct(ref struct_def, ref ast_generics) => {
-                self.check_type_defn(item, false, |fcx| {
-                    vec![fcx.non_enum_variant(struct_def)]
-                });
+        }
+        hir::ItemFn(..) => {
+            check_item_fn(tcx, item);
+        }
+        hir::ItemStatic(..) => {
+            check_item_type(tcx, item);
+        }
+        hir::ItemConst(..) => {
+            check_item_type(tcx, item);
+        }
+        hir::ItemStruct(ref struct_def, ref ast_generics) => {
+            check_type_defn(tcx, item, false, |fcx| {
+                vec![fcx.non_enum_variant(struct_def)]
+            });
 
-                self.check_variances_for_type_defn(item, ast_generics);
-            }
-            hir::ItemUnion(ref struct_def, ref ast_generics) => {
-                self.check_type_defn(item, true, |fcx| {
-                    vec![fcx.non_enum_variant(struct_def)]
-                });
+            check_variances_for_type_defn(tcx, item, ast_generics);
+        }
+        hir::ItemUnion(ref struct_def, ref ast_generics) => {
+            check_type_defn(tcx, item, true, |fcx| {
+                vec![fcx.non_enum_variant(struct_def)]
+            });
 
-                self.check_variances_for_type_defn(item, ast_generics);
-            }
-            hir::ItemEnum(ref enum_def, ref ast_generics) => {
-                self.check_type_defn(item, true, |fcx| {
-                    fcx.enum_variants(enum_def)
-                });
+            check_variances_for_type_defn(tcx, item, ast_generics);
+        }
+        hir::ItemEnum(ref enum_def, ref ast_generics) => {
+            check_type_defn(tcx, item, true, |fcx| {
+                fcx.enum_variants(enum_def)
+            });
 
-                self.check_variances_for_type_defn(item, ast_generics);
-            }
-            hir::ItemTrait(..) => {
-                self.check_trait(item);
-            }
-            _ => {}
+            check_variances_for_type_defn(tcx, item, ast_generics);
         }
+        hir::ItemTrait(..) => {
+            check_trait(tcx, item);
+        }
+        _ => {}
     }
+}
 
-    fn check_associated_item(&mut self,
-                             item_id: ast::NodeId,
-                             span: Span,
-                             sig_if_method: Option<&hir::MethodSig>) {
-        let code = self.code.clone();
-        self.for_id(item_id, span).with_fcx(|fcx, this| {
-            let item = fcx.tcx.associated_item(fcx.tcx.hir.local_def_id(item_id));
-
-            let (mut implied_bounds, self_ty) = match item.container {
-                ty::TraitContainer(_) => (vec![], fcx.tcx.mk_self_type()),
-                ty::ImplContainer(def_id) => (fcx.impl_implied_bounds(def_id, span),
-                                              fcx.tcx.type_of(def_id))
-            };
+pub fn check_trait_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
+    let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
+    let trait_item = tcx.hir.expect_trait_item(node_id);
+
+    let method_sig = match trait_item.node {
+        hir::TraitItemKind::Method(ref sig, _) => Some(sig),
+        _ => None
+    };
+    check_associated_item(tcx, trait_item.id, trait_item.span, method_sig);
+}
+
+pub fn check_impl_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
+    let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
+    let impl_item = tcx.hir.expect_impl_item(node_id);
+
+    let method_sig = match impl_item.node {
+        hir::ImplItemKind::Method(ref sig, _) => Some(sig),
+        _ => None
+    };
+    check_associated_item(tcx, impl_item.id, impl_item.span, method_sig);
+}
+
+fn check_associated_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                            item_id: ast::NodeId,
+                            span: Span,
+                            sig_if_method: Option<&hir::MethodSig>) {
+    let code = ObligationCauseCode::MiscObligation;
+    for_id(tcx, item_id, span).with_fcx(|fcx, tcx| {
+        let item = fcx.tcx.associated_item(fcx.tcx.hir.local_def_id(item_id));
+
+        let (mut implied_bounds, self_ty) = match item.container {
+            ty::TraitContainer(_) => (vec![], fcx.tcx.mk_self_type()),
+            ty::ImplContainer(def_id) => (fcx.impl_implied_bounds(def_id, span),
+                                            fcx.tcx.type_of(def_id))
+        };
 
-            match item.kind {
-                ty::AssociatedKind::Const => {
+        match item.kind {
+            ty::AssociatedKind::Const => {
+                let ty = fcx.tcx.type_of(item.def_id);
+                let ty = fcx.normalize_associated_types_in(span, &ty);
+                fcx.register_wf_obligation(ty, span, code.clone());
+            }
+            ty::AssociatedKind::Method => {
+                reject_shadowing_type_parameters(fcx.tcx, item.def_id);
+                let sig = fcx.tcx.fn_sig(item.def_id);
+                let sig = fcx.normalize_associated_types_in(span, &sig);
+                check_fn_or_method(tcx, fcx, span, sig,
+                                        item.def_id, &mut implied_bounds);
+                let sig_if_method = sig_if_method.expect("bad signature for method");
+                check_method_receiver(fcx, sig_if_method, &item, self_ty);
+            }
+            ty::AssociatedKind::Type => {
+                if item.defaultness.has_value() {
                     let ty = fcx.tcx.type_of(item.def_id);
                     let ty = fcx.normalize_associated_types_in(span, &ty);
                     fcx.register_wf_obligation(ty, span, code.clone());
                 }
-                ty::AssociatedKind::Method => {
-                    reject_shadowing_type_parameters(fcx.tcx, item.def_id);
-                    let sig = fcx.tcx.fn_sig(item.def_id);
-                    let sig = fcx.normalize_associated_types_in(span, &sig);
-                    this.check_fn_or_method(fcx, span, sig,
-                                            item.def_id, &mut implied_bounds);
-                    let sig_if_method = sig_if_method.expect("bad signature for method");
-                    this.check_method_receiver(fcx, sig_if_method, &item, self_ty);
-                }
-                ty::AssociatedKind::Type => {
-                    if item.defaultness.has_value() {
-                        let ty = fcx.tcx.type_of(item.def_id);
-                        let ty = fcx.normalize_associated_types_in(span, &ty);
-                        fcx.register_wf_obligation(ty, span, code.clone());
-                    }
-                }
             }
+        }
 
-            implied_bounds
-        })
-    }
-
-    fn for_item<'tcx>(&self, item: &hir::Item)
-                      -> CheckWfFcxBuilder<'a, 'gcx, 'tcx> {
-        self.for_id(item.id, item.span)
-    }
+        implied_bounds
+    })
+}
 
-    fn for_id<'tcx>(&self, id: ast::NodeId, span: Span)
+fn for_item<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>, item: &hir::Item)
                     -> CheckWfFcxBuilder<'a, 'gcx, 'tcx> {
-        let def_id = self.tcx.hir.local_def_id(id);
-        CheckWfFcxBuilder {
-            inherited: Inherited::build(self.tcx, def_id),
-            code: self.code.clone(),
-            id,
-            span,
-            param_env: self.tcx.param_env(def_id),
-        }
+    for_id(tcx, item.id, item.span)
+}
+
+fn for_id<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>, id: ast::NodeId, span: Span)
+                -> CheckWfFcxBuilder<'a, 'gcx, 'tcx> {
+    let def_id = tcx.hir.local_def_id(id);
+    CheckWfFcxBuilder {
+        inherited: Inherited::build(tcx, def_id),
+        id,
+        span,
+        param_env: tcx.param_env(def_id),
     }
+}
 
-    /// In a type definition, we check that to ensure that the types of the fields are well-formed.
-    fn check_type_defn<F>(&mut self, item: &hir::Item, all_sized: bool, mut lookup_fields: F)
-        where F: for<'fcx, 'tcx> FnMut(&FnCtxt<'fcx, 'gcx, 'tcx>) -> Vec<AdtVariant<'tcx>>
-    {
-        self.for_item(item).with_fcx(|fcx, this| {
-            let variants = lookup_fields(fcx);
-            let def_id = fcx.tcx.hir.local_def_id(item.id);
-            let packed = fcx.tcx.adt_def(def_id).repr.packed();
-
-            for variant in &variants {
-                // For DST, or when drop needs to copy things around, all
-                // intermediate types must be sized.
-                let needs_drop_copy = || {
-                    packed && {
-                        let ty = variant.fields.last().unwrap().ty;
-                        let ty = fcx.tcx.erase_regions(&ty).lift_to_tcx(this.tcx)
-                            .unwrap_or_else(|| {
-                                span_bug!(item.span, "inference variables in {:?}", ty)
-                            });
-                        ty.needs_drop(this.tcx, this.tcx.param_env(def_id))
-                    }
-                };
-                let unsized_len = if
-                    all_sized ||
-                    variant.fields.is_empty() ||
-                    needs_drop_copy()
-                {
-                    0
-                } else {
-                    1
-                };
-                for field in &variant.fields[..variant.fields.len() - unsized_len] {
-                    fcx.register_bound(
-                        field.ty,
-                        fcx.tcx.require_lang_item(lang_items::SizedTraitLangItem),
-                        traits::ObligationCause::new(field.span,
-                                                     fcx.body_id,
-                                                     traits::FieldSized(match item.node.adt_kind() {
-                                                        Some(i) => i,
-                                                        None => bug!(),
-                                                     })));
+/// In a type definition, we check that to ensure that the types of the fields are well-formed.
+fn check_type_defn<'a, 'tcx, F>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                item: &hir::Item, all_sized: bool, mut lookup_fields: F)
+    where F: for<'fcx, 'gcx, 'tcx2> FnMut(&FnCtxt<'fcx, 'gcx, 'tcx2>) -> Vec<AdtVariant<'tcx2>>
+{
+    for_item(tcx, item).with_fcx(|fcx, fcx_tcx| {
+        let variants = lookup_fields(fcx);
+        let def_id = fcx.tcx.hir.local_def_id(item.id);
+        let packed = fcx.tcx.adt_def(def_id).repr.packed();
+
+        for variant in &variants {
+            // For DST, or when drop needs to copy things around, all
+            // intermediate types must be sized.
+            let needs_drop_copy = || {
+                packed && {
+                    let ty = variant.fields.last().unwrap().ty;
+                    let ty = fcx.tcx.erase_regions(&ty).lift_to_tcx(fcx_tcx)
+                        .unwrap_or_else(|| {
+                            span_bug!(item.span, "inference variables in {:?}", ty)
+                        });
+                    ty.needs_drop(fcx_tcx, fcx_tcx.param_env(def_id))
                 }
+            };
+            let unsized_len = if
+                all_sized ||
+                variant.fields.is_empty() ||
+                needs_drop_copy()
+            {
+                0
+            } else {
+                1
+            };
+            for field in &variant.fields[..variant.fields.len() - unsized_len] {
+                fcx.register_bound(
+                    field.ty,
+                    fcx.tcx.require_lang_item(lang_items::SizedTraitLangItem),
+                    traits::ObligationCause::new(field.span,
+                                                    fcx.body_id,
+                                                    traits::FieldSized(match item.node.adt_kind() {
+                                                    Some(i) => i,
+                                                    None => bug!(),
+                                                    })));
+            }
 
-                // All field types must be well-formed.
-                for field in &variant.fields {
-                    fcx.register_wf_obligation(field.ty, field.span, this.code.clone())
-                }
+            // All field types must be well-formed.
+            for field in &variant.fields {
+                fcx.register_wf_obligation(field.ty, field.span,
+                    ObligationCauseCode::MiscObligation)
             }
+        }
 
-            self.check_where_clauses(fcx, item.span, def_id);
+        check_where_clauses(tcx, fcx, item.span, def_id);
 
-            vec![] // no implied bounds in a struct def'n
-        });
-    }
+        vec![] // no implied bounds in a struct def'n
+    });
+}
 
-    fn check_trait(&mut self, item: &hir::Item) {
-        let trait_def_id = self.tcx.hir.local_def_id(item.id);
-        self.for_item(item).with_fcx(|fcx, _| {
-            self.check_where_clauses(fcx, item.span, trait_def_id);
-            vec![]
-        });
-    }
+fn check_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item: &hir::Item) {
+    let trait_def_id = tcx.hir.local_def_id(item.id);
+    for_item(tcx, item).with_fcx(|fcx, _| {
+        check_where_clauses(tcx, fcx, item.span, trait_def_id);
+        vec![]
+    });
+}
 
-    fn check_item_fn(&mut self, item: &hir::Item) {
-        self.for_item(item).with_fcx(|fcx, this| {
-            let def_id = fcx.tcx.hir.local_def_id(item.id);
-            let sig = fcx.tcx.fn_sig(def_id);
-            let sig = fcx.normalize_associated_types_in(item.span, &sig);
-            let mut implied_bounds = vec![];
-            this.check_fn_or_method(fcx, item.span, sig,
-                                    def_id, &mut implied_bounds);
-            implied_bounds
-        })
-    }
+fn check_item_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item: &hir::Item) {
+    for_item(tcx, item).with_fcx(|fcx, tcx| {
+        let def_id = fcx.tcx.hir.local_def_id(item.id);
+        let sig = fcx.tcx.fn_sig(def_id);
+        let sig = fcx.normalize_associated_types_in(item.span, &sig);
+        let mut implied_bounds = vec![];
+        check_fn_or_method(tcx, fcx, item.span, sig,
+                                def_id, &mut implied_bounds);
+        implied_bounds
+    })
+}
 
-    fn check_item_type(&mut self,
-                       item: &hir::Item)
-    {
-        debug!("check_item_type: {:?}", item);
+fn check_item_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                    item: &hir::Item)
+{
+    debug!("check_item_type: {:?}", item);
 
-        self.for_item(item).with_fcx(|fcx, this| {
-            let ty = fcx.tcx.type_of(fcx.tcx.hir.local_def_id(item.id));
-            let item_ty = fcx.normalize_associated_types_in(item.span, &ty);
+    for_item(tcx, item).with_fcx(|fcx, _this| {
+        let ty = fcx.tcx.type_of(fcx.tcx.hir.local_def_id(item.id));
+        let item_ty = fcx.normalize_associated_types_in(item.span, &ty);
 
-            fcx.register_wf_obligation(item_ty, item.span, this.code.clone());
+        fcx.register_wf_obligation(item_ty, item.span, ObligationCauseCode::MiscObligation);
 
-            vec![] // no implied bounds in a const etc
-        });
-    }
+        vec![] // no implied bounds in a const etc
+    });
+}
 
-    fn check_impl(&mut self,
-                  item: &hir::Item,
-                  ast_self_ty: &hir::Ty,
-                  ast_trait_ref: &Option<hir::TraitRef>)
-    {
-        debug!("check_impl: {:?}", item);
-
-        self.for_item(item).with_fcx(|fcx, this| {
-            let item_def_id = fcx.tcx.hir.local_def_id(item.id);
-
-            match *ast_trait_ref {
-                Some(ref ast_trait_ref) => {
-                    let trait_ref = fcx.tcx.impl_trait_ref(item_def_id).unwrap();
-                    let trait_ref =
-                        fcx.normalize_associated_types_in(
-                            ast_trait_ref.path.span, &trait_ref);
-                    let obligations =
-                        ty::wf::trait_obligations(fcx,
-                                                  fcx.param_env,
-                                                  fcx.body_id,
-                                                  &trait_ref,
-                                                  ast_trait_ref.path.span);
-                    for obligation in obligations {
-                        fcx.register_predicate(obligation);
-                    }
-                }
-                None => {
-                    let self_ty = fcx.tcx.type_of(item_def_id);
-                    let self_ty = fcx.normalize_associated_types_in(item.span, &self_ty);
-                    fcx.register_wf_obligation(self_ty, ast_self_ty.span, this.code.clone());
+fn check_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                item: &hir::Item,
+                ast_self_ty: &hir::Ty,
+                ast_trait_ref: &Option<hir::TraitRef>)
+{
+    debug!("check_impl: {:?}", item);
+
+    for_item(tcx, item).with_fcx(|fcx, tcx| {
+        let item_def_id = fcx.tcx.hir.local_def_id(item.id);
+
+        match *ast_trait_ref {
+            Some(ref ast_trait_ref) => {
+                let trait_ref = fcx.tcx.impl_trait_ref(item_def_id).unwrap();
+                let trait_ref =
+                    fcx.normalize_associated_types_in(
+                        ast_trait_ref.path.span, &trait_ref);
+                let obligations =
+                    ty::wf::trait_obligations(fcx,
+                                                fcx.param_env,
+                                                fcx.body_id,
+                                                &trait_ref,
+                                                ast_trait_ref.path.span);
+                for obligation in obligations {
+                    fcx.register_predicate(obligation);
                 }
             }
+            None => {
+                let self_ty = fcx.tcx.type_of(item_def_id);
+                let self_ty = fcx.normalize_associated_types_in(item.span, &self_ty);
+                fcx.register_wf_obligation(self_ty, ast_self_ty.span,
+                    ObligationCauseCode::MiscObligation);
+            }
+        }
 
-            this.check_where_clauses(fcx, item.span, item_def_id);
+        check_where_clauses(tcx, fcx, item.span, item_def_id);
 
-            fcx.impl_implied_bounds(item_def_id, item.span)
-        });
-    }
+        fcx.impl_implied_bounds(item_def_id, item.span)
+    });
+}
 
-    /// Checks where clauses and inline bounds that are declared on def_id.
-    fn check_where_clauses<'fcx, 'tcx>(&mut self,
-                                       fcx: &FnCtxt<'fcx, 'gcx, 'tcx>,
-                                       span: Span,
-                                       def_id: DefId) {
-        use ty::subst::Subst;
-        use rustc::ty::TypeFoldable;
-
-        let mut predicates = fcx.tcx.predicates_of(def_id);
-        let mut substituted_predicates = Vec::new();
-
-        let generics = self.tcx.generics_of(def_id);
-        let is_our_default = |def: &ty::TypeParameterDef|
-                                def.has_default && def.index >= generics.parent_count() as u32;
-
-        // Check that concrete defaults are well-formed. See test `type-check-defaults.rs`.
-        // For example this forbids the declaration:
-        // struct Foo<T = Vec<[u32]>> { .. }
-        // Here the default `Vec<[u32]>` is not WF because `[u32]: Sized` does not hold.
-        for d in generics.types.iter().cloned().filter(is_our_default).map(|p| p.def_id) {
-            let ty = fcx.tcx.type_of(d);
-            // ignore dependent defaults -- that is, where the default of one type
-            // parameter includes another (e.g., <T, U = T>). In those cases, we can't
-            // be sure if it will error or not as user might always specify the other.
-            if !ty.needs_subst() {
-                fcx.register_wf_obligation(ty, fcx.tcx.def_span(d), self.code.clone());
-            }
+/// Checks where clauses and inline bounds that are declared on def_id.
+fn check_where_clauses<'a, 'gcx, 'fcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>,
+                                    fcx: &FnCtxt<'fcx, 'gcx, 'tcx>,
+                                    span: Span,
+                                    def_id: DefId) {
+    use ty::subst::Subst;
+    use rustc::ty::TypeFoldable;
+
+    let mut predicates = fcx.tcx.predicates_of(def_id);
+    let mut substituted_predicates = Vec::new();
+
+    let generics = tcx.generics_of(def_id);
+    let is_our_default = |def: &ty::TypeParameterDef|
+                            def.has_default && def.index >= generics.parent_count() as u32;
+
+    // Check that concrete defaults are well-formed. See test `type-check-defaults.rs`.
+    // For example this forbids the declaration:
+    // struct Foo<T = Vec<[u32]>> { .. }
+    // Here the default `Vec<[u32]>` is not WF because `[u32]: Sized` does not hold.
+    for d in generics.types.iter().cloned().filter(is_our_default).map(|p| p.def_id) {
+        let ty = fcx.tcx.type_of(d);
+        // ignore dependent defaults -- that is, where the default of one type
+        // parameter includes another (e.g., <T, U = T>). In those cases, we can't
+        // be sure if it will error or not as user might always specify the other.
+        if !ty.needs_subst() {
+            fcx.register_wf_obligation(ty, fcx.tcx.def_span(d),
+                ObligationCauseCode::MiscObligation);
         }
+    }
 
-        // Check that trait predicates are WF when params are substituted by their defaults.
-        // We don't want to overly constrain the predicates that may be written but we want to
-        // catch cases where a default my never be applied such as `struct Foo<T: Copy = String>`.
-        // Therefore we check if a predicate which contains a single type param
-        // with a concrete default is WF with that default substituted.
-        // For more examples see tests `defaults-well-formedness.rs` and `type-check-defaults.rs`.
-        //
-        // First we build the defaulted substitution.
-        let substs = ty::subst::Substs::for_item(fcx.tcx, def_id, |def, _| {
-                // All regions are identity.
-                fcx.tcx.mk_region(ty::ReEarlyBound(def.to_early_bound_region_data()))
-            }, |def, _| {
-                // If the param has a default,
-                if is_our_default(def) {
-                    let default_ty = fcx.tcx.type_of(def.def_id);
-                    // and it's not a dependent default
-                    if !default_ty.needs_subst() {
-                        // then substitute with the default.
-                        return default_ty;
-                    }
+    // Check that trait predicates are WF when params are substituted by their defaults.
+    // We don't want to overly constrain the predicates that may be written but we want to
+    // catch cases where a default my never be applied such as `struct Foo<T: Copy = String>`.
+    // Therefore we check if a predicate which contains a single type param
+    // with a concrete default is WF with that default substituted.
+    // For more examples see tests `defaults-well-formedness.rs` and `type-check-defaults.rs`.
+    //
+    // First we build the defaulted substitution.
+    let substs = ty::subst::Substs::for_item(fcx.tcx, def_id, |def, _| {
+            // All regions are identity.
+            fcx.tcx.mk_region(ty::ReEarlyBound(def.to_early_bound_region_data()))
+        }, |def, _| {
+            // If the param has a default,
+            if is_our_default(def) {
+                let default_ty = fcx.tcx.type_of(def.def_id);
+                // and it's not a dependent default
+                if !default_ty.needs_subst() {
+                    // then substitute with the default.
+                    return default_ty;
                 }
-                // Mark unwanted params as err.
-                fcx.tcx.types.err
-            });
-        // Now we build the substituted predicates.
-        for &pred in predicates.predicates.iter() {
-            struct CountParams { params: FxHashSet<u32> }
-            impl<'tcx> ty::fold::TypeVisitor<'tcx> for CountParams {
-                fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
-                    match t.sty {
-                        ty::TyParam(p) => {
-                            self.params.insert(p.idx);
-                            t.super_visit_with(self)
-                        }
-                        _ => t.super_visit_with(self)
+            }
+            // Mark unwanted params as err.
+            fcx.tcx.types.err
+        });
+    // Now we build the substituted predicates.
+    for &pred in predicates.predicates.iter() {
+        struct CountParams { params: FxHashSet<u32> }
+        impl<'tcx> ty::fold::TypeVisitor<'tcx> for CountParams {
+            fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
+                match t.sty {
+                    ty::TyParam(p) => {
+                        self.params.insert(p.idx);
+                        t.super_visit_with(self)
                     }
+                    _ => t.super_visit_with(self)
                 }
             }
-            let mut param_count = CountParams { params: FxHashSet() };
-            pred.visit_with(&mut param_count);
-            let substituted_pred = pred.subst(fcx.tcx, substs);
-            // Don't check non-defaulted params, dependent defaults or preds with multiple params.
-            if substituted_pred.references_error() || param_count.params.len() > 1 {
-                continue;
-            }
-            // Avoid duplication of predicates that contain no parameters, for example.
-            if !predicates.predicates.contains(&substituted_pred) {
-                substituted_predicates.push(substituted_pred);
-            }
         }
-
-        predicates.predicates.extend(substituted_predicates);
-        let predicates = predicates.instantiate_identity(fcx.tcx);
-        let predicates = fcx.normalize_associated_types_in(span, &predicates);
-
-        let obligations =
-            predicates.predicates
-                      .iter()
-                      .flat_map(|p| ty::wf::predicate_obligations(fcx,
-                                                                  fcx.param_env,
-                                                                  fcx.body_id,
-                                                                  p,
-                                                                  span));
-
-        for obligation in obligations {
-            fcx.register_predicate(obligation);
+        let mut param_count = CountParams { params: FxHashSet() };
+        pred.visit_with(&mut param_count);
+        let substituted_pred = pred.subst(fcx.tcx, substs);
+        // Don't check non-defaulted params, dependent defaults or preds with multiple params.
+        if substituted_pred.references_error() || param_count.params.len() > 1 {
+            continue;
+        }
+        // Avoid duplication of predicates that contain no parameters, for example.
+        if !predicates.predicates.contains(&substituted_pred) {
+            substituted_predicates.push(substituted_pred);
         }
     }
 
-    fn check_fn_or_method<'fcx, 'tcx>(&mut self,
-                                      fcx: &FnCtxt<'fcx, 'gcx, 'tcx>,
-                                      span: Span,
-                                      sig: ty::PolyFnSig<'tcx>,
-                                      def_id: DefId,
-                                      implied_bounds: &mut Vec<Ty<'tcx>>)
-    {
-        let sig = fcx.normalize_associated_types_in(span, &sig);
-        let sig = fcx.tcx.liberate_late_bound_regions(def_id, &sig);
-
-        for input_ty in sig.inputs() {
-            fcx.register_wf_obligation(&input_ty, span, self.code.clone());
-        }
-        implied_bounds.extend(sig.inputs());
+    predicates.predicates.extend(substituted_predicates);
+    let predicates = predicates.instantiate_identity(fcx.tcx);
+    let predicates = fcx.normalize_associated_types_in(span, &predicates);
+
+    let obligations =
+        predicates.predicates
+                    .iter()
+                    .flat_map(|p| ty::wf::predicate_obligations(fcx,
+                                                                fcx.param_env,
+                                                                fcx.body_id,
+                                                                p,
+                                                                span));
+
+    for obligation in obligations {
+        fcx.register_predicate(obligation);
+    }
+}
 
-        fcx.register_wf_obligation(sig.output(), span, self.code.clone());
+fn check_fn_or_method<'a, 'fcx, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>,
+                                    fcx: &FnCtxt<'fcx, 'gcx, 'tcx>,
+                                    span: Span,
+                                    sig: ty::PolyFnSig<'tcx>,
+                                    def_id: DefId,
+                                    implied_bounds: &mut Vec<Ty<'tcx>>)
+{
+    let sig = fcx.normalize_associated_types_in(span, &sig);
+    let sig = fcx.tcx.liberate_late_bound_regions(def_id, &sig);
+
+    for input_ty in sig.inputs() {
+        fcx.register_wf_obligation(&input_ty, span, ObligationCauseCode::MiscObligation);
+    }
+    implied_bounds.extend(sig.inputs());
 
-        // FIXME(#25759) return types should not be implied bounds
-        implied_bounds.push(sig.output());
+    fcx.register_wf_obligation(sig.output(), span, ObligationCauseCode::MiscObligation);
 
-        self.check_where_clauses(fcx, span, def_id);
-    }
+    // FIXME(#25759) return types should not be implied bounds
+    implied_bounds.push(sig.output());
 
-    fn check_method_receiver<'fcx, 'tcx>(&mut self,
-                                         fcx: &FnCtxt<'fcx, 'gcx, 'tcx>,
-                                         method_sig: &hir::MethodSig,
-                                         method: &ty::AssociatedItem,
-                                         self_ty: Ty<'tcx>)
-    {
-        // check that the method has a valid receiver type, given the type `Self`
-        debug!("check_method_receiver({:?}, self_ty={:?})",
-               method, self_ty);
+    check_where_clauses(tcx, fcx, span, def_id);
+}
 
-        if !method.method_has_self_argument {
-            return;
-        }
+fn check_method_receiver<'fcx, 'gcx, 'tcx>(fcx: &FnCtxt<'fcx, 'gcx, 'tcx>,
+                                           method_sig: &hir::MethodSig,
+                                           method: &ty::AssociatedItem,
+                                           self_ty: Ty<'tcx>)
+{
+    // check that the method has a valid receiver type, given the type `Self`
+    debug!("check_method_receiver({:?}, self_ty={:?})",
+            method, self_ty);
+
+    if !method.method_has_self_argument {
+        return;
+    }
 
-        let span = method_sig.decl.inputs[0].span;
+    let span = method_sig.decl.inputs[0].span;
 
-        let sig = fcx.tcx.fn_sig(method.def_id);
-        let sig = fcx.normalize_associated_types_in(span, &sig);
-        let sig = fcx.tcx.liberate_late_bound_regions(method.def_id, &sig);
+    let sig = fcx.tcx.fn_sig(method.def_id);
+    let sig = fcx.normalize_associated_types_in(span, &sig);
+    let sig = fcx.tcx.liberate_late_bound_regions(method.def_id, &sig);
 
-        debug!("check_method_receiver: sig={:?}", sig);
+    debug!("check_method_receiver: sig={:?}", sig);
 
-        let self_ty = fcx.normalize_associated_types_in(span, &self_ty);
-        let self_ty = fcx.tcx.liberate_late_bound_regions(
-            method.def_id,
-            &ty::Binder(self_ty)
-        );
+    let self_ty = fcx.normalize_associated_types_in(span, &self_ty);
+    let self_ty = fcx.tcx.liberate_late_bound_regions(
+        method.def_id,
+        &ty::Binder(self_ty)
+    );
 
-        let self_arg_ty = sig.inputs()[0];
+    let self_arg_ty = sig.inputs()[0];
 
-        let cause = fcx.cause(span, ObligationCauseCode::MethodReceiver);
-        let self_arg_ty = fcx.normalize_associated_types_in(span, &self_arg_ty);
-        let self_arg_ty = fcx.tcx.liberate_late_bound_regions(
-            method.def_id,
-            &ty::Binder(self_arg_ty)
-        );
+    let cause = fcx.cause(span, ObligationCauseCode::MethodReceiver);
+    let self_arg_ty = fcx.normalize_associated_types_in(span, &self_arg_ty);
+    let self_arg_ty = fcx.tcx.liberate_late_bound_regions(
+        method.def_id,
+        &ty::Binder(self_arg_ty)
+    );
 
-        let mut autoderef = fcx.autoderef(span, self_arg_ty).include_raw_pointers();
+    let mut autoderef = fcx.autoderef(span, self_arg_ty).include_raw_pointers();
 
-        loop {
-            if let Some((potential_self_ty, _)) = autoderef.next() {
-                debug!("check_method_receiver: potential self type `{:?}` to match `{:?}`",
-                    potential_self_ty, self_ty);
+    loop {
+        if let Some((potential_self_ty, _)) = autoderef.next() {
+            debug!("check_method_receiver: potential self type `{:?}` to match `{:?}`",
+                potential_self_ty, self_ty);
 
-                if fcx.infcx.can_eq(fcx.param_env, self_ty, potential_self_ty).is_ok() {
-                    autoderef.finalize();
-                    if let Some(mut err) = fcx.demand_eqtype_with_origin(
-                        &cause, self_ty, potential_self_ty) {
-                        err.emit();
-                    }
-                    break
+            if fcx.infcx.can_eq(fcx.param_env, self_ty, potential_self_ty).is_ok() {
+                autoderef.finalize();
+                if let Some(mut err) = fcx.demand_eqtype_with_origin(
+                    &cause, self_ty, potential_self_ty) {
+                    err.emit();
                 }
-            } else {
-                fcx.tcx.sess.diagnostic().mut_span_err(
-                    span, &format!("invalid `self` type: {:?}", self_arg_ty))
-                .note(&format!("type must be `{:?}` or a type that dereferences to it", self_ty))
-                .help("consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`")
-                .code(DiagnosticId::Error("E0307".into()))
-                .emit();
-                return
+                break
             }
+        } else {
+            fcx.tcx.sess.diagnostic().mut_span_err(
+                span, &format!("invalid `self` type: {:?}", self_arg_ty))
+            .note(&format!("type must be `{:?}` or a type that dereferences to it", self_ty))
+            .help("consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`")
+            .code(DiagnosticId::Error("E0307".into()))
+            .emit();
+            return
         }
+    }
 
-        let is_self_ty = |ty| fcx.infcx.can_eq(fcx.param_env, self_ty, ty).is_ok();
-        let self_kind = ExplicitSelf::determine(self_arg_ty, is_self_ty);
-
-        if !fcx.tcx.features().arbitrary_self_types {
-            match self_kind {
-                ExplicitSelf::ByValue |
-                ExplicitSelf::ByReference(_, _) |
-                ExplicitSelf::ByBox => (),
-
-                ExplicitSelf::ByRawPointer(_) => {
-                    feature_gate::feature_err(
-                        &fcx.tcx.sess.parse_sess,
-                        "arbitrary_self_types",
-                        span,
-                        GateIssue::Language,
-                        "raw pointer `self` is unstable")
-                    .help("consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`")
-                    .emit();
-                }
+    let is_self_ty = |ty| fcx.infcx.can_eq(fcx.param_env, self_ty, ty).is_ok();
+    let self_kind = ExplicitSelf::determine(self_arg_ty, is_self_ty);
+
+    if !fcx.tcx.features().arbitrary_self_types {
+        match self_kind {
+            ExplicitSelf::ByValue |
+            ExplicitSelf::ByReference(_, _) |
+            ExplicitSelf::ByBox => (),
+
+            ExplicitSelf::ByRawPointer(_) => {
+                feature_gate::feature_err(
+                    &fcx.tcx.sess.parse_sess,
+                    "arbitrary_self_types",
+                    span,
+                    GateIssue::Language,
+                    "raw pointer `self` is unstable")
+                .help("consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`")
+                .emit();
+            }
 
-                ExplicitSelf::Other => {
-                    feature_gate::feature_err(
-                        &fcx.tcx.sess.parse_sess,
-                        "arbitrary_self_types",
-                        span,
-                        GateIssue::Language,"arbitrary `self` types are unstable")
-                    .help("consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`")
-                    .emit();
-                }
+            ExplicitSelf::Other => {
+                feature_gate::feature_err(
+                    &fcx.tcx.sess.parse_sess,
+                    "arbitrary_self_types",
+                    span,
+                    GateIssue::Language,"arbitrary `self` types are unstable")
+                .help("consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`")
+                .emit();
             }
         }
     }
+}
 
-    fn check_variances_for_type_defn(&self,
-                                     item: &hir::Item,
-                                     ast_generics: &hir::Generics)
-    {
-        let item_def_id = self.tcx.hir.local_def_id(item.id);
-        let ty = self.tcx.type_of(item_def_id);
-        if self.tcx.has_error_field(ty) {
-            return;
-        }
-
-        let ty_predicates = self.tcx.predicates_of(item_def_id);
-        assert_eq!(ty_predicates.parent, None);
-        let variances = self.tcx.variances_of(item_def_id);
+fn check_variances_for_type_defn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                    item: &hir::Item,
+                                    ast_generics: &hir::Generics)
+{
+    let item_def_id = tcx.hir.local_def_id(item.id);
+    let ty = tcx.type_of(item_def_id);
+    if tcx.has_error_field(ty) {
+        return;
+    }
 
-        let mut constrained_parameters: FxHashSet<_> =
-            variances.iter().enumerate()
-                     .filter(|&(_, &variance)| variance != ty::Bivariant)
-                     .map(|(index, _)| Parameter(index as u32))
-                     .collect();
+    let ty_predicates = tcx.predicates_of(item_def_id);
+    assert_eq!(ty_predicates.parent, None);
+    let variances = tcx.variances_of(item_def_id);
 
-        identify_constrained_type_params(self.tcx,
-                                         ty_predicates.predicates.as_slice(),
-                                         None,
-                                         &mut constrained_parameters);
+    let mut constrained_parameters: FxHashSet<_> =
+        variances.iter().enumerate()
+                    .filter(|&(_, &variance)| variance != ty::Bivariant)
+                    .map(|(index, _)| Parameter(index as u32))
+                    .collect();
 
-        for (index, _) in variances.iter().enumerate() {
-            if constrained_parameters.contains(&Parameter(index as u32)) {
-                continue;
-            }
+    identify_constrained_type_params(tcx,
+                                        ty_predicates.predicates.as_slice(),
+                                        None,
+                                        &mut constrained_parameters);
 
-            let (span, name) = match ast_generics.params[index] {
-                hir::GenericParam::Lifetime(ref ld) => (ld.lifetime.span, ld.lifetime.name.name()),
-                hir::GenericParam::Type(ref tp) => (tp.span, tp.name),
-            };
-            self.report_bivariance(span, name);
+    for (index, _) in variances.iter().enumerate() {
+        if constrained_parameters.contains(&Parameter(index as u32)) {
+            continue;
         }
+
+        let (span, name) = match ast_generics.params[index] {
+            hir::GenericParam::Lifetime(ref ld) => (ld.lifetime.span, ld.lifetime.name.name()),
+            hir::GenericParam::Type(ref tp) => (tp.span, tp.name),
+        };
+        report_bivariance(tcx, span, name);
     }
+}
 
-    fn report_bivariance(&self,
-                         span: Span,
-                         param_name: ast::Name)
-    {
-        let mut err = error_392(self.tcx, span, param_name);
-
-        let suggested_marker_id = self.tcx.lang_items().phantom_data();
-        match suggested_marker_id {
-            Some(def_id) => {
-                err.help(
-                    &format!("consider removing `{}` or using a marker such as `{}`",
-                             param_name,
-                             self.tcx.item_path_str(def_id)));
-            }
-            None => {
-                // no lang items, no help!
-            }
+fn report_bivariance<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                        span: Span,
+                        param_name: ast::Name)
+{
+    let mut err = error_392(tcx, span, param_name);
+
+    let suggested_marker_id = tcx.lang_items().phantom_data();
+    match suggested_marker_id {
+        Some(def_id) => {
+            err.help(
+                &format!("consider removing `{}` or using a marker such as `{}`",
+                            param_name,
+                            tcx.item_path_str(def_id)));
+        }
+        None => {
+            // no lang items, no help!
         }
-        err.emit();
     }
+    err.emit();
 }
 
 fn reject_shadowing_type_parameters(tcx: TyCtxt, def_id: DefId) {
@@ -648,6 +654,19 @@ fn reject_shadowing_type_parameters(tcx: TyCtxt, def_id: DefId) {
     }
 }
 
+pub struct CheckTypeWellFormedVisitor<'a, 'tcx: 'a> {
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+}
+
+impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
+    pub fn new(tcx: TyCtxt<'a, 'gcx, 'gcx>)
+               -> CheckTypeWellFormedVisitor<'a, 'gcx> {
+        CheckTypeWellFormedVisitor {
+            tcx,
+        }
+    }
+}
+
 impl<'a, 'tcx, 'v> Visitor<'v> for CheckTypeWellFormedVisitor<'a, 'tcx> {
     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'v> {
         NestedVisitorMap::None
@@ -655,27 +674,22 @@ fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'v> {
 
     fn visit_item(&mut self, i: &hir::Item) {
         debug!("visit_item: {:?}", i);
-        self.check_item_well_formed(i);
+        let def_id = self.tcx.hir.local_def_id(i.id);
+        ty::maps::queries::check_item_well_formed::ensure(self.tcx, def_id);
         intravisit::walk_item(self, i);
     }
 
     fn visit_trait_item(&mut self, trait_item: &'v hir::TraitItem) {
         debug!("visit_trait_item: {:?}", trait_item);
-        let method_sig = match trait_item.node {
-            hir::TraitItemKind::Method(ref sig, _) => Some(sig),
-            _ => None
-        };
-        self.check_associated_item(trait_item.id, trait_item.span, method_sig);
+        let def_id = self.tcx.hir.local_def_id(trait_item.id);
+        ty::maps::queries::check_trait_item_well_formed::ensure(self.tcx, def_id);
         intravisit::walk_trait_item(self, trait_item)
     }
 
     fn visit_impl_item(&mut self, impl_item: &'v hir::ImplItem) {
         debug!("visit_impl_item: {:?}", impl_item);
-        let method_sig = match impl_item.node {
-            hir::ImplItemKind::Method(ref sig, _) => Some(sig),
-            _ => None
-        };
-        self.check_associated_item(impl_item.id, impl_item.span, method_sig);
+        let def_id = self.tcx.hir.local_def_id(impl_item.id);
+        ty::maps::queries::check_impl_item_well_formed::ensure(self.tcx, def_id);
         intravisit::walk_impl_item(self, impl_item)
     }
 }
index a17b35dec42d7c2f75683b7ec789a3ee6adf0a66..6f24d06844bb4c124ed600787acfe1ec7459e949 100644 (file)
@@ -35,8 +35,9 @@
 use rustc::ty::{self, AdtKind, ToPolyTraitRef, Ty, TyCtxt};
 use rustc::ty::maps::Providers;
 use rustc::ty::util::IntTypeExt;
-use rustc::util::nodemap::{FxHashSet, FxHashMap};
 use rustc::ty::util::Discr;
+use rustc::util::captures::Captures;
+use rustc::util::nodemap::{FxHashSet, FxHashMap};
 
 use syntax::{abi, ast};
 use syntax::ast::MetaItemKind;
@@ -1281,7 +1282,7 @@ fn is_unsized<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
 fn early_bound_lifetimes_from_generics<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     ast_generics: &'a hir::Generics)
-    -> impl Iterator<Item=&'a hir::LifetimeDef>
+    -> impl Iterator<Item=&'a hir::LifetimeDef> + Captures<'tcx>
 {
     ast_generics
         .lifetimes()
index 24044fd2d721840d237ea6a744787fb93f9423a5..f5337118e30d1924fba07238d74614d0095a17a6 100644 (file)
@@ -3559,8 +3559,6 @@ fn fly(&self) {} // And now that's ok!
 Example of erroneous code:
 
 ```compile_fail,E0527
-#![feature(slice_patterns)]
-
 let r = &[1, 2, 3, 4];
 match r {
     &[a, b] => { // error: pattern requires 2 elements but array
@@ -3625,8 +3623,6 @@ fn fly(&self) {} // And now that's ok!
 Example of erroneous code:
 
 ```compile_fail,E0529
-#![feature(slice_patterns)]
-
 let r: f32 = 1.0;
 match r {
     [a, b] => { // error: expected an array or slice, found `f32`
@@ -3639,8 +3635,6 @@ fn fly(&self) {} // And now that's ok!
 types:
 
 ```
-#![feature(slice_patterns)]
-
 let r = [1.0, 2.0];
 match r {
     [a, b] => { // ok!
index 964c0021133aae5100f55ac49de349abf7934948..9f98932f24b52d90100b6a75ed6ec22dcc1ef111 100644 (file)
@@ -72,7 +72,7 @@
 
 #![allow(non_camel_case_types)]
 
-#![feature(advanced_slice_patterns)]
+#![cfg_attr(stage0, feature(advanced_slice_patterns))]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
 #![feature(conservative_impl_trait)]
index 370fc9bbca2431224761fb82d24ab84d0cc684de..9ff3d25a45ae412081110b6f9166471857bd0371 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 use rustc::ty::TypeFoldable;
+use std::fmt::Debug;
 
 use super::*;
 
@@ -1081,18 +1082,25 @@ fn make_final_bounds<'b, 'c, 'cx>(
                     return None;
                 }
 
+                let mut bounds_vec = bounds.into_iter().collect();
+                self.sort_where_bounds(&mut bounds_vec);
+
                 Some(WherePredicate::BoundPredicate {
                     ty,
-                    bounds: bounds.into_iter().collect(),
+                    bounds: bounds_vec,
                 })
             })
             .chain(
                 lifetime_to_bounds
                     .into_iter()
                     .filter(|&(_, ref bounds)| !bounds.is_empty())
-                    .map(|(lifetime, bounds)| WherePredicate::RegionPredicate {
-                        lifetime,
-                        bounds: bounds.into_iter().collect(),
+                    .map(|(lifetime, bounds)| {
+                        let mut bounds_vec = bounds.into_iter().collect();
+                        self.sort_where_lifetimes(&mut bounds_vec);
+                        WherePredicate::RegionPredicate {
+                            lifetime,
+                            bounds: bounds_vec,
+                        }
                     }),
             )
             .collect()
@@ -1372,40 +1380,64 @@ fn param_env_to_generics<'b, 'c, 'cx>(
     // a given set of predicates always appears in the same order -
     // both for visual consistency between 'rustdoc' runs, and to
     // make writing tests much easier
-    fn sort_where_predicates(&self, predicates: &mut Vec<WherePredicate>) {
+    #[inline]
+    fn sort_where_predicates(&self, mut predicates: &mut Vec<WherePredicate>) {
         // We should never have identical bounds - and if we do,
         // they're visually identical as well. Therefore, using
         // an unstable sort is fine.
-        predicates.sort_unstable_by(|first, second| {
-            // This might look horrendously hacky, but it's actually not that bad.
-            //
-            // For performance reasons, we use several different FxHashMaps
-            // in the process of computing the final set of where predicates.
-            // However, the iteration order of a HashMap is completely unspecified.
-            // In fact, the iteration of an FxHashMap can even vary between platforms,
-            // since FxHasher has different behavior for 32-bit and 64-bit platforms.
-            //
-            // Obviously, it's extremely undesireable for documentation rendering
-            // to be depndent on the platform it's run on. Apart from being confusing
-            // to end users, it makes writing tests much more difficult, as predicates
-            // can appear in any order in the final result.
-            //
-            // To solve this problem, we sort WherePredicates by their Debug
-            // string. The thing to keep in mind is that we don't really
-            // care what the final order is - we're synthesizing an impl
-            // ourselves, so any order can be considered equally valid.
-            // By sorting the predicates, however, we ensure that for
-            // a given codebase, all auto-trait impls always render
-            // in exactly the same way.
-            //
-            // Using the Debug impementation for sorting prevents
-            // us from needing to write quite a bit of almost
-            // entirely useless code (e.g. how should two
-            // Types be sorted relative to each other).
-            // This approach is probably somewhat slower, but
-            // the small number of items involved (impls
-            // rarely have more than a few bounds) means
-            // that it shouldn't matter in practice.
+        self.unstable_debug_sort(&mut predicates);
+    }
+
+    // Ensure that the bounds are in a consistent order. The precise
+    // ordering doesn't actually matter, but it's important that
+    // a given set of bounds always appears in the same order -
+    // both for visual consistency between 'rustdoc' runs, and to
+    // make writing tests much easier
+    #[inline]
+    fn sort_where_bounds(&self, mut bounds: &mut Vec<TyParamBound>) {
+        // We should never have identical bounds - and if we do,
+        // they're visually identical as well. Therefore, using
+        // an unstable sort is fine.
+        self.unstable_debug_sort(&mut bounds);
+    }
+
+    #[inline]
+    fn sort_where_lifetimes(&self, mut bounds: &mut Vec<Lifetime>) {
+        // We should never have identical bounds - and if we do,
+        // they're visually identical as well. Therefore, using
+        // an unstable sort is fine.
+        self.unstable_debug_sort(&mut bounds);
+    }
+
+    // This might look horrendously hacky, but it's actually not that bad.
+    //
+    // For performance reasons, we use several different FxHashMaps
+    // in the process of computing the final set of where predicates.
+    // However, the iteration order of a HashMap is completely unspecified.
+    // In fact, the iteration of an FxHashMap can even vary between platforms,
+    // since FxHasher has different behavior for 32-bit and 64-bit platforms.
+    //
+    // Obviously, it's extremely undesireable for documentation rendering
+    // to be depndent on the platform it's run on. Apart from being confusing
+    // to end users, it makes writing tests much more difficult, as predicates
+    // can appear in any order in the final result.
+    //
+    // To solve this problem, we sort WherePredicates and TyParamBounds
+    // by their Debug string. The thing to keep in mind is that we don't really
+    // care what the final order is - we're synthesizing an impl or bound
+    // ourselves, so any order can be considered equally valid. By sorting the
+    // predicates and bounds, however, we ensure that for a given codebase, all
+    // auto-trait impls always render in exactly the same way.
+    //
+    // Using the Debug impementation for sorting prevents us from needing to
+    // write quite a bit of almost entirely useless code (e.g. how should two
+    // Types be sorted relative to each other). It also allows us to solve the
+    // problem for both WherePredicates and TyParamBounds at the same time. This
+    // approach is probably somewhat slower, but the small number of items
+    // involved (impls rarely have more than a few bounds) means that it
+    // shouldn't matter in practice.
+    fn unstable_debug_sort<T: Debug>(&self, vec: &mut Vec<T>) {
+        vec.sort_unstable_by(|first, second| {
             format!("{:?}", first).cmp(&format!("{:?}", second))
         });
     }
index 5cac2d1bbe7eeb1e0a5e55b1a26a218b1ed8df00..c228f54217d34c7f583dff93ef4744cf867d942d 100644 (file)
@@ -138,7 +138,7 @@ fn is_all(&self) -> bool {
 
     /// Renders the configuration for human display, as a short HTML description.
     pub(crate) fn render_short_html(&self) -> String {
-        let mut msg = Html(self).to_string();
+        let mut msg = ShortHtml(self).to_string();
         if self.should_capitalize_first_letter() {
             if let Some(i) = msg.find(|c: char| c.is_ascii_alphanumeric()) {
                 msg[i .. i+1].make_ascii_uppercase();
@@ -149,7 +149,13 @@ pub(crate) fn render_short_html(&self) -> String {
 
     /// Renders the configuration for long display, as a long HTML description.
     pub(crate) fn render_long_html(&self) -> String {
-        let mut msg = format!("This is supported on <strong>{}</strong>", Html(self));
+        let on = if self.should_use_with_in_description() {
+            "with"
+        } else {
+            "on"
+        };
+
+        let mut msg = format!("This is supported {} <strong>{}</strong>", on, Html(self));
         if self.should_append_only_to_description() {
             msg.push_str(" only");
         }
@@ -180,6 +186,13 @@ fn should_append_only_to_description(&self) -> bool {
             }
         }
     }
+
+    fn should_use_with_in_description(&self) -> bool {
+        match *self {
+            Cfg::Cfg(ref name, _) if name == &"target_feature" => true,
+            _ => false,
+        }
+    }
 }
 
 impl ops::Not for Cfg {
@@ -376,6 +389,8 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
                     },
                     ("target_endian", Some(endian)) => return write!(fmt, "{}-endian", endian),
                     ("target_pointer_width", Some(bits)) => return write!(fmt, "{}-bit", bits),
+                    ("target_feature", Some(feat)) =>
+                        return write!(fmt, "target feature <code>{}</code>", feat),
                     _ => "",
                 };
                 if !human_readable.is_empty() {
@@ -390,6 +405,19 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
+struct ShortHtml<'a>(&'a Cfg);
+
+impl<'a> fmt::Display for ShortHtml<'a> {
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+        match *self.0 {
+            Cfg::Cfg(ref name, Some(ref vendor)) if name == &"target_feature" => {
+                write!(fmt, "<code>{}</code>", vendor)
+            },
+            ref cfg => write!(fmt, "{}", Html(cfg)),
+        }
+    }
+}
+
 #[cfg(test)]
 mod test {
     use super::Cfg;
@@ -824,6 +852,10 @@ fn test_render_short_html() {
                 ).render_short_html(),
                 "(Debug-assertions enabled or Windows) and Unix"
             );
+            assert_eq!(
+                name_value_cfg("target_feature", "sse2").render_short_html(),
+                "<code>sse2</code>"
+            );
         })
     }
 
@@ -898,6 +930,10 @@ fn test_render_long_html() {
                 "This is supported on <strong>(debug-assertions enabled or Windows) and Unix\
                 </strong> only."
             );
+            assert_eq!(
+                name_value_cfg("target_feature", "sse2").render_long_html(),
+                "This is supported with <strong>target feature <code>sse2</code></strong> only."
+            );
         })
     }
 }
index 72e303e19820272d055dda6b2046bf2c6f051d50..1a42b02140cd27b04b0a1626343af235522a3547 100644 (file)
@@ -828,6 +828,19 @@ pub fn from_ast(diagnostic: &::errors::Handler,
             })
         }).collect();
 
+        // treat #[target_feature(enable = "feat")] attributes as if they were
+        // #[doc(cfg(target_feature = "feat"))] attributes as well
+        for attr in attrs.lists("target_feature") {
+            if attr.check_name("enable") {
+                if let Some(feat) = attr.value_str() {
+                    let meta = attr::mk_name_value_item_str("target_feature".into(), feat);
+                    if let Ok(feat_cfg) = Cfg::parse(&meta) {
+                        cfg &= feat_cfg;
+                    }
+                }
+            }
+        }
+
         Attributes {
             doc_strings,
             other_attrs,
index 8d1c9e4575e263037cad984b4c58e3af7b98b438..c09bd4cc84ae5222714bf7bb514a38d10c4998ec 100644 (file)
@@ -27,6 +27,7 @@
 
 #![allow(non_camel_case_types)]
 
+use rustc::session;
 use std::cell::RefCell;
 use std::collections::{HashMap, VecDeque};
 use std::default::Default;
@@ -434,7 +435,8 @@ fn next(&mut self) -> Option<Self::Item> {
     }
 }
 
-pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector, position: Span) {
+pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector, position: Span,
+                          sess: Option<&session::Session>) {
     tests.set_position(position);
 
     let mut parser = Parser::new(doc);
@@ -484,6 +486,9 @@ pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector, position: Sp
                                    line, filename, block_info.allow_fail);
                     prev_offset = offset;
                 } else {
+                    if let Some(ref sess) = sess {
+                        sess.span_warn(position, "invalid start of a new code block");
+                    }
                     break;
                 }
             }
index 28d39cb174a108dc0688c79098f0287374a5605b..21c1d9d670d65b787c5c0797ae6a171d5842422f 100644 (file)
         }
     }
 
-    function handleShortcut(ev) {
-        if (document.activeElement.tagName === "INPUT" &&
-                hasClass(document.getElementById('main'), "hidden")) {
-            return;
+    function handleEscape(ev, help) {
+        hideModal();
+        var search = document.getElementById("search");
+        if (!hasClass(help, "hidden")) {
+            displayHelp(false, ev);
+        } else if (!hasClass(search, "hidden")) {
+            ev.preventDefault();
+            addClass(search, "hidden");
+            removeClass(document.getElementById("main"), "hidden");
         }
+        defocusSearchBar();
+    }
 
+    function handleShortcut(ev) {
         // Don't interfere with browser shortcuts
         if (ev.ctrlKey || ev.altKey || ev.metaKey) {
             return;
         }
 
         var help = document.getElementById("help");
-        switch (getVirtualKey(ev)) {
-        case "Escape":
-            hideModal();
-            var search = document.getElementById("search");
-            if (!hasClass(help, "hidden")) {
-                displayHelp(false, ev);
-            } else if (!hasClass(search, "hidden")) {
-                ev.preventDefault();
-                addClass(search, "hidden");
-                removeClass(document.getElementById("main"), "hidden");
+        if (document.activeElement.tagName === "INPUT") {
+            switch (getVirtualKey(ev)) {
+            case "Escape":
+                handleEscape(ev, help);
+                break;
             }
-            defocusSearchBar();
-            break;
+        } else {
+            switch (getVirtualKey(ev)) {
+            case "Escape":
+                handleEscape(ev, help);
+                break;
 
-        case "s":
-        case "S":
-            displayHelp(false, ev);
-            hideModal();
-            ev.preventDefault();
-            focusSearchBar();
-            break;
+            case "s":
+            case "S":
+                displayHelp(false, ev);
+                hideModal();
+                ev.preventDefault();
+                focusSearchBar();
+                break;
 
-        case "+":
-        case "-":
-            ev.preventDefault();
-            toggleAllDocs();
-            break;
+            case "+":
+            case "-":
+                ev.preventDefault();
+                toggleAllDocs();
+                break;
 
-        case "?":
-            if (ev.shiftKey) {
-                hideModal();
-                displayHelp(true, ev);
+            case "?":
+                if (ev.shiftKey) {
+                    hideModal();
+                    displayHelp(true, ev);
+                }
+                break;
             }
-            break;
         }
     }
 
index da52fd5aa37253aa854db04bb2cc5a770627615d..bec25a98227a22d2ec551b571575125d980c996c 100644 (file)
@@ -20,7 +20,7 @@
 #![feature(box_syntax)]
 #![feature(fs_read_write)]
 #![feature(set_stdio)]
-#![feature(slice_patterns)]
+#![cfg_attr(stage0, feature(slice_patterns))]
 #![feature(test)]
 #![feature(unicode)]
 #![feature(vec_remove_item)]
index 0f107457d2bf88815927dbc36de0bfc679da5948..3a55b279b5cc701914f4330513a1b53320976c65 100644 (file)
@@ -152,7 +152,7 @@ pub fn test(input: &str, cfgs: Vec<String>, libs: SearchPaths, externs: Externs,
                                        true, opts, maybe_sysroot, None,
                                        Some(PathBuf::from(input)),
                                        linker);
-    find_testable_code(&input_str, &mut collector, DUMMY_SP);
+    find_testable_code(&input_str, &mut collector, DUMMY_SP, None);
     test_args.insert(0, "rustdoctest".to_string());
     testing::test_main(&test_args, collector.tests,
                        testing::Options::new().display_output(display_warnings));
index 117b21d47587f830121b43e9c2ff46b375b1dce3..3ce8bd4ebb4c1002f70e891ff7cd78930f6c924a 100644 (file)
@@ -416,6 +416,7 @@ fn partition_source(s: &str) -> (String, String) {
         let trimline = line.trim();
         let header = trimline.is_whitespace() ||
             trimline.starts_with("#![") ||
+            trimline.starts_with("#[macro_use] extern crate") ||
             trimline.starts_with("extern crate");
         if !header || after_header {
             after_header = true;
@@ -645,8 +646,10 @@ fn visit_testable<F: FnOnce(&mut Self)>(&mut self,
         // the collapse-docs pass won't combine sugared/raw doc attributes, or included files with
         // anything else, this will combine them for us
         if let Some(doc) = attrs.collapsed_doc_value() {
-            markdown::find_testable_code(&doc, self.collector,
-                                         attrs.span.unwrap_or(DUMMY_SP));
+            markdown::find_testable_code(&doc,
+                                         self.collector,
+                                         attrs.span.unwrap_or(DUMMY_SP),
+                                         Some(self.sess));
         }
 
         nested(self);
@@ -825,6 +828,24 @@ fn main() {
         assert_eq!(output, (expected, 2));
     }
 
+    #[test]
+    fn make_test_manual_extern_crate_with_macro_use() {
+        let opts = TestOptions::default();
+        let input =
+"#[macro_use] extern crate asdf;
+use asdf::qwop;
+assert_eq!(2+2, 4);";
+        let expected =
+"#![allow(unused)]
+#[macro_use] extern crate asdf;
+fn main() {
+use asdf::qwop;
+assert_eq!(2+2, 4);
+}".to_string();
+        let output = make_test(input, Some("asdf"), false, &opts);
+        assert_eq!(output, (expected, 2));
+    }
+
     #[test]
     fn make_test_opts_attrs() {
         //if you supplied some doctest attributes with #![doc(test(attr(...)))], it will use those
index 0837ff91c142d658aa5b68c967c3bdb20a9e9dce..6472edb0aa7d3981c8629d98185955c0244f1d89 100644 (file)
@@ -52,6 +52,7 @@
 ///
 /// [combining character]: https://en.wikipedia.org/wiki/Combining_character
 #[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
 pub trait AsciiExt {
     /// Container type for copied ASCII characters.
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -84,6 +85,7 @@ pub trait AsciiExt {
     /// [`make_ascii_uppercase`]: #tymethod.make_ascii_uppercase
     /// [`str::to_uppercase`]: ../primitive.str.html#method.to_uppercase
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[allow(deprecated)]
     fn to_ascii_uppercase(&self) -> Self::Owned;
 
     /// Makes a copy of the value in its ASCII lower case equivalent.
@@ -104,6 +106,7 @@ pub trait AsciiExt {
     /// [`make_ascii_lowercase`]: #tymethod.make_ascii_lowercase
     /// [`str::to_lowercase`]: ../primitive.str.html#method.to_lowercase
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[allow(deprecated)]
     fn to_ascii_lowercase(&self) -> Self::Owned;
 
     /// Checks that two values are an ASCII case-insensitive match.
@@ -162,6 +165,7 @@ pub trait AsciiExt {
     /// This method will be deprecated in favor of the identically-named
     /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
     fn is_ascii_alphabetic(&self) -> bool { unimplemented!(); }
 
     /// Checks if the value is an ASCII uppercase character:
@@ -174,6 +178,7 @@ pub trait AsciiExt {
     /// This method will be deprecated in favor of the identically-named
     /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
     fn is_ascii_uppercase(&self) -> bool { unimplemented!(); }
 
     /// Checks if the value is an ASCII lowercase character:
@@ -186,6 +191,7 @@ pub trait AsciiExt {
     /// This method will be deprecated in favor of the identically-named
     /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
     fn is_ascii_lowercase(&self) -> bool { unimplemented!(); }
 
     /// Checks if the value is an ASCII alphanumeric character:
@@ -199,6 +205,7 @@ pub trait AsciiExt {
     /// This method will be deprecated in favor of the identically-named
     /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
     fn is_ascii_alphanumeric(&self) -> bool { unimplemented!(); }
 
     /// Checks if the value is an ASCII decimal digit:
@@ -211,6 +218,7 @@ pub trait AsciiExt {
     /// This method will be deprecated in favor of the identically-named
     /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
     fn is_ascii_digit(&self) -> bool { unimplemented!(); }
 
     /// Checks if the value is an ASCII hexadecimal digit:
@@ -224,6 +232,7 @@ pub trait AsciiExt {
     /// This method will be deprecated in favor of the identically-named
     /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
     fn is_ascii_hexdigit(&self) -> bool { unimplemented!(); }
 
     /// Checks if the value is an ASCII punctuation character:
@@ -241,6 +250,7 @@ pub trait AsciiExt {
     /// This method will be deprecated in favor of the identically-named
     /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
     fn is_ascii_punctuation(&self) -> bool { unimplemented!(); }
 
     /// Checks if the value is an ASCII graphic character:
@@ -253,6 +263,7 @@ pub trait AsciiExt {
     /// This method will be deprecated in favor of the identically-named
     /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
     fn is_ascii_graphic(&self) -> bool { unimplemented!(); }
 
     /// Checks if the value is an ASCII whitespace character:
@@ -282,6 +293,7 @@ pub trait AsciiExt {
     /// This method will be deprecated in favor of the identically-named
     /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
     fn is_ascii_whitespace(&self) -> bool { unimplemented!(); }
 
     /// Checks if the value is an ASCII control character:
@@ -294,6 +306,7 @@ pub trait AsciiExt {
     /// This method will be deprecated in favor of the identically-named
     /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
     fn is_ascii_control(&self) -> bool { unimplemented!(); }
 }
 
@@ -354,6 +367,7 @@ fn is_ascii_control(&self) -> bool { self.is_ascii_control() }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
+#[allow(deprecated)]
 impl AsciiExt for u8 {
     type Owned = u8;
 
@@ -362,6 +376,7 @@ impl AsciiExt for u8 {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
+#[allow(deprecated)]
 impl AsciiExt for char {
     type Owned = char;
 
@@ -370,6 +385,7 @@ impl AsciiExt for char {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
+#[allow(deprecated)]
 impl AsciiExt for [u8] {
     type Owned = Vec<u8>;
 
@@ -427,6 +443,7 @@ fn is_ascii_control(&self) -> bool {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
+#[allow(deprecated)]
 impl AsciiExt for str {
     type Owned = String;
 
index 9250c1c437b2a639bd66a19d4623d86924d94dbf..ccaa19acc8379eaaa68424656281cf5cac597409 100644 (file)
@@ -168,8 +168,36 @@ pub fn get_mut(&mut self) -> &mut R { &mut self.inner }
     /// # }
     /// ```
     #[unstable(feature = "bufreader_is_empty", issue = "45323", reason = "recently added")]
+    #[rustc_deprecated(since = "1.26.0", reason = "use .buffer().is_empty() instead")]
     pub fn is_empty(&self) -> bool {
-        self.pos == self.cap
+        self.buffer().is_empty()
+    }
+
+    /// Returns a reference to the internally buffered data.
+    ///
+    /// Unlike `fill_buf`, this will not attempt to fill the buffer if it is empty.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # #![feature(bufreader_buffer)]
+    /// use std::io::{BufReader, BufRead};
+    /// use std::fs::File;
+    ///
+    /// # fn foo() -> std::io::Result<()> {
+    /// let f = File::open("log.txt")?;
+    /// let mut reader = BufReader::new(f);
+    /// assert!(reader.buffer().is_empty());
+    ///
+    /// if reader.fill_buf()?.len() > 0 {
+    ///     assert!(!reader.buffer().is_empty());
+    /// }
+    /// # Ok(())
+    /// # }
+    /// ```
+    #[unstable(feature = "bufreader_buffer", issue = "45323")]
+    pub fn buffer(&self) -> &[u8] {
+        &self.buf[self.pos..self.cap]
     }
 
     /// Unwraps this `BufReader`, returning the underlying reader.
index 70a1f82c9a159be64737616e48735449558841b1..62bef4bc49913dd49371705c669322c95ebf4d53 100644 (file)
 #![feature(fn_traits)]
 #![feature(fnbox)]
 #![feature(generic_param_attrs)]
-#![feature(hashmap_hasher)]
+#![feature(hashmap_internals)]
 #![feature(heap_api)]
 #![feature(i128)]
 #![feature(i128_type)]
 #![feature(raw)]
 #![feature(rustc_attrs)]
 #![feature(stdsimd)]
-#![feature(sip_hash_13)]
 #![feature(slice_bytes)]
 #![feature(slice_concat_ext)]
 #![feature(slice_internals)]
index a2c133954a3279695e3249cee369bcfdf3561c96..33d7053852246a9bf4c63d02d94682f989f888ba 100644 (file)
@@ -169,7 +169,6 @@ fn $test_name() {
 
     macro_rules! test_checked_next_power_of_two {
         ($test_name:ident, $T:ident) => (
-            #[cfg_attr(target_os = "emscripten", ignore)] // FIXME(#39119)
             fn $test_name() {
                 #![test]
                 assert_eq!((0 as $T).checked_next_power_of_two(), Some(1));
index f1ab9c4760965e38efcf59dbb4b98ebd603dcca9..afa8e3e1369354f370d5cbf5442b09dd2f3ef53b 100644 (file)
@@ -10,7 +10,6 @@
 
 #![unstable(feature = "process_internals", issue = "0")]
 
-use ascii::AsciiExt;
 use collections::BTreeMap;
 use env::split_paths;
 use env;
index 9fff8b91f96f32f155f8f9378e515e785ee56b1e..78b2bb5fe6e2f9213f1886922e8d7e19f0c2edae 100644 (file)
@@ -27,7 +27,6 @@
 
 use core::str::next_code_point;
 
-use ascii::*;
 use borrow::Cow;
 use char;
 use fmt;
@@ -871,24 +870,22 @@ fn hash<H: Hasher>(&self, state: &mut H) {
     }
 }
 
-impl AsciiExt for Wtf8 {
-    type Owned = Wtf8Buf;
-
-    fn is_ascii(&self) -> bool {
+impl Wtf8 {
+    pub fn is_ascii(&self) -> bool {
         self.bytes.is_ascii()
     }
-    fn to_ascii_uppercase(&self) -> Wtf8Buf {
+    pub fn to_ascii_uppercase(&self) -> Wtf8Buf {
         Wtf8Buf { bytes: self.bytes.to_ascii_uppercase() }
     }
-    fn to_ascii_lowercase(&self) -> Wtf8Buf {
+    pub fn to_ascii_lowercase(&self) -> Wtf8Buf {
         Wtf8Buf { bytes: self.bytes.to_ascii_lowercase() }
     }
-    fn eq_ignore_ascii_case(&self, other: &Wtf8) -> bool {
+    pub 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() }
+    pub fn make_ascii_uppercase(&mut self) { self.bytes.make_ascii_uppercase() }
+    pub fn make_ascii_lowercase(&mut self) { self.bytes.make_ascii_lowercase() }
 }
 
 #[cfg(test)]
index 3bf735ee868037f96feeb19c59b306d42583e959..7214203830e7457b1bea2c1317779bc7cbd8d4a2 100644 (file)
@@ -1,7 +1,9 @@
-NB: This crate is part of the Rust compiler. For an overview of the
-compiler as a whole, see
-[the README.md file found in `librustc`](../librustc/README.md).
-
 The `syntax` crate contains those things concerned purely with syntax
 â€“ that is, the AST ("abstract syntax tree"), parser, pretty-printer,
 lexer, macro expander, and utilities for traversing ASTs.
+
+For more information about how these things work in rustc, see the
+rustc guide:
+
+- [Parsing](https://rust-lang-nursery.github.io/rustc-guide/the-parser.html)
+- [Macro Expansion](https://rust-lang-nursery.github.io/rustc-guide/macro-expansion.html)
index a1aec0520885922fe5e2539be3c9f033b95d4ce4..73924c4270e669706b2fc027bff54c3fb4a9bce6 100644 (file)
@@ -597,21 +597,6 @@ pub fn span_to_prev_source(&self, sp: Span) -> Result<String, SpanSnippetError>
         self.span_to_source(sp, |src, start_index, _| src[..start_index].to_string())
     }
 
-    /// Given a `Span`, try to get a shorter span ending before the first occurrence of `c` `char`
-    pub fn span_until_char(&self, sp: Span, c: char) -> Span {
-        match self.span_to_snippet(sp) {
-            Ok(snippet) => {
-                let snippet = snippet.split(c).nth(0).unwrap_or("").trim_right();
-                if !snippet.is_empty() && !snippet.contains('\n') {
-                    sp.with_hi(BytePos(sp.lo().0 + snippet.len() as u32))
-                } else {
-                    sp
-                }
-            }
-            _ => sp,
-        }
-    }
-
     /// Extend the given `Span` to just after the previous occurrence of `c`. Return the same span
     /// if no character could be found or if an error occurred while retrieving the code snippet.
     pub fn span_extend_to_prev_char(&self, sp: Span, c: char) -> Span {
@@ -646,26 +631,50 @@ pub fn span_extend_to_prev_str(&self, sp: Span, pat: &str, accept_newlines: bool
         sp
     }
 
+    /// Given a `Span`, try to get a shorter span ending before the first occurrence of `c` `char`
+    pub fn span_until_char(&self, sp: Span, c: char) -> Span {
+        match self.span_to_snippet(sp) {
+            Ok(snippet) => {
+                let snippet = snippet.split(c).nth(0).unwrap_or("").trim_right();
+                if !snippet.is_empty() && !snippet.contains('\n') {
+                    sp.with_hi(BytePos(sp.lo().0 + snippet.len() as u32))
+                } else {
+                    sp
+                }
+            }
+            _ => sp,
+        }
+    }
+
+    /// Given a `Span`, try to get a shorter span ending just after the first occurrence of `char`
+    /// `c`.
+    pub fn span_through_char(&self, sp: Span, c: char) -> Span {
+        if let Ok(snippet) = self.span_to_snippet(sp) {
+            if let Some(offset) = snippet.find(c) {
+                return sp.with_hi(BytePos(sp.lo().0 + (offset + c.len_utf8()) as u32));
+            }
+        }
+        sp
+    }
+
     /// Given a `Span`, get a new `Span` covering the first token and all its trailing whitespace or
     /// the original `Span`.
     ///
     /// If `sp` points to `"let mut x"`, then a span pointing at `"let "` will be returned.
     pub fn span_until_non_whitespace(&self, sp: Span) -> Span {
-        if let Ok(snippet) = self.span_to_snippet(sp) {
-            let mut offset = 0;
-            // get the bytes width of all the non-whitespace characters
-            for c in snippet.chars().take_while(|c| !c.is_whitespace()) {
-                offset += c.len_utf8();
-            }
-            // get the bytes width of all the whitespace characters after that
-            for c in snippet[offset..].chars().take_while(|c| c.is_whitespace()) {
-                offset += c.len_utf8();
+        let mut whitespace_found = false;
+
+        self.span_take_while(sp, |c| {
+            if !whitespace_found && c.is_whitespace() {
+                whitespace_found = true;
             }
-            if offset > 1 {
-                return sp.with_hi(BytePos(sp.lo().0 + offset as u32));
+
+            if whitespace_found && !c.is_whitespace() {
+                false
+            } else {
+                true
             }
-        }
-        sp
+        })
     }
 
     /// Given a `Span`, get a new `Span` covering the first token without its trailing whitespace or
@@ -673,28 +682,23 @@ pub fn span_until_non_whitespace(&self, sp: Span) -> Span {
     ///
     /// If `sp` points to `"let mut x"`, then a span pointing at `"let"` will be returned.
     pub fn span_until_whitespace(&self, sp: Span) -> Span {
-        if let Ok(snippet) = self.span_to_snippet(sp) {
-            let mut offset = 0;
-            // Get the bytes width of all the non-whitespace characters
-            for c in snippet.chars().take_while(|c| !c.is_whitespace()) {
-                offset += c.len_utf8();
-            }
-            if offset > 1 {
-                return sp.with_hi(BytePos(sp.lo().0 + offset as u32));
-            }
-        }
-        sp
+        self.span_take_while(sp, |c| !c.is_whitespace())
     }
 
-    /// Given a `Span`, try to get a shorter span ending just after the first occurrence of `char`
-    /// `c`.
-    pub fn span_through_char(&self, sp: Span, c: char) -> Span {
+    /// Given a `Span`, get a shorter one until `predicate` yields false.
+    pub fn span_take_while<P>(&self, sp: Span, predicate: P) -> Span
+        where P: for <'r> FnMut(&'r char) -> bool
+    {
         if let Ok(snippet) = self.span_to_snippet(sp) {
-            if let Some(offset) = snippet.find(c) {
-                return sp.with_hi(BytePos(sp.lo().0 + (offset + c.len_utf8()) as u32));
-            }
+            let offset = snippet.chars()
+                .take_while(predicate)
+                .map(|c| c.len_utf8())
+                .sum::<usize>();
+
+            sp.with_hi(BytePos(sp.lo().0 + (offset as u32)))
+        } else {
+            sp
         }
-        sp
     }
 
     pub fn def_span(&self, sp: Span) -> Span {
index fa600cd686064a796a392d43a6250597581a14bc..915396d29fe26c6ebaa96953b12c1aacd199ac55 100644 (file)
@@ -145,7 +145,6 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
     // rustc internal
     (active, rustc_diagnostic_macros, "1.0.0", None, None),
     (active, rustc_const_unstable, "1.0.0", None, None),
-    (active, advanced_slice_patterns, "1.0.0", Some(23121), None),
     (active, box_syntax, "1.0.0", Some(27779), None),
     (active, placement_in_syntax, "1.0.0", Some(27779), None),
     (active, unboxed_closures, "1.0.0", Some(29625), None),
@@ -474,6 +473,8 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
     (removed, allocator, "1.0.0", None, None),
     // Allows the `#[simd]` attribute -- removed in favor of `#[repr(simd)]`
     (removed, simd, "1.0.0", Some(27731), None),
+    // Merged into `slice_patterns`
+    (removed, advanced_slice_patterns, "1.0.0", Some(23121), None),
 );
 
 declare_features! (
@@ -1655,17 +1656,10 @@ fn visit_arm(&mut self, arm: &'a ast::Arm) {
 
     fn visit_pat(&mut self, pattern: &'a ast::Pat) {
         match pattern.node {
-            PatKind::Slice(_, Some(_), ref last) if !last.is_empty() => {
-                gate_feature_post!(&self, advanced_slice_patterns,
-                                  pattern.span,
-                                  "multiple-element slice matches anywhere \
-                                   but at the end of a slice (e.g. \
-                                   `[0, ..xs, 0]`) are experimental")
-            }
-            PatKind::Slice(..) => {
+            PatKind::Slice(_, Some(ref subslice), _) => {
                 gate_feature_post!(&self, slice_patterns,
-                                  pattern.span,
-                                  "slice pattern syntax is experimental");
+                                   subslice.span,
+                                   "syntax for subslices in slice patterns is not yet stabilized");
             }
             PatKind::Box(..) => {
                 gate_feature_post!(&self, box_patterns,
index 053746b579dcb31508741c0711cee871698f3081..4c3f42d9c6b7d4c2f94406de5f05ed0e6e7843e9 100644 (file)
@@ -90,7 +90,7 @@ fn parse_attribute_with_inner_parse_policy(&mut self,
         debug!("parse_attribute_with_inner_parse_policy: inner_parse_policy={:?} self.token={:?}",
                inner_parse_policy,
                self.token);
-        let (span, path, tokens, mut style) = match self.token {
+        let (span, path, tokens, style) = match self.token {
             token::Pound => {
                 let lo = self.span;
                 self.bump();
@@ -129,15 +129,6 @@ fn parse_attribute_with_inner_parse_policy(&mut self,
             }
         };
 
-        if inner_parse_policy == InnerAttributeParsePolicy::Permitted &&
-           self.token == token::Semi {
-            self.bump();
-            self.span_warn(span,
-                           "this inner attribute syntax is deprecated. The new syntax is \
-                            `#![foo]`, with a bang and no semicolon");
-            style = ast::AttrStyle::Inner;
-        }
-
         Ok(ast::Attribute {
             id: attr::mk_attr_id(),
             style,
index f7e5d40b52468821e79a28e324a01cdd866fdb1f..202dc03eaa41d511452cb28880e194460d610dc9 100644 (file)
@@ -298,7 +298,6 @@ pub fn str_lit(lit: &str, diag: Option<(Span, &Handler)>) -> String {
     debug!("parse_str_lit: given {}", escape_default(lit));
     let mut res = String::with_capacity(lit.len());
 
-    // FIXME #8372: This could be a for-loop if it didn't borrow the iterator
     let error = |i| format!("lexer should have rejected {} at {}", lit, i);
 
     /// Eat everything up to a non-whitespace
@@ -503,7 +502,6 @@ pub fn byte_lit(lit: &str) -> (u8, usize) {
 pub fn byte_str_lit(lit: &str) -> Lrc<Vec<u8>> {
     let mut res = Vec::with_capacity(lit.len());
 
-    // FIXME #8372: This could be a for-loop if it didn't borrow the iterator
     let error = |i| format!("lexer should have rejected {} at {}", lit, i);
 
     /// Eat everything up to a non-whitespace
index cb5010a638df4f67b899c06b824009c326d60415..6d8975197d55cba73ee654ddbedea6ee9d91423e 100644 (file)
@@ -3618,7 +3618,7 @@ fn parse_pat_vec_elements(
                         slice = Some(P(Pat {
                             id: ast::DUMMY_NODE_ID,
                             node: PatKind::Wild,
-                            span: self.span,
+                            span: self.prev_span,
                         }));
                         before_slice = false;
                     }
index 9edfa767d31958df8c0ff07e7850c49708c072b0..5264b627e96137b0b933adce4c3bdcab30115ae5 100644 (file)
@@ -628,8 +628,15 @@ fn path_node(ids: Vec<Ident>) -> ast::Path {
 }
 
 fn path_name_i(idents: &[Ident]) -> String {
-    // FIXME: Bad copies (#2543 -- same for everything else that says "bad")
-    idents.iter().map(|i| i.to_string()).collect::<Vec<String>>().join("::")
+    let mut path_name = "".to_string();
+    let mut idents_iter = idents.iter().peekable();
+    while let Some(ident) = idents_iter.next() {
+        path_name.push_str(&ident.name.as_str());
+        if let Some(_) = idents_iter.peek() {
+            path_name.push_str("::")
+        }
+    }
+    path_name
 }
 
 fn mk_tests(cx: &TestCtxt) -> P<ast::Item> {
@@ -682,7 +689,6 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> P<ast::Expr> {
     // gensym information.
 
     let span = ignored_span(cx, test.span);
-    let path = test.path.clone();
     let ecx = &cx.ext_cx;
     let self_id = ecx.ident_of("self");
     let test_id = ecx.ident_of("test");
@@ -694,10 +700,11 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> P<ast::Expr> {
     // creates $name: $expr
     let field = |name, expr| ecx.field_imm(span, ecx.ident_of(name), expr);
 
-    debug!("encoding {}", path_name_i(&path[..]));
-
     // path to the #[test] function: "foo::bar::baz"
-    let path_string = path_name_i(&path[..]);
+    let path_string = path_name_i(&test.path[..]);
+
+    debug!("encoding {}", path_string);
+
     let name_expr = ecx.expr_str(span, Symbol::intern(&path_string));
 
     // self::test::StaticTestName($name_expr)
@@ -744,7 +751,7 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> P<ast::Expr> {
             diag.bug("expected to find top-level re-export name, but found None");
         }
     };
-    visible_path.extend(path);
+    visible_path.extend_from_slice(&test.path[..]);
 
     // Rather than directly give the test function to the test
     // harness, we create a wrapper like one of the following:
index b9578386ce5bc209cfbdd3a034b4df253cb85e7e..96ec1e6834dff30aa0c129f31b3af9a41349369b 100644 (file)
@@ -12,7 +12,7 @@
 # source tarball for a stable release you'll likely see `1.x.0` for rustc and
 # `0.x.0` for Cargo where they were released on `date`.
 
-date: 2018-02-20
+date: 2018-03-18
 rustc: beta
 cargo: beta
 
index 707531bf376a7e870e353a757a66ee214db04b06..367d509cadfe3755e38ad0f17a79bbe3dfc80b3f 100644 (file)
@@ -19,6 +19,7 @@
 // ignore-mips
 // ignore-mips64
 // ignore-powerpc
+// ignore-powerpc64
 // ignore-s390x
 // ignore-sparc
 // ignore-wasm32
index 9bfe47d0a1f28b67fb5387ddb5e3ac7251a3dcce..d6dd3f356b5fe7b363d4799ab2f6c7eb75f45fb8 100644 (file)
@@ -23,6 +23,8 @@
 // ignore-mips
 // ignore-mips64
 // ignore-msp430
+// ignore-powerpc64
+// ignore-powerpc64le
 // ignore-powerpc
 // ignore-r600
 // ignore-amdgcn
index 94b69a6cab58344ab4e0d944edb7fc05f201f587..6b79e79fa0080df6e56c9c97fc9e60186e6ab24b 100644 (file)
@@ -19,6 +19,8 @@
 // ignore-mips
 // ignore-mips64
 // ignore-msp430
+// ignore-powerpc64
+// ignore-powerpc64le
 // ignore-powerpc
 // ignore-r600
 // ignore-amdgcn
index c3688077f221bb479a742a3c7434bdbc8feabaa7..3f73a1cabbf19630d0e2a583af34ca75860bafbb 100644 (file)
@@ -19,6 +19,8 @@
 // ignore-mips
 // ignore-mips64
 // ignore-msp430
+// ignore-powerpc64
+// ignore-powerpc64le
 // ignore-powerpc
 // ignore-r600
 // ignore-amdgcn
index 3b8fe43fa048a98819d817e6994f365281c23362..3e118a50d454e10dc0642dff7ce357e9afa250d9 100644 (file)
@@ -19,6 +19,8 @@
 // ignore-mips
 // ignore-mips64
 // ignore-msp430
+// ignore-powerpc64
+// ignore-powerpc64le
 // ignore-powerpc
 // ignore-r600
 // ignore-amdgcn
index 655e67cf7eefe543a230a2089b4dabf9c55138ad..2eeed2b788ce2f68154dfa32243aa51bc7a6fc2a 100644 (file)
@@ -14,6 +14,7 @@
 // ignore-mips
 // ignore-mips64
 // ignore-powerpc
+// ignore-powerpc64
 // See repr-transparent.rs
 
 #![crate_type="lib"]
index 1d08b8074658288f8a432c367dc1658eac41a391..fa475949b36b0e65612e92e4290e4f0686f948fc 100644 (file)
@@ -13,7 +13,6 @@
 //[mir]compile-flags: -Z borrowck=mir
 
 #![feature(slice_patterns)]
-#![feature(advanced_slice_patterns)]
 
 pub struct Foo {
   x: u32
index 32a573911ececba1563ab3300cb441c1f9a3ff30..30047f84041f14354f71ca1649ed24d71d72f278 100644 (file)
@@ -13,8 +13,6 @@
 
 // Test that immutable pattern bindings cannot be reassigned.
 
-#![feature(slice_patterns)]
-
 enum E {
     Foo(isize)
 }
index e01161734623217ecd2dc7c2bf104c358877575a..0db31cef0ed777b3a3358b91251f58ec421f957e 100644 (file)
@@ -11,7 +11,8 @@
 // revisions: ast mir
 //[mir]compile-flags: -Z borrowck=mir
 
-#![feature(box_syntax, slice_patterns, advanced_slice_patterns)]
+#![feature(box_syntax)]
+#![feature(slice_patterns)]
 
 fn move_out_from_begin_and_end() {
     let a = [box 1, box 2];
index eb5d69d49bd6aad72ef826606ed5bda7327f2972..0fd6923326ab3eb7a56b503e667811f1bfbd0c80 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(advanced_slice_patterns)]
 #![feature(slice_patterns)]
 
 fn a<'a>() -> &'a [isize] {
index 4df1e24dcfbd53c05d12653f63e47e5a37dd8b45..1b9af393ccce473bfce789a75af2b8c6058aa70c 100644 (file)
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 #![feature(slice_patterns)]
-#![allow(unused_variables)]
 #![deny(unreachable_patterns)]
 
 fn main() {
index 6885c8d94c6b4fd16535103a91fa52bca135d372..fe7fbb176cc5e61adf95be6680d92539f3ccd8c4 100644 (file)
@@ -10,8 +10,6 @@
 
 // compile-flags:-Z verbose
 
-#![feature(slice_patterns)]
-
 fn main() {
     let x = [1,2];
     let y = match x {
index 82e82df31861ff35ab4a4fe913be379ebab96bda..32a63b79a32dd093cb845c688d72d8378cc7f7c2 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(slice_patterns)]
-
 fn main() {
   let x = [1,2];
   let y = match x {
index d0964d2aabea755357b9af916f00c127a642808d..1cdd803971b4bfd06c9259d7d86e48de8c8b743f 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(slice_patterns)]
-
 fn main() {
     let values: Vec<u8> = vec![1,2,3,4,5,6,7,8];
 
index ac85e43cf4f0557e38e826929debb914bf621d05..bdd502d442036bf751a32fe291c2fe704628fa76 100644 (file)
@@ -10,7 +10,6 @@
 
 // Matching against float literals should result in a linter error
 
-#![feature(slice_patterns)]
 #![feature(exclusive_range_pattern)]
 #![allow(unused)]
 #![forbid(illegal_floating_point_literal_pattern)]
index 9191dfa155c657d9dfc3813556ab36717c9a88a2..fffa27ab842ad43864ea07a15653467d510ec6c4 100644 (file)
@@ -10,7 +10,6 @@
 
 // Matching against NaN should result in a warning
 
-#![feature(slice_patterns)]
 #![allow(unused)]
 #![deny(illegal_floating_point_literal_pattern)]
 
index ad7e931a0ec9723999b7d5ba6fd2d1ea9c9337b3..abb770df107f12edc1c8c62d3c6eb82654496ccc 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(advanced_slice_patterns, slice_patterns)]
-
 fn main() {
     let buf = &[0, 1, 2, 3];
 
index 1ff07eae1c9c03a654d9cef0f63d7718df1ea873..9db4319b786821b2d205fb52dbb58ada2193be9a 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(advanced_slice_patterns, slice_patterns)]
+#![feature(slice_patterns)]
 #![deny(unreachable_patterns)]
 
 fn main() {
index 1cdbba17f658ad9501169068232e68ce3774af1a..cb8f8fad532fa2569d246d0a0c4e37af33ad555b 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(slice_patterns)]
 #![deny(unreachable_patterns)]
 
 // The arity of `ref x` is always 1. If the pattern is compared to some non-structural type whose
index fd4bd1c7b944b7b879e3160f3e1a89cf65cc0dd4..a8ec95da3d872c2a85c5068829c46f8da84b68a4 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(advanced_slice_patterns, slice_patterns)]
+#![feature(slice_patterns)]
 
 fn check(list: &[Option<()>]) {
     match list {
index dd9379c756d12a147d56d9a71c5e1308cb516d91..05971d70167bd39bbf94ecbafd97efb35635f9cb 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(slice_patterns)]
 #![deny(unreachable_patterns)]
 
 fn a() {
index 375d855d1fd31e6edae51647b965f13dec2e370f..52c5375f4e7d1179a19363c3ec54356d4af70619 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(slice_patterns)]
-
 fn main() {
     match () {
         [()] => { }
index 472b054b08777c19df99f71d58823864232199c9..d6e3fdbe088445272b6049665c356161953c2014 100644 (file)
@@ -10,7 +10,6 @@
 
 #![feature(slice_patterns)]
 #![deny(unreachable_patterns)]
-#![allow(unused_variables)]
 
 fn main() {
     let x: Vec<(isize, isize)> = Vec::new();
index 9ca9e0984e47668d2ed62315a6ad28062666b7e0..5efbef549ddcade388c35100db81bf9515bf978f 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(slice_patterns, box_patterns)]
+#![feature(box_patterns)]
 
 struct A;
 
index 8e83177090bb5223133a40c4b203fad65c2d1184..3401dd1becdd8b141dd5e8940e1af672ac7e68f2 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(slice_patterns)]
-
 fn assert_static<T: 'static>(_t: T) {}
 
 fn main() {
index 0c3ea53a903ae9062c03098e6ee2838a975b4a1a..1d3f8ff12d865650156ba18f24d64215e2e3e988 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(slice_patterns)]
-
 enum Void {}
 
 fn main() {
index 9f943f08232d673470cde1b68e5bec664b202ae4..e130df5c845b58fc309e50e3f2b0208e59427f53 100644 (file)
@@ -9,9 +9,9 @@
 // except according to those terms.
 
 #![feature(box_patterns)]
-#![feature(slice_patterns)]
 #![feature(box_syntax)]
 #![feature(exhaustive_patterns)]
+#![feature(slice_patterns)]
 #![deny(unreachable_patterns)]
 
 mod foo {
diff --git a/src/test/incremental/extern_static/issue-49153.rs b/src/test/incremental/extern_static/issue-49153.rs
new file mode 100644 (file)
index 0000000..e0538e0
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2018 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.
+
+// https://github.com/rust-lang/rust/issues/49153
+
+// revisions:rpass1 rpass2
+
+extern "C" {
+    pub static __ImageBase: u8;
+}
+
+pub static FOO: &'static u8 = unsafe { &__ImageBase };
+
+fn main() {}
diff --git a/src/test/incremental/issue-49043.rs b/src/test/incremental/issue-49043.rs
new file mode 100644 (file)
index 0000000..118027b
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2016 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 hashing involving canonical variables.  In this
+// test -- which has an intensional error -- the type of the value
+// being dropped winds up including a type variable. Canonicalization
+// would then produce a `?0` which -- in turn -- triggered an ICE in
+// hashing.
+
+// revisions:cfail1
+
+fn main() {
+    println!("Hello, world! {}",*thread_rng().choose(&[0, 1, 2, 3]).unwrap());
+    //[cfail1]~^ ERROR cannot find function `thread_rng`
+}
diff --git a/src/test/incremental/static_refering_to_other_static/issue-49081.rs b/src/test/incremental/static_refering_to_other_static/issue-49081.rs
new file mode 100644 (file)
index 0000000..6345b45
--- /dev/null
@@ -0,0 +1,18 @@
+// Copyright 2018 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.
+
+// https://github.com/rust-lang/rust/issues/49081
+
+// revisions:rpass1 rpass2
+
+pub static A: i32 = 42;
+pub static B: &i32 = &A;
+
+fn main() {}
index 405864aba94365fb85c895a2665553d58978c092..d621cdb4d58f8c89d5f3791f581963cca37f624d 100644 (file)
@@ -36,7 +36,7 @@ fn foo<F>(f: F) where F: FnOnce() -> i32 {
 //    let _2: &'21_1rs D;
 //    ...
 //    let mut _3: ();
-//    let mut _4: [closure@NodeId(22) r:&'21_1rs D];
+//    let mut _4: [closure@NodeId(22) r:&'19s D];
 //    let mut _5: &'21_1rs D;
 //    bb0: {
 //        StorageLive(_1);
@@ -54,6 +54,7 @@ fn foo<F>(f: F) where F: FnOnce() -> i32 {
 //        resume;
 //    }
 //    bb2: {
+//        EndRegion('19s);
 //        StorageDead(_4);
 //        _0 = ();
 //        EndRegion('21_1rs);
@@ -61,6 +62,7 @@ fn foo<F>(f: F) where F: FnOnce() -> i32 {
 //        drop(_1) -> [return: bb4, unwind: bb1];
 //    }
 //    bb3: {
+//        EndRegion('19s);
 //        EndRegion('21_1rs);
 //        drop(_1) -> bb1;
 //    }
@@ -72,7 +74,7 @@ fn foo<F>(f: F) where F: FnOnce() -> i32 {
 // END rustc.main.SimplifyCfg-qualify-consts.after.mir
 
 // START rustc.main-{{closure}}.SimplifyCfg-qualify-consts.after.mir
-// fn main::{{closure}}(_1: [closure@NodeId(22) r:&'21_1rs D]) -> i32 {
+// fn main::{{closure}}(_1: [closure@NodeId(22) r:&'19s D]) -> i32 {
 //     let mut _0: i32;
 //     let mut _2: i32;
 //
index 482b69a59ddbc1bcdd34a065f669194081758001..fa5f62f89f63cd88451a94e2493dd671425352d8 100644 (file)
@@ -8,7 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(box_syntax, slice_patterns, advanced_slice_patterns)]
+#![feature(box_syntax)]
+#![feature(slice_patterns)]
 
 fn move_out_from_end() {
     let a = [box 1, box 2];
index d9103e1992735eda23ea2bfeeeb7984996f20edd..af1707de6c02f52432cfc241cca0df4f9e06ad70 100644 (file)
@@ -9,7 +9,7 @@ RUSTC_ORIGINAL := $(RUSTC)
 BARE_RUSTC := $(HOST_RPATH_ENV) '$(RUSTC)'
 BARE_RUSTDOC := $(HOST_RPATH_ENV) '$(RUSTDOC)'
 RUSTC := $(BARE_RUSTC) --out-dir $(TMPDIR) -L $(TMPDIR) $(RUSTFLAGS)
-RUSTDOC := $(BARE_RUSTDOC)
+RUSTDOC := $(BARE_RUSTDOC) -L $(TARGET_RPATH_DIR)
 ifdef RUSTC_LINKER
 RUSTC := $(RUSTC) -Clinker=$(RUSTC_LINKER)
 RUSTDOC := $(RUSTDOC) --linker $(RUSTC_LINKER) -Z unstable-options
index 26419a51513f2f9e7498e8d0f5cc10d4f7e1389e..17cf39372c0e4986fe128b4de0bbaa1013ceff61 100644 (file)
@@ -12,7 +12,6 @@
 
 #![crate_type="dylib"]
 #![feature(plugin_registrar, rustc_private)]
-#![feature(slice_patterns)]
 
 extern crate syntax;
 extern crate syntax_pos;
index 9ae4f2c1e70853cf887cab3b13e280e5b3adfdeb..d59fe8d813d249af0e9d4782519299c9d6b745a5 100644 (file)
@@ -8,9 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
-
-
+// ignore-emscripten apparently blows the stack
 
 fn f(x: isize) -> isize {
     if x == 1 { return 1; } else { let y: isize = 1 + f(x - 1); return y; }
index 0d24f0bd0d7b32cc1ae645a633e87c6ad8a070d3..43271162c18125b0f4d7b3e27e393639c941bb99 100644 (file)
@@ -11,9 +11,6 @@
 // Ensure that we can do a destructuring bind of a fixed-size array,
 // even when the element type has a destructor.
 
-
-#![feature(slice_patterns)]
-
 struct D { x: u8 }
 
 impl Drop for D { fn drop(&mut self) { } }
index 4d0bd3f3412f1f7fd0933363af3779e4b0cd4807..1f543f7be0e8fb24dd95aa659021ed7d1a4b42ce 100644 (file)
@@ -13,7 +13,8 @@
 
 // ignore-wasm32-bare compiled with panic=abort by default
 
-#![feature(generators, generator_trait, untagged_unions, slice_patterns, advanced_slice_patterns)]
+#![feature(generators, generator_trait, untagged_unions)]
+#![feature(slice_patterns)]
 
 use std::cell::{Cell, RefCell};
 use std::ops::Generator;
index 80ab12482cbb7821c77e4dd5817a2eda40dfa326..d44f78922c70221b410ae3dcc47d87ccaf0fc082 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-emscripten no i128 support
+
 #![feature(i128_type)]
 #![deny(const_err)]
 
index 711f2dd6c66763db9aed1ba10bfc4b37688efb99..c14f3dc72916d6e26b0e03510691cf05b55cefae 100644 (file)
@@ -10,7 +10,6 @@
 
 // pretty-expanded FIXME #23616
 
-#![feature(advanced_slice_patterns)]
 #![feature(slice_patterns)]
 
 struct Foo(isize, isize, isize, isize);
@@ -20,11 +19,11 @@ pub fn main() {
     let Foo(..) = Foo(5, 5, 5, 5);
     let Foo(..) = Foo(5, 5, 5, 5);
     let Bar{..} = Bar{a: 5, b: 5, c: 5, d: 5};
-    //let (..) = (5, 5, 5, 5);
-    //let Foo(a, b, ..) = Foo(5, 5, 5, 5);
-    //let Foo(.., d) = Foo(5, 5, 5, 5);
-    //let (a, b, ..) = (5, 5, 5, 5);
-    //let (.., c, d) = (5, 5, 5, 5);
+    let (..) = (5, 5, 5, 5);
+    let Foo(a, b, ..) = Foo(5, 5, 5, 5);
+    let Foo(.., d) = Foo(5, 5, 5, 5);
+    let (a, b, ..) = (5, 5, 5, 5);
+    let (.., c, d) = (5, 5, 5, 5);
     let Bar{b: b, ..} = Bar{a: 5, b: 5, c: 5, d: 5};
     match [5, 5, 5, 5] {
         [..] => { }
index bfa3a1e128a9a3e97948d0e8a8b3c41bc28483dc..cdfad51e648a3b03f65d0843686bb5e1673ba5d1 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-emscripten no i128 support
+
 #![feature(intrinsics, i128_type)]
 
 mod rusti {
index a2c55634749cbfef24f225727b07a2af0f74577a..5132405a9d583a00ed4a0d8850878500817bacb5 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-emscripten fma not implemented in emscripten
+
 macro_rules! assert_approx_eq {
     ($a:expr, $b:expr) => ({
         let (a, b) = (&$a, &$b);
index eb2177202a22b526240471c39bec9acfd6e0109c..d3ba477fa573e7ca9937253deb520ac8f0adcc72 100644 (file)
@@ -10,8 +10,6 @@
 
 // pretty-expanded FIXME #23616
 
-use std::ascii::AsciiExt;
-
 static NAME: &'static str = "hello world";
 
 fn main() {
index 14987484711792ea44275d6236af8894a8a334a2..d28ea94ec1a0dfc7f038926c419e423350cac6fe 100644 (file)
@@ -12,8 +12,6 @@
 // Tests that match expression handles overlapped literal and range
 // properly in the presence of guard function.
 
-#![feature(slice_patterns)]
-
 fn val() -> usize { 1 }
 
 static CONST: usize = 1;
index 14e003788469860bee538052bca30a52c53cc016..59267f79e26437d7f07cfde026daac7b4bbb5237 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
 #![feature(slice_patterns)]
 
 fn main() {
index 508360cb70110a96ac10973133548c07053a1afc..2878f2795c5904e1f32f93bc4859ca8da9e6ac33 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
 #![feature(slice_patterns)]
 
 fn main() {
index e1b94179764bf8fbe6bfa3ad3516e603955ad1c9..bf272308fa9dfb50f332ee37262243723784f3ba 100644 (file)
@@ -8,9 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
-#![feature(slice_patterns)]
-
 fn main() {
     let x: (isize, &[isize]) = (2, &[1, 2]);
     assert_eq!(match x {
index 6c87e8d35fbf0643c1402c409329ad64d4aa4ab3..d3fe0903a1d6440c3711c45ea462169e74a82887 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
 #![feature(slice_patterns)]
 
 fn main() {
index 3f7d0400c884e953d67835ccd91dc74005cd7457..29a5f6dd24bd0c0f874fc32fb33c9461e33b25b0 100644 (file)
@@ -10,7 +10,6 @@
 
 // Test that a field can have the same name in different variants
 // of an enum
-// FIXME #27889
 
 pub enum Foo {
     X { foo: u32 },
index 8c73830f4d7788bb173162eff80521ecab74e851..e21e487fedd1c81d5618a491e3530b3a75f99907 100644 (file)
@@ -45,7 +45,7 @@ struct Array<T> {
     f32: [T; 32],
 }
 
-// FIXME(#7622): merge with `Array` once `[T; N]: Clone` where `T: Clone`
+// FIXME(#44580): merge with `Array` once `[T; N]: Clone` where `T: Clone`
 #[derive(Clone, Copy)]
 struct CopyArray<T: Copy> {
     f00: [T; 00],
index d0fef36efb9cd93c8e294b9e525081fa981765dc..d059a46b4df123d3456d2b2e26ec3f1c99ed6e1a 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-emscripten FIXME(#45351)
+
 #![feature(repr_simd, test)]
 
 extern crate test;
index d32d2fc295440ed12a65be3558fa0c41bb279a05..e97c8d9f4176cd6b2e85ff19713a234f02fe3c3c 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(advanced_slice_patterns, slice_patterns)]
+#![feature(slice_patterns)]
 
 fn check(list: &[u8]) {
     match list {
index 489d35e9147ad2a31b55fc2007247b1bfb9db02f..dd6ccec973fc0926273db5822bd8946bb26417c3 100644 (file)
@@ -10,8 +10,6 @@
 
 // Check that constant ADTs are translated OK, part k of N.
 
-#![feature(slice_patterns)]
-
 enum Bar {
     C
 }
index 5c9a63b861663d0fd175703b06ee5cf971f9a177..2368ba8a110be28206c27beeb03b7b2a77bab0b4 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-emscripten FIXME(#45351)
+
 #![feature(platform_intrinsics, repr_simd)]
 
 extern "platform-intrinsic" {
index f90696e3cdf16b1d120e0306de6a625cabc3c5be..9873a8c2bf44f8eba4f6b5a1c534dc7d8e73dbb9 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-emscripten FIXME(#45351)
+
 #![feature(repr_simd, platform_intrinsics)]
 
 #[repr(C)]
index d864d55c93972140775283ab64eedf5722f41314..28aa6c731ec814ba2c023b51079a1f997dba86b3 100644 (file)
@@ -10,8 +10,6 @@
 
 // compile-flags: -Zmir-opt-level=1
 
-#![feature(slice_patterns)]
-
 use std::mem;
 
 #[derive(Copy, Clone)]
index badc013cd621f6297af82991af69264dc35b0073..8d21594aa12ca560b80bd0abb263171b5088dd51 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
-#![feature(advanced_slice_patterns)]
 #![feature(slice_patterns)]
 
 use std::ops::Add;
index fa609593c24b631807873967526c5c30238b803e..7d03d9c2abe20fac2237989a2755e45066c78efc 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
-#![feature(advanced_slice_patterns)]
 #![feature(slice_patterns)]
 
 fn match_vecs<'a, T>(l1: &'a [T], l2: &'a [T]) -> &'static str {
index 9e033421574b9eb333c1d2c3c65943d2c710d751..b50852175776cb9d35e64081a219aca9beca5f6b 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-emscripten apparently only works in optimized mode
+
 const TEST_DATA: [u8; 32 * 1024 * 1024] = [42; 32 * 1024 * 1024];
 
 // Check that the promoted copy of TEST_DATA doesn't
index 2782f8c2a598ce2a8e7c116565f8dd3e013a8045..599c6dfd31d906b5de6b98f43c5ccbc25b797c2d 100644 (file)
@@ -10,6 +10,7 @@
 
 // compile-flags: -C debug_assertions=yes
 // ignore-wasm32-bare compiled with panic=abort by default
+// ignore-emscripten dies with an LLVM error
 
 #![feature(i128_type)]
 
index f8bcb961c68338400ab2b783c700ca22563ac782..f2312b70be679aa3bcdd9931eccfe6abdc51fabf 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // compile-flags: -C debug_assertions=no
+// ignore-emscripten dies with an LLVM error
 
 #![feature(i128_type)]
 
index 3041c73afba8819ddbe2b500d9ea4a5400d3347d..e725b25efee520ab92d16a46cd0e55643173a578 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-emscripten weird assertion?
 
 #[repr(packed)]
 struct Foo {
index 1717d0d54c0260bd7d3283ace94e9379eb055015..6178f613b4b86a5ab555740489d9e664cf011262 100644 (file)
@@ -8,8 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(slice_patterns)]
 #![feature(match_default_bindings)]
+#![feature(slice_patterns)]
 
 fn slice_pat() {
     let sl: &[u8] = b"foo";
index 1894cd0084bcb167a4c4d8e50da6efaf6390fb92..ac6d0c697ecc04bb8dc524f3bae9b09dd0a9576b 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-emscripten FIXME(#45351) hits an LLVM assert
+
 #![feature(repr_simd, platform_intrinsics)]
 
 #[repr(simd)]
index 5802fb30bd68045f59e1a31e2376057316b04da7..d27378ba893082ed1d5385624e4ece0e23604d10 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-emscripten FIXME(#45351) hits an LLVM assert
+
 #![feature(repr_simd, platform_intrinsics, concat_idents)]
 #![allow(non_camel_case_types)]
 
index f0444c27170561550a80c85b48e8e4f3f17dd2c1..72fcef27a665bc7b00e80fb1bdf727141c6ba086 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-emscripten FIXME(#45351) hits an LLVM assert
+
 #![feature(repr_simd, platform_intrinsics)]
 
 #[repr(simd)]
index b9eda0846537fc5e0c1190dbe808282a37940074..02bae5aa455158f6d83aa4a621b05ddc03371f2e 100644 (file)
@@ -10,7 +10,6 @@
 
 // pretty-expanded FIXME #23616
 
-#![feature(advanced_slice_patterns,)]
 #![feature(slice_patterns)]
 
 fn f<T,>(_: T,) {}
index 9df777e7af0dc4e85f6d2dc82441f061d5f063e5..7268536a51fad6ef90c9c847073c49c2a340427d 100644 (file)
@@ -8,9 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
-#![feature(slice_patterns)]
-
 pub fn main() {
     let x = [1, 2, 3];
     match x {
index 1ed6ddc4110768a55e8df2eab7e18c868533a2f8..060d152488a97713a1cceec8717dbb80a8b24f81 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
-#![feature(advanced_slice_patterns)]
 #![feature(slice_patterns)]
 
 fn a() {
index ac80a4211ada627fbfc0c0a2eb50dfda3d31f570..1a30f875580c201480aec5173002d74d381f0726 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
-#![feature(advanced_slice_patterns)]
 #![feature(slice_patterns)]
 
 use std::fmt::Debug;
index bd0731a555cb6d80feef08a5c33d975580936f2b..ace418f2160682485798e7fe1ab826f0f6166926 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
-#![feature(advanced_slice_patterns)]
 #![feature(slice_patterns)]
 
 fn a() {
index d123eb36a7d4d0d2a762b0ddf2dc733e68e6f6b9..4f31405ead500355900bca2e41d5ca699139dd63 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
-
 #![feature(slice_patterns)]
 
 struct Foo {
index 8499e5c741ee043e0225f5025af6ea88578bf114..ea8a13b034beb244eaf4a716864f1317ec70f07d 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 #![feature(doc_cfg)]
+#![feature(target_feature, cfg_target_feature)]
 
 // @has doc_cfg/struct.Portable.html
 // @!has - '//*[@id="main"]/*[@class="stability"]/*[@class="stab portability"]' ''
@@ -45,3 +46,26 @@ impl ArmOnly for super::Portable {
         fn unix_and_arm_only_function() {}
     }
 }
+
+// tagging a function with `#[target_feature]` creates a doc(cfg(target_feature)) node for that
+// item as well
+
+// the portability header is different on the module view versus the full view
+// @has doc_cfg/index.html
+// @matches - '//*[@class=" module-item"]//*[@class="stab portability"]' '\Aavx\Z'
+
+// @has doc_cfg/fn.uses_target_feature.html
+// @has - '//*[@id="main"]/*[@class="stability"]/*[@class="stab portability"]' \
+//        'This is supported with target feature avx only.'
+#[target_feature(enable = "avx")]
+pub unsafe fn uses_target_feature() {
+    content::should::be::irrelevant();
+}
+
+// @has doc_cfg/fn.uses_cfg_target_feature.html
+// @has - '//*[@id="main"]/*[@class="stability"]/*[@class="stab portability"]' \
+//        'This is supported with target feature avx only.'
+#[doc(cfg(target_feature = "avx"))]
+pub fn uses_cfg_target_feature() {
+    uses_target_feature();
+}
index 07b268f1a4b015a44dd4f5aa5d6b16c99f4b053b..111968e9c9313a62be77f7a685ebc6639d89ea20 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(advanced_slice_patterns)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
 #![feature(slice_patterns)]
index e11702df80a97b108efb65c7bf9685a253fd8a21..6673549e23903e7416f34a81c780bb72919252f8 100644 (file)
@@ -1,5 +1,5 @@
 error[E0506]: cannot assign to `vec[..]` because it is borrowed
-  --> $DIR/borrowck-vec-pattern-nesting.rs:21:13
+  --> $DIR/borrowck-vec-pattern-nesting.rs:20:13
    |
 LL |         [box ref _a, _, _] => {
    |              ------ borrow of `vec[..]` occurs here
@@ -8,7 +8,7 @@ LL |             vec[0] = box 4; //~ ERROR cannot assign
    |             ^^^^^^^^^^^^^^ assignment to borrowed `vec[..]` occurs here
 
 error[E0506]: cannot assign to `vec[..]` because it is borrowed
-  --> $DIR/borrowck-vec-pattern-nesting.rs:33:13
+  --> $DIR/borrowck-vec-pattern-nesting.rs:32:13
    |
 LL |         &mut [ref _b..] => {
    |               ------ borrow of `vec[..]` occurs here
@@ -17,7 +17,7 @@ LL |             vec[0] = box 4; //~ ERROR cannot assign
    |             ^^^^^^^^^^^^^^ assignment to borrowed `vec[..]` occurs here
 
 error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
-  --> $DIR/borrowck-vec-pattern-nesting.rs:43:14
+  --> $DIR/borrowck-vec-pattern-nesting.rs:42:14
    |
 LL |           &mut [_a, //~ ERROR cannot move out
    |                ^-- hint: to prevent move, use `ref _a` or `ref mut _a`
@@ -30,7 +30,7 @@ LL | |         ] => {
    | |_________^ cannot move out of here
 
 error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
-  --> $DIR/borrowck-vec-pattern-nesting.rs:56:13
+  --> $DIR/borrowck-vec-pattern-nesting.rs:55:13
    |
 LL |     let a = vec[0]; //~ ERROR cannot move out
    |             ^^^^^^
@@ -39,7 +39,7 @@ LL |     let a = vec[0]; //~ ERROR cannot move out
    |             help: consider using a reference instead: `&vec[0]`
 
 error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
-  --> $DIR/borrowck-vec-pattern-nesting.rs:64:14
+  --> $DIR/borrowck-vec-pattern-nesting.rs:63:14
    |
 LL |           &mut [ //~ ERROR cannot move out
    |  ______________^
@@ -50,7 +50,7 @@ LL | |          _b] => {}
    |            hint: to prevent move, use `ref _b` or `ref mut _b`
 
 error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
-  --> $DIR/borrowck-vec-pattern-nesting.rs:69:13
+  --> $DIR/borrowck-vec-pattern-nesting.rs:68:13
    |
 LL |     let a = vec[0]; //~ ERROR cannot move out
    |             ^^^^^^
@@ -59,7 +59,7 @@ LL |     let a = vec[0]; //~ ERROR cannot move out
    |             help: consider using a reference instead: `&vec[0]`
 
 error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
-  --> $DIR/borrowck-vec-pattern-nesting.rs:77:14
+  --> $DIR/borrowck-vec-pattern-nesting.rs:76:14
    |
 LL |         &mut [_a, _b, _c] => {}  //~ ERROR cannot move out
    |              ^--^^--^^--^
@@ -70,7 +70,7 @@ LL |         &mut [_a, _b, _c] => {}  //~ ERROR cannot move out
    |              cannot move out of here
 
 error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
-  --> $DIR/borrowck-vec-pattern-nesting.rs:81:13
+  --> $DIR/borrowck-vec-pattern-nesting.rs:80:13
    |
 LL |     let a = vec[0]; //~ ERROR cannot move out
    |             ^^^^^^
index 480d8c40022d52ac98caaff52c5888bf58358d2c..df3b09ba7c9f34b8f9a2ac7a39223446f98bcb4a 100644 (file)
@@ -2,7 +2,7 @@ error[E0449]: unnecessary visibility qualifier
   --> $DIR/E0449.rs:17:1
    |
 LL | pub impl Bar {} //~ ERROR E0449
-   | ^^^ `pub` not needed here
+   | ^^^ `pub` not permitted here because it's implied
    |
    = note: place qualifiers on individual impl items instead
 
@@ -10,13 +10,13 @@ error[E0449]: unnecessary visibility qualifier
   --> $DIR/E0449.rs:19:1
    |
 LL | pub impl Foo for Bar { //~ ERROR E0449
-   | ^^^ `pub` not needed here
+   | ^^^ `pub` not permitted here because it's implied
 
 error[E0449]: unnecessary visibility qualifier
   --> $DIR/E0449.rs:20:5
    |
 LL |     pub fn foo() {} //~ ERROR E0449
-   |     ^^^ `pub` not needed here
+   |     ^^^ `pub` not permitted here because it's implied
 
 error: aborting due to 3 previous errors
 
index 67d222e867e638dc2c3dfb975aea834a6c321bb1..a90ccec9cf5e922eb3dc5ea4d29b86e093eaf562 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(slice_patterns)]
-
 fn main() {
     let r = &[1, 2, 3, 4];
     match r {
index 2060f1e69e0ca2324d1f1de67bd8239ae83adb89..1e764c185877b1886dd339cfaea2b7b8396799c7 100644 (file)
@@ -1,5 +1,5 @@
 error[E0527]: pattern requires 2 elements but array has 4
-  --> $DIR/E0527.rs:16:10
+  --> $DIR/E0527.rs:14:10
    |
 LL |         &[a, b] => {
    |          ^^^^^^ expected 4 elements
index 5262ad7b716f5e25be27bb6842a9981dba335ec9..2459054da89afc3e5210d3414e8312152b323cda 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(slice_patterns)]
-
 fn main() {
     let r: f32 = 1.0;
     match r {
index fcada000790661246d5143c124f7be37a325496a..b2e7ae23fb0ebbf3fdd2876d45d1be991bf8bf8d 100644 (file)
@@ -1,5 +1,5 @@
 error[E0529]: expected an array or slice, found `f32`
-  --> $DIR/E0529.rs:16:9
+  --> $DIR/E0529.rs:14:9
    |
 LL |         [a, b] => {
    |         ^^^^^^ pattern cannot match with input type `f32`
diff --git a/src/test/ui/feature-gate-advanced-slice-features.rs b/src/test/ui/feature-gate-advanced-slice-features.rs
deleted file mode 100644 (file)
index dc9b4e6..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-// 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.
-
-// gate-test-advanced_slice_patterns
-
-#![feature(slice_patterns)]
-
-fn main() {
-    let x = [ 1, 2, 3, 4, 5 ];
-    match x {
-        [ xs.., 4, 5 ] => {}    //~ ERROR multiple-element slice matches
-        [ 1, xs.., 5 ] => {}    //~ ERROR multiple-element slice matches
-        [ 1, 2, xs.. ] => {}    // OK without feature gate
-    }
-}
diff --git a/src/test/ui/feature-gate-advanced-slice-features.stderr b/src/test/ui/feature-gate-advanced-slice-features.stderr
deleted file mode 100644 (file)
index 9d9e755..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-error[E0658]: multiple-element slice matches anywhere but at the end of a slice (e.g. `[0, ..xs, 0]`) are experimental (see issue #23121)
-  --> $DIR/feature-gate-advanced-slice-features.rs:18:9
-   |
-LL |         [ xs.., 4, 5 ] => {}    //~ ERROR multiple-element slice matches
-   |         ^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(advanced_slice_patterns)] to the crate attributes to enable
-
-error[E0658]: multiple-element slice matches anywhere but at the end of a slice (e.g. `[0, ..xs, 0]`) are experimental (see issue #23121)
-  --> $DIR/feature-gate-advanced-slice-features.rs:19:9
-   |
-LL |         [ 1, xs.., 5 ] => {}    //~ ERROR multiple-element slice matches
-   |         ^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(advanced_slice_patterns)] to the crate attributes to enable
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0658`.
index 625cb2d351553709b9c7dac7379c2b4ec7ebdb88..fd058f6517211ce7e86a94bbee64fd4bc299c2be 100644 (file)
@@ -8,11 +8,20 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// Test that slice pattern syntax is gated by `slice_patterns` feature gate
+// Test that slice pattern syntax with `..` is gated by `slice_patterns` feature gate
 
 fn main() {
     let x = [1, 2, 3, 4, 5];
     match x {
-        [1, 2, xs..] => {} //~ ERROR slice pattern syntax is experimental
+        [1, 2, ..] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized
+        [1, .., 5] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized
+        [.., 4, 5] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized
+    }
+
+    let x = [ 1, 2, 3, 4, 5 ];
+    match x {
+        [ xs.., 4, 5 ] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized
+        [ 1, xs.., 5 ] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized
+        [ 1, 2, xs.. ] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized
     }
 }
index 7c216fad933e3c349f64e9174a6dfcb7a9830c89..d560dcd54eefbdb392c6bfa68ad06169ad5b745a 100644 (file)
@@ -1,11 +1,51 @@
-error[E0658]: slice pattern syntax is experimental (see issue #23121)
-  --> $DIR/feature-gate-slice-patterns.rs:16:9
+error[E0658]: syntax for subslices in slice patterns is not yet stabilized (see issue #23121)
+  --> $DIR/feature-gate-slice-patterns.rs:16:16
    |
-LL |         [1, 2, xs..] => {} //~ ERROR slice pattern syntax is experimental
-   |         ^^^^^^^^^^^^
+LL |         [1, 2, ..] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized
+   |                ^^
    |
    = help: add #![feature(slice_patterns)] to the crate attributes to enable
 
-error: aborting due to previous error
+error[E0658]: syntax for subslices in slice patterns is not yet stabilized (see issue #23121)
+  --> $DIR/feature-gate-slice-patterns.rs:17:13
+   |
+LL |         [1, .., 5] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized
+   |             ^^
+   |
+   = help: add #![feature(slice_patterns)] to the crate attributes to enable
+
+error[E0658]: syntax for subslices in slice patterns is not yet stabilized (see issue #23121)
+  --> $DIR/feature-gate-slice-patterns.rs:18:10
+   |
+LL |         [.., 4, 5] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized
+   |          ^^
+   |
+   = help: add #![feature(slice_patterns)] to the crate attributes to enable
+
+error[E0658]: syntax for subslices in slice patterns is not yet stabilized (see issue #23121)
+  --> $DIR/feature-gate-slice-patterns.rs:23:11
+   |
+LL |         [ xs.., 4, 5 ] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized
+   |           ^^
+   |
+   = help: add #![feature(slice_patterns)] to the crate attributes to enable
+
+error[E0658]: syntax for subslices in slice patterns is not yet stabilized (see issue #23121)
+  --> $DIR/feature-gate-slice-patterns.rs:24:14
+   |
+LL |         [ 1, xs.., 5 ] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized
+   |              ^^
+   |
+   = help: add #![feature(slice_patterns)] to the crate attributes to enable
+
+error[E0658]: syntax for subslices in slice patterns is not yet stabilized (see issue #23121)
+  --> $DIR/feature-gate-slice-patterns.rs:25:17
+   |
+LL |         [ 1, 2, xs.. ] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized
+   |                 ^^
+   |
+   = help: add #![feature(slice_patterns)] to the crate attributes to enable
+
+error: aborting due to 6 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
index cd83915fe82d30bba1c2fc4bd320ce0b469a7e86..dd78baf9275098266074f7a73cae1043dfa1ad87 100644 (file)
@@ -1,15 +1,15 @@
-error[E0277]: the trait bound `No: Foo` is not satisfied in `[generator@$DIR/auto-trait-regions.rs:35:15: 39:6 x:&&'static OnlyFooIfStaticRef for<'r> {&'r OnlyFooIfStaticRef, ()}]`
+error[E0277]: the trait bound `No: Foo` is not satisfied in `[generator@$DIR/auto-trait-regions.rs:35:15: 39:6 x:&&OnlyFooIfStaticRef for<'r> {&'r OnlyFooIfStaticRef, ()}]`
   --> $DIR/auto-trait-regions.rs:40:5
    |
 LL |     assert_foo(gen); //~ ERROR the trait bound `No: Foo` is not satisfied
-   |     ^^^^^^^^^^ within `[generator@$DIR/auto-trait-regions.rs:35:15: 39:6 x:&&'static OnlyFooIfStaticRef for<'r> {&'r OnlyFooIfStaticRef, ()}]`, the trait `Foo` is not implemented for `No`
+   |     ^^^^^^^^^^ within `[generator@$DIR/auto-trait-regions.rs:35:15: 39:6 x:&&OnlyFooIfStaticRef for<'r> {&'r OnlyFooIfStaticRef, ()}]`, the trait `Foo` is not implemented for `No`
    |
    = help: the following implementations were found:
              <No as Foo>
    = note: required because it appears within the type `OnlyFooIfStaticRef`
    = note: required because it appears within the type `&OnlyFooIfStaticRef`
    = note: required because it appears within the type `for<'r> {&'r OnlyFooIfStaticRef, ()}`
-   = note: required because it appears within the type `[generator@$DIR/auto-trait-regions.rs:35:15: 39:6 x:&&'static OnlyFooIfStaticRef for<'r> {&'r OnlyFooIfStaticRef, ()}]`
+   = note: required because it appears within the type `[generator@$DIR/auto-trait-regions.rs:35:15: 39:6 x:&&OnlyFooIfStaticRef for<'r> {&'r OnlyFooIfStaticRef, ()}]`
 note: required by `assert_foo`
   --> $DIR/auto-trait-regions.rs:30:1
    |
diff --git a/src/test/ui/impl-trait/region-escape-via-bound-contravariant-closure.rs b/src/test/ui/impl-trait/region-escape-via-bound-contravariant-closure.rs
new file mode 100644 (file)
index 0000000..f554efe
--- /dev/null
@@ -0,0 +1,31 @@
+// Copyright 2016 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.
+
+// In contrast to `region-escape-via-bound-invariant`, in this case we
+// *can* return a value of type `&'x u32`, even though `'x` does not
+// appear in the bounds. This is because `&` is contravariant, and so
+// we are *actually* returning a `&'y u32`.
+//
+// See https://github.com/rust-lang/rust/issues/46541 for more details.
+
+// run-pass
+
+#![allow(dead_code)]
+#![feature(conservative_impl_trait)]
+#![feature(in_band_lifetimes)]
+#![feature(nll)]
+
+fn foo(x: &'x u32) -> impl Fn() -> &'y u32
+where 'x: 'y
+{
+    move || x
+}
+
+fn main() { }
diff --git a/src/test/ui/impl-trait/region-escape-via-bound-contravariant.rs b/src/test/ui/impl-trait/region-escape-via-bound-contravariant.rs
new file mode 100644 (file)
index 0000000..416bdae
--- /dev/null
@@ -0,0 +1,35 @@
+// Copyright 2016 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.
+
+// In contrast to `region-escape-via-bound-invariant`, in this case we
+// *can* return a value of type `&'x u32`, even though `'x` does not
+// appear in the bounds. This is because `&` is contravariant, and so
+// we are *actually* returning a `&'y u32`.
+//
+// See https://github.com/rust-lang/rust/issues/46541 for more details.
+
+// run-pass
+
+#![allow(dead_code)]
+#![feature(conservative_impl_trait)]
+#![feature(in_band_lifetimes)]
+#![feature(nll)]
+
+trait Trait<'a> { }
+
+impl Trait<'b> for &'a u32 { }
+
+fn foo(x: &'x u32) -> impl Trait<'y>
+where 'x: 'y
+{
+    x
+}
+
+fn main() { }
diff --git a/src/test/ui/impl-trait/region-escape-via-bound.rs b/src/test/ui/impl-trait/region-escape-via-bound.rs
new file mode 100644 (file)
index 0000000..38c18ce
--- /dev/null
@@ -0,0 +1,34 @@
+// Copyright 2016 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 do not allow the region `'x` to escape in the impl
+// trait **even though** `'y` escapes, which outlives `'x`.
+//
+// See https://github.com/rust-lang/rust/issues/46541 for more details.
+
+#![allow(dead_code)]
+#![feature(conservative_impl_trait)]
+#![feature(in_band_lifetimes)]
+#![feature(nll)]
+
+use std::cell::Cell;
+
+trait Trait<'a> { }
+
+impl Trait<'b> for Cell<&'a u32> { }
+
+fn foo(x: Cell<&'x u32>) -> impl Trait<'y>
+    //~^ ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds [E0909]
+where 'x: 'y
+{
+    x
+}
+
+fn main() { }
diff --git a/src/test/ui/impl-trait/region-escape-via-bound.stderr b/src/test/ui/impl-trait/region-escape-via-bound.stderr
new file mode 100644 (file)
index 0000000..5659fee
--- /dev/null
@@ -0,0 +1,20 @@
+error[E0909]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+  --> $DIR/region-escape-via-bound.rs:27:29
+   |
+LL | fn foo(x: Cell<&'x u32>) -> impl Trait<'y>
+   |                             ^^^^^^^^^^^^^^
+   |
+note: hidden type `std::cell::Cell<&'x u32>` captures the lifetime 'x as defined on the function body at 27:1
+  --> $DIR/region-escape-via-bound.rs:27:1
+   |
+LL | / fn foo(x: Cell<&'x u32>) -> impl Trait<'y>
+LL | |     //~^ ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds [E0909]
+LL | | where 'x: 'y
+LL | | {
+LL | |     x
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0909`.
diff --git a/src/test/ui/issue-49040.rs b/src/test/ui/issue-49040.rs
new file mode 100644 (file)
index 0000000..866ecd9
--- /dev/null
@@ -0,0 +1,12 @@
+// 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.
+
+#![allow(unused_variables)]; //~ ERROR expected item, found `;`
+fn main() {}
diff --git a/src/test/ui/issue-49040.stderr b/src/test/ui/issue-49040.stderr
new file mode 100644 (file)
index 0000000..b6f624d
--- /dev/null
@@ -0,0 +1,8 @@
+error: expected item, found `;`
+  --> $DIR/issue-49040.rs:11:28
+   |
+LL | #![allow(unused_variables)]; //~ ERROR expected item, found `;`
+   |                            ^ help: consider removing this semicolon
+
+error: aborting due to previous error
+
index b9b6b05996b665adb0995448164fbf80fa12ccb5..8e613d4edba14570408c06476d59b9957cfa30cd 100644 (file)
@@ -7,8 +7,6 @@
 // <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(slice_patterns)]
-
 
 struct Foo {
 }
index 1bf1521e39e0385d146328b6a8e804378e54715f..dd5da769075150436972126a69556474d0bc01ea 100644 (file)
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/issue-38371.rs:16:8
+  --> $DIR/issue-38371.rs:14:8
    |
 LL | fn foo(&foo: Foo) { //~ ERROR mismatched types
    |        ^^^^ expected struct `Foo`, found reference
@@ -9,7 +9,7 @@ LL | fn foo(&foo: Foo) { //~ ERROR mismatched types
    = help: did you mean `foo: &Foo`?
 
 error[E0308]: mismatched types
-  --> $DIR/issue-38371.rs:30:9
+  --> $DIR/issue-38371.rs:28:9
    |
 LL | fn agh(&&bar: &u32) { //~ ERROR mismatched types
    |         ^^^^ expected u32, found reference
@@ -19,7 +19,7 @@ LL | fn agh(&&bar: &u32) { //~ ERROR mismatched types
    = help: did you mean `bar: &u32`?
 
 error[E0308]: mismatched types
-  --> $DIR/issue-38371.rs:33:8
+  --> $DIR/issue-38371.rs:31:8
    |
 LL | fn bgh(&&bar: u32) { //~ ERROR mismatched types
    |        ^^^^^ expected u32, found reference
@@ -28,7 +28,7 @@ LL | fn bgh(&&bar: u32) { //~ ERROR mismatched types
               found type `&_`
 
 error[E0529]: expected an array or slice, found `u32`
-  --> $DIR/issue-38371.rs:36:9
+  --> $DIR/issue-38371.rs:34:9
    |
 LL | fn ugh(&[bar]: &u32) { //~ ERROR expected an array or slice
    |         ^^^^^ pattern cannot match with input type `u32`
index 0b12a9acbcb9e9d56de662b81d4234bda7fc35a7..dd14a10a2bcecd1f5acc80d309c9ca77b8e87664 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(advanced_slice_patterns)]
 #![feature(slice_patterns)]
 
 struct Foo {
index 7179b4b135a127e8a3440bf1c241b21324ac1b70..e364e822ea8786a5d7d7ebcc7e1413711f621189 100644 (file)
@@ -1,41 +1,41 @@
 error[E0004]: non-exhaustive patterns: `Foo { first: false, second: Some([_, _, _, _]) }` not covered
-  --> $DIR/non-exhaustive-pattern-witness.rs:20:11
+  --> $DIR/non-exhaustive-pattern-witness.rs:19:11
    |
 LL |     match (Foo { first: true, second: None }) {
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo { first: false, second: Some([_, _, _, _]) }` not covered
 
 error[E0004]: non-exhaustive patterns: `Red` not covered
-  --> $DIR/non-exhaustive-pattern-witness.rs:36:11
+  --> $DIR/non-exhaustive-pattern-witness.rs:35:11
    |
 LL |     match Color::Red {
    |           ^^^^^^^^^^ pattern `Red` not covered
 
 error[E0004]: non-exhaustive patterns: `East`, `South` and `West` not covered
-  --> $DIR/non-exhaustive-pattern-witness.rs:48:11
+  --> $DIR/non-exhaustive-pattern-witness.rs:47:11
    |
 LL |     match Direction::North {
    |           ^^^^^^^^^^^^^^^^ patterns `East`, `South` and `West` not covered
 
 error[E0004]: non-exhaustive patterns: `Second`, `Third`, `Fourth` and 8 more not covered
-  --> $DIR/non-exhaustive-pattern-witness.rs:59:11
+  --> $DIR/non-exhaustive-pattern-witness.rs:58:11
    |
 LL |     match ExcessiveEnum::First {
    |           ^^^^^^^^^^^^^^^^^^^^ patterns `Second`, `Third`, `Fourth` and 8 more not covered
 
 error[E0004]: non-exhaustive patterns: `CustomRGBA { a: true, .. }` not covered
-  --> $DIR/non-exhaustive-pattern-witness.rs:67:11
+  --> $DIR/non-exhaustive-pattern-witness.rs:66:11
    |
 LL |     match Color::Red {
    |           ^^^^^^^^^^ pattern `CustomRGBA { a: true, .. }` not covered
 
 error[E0004]: non-exhaustive patterns: `[Second(true), Second(false)]` not covered
-  --> $DIR/non-exhaustive-pattern-witness.rs:83:11
+  --> $DIR/non-exhaustive-pattern-witness.rs:82:11
    |
 LL |     match *x {
    |           ^^ pattern `[Second(true), Second(false)]` not covered
 
 error[E0004]: non-exhaustive patterns: `((), false)` not covered
-  --> $DIR/non-exhaustive-pattern-witness.rs:96:11
+  --> $DIR/non-exhaustive-pattern-witness.rs:95:11
    |
 LL |     match ((), false) {
    |           ^^^^^^^^^^^ pattern `((), false)` not covered
index 4ff1e94b08721bfc866aa23b327b11cdcdfad29f..65578e76d6d696e0725438196a5f9cc7af616a8a 100644 (file)
@@ -8,11 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(slice_patterns)]
-
 // NB: this test was introduced in #23121 and will have to change when default match binding modes
 // stabilizes.
 
+#![feature(slice_patterns)]
+
 fn slice_pat(x: &[u8]) {
     // OLD!
     match x {
index 40aa957242cb81c0be2c31a94446c7a9e1a9f375..20ef0624bf91b4102c29e4a61c207cdb9d120e37 100644 (file)
@@ -8,8 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(slice_patterns)]
 #![feature(match_default_bindings)]
+#![feature(slice_patterns)]
 
 pub fn main() {
     let sl: &[u8] = b"foo";
diff --git a/src/test/ui/suggest-remove-refs-1.rs b/src/test/ui/suggest-remove-refs-1.rs
new file mode 100644 (file)
index 0000000..0f19c48
--- /dev/null
@@ -0,0 +1,18 @@
+// 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 v = vec![0, 1, 2, 3];
+
+    for (i, n) in &v.iter().enumerate() {
+        //~^ ERROR the trait bound
+        println!("{}", i);
+    }
+}
diff --git a/src/test/ui/suggest-remove-refs-1.stderr b/src/test/ui/suggest-remove-refs-1.stderr
new file mode 100644 (file)
index 0000000..c47b4d2
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `&std::iter::Enumerate<std::slice::Iter<'_, {integer}>>: std::iter::Iterator` is not satisfied
+  --> $DIR/suggest-remove-refs-1.rs:14:19
+   |
+LL |     for (i, n) in &v.iter().enumerate() {
+   |                   -^^^^^^^^^^^^^^^^^^^^
+   |                   |
+   |                   `&std::iter::Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator; maybe try calling `.iter()` or a similar method
+   |                   help: consider removing 1 leading `&`-references
+   |
+   = help: the trait `std::iter::Iterator` is not implemented for `&std::iter::Enumerate<std::slice::Iter<'_, {integer}>>`
+   = note: required by `std::iter::IntoIterator::into_iter`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/suggest-remove-refs-2.rs b/src/test/ui/suggest-remove-refs-2.rs
new file mode 100644 (file)
index 0000000..c427f69
--- /dev/null
@@ -0,0 +1,18 @@
+// 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 v = vec![0, 1, 2, 3];
+
+    for (i, n) in & & & & &v.iter().enumerate() {
+        //~^ ERROR the trait bound
+        println!("{}", i);
+    }
+}
diff --git a/src/test/ui/suggest-remove-refs-2.stderr b/src/test/ui/suggest-remove-refs-2.stderr
new file mode 100644 (file)
index 0000000..fdd654e
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `&&&&&std::iter::Enumerate<std::slice::Iter<'_, {integer}>>: std::iter::Iterator` is not satisfied
+  --> $DIR/suggest-remove-refs-2.rs:14:19
+   |
+LL |     for (i, n) in & & & & &v.iter().enumerate() {
+   |                   ---------^^^^^^^^^^^^^^^^^^^^
+   |                   |
+   |                   `&&&&&std::iter::Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator; maybe try calling `.iter()` or a similar method
+   |                   help: consider removing 5 leading `&`-references
+   |
+   = help: the trait `std::iter::Iterator` is not implemented for `&&&&&std::iter::Enumerate<std::slice::Iter<'_, {integer}>>`
+   = note: required by `std::iter::IntoIterator::into_iter`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/suggest-remove-refs-3.rs b/src/test/ui/suggest-remove-refs-3.rs
new file mode 100644 (file)
index 0000000..f54ae30
--- /dev/null
@@ -0,0 +1,21 @@
+// 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 v = vec![0, 1, 2, 3];
+
+    for (i, n) in & & &
+        & &v
+        .iter()
+        .enumerate() {
+        //~^^^^ ERROR the trait bound
+        println!("{}", i);
+    }
+}
diff --git a/src/test/ui/suggest-remove-refs-3.stderr b/src/test/ui/suggest-remove-refs-3.stderr
new file mode 100644 (file)
index 0000000..b0920a0
--- /dev/null
@@ -0,0 +1,19 @@
+error[E0277]: the trait bound `&&&&&std::iter::Enumerate<std::slice::Iter<'_, {integer}>>: std::iter::Iterator` is not satisfied
+  --> $DIR/suggest-remove-refs-3.rs:14:19
+   |
+LL |        for (i, n) in & & &
+   |   ___________________^
+   |  |___________________|
+   | ||
+LL | ||         & &v
+   | ||___________- help: consider removing 5 leading `&`-references
+LL | |          .iter()
+LL | |          .enumerate() {
+   | |_____________________^ `&&&&&std::iter::Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator; maybe try calling `.iter()` or a similar method
+   |
+   = help: the trait `std::iter::Iterator` is not implemented for `&&&&&std::iter::Enumerate<std::slice::Iter<'_, {integer}>>`
+   = note: required by `std::iter::IntoIterator::into_iter`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/suggestions/const-type-mismatch.rs b/src/test/ui/suggestions/const-type-mismatch.rs
new file mode 100644 (file)
index 0000000..ddad4e7
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2018 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`s shouldn't suggest `.into()`
+
+const TEN: u8 = 10;
+const TWELVE: u16 = TEN + 2;
+//~^ ERROR mismatched types [E0308]
+
+fn main() {
+    const TEN: u8 = 10;
+    const ALSO_TEN: u16 = TEN;
+    //~^ ERROR mismatched types [E0308]
+}
diff --git a/src/test/ui/suggestions/const-type-mismatch.stderr b/src/test/ui/suggestions/const-type-mismatch.stderr
new file mode 100644 (file)
index 0000000..965995f
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0308]: mismatched types
+  --> $DIR/const-type-mismatch.rs:14:21
+   |
+LL | const TWELVE: u16 = TEN + 2;
+   |                     ^^^^^^^ expected u16, found u8
+
+error[E0308]: mismatched types
+  --> $DIR/const-type-mismatch.rs:19:27
+   |
+LL |     const ALSO_TEN: u16 = TEN;
+   |                           ^^^ expected u16, found u8
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
index d6c3983fe3bd8fa06b54712e53fb23645598188b..d10ec661b06420654bbc4ed0ccd32295698aa1dc 160000 (submodule)
@@ -1 +1 @@
-Subproject commit d6c3983fe3bd8fa06b54712e53fb23645598188b
+Subproject commit d10ec661b06420654bbc4ed0ccd32295698aa1dc
index 6f3f25878f2271911e4b6de4d0cf86accc397455..4edd140e57cce900fa930e1439bab469f5bbce46 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 6f3f25878f2271911e4b6de4d0cf86accc397455
+Subproject commit 4edd140e57cce900fa930e1439bab469f5bbce46
index 953a13a3f582035a45ced2040dd2d03292635043..43220af4893bbcd97efb776f6af9961e68c4f9a0 100644 (file)
@@ -1324,6 +1324,8 @@ fn document(&self, out_dir: &Path) -> ProcRes {
         let mut rustdoc = Command::new(rustdoc_path);
 
         rustdoc
+            .arg("-L")
+            .arg(self.config.run_lib_path.to_str().unwrap())
             .arg("-L")
             .arg(aux_dir)
             .arg("-o")
@@ -2358,11 +2360,6 @@ fn incremental_dir(&self) -> PathBuf {
     }
 
     fn run_rmake_test(&self) {
-        // FIXME(#11094): we should fix these tests
-        if self.config.host != self.config.target {
-            return;
-        }
-
         let cwd = env::current_dir().unwrap();
         let src_root = self.config
             .src_base
index 0e3fa25b13ce9368233e815835902df375795318..c612f0117aaf7f311365369302807cea21eef268 100644 (file)
 /// Conversion table from triple OS name to Rust SYSNAME
 const OS_TABLE: &'static [(&'static str, &'static str)] = &[
     ("android", "android"),
+    ("androideabi", "android"),
     ("bitrig", "bitrig"),
     ("cloudabi", "cloudabi"),
     ("darwin", "macos"),
     ("dragonfly", "dragonfly"),
+    ("emscripten", "emscripten"),
     ("freebsd", "freebsd"),
+    ("fuchsia", "fuchsia"),
     ("haiku", "haiku"),
     ("ios", "ios"),
+    ("l4re", "l4re"),
     ("linux", "linux"),
     ("mingw32", "windows"),
     ("netbsd", "netbsd"),
     ("openbsd", "openbsd"),
+    ("redox", "redox"),
+    ("solaris", "solaris"),
     ("win32", "windows"),
     ("windows", "windows"),
-    ("solaris", "solaris"),
-    ("emscripten", "emscripten"),
 ];
 
 const ARCH_TABLE: &'static [(&'static str, &'static str)] = &[
     ("amd64", "x86_64"),
     ("arm", "arm"),
     ("arm64", "aarch64"),
+    ("armv4t", "arm"),
+    ("armv5te", "arm"),
+    ("armv7", "arm"),
+    ("armv7s", "arm"),
+    ("asmjs", "asmjs"),
     ("hexagon", "hexagon"),
     ("i386", "x86"),
     ("i586", "x86"),
     ("i686", "x86"),
-    ("mips64", "mips64"),
     ("mips", "mips"),
+    ("mips64", "mips64"),
+    ("mips64el", "mips64"),
+    ("mipsel", "mips"),
     ("msp430", "msp430"),
     ("powerpc", "powerpc"),
+    ("powerpc64", "powerpc64"),
+    ("powerpc64le", "powerpc64"),
     ("s390x", "s390x"),
     ("sparc", "sparc"),
+    ("sparc64", "sparc64"),
+    ("sparcv9", "sparc64"),
+    ("thumbv6m", "thumb"),
+    ("thumbv7em", "thumb"),
+    ("thumbv7m", "thumb"),
+    ("wasm32", "wasm32"),
     ("x86_64", "x86_64"),
     ("xcore", "xcore"),
-    ("asmjs", "asmjs"),
-    ("wasm32", "wasm32"),
 ];
 
 pub fn matches_os(triple: &str, name: &str) -> bool {
@@ -58,16 +75,18 @@ pub fn matches_os(triple: &str, name: &str) -> bool {
     if triple == "wasm32-unknown-unknown" {
         return name == "emscripten" || name == "wasm32-bare"
     }
+    let triple: Vec<_> = triple.split('-').collect();
     for &(triple_os, os) in OS_TABLE {
-        if triple.contains(triple_os) {
+        if triple.contains(&triple_os) {
             return os == name;
         }
     }
     panic!("Cannot determine OS from triple");
 }
 pub fn get_arch(triple: &str) -> &'static str {
+    let triple: Vec<_> = triple.split('-').collect();
     for &(triple_arch, arch) in ARCH_TABLE {
-        if triple.contains(triple_arch) {
+        if triple.contains(&triple_arch) {
             return arch;
         }
     }
index fc4db0a5e99e426fd97de370c6f36f585b6af13a..567fb6d74cca9ccbfae2440c688035400b51e3c6 160000 (submodule)
@@ -1 +1 @@
-Subproject commit fc4db0a5e99e426fd97de370c6f36f585b6af13a
+Subproject commit 567fb6d74cca9ccbfae2440c688035400b51e3c6
index 346238f49740d6c98102a6a59811b1625c73a9d7..87180d9065e7c8070c0ba46eb48ddf8779ef89ac 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 346238f49740d6c98102a6a59811b1625c73a9d7
+Subproject commit 87180d9065e7c8070c0ba46eb48ddf8779ef89ac