]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #48939 - wesleywiser:incr_query_wf_checking, r=michaelwoerister
authorkennytm <kennytm@gmail.com>
Thu, 22 Mar 2018 09:51:19 +0000 (17:51 +0800)
committerkennytm <kennytm@gmail.com>
Thu, 22 Mar 2018 14:43:30 +0000 (22:43 +0800)
Querify WF-checking so it can be cached

r? @michaelwoerister

297 files changed:
.travis.yml
RELEASES.md
config.toml.example
src/Cargo.lock
src/Cargo.toml
src/bootstrap/bootstrap.py
src/bootstrap/builder.rs
src/bootstrap/cc_detect.rs
src/bootstrap/dist.rs
src/bootstrap/flags.rs
src/bootstrap/lib.rs
src/bootstrap/test.rs
src/bootstrap/tool.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/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/heap.rs
src/liballoc/lib.rs
src/libcore/benches/lib.rs
src/libcore/borrow.rs
src/libcore/fmt/mod.rs
src/libcore/fmt/num.rs
src/libcore/hash/mod.rs
src/libcore/hash/sip.rs
src/libcore/macros.rs
src/libcore/marker.rs
src/libcore/mem.rs
src/libcore/num/wrapping.rs
src/libcore/tests/fmt/num.rs
src/libcore/tests/hash/sip.rs
src/libcore/tests/lib.rs
src/libfmt_macros/lib.rs
src/libproc_macro/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/diagnostics.rs
src/librustc/hir/intravisit.rs
src/librustc/hir/lowering.rs
src/librustc/hir/mod.rs
src/librustc/hir/print.rs
src/librustc/ich/impls_hir.rs
src/librustc/ich/impls_syntax.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/middle/resolve_lifetime.rs
src/librustc/mir/interpret/error.rs
src/librustc/mir/interpret/mod.rs
src/librustc/mir/mod.rs
src/librustc/session/config.rs
src/librustc/traits/error_reporting.rs
src/librustc/traits/mod.rs
src/librustc/traits/query/dropck_outlives.rs
src/librustc/traits/specialize/specialization_graph.rs
src/librustc/traits/structural_impls.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_allocator/expand.rs
src/librustc_apfloat/lib.rs
src/librustc_back/README.md
src/librustc_back/target/mod.rs
src/librustc_borrowck/borrowck/README.md
src/librustc_borrowck/borrowck/mod.rs
src/librustc_const_eval/lib.rs
src/librustc_driver/README.md
src/librustc_driver/driver.rs
src/librustc_driver/lib.rs
src/librustc_errors/emitter.rs
src/librustc_errors/lib.rs
src/librustc_lint/builtin.rs
src/librustc_lint/lib.rs
src/librustc_lint/unused.rs
src/librustc_llvm/ffi.rs
src/librustc_metadata/creader.rs
src/librustc_metadata/cstore.rs
src/librustc_metadata/cstore_impl.rs
src/librustc_metadata/decoder.rs
src/librustc_metadata/encoder.rs
src/librustc_mir/build/mod.rs
src/librustc_mir/monomorphize/collector.rs
src/librustc_mir/util/borrowck_errors.rs
src/librustc_passes/ast_validation.rs
src/librustc_plugin/registry.rs
src/librustc_resolve/build_reduced_graph.rs
src/librustc_resolve/lib.rs
src/librustc_resolve/resolve_imports.rs
src/librustc_save_analysis/dump_visitor.rs
src/librustc_traits/lib.rs
src/librustc_traits/lowering.rs [new file with mode: 0644]
src/librustc_trans/README.md
src/librustc_trans/back/write.rs
src/librustc_trans/builder.rs
src/librustc_trans/common.rs
src/librustc_trans/intrinsic.rs
src/librustc_trans/lib.rs
src/librustc_trans_utils/lib.rs
src/librustc_trans_utils/trans_crate.rs
src/librustc_typeck/check/demand.rs
src/librustc_typeck/check/intrinsic.rs
src/librustc_typeck/check/method/suggest.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/upvar.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/highlight.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/librustdoc/visit_ast.rs
src/libstd/build.rs
src/libstd/io/buffered.rs
src/libstd/lib.rs
src/libstd/macros.rs
src/libsyntax/README.md
src/libsyntax/ast.rs
src/libsyntax/codemap.rs
src/libsyntax/diagnostics/plugin.rs
src/libsyntax/ext/base.rs
src/libsyntax/ext/build.rs
src/libsyntax/ext/expand.rs
src/libsyntax/ext/quote.rs
src/libsyntax/ext/tt/macro_parser.rs
src/libsyntax/ext/tt/macro_rules.rs
src/libsyntax/feature_gate.rs
src/libsyntax/fold.rs
src/libsyntax/json.rs
src/libsyntax/parse/attr.rs
src/libsyntax/parse/lexer/mod.rs
src/libsyntax/parse/mod.rs
src/libsyntax/parse/parser.rs
src/libsyntax/parse/token.rs
src/libsyntax/print/pprust.rs
src/libsyntax/std_inject.rs
src/libsyntax/test.rs
src/libsyntax/visit.rs
src/libsyntax_ext/assert.rs [new file with mode: 0644]
src/libsyntax_ext/deriving/generic/mod.rs
src/libsyntax_ext/env.rs
src/libsyntax_ext/global_asm.rs
src/libsyntax_ext/lib.rs
src/libsyntax_pos/lib.rs
src/libsyntax_pos/symbol.rs
src/rustllvm/RustWrapper.cpp
src/stage0.txt
src/test/compile-fail/auxiliary/unstable-macros.rs [new file with mode: 0644]
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-47309.rs [new file with mode: 0644]
src/test/compile-fail/issue-6804.rs
src/test/compile-fail/lint-unnecessary-import-braces.rs
src/test/compile-fail/macro-stability.rs [new file with mode: 0644]
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/simd-intrinsic-generic-reduction.rs [new file with mode: 0644]
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/parse-fail/issue-32501.rs
src/test/parse-fail/recover-enum2.rs
src/test/parse-fail/underscore-suffix-for-float.rs
src/test/run-make/hotplug_codegen_backend/the_backend.rs
src/test/run-pass-fulldeps/auxiliary/plugin_args.rs
src/test/run-pass-fulldeps/auxiliary/roman_numerals.rs
src/test/run-pass/assert-escape.rs [new file with mode: 0644]
src/test/run-pass/auxiliary/unstable-macros.rs [new file with mode: 0644]
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-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-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/macro-stability.rs [new file with mode: 0644]
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/simd-intrinsic-generic-reduction.rs [new file with mode: 0644]
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/chalkify/lower_impl.rs [new file with mode: 0644]
src/test/ui/chalkify/lower_impl.stderr [new file with mode: 0644]
src/test/ui/codemap_tests/issue-28308.rs
src/test/ui/codemap_tests/issue-28308.stderr
src/test/ui/cross-file-errors/main.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/issue-49074.rs [new file with mode: 0644]
src/test/ui/issue-49074.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/test/ui/underscore-ident-matcher.rs [new file with mode: 0644]
src/test/ui/underscore-ident-matcher.stderr [new file with mode: 0644]
src/test/ui/underscore-lifetime/dyn-trait-underscore.rs [new file with mode: 0644]
src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr [new file with mode: 0644]
src/tools/cargo
src/tools/clippy
src/tools/miri
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 b47f9163c0dacf7a08a9f93cc46f833e1db078cf..de7036db29f4afa5883a39e467731f8da575b764 100644 (file)
 # Indicate whether submodules are managed and updated automatically.
 #submodules = true
 
+# Update submodules only when the checked out commit in the submodules differs
+# from what is committed in the main rustc repo.
+#fast-submodules = true
+
 # The path to (or name of) the GDB executable to use. This is only used for
 # executing the debuginfo test suite.
 #gdb = "gdb"
 # 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 63a6b3c66a6a97e9f92b9c6b75749f77cb62f1ac..675457905eade8de5dcb485c065c7461aec2066e 100644 (file)
@@ -56,8 +56,11 @@ dependencies = [
 
 [[package]]
 name = "ansi_term"
-version = "0.10.2"
+version = "0.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+]
 
 [[package]]
 name = "ar"
@@ -181,12 +184,12 @@ 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.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)",
  "crypto-hash 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "curl 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "docopt 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -205,6 +208,7 @@ dependencies = [
  "libgit2-sys 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "miow 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-traits 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -232,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"
@@ -281,13 +273,13 @@ dependencies = [
 
 [[package]]
 name = "clap"
-version = "2.29.0"
+version = "2.31.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -296,15 +288,16 @@ dependencies = [
 
 [[package]]
 name = "clippy"
-version = "0.0.186"
+version = "0.0.188"
 dependencies = [
- "cargo_metadata 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cargo_metadata 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "clippy-mini-macro-test 0.2.0",
- "clippy_lints 0.0.186",
- "compiletest_rs 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "duct 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clippy_lints 0.0.188",
+ "compiletest_rs 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "derive-new 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "semver 0.9.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)",
 ]
@@ -315,36 +308,16 @@ version = "0.2.0"
 
 [[package]]
 name = "clippy_lints"
-version = "0.0.186"
-dependencies = [
- "if_chain 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "itertools 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "pulldown-cmark 0.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex-syntax 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "semver 0.6.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)",
- "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "clippy_lints"
-version = "0.0.187"
-source = "registry+https://github.com/rust-lang/crates.io-index"
+version = "0.0.188"
 dependencies = [
  "if_chain 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "itertools 0.6.5 (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)",
  "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "pulldown-cmark 0.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex-syntax 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex-syntax 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "semver 0.9.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)",
  "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -404,18 +377,20 @@ dependencies = [
 
 [[package]]
 name = "compiletest_rs"
-version = "0.3.6"
+version = "0.3.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "getopts 0.2.15 (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)",
- "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "miow 0.3.1 (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)",
  "tempdir 0.3.6 (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]]
@@ -561,34 +536,11 @@ dependencies = [
  "core 0.0.0",
 ]
 
-[[package]]
-name = "docopt"
-version = "0.8.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex 0.2.7 (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)",
- "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "dtoa"
 version = "0.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
-[[package]]
-name = "duct"
-version = "0.8.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "error-chain 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazycell 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "os_pipe 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "shared_child 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "either"
 version = "1.4.0"
@@ -624,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"
@@ -645,14 +588,6 @@ dependencies = [
  "termcolor 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
-[[package]]
-name = "error-chain"
-version = "0.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "backtrace 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "error-chain"
 version = "0.11.0"
@@ -905,7 +840,7 @@ version = "0.1.0"
 name = "installer"
 version = "0.0.0"
 dependencies = [
- "clap 2.29.0 (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)",
@@ -921,14 +856,6 @@ name = "is-match"
 version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
-[[package]]
-name = "itertools"
-version = "0.6.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "itertools"
 version = "0.7.6"
@@ -980,7 +907,7 @@ dependencies = [
 
 [[package]]
 name = "languageserver-types"
-version = "0.30.0"
+version = "0.31.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1001,11 +928,6 @@ name = "lazy_static"
 version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
-[[package]]
-name = "lazycell"
-version = "0.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
 [[package]]
 name = "lazycell"
 version = "0.6.0"
@@ -1111,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.29.0 (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)",
@@ -1161,17 +1083,6 @@ dependencies = [
  "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
-[[package]]
-name = "miow"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "net2 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "miow"
 version = "0.3.1"
@@ -1187,7 +1098,7 @@ version = "0.1.0"
 dependencies = [
  "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "cargo_metadata 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "compiletest_rs 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "compiletest_rs 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -1196,32 +1107,11 @@ dependencies = [
 name = "multiple_bins"
 version = "0.1.0"
 
-[[package]]
-name = "net2"
-version = "0.2.32"
-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)",
- "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "nibble_vec"
 version = "0.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
-[[package]]
-name = "nix"
-version = "0.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
- "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "nodrop"
 version = "0.1.12"
@@ -1308,16 +1198,6 @@ dependencies = [
  "vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
-[[package]]
-name = "os_pipe"
-version = "0.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "nix 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "owning_ref"
 version = "0.3.3"
@@ -1405,15 +1285,6 @@ dependencies = [
  "core 0.0.0",
 ]
 
-[[package]]
-name = "pulldown-cmark"
-version = "0.0.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "pulldown-cmark"
 version = "0.1.2"
@@ -1451,7 +1322,7 @@ name = "racer"
 version = "2.0.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "clap 2.29.0 (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)",
@@ -1550,11 +1421,6 @@ name = "regex-syntax"
 version = "0.3.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
-[[package]]
-name = "regex-syntax"
-version = "0.4.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
 [[package]]
 name = "regex-syntax"
 version = "0.5.0"
@@ -1586,12 +1452,12 @@ version = "0.126.0"
 dependencies = [
  "cargo 0.27.0",
  "cargo_metadata 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "clippy_lints 0.0.187 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clippy_lints 0.0.188",
  "env_logger 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "json 0.11.12 (registry+https://github.com/rust-lang/crates.io-index)",
  "jsonrpc-core 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "languageserver-types 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "languageserver-types 0.31.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1603,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)",
@@ -1667,7 +1533,7 @@ dependencies = [
 name = "rustbook"
 version = "0.1.0"
 dependencies = [
- "clap 2.29.0 (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)",
 ]
 
@@ -1698,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)",
@@ -1707,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)",
 ]
@@ -2179,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]]
@@ -2259,23 +2104,6 @@ name = "scopeguard"
 version = "0.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
-[[package]]
-name = "semver"
-version = "0.6.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)",
-]
-
-[[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"
@@ -2338,16 +2166,6 @@ dependencies = [
 name = "serialize"
 version = "0.0.0"
 
-[[package]]
-name = "shared_child"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "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)",
- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "shell-escape"
 version = "0.1.3"
@@ -2410,7 +2228,7 @@ dependencies = [
 
 [[package]]
 name = "strsim"
-version = "0.6.0"
+version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -2555,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"
@@ -2831,15 +2658,6 @@ dependencies = [
 name = "workspace_symbol"
 version = "0.1.0"
 
-[[package]]
-name = "ws2_32-sys"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "xattr"
 version = "0.1.11"
@@ -2865,7 +2683,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum advapi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e06588080cb19d0acb6739808aafa5f26bfb2ca015b2b6370028b44cf7cb8a9a"
 "checksum aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ca972c2ea5f742bfce5687b9aef75506a764f61d37f8f649047846a9686ddb66"
 "checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4"
-"checksum ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6b3568b48b7cefa6b8ce125f9bb4989e52fbcc29ebea88df04cc7c5f12f70455"
+"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
 "checksum ar 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "35c7a5669cb64f085739387e1308b74e6d44022464b7f1b63bbd4ceb6379ec31"
 "checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef"
 "checksum atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "af80143d6f7608d746df1520709e5d141c96f240b0e62b0aa41bdfb53374d9d4"
@@ -2877,17 +2695,15 @@ 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.29.0 (registry+https://github.com/rust-lang/crates.io-index)" = "110d43e343eb29f4f51c1db31beb879d546db27998577e5715270a54bcf41d3f"
-"checksum clippy_lints 0.0.187 (registry+https://github.com/rust-lang/crates.io-index)" = "f2227eeb80d00b3e6f67d27953224b2087a65e40597e3253b2a25493aac63859"
+"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"
-"checksum compiletest_rs 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "6c5aafb5d4a77c6b5fa384fe93c7a9a3561bd88c4b8b8e45187cf5e779b1badc"
+"checksum compiletest_rs 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "d47ca9a69772587159e1c7e20ee1e43dfe5f184d59591eac70e7d3603bdfe57a"
 "checksum core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "286e0b41c3a20da26536c6000a280585d519fd07b3956b43aed8a79e9edce980"
 "checksum core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "716c271e8613ace48344f723b60b900a93150271e5be206212d052bbc0883efa"
 "checksum crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "24ce9782d4d5c53674646a6a4c1863a21a8fc0cb649b3c94dfc16e45071dea19"
@@ -2899,18 +2715,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum curl-sys 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f46e49c7125131f5afaded06944d6888b55cbdf8eba05dae73c954019b907961"
 "checksum derive-new 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "92f8b8e1d6c8a5f5ea0849a0e4c55941576115c62d3fc425e96918bbbeb3d3c2"
 "checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a"
-"checksum docopt 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d8acd393692c503b168471874953a2531df0e9ab77d0b6bbc582395743300a4a"
 "checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab"
-"checksum duct 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e45aa15fe0a8a8f511e6d834626afd55e49b62e5c8802e18328a87e8a8f6065c"
 "checksum either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "740178ddf48b1a9e878e6d6509a1442a2d42fd2928aae8e7a6f8a36fb01981b3"
 "checksum ena 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f8b449f3b18c89d2dbe40548d2ee4fa58ea0a08b761992da6ecb9788e4688834"
 "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 error-chain 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6930e04918388a9a2e41d518c25cf679ccafe26733fb4127dbf21993f2575d46"
 "checksum failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "934799b6c1de475a012a02dab0ace1ace43789ee4b99bcfbf1a2e3e8ced5de82"
 "checksum failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c7cdda555bb90c9bb67a3b670a0f42de8e73f5981524123ad8578aafec8ddb8b"
 "checksum filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "714653f3e34871534de23771ac7b26e999651a0a228f47beb324dfdf1dd4b10f"
@@ -2935,17 +2747,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum if_chain 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "61bb90bdd39e3af69b0172dfc6130f6cd6332bf040fbb9bdd4401d37adbd48b8"
 "checksum ignore 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "245bea0ba52531a3739cb8ba99f8689eda13d7faf8c36b6a73ce4421aab42588"
 "checksum is-match 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7e5b386aef33a1c677be65237cb9d32c3f3ef56bd035949710c4bb13083eb053"
-"checksum itertools 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d3f2be4da1690a039e9ae5fd575f706a63ad5a2120f161b1d653c9da3930dd21"
 "checksum itertools 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b07332223953b5051bceb67e8c4700aa65291535568e1f12408c43c4a42c0394"
 "checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c"
 "checksum jobserver 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "9f2abd9fd3242accb0e2e30986f2cf30cda3e19eec5cc6d584b218ce2b1c0e3c"
 "checksum json 0.11.12 (registry+https://github.com/rust-lang/crates.io-index)" = "39ebf0fac977ee3a4a3242b6446004ff64514889e3e2730bbd4f764a67a2e483"
 "checksum jsonrpc-core 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ddf83704f4e79979a424d1082dd2c1e52683058056c9280efa19ac5f6bc9033c"
 "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
-"checksum languageserver-types 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1541f9b22687f060511d213036e1f058797c48e3501e177f01cb6e88de802f5b"
+"checksum languageserver-types 0.31.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d25086d59f44b80253d5ff96c66a692fb69de8485cf7a25b28677e89126de0d"
 "checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73"
 "checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d"
-"checksum lazycell 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3b585b7a6811fb03aa10e74b278a0f00f8dd9b45dc681f148bb29fa5cb61859b"
 "checksum lazycell 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a6f08839bc70ef4a3fe1d566d5350f519c5912ea86be0df1740a7d247c7fc0ef"
 "checksum libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)" = "f54263ad99207254cf58b5f701ecb432c717445ea2ee8af387334bdd1a03fdff"
 "checksum libgit2-sys 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1ecbd6428006c321c29b6c8a895f0d90152f1cf4fd8faab69fc436a3d9594f63"
@@ -2961,11 +2771,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d"
 "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3"
 "checksum miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "609ce024854aeb19a0ef7567d348aaa5a746b32fb72e336df7fcc16869d7e2b4"
-"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
 "checksum miow 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9224c91f82b3c47cf53dcf78dfaa20d6888fbcc5d272d5f2fcdf8a697f3c987d"
-"checksum net2 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)" = "9044faf1413a1057267be51b5afba8eb1090bd2231c693664aa1db716fe1eae0"
 "checksum nibble_vec 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "62e678237a4c70c5f2b917cefd7d080dfbf800421f06e8a59d4e28ef5130fd9e"
-"checksum nix 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "47e49f6982987135c5e9620ab317623e723bd06738fd85377e8d55f57c8b6487"
 "checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2"
 "checksum num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "4703ad64153382334aa8db57c637364c322d3372e097840c72000dabdcf6156e"
 "checksum num-integer 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f8d26da319fb45674985c78f1d1caf99aa4941f785d384a2ae36d0740bc3e2fe"
@@ -2977,7 +2784,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum openssl 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1636c9f1d78af9cbcc50e523bfff4a30274108aad5e86761afd4d31e4e184fa7"
 "checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de"
 "checksum openssl-sys 0.9.27 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fdc5c4a02e69ce65046f1763a0181107038e02176233acb0b3351d7cc588f9"
-"checksum os_pipe 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "998bfbb3042e715190fe2a41abfa047d7e8cb81374d2977d7f100eacd8619cb1"
 "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37"
 "checksum parking_lot 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3e7f7c9857874e54afeb950eebeae662b1e51a2493666d2ea4c0a5d91dcf0412"
 "checksum parking_lot_core 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "538ef00b7317875071d5e00f603f24d16f0b474c1a5fc0ccb8b454ca72eafa79"
@@ -2985,7 +2791,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum pest 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0a6dda33d67c26f0aac90d324ab2eb7239c819fc7b2552fe9faa4fe88441edc8"
 "checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903"
 "checksum proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cd07deb3c6d1d9ff827999c7f9b04cdfd66b1b17ae508e14fe47b620f2282ae0"
-"checksum pulldown-cmark 0.0.15 (registry+https://github.com/rust-lang/crates.io-index)" = "378e941dbd392c101f2cb88097fa4d7167bc421d4b88de3ff7dbee503bc3233b"
 "checksum pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fdf85cda6cadfae5428a54661d431330b312bc767ddbc57adbedc24da66e32"
 "checksum quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eda5fe9b71976e62bc81b781206aaa076401769b2143379d3eb2118388babac4"
 "checksum quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "07589615d719a60c8dd8a4622e7946465dfef20d1a428f969e3443e7386d5f45"
@@ -3001,7 +2806,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f"
 "checksum regex 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a62bf8bb734ab90b7f234b681b01af396e5d39b028906c210dc04fa1d5e9e5b3"
 "checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957"
-"checksum regex-syntax 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8e931c58b93d86f080c734bfd2bce7dd0079ae2331235818133c8be7f422e20e"
 "checksum regex-syntax 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "48d7391e7e90e06eaf3aefbe4652464153ecfec64806f3bf77ffc59638a63e77"
 "checksum remove_dir_all 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b5d2f806b0fcdabd98acd380dc8daef485e22bcb7cddc811d1337967f2528cf5"
 "checksum rls-analysis 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fd4b9a3a3f2345854e39768e6425d1c893855da217183d1c0b3ff6f1664b6b6d"
@@ -3010,22 +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.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3186ec9e65071a2095434b1f5bb24838d4e8e130f584c790f6033c79943537"
-"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"
@@ -3033,13 +2834,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum serde_derive_internals 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1fc848d073be32cd982380c06587ea1d433bc1a4c4a111de07ec2286a3ddade8"
 "checksum serde_ignored 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "190e9765dcedb56be63b6e0993a006c7e3b071a016a304736e4a315dc01fb142"
 "checksum serde_json 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "57781ed845b8e742fc2bf306aba8e3b408fe8c366b900e3769fbc39f49eb8b39"
-"checksum shared_child 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "099b38928dbe4a0a01fcd8c233183072f14a7d126a34bed05880869be66e14cc"
 "checksum shell-escape 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "dd5cc96481d54583947bfe88bf30c23d53f883c6cd0145368b69989d97b84ef8"
 "checksum shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2"
 "checksum smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44db0ecb22921ef790d17ae13a3f6d15784183ff5f2a01aa32098c7498d2b4b9"
 "checksum socket2 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "78e4c1cde1adbc6bc4c394da2e7727c916b9b7d0b53d6984c890c65c1f4e6437"
 "checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b"
-"checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694"
+"checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550"
 "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad"
 "checksum syn 0.12.14 (registry+https://github.com/rust-lang/crates.io-index)" = "8c5bc2d6ff27891209efa5f63e9de78648d7801f085e4653701a692ce938d6fd"
 "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
@@ -3050,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"
@@ -3084,7 +2885,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
 "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
 "checksum wincolor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "eeb06499a3a4d44302791052df005d5232b927ed1a9658146d842165c4de7767"
-"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
 "checksum xattr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "5f04de8a1346489a2f9e9bd8526b73d135ec554227b17568456e86aa35b6f3fc"
 "checksum xz2 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "98df591c3504d014dd791d998123ed00a476c7e26dc6b2e873cb55c6ac9e59fa"
 "checksum yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e66366e18dc58b46801afbf2ca7661a9f59cc8c5962c29892b6039b4f86fa992"
index c03301852cd3b97de7ab1af12570ba23e1b331c7..814c054c51e41eaff3c6b155110474f8a252c3e8 100644 (file)
@@ -72,3 +72,4 @@ cargo = { path = "tools/cargo" }
 # RLS depends on `rustfmt` from crates.io, so we put this in a `[patch]` section
 # for crates.io
 rustfmt-nightly = { path = "tools/rustfmt" }
+clippy_lints = { path = "tools/clippy/clippy_lints" }
index d8f7cd7ed9227377fefbfe93a2c9bc16de1f19a5..b55a133501d8eefc126966df971bd848c830179b 100644 (file)
@@ -597,10 +597,8 @@ class RustBuild(object):
                 self.cargo()))
         args = [self.cargo(), "build", "--manifest-path",
                 os.path.join(self.rust_root, "src/bootstrap/Cargo.toml")]
-        if self.verbose:
+        for _ in range(1, self.verbose):
             args.append("--verbose")
-            if self.verbose > 1:
-                args.append("--verbose")
         if self.use_locked_deps:
             args.append("--locked")
         if self.use_vendored_sources:
@@ -614,20 +612,55 @@ class RustBuild(object):
             return config
         return default_build_triple()
 
+    def check_submodule(self, module, slow_submodules):
+        if not slow_submodules:
+            checked_out = subprocess.Popen(["git", "rev-parse", "HEAD"],
+                                           cwd=os.path.join(self.rust_root, module),
+                                           stdout=subprocess.PIPE)
+            return checked_out
+        else:
+            return None
+
+    def update_submodule(self, module, checked_out, recorded_submodules):
+        module_path = os.path.join(self.rust_root, module)
+
+        if checked_out != None:
+            default_encoding = sys.getdefaultencoding()
+            checked_out = checked_out.communicate()[0].decode(default_encoding).strip()
+            if recorded_submodules[module] == checked_out:
+                return
+
+        print("Updating submodule", module)
+
+        run(["git", "submodule", "-q", "sync", module],
+            cwd=self.rust_root, verbose=self.verbose)
+        run(["git", "submodule", "update",
+            "--init", "--recursive", module],
+            cwd=self.rust_root, verbose=self.verbose)
+        run(["git", "reset", "-q", "--hard"],
+            cwd=module_path, verbose=self.verbose)
+        run(["git", "clean", "-qdfx"],
+            cwd=module_path, verbose=self.verbose)
+
     def update_submodules(self):
         """Update submodules"""
         if (not os.path.exists(os.path.join(self.rust_root, ".git"))) or \
                 self.get_toml('submodules') == "false":
             return
-        print('Updating submodules')
+        slow_submodules = self.get_toml('fast-submodule') == "false"
+        start_time = time()
+        if slow_submodules:
+            print('Unconditionally updating all submodules')
+        else:
+            print('Updating only changed submodules')
         default_encoding = sys.getdefaultencoding()
-        run(["git", "submodule", "-q", "sync"], cwd=self.rust_root, verbose=self.verbose)
         submodules = [s.split(' ', 1)[1] for s in subprocess.check_output(
             ["git", "config", "--file",
              os.path.join(self.rust_root, ".gitmodules"),
              "--get-regexp", "path"]
         ).decode(default_encoding).splitlines()]
         filtered_submodules = []
+        submodules_names = []
         for module in submodules:
             if module.endswith("llvm"):
                 if self.get_toml('llvm-config'):
@@ -645,16 +678,19 @@ class RustBuild(object):
                 config = self.get_toml('lld')
                 if config is None or config == 'false':
                     continue
-            filtered_submodules.append(module)
-        run(["git", "submodule", "update",
-             "--init", "--recursive"] + filtered_submodules,
-            cwd=self.rust_root, verbose=self.verbose)
-        run(["git", "submodule", "-q", "foreach", "git",
-             "reset", "-q", "--hard"],
-            cwd=self.rust_root, verbose=self.verbose)
-        run(["git", "submodule", "-q", "foreach", "git",
-             "clean", "-qdfx"],
-            cwd=self.rust_root, verbose=self.verbose)
+            check = self.check_submodule(module, slow_submodules)
+            filtered_submodules.append((module, check))
+            submodules_names.append(module)
+        recorded = subprocess.Popen(["git", "ls-tree", "HEAD"] + submodules_names,
+                                    cwd=self.rust_root, stdout=subprocess.PIPE)
+        recorded = recorded.communicate()[0].decode(default_encoding).strip().splitlines()
+        recorded_submodules = {}
+        for data in recorded:
+            data = data.split()
+            recorded_submodules[data[3]] = data[2]
+        for module in filtered_submodules:
+            self.update_submodule(module[0], module[1], recorded_submodules)
+        print("Submodules updated in %.2f seconds" % (time() - start_time))
 
     def set_dev_environment(self):
         """Set download URL for development environment"""
@@ -675,7 +711,7 @@ def bootstrap(help_triggered):
     parser.add_argument('--config')
     parser.add_argument('--build')
     parser.add_argument('--clean', action='store_true')
-    parser.add_argument('-v', '--verbose', action='store_true')
+    parser.add_argument('-v', '--verbose', action='count', default=0)
 
     args = [a for a in sys.argv if a != '-h' and a != '--help']
     args, _ = parser.parse_known_args(args)
@@ -691,10 +727,9 @@ def bootstrap(help_triggered):
     except (OSError, IOError):
         pass
 
-    if '\nverbose = 2' in build.config_toml:
-        build.verbose = 2
-    elif '\nverbose = 1' in build.config_toml:
-        build.verbose = 1
+    match = re.search(r'\nverbose = (\d+)', build.config_toml)
+    if match is not None:
+        build.verbose = max(build.verbose, int(match.group(1)))
 
     build.use_vendored_sources = '\nvendor = true' in build.config_toml
 
index fab7a2b3fcc5c01993d26d20462fa786090416ba..675d3dd437eef9deb3cc60d7956b038628c81e05 100644 (file)
@@ -309,8 +309,8 @@ macro_rules! describe {
                 test::CompileFailFullDeps, test::IncrementalFullDeps, test::Rustdoc, test::Pretty,
                 test::RunPassPretty, test::RunFailPretty, test::RunPassValgrindPretty,
                 test::RunPassFullDepsPretty, test::RunFailFullDepsPretty, test::RunMake,
-                test::Crate, test::CrateLibrustc, test::Rustdoc, test::Linkcheck, test::Cargotest,
-                test::Cargo, test::Rls, test::ErrorIndex, test::Distcheck,
+                test::Crate, test::CrateLibrustc, test::CrateRustdoc, test::Linkcheck,
+                test::Cargotest, test::Cargo, test::Rls, test::ErrorIndex, test::Distcheck,
                 test::Nomicon, test::Reference, test::RustdocBook, test::RustByExample,
                 test::TheBook, test::UnstableBook,
                 test::Rustfmt, test::Miri, test::Clippy, test::RustdocJS, test::RustdocTheme),
@@ -763,7 +763,7 @@ pub fn cargo(&self,
             cargo.env("WINAPI_NO_BUNDLED_LIBRARIES", "1");
         }
 
-        if self.is_very_verbose() {
+        for _ in 1..self.verbosity {
             cargo.arg("-v");
         }
 
index 9e1b1f7db2f991a7c9774cef39f16331d52cde07..8f393a4c573716e38eecc660f4a412a1a0ed1a1c 100644 (file)
@@ -77,7 +77,7 @@ pub fn find(build: &mut Build) {
                                .collect::<HashSet<_>>();
     for target in targets.into_iter() {
         let mut cfg = cc::Build::new();
-        cfg.cargo_metadata(false).opt_level(0).warnings(false).debug(false)
+        cfg.cargo_metadata(false).opt_level(2).warnings(false).debug(false)
            .target(&target).host(&build.build);
         if target.contains("msvc") {
             cfg.static_crt(true);
@@ -109,7 +109,7 @@ pub fn find(build: &mut Build) {
     let hosts = build.hosts.iter().cloned().chain(iter::once(build.build)).collect::<HashSet<_>>();
     for host in hosts.into_iter() {
         let mut cfg = cc::Build::new();
-        cfg.cargo_metadata(false).opt_level(0).warnings(false).debug(false).cpp(true)
+        cfg.cargo_metadata(false).opt_level(2).warnings(false).debug(false).cpp(true)
            .target(&host).host(&build.build);
         let config = build.config.target_config.get(&host);
         if let Some(cxx) = config.and_then(|c| c.cxx.as_ref()) {
index c3d8c9f8c010d4019e526f9886489479040176f4..eca06eac7f30788fc7d53e8b723fc53c479ed154 100644 (file)
@@ -203,11 +203,14 @@ fn make_win_dist(
         "libbcrypt.a",
         "libcomctl32.a",
         "libcomdlg32.a",
+        "libcredui.a",
         "libcrypt32.a",
+        "libdbghelp.a",
         "libgdi32.a",
         "libimagehlp.a",
         "libiphlpapi.a",
         "libkernel32.a",
+        "libmsimg32.a",
         "libmsvcrt.a",
         "libodbc32.a",
         "libole32.a",
@@ -215,8 +218,10 @@ fn make_win_dist(
         "libopengl32.a",
         "libpsapi.a",
         "librpcrt4.a",
+        "libsecur32.a",
         "libsetupapi.a",
         "libshell32.a",
+        "libsynchronization.a",
         "libuser32.a",
         "libuserenv.a",
         "libuuid.a",
@@ -225,8 +230,6 @@ fn make_win_dist(
         "libwinspool.a",
         "libws2_32.a",
         "libwsock32.a",
-        "libdbghelp.a",
-        "libmsimg32.a",
     ];
 
     //Find mingw artifacts we want to bundle
@@ -1120,7 +1123,7 @@ fn run(self, builder: &Builder) -> Option<PathBuf> {
         // state for RLS isn't testing.
         let rls = builder.ensure(tool::Rls {
             compiler: builder.compiler(stage, build.build),
-            target
+            target, extra_features: Vec::new()
         }).or_else(|| { println!("Unable to build RLS, skipping dist"); None })?;
 
         install(&rls, &image.join("bin"), 0o755);
@@ -1199,11 +1202,11 @@ fn run(self, builder: &Builder) -> Option<PathBuf> {
         // Prepare the image directory
         let rustfmt = builder.ensure(tool::Rustfmt {
             compiler: builder.compiler(stage, build.build),
-            target
+            target, extra_features: Vec::new()
         }).or_else(|| { println!("Unable to build Rustfmt, skipping dist"); None })?;
         let cargofmt = builder.ensure(tool::Cargofmt {
             compiler: builder.compiler(stage, build.build),
-            target
+            target, extra_features: Vec::new()
         }).or_else(|| { println!("Unable to build Cargofmt, skipping dist"); None })?;
 
         install(&rustfmt, &image.join("bin"), 0o755);
index af50ad1e96b9f184039dc17c15503feb322e4ff9..c5af0f8e2e15331cc45fbf779b471731cde82149 100644 (file)
@@ -29,7 +29,7 @@
 
 /// Deserialized version of all flags for this compile.
 pub struct Flags {
-    pub verbose: usize, // verbosity level: 0 == not verbose, 1 == verbose, 2 == very verbose
+    pub verbose: usize, // number of -v args; each extra -v after the first is passed to Cargo
     pub on_fail: Option<String>,
     pub stage: Option<u32>,
     pub keep_stage: Option<u32>,
index 938237dd82d52cad9e0662aa01d2054dd7a10eea..b778ba33d89ccfd06e71d372596400c509ffd1b4 100644 (file)
 
 #![deny(warnings)]
 #![feature(core_intrinsics)]
+#![feature(slice_concat_ext)]
 
 #[macro_use]
 extern crate build_helper;
@@ -605,10 +606,6 @@ pub fn is_verbose(&self) -> bool {
         self.verbosity > 0
     }
 
-    pub fn is_very_verbose(&self) -> bool {
-        self.verbosity > 1
-    }
-
     /// Prints a message if this build is configured in verbose mode.
     fn verbose(&self, msg: &str) {
         if self.is_verbose() {
index d5c837c1274980ddcb5650a73d4154393c9c846b..de938ec8e8306a9f828c8e14b5d1b8f02466c83c 100644 (file)
@@ -245,7 +245,7 @@ fn run(self, builder: &Builder) {
         let host = self.host;
         let compiler = builder.compiler(stage, host);
 
-        builder.ensure(tool::Rls { compiler, target: self.host });
+        builder.ensure(tool::Rls { compiler, target: self.host, extra_features: Vec::new() });
         let mut cargo = tool::prepare_tool_cargo(builder,
                                                  compiler,
                                                  host,
@@ -291,7 +291,7 @@ fn run(self, builder: &Builder) {
         let host = self.host;
         let compiler = builder.compiler(stage, host);
 
-        builder.ensure(tool::Rustfmt { compiler, target: self.host });
+        builder.ensure(tool::Rustfmt { compiler, target: self.host, extra_features: Vec::new() });
         let mut cargo = tool::prepare_tool_cargo(builder,
                                                  compiler,
                                                  host,
@@ -339,7 +339,12 @@ fn run(self, builder: &Builder) {
         let host = self.host;
         let compiler = builder.compiler(stage, host);
 
-        if let Some(miri) = builder.ensure(tool::Miri { compiler, target: self.host }) {
+        let miri = builder.ensure(tool::Miri {
+            compiler,
+            target: self.host,
+            extra_features: Vec::new(),
+        });
+        if let Some(miri) = miri {
             let mut cargo = builder.cargo(compiler, Mode::Tool, host, "test");
             cargo.arg("--manifest-path").arg(build.src.join("src/tools/miri/Cargo.toml"));
 
@@ -391,7 +396,12 @@ fn run(self, builder: &Builder) {
         let host = self.host;
         let compiler = builder.compiler(stage, host);
 
-        if let Some(clippy) = builder.ensure(tool::Clippy { compiler, target: self.host }) {
+        let clippy = builder.ensure(tool::Clippy {
+            compiler,
+            target: self.host,
+            extra_features: Vec::new(),
+        });
+        if let Some(clippy) = clippy {
             let mut cargo = builder.cargo(compiler, Mode::Tool, host, "test");
             cargo.arg("--manifest-path").arg(build.src.join("src/tools/clippy/Cargo.toml"));
 
index 9036eb044b5a5677a86d58b15bb0b354de0a0aaf..5f5b10a07b865893cc3c0750ccf0961b42ed8b4d 100644 (file)
@@ -12,6 +12,7 @@
 use std::env;
 use std::path::PathBuf;
 use std::process::{Command, exit};
+use std::slice::SliceConcatExt;
 
 use Mode;
 use Compiler;
@@ -74,7 +75,7 @@ fn run(self, builder: &Builder) {
     }
 }
 
-#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
+#[derive(Debug, Clone, Hash, PartialEq, Eq)]
 struct ToolBuild {
     compiler: Compiler,
     target: Interned<String>,
@@ -82,6 +83,7 @@ struct ToolBuild {
     path: &'static str,
     mode: Mode,
     is_ext_tool: bool,
+    extra_features: Vec<String>,
 }
 
 impl Step for ToolBuild {
@@ -114,6 +116,7 @@ fn run(self, builder: &Builder) -> Option<PathBuf> {
         println!("Building stage{} tool {} ({})", compiler.stage, tool, target);
 
         let mut cargo = prepare_tool_cargo(builder, compiler, target, "build", path);
+        cargo.arg("--features").arg(self.extra_features.join(" "));
         let is_expected = build.try_run(&mut cargo);
         build.save_toolstate(tool, if is_expected {
             ToolState::TestFail
@@ -242,6 +245,7 @@ fn run(self, builder: &Builder) -> PathBuf {
                     mode: $mode,
                     path: $path,
                     is_ext_tool: false,
+                    extra_features: Vec::new(),
                 }).expect("expected to build -- essential tool")
             }
         }
@@ -291,6 +295,7 @@ fn run(self, builder: &Builder) -> PathBuf {
             mode: Mode::Libstd,
             path: "src/tools/remote-test-server",
             is_ext_tool: false,
+            extra_features: Vec::new(),
         }).expect("expected to build -- essential tool")
     }
 }
@@ -409,6 +414,7 @@ fn run(self, builder: &Builder) -> PathBuf {
             mode: Mode::Librustc,
             path: "src/tools/cargo",
             is_ext_tool: false,
+            extra_features: Vec::new(),
         }).expect("expected to build -- essential tool")
     }
 }
@@ -421,10 +427,11 @@ macro_rules! tool_extended {
        $tool_name:expr,
        $extra_deps:block;)+) => {
         $(
-            #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
+            #[derive(Debug, Clone, Hash, PartialEq, Eq)]
         pub struct $name {
             pub compiler: Compiler,
             pub target: Interned<String>,
+            pub extra_features: Vec<String>,
         }
 
         impl Step for $name {
@@ -441,10 +448,12 @@ fn make_run(run: RunConfig) {
                 run.builder.ensure($name {
                     compiler: run.builder.compiler(run.builder.top_stage, run.builder.build.build),
                     target: run.target,
+                    extra_features: Vec::new(),
                 });
             }
 
-            fn run($sel, $builder: &Builder) -> Option<PathBuf> {
+            #[allow(unused_mut)]
+            fn run(mut $sel, $builder: &Builder) -> Option<PathBuf> {
                 $extra_deps
                 $builder.ensure(ToolBuild {
                     compiler: $sel.compiler,
@@ -452,6 +461,7 @@ fn run($sel, $builder: &Builder) -> Option<PathBuf> {
                     tool: $tool_name,
                     mode: Mode::Librustc,
                     path: $path,
+                    extra_features: $sel.extra_features,
                     is_ext_tool: true,
                 })
             }
@@ -472,6 +482,14 @@ fn run($sel, $builder: &Builder) -> Option<PathBuf> {
     };
     Miri, miri, "src/tools/miri", "miri", {};
     Rls, rls, "src/tools/rls", "rls", {
+        let clippy = builder.ensure(Clippy {
+            compiler: self.compiler,
+            target: self.target,
+            extra_features: Vec::new(),
+        });
+        if clippy.is_some() {
+            self.extra_features.push("clippy".to_owned());
+        }
         builder.ensure(native::Openssl {
             target: self.target,
         });
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 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 372d606e4572222c1423ce6de400ef72c026c329..c13ad39e5e1d598a8f9b40f15ff572a271417a4d 100644 (file)
@@ -228,14 +228,6 @@ unsafe fn shrink_in_place(&mut self,
     }
 }
 
-/// An arbitrary non-null address to represent zero-size allocations.
-///
-/// This preserves the non-null invariant for types like `Box<T>`. The address
-/// may overlap with non-zero-size memory allocations.
-#[rustc_deprecated(since = "1.19.0", reason = "Use Unique/NonNull::empty() instead")]
-#[unstable(feature = "heap_api", issue = "27700")]
-pub const EMPTY: *mut () = 1 as *mut ();
-
 /// The allocator for unique pointers.
 // This function must not unwind. If it does, MIR trans will fail.
 #[cfg(not(test))]
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 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 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 52eb9f29d57a1856ad66023fee7d68e65f4ceca5..8a87bea71e2530cf9562698aa6650955a854cc33 100644 (file)
@@ -76,6 +76,7 @@ macro_rules! panic {
 /// ```
 #[macro_export]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg(stage0)]
 macro_rules! assert {
     ($cond:expr) => (
         if !$cond {
@@ -784,4 +785,18 @@ macro_rules! include {
         ($file:expr) => ({ /* compiler built-in */ });
         ($file:expr,) => ({ /* compiler built-in */ });
     }
+
+    /// Ensure that a boolean expression is `true` at runtime.
+    ///
+    /// For more information, see the documentation for [`std::assert!`].
+    ///
+    /// [`std::assert!`]: ../std/macro.assert.html
+    #[macro_export]
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[cfg(dox)]
+    macro_rules! assert {
+        ($cond:expr) => ({ /* compiler built-in */ });
+        ($cond:expr,) => ({ /* compiler built-in */ });
+        ($cond:expr, $($arg:tt)+) => ({ /* compiler built-in */ });
+    }
 }
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 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 1163c1a98d5acd3ae1ad68796f6ed1cfac850331..b239f8018bebb9207b22527fcb834efddf33c9e0 100644 (file)
@@ -680,7 +680,6 @@ fn joint(first: char, rest: Token, is_joint: bool, span: &mut syntax_pos::Span,
             Pound => op!('#'),
             Dollar => op!('$'),
             Question => op!('?'),
-            Underscore => op!('_'),
 
             Ident(ident) | Lifetime(ident) => TokenNode::Term(Term(ident.name)),
             Literal(..) | DocComment(..) => TokenNode::Literal(self::Literal(token)),
@@ -743,7 +742,6 @@ fn to_internal(self) -> tokenstream::TokenStream {
             '#' => Pound,
             '$' => Dollar,
             '?' => Question,
-            '_' => Underscore,
             _ => panic!("unsupported character {}", op),
         };
 
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 13cf7a9ec8f1ee4e8905dea3320e4cd37c32cf67..1e2e4e5a69fa1ad0b9ef05757976eabc03b236bc 100644 (file)
@@ -651,6 +651,8 @@ pub fn fingerprint_needed_for_crate_hash(self) -> bool {
     [] GetSymbolExportLevel(DefId),
 
     [input] Features,
+
+    [] ProgramClausesFor(DefId),
 );
 
 trait DepNodeParams<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> : fmt::Debug {
index 210bdd8d5ddca7ae8758eceff5814dd280246282..0ad79eacd2b03f9a04981bf5d2a4e9db918b7089 100644 (file)
@@ -648,8 +648,15 @@ pub fn try_mark_green<'tcx>(&self,
                                 return None
                             }
                             None => {
-                                bug!("try_mark_green() - Forcing the DepNode \
-                                      should have set its color")
+                                if !tcx.sess.has_errors() {
+                                    bug!("try_mark_green() - Forcing the DepNode \
+                                          should have set its color")
+                                } else {
+                                    // If the query we just forced has resulted
+                                    // in some kind of compilation error, we
+                                    // don't expect that the corresponding
+                                    // dep-node color has been updated.
+                                }
                             }
                         }
                     } else {
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 b804cf7bf5a34d532f4917f7a385610770e2001f..972278bdf865fb5bd61db6acc405caa4e05f4c16 100644 (file)
@@ -444,10 +444,10 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
     visitor.visit_vis(&item.vis);
     visitor.visit_name(item.span, item.name);
     match item.node {
-        ItemExternCrate(opt_name) => {
+        ItemExternCrate(orig_name) => {
             visitor.visit_id(item.id);
-            if let Some(name) = opt_name {
-                visitor.visit_name(item.span, name);
+            if let Some(orig_name) = orig_name {
+                visitor.visit_name(item.span, orig_name);
             }
         }
         ItemUse(ref path, _) => {
index 49611689fc4af5c8b883254cbe10909b9bd24bd0..1439410f7e9aa2ac025f2d23b92363cc77a1f9ff 100644 (file)
@@ -879,7 +879,7 @@ fn lower_ty(&mut self, t: &Ty, itctx: ImplTraitContext) -> P<hir::Ty> {
             TyKind::Slice(ref ty) => hir::TySlice(self.lower_ty(ty, itctx)),
             TyKind::Ptr(ref mt) => hir::TyPtr(self.lower_mt(mt, itctx)),
             TyKind::Rptr(ref region, ref mt) => {
-                let span = t.span.with_hi(t.span.lo());
+                let span = t.span.shrink_to_lo();
                 let lifetime = match *region {
                     Some(ref lt) => self.lower_lifetime(lt),
                     None => self.elided_lifetime(span)
@@ -1355,17 +1355,11 @@ fn lower_path_extra(&mut self,
                         id: NodeId,
                         p: &Path,
                         name: Option<Name>,
-                        param_mode: ParamMode,
-                        defaults_to_global: bool)
+                        param_mode: ParamMode)
                         -> hir::Path {
-        let mut segments = p.segments.iter();
-        if defaults_to_global && p.is_global() {
-            segments.next();
-        }
-
         hir::Path {
             def: self.expect_full_def(id),
-            segments: segments.map(|segment| {
+            segments: p.segments.iter().map(|segment| {
                 self.lower_path_segment(p.span, segment, param_mode, 0,
                                         ParenthesizedGenericArgs::Err,
                                         ImplTraitContext::Disallowed)
@@ -1378,10 +1372,9 @@ fn lower_path_extra(&mut self,
     fn lower_path(&mut self,
                   id: NodeId,
                   p: &Path,
-                  param_mode: ParamMode,
-                  defaults_to_global: bool)
+                  param_mode: ParamMode)
                   -> hir::Path {
-        self.lower_path_extra(id, p, None, param_mode, defaults_to_global)
+        self.lower_path_extra(id, p, None, param_mode)
     }
 
     fn lower_path_segment(&mut self,
@@ -1904,7 +1897,7 @@ fn lower_item_kind(&mut self,
                        i: &ItemKind)
                        -> hir::Item_ {
         match *i {
-            ItemKind::ExternCrate(string) => hir::ItemExternCrate(string),
+            ItemKind::ExternCrate(orig_name) => hir::ItemExternCrate(orig_name),
             ItemKind::Use(ref use_tree) => {
                 // Start with an empty prefix
                 let prefix = Path {
@@ -2047,8 +2040,8 @@ fn lower_use_tree(&mut self,
         let path = &tree.prefix;
 
         match tree.kind {
-            UseTreeKind::Simple(ident) => {
-                *name = ident.name;
+            UseTreeKind::Simple(rename) => {
+                *name = tree.ident().name;
 
                 // First apply the prefix to the path
                 let mut path = Path {
@@ -2064,12 +2057,12 @@ fn lower_use_tree(&mut self,
                 if path.segments.len() > 1 &&
                    path.segments.last().unwrap().identifier.name == keywords::SelfValue.name() {
                     let _ = path.segments.pop();
-                    if ident.name == keywords::SelfValue.name() {
+                    if rename.is_none() {
                         *name = path.segments.last().unwrap().identifier.name;
                     }
                 }
 
-                let path = P(self.lower_path(id, &path, ParamMode::Explicit, true));
+                let path = P(self.lower_path(id, &path, ParamMode::Explicit));
                 hir::ItemUse(path, hir::UseKind::Single)
             }
             UseTreeKind::Glob => {
@@ -2080,7 +2073,7 @@ fn lower_use_tree(&mut self,
                         .cloned()
                         .collect(),
                     span: path.span,
-                }, ParamMode::Explicit, true));
+                }, ParamMode::Explicit));
                 hir::ItemUse(path, hir::UseKind::Glob)
             }
             UseTreeKind::Nested(ref trees) => {
@@ -2136,7 +2129,7 @@ fn lower_use_tree(&mut self,
                 // Privatize the degenerate import base, used only to check
                 // the stability of `use a::{};`, to avoid it showing up as
                 // a re-export by accident when `pub`, e.g. in documentation.
-                let path = P(self.lower_path(id, &prefix, ParamMode::Explicit, true));
+                let path = P(self.lower_path(id, &prefix, ParamMode::Explicit));
                 *vis = hir::Inherited;
                 hir::ItemUse(path, hir::UseKind::ListStem)
             }
@@ -3379,7 +3372,7 @@ fn lower_visibility(&mut self,
             VisibilityKind::Crate(..) => hir::Visibility::Crate,
             VisibilityKind::Restricted { ref path, id, .. } => {
                 hir::Visibility::Restricted {
-                    path: P(self.lower_path(id, path, ParamMode::Explicit, true)),
+                    path: P(self.lower_path(id, path, ParamMode::Explicit)),
                     id: if let Some(owner) = explicit_owner {
                         self.lower_node_id_with_owner(id, owner).node_id
                     } else {
index f4638c23c5f4bf35c721f6e8f7915e42064061fa..5ae84f5685eafca61a09c0716dd2de7ff76d7a56 100644 (file)
@@ -214,7 +214,7 @@ pub fn name(&self) -> Name {
         use self::LifetimeName::*;
         match *self {
             Implicit => keywords::Invalid.name(),
-            Underscore => Symbol::intern("'_"),
+            Underscore => keywords::UnderscoreLifetime.name(),
             Static => keywords::StaticLifetime.name(),
             Name(name) => name,
         }
@@ -2011,9 +2011,9 @@ pub struct Item {
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub enum Item_ {
-    /// An `extern crate` item, with optional original crate name,
+    /// An `extern crate` item, with optional *original* crate name if the crate was renamed.
     ///
-    /// e.g. `extern crate foo` or `extern crate foo_bar as foo`
+    /// E.g. `extern crate foo` or `extern crate foo_bar as foo`
     ItemExternCrate(Option<Name>),
 
     /// `use foo::bar::*;` or `use foo::bar::baz as quux;`
index 9e755f366a7de39bb8b1cc0d794f1266477e81a3..3d38c0c8ed9e57f396076d84786fdc54bdc13e43 100644 (file)
@@ -524,15 +524,10 @@ pub fn print_item(&mut self, item: &hir::Item) -> io::Result<()> {
         self.print_outer_attributes(&item.attrs)?;
         self.ann.pre(self, NodeItem(item))?;
         match item.node {
-            hir::ItemExternCrate(ref optional_path) => {
+            hir::ItemExternCrate(orig_name) => {
                 self.head(&visibility_qualified(&item.vis, "extern crate"))?;
-                if let Some(p) = *optional_path {
-                    let val = p.as_str();
-                    if val.contains("-") {
-                        self.print_string(&val, ast::StrStyle::Cooked)?;
-                    } else {
-                        self.print_name(p)?;
-                    }
+                if let Some(orig_name) = orig_name {
+                    self.print_name(orig_name)?;
                     self.s.space()?;
                     self.s.word("as")?;
                     self.s.space()?;
index c085b803085a853bb1eacbf6d630c577b0a28f86..e764cedd658b5df4070f031fcd0f5bc33c26c663 100644 (file)
@@ -851,7 +851,7 @@ fn hash_stable<W: StableHasherResult>(&self,
 }
 
 impl_stable_hash_for!(enum hir::Item_ {
-    ItemExternCrate(name),
+    ItemExternCrate(orig_name),
     ItemUse(path, use_kind),
     ItemStatic(ty, mutability, body_id),
     ItemConst(ty, body_id),
index 52f43fbed7b0acb3e8f255afebb7153847df042b..513b6c835f982337cb3b9f72b85e9a473446eab2 100644 (file)
@@ -287,7 +287,6 @@ fn hash_token<'a, 'gcx, W: StableHasherResult>(
         token::Token::Pound |
         token::Token::Dollar |
         token::Token::Question |
-        token::Token::Underscore |
         token::Token::Whitespace |
         token::Token::Comment |
         token::Token::Eof => {}
@@ -417,24 +416,27 @@ fn hash_stable<W: StableHasherResult>(&self,
         src_hash.hash_stable(hcx, hasher);
 
         // We only hash the relative position within this filemap
-        let lines = lines.borrow();
-        lines.len().hash_stable(hcx, hasher);
-        for &line in lines.iter() {
-            stable_byte_pos(line, start_pos).hash_stable(hcx, hasher);
-        }
+        lines.with_lock(|lines| {
+            lines.len().hash_stable(hcx, hasher);
+            for &line in lines.iter() {
+                stable_byte_pos(line, start_pos).hash_stable(hcx, hasher);
+            }
+        });
 
         // We only hash the relative position within this filemap
-        let multibyte_chars = multibyte_chars.borrow();
-        multibyte_chars.len().hash_stable(hcx, hasher);
-        for &char_pos in multibyte_chars.iter() {
-            stable_multibyte_char(char_pos, start_pos).hash_stable(hcx, hasher);
-        }
+        multibyte_chars.with_lock(|multibyte_chars| {
+            multibyte_chars.len().hash_stable(hcx, hasher);
+            for &char_pos in multibyte_chars.iter() {
+                stable_multibyte_char(char_pos, start_pos).hash_stable(hcx, hasher);
+            }
+        });
 
-        let non_narrow_chars = non_narrow_chars.borrow();
-        non_narrow_chars.len().hash_stable(hcx, hasher);
-        for &char_pos in non_narrow_chars.iter() {
-            stable_non_narrow_char(char_pos, start_pos).hash_stable(hcx, hasher);
-        }
+        non_narrow_chars.with_lock(|non_narrow_chars| {
+            non_narrow_chars.len().hash_stable(hcx, hasher);
+            for &char_pos in non_narrow_chars.iter() {
+                stable_non_narrow_char(char_pos, start_pos).hash_stable(hcx, hasher);
+            }
+        });
     }
 }
 
index bb3051b546e64d61e0131f9fec2789417f988a64..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
@@ -1285,3 +1331,86 @@ impl<'tcx, R> for struct infer::canonical::QueryResult<'tcx, R> {
 impl_stable_hash_for!(enum infer::canonical::Certainty {
     Proven, Ambiguous
 });
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for traits::WhereClauseAtom<'tcx> {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a>,
+                                          hasher: &mut StableHasher<W>) {
+        use traits::WhereClauseAtom::*;
+
+        mem::discriminant(self).hash_stable(hcx, hasher);
+        match self {
+            Implemented(trait_ref) => trait_ref.hash_stable(hcx, hasher),
+            ProjectionEq(projection) => projection.hash_stable(hcx, hasher),
+        }
+    }
+}
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for traits::DomainGoal<'tcx> {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a>,
+                                          hasher: &mut StableHasher<W>) {
+        use traits::DomainGoal::*;
+
+        mem::discriminant(self).hash_stable(hcx, hasher);
+        match self {
+            Holds(where_clause) |
+            WellFormed(where_clause) |
+            FromEnv(where_clause) => where_clause.hash_stable(hcx, hasher),
+
+            WellFormedTy(ty) => ty.hash_stable(hcx, hasher),
+            FromEnvTy(ty) => ty.hash_stable(hcx, hasher),
+            RegionOutlives(predicate) => predicate.hash_stable(hcx, hasher),
+            TypeOutlives(predicate) => predicate.hash_stable(hcx, hasher),
+        }
+    }
+}
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for traits::Goal<'tcx> {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a>,
+                                          hasher: &mut StableHasher<W>) {
+        use traits::Goal::*;
+
+        mem::discriminant(self).hash_stable(hcx, hasher);
+        match self {
+            Implies(hypotheses, goal) => {
+                hypotheses.hash_stable(hcx, hasher);
+                goal.hash_stable(hcx, hasher);
+            },
+            And(goal1, goal2) => {
+                goal1.hash_stable(hcx, hasher);
+                goal2.hash_stable(hcx, hasher);
+            }
+            Not(goal) => goal.hash_stable(hcx, hasher),
+            DomainGoal(domain_goal) => domain_goal.hash_stable(hcx, hasher),
+            Quantified(quantifier, goal) => {
+                quantifier.hash_stable(hcx, hasher);
+                goal.hash_stable(hcx, hasher);
+            },
+        }
+    }
+}
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for traits::Clause<'tcx> {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a>,
+                                          hasher: &mut StableHasher<W>) {
+        use traits::Clause::*;
+
+        mem::discriminant(self).hash_stable(hcx, hasher);
+        match self {
+            Implies(hypotheses, goal) => {
+                hypotheses.hash_stable(hcx, hasher);
+                goal.hash_stable(hcx, hasher);
+            }
+            DomainGoal(domain_goal) => domain_goal.hash_stable(hcx, hasher),
+            ForAll(clause) => clause.hash_stable(hcx, hasher),
+        }
+    }
+}
+
+impl_stable_hash_for!(enum traits::QuantifierKind {
+    Universal,
+    Existential
+});
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 f8fb2e5a1c821d0dfa0ba8aa3eaf619a9c98cbf4..0aa750aba066057b50db4eca855e2472a535362f 100644 (file)
@@ -19,6 +19,7 @@
 use hir::def::Def;
 use hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
 use hir::ItemLocalId;
+use hir::LifetimeName;
 use ty::{self, TyCtxt};
 
 use std::cell::Cell;
@@ -569,10 +570,26 @@ fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
                 for bound in bounds {
                     self.visit_poly_trait_ref(bound, hir::TraitBoundModifier::None);
                 }
-                if lifetime.is_elided() {
-                    self.resolve_object_lifetime_default(lifetime)
-                } else {
-                    self.visit_lifetime(lifetime);
+                match lifetime.name {
+                    LifetimeName::Implicit => {
+                        // If the user does not write *anything*, we
+                        // use the object lifetime defaulting
+                        // rules. So e.g. `Box<dyn Debug>` becomes
+                        // `Box<dyn Debug + 'static>`.
+                        self.resolve_object_lifetime_default(lifetime)
+                    }
+                    LifetimeName::Underscore => {
+                        // If the user writes `'_`, we use the *ordinary* elision
+                        // rules. So the `'_` in e.g. `Box<dyn Debug + '_>` will be
+                        // resolved the same as the `'_` in `&'_ Foo`.
+                        //
+                        // cc #48468
+                        self.resolve_elided_lifetimes(slice::from_ref(lifetime), false)
+                    }
+                    LifetimeName::Static | LifetimeName::Name(_) => {
+                        // If the user wrote an explicit name, use that.
+                        self.visit_lifetime(lifetime);
+                    }
                 }
             }
             hir::TyRptr(ref lifetime_ref, ref mt) => {
index 51660b180cd980d0f7456d46287a3f78f41c2386..9e69990f22c0d0c20af457727493daf481e919be 100644 (file)
@@ -20,7 +20,7 @@ pub struct EvalError<'tcx> {
 
 impl<'tcx> From<EvalErrorKind<'tcx>> for EvalError<'tcx> {
     fn from(kind: EvalErrorKind<'tcx>) -> Self {
-        let backtrace = match env::var("RUST_BACKTRACE") {
+        let backtrace = match env::var("MIRI_BACKTRACE") {
             Ok(ref val) if !val.is_empty() => Some(Backtrace::new_unresolved()),
             _ => None
         };
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 736d7f8a1396b8c0a71b44a58ebf71384794fb68..0d91074e946bda028c813aebb2804082c91569fe 100644 (file)
@@ -385,7 +385,7 @@ pub struct Options {
         externs: Externs [UNTRACKED],
         crate_name: Option<String> [TRACKED],
         // An optional name to use as the crate for std during std injection,
-        // written `extern crate std = "name"`. Default to "std". Used by
+        // written `extern crate name as std`. Defaults to `std`. Used by
         // out-of-tree drivers.
         alt_std_name: Option<String> [TRACKED],
         // Indicates how the compiler should treat unstable features
@@ -1288,6 +1288,8 @@ fn parse_epoch(slot: &mut Epoch, v: Option<&str>) -> bool {
           "run `dsymutil` and delete intermediate object files"),
     ui_testing: bool = (false, parse_bool, [UNTRACKED],
           "format compiler diagnostics in a way that's better suitable for UI testing"),
+    embed_bitcode: bool = (false, parse_bool, [TRACKED],
+          "embed LLVM bitcode in object files"),
 }
 
 pub fn default_lib_output() -> CrateType {
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 bd8f99780f9f12c8913f615d933a3fbeeee5a3f6..a0ba88f7d559af588dc43214c3b381a1b849a780 100644 (file)
@@ -29,6 +29,7 @@
 
 use rustc_data_structures::sync::Lrc;
 use std::rc::Rc;
+use std::convert::From;
 use syntax::ast;
 use syntax_pos::{Span, DUMMY_SP};
 
@@ -244,6 +245,69 @@ pub struct DerivedObligationCause<'tcx> {
 pub type PredicateObligations<'tcx> = Vec<PredicateObligation<'tcx>>;
 pub type TraitObligations<'tcx> = Vec<TraitObligation<'tcx>>;
 
+/// The following types:
+/// * `WhereClauseAtom`
+/// * `DomainGoal`
+/// * `Goal`
+/// * `Clause`
+/// are used for representing the trait system in the form of
+/// logic programming clauses. They are part of the interface
+/// for the chalk SLG solver.
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
+pub enum WhereClauseAtom<'tcx> {
+    Implemented(ty::TraitPredicate<'tcx>),
+    ProjectionEq(ty::ProjectionPredicate<'tcx>),
+}
+
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
+pub enum DomainGoal<'tcx> {
+    Holds(WhereClauseAtom<'tcx>),
+    WellFormed(WhereClauseAtom<'tcx>),
+    FromEnv(WhereClauseAtom<'tcx>),
+    WellFormedTy(Ty<'tcx>),
+    FromEnvTy(Ty<'tcx>),
+    RegionOutlives(ty::RegionOutlivesPredicate<'tcx>),
+    TypeOutlives(ty::TypeOutlivesPredicate<'tcx>),
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
+pub enum QuantifierKind {
+    Universal,
+    Existential,
+}
+
+#[derive(Clone, PartialEq, Eq, Hash, Debug)]
+pub enum Goal<'tcx> {
+    // FIXME: use interned refs instead of `Box`
+    Implies(Vec<Clause<'tcx>>, Box<Goal<'tcx>>),
+    And(Box<Goal<'tcx>>, Box<Goal<'tcx>>),
+    Not(Box<Goal<'tcx>>),
+    DomainGoal(DomainGoal<'tcx>),
+    Quantified(QuantifierKind, Box<ty::Binder<Goal<'tcx>>>)
+}
+
+impl<'tcx> From<DomainGoal<'tcx>> for Goal<'tcx> {
+    fn from(domain_goal: DomainGoal<'tcx>) -> Self {
+        Goal::DomainGoal(domain_goal)
+    }
+}
+
+impl<'tcx> From<DomainGoal<'tcx>> for Clause<'tcx> {
+    fn from(domain_goal: DomainGoal<'tcx>) -> Self {
+        Clause::DomainGoal(domain_goal)
+    }
+}
+
+/// This matches the definition from Page 7 of "A Proof Procedure for the Logic of Hereditary
+/// Harrop Formulas".
+#[derive(Clone, PartialEq, Eq, Hash, Debug)]
+pub enum Clause<'tcx> {
+    // FIXME: again, use interned refs instead of `Box`
+    Implies(Vec<Goal<'tcx>>, DomainGoal<'tcx>),
+    DomainGoal(DomainGoal<'tcx>),
+    ForAll(Box<ty::Binder<Clause<'tcx>>>),
+}
+
 pub type Selection<'tcx> = Vtable<'tcx, PredicateObligation<'tcx>>;
 
 #[derive(Clone,Debug)]
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 a2d98a456f49a0ea39b00b7e2eb7b226208b3bb9..d6e6f0e98adc48afb18f4f61efdae5ac64dec78d 100644 (file)
@@ -425,3 +425,138 @@ impl<'tcx, T> TypeFoldable<'tcx> for Normalized<'tcx, T> {
         obligations
     } where T: TypeFoldable<'tcx>
 }
+
+impl<'tcx> fmt::Display for traits::WhereClauseAtom<'tcx> {
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+        use traits::WhereClauseAtom::*;
+
+        match self {
+            Implemented(trait_ref) => write!(fmt, "Implemented({})", trait_ref),
+            ProjectionEq(projection) => write!(fmt, "ProjectionEq({})", projection),
+        }
+    }
+}
+
+impl<'tcx> fmt::Display for traits::DomainGoal<'tcx> {
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+        use traits::DomainGoal::*;
+        use traits::WhereClauseAtom::*;
+
+        match self {
+            Holds(wc) => write!(fmt, "{}", wc),
+            WellFormed(Implemented(trait_ref)) => write!(fmt, "WellFormed({})", trait_ref),
+            WellFormed(ProjectionEq(projection)) => write!(fmt, "WellFormed({})", projection),
+            FromEnv(Implemented(trait_ref)) => write!(fmt, "FromEnv({})", trait_ref),
+            FromEnv(ProjectionEq(projection)) => write!(fmt, "FromEnv({})", projection),
+            WellFormedTy(ty) => write!(fmt, "WellFormed({})", ty),
+            FromEnvTy(ty) => write!(fmt, "FromEnv({})", ty),
+            RegionOutlives(predicate) => write!(fmt, "RegionOutlives({})", predicate),
+            TypeOutlives(predicate) => write!(fmt, "TypeOutlives({})", predicate),
+        }
+    }
+}
+
+impl fmt::Display for traits::QuantifierKind {
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+        use traits::QuantifierKind::*;
+
+        match self {
+            Universal => write!(fmt, "forall"),
+            Existential => write!(fmt, "exists"),
+        }
+    }
+}
+
+impl<'tcx> fmt::Display for traits::Goal<'tcx> {
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+        use traits::Goal::*;
+
+        match self {
+            Implies(hypotheses, goal) => {
+                write!(fmt, "if (")?;
+                for (index, hyp) in hypotheses.iter().enumerate() {
+                    if index > 0 {
+                        write!(fmt, ", ")?;
+                    }
+                    write!(fmt, "{}", hyp)?;
+                }
+                write!(fmt, ") {{ {} }}", goal)
+            }
+            And(goal1, goal2) => write!(fmt, "({} && {})", goal1, goal2),
+            Not(goal) => write!(fmt, "not {{ {} }}", goal),
+            DomainGoal(goal) => write!(fmt, "{}", goal),
+            Quantified(qkind, goal) => {
+                // FIXME: appropriate binder names
+                write!(fmt, "{}<> {{ {} }}", qkind, goal.skip_binder())
+            }
+        }
+    }
+}
+
+impl<'tcx> fmt::Display for traits::Clause<'tcx> {
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+        use traits::Clause::*;
+
+        match self {
+            Implies(hypotheses, goal) => {
+                write!(fmt, "{}", goal)?;
+                if !hypotheses.is_empty() {
+                    write!(fmt, " :- ")?;
+                    for (index, condition) in hypotheses.iter().enumerate() {
+                        if index > 0 {
+                            write!(fmt, ", ")?;
+                        }
+                        write!(fmt, "{}", condition)?;
+                    }
+                }
+                write!(fmt, ".")
+            }
+            DomainGoal(domain_goal) => write!(fmt, "{}.", domain_goal),
+            ForAll(clause) => {
+                // FIXME: appropriate binder names
+                write!(fmt, "forall<> {{ {} }}", clause.skip_binder())
+            }
+        }
+    }
+}
+
+EnumTypeFoldableImpl! {
+    impl<'tcx> TypeFoldable<'tcx> for traits::WhereClauseAtom<'tcx> {
+        (traits::WhereClauseAtom::Implemented)(trait_ref),
+        (traits::WhereClauseAtom::ProjectionEq)(projection),
+    }
+}
+
+EnumTypeFoldableImpl! {
+    impl<'tcx> TypeFoldable<'tcx> for traits::DomainGoal<'tcx> {
+        (traits::DomainGoal::Holds)(wc),
+        (traits::DomainGoal::WellFormed)(wc),
+        (traits::DomainGoal::FromEnv)(wc),
+        (traits::DomainGoal::WellFormedTy)(ty),
+        (traits::DomainGoal::FromEnvTy)(ty),
+        (traits::DomainGoal::RegionOutlives)(predicate),
+        (traits::DomainGoal::TypeOutlives)(predicate),
+    }
+}
+
+CloneTypeFoldableImpls! {
+    traits::QuantifierKind,
+}
+
+EnumTypeFoldableImpl! {
+    impl<'tcx> TypeFoldable<'tcx> for traits::Goal<'tcx> {
+        (traits::Goal::Implies)(hypotheses, goal),
+        (traits::Goal::And)(goal1, goal2),
+        (traits::Goal::Not)(goal),
+        (traits::Goal::DomainGoal)(domain_goal),
+        (traits::Goal::Quantified)(qkind, goal),
+    }
+}
+
+EnumTypeFoldableImpl! {
+    impl<'tcx> TypeFoldable<'tcx> for traits::Clause<'tcx> {
+        (traits::Clause::Implies)(hypotheses, goal),
+        (traits::Clause::DomainGoal)(domain_goal),
+        (traits::Clause::ForAll)(clause),
+    }
+}
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 11675f542873d262ac7d1aa833b09b6e1608406d..117d92193123564fffb7365427601f2a0a81b0d1 100644 (file)
@@ -693,6 +693,12 @@ fn try_load_from_disk<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     }
 }
 
+impl<'tcx> QueryDescription<'tcx> for queries::program_clauses_for<'tcx> {
+    fn describe(_tcx: TyCtxt, _: DefId) -> String {
+        format!("generating chalk-style clauses")
+    }
+}
+
 macro_rules! impl_disk_cacheable_query(
     ($query_name:ident, |$key:tt| $cond:expr) => {
         impl<'tcx> QueryDescription<'tcx> for queries::$query_name<'tcx> {
@@ -721,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 4dcd7c20c33d5d31848f585dcb1fa1a2e3eab4ec..6c3b4efb932ad891923f0bce0c88fa90ec4a2c7c 100644 (file)
@@ -38,6 +38,7 @@
 use traits::query::dropck_outlives::{DtorckConstraint, DropckOutlivesResult};
 use traits::query::normalize::NormalizationResult;
 use traits::specialization_graph;
+use traits::Clause;
 use ty::{self, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt};
 use ty::steal::Steal;
 use ty::subst::Substs;
         -> usize,
 
     [] fn features_query: features_node(CrateNum) -> Lrc<feature_gate::Features>,
+
+    [] fn program_clauses_for: ProgramClausesFor(DefId) -> Lrc<Vec<Clause<'tcx>>>,
 }
 
 //////////////////////////////////////////////////////////////////////
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 267d7da5e0c255e5b0752ac218f86c8f3b0531b2..4170fa7679716034468fdf9e8cb52d32403f1eed 100644 (file)
@@ -938,6 +938,8 @@ macro_rules! force {
 
         DepKind::GetSymbolExportLevel => { force!(symbol_export_level, def_id!()); }
         DepKind::Features => { force!(features_query, LOCAL_CRATE); }
+
+        DepKind::ProgramClausesFor => { force!(program_clauses_for, def_id!()); }
     }
 
     true
@@ -1004,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 09b11a36352e123a50ae532b68851df03dd8d2e2..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};
@@ -1073,9 +1074,12 @@ pub fn def_id(&self) -> DefId {
 #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
 pub struct OutlivesPredicate<A,B>(pub A, pub B); // `A : B`
 pub type PolyOutlivesPredicate<A,B> = ty::Binder<OutlivesPredicate<A,B>>;
-pub type PolyRegionOutlivesPredicate<'tcx> = PolyOutlivesPredicate<ty::Region<'tcx>,
-                                                                   ty::Region<'tcx>>;
-pub type PolyTypeOutlivesPredicate<'tcx> = PolyOutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>;
+pub type RegionOutlivesPredicate<'tcx> = OutlivesPredicate<ty::Region<'tcx>,
+                                                           ty::Region<'tcx>>;
+pub type TypeOutlivesPredicate<'tcx> = OutlivesPredicate<Ty<'tcx>,
+                                                         ty::Region<'tcx>>;
+pub type PolyRegionOutlivesPredicate<'tcx> = ty::Binder<RegionOutlivesPredicate<'tcx>>;
+pub type PolyTypeOutlivesPredicate<'tcx> = ty::Binder<TypeOutlivesPredicate<'tcx>>;
 
 #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
 pub struct SubtypePredicate<'tcx> {
@@ -1939,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>>;
@@ -2287,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()
@@ -2391,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 c088458c3557c7076e26c42cbe208e8a2c01d3f7..02e704b6841856779af8b5c5696d04caa96eaf0a 100644 (file)
@@ -99,7 +99,7 @@ fn fold_item(&mut self, item: P<Item>) -> SmallVector<P<Item>> {
             f.cx.item_extern_crate(f.span, f.alloc),
             f.cx.item_use_simple(
                 f.span,
-                respan(f.span.empty(), VisibilityKind::Inherited),
+                respan(f.span.shrink_to_lo(), VisibilityKind::Inherited),
                 super_path,
             ),
         ];
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 250d85d45203ed5c261e27c1776049662c53b569..f53eeb86a9c56f562b77e05e528382e335a9386d 100644 (file)
@@ -473,6 +473,9 @@ pub struct TargetOptions {
     /// The default visibility for symbols in this target should be "hidden"
     /// rather than "default"
     pub default_hidden_visibility: bool,
+
+    /// Whether or not bitcode is embedded in object files
+    pub embed_bitcode: bool,
 }
 
 impl Default for TargetOptions {
@@ -544,6 +547,7 @@ fn default() -> TargetOptions {
             i128_lowering: false,
             codegen_backend: "llvm".to_string(),
             default_hidden_visibility: false,
+            embed_bitcode: false,
         }
     }
 }
@@ -792,6 +796,7 @@ macro_rules! key {
         key!(no_builtins, bool);
         key!(codegen_backend);
         key!(default_hidden_visibility, bool);
+        key!(embed_bitcode, bool);
 
         if let Some(array) = obj.find("abi-blacklist").and_then(Json::as_array) {
             for name in array.iter().filter_map(|abi| abi.as_string()) {
@@ -990,6 +995,7 @@ macro_rules! target_option_val {
         target_option_val!(no_builtins);
         target_option_val!(codegen_backend);
         target_option_val!(default_hidden_visibility);
+        target_option_val!(embed_bitcode);
 
         if default.abi_blacklist != self.options.abi_blacklist {
             d.insert("abi-blacklist".to_string(), self.options.abi_blacklist.iter()
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 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 e52575f02b2ff4dc53dcbcb3dce742d10977528e..f2fe6542db171d02b6cf4c8926f02dfda2b00560 100644 (file)
@@ -683,7 +683,7 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session,
     });
 
     krate = time(sess, "crate injection", || {
-        let alt_std_name = sess.opts.alt_std_name.clone();
+        let alt_std_name = sess.opts.alt_std_name.as_ref().map(|s| &**s);
         syntax::std_inject::maybe_inject_crates_ref(krate, alt_std_name)
     });
 
@@ -877,10 +877,6 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session,
         Ok(())
     })?;
 
-    if resolver.found_unresolved_macro {
-        sess.parse_sess.span_diagnostic.abort_if_errors();
-    }
-
     // Needs to go *after* expansion to be able to check the results of macro expansion.
     time(sess, "complete gated feature checking", || {
         sess.track_errors(|| {
@@ -892,6 +888,12 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session,
         })
     })?;
 
+    // Unresolved macros might be due to mistyped `#[macro_use]`,
+    // so abort after checking for unknown attributes. (#49074)
+    if resolver.found_unresolved_macro {
+        sess.parse_sess.span_diagnostic.abort_if_errors();
+    }
+
     // Lower ast -> hir.
     // First, we need to collect the dep_graph.
     let dep_graph = match future_dep_graph {
@@ -1089,6 +1091,10 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(trans: &TransCrate,
 
         time(sess, "lint checking", || lint::check_crate(tcx));
 
+        time(sess,
+             "dumping chalk-like clauses",
+             || rustc_traits::lowering::dump_program_clauses(tcx));
+
         return Ok(f(tcx, analysis, rx, tcx.sess.compile_status()));
     })
 }
index 5a1983bfec64f16a8160f70c19da08fd3b70a35b..f1f3a0519bbcb2044bb4f1db598695073a0fa532 100644 (file)
@@ -444,7 +444,7 @@ fn GetModuleFileNameW(hModule: usize,
 // The FileLoader provides a way to load files from sources other than the file system.
 pub fn run_compiler<'a>(args: &[String],
                         callbacks: &mut CompilerCalls<'a>,
-                        file_loader: Option<Box<FileLoader + 'static>>,
+                        file_loader: Option<Box<FileLoader + Send + Sync + 'static>>,
                         emitter_dest: Option<Box<Write + Send>>)
                         -> (CompileResult, Option<Session>)
 {
@@ -455,7 +455,7 @@ pub fn run_compiler<'a>(args: &[String],
 
 fn run_compiler_impl<'a>(args: &[String],
                          callbacks: &mut CompilerCalls<'a>,
-                         file_loader: Option<Box<FileLoader + 'static>>,
+                         file_loader: Option<Box<FileLoader + Send + Sync + 'static>>,
                          emitter_dest: Option<Box<Write + Send>>)
                          -> (CompileResult, Option<Session>)
 {
index 3b6e6db7f46c3452b12dfa202e791c91a8227a8a..ca5d3f55a0fea4988d75505405c1a32d05917145 100644 (file)
@@ -12,7 +12,7 @@
 
 use syntax_pos::{DUMMY_SP, FileMap, Span, MultiSpan};
 
-use {Level, CodeSuggestion, DiagnosticBuilder, SubDiagnostic, CodeMapper, DiagnosticId};
+use {Level, CodeSuggestion, DiagnosticBuilder, SubDiagnostic, CodeMapperDyn, DiagnosticId};
 use snippet::{Annotation, AnnotationType, Line, MultilineAnnotation, StyledString, Style};
 use styled_buffer::StyledBuffer;
 
@@ -120,7 +120,7 @@ fn to_color_choice(&self) -> ColorChoice {
 
 pub struct EmitterWriter {
     dst: Destination,
-    cm: Option<Lrc<CodeMapper>>,
+    cm: Option<Lrc<CodeMapperDyn>>,
     short_message: bool,
     teach: bool,
     ui_testing: bool,
@@ -134,7 +134,7 @@ struct FileWithAnnotatedLines {
 
 impl EmitterWriter {
     pub fn stderr(color_config: ColorConfig,
-                  code_map: Option<Lrc<CodeMapper>>,
+                  code_map: Option<Lrc<CodeMapperDyn>>,
                   short_message: bool,
                   teach: bool)
                   -> EmitterWriter {
@@ -149,7 +149,7 @@ pub fn stderr(color_config: ColorConfig,
     }
 
     pub fn new(dst: Box<Write + Send>,
-               code_map: Option<Lrc<CodeMapper>>,
+               code_map: Option<Lrc<CodeMapperDyn>>,
                short_message: bool,
                teach: bool)
                -> EmitterWriter {
@@ -1195,8 +1195,6 @@ fn emit_suggestion_default(&mut self,
                                level: &Level,
                                max_line_num_len: usize)
                                -> io::Result<()> {
-        use std::borrow::Borrow;
-
         if let Some(ref cm) = self.cm {
             let mut buffer = StyledBuffer::new();
 
@@ -1213,7 +1211,7 @@ fn emit_suggestion_default(&mut self,
                                Some(Style::HeaderMsg));
 
             // Render the replacements for each suggestion
-            let suggestions = suggestion.splice_lines(cm.borrow());
+            let suggestions = suggestion.splice_lines(&**cm);
 
             let mut row_num = 2;
             for &(ref complete, ref parts) in suggestions.iter().take(MAX_SUGGESTIONS) {
index 7148969191f2b6caaa49c233e04c8270902e625c..a25c3668bb13b168a5a17c79b4bda065416a1d2d 100644 (file)
@@ -36,7 +36,7 @@
 
 use emitter::{Emitter, EmitterWriter};
 
-use rustc_data_structures::sync::Lrc;
+use rustc_data_structures::sync::{self, Lrc};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::stable_hasher::StableHasher;
 
@@ -106,6 +106,8 @@ pub struct SubstitutionPart {
     pub snippet: String,
 }
 
+pub type CodeMapperDyn = CodeMapper + sync::Send + sync::Sync;
+
 pub trait CodeMapper {
     fn lookup_char_pos(&self, pos: BytePos) -> Loc;
     fn span_to_lines(&self, sp: Span) -> FileLinesResult;
@@ -119,7 +121,8 @@ pub trait CodeMapper {
 
 impl CodeSuggestion {
     /// Returns the assembled code suggestions and whether they should be shown with an underline.
-    pub fn splice_lines(&self, cm: &CodeMapper) -> Vec<(String, Vec<SubstitutionPart>)> {
+    pub fn splice_lines(&self, cm: &CodeMapperDyn)
+                        -> Vec<(String, Vec<SubstitutionPart>)> {
         use syntax_pos::{CharPos, Loc, Pos};
 
         fn push_trailing(buf: &mut String,
@@ -290,7 +293,7 @@ impl Handler {
     pub fn with_tty_emitter(color_config: ColorConfig,
                             can_emit_warnings: bool,
                             treat_err_as_bug: bool,
-                            cm: Option<Lrc<CodeMapper>>)
+                            cm: Option<Lrc<CodeMapperDyn>>)
                             -> Handler {
         Handler::with_tty_emitter_and_flags(
             color_config,
@@ -303,7 +306,7 @@ pub fn with_tty_emitter(color_config: ColorConfig,
     }
 
     pub fn with_tty_emitter_and_flags(color_config: ColorConfig,
-                                      cm: Option<Lrc<CodeMapper>>,
+                                      cm: Option<Lrc<CodeMapperDyn>>,
                                       flags: HandlerFlags)
                                       -> Handler {
         let emitter = Box::new(EmitterWriter::stderr(color_config, cm, false, false));
index 031033f7208e1dff4767e43afdec28e79e56ffbb..bffa8628ff3530f527ff72589df83e826bcc9e76 100644 (file)
@@ -1082,7 +1082,7 @@ fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
                     if !cx.access_levels.is_reachable(it.id) {
                         let msg = "function is marked #[no_mangle], but not exported";
                         let mut err = cx.struct_span_lint(PRIVATE_NO_MANGLE_FNS, it.span, msg);
-                        let insertion_span = it.span.with_hi(it.span.lo());
+                        let insertion_span = it.span.shrink_to_lo();
                         if it.vis == hir::Visibility::Inherited {
                             err.span_suggestion(insertion_span,
                                                 "try making it public",
@@ -1107,7 +1107,7 @@ fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
                    !cx.access_levels.is_reachable(it.id) {
                        let msg = "static is marked #[no_mangle], but not exported";
                        let mut err = cx.struct_span_lint(PRIVATE_NO_MANGLE_STATICS, it.span, msg);
-                       let insertion_span = it.span.with_hi(it.span.lo());
+                       let insertion_span = it.span.shrink_to_lo();
                        if it.vis == hir::Visibility::Inherited {
                            err.span_suggestion(insertion_span,
                                                "try making it public",
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 d777f6f19b0ffd8ca7af3aa916ec0f13780533a5..86f79c553c3917fc9249e7cd49a8c69a7445f55a 100644 (file)
@@ -377,11 +377,12 @@ fn check_use_tree(&self, cx: &EarlyContext, use_tree: &ast::UseTree, item: &ast:
             // Trigger the lint if the nested item is a non-self single item
             let node_ident;
             match items[0].0.kind {
-                ast::UseTreeKind::Simple(ident) => {
-                    if ident.name == keywords::SelfValue.name() {
+                ast::UseTreeKind::Simple(rename) => {
+                    let orig_ident = items[0].0.prefix.segments.last().unwrap().identifier;
+                    if orig_ident.name == keywords::SelfValue.name() {
                         return;
                     } else {
-                        node_ident = ident;
+                        node_ident = rename.unwrap_or(orig_ident);
                     }
                 }
                 ast::UseTreeKind::Glob => {
index 0ec5700f5f32a44ae88f01011e80c67d24811ec1..c0cdd212770623bf6ff827776db7ff55b0d84e68 100644 (file)
@@ -621,6 +621,7 @@ pub fn LLVMStructTypeInContext(C: ContextRef,
     pub fn LLVMConstIntGetSExtValue(ConstantVal: ValueRef) -> c_longlong;
     pub fn LLVMRustConstInt128Get(ConstantVal: ValueRef, SExt: bool,
                                   high: *mut u64, low: *mut u64) -> bool;
+    pub fn LLVMConstRealGetDouble (ConstantVal: ValueRef, losesInfo: *mut Bool) -> f64;
 
 
     // Operations on composite constants
@@ -1201,6 +1202,46 @@ pub fn LLVMBuildInsertValue(B: BuilderRef,
                                 Name: *const c_char)
                                 -> ValueRef;
 
+    pub fn LLVMRustBuildVectorReduceFAdd(B: BuilderRef,
+                                         Acc: ValueRef,
+                                         Src: ValueRef)
+                                         -> ValueRef;
+    pub fn LLVMRustBuildVectorReduceFMul(B: BuilderRef,
+                                         Acc: ValueRef,
+                                         Src: ValueRef)
+                                         -> ValueRef;
+    pub fn LLVMRustBuildVectorReduceAdd(B: BuilderRef,
+                                        Src: ValueRef)
+                                        -> ValueRef;
+    pub fn LLVMRustBuildVectorReduceMul(B: BuilderRef,
+                                        Src: ValueRef)
+                                        -> ValueRef;
+    pub fn LLVMRustBuildVectorReduceAnd(B: BuilderRef,
+                                        Src: ValueRef)
+                                        -> ValueRef;
+    pub fn LLVMRustBuildVectorReduceOr(B: BuilderRef,
+                                       Src: ValueRef)
+                                       -> ValueRef;
+    pub fn LLVMRustBuildVectorReduceXor(B: BuilderRef,
+                                        Src: ValueRef)
+                                        -> ValueRef;
+    pub fn LLVMRustBuildVectorReduceMin(B: BuilderRef,
+                                        Src: ValueRef,
+                                        IsSigned: bool)
+                                        -> ValueRef;
+    pub fn LLVMRustBuildVectorReduceMax(B: BuilderRef,
+                                        Src: ValueRef,
+                                        IsSigned: bool)
+                                        -> ValueRef;
+    pub fn LLVMRustBuildVectorReduceFMin(B: BuilderRef,
+                                         Src: ValueRef,
+                                         IsNaN: bool)
+                                         -> ValueRef;
+    pub fn LLVMRustBuildVectorReduceFMax(B: BuilderRef,
+                                         Src: ValueRef,
+                                         IsNaN: bool)
+                                         -> ValueRef;
+
     pub fn LLVMBuildIsNull(B: BuilderRef, Val: ValueRef, Name: *const c_char) -> ValueRef;
     pub fn LLVMBuildIsNotNull(B: BuilderRef, Val: ValueRef, Name: *const c_char) -> ValueRef;
     pub fn LLVMBuildPtrDiff(B: BuilderRef,
@@ -1567,6 +1608,7 @@ pub fn LLVMRustDIBuilderCreateDebugLocation(Context: ContextRef,
     pub fn LLVMRustWriteValueToString(value_ref: ValueRef, s: RustStringRef);
 
     pub fn LLVMIsAConstantInt(value_ref: ValueRef) -> ValueRef;
+    pub fn LLVMIsAConstantFP(value_ref: ValueRef) -> ValueRef;
 
     pub fn LLVMRustPassKind(Pass: PassRef) -> PassKind;
     pub fn LLVMRustFindAndCreatePass(Pass: *const c_char) -> PassRef;
index 789ecd0f6136b1766436313795d9a85da1d8913c..a0546b369a8ebba094105cdc45f61cbe485ee9b7 100644 (file)
@@ -14,7 +14,7 @@
 use locator::{self, CratePaths};
 use native_libs::relevant_lib;
 use schema::CrateRoot;
-use rustc_data_structures::sync::Lrc;
+use rustc_data_structures::sync::{Lrc, RwLock, Lock};
 
 use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX};
 use rustc::hir::svh::Svh;
@@ -30,7 +30,6 @@
 use rustc::util::nodemap::FxHashSet;
 use rustc::hir::map::Definitions;
 
-use std::cell::{RefCell, Cell};
 use std::ops::Deref;
 use std::path::PathBuf;
 use std::{cmp, fs};
@@ -63,7 +62,7 @@ fn dump_crates(cstore: &CStore) {
         info!("  name: {}", data.name());
         info!("  cnum: {}", data.cnum);
         info!("  hash: {}", data.hash());
-        info!("  reqd: {:?}", data.dep_kind.get());
+        info!("  reqd: {:?}", *data.dep_kind.lock());
         let CrateSource { dylib, rlib, rmeta } = data.source.clone();
         dylib.map(|dl| info!("  dylib: {}", dl.0.display()));
         rlib.map(|rl|  info!("   rlib: {}", rl.0.display()));
@@ -233,7 +232,7 @@ fn register_crate(&mut self,
 
         let mut cmeta = cstore::CrateMetadata {
             name,
-            extern_crate: Cell::new(None),
+            extern_crate: Lock::new(None),
             def_path_table: Lrc::new(def_path_table),
             trait_impls,
             proc_macros: crate_root.macro_derive_registrar.map(|_| {
@@ -241,11 +240,11 @@ fn register_crate(&mut self,
             }),
             root: crate_root,
             blob: metadata,
-            cnum_map: RefCell::new(cnum_map),
+            cnum_map: Lock::new(cnum_map),
             cnum,
-            codemap_import_info: RefCell::new(vec![]),
-            attribute_cache: RefCell::new([Vec::new(), Vec::new()]),
-            dep_kind: Cell::new(dep_kind),
+            codemap_import_info: RwLock::new(vec![]),
+            attribute_cache: Lock::new([Vec::new(), Vec::new()]),
+            dep_kind: Lock::new(dep_kind),
             source: cstore::CrateSource {
                 dylib,
                 rlib,
@@ -335,7 +334,9 @@ fn resolve_crate(&mut self,
                 if data.root.macro_derive_registrar.is_some() {
                     dep_kind = DepKind::UnexportedMacrosOnly;
                 }
-                data.dep_kind.set(cmp::max(data.dep_kind.get(), dep_kind));
+                data.dep_kind.with_lock(|data_dep_kind| {
+                    *data_dep_kind = cmp::max(*data_dep_kind, dep_kind);
+                });
                 (cnum, data)
             }
             LoadResult::Loaded(library) => {
@@ -379,14 +380,14 @@ fn update_extern_crate(&mut self,
         if !visited.insert((cnum, extern_crate.direct)) { return }
 
         let cmeta = self.cstore.get_crate_data(cnum);
-        let old_extern_crate = cmeta.extern_crate.get();
+        let mut old_extern_crate = cmeta.extern_crate.borrow_mut();
 
         // Prefer:
         // - something over nothing (tuple.0);
         // - direct extern crate to indirect (tuple.1);
         // - shorter paths to longer (tuple.2).
         let new_rank = (true, extern_crate.direct, !extern_crate.path_len);
-        let old_rank = match old_extern_crate {
+        let old_rank = match *old_extern_crate {
             None => (false, false, !0),
             Some(ref c) => (true, c.direct, !c.path_len),
         };
@@ -395,7 +396,9 @@ fn update_extern_crate(&mut self,
             return; // no change needed
         }
 
-        cmeta.extern_crate.set(Some(extern_crate));
+        *old_extern_crate = Some(extern_crate);
+        drop(old_extern_crate);
+
         // Propagate the extern crate info to dependencies.
         extern_crate.direct = false;
         for &dep_cnum in cmeta.cnum_map.borrow().iter() {
@@ -646,7 +649,7 @@ fn inject_panic_runtime(&mut self, krate: &ast::Crate) {
                 // #![panic_runtime] crate.
                 self.inject_dependency_if(cnum, "a panic runtime",
                                           &|data| data.needs_panic_runtime(sess));
-                runtime_found = runtime_found || data.dep_kind.get() == DepKind::Explicit;
+                runtime_found = runtime_found || *data.dep_kind.lock() == DepKind::Explicit;
             }
         });
 
@@ -1052,12 +1055,14 @@ fn postprocess(&mut self, krate: &ast::Crate) {
 
     fn process_item(&mut self, item: &ast::Item, definitions: &Definitions) {
         match item.node {
-            ast::ItemKind::ExternCrate(rename) => {
-                debug!("resolving extern crate stmt. ident: {} rename: {:?}", item.ident, rename);
-                let rename = match rename {
-                    Some(rename) => {
-                        validate_crate_name(Some(self.sess), &rename.as_str(), Some(item.span));
-                        rename
+            ast::ItemKind::ExternCrate(orig_name) => {
+                debug!("resolving extern crate stmt. ident: {} orig_name: {:?}",
+                       item.ident, orig_name);
+                let orig_name = match orig_name {
+                    Some(orig_name) => {
+                        validate_crate_name(Some(self.sess), &orig_name.as_str(),
+                                            Some(item.span));
+                        orig_name
                     }
                     None => item.ident.name,
                 };
@@ -1068,7 +1073,7 @@ fn process_item(&mut self, item: &ast::Item, definitions: &Definitions) {
                 };
 
                 let (cnum, ..) = self.resolve_crate(
-                    &None, item.ident.name, rename, None, item.span, PathKind::Crate, dep_kind,
+                    &None, item.ident.name, orig_name, None, item.span, PathKind::Crate, dep_kind,
                 );
 
                 let def_id = definitions.opt_local_def_id(item.id).unwrap();
index 202efb9276a81e0f8071e1b9915cee8fcc30080c..bd5ad93946e3cf9a10f9531fb423af50942cbc4a 100644 (file)
@@ -22,8 +22,7 @@
 use rustc_data_structures::indexed_vec::IndexVec;
 use rustc::util::nodemap::{FxHashMap, FxHashSet, NodeMap};
 
-use std::cell::{RefCell, Cell};
-use rustc_data_structures::sync::Lrc;
+use rustc_data_structures::sync::{Lrc, RwLock, Lock};
 use syntax::{ast, attr};
 use syntax::ext::base::SyntaxExtension;
 use syntax::symbol::Symbol;
@@ -62,13 +61,13 @@ pub struct CrateMetadata {
     /// Information about the extern crate that caused this crate to
     /// be loaded. If this is `None`, then the crate was injected
     /// (e.g., by the allocator)
-    pub extern_crate: Cell<Option<ExternCrate>>,
+    pub extern_crate: Lock<Option<ExternCrate>>,
 
     pub blob: MetadataBlob,
-    pub cnum_map: RefCell<CrateNumMap>,
+    pub cnum_map: Lock<CrateNumMap>,
     pub cnum: CrateNum,
-    pub codemap_import_info: RefCell<Vec<ImportedFileMap>>,
-    pub attribute_cache: RefCell<[Vec<Option<Lrc<[ast::Attribute]>>>; 2]>,
+    pub codemap_import_info: RwLock<Vec<ImportedFileMap>>,
+    pub attribute_cache: Lock<[Vec<Option<Lrc<[ast::Attribute]>>>; 2]>,
 
     pub root: schema::CrateRoot,
 
@@ -81,7 +80,7 @@ pub struct CrateMetadata {
 
     pub trait_impls: FxHashMap<(u32, DefIndex), schema::LazySeq<DefIndex>>,
 
-    pub dep_kind: Cell<DepKind>,
+    pub dep_kind: Lock<DepKind>,
     pub source: CrateSource,
 
     pub proc_macros: Option<Vec<(ast::Name, Lrc<SyntaxExtension>)>>,
@@ -90,21 +89,23 @@ pub struct CrateMetadata {
 }
 
 pub struct CStore {
-    metas: RefCell<IndexVec<CrateNum, Option<Lrc<CrateMetadata>>>>,
+    metas: RwLock<IndexVec<CrateNum, Option<Lrc<CrateMetadata>>>>,
     /// Map from NodeId's of local extern crate statements to crate numbers
-    extern_mod_crate_map: RefCell<NodeMap<CrateNum>>,
-    pub metadata_loader: Box<MetadataLoader>,
+    extern_mod_crate_map: Lock<NodeMap<CrateNum>>,
+    pub metadata_loader: Box<MetadataLoader + Sync>,
 }
 
 impl CStore {
-    pub fn new(metadata_loader: Box<MetadataLoader>) -> CStore {
+    pub fn new(metadata_loader: Box<MetadataLoader + Sync>) -> CStore {
         CStore {
-            metas: RefCell::new(IndexVec::new()),
-            extern_mod_crate_map: RefCell::new(FxHashMap()),
+            metas: RwLock::new(IndexVec::new()),
+            extern_mod_crate_map: Lock::new(FxHashMap()),
             metadata_loader,
         }
     }
 
+    /// You cannot use this function to allocate a CrateNum in a thread-safe manner.
+    /// It is currently only used in CrateLoader which is single-threaded code.
     pub fn next_crate_num(&self) -> CrateNum {
         CrateNum::new(self.metas.borrow().len() + 1)
     }
index 0b50f5c44962b7dfdd766a5fd716bd3751a87527..2de27f3a1c3eac510b32a74ba637cfaf92528185 100644 (file)
@@ -175,7 +175,10 @@ fn into_args(self) -> (DefId, DefId) { (self.0.as_def_id(), self.1) }
     is_sanitizer_runtime => { cdata.is_sanitizer_runtime(tcx.sess) }
     is_profiler_runtime => { cdata.is_profiler_runtime(tcx.sess) }
     panic_strategy => { cdata.panic_strategy() }
-    extern_crate => { Lrc::new(cdata.extern_crate.get()) }
+    extern_crate => {
+        let r = Lrc::new(*cdata.extern_crate.lock());
+        r
+    }
     is_no_builtins => { cdata.is_no_builtins(tcx.sess) }
     impl_defaultness => { cdata.get_impl_defaultness(def_id.index) }
     reachable_non_generics => {
@@ -225,7 +228,10 @@ fn into_args(self) -> (DefId, DefId) { (self.0.as_def_id(), self.1) }
         cdata.is_dllimport_foreign_item(def_id.index)
     }
     visibility => { cdata.get_visibility(def_id.index) }
-    dep_kind => { cdata.dep_kind.get() }
+    dep_kind => {
+        let r = *cdata.dep_kind.lock();
+        r
+    }
     crate_name => { cdata.name }
     item_children => {
         let mut result = vec![];
@@ -241,10 +247,11 @@ fn into_args(self) -> (DefId, DefId) { (self.0.as_def_id(), self.1) }
     }
 
     missing_extern_crate_item => {
-        match cdata.extern_crate.get() {
+        let r = match *cdata.extern_crate.borrow() {
             Some(extern_crate) if !extern_crate.direct => true,
             _ => false,
-        }
+        };
+        r
     }
 
     used_crate_source => { Lrc::new(cdata.source.clone()) }
@@ -419,13 +426,16 @@ fn associated_item_cloned_untracked(&self, def: DefId) -> ty::AssociatedItem
 
     fn dep_kind_untracked(&self, cnum: CrateNum) -> DepKind
     {
-        self.get_crate_data(cnum).dep_kind.get()
+        let data = self.get_crate_data(cnum);
+        let r = *data.dep_kind.lock();
+        r
     }
 
     fn export_macros_untracked(&self, cnum: CrateNum) {
         let data = self.get_crate_data(cnum);
-        if data.dep_kind.get() == DepKind::UnexportedMacrosOnly {
-            data.dep_kind.set(DepKind::MacrosOnly)
+        let mut dep_kind = data.dep_kind.lock();
+        if *dep_kind == DepKind::UnexportedMacrosOnly {
+            *dep_kind = DepKind::MacrosOnly;
         }
     }
 
@@ -523,7 +533,7 @@ fn load_macro_untracked(&self, id: DefId, sess: &Session) -> LoadedMacro {
                 tokens: body.into(),
                 legacy: def.legacy,
             }),
-            vis: codemap::respan(local_span.empty(), ast::VisibilityKind::Inherited),
+            vis: codemap::respan(local_span.shrink_to_lo(), ast::VisibilityKind::Inherited),
             tokens: None,
         })
     }
index f44703b9335e20e360c71e02414e0ddbc976e61a..b0c945fbf2a052f3f1f1027c3d62b03dc2b76451 100644 (file)
@@ -13,7 +13,7 @@
 use cstore::{self, CrateMetadata, MetadataBlob, NativeLibrary};
 use schema::*;
 
-use rustc_data_structures::sync::Lrc;
+use rustc_data_structures::sync::{Lrc, ReadGuard};
 use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash};
 use rustc::hir;
 use rustc::middle::cstore::{LinkagePreference, ExternConstBody,
@@ -29,9 +29,9 @@
 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::cell::Ref;
 use std::collections::BTreeMap;
 use std::io;
 use std::mem;
@@ -58,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.
@@ -77,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(),
         }
     }
 }
@@ -143,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())
@@ -282,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)
     }
 }
 
@@ -714,7 +709,7 @@ pub fn each_child_of_item<F>(&self, id: DefIndex, mut callback: F, sess: &Sessio
         };
 
         // Iterate over all children.
-        let macros_only = self.dep_kind.get().macros_only();
+        let macros_only = self.dep_kind.lock().macros_only();
         for child_index in item.children.decode((self, sess)) {
             if macros_only {
                 continue
@@ -950,6 +945,8 @@ pub fn get_item_attrs(&self, node_id: DefIndex, sess: &Session) -> Lrc<[ast::Att
         if vec_.len() < node_index + 1 {
             vec_.resize(node_index + 1, None);
         }
+        // This can overwrite the result produced by another thread, but the value
+        // written should be the same
         vec_[node_index] = Some(result.clone());
         result
     }
@@ -1156,7 +1153,7 @@ pub fn def_path_hash(&self, index: DefIndex) -> DefPathHash {
     /// for items inlined from other crates.
     pub fn imported_filemaps(&'a self,
                              local_codemap: &codemap::CodeMap)
-                             -> Ref<'a, Vec<cstore::ImportedFileMap>> {
+                             -> ReadGuard<'a, Vec<cstore::ImportedFileMap>> {
         {
             let filemaps = self.codemap_import_info.borrow();
             if !filemaps.is_empty() {
@@ -1164,6 +1161,14 @@ pub fn imported_filemaps(&'a self,
             }
         }
 
+        // Lock the codemap_import_info to ensure this only happens once
+        let mut codemap_import_info = self.codemap_import_info.borrow_mut();
+
+        if !codemap_import_info.is_empty() {
+            drop(codemap_import_info);
+            return self.codemap_import_info.borrow();
+        }
+
         let external_codemap = self.root.codemap.decode(self);
 
         let imported_filemaps = external_codemap.map(|filemap_to_import| {
@@ -1222,8 +1227,10 @@ pub fn imported_filemaps(&'a self,
             }
         }).collect();
 
+        *codemap_import_info = imported_filemaps;
+        drop(codemap_import_info);
+
         // This shouldn't borrow twice, but there is no way to downgrade RefMut to Ref.
-        *self.codemap_import_info.borrow_mut() = imported_filemaps;
         self.codemap_import_info.borrow()
     }
 }
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 23c5499bb639648c15a0ac570b531f029087988e..8494c043f90fcd28ef2e6ea3b3b20a0d0a1dceca 100644 (file)
@@ -422,7 +422,7 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
             builder.args_and_body(block, &arguments, arg_scope, &body.value)
         }));
         // Attribute epilogue to function's closing brace
-        let fn_end = span.with_lo(span.hi());
+        let fn_end = span.shrink_to_hi();
         let source_info = builder.source_info(fn_end);
         let return_block = builder.return_block();
         builder.cfg.terminate(block, source_info,
index 7fd2ea265de8025579deb08ae0d72fc4372daf77..446ef6bd32876b63dce95e1b156cf90a05b5cb54 100644 (file)
@@ -341,6 +341,8 @@ fn collect_roots<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         };
 
         tcx.hir.krate().visit_all_item_likes(&mut visitor);
+
+        visitor.push_extra_entry_roots();
     }
 
     // We can only translate items that are instantiable - items all of
@@ -998,8 +1000,6 @@ fn push_if_root(&mut self, def_id: DefId) {
 
             let instance = Instance::mono(self.tcx, def_id);
             self.output.push(create_fn_mono_item(instance));
-
-            self.push_extra_entry_roots(def_id);
         }
     }
 
@@ -1008,20 +1008,22 @@ fn push_if_root(&mut self, def_id: DefId) {
     /// monomorphized copy of the start lang item based on
     /// the return type of `main`. This is not needed when
     /// the user writes their own `start` manually.
-    fn push_extra_entry_roots(&mut self, def_id: DefId) {
-        if self.entry_fn != Some(def_id) {
-            return;
-        }
-
+    fn push_extra_entry_roots(&mut self) {
         if self.tcx.sess.entry_type.get() != Some(config::EntryMain) {
-            return;
+            return
         }
 
+        let main_def_id = if let Some(def_id) = self.entry_fn {
+            def_id
+        } else {
+            return
+        };
+
         let start_def_id = match self.tcx.lang_items().require(StartFnLangItem) {
             Ok(s) => s,
             Err(err) => self.tcx.sess.fatal(&err),
         };
-        let main_ret_ty = self.tcx.fn_sig(def_id).output();
+        let main_ret_ty = self.tcx.fn_sig(main_def_id).output();
 
         // Given that `main()` has no arguments,
         // then its return type cannot have
@@ -1066,7 +1068,6 @@ fn create_mono_items_for_default_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                    def_id_to_string(tcx, impl_def_id));
 
             if let Some(trait_ref) = tcx.impl_trait_ref(impl_def_id) {
-                let callee_substs = tcx.erase_regions(&trait_ref.substs);
                 let overridden_methods: FxHashSet<_> =
                     impl_item_refs.iter()
                                   .map(|iiref| iiref.name)
@@ -1080,10 +1081,15 @@ fn create_mono_items_for_default_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                         continue;
                     }
 
+                    let substs = Substs::for_item(tcx,
+                                                  method.def_id,
+                                                  |_, _| tcx.types.re_erased,
+                                                  |def, _| trait_ref.substs.type_for_def(def));
+
                     let instance = ty::Instance::resolve(tcx,
                                                          ty::ParamEnv::reveal_all(),
                                                          method.def_id,
-                                                         callee_substs).unwrap();
+                                                         substs).unwrap();
 
                     let mono_item = create_fn_mono_item(instance);
                     if mono_item.is_instantiable(tcx)
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 55d00f92e4dac0b1d235fa3bb9f72b6996e5a927..e5157a071bf0aa65df72e5ee9cda63508db9d272 100644 (file)
@@ -37,7 +37,9 @@ fn err_handler(&self) -> &errors::Handler {
     }
 
     fn check_lifetime(&self, lifetime: &Lifetime) {
-        let valid_names = [keywords::StaticLifetime.name(), keywords::Invalid.name()];
+        let valid_names = [keywords::UnderscoreLifetime.name(),
+                           keywords::StaticLifetime.name(),
+                           keywords::Invalid.name()];
         if !valid_names.contains(&lifetime.ident.name) &&
             token::Ident(lifetime.ident.without_first_quote()).is_reserved_ident() {
             self.err_handler().span_err(lifetime.span, "lifetimes cannot use keyword names");
@@ -45,7 +47,7 @@ fn check_lifetime(&self, lifetime: &Lifetime) {
     }
 
     fn check_label(&self, label: Ident, span: Span) {
-        if token::Ident(label.without_first_quote()).is_reserved_ident() || label.name == "'_" {
+        if token::Ident(label.without_first_quote()).is_reserved_ident() {
             self.err_handler().span_err(span, &format!("invalid label name `{}`", label.name));
         }
     }
@@ -65,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 3f74093241d297e4861f62098e33d61823f879f0..ebfd8785a0a0c8e0866fae9b2a979d11158cc09d 100644 (file)
@@ -106,14 +106,16 @@ pub fn register_syntax_extension(&mut self, name: ast::Name, extension: SyntaxEx
                 expander,
                 def_info: _,
                 allow_internal_unstable,
-                allow_internal_unsafe
+                allow_internal_unsafe,
+                unstable_feature
             } => {
                 let nid = ast::CRATE_NODE_ID;
                 NormalTT {
                     expander,
                     def_info: Some((nid, self.krate_span)),
                     allow_internal_unstable,
-                    allow_internal_unsafe
+                    allow_internal_unsafe,
+                    unstable_feature
                 }
             }
             IdentTT(ext, _, allow_internal_unstable) => {
@@ -149,6 +151,7 @@ pub fn register_macro(&mut self, name: &str, expander: MacroExpanderFn) {
             def_info: None,
             allow_internal_unstable: false,
             allow_internal_unsafe: false,
+            unstable_feature: None,
         });
     }
 
index bf7b81c4d0e420938ad8ca08a906ec9c02330366..c192f349c2019723f6eb2bba0679db27a4c43220 100644 (file)
@@ -119,7 +119,8 @@ fn build_reduced_graph_for_use_tree(&mut self,
             .collect();
 
         match use_tree.kind {
-            ast::UseTreeKind::Simple(mut ident) => {
+            ast::UseTreeKind::Simple(rename) => {
+                let mut ident = use_tree.ident();
                 let mut source = module_path.pop().unwrap().node;
                 let mut type_ns_only = false;
 
@@ -142,7 +143,7 @@ fn build_reduced_graph_for_use_tree(&mut self,
                         // Replace `use foo::self;` with `use foo;`
                         let _ = module_path.pop();
                         source = last_segment.node;
-                        if ident.name == keywords::SelfValue.name() {
+                        if rename.is_none() {
                             ident = last_segment.node;
                         }
                     }
@@ -162,7 +163,7 @@ fn build_reduced_graph_for_use_tree(&mut self,
                             ModuleKind::Block(..) => unreachable!(),
                         };
                         source.name = crate_name;
-                        if ident.name == keywords::DollarCrate.name() {
+                        if rename.is_none() {
                             ident.name = crate_name;
                         }
 
@@ -206,8 +207,8 @@ fn build_reduced_graph_for_use_tree(&mut self,
 
                 // Ensure there is at most one `self` in the list
                 let self_spans = items.iter().filter_map(|&(ref use_tree, _)| {
-                    if let ast::UseTreeKind::Simple(ident) = use_tree.kind {
-                        if ident.name == keywords::SelfValue.name() {
+                    if let ast::UseTreeKind::Simple(..) = use_tree.kind {
+                        if use_tree.ident().name == keywords::SelfValue.name() {
                             return Some(use_tree.span);
                         }
                     }
@@ -244,9 +245,9 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, expansion: Mark) {
 
         match item.node {
             ItemKind::Use(ref use_tree) => {
-                // Just an empty prefix to start out
+                // Imports are resolved as global by default, add starting root segment.
                 let prefix = ast::Path {
-                    segments: vec![],
+                    segments: use_tree.prefix.make_root().into_iter().collect(),
                     span: use_tree.span,
                 };
 
@@ -255,7 +256,7 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, expansion: Mark) {
                 );
             }
 
-            ItemKind::ExternCrate(as_name) => {
+            ItemKind::ExternCrate(orig_name) => {
                 self.crate_loader.process_item(item, &self.definitions);
 
                 // n.b. we don't need to look at the path option here, because cstore already did
@@ -274,7 +275,7 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, expansion: Mark) {
                     id: item.id,
                     parent,
                     imported_module: Cell::new(Some(module)),
-                    subclass: ImportDirectiveSubclass::ExternCrate(as_name),
+                    subclass: ImportDirectiveSubclass::ExternCrate(orig_name),
                     span: item.span,
                     module_path: Vec::new(),
                     vis: Cell::new(vis),
index c84caee13e82a0c4233f535661ed12dd35367912..dc22c23271d63855639e095e76df63fc701f8a18 100644 (file)
@@ -756,7 +756,7 @@ fn visit_mod(
                     // don't suggest placing a use before the prelude
                     // import or other generated ones
                     if item.span.ctxt().outer().expn_info().is_none() {
-                        self.span = Some(item.span.with_hi(item.span.lo()));
+                        self.span = Some(item.span.shrink_to_lo());
                         self.found_use = true;
                         return;
                     }
@@ -768,12 +768,12 @@ fn visit_mod(
                     if item.span.ctxt().outer().expn_info().is_none() {
                         // don't insert between attributes and an item
                         if item.attrs.is_empty() {
-                            self.span = Some(item.span.with_hi(item.span.lo()));
+                            self.span = Some(item.span.shrink_to_lo());
                         } else {
                             // find the first attribute on the item
                             for attr in &item.attrs {
                                 if self.span.map_or(true, |span| attr.span < span) {
-                                    self.span = Some(attr.span.with_hi(attr.span.lo()));
+                                    self.span = Some(attr.span.shrink_to_lo());
                                 }
                             }
                         }
@@ -2164,8 +2164,9 @@ fn resolve_item(&mut self, item: &Item) {
             }
 
             ItemKind::Use(ref use_tree) => {
+                // Imports are resolved as global by default, add starting root segment.
                 let path = Path {
-                    segments: vec![],
+                    segments: use_tree.prefix.make_root().into_iter().collect(),
                     span: use_tree.span,
                 };
                 self.resolve_use_tree(item.id, use_tree, &path);
@@ -2300,7 +2301,6 @@ fn with_optional_trait_ref<T, F>(&mut self, opt_trait_ref: Option<&TraitRef>, f:
                 None,
                 &path,
                 trait_ref.path.span,
-                trait_ref.path.segments.last().unwrap().span,
                 PathSource::Trait(AliasPossibility::No)
             ).base_def();
             if def != Def::Err {
@@ -2731,8 +2731,7 @@ fn smart_resolve_path(&mut self,
         let segments = &path.segments.iter()
             .map(|seg| respan(seg.span, seg.identifier))
             .collect::<Vec<_>>();
-        let ident_span = path.segments.last().map_or(path.span, |seg| seg.span);
-        self.smart_resolve_path_fragment(id, qself, segments, path.span, ident_span, source)
+        self.smart_resolve_path_fragment(id, qself, segments, path.span, source)
     }
 
     fn smart_resolve_path_fragment(&mut self,
@@ -2740,9 +2739,9 @@ fn smart_resolve_path_fragment(&mut self,
                                    qself: Option<&QSelf>,
                                    path: &[SpannedIdent],
                                    span: Span,
-                                   ident_span: Span,
                                    source: PathSource)
                                    -> PathResolution {
+        let ident_span = path.last().map_or(span, |ident| ident.span);
         let ns = source.namespace();
         let is_expected = &|def| source.is_expected(def);
         let is_enum_variant = &|def| if let Def::Variant(..) = def { true } else { false };
@@ -3090,7 +3089,7 @@ fn resolve_qpath(&mut self,
             // Make sure `A::B` in `<T as A>::B::C` is a trait item.
             let ns = if qself.position + 1 == path.len() { ns } else { TypeNS };
             let res = self.smart_resolve_path_fragment(id, None, &path[..qself.position + 1],
-                                                       span, span, PathSource::TraitItem(ns));
+                                                       span, PathSource::TraitItem(ns));
             return Some(PathResolution::with_unresolved_segments(
                 res.base_def(), res.unresolved_segments() + path.len() - qself.position - 1
             ));
@@ -3941,8 +3940,12 @@ fn resolve_visibility(&mut self, vis: &ast::Visibility) -> ty::Visibility {
                 ty::Visibility::Restricted(self.current_module.normal_ancestor_id)
             }
             ast::VisibilityKind::Restricted { ref path, id, .. } => {
-                let def = self.smart_resolve_path(id, None, path,
-                                                  PathSource::Visibility).base_def();
+                // Visibilities are resolved as global by default, add starting root segment.
+                let segments = path.make_root().iter().chain(path.segments.iter())
+                    .map(|seg| respan(seg.span, seg.identifier))
+                    .collect::<Vec<_>>();
+                let def = self.smart_resolve_path_fragment(id, None, &segments, path.span,
+                                                           PathSource::Visibility).base_def();
                 if def == Def::Err {
                     ty::Visibility::Public
                 } else {
index 01c1ded94578ecc1fa45da7521930f70595598e7..4cbebdc3c1c39f9458fb732e4e0da80bf471d2f7 100644 (file)
@@ -667,11 +667,10 @@ fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> Option<(Spa
             }
             PathResult::Failed(span, msg, true) => {
                 let (mut self_path, mut self_result) = (module_path.clone(), None);
-                if !self_path.is_empty() &&
-                    !token::Ident(self_path[0].node).is_path_segment_keyword() &&
-                    !(self_path.len() > 1 &&
-                      token::Ident(self_path[1].node).is_path_segment_keyword())
-                {
+                let is_special = |ident| token::Ident(ident).is_path_segment_keyword() &&
+                                         ident.name != keywords::CrateRoot.name();
+                if !self_path.is_empty() && !is_special(self_path[0].node) &&
+                   !(self_path.len() > 1 && is_special(self_path[1].node)) {
                     self_path[0].node.name = keywords::SelfValue.name();
                     self_result = Some(self.resolve_path(&self_path, None, false, span));
                 }
index d92025a6787d6f63597ab87accae8599e012f37b..3d4d8571c6e4242283bea932777f3e3c30ae9b4a 100644 (file)
@@ -1209,7 +1209,7 @@ fn process_macro_use(&mut self, span: Span) {
 
     fn process_trait_item(&mut self, trait_item: &'l ast::TraitItem, trait_id: DefId) {
         self.process_macro_use(trait_item.span);
-        let vis_span = trait_item.span.empty();
+        let vis_span = trait_item.span.shrink_to_lo();
         match trait_item.node {
             ast::TraitItemKind::Const(ref ty, ref expr) => {
                 self.process_assoc_const(
@@ -1342,7 +1342,8 @@ fn process_use_tree(&mut self,
             .map(::id_from_def_id);
 
         match use_tree.kind {
-            ast::UseTreeKind::Simple(ident) => {
+            ast::UseTreeKind::Simple(..) => {
+                let ident = use_tree.ident();
                 let path = ast::Path {
                     segments: prefix.segments
                         .iter()
index 45d23a2733a2a3337d12c3020323e0b14072d6a3..2a0f076cefde3c610f3085890744cadd4883de81 100644 (file)
@@ -29,6 +29,7 @@
 mod normalize_projection_ty;
 mod normalize_erasing_regions;
 mod util;
+pub mod lowering;
 
 use rustc::ty::maps::Providers;
 
@@ -39,6 +40,7 @@ pub fn provide(p: &mut Providers) {
         normalize_projection_ty: normalize_projection_ty::normalize_projection_ty,
         normalize_ty_after_erasing_regions:
             normalize_erasing_regions::normalize_ty_after_erasing_regions,
+        program_clauses_for: lowering::program_clauses_for,
         ..*p
     };
 }
diff --git a/src/librustc_traits/lowering.rs b/src/librustc_traits/lowering.rs
new file mode 100644 (file)
index 0000000..c9666f5
--- /dev/null
@@ -0,0 +1,184 @@
+// 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.
+
+use rustc::hir::{self, ImplPolarity};
+use rustc::hir::def_id::DefId;
+use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
+use rustc::ty::{self, TyCtxt};
+use rustc::traits::{QuantifierKind, Goal, DomainGoal, Clause, WhereClauseAtom};
+use syntax::ast;
+use rustc_data_structures::sync::Lrc;
+
+trait Lower<T> {
+    /// Lower a rustc construction (e.g. `ty::TraitPredicate`) to a chalk-like type.
+    fn lower(&self) -> T;
+}
+
+impl<T, U> Lower<Vec<U>> for Vec<T> where T: Lower<U> {
+    fn lower(&self) -> Vec<U> {
+        self.iter().map(|item| item.lower()).collect()
+    }
+}
+
+impl<'tcx> Lower<WhereClauseAtom<'tcx>> for ty::TraitPredicate<'tcx> {
+    fn lower(&self) -> WhereClauseAtom<'tcx> {
+        WhereClauseAtom::Implemented(*self)
+    }
+}
+
+impl<'tcx> Lower<WhereClauseAtom<'tcx>> for ty::ProjectionPredicate<'tcx> {
+    fn lower(&self) -> WhereClauseAtom<'tcx> {
+        WhereClauseAtom::ProjectionEq(*self)
+    }
+}
+
+impl<'tcx, T> Lower<DomainGoal<'tcx>> for T where T: Lower<WhereClauseAtom<'tcx>> {
+    fn lower(&self) -> DomainGoal<'tcx> {
+        DomainGoal::Holds(self.lower())
+    }
+}
+
+impl<'tcx> Lower<DomainGoal<'tcx>> for ty::RegionOutlivesPredicate<'tcx> {
+    fn lower(&self) -> DomainGoal<'tcx> {
+        DomainGoal::RegionOutlives(*self)
+    }
+}
+
+impl<'tcx> Lower<DomainGoal<'tcx>> for ty::TypeOutlivesPredicate<'tcx> {
+    fn lower(&self) -> DomainGoal<'tcx> {
+        DomainGoal::TypeOutlives(*self)
+    }
+}
+
+/// `ty::Binder` is used for wrapping a rustc construction possibly containing generic
+/// lifetimes, e.g. `for<'a> T: Fn(&'a i32)`. Instead of representing higher-ranked things
+/// in that leaf-form (i.e. `Holds(Implemented(Binder<TraitPredicate>))` in the previous
+/// example), we model them with quantified goals, e.g. as for the previous example:
+/// `forall<'a> { T: Fn(&'a i32) }` which corresponds to something like
+/// `Binder<Holds(Implemented(TraitPredicate))>`.
+///
+/// Also, if `self` does not contain generic lifetimes, we can safely drop the binder and we
+/// can directly lower to a leaf goal instead of a quantified goal.
+impl<'tcx, T> Lower<Goal<'tcx>> for ty::Binder<T>
+    where T: Lower<DomainGoal<'tcx>> + ty::fold::TypeFoldable<'tcx> + Copy
+{
+    fn lower(&self) -> Goal<'tcx> {
+        match self.no_late_bound_regions() {
+            Some(p) => p.lower().into(),
+            None => Goal::Quantified(
+                QuantifierKind::Universal,
+                Box::new(self.map_bound(|p| p.lower().into()))
+            ),
+        }
+    }
+}
+
+impl<'tcx> Lower<Goal<'tcx>> for ty::Predicate<'tcx> {
+    fn lower(&self) -> Goal<'tcx> {
+        use rustc::ty::Predicate::*;
+
+        match self {
+            Trait(predicate) => predicate.lower(),
+            RegionOutlives(predicate) => predicate.lower(),
+            TypeOutlives(predicate) => predicate.lower(),
+            Projection(predicate) => predicate.lower(),
+            WellFormed(ty) => DomainGoal::WellFormedTy(*ty).into(),
+            ObjectSafe(..) |
+            ClosureKind(..) |
+            Subtype(..) |
+            ConstEvaluatable(..) => unimplemented!(),
+        }
+    }
+}
+
+crate fn program_clauses_for<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
+    -> Lrc<Vec<Clause<'tcx>>>
+{
+    let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
+    let item = tcx.hir.expect_item(node_id);
+    match item.node {
+        hir::ItemImpl(..) => program_clauses_for_impl(tcx, def_id),
+
+        // FIXME: other constructions e.g. traits, associated types...
+        _ => Lrc::new(vec![]),
+    }
+}
+
+fn program_clauses_for_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
+    -> Lrc<Vec<Clause<'tcx>>>
+{
+    if let ImplPolarity::Negative = tcx.impl_polarity(def_id) {
+        return Lrc::new(vec![]);
+    }
+
+    // Rule Implemented-From-Impl
+    //
+    // (see rustc guide)
+
+    let trait_ref = tcx.impl_trait_ref(def_id).unwrap();
+    let trait_ref = ty::TraitPredicate { trait_ref }.lower();
+    let where_clauses = tcx.predicates_of(def_id).predicates.lower();
+
+    let clause = Clause::Implies(where_clauses, trait_ref);
+    Lrc::new(vec![clause])
+}
+
+pub fn dump_program_clauses<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
+    if !tcx.features().rustc_attrs {
+        return;
+    }
+
+    let mut visitor = ClauseDumper { tcx };
+    tcx.hir.krate().visit_all_item_likes(&mut visitor.as_deep_visitor());
+}
+
+struct ClauseDumper<'a, 'tcx: 'a> {
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+}
+
+impl <'a, 'tcx> ClauseDumper<'a, 'tcx > {
+    fn process_attrs(&mut self, node_id: ast::NodeId, attrs: &[ast::Attribute]) {
+        let def_id = self.tcx.hir.local_def_id(node_id);
+        for attr in attrs {
+            if attr.check_name("rustc_dump_program_clauses") {
+                let clauses = self.tcx.program_clauses_for(def_id);
+                for clause in &*clauses {
+                    self.tcx.sess.struct_span_err(attr.span, &format!("{}", clause)).emit();
+                }
+            }
+        }
+    }
+}
+
+impl<'a, 'tcx> Visitor<'tcx> for ClauseDumper<'a, 'tcx> {
+    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+        NestedVisitorMap::OnlyBodies(&self.tcx.hir)
+    }
+
+    fn visit_item(&mut self, item: &'tcx hir::Item) {
+        self.process_attrs(item.id, &item.attrs);
+        intravisit::walk_item(self, item);
+    }
+
+    fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
+        self.process_attrs(trait_item.id, &trait_item.attrs);
+        intravisit::walk_trait_item(self, trait_item);
+    }
+
+    fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
+        self.process_attrs(impl_item.id, &impl_item.attrs);
+        intravisit::walk_impl_item(self, impl_item);
+    }
+
+    fn visit_struct_field(&mut self, s: &'tcx hir::StructField) {
+        self.process_attrs(s.id, &s.attrs);
+        intravisit::walk_struct_field(self, s);
+    }
+}
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 7651a8e748e3c0ba87f9b43e2bd69000ebed34e6..3e7422557e9b69bfad097094d7c51ae9876b683f 100644 (file)
@@ -42,6 +42,7 @@
 use syntax_pos::symbol::Symbol;
 use type_::Type;
 use context::{is_pie_binary, get_reloc_model};
+use common::{C_bytes_in_context, val_ty};
 use jobserver::{Client, Acquired};
 use rustc_demangle;
 
@@ -262,6 +263,8 @@ pub struct ModuleConfig {
     // emscripten's ecc compiler, when used as the linker.
     obj_is_bitcode: bool,
     no_integrated_as: bool,
+    embed_bitcode: bool,
+    embed_bitcode_marker: bool,
 }
 
 impl ModuleConfig {
@@ -279,6 +282,8 @@ fn new(passes: Vec<String>) -> ModuleConfig {
             emit_asm: false,
             emit_obj: false,
             obj_is_bitcode: false,
+            embed_bitcode: false,
+            embed_bitcode_marker: false,
             no_integrated_as: false,
 
             no_verify: false,
@@ -299,6 +304,17 @@ fn set_flags(&mut self, sess: &Session, no_builtins: bool) {
         self.time_passes = sess.time_passes();
         self.inline_threshold = sess.opts.cg.inline_threshold;
         self.obj_is_bitcode = sess.target.target.options.obj_is_bitcode;
+        let embed_bitcode = sess.target.target.options.embed_bitcode ||
+            sess.opts.debugging_opts.embed_bitcode;
+        if embed_bitcode {
+            match sess.opts.optimize {
+                config::OptLevel::No |
+                config::OptLevel::Less => {
+                    self.embed_bitcode_marker = embed_bitcode;
+                }
+                _ => self.embed_bitcode = embed_bitcode,
+            }
+        }
 
         // Copy what clang does by turning on loop vectorization at O2 and
         // slp vectorization at O3. Otherwise configure other optimization aspects
@@ -662,7 +678,7 @@ unsafe fn with_codegen<F, R>(tm: TargetMachineRef,
     let obj_out = cgcx.output_filenames.temp_path(OutputType::Object, module_name);
 
 
-    if write_bc || config.emit_bc_compressed {
+    if write_bc || config.emit_bc_compressed || config.embed_bitcode {
         let thin;
         let old;
         let data = if llvm::LLVMRustThinLTOAvailable() {
@@ -681,6 +697,11 @@ unsafe fn with_codegen<F, R>(tm: TargetMachineRef,
             timeline.record("write-bc");
         }
 
+        if config.embed_bitcode {
+            embed_bitcode(cgcx, llcx, llmod, Some(data));
+            timeline.record("embed-bc");
+        }
+
         if config.emit_bc_compressed {
             let dst = bc_out.with_extension(RLIB_BYTECODE_EXTENSION);
             let data = bytecode::encode(&mtrans.llmod_id, data);
@@ -689,6 +710,8 @@ unsafe fn with_codegen<F, R>(tm: TargetMachineRef,
             }
             timeline.record("compress-bc");
         }
+    } else if config.embed_bitcode_marker {
+        embed_bitcode(cgcx, llcx, llmod, None);
     }
 
     time_ext(config.time_passes, None, &format!("codegen passes [{}]", module_name.unwrap()),
@@ -796,6 +819,59 @@ extern "C" fn demangle_callback(input_ptr: *const c_char,
                                    &cgcx.output_filenames))
 }
 
+/// Embed the bitcode of an LLVM module in the LLVM module itself.
+///
+/// This is done primarily for iOS where it appears to be standard to compile C
+/// code at least with `-fembed-bitcode` which creates two sections in the
+/// executable:
+///
+/// * __LLVM,__bitcode
+/// * __LLVM,__cmdline
+///
+/// It appears *both* of these sections are necessary to get the linker to
+/// recognize what's going on. For us though we just always throw in an empty
+/// cmdline section.
+///
+/// Furthermore debug/O1 builds don't actually embed bitcode but rather just
+/// embed an empty section.
+///
+/// Basically all of this is us attempting to follow in the footsteps of clang
+/// on iOS. See #35968 for lots more info.
+unsafe fn embed_bitcode(cgcx: &CodegenContext,
+                        llcx: ContextRef,
+                        llmod: ModuleRef,
+                        bitcode: Option<&[u8]>) {
+    let llconst = C_bytes_in_context(llcx, bitcode.unwrap_or(&[]));
+    let llglobal = llvm::LLVMAddGlobal(
+        llmod,
+        val_ty(llconst).to_ref(),
+        "rustc.embedded.module\0".as_ptr() as *const _,
+    );
+    llvm::LLVMSetInitializer(llglobal, llconst);
+    let section = if cgcx.opts.target_triple.contains("-ios") {
+        "__LLVM,__bitcode\0"
+    } else {
+        ".llvmbc\0"
+    };
+    llvm::LLVMSetSection(llglobal, section.as_ptr() as *const _);
+    llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage);
+
+    let llconst = C_bytes_in_context(llcx, &[]);
+    let llglobal = llvm::LLVMAddGlobal(
+        llmod,
+        val_ty(llconst).to_ref(),
+        "rustc.embedded.cmdline\0".as_ptr() as *const _,
+    );
+    llvm::LLVMSetInitializer(llglobal, llconst);
+    let section = if cgcx.opts.target_triple.contains("-ios") {
+        "__LLVM,__cmdline\0"
+    } else {
+        ".llvmcmd\0"
+    };
+    llvm::LLVMSetSection(llglobal, section.as_ptr() as *const _);
+    llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage);
+}
+
 pub(crate) struct CompiledModules {
     pub modules: Vec<CompiledModule>,
     pub metadata_module: CompiledModule,
index d4e05a18e3a506cbdabd781d3e710c58b99b352c..3f5a9a54ff1eacfab2bd485672b2091e50d4635a 100644 (file)
@@ -955,6 +955,147 @@ pub fn vector_splat(&self, num_elts: usize, elt: ValueRef) -> ValueRef {
         }
     }
 
+    pub fn vector_reduce_fadd_fast(&self, acc: ValueRef, src: ValueRef) -> ValueRef {
+        self.count_insn("vector.reduce.fadd_fast");
+        unsafe {
+            // FIXME: add a non-fast math version once
+            // https://bugs.llvm.org/show_bug.cgi?id=36732
+            // is fixed.
+            let instr = llvm::LLVMRustBuildVectorReduceFAdd(self.llbuilder, acc, src);
+            if instr.is_null() {
+                bug!("LLVMRustBuildVectorReduceFAdd is not available in LLVM version < 5.0");
+            }
+            llvm::LLVMRustSetHasUnsafeAlgebra(instr);
+            instr
+        }
+    }
+    pub fn vector_reduce_fmul_fast(&self, acc: ValueRef, src: ValueRef) -> ValueRef {
+        self.count_insn("vector.reduce.fmul_fast");
+        unsafe {
+            // FIXME: add a non-fast math version once
+            // https://bugs.llvm.org/show_bug.cgi?id=36732
+            // is fixed.
+            let instr = llvm::LLVMRustBuildVectorReduceFMul(self.llbuilder, acc, src);
+            if instr.is_null() {
+                bug!("LLVMRustBuildVectorReduceFMul is not available in LLVM version < 5.0");
+            }
+            llvm::LLVMRustSetHasUnsafeAlgebra(instr);
+            instr
+        }
+    }
+    pub fn vector_reduce_add(&self, src: ValueRef) -> ValueRef {
+        self.count_insn("vector.reduce.add");
+        unsafe {
+            let instr = llvm::LLVMRustBuildVectorReduceAdd(self.llbuilder, src);
+            if instr.is_null() {
+                bug!("LLVMRustBuildVectorReduceAdd is not available in LLVM version < 5.0");
+            }
+            instr
+        }
+    }
+    pub fn vector_reduce_mul(&self, src: ValueRef) -> ValueRef {
+        self.count_insn("vector.reduce.mul");
+        unsafe {
+            let instr = llvm::LLVMRustBuildVectorReduceMul(self.llbuilder, src);
+            if instr.is_null() {
+                bug!("LLVMRustBuildVectorReduceMul is not available in LLVM version < 5.0");
+            }
+            instr
+        }
+    }
+    pub fn vector_reduce_and(&self, src: ValueRef) -> ValueRef {
+        self.count_insn("vector.reduce.and");
+        unsafe {
+            let instr = llvm::LLVMRustBuildVectorReduceAnd(self.llbuilder, src);
+            if instr.is_null() {
+                bug!("LLVMRustBuildVectorReduceAnd is not available in LLVM version < 5.0");
+            }
+            instr
+        }
+    }
+    pub fn vector_reduce_or(&self, src: ValueRef) -> ValueRef {
+        self.count_insn("vector.reduce.or");
+        unsafe {
+            let instr = llvm::LLVMRustBuildVectorReduceOr(self.llbuilder, src);
+            if instr.is_null() {
+                bug!("LLVMRustBuildVectorReduceOr is not available in LLVM version < 5.0");
+            }
+            instr
+        }
+    }
+    pub fn vector_reduce_xor(&self, src: ValueRef) -> ValueRef {
+        self.count_insn("vector.reduce.xor");
+        unsafe {
+            let instr = llvm::LLVMRustBuildVectorReduceXor(self.llbuilder, src);
+            if instr.is_null() {
+                bug!("LLVMRustBuildVectorReduceXor is not available in LLVM version < 5.0");
+            }
+            instr
+        }
+    }
+    pub fn vector_reduce_fmin(&self, src: ValueRef) -> ValueRef {
+        self.count_insn("vector.reduce.fmin");
+        unsafe {
+            let instr = llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, true);
+            if instr.is_null() {
+                bug!("LLVMRustBuildVectorReduceFMin is not available in LLVM version < 5.0");
+            }
+            instr
+        }
+    }
+    pub fn vector_reduce_fmax(&self, src: ValueRef) -> ValueRef {
+        self.count_insn("vector.reduce.fmax");
+        unsafe {
+            let instr = llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, true);
+            if instr.is_null() {
+                bug!("LLVMRustBuildVectorReduceFMax is not available in LLVM version < 5.0");
+            }
+            instr
+        }
+    }
+    pub fn vector_reduce_fmin_fast(&self, src: ValueRef) -> ValueRef {
+        self.count_insn("vector.reduce.fmin_fast");
+        unsafe {
+            let instr = llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, false);
+            if instr.is_null() {
+                bug!("LLVMRustBuildVectorReduceFMin is not available in LLVM version < 5.0");
+            }
+            llvm::LLVMRustSetHasUnsafeAlgebra(instr);
+            instr
+        }
+    }
+    pub fn vector_reduce_fmax_fast(&self, src: ValueRef) -> ValueRef {
+        self.count_insn("vector.reduce.fmax_fast");
+        unsafe {
+            let instr = llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, false);
+            if instr.is_null() {
+                bug!("LLVMRustBuildVectorReduceFMax is not available in LLVM version < 5.0");
+            }
+            llvm::LLVMRustSetHasUnsafeAlgebra(instr);
+            instr
+        }
+    }
+    pub fn vector_reduce_min(&self, src: ValueRef, is_signed: bool) -> ValueRef {
+        self.count_insn("vector.reduce.min");
+        unsafe {
+            let instr = llvm::LLVMRustBuildVectorReduceMin(self.llbuilder, src, is_signed);
+            if instr.is_null() {
+                bug!("LLVMRustBuildVectorReduceMin is not available in LLVM version < 5.0");
+            }
+            instr
+        }
+    }
+    pub fn vector_reduce_max(&self, src: ValueRef, is_signed: bool) -> ValueRef {
+        self.count_insn("vector.reduce.max");
+        unsafe {
+            let instr = llvm::LLVMRustBuildVectorReduceMax(self.llbuilder, src, is_signed);
+            if instr.is_null() {
+                bug!("LLVMRustBuildVectorReduceMax is not available in LLVM version < 5.0");
+            }
+            instr
+        }
+    }
+
     pub fn extract_value(&self, agg_val: ValueRef, idx: u64) -> ValueRef {
         self.count_insn("extractvalue");
         assert_eq!(idx as c_uint as u64, idx);
index c71c0cc0ebf2c9ee3a98b25a649b6d0bfd5004c0..e83e73c8ae7578d33fdc61b71a767e32aba262cc 100644 (file)
@@ -269,6 +269,19 @@ pub fn const_get_elt(v: ValueRef, idx: u64) -> ValueRef {
     }
 }
 
+pub fn const_get_real(v: ValueRef) -> Option<(f64, bool)> {
+    unsafe {
+        if is_const_real(v) {
+            let mut loses_info: llvm::Bool = ::std::mem::uninitialized();
+            let r = llvm::LLVMConstRealGetDouble(v, &mut loses_info as *mut llvm::Bool);
+            let loses_info = if loses_info == 1 { true } else { false };
+            Some((r, loses_info))
+        } else {
+            None
+        }
+    }
+}
+
 pub fn const_to_uint(v: ValueRef) -> u64 {
     unsafe {
         llvm::LLVMConstIntGetZExtValue(v)
@@ -281,6 +294,13 @@ pub fn is_const_integral(v: ValueRef) -> bool {
     }
 }
 
+pub fn is_const_real(v: ValueRef) -> bool {
+    unsafe {
+        !llvm::LLVMIsAConstantFP(v).is_null()
+    }
+}
+
+
 #[inline]
 fn hi_lo_to_u128(lo: u64, hi: u64) -> u128 {
     ((hi as u128) << 64) | (lo as u128)
index 4cef7470c62d738ab181381f61d2182eb3a59ebe..c3de9e0ffcce226bc11ce5c1b3232bf6f931f982 100644 (file)
@@ -1018,14 +1018,22 @@ macro_rules! emit_error {
                          name, $($fmt)*));
         }
     }
-    macro_rules! require {
-        ($cond: expr, $($fmt: tt)*) => {
-            if !$cond {
+    macro_rules! return_error {
+        ($($fmt: tt)*) => {
+            {
                 emit_error!($($fmt)*);
                 return Err(());
             }
         }
     }
+
+    macro_rules! require {
+        ($cond: expr, $($fmt: tt)*) => {
+            if !$cond {
+                return_error!($($fmt)*);
+            }
+        };
+    }
     macro_rules! require_simd {
         ($ty: expr, $position: expr) => {
             require!($ty.is_simd(), "expected SIMD {} type, found non-SIMD `{}`", $position, $ty)
@@ -1145,6 +1153,161 @@ macro_rules! require_simd {
         return Ok(bx.extract_element(args[0].immediate(), args[1].immediate()))
     }
 
+    macro_rules! arith_red {
+        ($name:tt : $integer_reduce:ident, $float_reduce:ident, $ordered:expr) => {
+            if name == $name {
+                require!(ret_ty == in_elem,
+                         "expected return type `{}` (element of input `{}`), found `{}`",
+                         in_elem, in_ty, ret_ty);
+                return match in_elem.sty {
+                    ty::TyInt(_) | ty::TyUint(_) => {
+                        let r = bx.$integer_reduce(args[0].immediate());
+                        if $ordered {
+                            // if overflow occurs, the result is the
+                            // mathematical result modulo 2^n:
+                            if name.contains("mul") {
+                                Ok(bx.mul(args[1].immediate(), r))
+                            } else {
+                                Ok(bx.add(args[1].immediate(), r))
+                            }
+                        } else {
+                            Ok(bx.$integer_reduce(args[0].immediate()))
+                        }
+                    },
+                    ty::TyFloat(f) => {
+                        // ordered arithmetic reductions take an accumulator
+                        let acc = if $ordered {
+                            let acc = args[1].immediate();
+                            // FIXME: https://bugs.llvm.org/show_bug.cgi?id=36734
+                            // * if the accumulator of the fadd isn't 0, incorrect
+                            //   code is generated
+                            // * if the accumulator of the fmul isn't 1, incorrect
+                            //   code is generated
+                            match const_get_real(acc) {
+                                None => return_error!("accumulator of {} is not a constant", $name),
+                                Some((v, loses_info)) => {
+                                    if $name.contains("mul") && v != 1.0_f64 {
+                                        return_error!("accumulator of {} is not 1.0", $name);
+                                    } else if $name.contains("add") && v != 0.0_f64 {
+                                        return_error!("accumulator of {} is not 0.0", $name);
+                                    } else if loses_info {
+                                        return_error!("accumulator of {} loses information", $name);
+                                    }
+                                }
+                            }
+                            acc
+                        } else {
+                            // unordered arithmetic reductions do not:
+                            match f.bit_width() {
+                                32 => C_undef(Type::f32(bx.cx)),
+                                64 => C_undef(Type::f64(bx.cx)),
+                                v => {
+                                    return_error!(r#"
+unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,
+                                        $name, in_ty, in_elem, v, ret_ty
+                                    )
+                                }
+                            }
+
+                        };
+                        Ok(bx.$float_reduce(acc, args[0].immediate()))
+                    }
+                    _ => {
+                        return_error!(
+                            "unsupported {} from `{}` with element `{}` to `{}`",
+                            $name, in_ty, in_elem, ret_ty
+                        )
+                    },
+                }
+            }
+        }
+    }
+
+    arith_red!("simd_reduce_add_ordered": vector_reduce_add, vector_reduce_fadd_fast, true);
+    arith_red!("simd_reduce_mul_ordered": vector_reduce_mul, vector_reduce_fmul_fast, true);
+    arith_red!("simd_reduce_add_unordered": vector_reduce_add, vector_reduce_fadd_fast, false);
+    arith_red!("simd_reduce_mul_unordered": vector_reduce_mul, vector_reduce_fmul_fast, false);
+
+    macro_rules! minmax_red {
+        ($name:tt: $int_red:ident, $float_red:ident) => {
+            if name == $name {
+                require!(ret_ty == in_elem,
+                         "expected return type `{}` (element of input `{}`), found `{}`",
+                         in_elem, in_ty, ret_ty);
+                return match in_elem.sty {
+                    ty::TyInt(_i) => {
+                        Ok(bx.$int_red(args[0].immediate(), true))
+                    },
+                    ty::TyUint(_u) => {
+                        Ok(bx.$int_red(args[0].immediate(), false))
+                    },
+                    ty::TyFloat(_f) => {
+                        Ok(bx.$float_red(args[0].immediate()))
+                    }
+                    _ => {
+                        return_error!("unsupported {} from `{}` with element `{}` to `{}`",
+                                      $name, in_ty, in_elem, ret_ty)
+                    },
+                }
+            }
+
+        }
+    }
+
+    minmax_red!("simd_reduce_min": vector_reduce_min, vector_reduce_fmin);
+    minmax_red!("simd_reduce_max": vector_reduce_max, vector_reduce_fmax);
+
+    minmax_red!("simd_reduce_min_nanless": vector_reduce_min, vector_reduce_fmin_fast);
+    minmax_red!("simd_reduce_max_nanless": vector_reduce_max, vector_reduce_fmax_fast);
+
+    macro_rules! bitwise_red {
+        ($name:tt : $red:ident, $boolean:expr) => {
+            if name == $name {
+                let input = if !$boolean {
+                    require!(ret_ty == in_elem,
+                             "expected return type `{}` (element of input `{}`), found `{}`",
+                             in_elem, in_ty, ret_ty);
+                    args[0].immediate()
+                } else {
+                    match in_elem.sty {
+                        ty::TyInt(_) | ty::TyUint(_) => {},
+                        _ => {
+                            return_error!("unsupported {} from `{}` with element `{}` to `{}`",
+                                          $name, in_ty, in_elem, ret_ty)
+                        }
+                    }
+
+                    // boolean reductions operate on vectors of i1s:
+                    let i1 = Type::i1(bx.cx);
+                    let i1xn = Type::vector(&i1, in_len as u64);
+                    bx.trunc(args[0].immediate(), i1xn)
+                };
+                return match in_elem.sty {
+                    ty::TyInt(_) | ty::TyUint(_) => {
+                        let r = bx.$red(input);
+                        Ok(
+                            if !$boolean {
+                                r
+                            } else {
+                                bx.zext(r, Type::bool(bx.cx))
+                            }
+                        )
+                    },
+                    _ => {
+                        return_error!("unsupported {} from `{}` with element `{}` to `{}`",
+                                      $name, in_ty, in_elem, ret_ty)
+                    },
+                }
+            }
+        }
+    }
+
+    bitwise_red!("simd_reduce_and": vector_reduce_and, false);
+    bitwise_red!("simd_reduce_or": vector_reduce_or, false);
+    bitwise_red!("simd_reduce_xor": vector_reduce_xor, false);
+    bitwise_red!("simd_reduce_all": vector_reduce_and, true);
+    bitwise_red!("simd_reduce_any": vector_reduce_or, true);
+
     if name == "simd_cast" {
         require_simd!(ret_ty, "return");
         let out_len = ret_ty.simd_size(tcx);
index 0a98f74212d69e59281e35762a081a58f9372db8..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)]
@@ -201,7 +201,7 @@ fn target_features(&self, sess: &Session) -> Vec<Symbol> {
         target_features(sess)
     }
 
-    fn metadata_loader(&self) -> Box<MetadataLoader> {
+    fn metadata_loader(&self) -> Box<MetadataLoader + Sync> {
         box metadata::LlvmMetadataLoader
     }
 
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 0d4811c4b025dfd05c14eeaf3a9b5ac93f6ed70f..5cf9819288b5ef7628c1a8b670c05f979aa37b10 100644 (file)
@@ -58,7 +58,7 @@ fn print_passes(&self) {}
     fn print_version(&self) {}
     fn diagnostics(&self) -> &[(&'static str, &'static str)] { &[] }
 
-    fn metadata_loader(&self) -> Box<MetadataLoader>;
+    fn metadata_loader(&self) -> Box<MetadataLoader + Sync>;
     fn provide(&self, _providers: &mut Providers);
     fn provide_extern(&self, _providers: &mut Providers);
     fn trans_crate<'a, 'tcx>(
@@ -84,7 +84,7 @@ fn join_trans_and_link(
 pub struct DummyTransCrate;
 
 impl TransCrate for DummyTransCrate {
-    fn metadata_loader(&self) -> Box<MetadataLoader> {
+    fn metadata_loader(&self) -> Box<MetadataLoader + Sync> {
         box DummyMetadataLoader(())
     }
 
@@ -195,7 +195,7 @@ fn init(&self, sess: &Session) {
         }
     }
 
-    fn metadata_loader(&self) -> Box<MetadataLoader> {
+    fn metadata_loader(&self) -> Box<MetadataLoader + Sync> {
         box NoLlvmMetadataLoader
     }
 
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 59cf8a0358efac01de1b1d6c50f67a41d521543a..99707a4a3c0e59618e9fc36fd15e274adf16533d 100644 (file)
@@ -361,6 +361,14 @@ pub fn check_platform_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         "simd_insert" => (2, vec![param(0), tcx.types.u32, param(1)], param(0)),
         "simd_extract" => (2, vec![param(0), tcx.types.u32], param(1)),
         "simd_cast" => (2, vec![param(0)], param(1)),
+        "simd_reduce_all" | "simd_reduce_any" => (1, vec![param(0)], tcx.types.bool),
+        "simd_reduce_add_ordered" | "simd_reduce_mul_ordered"
+            => (2, vec![param(0), param(1)], param(1)),
+        "simd_reduce_add_unordered" | "simd_reduce_mul_unordered" |
+        "simd_reduce_and" | "simd_reduce_or"  | "simd_reduce_xor" |
+        "simd_reduce_min" | "simd_reduce_max" |
+        "simd_reduce_min_nanless" | "simd_reduce_max_nanless"
+            => (2, vec![param(0)], param(1)),
         name if name.starts_with("simd_shuffle") => {
             match name["simd_shuffle".len()..].parse() {
                 Ok(n) => {
index 5c20490f8230316b392c527d50de33a9f69c5c20..61afac97d6409b337a19522d934bc35519645f9e 100644 (file)
@@ -767,7 +767,7 @@ fn visit_mod(
                     // don't suggest placing a use before the prelude
                     // import or other generated ones
                     if item.span.ctxt().outer().expn_info().is_none() {
-                        self.span = Some(item.span.with_hi(item.span.lo()));
+                        self.span = Some(item.span.shrink_to_lo());
                         self.found_use = true;
                         return;
                     }
@@ -779,12 +779,12 @@ fn visit_mod(
                     if item.span.ctxt().outer().expn_info().is_none() {
                         // don't insert between attributes and an item
                         if item.attrs.is_empty() {
-                            self.span = Some(item.span.with_hi(item.span.lo()));
+                            self.span = Some(item.span.shrink_to_lo());
                         } else {
                             // find the first attribute on the item
                             for attr in &item.attrs {
                                 if self.span.map_or(true, |span| attr.span < span) {
-                                    self.span = Some(attr.span.with_hi(attr.span.lo()));
+                                    self.span = Some(attr.span.shrink_to_lo());
                                 }
                             }
                         }
index 8b5d45d6aa118150b36db3af9005060fae33ee12..eb61aa94cd76fbf571d153fd7bd00fa8c85ea451 100644 (file)
@@ -2535,7 +2535,7 @@ fn parameter_count_error<'tcx>(sess: &Session,
             if sugg_unit {
                 let sugg_span = sess.codemap().end_point(expr_sp);
                 // remove closing `)` from the span
-                let sugg_span = sugg_span.with_hi(sugg_span.lo());
+                let sugg_span = sugg_span.shrink_to_lo();
                 err.span_suggestion(
                     sugg_span,
                     "expected the unit value `()`; create it with empty parentheses",
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 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 904c24815cb7f3d4c36b033a044f087e66c9901e..b3ee685fb84c0d0bce035151c66177db34281f01 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 ef01c3e6bdb0c224b69168552082b069a3e00f36..659ec8a993dc8e3f60e5b3ea6db95f11e38b5c87 100644 (file)
@@ -352,7 +352,7 @@ fn write_token<W: Writer>(&mut self,
 
             token::Lifetime(..) => Class::Lifetime,
 
-            token::Underscore | token::Eof | token::Interpolated(..) |
+            token::Eof | token::Interpolated(..) |
             token::Tilde | token::At | token::DotEq => Class::None,
         };
 
index ae28e5a0923ead24ca3e4c8b5f705a21024137c8..5ce3d57f82f23f79dc6255b572940fc45da84080 100644 (file)
 //! use rustdoc::html::markdown::Markdown;
 //!
 //! let s = "My *markdown* _text_";
-//! let html = format!("{}", Markdown(s));
+//! let html = format!("{}", Markdown(s, &[]));
 //! // ... something using html
 //! ```
 
 #![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..707d5a12bbf9f53df8f6adf9f353df25eda30991 100644 (file)
@@ -645,8 +645,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);
index f692e05d6a2591c07c9c618cc1456685f4dbb884..f45a5b030db2bf354b0095e5ccc58c7004826bcd 100644 (file)
@@ -406,13 +406,13 @@ pub fn visit_item(&mut self, item: &hir::Item,
             // If we're inlining, skip private items.
             _ if self.inlining && item.vis != hir::Public => {}
             hir::ItemGlobalAsm(..) => {}
-            hir::ItemExternCrate(ref p) => {
+            hir::ItemExternCrate(orig_name) => {
                 let def_id = self.cx.tcx.hir.local_def_id(item.id);
                 om.extern_crates.push(ExternCrate {
                     cnum: self.cx.tcx.extern_mod_stmt_cnum(def_id)
                                 .unwrap_or(LOCAL_CRATE),
                     name,
-                    path: p.map(|x|x.to_string()),
+                    path: orig_name.map(|x|x.to_string()),
                     vis: item.vis.clone(),
                     attrs: item.attrs.clone(),
                     whence: item.span,
index a41c155f3fb521fd1ac5f519c6b0107c00dda019..6652ff98201a07b40f3da92de3276b8e4eb51486 100644 (file)
@@ -86,6 +86,7 @@ fn main() {
 
 fn build_libbacktrace(host: &str, target: &str) -> Result<(), ()> {
     let native = native_lib_boilerplate("libbacktrace", "libbacktrace", "backtrace", ".libs")?;
+    let cflags = env::var("CFLAGS").unwrap_or_default() + " -fvisibility=hidden -O2";
 
     run(Command::new("sh")
                 .current_dir(&native.out_dir)
@@ -98,7 +99,7 @@ fn build_libbacktrace(host: &str, target: &str) -> Result<(), ()> {
                 .arg("--disable-host-shared")
                 .arg(format!("--host={}", build_helper::gnu_target(target)))
                 .arg(format!("--build={}", build_helper::gnu_target(host)))
-                .env("CFLAGS", env::var("CFLAGS").unwrap_or_default() + " -fvisibility=hidden"));
+                .env("CFLAGS", cflags));
 
     run(Command::new(build_helper::make(host))
                 .current_dir(&native.out_dir)
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 cd9484de85a89d217386c8389d3beed7ab5adfd1..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)]
 // We want to re-export a few macros from core but libcore has already been
 // imported by the compiler (via our #[no_std] attribute) In this case we just
 // add a new crate name so we can attach the re-exports to it.
-#[macro_reexport(assert, assert_eq, assert_ne, debug_assert, debug_assert_eq,
+#[macro_reexport(assert_eq, assert_ne, debug_assert, debug_assert_eq,
                  debug_assert_ne, unreachable, unimplemented, write, writeln, try)]
+#[cfg_attr(stage0, macro_reexport(assert))]
 extern crate core as __core;
 
 #[macro_use]
index b804cf7cd9021711d818ad766f0ccfa3830318a9..000f9713615300f5871cfd45a35c354c7fd85c40 100644 (file)
@@ -719,6 +719,60 @@ macro_rules! include {
         ($file:expr) => ({ /* compiler built-in */ });
         ($file:expr,) => ({ /* compiler built-in */ });
     }
+
+    /// Ensure that a boolean expression is `true` at runtime.
+    ///
+    /// This will invoke the [`panic!`] macro if the provided expression cannot be
+    /// evaluated to `true` at runtime.
+    ///
+    /// # Uses
+    ///
+    /// Assertions are always checked in both debug and release builds, and cannot
+    /// be disabled. See [`debug_assert!`] for assertions that are not enabled in
+    /// release builds by default.
+    ///
+    /// Unsafe code relies on `assert!` to enforce run-time invariants that, if
+    /// violated could lead to unsafety.
+    ///
+    /// Other use-cases of `assert!` include [testing] and enforcing run-time
+    /// invariants in safe code (whose violation cannot result in unsafety).
+    ///
+    /// # Custom Messages
+    ///
+    /// This macro has a second form, where a custom panic message can
+    /// be provided with or without arguments for formatting.  See [`std::fmt`]
+    /// for syntax for this form.
+    ///
+    /// [`panic!`]: macro.panic.html
+    /// [`debug_assert!`]: macro.debug_assert.html
+    /// [testing]: ../book/second-edition/ch11-01-writing-tests.html#checking-results-with-the-assert-macro
+    /// [`std::fmt`]: ../std/fmt/index.html
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// // the panic message for these assertions is the stringified value of the
+    /// // expression given.
+    /// assert!(true);
+    ///
+    /// fn some_computation() -> bool { true } // a very simple function
+    ///
+    /// assert!(some_computation());
+    ///
+    /// // assert with a custom message
+    /// let x = true;
+    /// assert!(x, "x wasn't true!");
+    ///
+    /// let a = 3; let b = 27;
+    /// assert!(a + b == 30, "a = {}, b = {}", a, b);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[macro_export]
+    macro_rules! assert {
+        ($cond:expr) => ({ /* compiler built-in */ });
+        ($cond:expr,) => ({ /* compiler built-in */ });
+        ($cond:expr, $($arg:tt)+) => ({ /* compiler built-in */ });
+    }
 }
 
 /// A macro for defining #[cfg] if-else statements.
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 8b3a7164cccb6779d679b7f2c8daff76e5ce37cb..1f16b728cd23951cec66be533adae4fe0b6217e4 100644 (file)
@@ -108,17 +108,16 @@ pub fn from_ident(s: Span, identifier: Ident) -> Path {
         }
     }
 
-    // Add starting "crate root" segment to all paths except those that
-    // already have it or start with `self`, `super`, `Self` or `$crate`.
-    pub fn default_to_global(mut self) -> Path {
-        if !self.is_global() {
-            let ident = self.segments[0].identifier;
-            if !::parse::token::Ident(ident).is_path_segment_keyword() ||
-               ident.name == keywords::Crate.name() {
-                self.segments.insert(0, PathSegment::crate_root(self.span));
+    // Make a "crate root" segment for this path unless it already has it
+    // or starts with something like `self`/`super`/`$crate`/etc.
+    pub fn make_root(&self) -> Option<PathSegment> {
+        if let Some(ident) = self.segments.get(0).map(|seg| seg.identifier) {
+            if ::parse::token::Ident(ident).is_path_segment_keyword() &&
+               ident.name != keywords::Crate.name() {
+                return None;
             }
         }
-        self
+        Some(PathSegment::crate_root(self.span.shrink_to_lo()))
     }
 
     pub fn is_global(&self) -> bool {
@@ -1878,20 +1877,37 @@ pub struct Variant_ {
 
 pub type Variant = Spanned<Variant_>;
 
+/// Part of `use` item to the right of its prefix.
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub enum UseTreeKind {
-    Simple(Ident),
-    Glob,
+    /// `use prefix` or `use prefix as rename`
+    Simple(Option<Ident>),
+    /// `use prefix::{...}`
     Nested(Vec<(UseTree, NodeId)>),
+    /// `use prefix::*`
+    Glob,
 }
 
+/// A tree of paths sharing common prefixes.
+/// Used in `use` items both at top-level and inside of braces in import groups.
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct UseTree {
-    pub kind: UseTreeKind,
     pub prefix: Path,
+    pub kind: UseTreeKind,
     pub span: Span,
 }
 
+impl UseTree {
+    pub fn ident(&self) -> Ident {
+        match self.kind {
+            UseTreeKind::Simple(Some(rename)) => rename,
+            UseTreeKind::Simple(None) =>
+                self.prefix.segments.last().expect("empty prefix in a simple import").identifier,
+            _ => panic!("`UseTree::ident` can only be used on a simple import"),
+        }
+    }
+}
+
 /// Distinguishes between Attributes that decorate items and Attributes that
 /// are contained as statements within items. These two cases need to be
 /// distinguished for pretty-printing.
@@ -2055,7 +2071,7 @@ pub struct Item {
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub enum ItemKind {
-    /// An `extern crate` item, with optional original crate name.
+    /// An `extern crate` item, with optional *original* crate name if the crate was renamed.
     ///
     /// E.g. `extern crate foo` or `extern crate foo_bar as foo`
     ExternCrate(Option<Name>),
index 951f8a871ca66d2588f90f23a832ed154371453a..73924c4270e669706b2fc027bff54c3fb4a9bce6 100644 (file)
@@ -24,8 +24,7 @@
 
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::StableHasher;
-use rustc_data_structures::sync::Lrc;
-use std::cell::{RefCell, Ref};
+use rustc_data_structures::sync::{Lrc, Lock, LockGuard};
 use std::cmp;
 use std::hash::Hash;
 use std::path::{Path, PathBuf};
@@ -125,13 +124,17 @@ pub fn new(filemap: &FileMap) -> StableFilemapId {
 // CodeMap
 //
 
+pub(super) struct CodeMapFiles {
+    pub(super) file_maps: Vec<Lrc<FileMap>>,
+    stable_id_to_filemap: FxHashMap<StableFilemapId, Lrc<FileMap>>
+}
+
 pub struct CodeMap {
-    pub(super) files: RefCell<Vec<Lrc<FileMap>>>,
-    file_loader: Box<FileLoader>,
+    pub(super) files: Lock<CodeMapFiles>,
+    file_loader: Box<FileLoader + Sync + Send>,
     // This is used to apply the file path remapping as specified via
     // --remap-path-prefix to all FileMaps allocated within this CodeMap.
     path_mapping: FilePathMapping,
-    stable_id_to_filemap: RefCell<FxHashMap<StableFilemapId, Lrc<FileMap>>>,
     /// In case we are in a doctest, replace all file names with the PathBuf,
     /// and add the given offsets to the line info
     doctest_offset: Option<(FileName, isize)>,
@@ -140,10 +143,12 @@ pub struct CodeMap {
 impl CodeMap {
     pub fn new(path_mapping: FilePathMapping) -> CodeMap {
         CodeMap {
-            files: RefCell::new(Vec::new()),
+            files: Lock::new(CodeMapFiles {
+                file_maps: Vec::new(),
+                stable_id_to_filemap: FxHashMap(),
+            }),
             file_loader: Box::new(RealFileLoader),
             path_mapping,
-            stable_id_to_filemap: RefCell::new(FxHashMap()),
             doctest_offset: None,
         }
     }
@@ -157,14 +162,16 @@ pub fn new_doctest(path_mapping: FilePathMapping,
 
     }
 
-    pub fn with_file_loader(file_loader: Box<FileLoader>,
+    pub fn with_file_loader(file_loader: Box<FileLoader + Sync + Send>,
                             path_mapping: FilePathMapping)
                             -> CodeMap {
         CodeMap {
-            files: RefCell::new(Vec::new()),
-            file_loader,
+            files: Lock::new(CodeMapFiles {
+                file_maps: Vec::new(),
+                stable_id_to_filemap: FxHashMap(),
+            }),
+            file_loader: file_loader,
             path_mapping,
-            stable_id_to_filemap: RefCell::new(FxHashMap()),
             doctest_offset: None,
         }
     }
@@ -187,17 +194,16 @@ pub fn load_file(&self, path: &Path) -> io::Result<Lrc<FileMap>> {
         Ok(self.new_filemap(filename, src))
     }
 
-    pub fn files(&self) -> Ref<Vec<Lrc<FileMap>>> {
-        self.files.borrow()
+    pub fn files(&self) -> LockGuard<Vec<Lrc<FileMap>>> {
+        LockGuard::map(self.files.borrow(), |files| &mut files.file_maps)
     }
 
     pub fn filemap_by_stable_id(&self, stable_id: StableFilemapId) -> Option<Lrc<FileMap>> {
-        self.stable_id_to_filemap.borrow().get(&stable_id).map(|fm| fm.clone())
+        self.files.borrow().stable_id_to_filemap.get(&stable_id).map(|fm| fm.clone())
     }
 
     fn next_start_pos(&self) -> usize {
-        let files = self.files.borrow();
-        match files.last() {
+        match self.files.borrow().file_maps.last() {
             None => 0,
             // Add one so there is some space between files. This lets us distinguish
             // positions in the codemap, even in the presence of zero-length files.
@@ -207,9 +213,9 @@ fn next_start_pos(&self) -> usize {
 
     /// Creates a new filemap without setting its line information. If you don't
     /// intend to set the line information yourself, you should use new_filemap_and_lines.
+    /// This does not ensure that only one FileMap exists per file name.
     pub fn new_filemap(&self, filename: FileName, src: String) -> Lrc<FileMap> {
         let start_pos = self.next_start_pos();
-        let mut files = self.files.borrow_mut();
 
         // The path is used to determine the directory for loading submodules and
         // include files, so it must be before remapping.
@@ -233,16 +239,16 @@ pub fn new_filemap(&self, filename: FileName, src: String) -> Lrc<FileMap> {
             Pos::from_usize(start_pos),
         ));
 
-        files.push(filemap.clone());
+        let mut files = self.files.borrow_mut();
 
-        self.stable_id_to_filemap
-            .borrow_mut()
-            .insert(StableFilemapId::new(&filemap), filemap.clone());
+        files.file_maps.push(filemap.clone());
+        files.stable_id_to_filemap.insert(StableFilemapId::new(&filemap), filemap.clone());
 
         filemap
     }
 
     /// Creates a new filemap and sets its line information.
+    /// This does not ensure that only one FileMap exists per file name.
     pub fn new_filemap_and_lines(&self, filename: &Path, src: &str) -> Lrc<FileMap> {
         let fm = self.new_filemap(filename.to_owned().into(), src.to_owned());
         let mut byte_pos: u32 = fm.start_pos.0;
@@ -273,7 +279,6 @@ pub fn new_imported_filemap(&self,
                                 mut file_local_non_narrow_chars: Vec<NonNarrowChar>)
                                 -> Lrc<FileMap> {
         let start_pos = self.next_start_pos();
-        let mut files = self.files.borrow_mut();
 
         let end_pos = Pos::from_usize(start_pos + source_len);
         let start_pos = Pos::from_usize(start_pos);
@@ -297,20 +302,19 @@ pub fn new_imported_filemap(&self,
             crate_of_origin,
             src: None,
             src_hash,
-            external_src: RefCell::new(ExternalSource::AbsentOk),
+            external_src: Lock::new(ExternalSource::AbsentOk),
             start_pos,
             end_pos,
-            lines: RefCell::new(file_local_lines),
-            multibyte_chars: RefCell::new(file_local_multibyte_chars),
-            non_narrow_chars: RefCell::new(file_local_non_narrow_chars),
+            lines: Lock::new(file_local_lines),
+            multibyte_chars: Lock::new(file_local_multibyte_chars),
+            non_narrow_chars: Lock::new(file_local_non_narrow_chars),
             name_hash,
         });
 
-        files.push(filemap.clone());
+        let mut files = self.files.borrow_mut();
 
-        self.stable_id_to_filemap
-            .borrow_mut()
-            .insert(StableFilemapId::new(&filemap), filemap.clone());
+        files.file_maps.push(filemap.clone());
+        files.stable_id_to_filemap.insert(StableFilemapId::new(&filemap), filemap.clone());
 
         filemap
     }
@@ -401,8 +405,7 @@ pub fn lookup_char_pos(&self, pos: BytePos) -> Loc {
     pub fn lookup_line(&self, pos: BytePos) -> Result<FileMapAndLine, Lrc<FileMap>> {
         let idx = self.lookup_filemap_idx(pos);
 
-        let files = self.files.borrow();
-        let f = (*files)[idx].clone();
+        let f = (*self.files.borrow().file_maps)[idx].clone();
 
         match f.lookup_line(pos) {
             Some(line) => Ok(FileMapAndLine { fm: f, line: line }),
@@ -456,7 +459,7 @@ pub fn merge_spans(&self, sp_lhs: Span, sp_rhs: Span) -> Option<Span> {
     }
 
     pub fn span_to_string(&self, sp: Span) -> String {
-        if self.files.borrow().is_empty() && sp.source_equal(&DUMMY_SP) {
+        if self.files.borrow().file_maps.is_empty() && sp.source_equal(&DUMMY_SP) {
             return "no-location".to_string();
         }
 
@@ -594,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 {
@@ -643,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
@@ -670,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 {
@@ -799,7 +806,7 @@ fn find_width_of_character_at_span(&self, sp: Span, forwards: bool) -> u32 {
     }
 
     pub fn get_filemap(&self, filename: &FileName) -> Option<Lrc<FileMap>> {
-        for fm in self.files.borrow().iter() {
+        for fm in self.files.borrow().file_maps.iter() {
             if *filename == fm.name {
                 return Some(fm.clone());
             }
@@ -810,7 +817,7 @@ pub fn get_filemap(&self, filename: &FileName) -> Option<Lrc<FileMap>> {
     /// For a global BytePos compute the local offset within the containing FileMap
     pub fn lookup_byte_offset(&self, bpos: BytePos) -> FileMapAndBytePos {
         let idx = self.lookup_filemap_idx(bpos);
-        let fm = (*self.files.borrow())[idx].clone();
+        let fm = (*self.files.borrow().file_maps)[idx].clone();
         let offset = bpos - fm.start_pos;
         FileMapAndBytePos {fm: fm, pos: offset}
     }
@@ -818,8 +825,7 @@ pub fn lookup_byte_offset(&self, bpos: BytePos) -> FileMapAndBytePos {
     /// Converts an absolute BytePos to a CharPos relative to the filemap.
     pub fn bytepos_to_file_charpos(&self, bpos: BytePos) -> CharPos {
         let idx = self.lookup_filemap_idx(bpos);
-        let files = self.files.borrow();
-        let map = &(*files)[idx];
+        let map = &(*self.files.borrow().file_maps)[idx];
 
         // The number of extra bytes due to multibyte chars in the FileMap
         let mut total_extra_bytes = 0;
@@ -845,7 +851,7 @@ pub fn bytepos_to_file_charpos(&self, bpos: BytePos) -> CharPos {
     // Return the index of the filemap (in self.files) which contains pos.
     pub fn lookup_filemap_idx(&self, pos: BytePos) -> usize {
         let files = self.files.borrow();
-        let files = &*files;
+        let files = &files.file_maps;
         let count = files.len();
 
         // Binary search for the filemap.
index e8c2d325bd653d30d1014955d96d345ccf73cd93..2c91844da96d70ecec36f6b9aa113ec102ad37a5 100644 (file)
@@ -19,7 +19,7 @@
 use ext::build::AstBuilder;
 use parse::token;
 use ptr::P;
-use symbol::Symbol;
+use symbol::{keywords, Symbol};
 use tokenstream::{TokenTree};
 use util::small_vector::SmallVector;
 
@@ -192,7 +192,7 @@ pub fn expand_build_diagnostic_array<'cx>(ecx: &'cx mut ExtCtxt,
             (descriptions.len(), ecx.expr_vec(span, descriptions))
         });
 
-    let static_ = ecx.lifetime(span, Ident::from_str("'static"));
+    let static_ = ecx.lifetime(span, keywords::StaticLifetime.ident());
     let ty_str = ecx.ty_rptr(
         span,
         ecx.ty_ident(span, ecx.ident_of("str")),
@@ -220,7 +220,7 @@ pub fn expand_build_diagnostic_array<'cx>(ecx: &'cx mut ExtCtxt,
                 ty,
                 expr,
             ),
-            vis: codemap::respan(span.empty(), ast::VisibilityKind::Public),
+            vis: codemap::respan(span.shrink_to_lo(), ast::VisibilityKind::Public),
             span,
             tokens: None,
         })
index 7b333270d041c202a584f1ad11fc113cd2c4bd7b..23c42972912a149ec22b563c04189f046bcb74e6 100644 (file)
@@ -555,6 +555,8 @@ pub enum SyntaxExtension {
         /// Whether the contents of the macro can use `unsafe`
         /// without triggering the `unsafe_code` lint.
         allow_internal_unsafe: bool,
+        /// The macro's feature name if it is unstable, and the stability feature
+        unstable_feature: Option<(Symbol, u32)>,
     },
 
     /// A function-like syntax extension that has an extra ident before
@@ -670,6 +672,7 @@ pub struct ExpansionData {
     pub depth: usize,
     pub module: Rc<ModuleData>,
     pub directory_ownership: DirectoryOwnership,
+    pub crate_span: Option<Span>,
 }
 
 /// One of these is made during expansion and incrementally updated as we go;
@@ -701,6 +704,7 @@ pub fn new(parse_sess: &'a parse::ParseSess,
                 depth: 0,
                 module: Rc::new(ModuleData { mod_path: Vec::new(), directory: PathBuf::new() }),
                 directory_ownership: DirectoryOwnership::Owned { relative: None },
+                crate_span: None,
             },
             expansions: HashMap::new(),
         }
index b88e064e7e56dd059c8d54290a9cd005c3a9d6f7..9b53553bf69d723b6d921078f60f4124180e06b3 100644 (file)
@@ -294,7 +294,7 @@ fn item_use(&self, sp: Span,
                 vis: ast::Visibility, vp: P<ast::UseTree>) -> P<ast::Item>;
     fn item_use_simple(&self, sp: Span, vis: ast::Visibility, path: ast::Path) -> P<ast::Item>;
     fn item_use_simple_(&self, sp: Span, vis: ast::Visibility,
-                        ident: ast::Ident, path: ast::Path) -> P<ast::Item>;
+                        ident: Option<ast::Ident>, path: ast::Path) -> P<ast::Item>;
     fn item_use_list(&self, sp: Span, vis: ast::Visibility,
                      path: Vec<ast::Ident>, imports: &[ast::Ident]) -> P<ast::Item>;
     fn item_use_glob(&self, sp: Span,
@@ -329,9 +329,13 @@ fn path_all(&self,
             None
         };
         segments.push(ast::PathSegment { identifier: last_identifier, span, parameters });
-        let path = ast::Path { span, segments };
-
-        if global { path.default_to_global() } else { path }
+        let mut path = ast::Path { span, segments };
+        if global {
+            if let Some(seg) = path.make_root() {
+                path.segments.insert(0, seg);
+            }
+        }
+        path
     }
 
     /// Constructs a qualified path.
@@ -983,7 +987,7 @@ fn item(&self, span: Span, name: Ident,
             attrs,
             id: ast::DUMMY_NODE_ID,
             node,
-            vis: respan(span.empty(), ast::VisibilityKind::Inherited),
+            vis: respan(span.shrink_to_lo(), ast::VisibilityKind::Inherited),
             span,
             tokens: None,
         })
@@ -1029,7 +1033,7 @@ fn variant(&self, span: Span, name: Ident, tys: Vec<P<ast::Ty>> ) -> ast::Varian
                 span: ty.span,
                 ty,
                 ident: None,
-                vis: respan(span.empty(), ast::VisibilityKind::Inherited),
+                vis: respan(span.shrink_to_lo(), ast::VisibilityKind::Inherited),
                 attrs: Vec::new(),
                 id: ast::DUMMY_NODE_ID,
             }
@@ -1159,16 +1163,15 @@ fn item_use(&self, sp: Span,
     }
 
     fn item_use_simple(&self, sp: Span, vis: ast::Visibility, path: ast::Path) -> P<ast::Item> {
-        let last = path.segments.last().unwrap().identifier;
-        self.item_use_simple_(sp, vis, last, path)
+        self.item_use_simple_(sp, vis, None, path)
     }
 
     fn item_use_simple_(&self, sp: Span, vis: ast::Visibility,
-                        ident: ast::Ident, path: ast::Path) -> P<ast::Item> {
+                        rename: Option<ast::Ident>, path: ast::Path) -> P<ast::Item> {
         self.item_use(sp, vis, P(ast::UseTree {
             span: sp,
             prefix: path,
-            kind: ast::UseTreeKind::Simple(ident),
+            kind: ast::UseTreeKind::Simple(rename),
         }))
     }
 
@@ -1178,7 +1181,7 @@ fn item_use_list(&self, sp: Span, vis: ast::Visibility,
             (ast::UseTree {
                 span: sp,
                 prefix: self.path(sp, vec![*id]),
-                kind: ast::UseTreeKind::Simple(*id),
+                kind: ast::UseTreeKind::Simple(None),
             }, ast::DUMMY_NODE_ID)
         }).collect();
 
index 3e75afcee1cf30d4b51c19392d44bed6c99dfad2..34dd7696168a6d431ba160010d3ff3b17d00f2d1 100644 (file)
@@ -18,7 +18,7 @@
 use ext::derive::{add_derived_markers, collect_derives};
 use ext::hygiene::{Mark, SyntaxContext};
 use ext::placeholders::{placeholder, PlaceholderExpander};
-use feature_gate::{self, Features, is_builtin_attr};
+use feature_gate::{self, Features, GateIssue, is_builtin_attr, emit_feature_err};
 use fold;
 use fold::*;
 use parse::{DirectoryOwnership, PResult};
@@ -229,6 +229,7 @@ pub fn expand_crate(&mut self, mut krate: ast::Crate) -> ast::Crate {
         module.directory.pop();
         self.cx.root_path = module.directory.clone();
         self.cx.current_expansion.module = Rc::new(module);
+        self.cx.current_expansion.crate_span = Some(krate.span);
 
         let orig_mod_span = krate.module.inner;
 
@@ -238,7 +239,7 @@ pub fn expand_crate(&mut self, mut krate: ast::Crate) -> ast::Crate {
             node: ast::ItemKind::Mod(krate.module),
             ident: keywords::Invalid.ident(),
             id: ast::DUMMY_NODE_ID,
-            vis: respan(krate.span.empty(), ast::VisibilityKind::Public),
+            vis: respan(krate.span.shrink_to_lo(), ast::VisibilityKind::Public),
             tokens: None,
         })));
 
@@ -533,11 +534,36 @@ fn expand_bang_invoc(&mut self,
         let path = &mac.node.path;
 
         let ident = ident.unwrap_or_else(|| keywords::Invalid.ident());
-        let validate_and_set_expn_info = |def_site_span,
+        let validate_and_set_expn_info = |this: &mut Self, // arg instead of capture
+                                          def_site_span: Option<Span>,
                                           allow_internal_unstable,
-                                          allow_internal_unsafe| {
+                                          allow_internal_unsafe,
+                                          // can't infer this type
+                                          unstable_feature: Option<(Symbol, u32)>| {
+
+            // feature-gate the macro invocation
+            if let Some((feature, issue)) = unstable_feature {
+                let crate_span = this.cx.current_expansion.crate_span.unwrap();
+                // don't stability-check macros in the same crate
+                // (the only time this is null is for syntax extensions registered as macros)
+                if def_site_span.map_or(false, |def_span| !crate_span.contains(def_span))
+                    && !span.allows_unstable() && this.cx.ecfg.features.map_or(true, |feats| {
+                    // macro features will count as lib features
+                    !feats.declared_lib_features.iter().any(|&(feat, _)| feat == feature)
+                }) {
+                    let explain = format!("macro {}! is unstable", path);
+                    emit_feature_err(this.cx.parse_sess, &*feature.as_str(), span,
+                                     GateIssue::Library(Some(issue)), &explain);
+                    this.cx.trace_macros_diag();
+                    return Err(kind.dummy(span));
+                }
+            }
+
             if ident.name != keywords::Invalid.name() {
-                return Err(format!("macro {}! expects no ident argument, given '{}'", path, ident));
+                let msg = format!("macro {}! expects no ident argument, given '{}'", path, ident);
+                this.cx.span_err(path.span, &msg);
+                this.cx.trace_macros_diag();
+                return Err(kind.dummy(span));
             }
             mark.set_expn_info(ExpnInfo {
                 call_site: span,
@@ -553,11 +579,9 @@ fn expand_bang_invoc(&mut self,
 
         let opt_expanded = match *ext {
             DeclMacro(ref expand, def_span) => {
-                if let Err(msg) = validate_and_set_expn_info(def_span.map(|(_, s)| s),
-                                                             false, false) {
-                    self.cx.span_err(path.span, &msg);
-                    self.cx.trace_macros_diag();
-                    kind.dummy(span)
+                if let Err(dummy_span) = validate_and_set_expn_info(self, def_span.map(|(_, s)| s),
+                                                                    false, false, None) {
+                    dummy_span
                 } else {
                     kind.make_from(expand.expand(self.cx, span, mac.node.stream()))
                 }
@@ -567,14 +591,14 @@ fn expand_bang_invoc(&mut self,
                 ref expander,
                 def_info,
                 allow_internal_unstable,
-                allow_internal_unsafe
+                allow_internal_unsafe,
+                unstable_feature,
             } => {
-                if let Err(msg) = validate_and_set_expn_info(def_info.map(|(_, s)| s),
-                                                             allow_internal_unstable,
-                                                             allow_internal_unsafe) {
-                    self.cx.span_err(path.span, &msg);
-                    self.cx.trace_macros_diag();
-                    kind.dummy(span)
+                if let Err(dummy_span) = validate_and_set_expn_info(self, def_info.map(|(_, s)| s),
+                                                                    allow_internal_unstable,
+                                                                    allow_internal_unsafe,
+                                                                    unstable_feature) {
+                    dummy_span
                 } else {
                     kind.make_from(expander.expand(self.cx, span, mac.node.stream()))
                 }
index 7a024dbad88300e0fe451f6503c6b280c5e7c686..6844532e7b375ece36530f74a3d9c56dfb85e9ef 100644 (file)
@@ -709,7 +709,6 @@ macro_rules! mk_lit {
         token::Pound        => "Pound",
         token::Dollar       => "Dollar",
         token::Question     => "Question",
-        token::Underscore   => "Underscore",
         token::Eof          => "Eof",
 
         token::Whitespace | token::Comment | token::Shebang(_) => {
@@ -858,7 +857,7 @@ fn expand_wrapper(cx: &ExtCtxt,
         let path = path.iter().map(|s| s.to_string()).collect();
         let use_item = cx.item_use_glob(
             sp,
-            respan(sp.empty(), ast::VisibilityKind::Inherited),
+            respan(sp.shrink_to_lo(), ast::VisibilityKind::Inherited),
             ids_ext(path),
         );
         cx.stmt_item(sp, use_item)
index 0621f728e2a9d0fa6a33988977c9e618c9a63959..667653b5f7f26686f62a9f245ee65a053b86bd52 100644 (file)
@@ -86,7 +86,7 @@
 
 use ast::Ident;
 use syntax_pos::{self, BytePos, Span};
-use codemap::Spanned;
+use codemap::respan;
 use errors::FatalError;
 use ext::tt::quoted::{self, TokenTree};
 use parse::{Directory, ParseSess};
@@ -709,6 +709,15 @@ pub fn parse(
     }
 }
 
+/// The token is an identifier, but not `_`.
+/// We prohibit passing `_` to macros expecting `ident` for now.
+fn get_macro_ident(token: &Token) -> Option<Ident> {
+    match *token {
+        token::Ident(ident) if ident.name != keywords::Underscore.name() => Some(ident),
+        _ => None,
+    }
+}
+
 /// Checks whether a non-terminal may begin with a particular token.
 ///
 /// Returning `false` is a *stability guarantee* that such a matcher will *never* begin with that
@@ -725,7 +734,7 @@ fn may_be_ident(nt: &token::Nonterminal) -> bool {
     match name {
         "expr" => token.can_begin_expr(),
         "ty" => token.can_begin_type(),
-        "ident" => token.is_ident(),
+        "ident" => get_macro_ident(token).is_some(),
         "vis" => match *token {
             // The follow-set of :vis + "priv" keyword + interpolated
             Token::Comma | Token::Ident(_) | Token::Interpolated(_) => true,
@@ -765,8 +774,7 @@ fn may_be_ident(nt: &token::Nonterminal) -> bool {
             Token::DotDotDot |                  // range pattern (future compat)
             Token::ModSep |                     // path
             Token::Lt |                         // path (UFCS constant)
-            Token::BinOp(token::Shl) |          // path (double UFCS)
-            Token::Underscore => true,          // placeholder
+            Token::BinOp(token::Shl) => true,   // path (double UFCS)
             Token::Interpolated(ref nt) => may_be_ident(&nt.0),
             _ => false,
         },
@@ -815,21 +823,14 @@ fn parse_nt<'a>(p: &mut Parser<'a>, sp: Span, name: &str) -> Nonterminal {
         "expr" => token::NtExpr(panictry!(p.parse_expr())),
         "ty" => token::NtTy(panictry!(p.parse_ty())),
         // this could be handled like a token, since it is one
-        "ident" => match p.token {
-            token::Ident(sn) => {
-                p.bump();
-                token::NtIdent(Spanned::<Ident> {
-                    node: sn,
-                    span: p.prev_span,
-                })
-            }
-            _ => {
-                let token_str = pprust::token_to_string(&p.token);
-                p.fatal(&format!("expected ident, found {}", &token_str[..]))
-                    .emit();
-                FatalError.raise()
-            }
-        },
+        "ident" => if let Some(ident) = get_macro_ident(&p.token) {
+            p.bump();
+            token::NtIdent(respan(p.prev_span, ident))
+        } else {
+            let token_str = pprust::token_to_string(&p.token);
+            p.fatal(&format!("expected ident, found {}", &token_str)).emit();
+            FatalError.raise()
+        }
         "path" => token::NtPath(panictry!(p.parse_path_common(PathStyle::Type, false))),
         "meta" => token::NtMeta(panictry!(p.parse_meta_item())),
         "vis" => token::NtVis(panictry!(p.parse_visibility(true))),
index 9162a582599fc6dc79f1b1b9ed6161c47fd6479b..a4b2c3990f5e1bbe9414f34915dc715f59c1d271 100644 (file)
@@ -283,11 +283,22 @@ pub fn compile(sess: &ParseSess, features: &Features, def: &ast::Item) -> Syntax
     if body.legacy {
         let allow_internal_unstable = attr::contains_name(&def.attrs, "allow_internal_unstable");
         let allow_internal_unsafe = attr::contains_name(&def.attrs, "allow_internal_unsafe");
+
+        let unstable_feature = attr::find_stability(&sess.span_diagnostic,
+                                                    &def.attrs, def.span).and_then(|stability| {
+            if let attr::StabilityLevel::Unstable { issue, .. } = stability.level {
+                Some((stability.feature, issue))
+            } else {
+                None
+            }
+        });
+
         NormalTT {
             expander,
             def_info: Some((def.id, def.span)),
             allow_internal_unstable,
-            allow_internal_unsafe
+            allow_internal_unsafe,
+            unstable_feature
         }
     } else {
         SyntaxExtension::DeclMacro(expander, Some((def.id, def.span)))
index f42cb8a258314a4d28d8226c4c1252fbb3110f6f..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! (
@@ -832,6 +833,13 @@ pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
                                                           across crates and will never be stable",
                                                           cfg_fn!(rustc_attrs))),
 
+    ("rustc_dump_program_clauses", Whitelisted, Gated(Stability::Unstable,
+                                                     "rustc_attrs",
+                                                     "the `#[rustc_dump_program_clauses]` \
+                                                      attribute is just used for rustc unit \
+                                                      tests and will never be stable",
+                                                     cfg_fn!(rustc_attrs))),
+
     // RFC #2094
     ("nll", Whitelisted, Gated(Stability::Unstable,
                                "nll",
@@ -1438,7 +1446,7 @@ fn visit_name(&mut self, sp: Span, name: ast::Name) {
     }
 
     fn visit_use_tree(&mut self, use_tree: &'a ast::UseTree, id: NodeId, _nested: bool) {
-        if let ast::UseTreeKind::Simple(ident) = use_tree.kind {
+        if let ast::UseTreeKind::Simple(Some(ident)) = use_tree.kind {
             if ident.name == "_" {
                 gate_feature_post!(&self, underscore_imports, use_tree.span,
                                    "renaming imports with `_` is unstable");
@@ -1648,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,
@@ -1790,7 +1791,7 @@ fn visit_generic_param(&mut self, param: &'a ast::GenericParam) {
     }
 
     fn visit_lifetime(&mut self, lt: &'a ast::Lifetime) {
-        if lt.ident.name == "'_" {
+        if lt.ident.name == keywords::UnderscoreLifetime.name() {
             gate_feature_post!(&self, underscore_lifetimes, lt.span,
                                "underscore lifetimes are unstable");
         }
index 2cf99e15d1f9b987d4975495a8b87704a93cbc7c..46e6027b094bc2d7a8e94713e1df71ef3081d59b 100644 (file)
@@ -323,7 +323,8 @@ pub fn noop_fold_use_tree<T: Folder>(use_tree: UseTree, fld: &mut T) -> UseTree
         span: fld.new_span(use_tree.span),
         prefix: fld.fold_path(use_tree.prefix),
         kind: match use_tree.kind {
-            UseTreeKind::Simple(ident) => UseTreeKind::Simple(fld.fold_ident(ident)),
+            UseTreeKind::Simple(rename) =>
+                UseTreeKind::Simple(rename.map(|ident| fld.fold_ident(ident))),
             UseTreeKind::Glob => UseTreeKind::Glob,
             UseTreeKind::Nested(items) => UseTreeKind::Nested(items.move_map(|(tree, id)| {
                 (fld.fold_use_tree(tree), fld.new_id(id))
@@ -886,7 +887,7 @@ pub fn noop_fold_block<T: Folder>(b: P<Block>, folder: &mut T) -> P<Block> {
 
 pub fn noop_fold_item_kind<T: Folder>(i: ItemKind, folder: &mut T) -> ItemKind {
     match i {
-        ItemKind::ExternCrate(string) => ItemKind::ExternCrate(string),
+        ItemKind::ExternCrate(orig_name) => ItemKind::ExternCrate(orig_name),
         ItemKind::Use(use_tree) => {
             ItemKind::Use(use_tree.map(|tree| folder.fold_use_tree(tree)))
         }
@@ -1018,7 +1019,7 @@ pub fn noop_fold_crate<T: Folder>(Crate {module, attrs, span}: Crate,
         ident: keywords::Invalid.ident(),
         attrs,
         id: ast::DUMMY_NODE_ID,
-        vis: respan(span.empty(), ast::VisibilityKind::Public),
+        vis: respan(span.shrink_to_lo(), ast::VisibilityKind::Public),
         span,
         node: ast::ItemKind::Mod(module),
         tokens: None,
index eed3c6914054d20c473fa7f7a95af4ca1aea6de5..b4f34fb12e36a1c846af690e37114823a7729f0a 100644 (file)
@@ -26,7 +26,7 @@
 use errors::DiagnosticId;
 use errors::emitter::{Emitter, EmitterWriter};
 
-use rustc_data_structures::sync::Lrc;
+use rustc_data_structures::sync::{self, Lrc};
 use std::io::{self, Write};
 use std::vec;
 use std::sync::{Arc, Mutex};
@@ -36,7 +36,7 @@
 pub struct JsonEmitter {
     dst: Box<Write + Send>,
     registry: Option<Registry>,
-    cm: Lrc<CodeMapper + 'static>,
+    cm: Lrc<CodeMapper + sync::Send + sync::Sync>,
     pretty: bool,
     /// Whether "approximate suggestions" are enabled in the config
     approximate_suggestions: bool,
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 d0075c896567bc4ac48684cfc93d1908c0bb0b41..0e20eb49d395ed213211ff0a02ce52be7ee3e748 100644 (file)
@@ -34,7 +34,7 @@ pub struct TokenAndSpan {
 
 impl Default for TokenAndSpan {
     fn default() -> Self {
-        TokenAndSpan { tok: token::Underscore, sp: syntax_pos::DUMMY_SP }
+        TokenAndSpan { tok: token::Whitespace, sp: syntax_pos::DUMMY_SP }
     }
 }
 
@@ -126,7 +126,7 @@ fn is_eof(&self) -> bool {
     pub fn try_next_token(&mut self) -> Result<TokenAndSpan, ()> {
         assert!(self.fatal_errs.is_empty());
         let ret_val = TokenAndSpan {
-            tok: replace(&mut self.peek_tok, token::Underscore),
+            tok: replace(&mut self.peek_tok, token::Whitespace),
             sp: self.peek_span,
         };
         self.advance_token()?;
@@ -214,7 +214,7 @@ pub fn retokenize(sess: &'a ParseSess, mut span: Span) -> Self {
 
         // Make the range zero-length if the span is invalid.
         if span.lo() > span.hi() || begin.fm.start_pos != end.fm.start_pos {
-            span = span.with_hi(span.lo());
+            span = span.shrink_to_lo();
         }
 
         let mut sr = StringReader::new_raw_internal(sess, begin.fm);
@@ -611,7 +611,7 @@ fn scan_comment(&mut self) -> Option<TokenAndSpan> {
                 // I guess this is the only way to figure out if
                 // we're at the beginning of the file...
                 let cmap = CodeMap::new(FilePathMapping::empty());
-                cmap.files.borrow_mut().push(self.filemap.clone());
+                cmap.files.borrow_mut().file_maps.push(self.filemap.clone());
                 let loc = cmap.lookup_char_pos_adj(self.pos);
                 debug!("Skipping a shebang");
                 if loc.line == 1 && loc.col == CharPos(0) {
@@ -1133,14 +1133,8 @@ fn next_token_inner(&mut self) -> Result<token::Token, ()> {
                 self.bump();
             }
 
-            return Ok(self.with_str_from(start, |string| {
-                if string == "_" {
-                    token::Underscore
-                } else {
-                    // FIXME: perform NFKC normalization here. (Issue #2253)
-                    token::Ident(self.mk_ident(string))
-                }
-            }));
+            // FIXME: perform NFKC normalization here. (Issue #2253)
+            return Ok(self.with_str_from(start, |string| token::Ident(self.mk_ident(string))));
         }
 
         if is_dec_digit(c) {
index ff097c362fe6101761a1034f2dd9db4df8837777..f7e5d40b52468821e79a28e324a01cdd866fdb1f 100644 (file)
@@ -713,7 +713,7 @@ fn str2seg(s: &str, lo: u32, hi: u32) -> ast::PathSegment {
                         id: ast::DUMMY_NODE_ID,
                         node: ast::ExprKind::Path(None, ast::Path {
                             span: sp(0, 6),
-                            segments: vec![ast::PathSegment::crate_root(sp(0, 2)),
+                            segments: vec![ast::PathSegment::crate_root(sp(0, 0)),
                                         str2seg("a", 2, 3),
                                         str2seg("b", 5, 6)]
                         }),
index a3a6489fe8b148265c092bd3bb4ac9a05ca7ff5c..6d8975197d55cba73ee654ddbedea6ee9d91423e 100644 (file)
@@ -549,7 +549,7 @@ pub fn new(sess: &'a ParseSess,
                -> Self {
         let mut parser = Parser {
             sess,
-            token: token::Underscore,
+            token: token::Whitespace,
             span: syntax_pos::DUMMY_SP,
             prev_span: syntax_pos::DUMMY_SP,
             meta_var_span: None,
@@ -800,11 +800,7 @@ fn parse_ident_common(&mut self, recover: bool) -> PResult<'a, ast::Ident> {
                 Err(if self.prev_token_kind == PrevTokenKind::DocComment {
                         self.span_fatal_err(self.prev_span, Error::UselessDocComment)
                     } else {
-                        let mut err = self.expected_ident_found();
-                        if self.token == token::Underscore {
-                            err.note("`_` is a wildcard pattern, not an identifier");
-                        }
-                        err
+                        self.expected_ident_found()
                     })
             }
         }
@@ -1512,7 +1508,7 @@ fn parse_ret_ty(&mut self, allow_plus: bool) -> PResult<'a, FunctionRetTy> {
         if self.eat(&token::RArrow) {
             Ok(FunctionRetTy::Ty(self.parse_ty_common(allow_plus, true)?))
         } else {
-            Ok(FunctionRetTy::Default(self.span.with_hi(self.span.lo())))
+            Ok(FunctionRetTy::Default(self.span.shrink_to_lo()))
         }
     }
 
@@ -1602,7 +1598,7 @@ fn parse_ty_common(&mut self, allow_plus: bool, allow_qpath_recovery: bool)
             let e = self.parse_expr()?;
             self.expect(&token::CloseDelim(token::Paren))?;
             TyKind::Typeof(e)
-        } else if self.eat(&token::Underscore) {
+        } else if self.eat_keyword(keywords::Underscore) {
             // A type to be inferred `_`
             TyKind::Infer
         } else if self.token_is_bare_fn_keyword() {
@@ -1796,7 +1792,7 @@ fn is_named_argument(&mut self) -> bool {
             _ => 0,
         };
 
-        self.look_ahead(offset, |t| t.is_ident() || t == &token::Underscore) &&
+        self.look_ahead(offset, |t| t.is_ident()) &&
         self.look_ahead(offset + 1, |t| t == &token::Colon)
     }
 
@@ -1990,7 +1986,7 @@ pub fn parse_path_common(&mut self, style: PathStyle, enable_warning: bool)
         let lo = self.meta_var_span.unwrap_or(self.span);
         let mut segments = Vec::new();
         if self.eat(&token::ModSep) {
-            segments.push(PathSegment::crate_root(lo));
+            segments.push(PathSegment::crate_root(lo.shrink_to_lo()));
         }
         self.parse_path_segments(&mut segments, style, enable_warning)?;
 
@@ -2025,7 +2021,7 @@ fn parse_path_segments(&mut self,
         loop {
             segments.push(self.parse_path_segment(style, enable_warning)?);
 
-            if self.is_import_coupler(false) || !self.eat(&token::ModSep) {
+            if self.is_import_coupler() || !self.eat(&token::ModSep) {
                 return Ok(());
             }
         }
@@ -2782,7 +2778,7 @@ pub fn parse_token_tree(&mut self) -> TokenTree {
             },
             token::CloseDelim(_) | token::Eof => unreachable!(),
             _ => {
-                let (token, span) = (mem::replace(&mut self.token, token::Underscore), self.span);
+                let (token, span) = (mem::replace(&mut self.token, token::Whitespace), self.span);
                 self.bump();
                 TokenTree::Token(span, token)
             }
@@ -3622,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;
                     }
@@ -3815,11 +3811,6 @@ fn parse_pat_with_range_pat(&mut self, allow_range_pat: bool) -> PResult<'a, P<P
         let lo = self.span;
         let pat;
         match self.token {
-            token::Underscore => {
-                // Parse _
-                self.bump();
-                pat = PatKind::Wild;
-            }
             token::BinOp(token::And) | token::AndAnd => {
                 // Parse &pat / &mut pat
                 self.expect_and()?;
@@ -3849,8 +3840,11 @@ fn parse_pat_with_range_pat(&mut self, allow_range_pat: bool) -> PResult<'a, P<P
                 self.expect(&token::CloseDelim(token::Bracket))?;
                 pat = PatKind::Slice(before, slice, after);
             }
-            // At this point, token != _, &, &&, (, [
-            _ => if self.eat_keyword(keywords::Mut) {
+            // At this point, token != &, &&, (, [
+            _ => if self.eat_keyword(keywords::Underscore) {
+                // Parse _
+                pat = PatKind::Wild;
+            } else if self.eat_keyword(keywords::Mut) {
                 // Parse mut ident @ pat / mut ref ident @ pat
                 let mutref_span = self.prev_span.to(self.span);
                 let binding_mode = if self.eat_keyword(keywords::Ref) {
@@ -5869,7 +5863,7 @@ pub fn parse_visibility(&mut self, can_take_tuple: bool) -> PResult<'a, Visibili
                 // `pub(in path)`
                 self.bump(); // `(`
                 self.bump(); // `in`
-                let path = self.parse_path(PathStyle::Mod)?.default_to_global(); // `path`
+                let path = self.parse_path(PathStyle::Mod)?; // `path`
                 self.expect(&token::CloseDelim(token::Paren))?; // `)`
                 let vis = respan(lo.to(self.prev_span), VisibilityKind::Restricted {
                     path: P(path),
@@ -5882,7 +5876,7 @@ pub fn parse_visibility(&mut self, can_take_tuple: bool) -> PResult<'a, Visibili
             {
                 // `pub(self)` or `pub(super)`
                 self.bump(); // `(`
-                let path = self.parse_path(PathStyle::Mod)?.default_to_global(); // `super`/`self`
+                let path = self.parse_path(PathStyle::Mod)?; // `super`/`self`
                 self.expect(&token::CloseDelim(token::Paren))?; // `)`
                 let vis = respan(lo.to(self.prev_span), VisibilityKind::Restricted {
                     path: P(path),
@@ -6291,23 +6285,17 @@ fn parse_item_extern_crate(&mut self,
                                lo: Span,
                                visibility: Visibility,
                                attrs: Vec<Attribute>)
-                                -> PResult<'a, P<Item>> {
-
-        let crate_name = self.parse_ident()?;
-        let (maybe_path, ident) = if let Some(ident) = self.parse_rename()? {
-            (Some(crate_name.name), ident)
+                               -> PResult<'a, P<Item>> {
+        let orig_name = self.parse_ident()?;
+        let (item_name, orig_name) = if let Some(rename) = self.parse_rename()? {
+            (rename, Some(orig_name.name))
         } else {
-            (None, crate_name)
+            (orig_name, None)
         };
         self.expect(&token::Semi)?;
 
-        let prev_span = self.prev_span;
-
-        Ok(self.mk_item(lo.to(prev_span),
-                        ident,
-                        ItemKind::ExternCrate(maybe_path),
-                        visibility,
-                        attrs))
+        let span = lo.to(self.prev_span);
+        Ok(self.mk_item(span, item_name, ItemKind::ExternCrate(orig_name), visibility, attrs))
     }
 
     /// Parse `extern` for foreign ABIs
@@ -6486,12 +6474,11 @@ fn parse_item_(&mut self, attrs: Vec<Attribute>,
 
         if self.eat_keyword(keywords::Use) {
             // USE ITEM
-            let item_ = ItemKind::Use(P(self.parse_use_tree(false)?));
+            let item_ = ItemKind::Use(P(self.parse_use_tree()?));
             self.expect(&token::Semi)?;
 
-            let prev_span = self.prev_span;
-            let invalid = keywords::Invalid.ident();
-            let item = self.mk_item(lo.to(prev_span), invalid, item_, visibility, attrs);
+            let span = lo.to(self.prev_span);
+            let item = self.mk_item(span, keywords::Invalid.ident(), item_, visibility, attrs);
             return Ok(Some(item));
         }
 
@@ -6966,90 +6953,53 @@ pub fn parse_item(&mut self) -> PResult<'a, Option<P<Item>>> {
         }))
     }
 
-    /// `{` or `::{` or `*` or `::*`
-    /// `::{` or `::*` (also `{`  or `*` if unprefixed is true)
-    fn is_import_coupler(&mut self, unprefixed: bool) -> bool {
-        self.is_import_coupler_inner(&token::OpenDelim(token::Brace), unprefixed) ||
-            self.is_import_coupler_inner(&token::BinOp(token::Star), unprefixed)
-    }
-
-    fn is_import_coupler_inner(&mut self, token: &token::Token, unprefixed: bool) -> bool {
-        if self.check(&token::ModSep) {
-            self.look_ahead(1, |t| t == token)
-        } else if unprefixed {
-            self.check(token)
-        } else {
-            false
-        }
+    /// `::{` or `::*`
+    fn is_import_coupler(&mut self) -> bool {
+        self.check(&token::ModSep) &&
+            self.look_ahead(1, |t| *t == token::OpenDelim(token::Brace) ||
+                                   *t == token::BinOp(token::Star))
     }
 
     /// Parse UseTree
     ///
-    /// USE_TREE = `*` |
-    ///            `{` USE_TREE_LIST `}` |
+    /// USE_TREE = [`::`] `*` |
+    ///            [`::`] `{` USE_TREE_LIST `}` |
     ///            PATH `::` `*` |
     ///            PATH `::` `{` USE_TREE_LIST `}` |
     ///            PATH [`as` IDENT]
-    fn parse_use_tree(&mut self, nested: bool) -> PResult<'a, UseTree> {
+    fn parse_use_tree(&mut self) -> PResult<'a, UseTree> {
         let lo = self.span;
 
-        let mut prefix = ast::Path {
-            segments: vec![],
-            span: lo.to(self.span),
-        };
-
-        let kind = if self.is_import_coupler(true) {
-            // `use *;` or `use ::*;` or `use {...};` `use ::{...};`
-
-            // Remove the first `::`
+        let mut prefix = ast::Path { segments: Vec::new(), span: lo.shrink_to_lo() };
+        let kind = if self.check(&token::OpenDelim(token::Brace)) ||
+                      self.check(&token::BinOp(token::Star)) ||
+                      self.is_import_coupler() {
+            // `use *;` or `use ::*;` or `use {...};` or `use ::{...};`
             if self.eat(&token::ModSep) {
-                prefix.segments.push(PathSegment::crate_root(self.prev_span));
-            } else if !nested {
-                prefix.segments.push(PathSegment::crate_root(self.span));
+                prefix.segments.push(PathSegment::crate_root(lo.shrink_to_lo()));
             }
 
             if self.eat(&token::BinOp(token::Star)) {
-                // `use *;`
                 UseTreeKind::Glob
-            } else if self.check(&token::OpenDelim(token::Brace)) {
-                // `use {...};`
-                UseTreeKind::Nested(self.parse_use_tree_list()?)
             } else {
-                return self.unexpected();
+                UseTreeKind::Nested(self.parse_use_tree_list()?)
             }
         } else {
-            // `use path::...;`
-            let mut parsed = self.parse_path(PathStyle::Mod)?;
-            if !nested {
-                parsed = parsed.default_to_global();
-            }
-
-            prefix.segments.append(&mut parsed.segments);
-            prefix.span = prefix.span.to(parsed.span);
+            // `use path::*;` or `use path::{...};` or `use path;` or `use path as bar;`
+            prefix = self.parse_path(PathStyle::Mod)?;
 
             if self.eat(&token::ModSep) {
                 if self.eat(&token::BinOp(token::Star)) {
-                    // `use path::*;`
                     UseTreeKind::Glob
-                } else if self.check(&token::OpenDelim(token::Brace)) {
-                    // `use path::{...};`
-                    UseTreeKind::Nested(self.parse_use_tree_list()?)
                 } else {
-                    return self.unexpected();
+                    UseTreeKind::Nested(self.parse_use_tree_list()?)
                 }
             } else {
-                // `use path::foo;` or `use path::foo as bar;`
-                let rename = self.parse_rename()?.
-                                  unwrap_or(prefix.segments.last().unwrap().identifier);
-                UseTreeKind::Simple(rename)
+                UseTreeKind::Simple(self.parse_rename()?)
             }
         };
 
-        Ok(UseTree {
-            span: lo.to(self.prev_span),
-            kind,
-            prefix,
-        })
+        Ok(UseTree { prefix, kind, span: lo.to(self.prev_span) })
     }
 
     /// Parse UseTreeKind::Nested(list)
@@ -7059,16 +7009,18 @@ fn parse_use_tree_list(&mut self) -> PResult<'a, Vec<(UseTree, ast::NodeId)>> {
         self.parse_unspanned_seq(&token::OpenDelim(token::Brace),
                                  &token::CloseDelim(token::Brace),
                                  SeqSep::trailing_allowed(token::Comma), |this| {
-            Ok((this.parse_use_tree(true)?, ast::DUMMY_NODE_ID))
+            Ok((this.parse_use_tree()?, ast::DUMMY_NODE_ID))
         })
     }
 
     fn parse_rename(&mut self) -> PResult<'a, Option<Ident>> {
         if self.eat_keyword(keywords::As) {
-            if self.eat(&token::Underscore) {
-                Ok(Some(Ident::with_empty_ctxt(Symbol::gensym("_"))))
-            } else {
-                self.parse_ident().map(Some)
+            match self.token {
+                token::Ident(ident) if ident.name == keywords::Underscore.name() => {
+                    self.bump(); // `_`
+                    Ok(Some(Ident { name: ident.name.gensymed(), ..ident }))
+                }
+                _ => self.parse_ident().map(Some),
             }
         } else {
             Ok(None)
index 097a2eb89fdf4d7d8eca68764e9e1977fceb28dc..4ada9e20f2cc0db63af93a20cf04bdf6be3e9856 100644 (file)
@@ -122,6 +122,7 @@ fn ident_can_begin_type(ident: ast::Ident) -> bool {
     !ident_token.is_reserved_ident() ||
     ident_token.is_path_segment_keyword() ||
     [
+        keywords::Underscore.name(),
         keywords::For.name(),
         keywords::Impl.name(),
         keywords::Fn.name(),
@@ -175,7 +176,6 @@ pub enum Token {
 
     /* Name components */
     Ident(ast::Ident),
-    Underscore,
     Lifetime(ast::Ident),
 
     // The `LazyTokenStream` is a pure function of the `Nonterminal`,
@@ -242,7 +242,6 @@ pub fn can_begin_type(&self) -> bool {
             Ident(ident)                => ident_can_begin_type(ident), // type name or keyword
             OpenDelim(Paren)            | // tuple
             OpenDelim(Bracket)          | // array
-            Underscore                  | // placeholder
             Not                         | // never
             BinOp(Star)                 | // raw pointer
             BinOp(And)                  | // reference
@@ -362,6 +361,7 @@ pub fn is_path_segment_keyword(&self) -> bool {
                         id.name == keywords::SelfType.name() ||
                         id.name == keywords::Extern.name() ||
                         id.name == keywords::Crate.name() ||
+                        id.name == keywords::CrateRoot.name() ||
                         id.name == keywords::DollarCrate.name(),
             None => false,
         }
@@ -371,7 +371,7 @@ pub fn is_path_segment_keyword(&self) -> bool {
     // unnamed method parameters, crate root module, error recovery etc.
     pub fn is_special_ident(&self) -> bool {
         match self.ident() {
-            Some(id) => id.name <= keywords::DollarCrate.name(),
+            Some(id) => id.name <= keywords::Underscore.name(),
             _ => false,
         }
     }
@@ -441,7 +441,7 @@ pub fn glue(self, joint: Token) -> Option<Token> {
 
             Le | EqEq | Ne | Ge | AndAnd | OrOr | Tilde | BinOpEq(..) | At | DotDotDot | DotEq |
             DotDotEq | Comma | Semi | ModSep | RArrow | LArrow | FatArrow | Pound | Dollar |
-            Question | OpenDelim(..) | CloseDelim(..) | Underscore => return None,
+            Question | OpenDelim(..) | CloseDelim(..) => return None,
 
             Literal(..) | Ident(..) | Lifetime(..) | Interpolated(..) | DocComment(..) |
             Whitespace | Comment | Shebang(..) | Eof => return None,
@@ -573,7 +573,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 pub fn is_op(tok: &Token) -> bool {
     match *tok {
         OpenDelim(..) | CloseDelim(..) | Literal(..) | DocComment(..) |
-        Ident(..) | Underscore | Lifetime(..) | Interpolated(..) |
+        Ident(..) | Lifetime(..) | Interpolated(..) |
         Whitespace | Comment | Shebang(..) | Eof => false,
         _ => true,
     }
index 1cf2b7a44bc1728e026d83e6a868f4ed7a9537e0..7adb2848f8d94fae5f43842e0b3693f293bb56db 100644 (file)
@@ -252,7 +252,6 @@ pub fn token_to_string(tok: &Token) -> String {
         /* Name components */
         token::Ident(s)             => s.to_string(),
         token::Lifetime(s)          => s.to_string(),
-        token::Underscore           => "_".to_string(),
 
         /* Other */
         token::DocComment(s)        => s.to_string(),
@@ -353,7 +352,7 @@ pub fn fn_block_to_string(p: &ast::FnDecl) -> String {
 }
 
 pub fn path_to_string(p: &ast::Path) -> String {
-    to_string(|s| s.print_path(p, false, 0, false))
+    to_string(|s| s.print_path(p, false, 0))
 }
 
 pub fn path_segment_to_string(p: &ast::PathSegment) -> String {
@@ -1051,7 +1050,7 @@ pub fn print_type(&mut self, ty: &ast::Ty) -> io::Result<()> {
                                  &f.generic_params)?;
             }
             ast::TyKind::Path(None, ref path) => {
-                self.print_path(path, false, 0, false)?;
+                self.print_path(path, false, 0)?;
             }
             ast::TyKind::Path(Some(ref qself), ref path) => {
                 self.print_qpath(path, qself, false)?
@@ -1174,15 +1173,10 @@ pub fn print_item(&mut self, item: &ast::Item) -> io::Result<()> {
         self.print_outer_attributes(&item.attrs)?;
         self.ann.pre(self, NodeItem(item))?;
         match item.node {
-            ast::ItemKind::ExternCrate(ref optional_path) => {
+            ast::ItemKind::ExternCrate(orig_name) => {
                 self.head(&visibility_qualified(&item.vis, "extern crate"))?;
-                if let Some(p) = *optional_path {
-                    let val = p.as_str();
-                    if val.contains('-') {
-                        self.print_string(&val, ast::StrStyle::Cooked)?;
-                    } else {
-                        self.print_name(p)?;
-                    }
+                if let Some(orig_name) = orig_name {
+                    self.print_name(orig_name)?;
                     self.s.space()?;
                     self.s.word("as")?;
                     self.s.space()?;
@@ -1383,7 +1377,7 @@ pub fn print_item(&mut self, item: &ast::Item) -> io::Result<()> {
                 self.s.word(";")?;
             }
             ast::ItemKind::Mac(codemap::Spanned { ref node, .. }) => {
-                self.print_path(&node.path, false, 0, false)?;
+                self.print_path(&node.path, false, 0)?;
                 self.s.word("! ")?;
                 self.print_ident(item.ident)?;
                 self.cbox(INDENT_UNIT)?;
@@ -1408,7 +1402,7 @@ pub fn print_item(&mut self, item: &ast::Item) -> io::Result<()> {
     }
 
     fn print_trait_ref(&mut self, t: &ast::TraitRef) -> io::Result<()> {
-        self.print_path(&t.path, false, 0, false)
+        self.print_path(&t.path, false, 0)
     }
 
     fn print_formal_generic_params(
@@ -1465,7 +1459,7 @@ pub fn print_visibility(&mut self, vis: &ast::Visibility) -> io::Result<()> {
                 ast::CrateSugar::JustCrate => self.word_nbsp("crate")
             }
             ast::VisibilityKind::Restricted { ref path, .. } => {
-                let path = to_string(|s| s.print_path(path, false, 0, true));
+                let path = to_string(|s| s.print_path(path, false, 0));
                 if path == "self" || path == "super" {
                     self.word_nbsp(&format!("pub({})", path))
                 } else {
@@ -1573,7 +1567,7 @@ pub fn print_trait_item(&mut self, ti: &ast::TraitItem)
                     ti.ident,
                     ty,
                     default.as_ref().map(|expr| &**expr),
-                    &codemap::respan(ti.span.empty(), ast::VisibilityKind::Inherited),
+                    &codemap::respan(ti.span.shrink_to_lo(), ast::VisibilityKind::Inherited),
                 )?;
             }
             ast::TraitItemKind::Method(ref sig, ref body) => {
@@ -1584,7 +1578,7 @@ pub fn print_trait_item(&mut self, ti: &ast::TraitItem)
                     ti.ident,
                     &ti.generics,
                     sig,
-                    &codemap::respan(ti.span.empty(), ast::VisibilityKind::Inherited),
+                    &codemap::respan(ti.span.shrink_to_lo(), ast::VisibilityKind::Inherited),
                 )?;
                 if let Some(ref body) = *body {
                     self.nbsp()?;
@@ -1599,7 +1593,7 @@ pub fn print_trait_item(&mut self, ti: &ast::TraitItem)
             }
             ast::TraitItemKind::Macro(codemap::Spanned { ref node, .. }) => {
                 // code copied from ItemKind::Mac:
-                self.print_path(&node.path, false, 0, false)?;
+                self.print_path(&node.path, false, 0)?;
                 self.s.word("! ")?;
                 self.cbox(INDENT_UNIT)?;
                 self.popen()?;
@@ -1633,7 +1627,7 @@ pub fn print_impl_item(&mut self, ii: &ast::ImplItem) -> io::Result<()> {
             }
             ast::ImplItemKind::Macro(codemap::Spanned { ref node, .. }) => {
                 // code copied from ItemKind::Mac:
-                self.print_path(&node.path, false, 0, false)?;
+                self.print_path(&node.path, false, 0)?;
                 self.s.word("! ")?;
                 self.cbox(INDENT_UNIT)?;
                 self.popen()?;
@@ -1819,7 +1813,7 @@ pub fn print_if_let(&mut self, pats: &[P<ast::Pat>], expr: &ast::Expr, blk: &ast
 
     pub fn print_mac(&mut self, m: &ast::Mac, delim: token::DelimToken)
                      -> io::Result<()> {
-        self.print_path(&m.node.path, false, 0, false)?;
+        self.print_path(&m.node.path, false, 0)?;
         self.s.word("!")?;
         match delim {
             token::Paren => self.popen()?,
@@ -1920,7 +1914,7 @@ fn print_expr_struct(&mut self,
                          fields: &[ast::Field],
                          wth: &Option<P<ast::Expr>>,
                          attrs: &[Attribute]) -> io::Result<()> {
-        self.print_path(path, true, 0, false)?;
+        self.print_path(path, true, 0)?;
         self.s.word("{")?;
         self.print_inner_attributes_inline(attrs)?;
         self.commasep_cmnt(
@@ -2241,7 +2235,7 @@ fn print_expr_outer_attr_style(&mut self,
                 }
             }
             ast::ExprKind::Path(None, ref path) => {
-                self.print_path(path, true, 0, false)?
+                self.print_path(path, true, 0)?
             }
             ast::ExprKind::Path(Some(ref qself), ref path) => {
                 self.print_qpath(path, qself, true)?
@@ -2401,17 +2395,12 @@ pub fn print_for_decl(&mut self, loc: &ast::Local,
     fn print_path(&mut self,
                   path: &ast::Path,
                   colons_before_params: bool,
-                  depth: usize,
-                  defaults_to_global: bool)
+                  depth: usize)
                   -> io::Result<()>
     {
         self.maybe_print_comment(path.span.lo())?;
 
-        let mut segments = path.segments[..path.segments.len()-depth].iter();
-        if defaults_to_global && path.is_global() {
-            segments.next();
-        }
-        for (i, segment) in segments.enumerate() {
+        for (i, segment) in path.segments[..path.segments.len() - depth].iter().enumerate() {
             if i > 0 {
                 self.s.word("::")?
             }
@@ -2450,7 +2439,7 @@ fn print_qpath(&mut self,
             self.s.space()?;
             self.word_space("as")?;
             let depth = path.segments.len() - qself.position;
-            self.print_path(path, false, depth, false)?;
+            self.print_path(path, false, depth)?;
         }
         self.s.word(">")?;
         self.s.word("::")?;
@@ -2553,7 +2542,7 @@ pub fn print_pat(&mut self, pat: &ast::Pat) -> io::Result<()> {
                 }
             }
             PatKind::TupleStruct(ref path, ref elts, ddpos) => {
-                self.print_path(path, true, 0, false)?;
+                self.print_path(path, true, 0)?;
                 self.popen()?;
                 if let Some(ddpos) = ddpos {
                     self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(p))?;
@@ -2571,13 +2560,13 @@ pub fn print_pat(&mut self, pat: &ast::Pat) -> io::Result<()> {
                 self.pclose()?;
             }
             PatKind::Path(None, ref path) => {
-                self.print_path(path, true, 0, false)?;
+                self.print_path(path, true, 0)?;
             }
             PatKind::Path(Some(ref qself), ref path) => {
                 self.print_qpath(path, qself, false)?;
             }
             PatKind::Struct(ref path, ref fields, etc) => {
-                self.print_path(path, true, 0, false)?;
+                self.print_path(path, true, 0)?;
                 self.nbsp()?;
                 self.word_space("{")?;
                 self.commasep_cmnt(
@@ -2954,18 +2943,17 @@ pub fn print_where_clause(&mut self, where_clause: &ast::WhereClause)
 
     pub fn print_use_tree(&mut self, tree: &ast::UseTree) -> io::Result<()> {
         match tree.kind {
-            ast::UseTreeKind::Simple(ref ident) => {
-                self.print_path(&tree.prefix, false, 0, true)?;
-
-                if tree.prefix.segments.last().unwrap().identifier.name != ident.name {
+            ast::UseTreeKind::Simple(rename) => {
+                self.print_path(&tree.prefix, false, 0)?;
+                if let Some(rename) = rename {
                     self.s.space()?;
                     self.word_space("as")?;
-                    self.print_ident(*ident)?;
+                    self.print_ident(rename)?;
                 }
             }
             ast::UseTreeKind::Glob => {
                 if !tree.prefix.segments.is_empty() {
-                    self.print_path(&tree.prefix, false, 0, true)?;
+                    self.print_path(&tree.prefix, false, 0)?;
                     self.s.word("::")?;
                 }
                 self.s.word("*")?;
@@ -2974,7 +2962,7 @@ pub fn print_use_tree(&mut self, tree: &ast::UseTree) -> io::Result<()> {
                 if tree.prefix.segments.is_empty() {
                     self.s.word("{")?;
                 } else {
-                    self.print_path(&tree.prefix, false, 0, true)?;
+                    self.print_path(&tree.prefix, false, 0)?;
                     self.s.word("::{")?;
                 }
                 self.commasep(Inconsistent, &items[..], |this, &(ref tree, _)| {
index da24107f4c33b53485f44008d93b9de19183d68a..fdbc795b2d365500e81ac29da08ba6733008de8f 100644 (file)
@@ -43,7 +43,7 @@ pub fn injected_crate_name() -> Option<&'static str> {
     static INJECTED_CRATE_NAME: Cell<Option<&'static str>> = Cell::new(None);
 }
 
-pub fn maybe_inject_crates_ref(mut krate: ast::Crate, alt_std_name: Option<String>) -> ast::Crate {
+pub fn maybe_inject_crates_ref(mut krate: ast::Crate, alt_std_name: Option<&str>) -> ast::Crate {
     let name = if attr::contains_name(&krate.attrs, "no_core") {
         return krate;
     } else if attr::contains_name(&krate.attrs, "no_std") {
@@ -54,14 +54,12 @@ pub fn maybe_inject_crates_ref(mut krate: ast::Crate, alt_std_name: Option<Strin
 
     INJECTED_CRATE_NAME.with(|opt_name| opt_name.set(Some(name)));
 
-    let crate_name = Symbol::intern(&alt_std_name.unwrap_or_else(|| name.to_string()));
-
     krate.module.items.insert(0, P(ast::Item {
         attrs: vec![attr::mk_attr_outer(DUMMY_SP,
                                         attr::mk_attr_id(),
                                         attr::mk_word_item(Symbol::intern("macro_use")))],
         vis: dummy_spanned(ast::VisibilityKind::Inherited),
-        node: ast::ItemKind::ExternCrate(Some(crate_name)),
+        node: ast::ItemKind::ExternCrate(alt_std_name.map(Symbol::intern)),
         ident: ast::Ident::from_str(name),
         id: ast::DUMMY_NODE_ID,
         span: DUMMY_SP,
@@ -78,10 +76,10 @@ pub fn maybe_inject_crates_ref(mut krate: ast::Crate, alt_std_name: Option<Strin
             is_sugared_doc: false,
             span,
         }],
-        vis: respan(span.empty(), ast::VisibilityKind::Inherited),
+        vis: respan(span.shrink_to_lo(), ast::VisibilityKind::Inherited),
         node: ast::ItemKind::Use(P(ast::UseTree {
             prefix: ast::Path {
-                segments: ["{{root}}", name, "prelude", "v1"].into_iter().map(|name| {
+                segments: [name, "prelude", "v1"].into_iter().map(|name| {
                     ast::PathSegment::from_ident(ast::Ident::from_str(name), DUMMY_SP)
                 }).collect(),
                 span,
index 39306229c82b2e8f28cc73a957946c67f1b910c5..9edfa767d31958df8c0ff07e7850c49708c072b0 100644 (file)
@@ -78,7 +78,7 @@ pub fn modify_for_testing(sess: &ParseSess,
                           span_diagnostic: &errors::Handler,
                           features: &Features) -> ast::Crate {
     // Check for #[reexport_test_harness_main = "some_name"] which
-    // creates a `use some_name = __test::main;`. This needs to be
+    // creates a `use __test::main as some_name;`. This needs to be
     // unconditional, so that the attribute is still marked as used in
     // non-test builds.
     let reexport_test_harness_main =
@@ -240,7 +240,8 @@ fn mk_reexport_mod(cx: &mut TestCtxt,
                                   cx.ext_cx.path(DUMMY_SP, vec![super_, r]))
     }).chain(tested_submods.into_iter().map(|(r, sym)| {
         let path = cx.ext_cx.path(DUMMY_SP, vec![super_, r, sym]);
-        cx.ext_cx.item_use_simple_(DUMMY_SP, dummy_spanned(ast::VisibilityKind::Public), r, path)
+        cx.ext_cx.item_use_simple_(DUMMY_SP, dummy_spanned(ast::VisibilityKind::Public),
+                                   Some(r), path)
     })).collect();
 
     let reexport_mod = ast::Mod {
@@ -502,7 +503,7 @@ fn mk_std(cx: &TestCtxt) -> P<ast::Item> {
         (ast::ItemKind::Use(P(ast::UseTree {
             span: DUMMY_SP,
             prefix: path_node(vec![id_test]),
-            kind: ast::UseTreeKind::Simple(id_test),
+            kind: ast::UseTreeKind::Simple(None),
         })),
          ast::VisibilityKind::Public, keywords::Invalid.ident())
     } else {
@@ -590,13 +591,13 @@ fn mk_test_module(cx: &mut TestCtxt) -> (P<ast::Item>, Option<P<ast::Item>>) {
         tokens: None,
     })).pop().unwrap();
     let reexport = cx.reexport_test_harness_main.map(|s| {
-        // building `use <ident> = __test::main`
-        let reexport_ident = Ident::with_empty_ctxt(s);
+        // building `use __test::main as <ident>;`
+        let rename = Ident::with_empty_ctxt(s);
 
         let use_path = ast::UseTree {
             span: DUMMY_SP,
             prefix: path_node(vec![mod_ident, Ident::from_str("main")]),
-            kind: ast::UseTreeKind::Simple(reexport_ident),
+            kind: ast::UseTreeKind::Simple(Some(rename)),
         };
 
         expander.fold_item(P(ast::Item {
index 5a24c61cb5aaf8588f28ab255251aadbf2e3ab40..bbf1fe124f1ba3f4f4b29fe124873bc3dab25bc6 100644 (file)
@@ -213,9 +213,9 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
     visitor.visit_vis(&item.vis);
     visitor.visit_ident(item.span, item.ident);
     match item.node {
-        ItemKind::ExternCrate(opt_name) => {
-            if let Some(name) = opt_name {
-                visitor.visit_name(item.span, name);
+        ItemKind::ExternCrate(orig_name) => {
+            if let Some(orig_name) = orig_name {
+                visitor.visit_name(item.span, orig_name);
             }
         }
         ItemKind::Use(ref use_tree) => {
@@ -354,10 +354,11 @@ pub fn walk_use_tree<'a, V: Visitor<'a>>(
     visitor: &mut V, use_tree: &'a UseTree, id: NodeId,
 ) {
     visitor.visit_path(&use_tree.prefix, id);
-
     match use_tree.kind {
-        UseTreeKind::Simple(ident) => {
-            visitor.visit_ident(use_tree.span, ident);
+        UseTreeKind::Simple(rename) => {
+            if let Some(rename) = rename {
+                visitor.visit_ident(use_tree.span, rename);
+            }
         }
         UseTreeKind::Glob => {},
         UseTreeKind::Nested(ref use_trees) => {
diff --git a/src/libsyntax_ext/assert.rs b/src/libsyntax_ext/assert.rs
new file mode 100644 (file)
index 0000000..8b29e6a
--- /dev/null
@@ -0,0 +1,122 @@
+// 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.
+
+use syntax::ast::*;
+use syntax::codemap::Spanned;
+use syntax::ext::base::*;
+use syntax::ext::build::AstBuilder;
+use syntax::parse::token;
+use syntax::print::pprust;
+use syntax::tokenstream::{TokenStream, TokenTree};
+use syntax_pos::{Span, DUMMY_SP};
+
+pub fn expand_assert<'cx>(
+    cx: &'cx mut ExtCtxt,
+    sp: Span,
+    tts: &[TokenTree],
+) -> Box<MacResult + 'cx> {
+    let mut parser = cx.new_parser_from_tts(tts);
+    let cond_expr = panictry!(parser.parse_expr());
+    let custom_msg_args = if parser.eat(&token::Comma) {
+        let ts = parser.parse_tokens();
+        if !ts.is_empty() {
+            Some(ts)
+        } else {
+            None
+        }
+    } else {
+        None
+    };
+
+    let sp = sp.with_ctxt(sp.ctxt().apply_mark(cx.current_expansion.mark));
+    let panic_call = Mac_ {
+        path: Path::from_ident(sp, Ident::from_str("panic")),
+        tts: if let Some(ts) = custom_msg_args {
+            ts.into()
+        } else {
+            // `expr_to_string` escapes the string literals with `.escape_default()`
+            // which escapes all non-ASCII characters with `\u`.
+            let escaped_expr = escape_format_string(&unescape_printable_unicode(
+                &pprust::expr_to_string(&cond_expr),
+            ));
+
+            TokenStream::from(TokenTree::Token(
+                DUMMY_SP,
+                token::Literal(
+                    token::Lit::Str_(Name::intern(&format!("assertion failed: {}", escaped_expr))),
+                    None,
+                ),
+            )).into()
+        },
+    };
+    let if_expr = cx.expr_if(
+        sp,
+        cx.expr(sp, ExprKind::Unary(UnOp::Not, cond_expr)),
+        cx.expr(
+            sp,
+            ExprKind::Mac(Spanned {
+                span: sp,
+                node: panic_call,
+            }),
+        ),
+        None,
+    );
+    MacEager::expr(if_expr)
+}
+
+/// Escapes a string for use as a formatting string.
+fn escape_format_string(s: &str) -> String {
+    let mut res = String::with_capacity(s.len());
+    for c in s.chars() {
+        res.extend(c.escape_debug());
+        match c {
+            '{' | '}' => res.push(c),
+            _ => {}
+        }
+    }
+    res
+}
+
+#[test]
+fn test_escape_format_string() {
+    assert!(escape_format_string(r"foo{}\") == r"foo{{}}\\");
+}
+
+/// Unescapes the escaped unicodes (`\u{...}`) that are printable.
+fn unescape_printable_unicode(mut s: &str) -> String {
+    use std::{char, u32};
+
+    let mut res = String::with_capacity(s.len());
+
+    loop {
+        if let Some(start) = s.find(r"\u{") {
+            res.push_str(&s[0..start]);
+            s = &s[start..];
+            s.find('}')
+                .and_then(|end| {
+                    let v = u32::from_str_radix(&s[3..end], 16).ok()?;
+                    let c = char::from_u32(v)?;
+                    // Escape unprintable characters.
+                    res.extend(c.escape_debug());
+                    s = &s[end + 1..];
+                    Some(())
+                })
+                .expect("lexer should have rejected invalid escape sequences");
+        } else {
+            res.push_str(s);
+            return res;
+        }
+    }
+}
+
+#[test]
+fn test_unescape_printable_unicode() {
+    assert!(unescape_printable_unicode(r"\u{2603}\n\u{0}") == r"☃\n\u{0}");
+}
index 1b3917efdd1e78a631da4c48c257ebf35b67e9b2..49c372b751b506d4b694807aefddaf20810a2bda 100644 (file)
@@ -530,7 +530,7 @@ fn create_derived_impl(&self,
                 id: ast::DUMMY_NODE_ID,
                 span: self.span,
                 ident,
-                vis: respan(self.span.empty(), ast::VisibilityKind::Inherited),
+                vis: respan(self.span.shrink_to_lo(), ast::VisibilityKind::Inherited),
                 defaultness: ast::Defaultness::Final,
                 attrs: Vec::new(),
                 generics: Generics::default(),
@@ -977,7 +977,7 @@ fn create_method(&self,
             attrs: self.attributes.clone(),
             generics: fn_generics,
             span: trait_.span,
-            vis: respan(trait_.span.empty(), ast::VisibilityKind::Inherited),
+            vis: respan(trait_.span.shrink_to_lo(), ast::VisibilityKind::Inherited),
             defaultness: ast::Defaultness::Final,
             ident: method_ident,
             node: ast::ImplItemKind::Method(ast::MethodSig {
index fcad065be52bcaf1868a5594dc95e1ea5d89fea5..ba6d25f7a60a4bf8647d0f22608cec67ba868b3d 100644 (file)
@@ -17,7 +17,7 @@
 use syntax::ext::base::*;
 use syntax::ext::base;
 use syntax::ext::build::AstBuilder;
-use syntax::symbol::Symbol;
+use syntax::symbol::{keywords, Symbol};
 use syntax_pos::Span;
 use syntax::tokenstream;
 
@@ -35,14 +35,14 @@ pub fn expand_option_env<'cx>(cx: &'cx mut ExtCtxt,
     let sp = sp.with_ctxt(sp.ctxt().apply_mark(cx.current_expansion.mark));
     let e = match env::var(&*var.as_str()) {
         Err(..) => {
+            let lt = cx.lifetime(sp, keywords::StaticLifetime.ident());
             cx.expr_path(cx.path_all(sp,
                                      true,
                                      cx.std_path(&["option", "Option", "None"]),
                                      Vec::new(),
                                      vec![cx.ty_rptr(sp,
                                                      cx.ty_ident(sp, Ident::from_str("str")),
-                                                     Some(cx.lifetime(sp,
-                                                                      Ident::from_str("'static"))),
+                                                     Some(lt),
                                                      ast::Mutability::Immutable)],
                                      Vec::new()))
         }
index 9605f6b5c5a9d30b60e24ad724e04d0ea089241e..f01a0aacb0a734a5cc2337d55bd82779b796d409 100644 (file)
@@ -60,7 +60,7 @@ pub fn expand_global_asm<'cx>(cx: &'cx mut ExtCtxt,
             asm,
             ctxt: cx.backtrace(),
         })),
-        vis: respan(sp.empty(), ast::VisibilityKind::Inherited),
+        vis: respan(sp.shrink_to_lo(), ast::VisibilityKind::Inherited),
         span: sp,
         tokens: None,
     })))
index 772dec72ab98edd300a034fbc9ca5afb175a8a6a..249a64b353f5912f981425e92c1b94b7c3f7e928 100644 (file)
@@ -17,6 +17,7 @@
 
 #![feature(proc_macro_internals)]
 #![feature(decl_macro)]
+#![feature(str_escape)]
 
 extern crate fmt_macros;
 #[macro_use]
@@ -26,6 +27,7 @@
 extern crate rustc_data_structures;
 extern crate rustc_errors as errors;
 
+mod assert;
 mod asm;
 mod cfg;
 mod compile_error;
@@ -67,6 +69,7 @@ macro_rules! register {
                         def_info: None,
                         allow_internal_unstable: false,
                         allow_internal_unsafe: false,
+                        unstable_feature: None,
                     });
         )* }
     }
@@ -111,6 +114,7 @@ macro_rules! register {
         log_syntax: log_syntax::expand_syntax_ext,
         trace_macros: trace_macros::expand_trace_macros,
         compile_error: compile_error::expand_compile_error,
+        assert: assert::expand_assert,
     }
 
     // format_args uses `unstable` things internally.
@@ -120,6 +124,7 @@ macro_rules! register {
                 def_info: None,
                 allow_internal_unstable: true,
                 allow_internal_unsafe: false,
+                unstable_feature: None
             });
 
     for (name, ext) in user_exts {
index bec46ff3d797c6c82b2f1e7a570d9638ea337941..9b83d5510fb7d836dec3d37406c80dc7b21ef566 100644 (file)
@@ -27,7 +27,7 @@
 #![feature(specialization)]
 
 use std::borrow::Cow;
-use std::cell::{Cell, RefCell};
+use std::cell::Cell;
 use std::cmp::{self, Ordering};
 use std::fmt;
 use std::hash::{Hasher, Hash};
@@ -239,8 +239,15 @@ pub fn with_ctxt(self, ctxt: SyntaxContext) -> Span {
 
     /// Returns a new span representing an empty span at the beginning of this span
     #[inline]
-    pub fn empty(self) -> Span {
-        self.with_hi(self.lo())
+    pub fn shrink_to_lo(self) -> Span {
+        let span = self.data();
+        span.with_hi(span.lo)
+    }
+    /// Returns a new span representing an empty span at the end of this span
+    #[inline]
+    pub fn shrink_to_hi(self) -> Span {
+        let span = self.data();
+        span.with_lo(span.hi)
     }
 
     /// Returns `self` if `self` is not the dummy span, and `other` otherwise.
@@ -699,17 +706,17 @@ pub struct FileMap {
     pub src_hash: u128,
     /// The external source code (used for external crates, which will have a `None`
     /// value as `self.src`.
-    pub external_src: RefCell<ExternalSource>,
+    pub external_src: Lock<ExternalSource>,
     /// The start position of this source in the CodeMap
     pub start_pos: BytePos,
     /// The end position of this source in the CodeMap
     pub end_pos: BytePos,
     /// Locations of lines beginnings in the source code
-    pub lines: RefCell<Vec<BytePos>>,
+    pub lines: Lock<Vec<BytePos>>,
     /// Locations of multi-byte characters in the source code
-    pub multibyte_chars: RefCell<Vec<MultiByteChar>>,
+    pub multibyte_chars: Lock<Vec<MultiByteChar>>,
     /// Width of characters that are not narrow in the source code
-    pub non_narrow_chars: RefCell<Vec<NonNarrowChar>>,
+    pub non_narrow_chars: Lock<Vec<NonNarrowChar>>,
     /// A hash of the filename, used for speeding up the incr. comp. hashing.
     pub name_hash: u128,
 }
@@ -839,10 +846,10 @@ fn decode<D: Decoder>(d: &mut D) -> Result<FileMap, D::Error> {
                 end_pos,
                 src: None,
                 src_hash,
-                external_src: RefCell::new(ExternalSource::AbsentOk),
-                lines: RefCell::new(lines),
-                multibyte_chars: RefCell::new(multibyte_chars),
-                non_narrow_chars: RefCell::new(non_narrow_chars),
+                external_src: Lock::new(ExternalSource::AbsentOk),
+                lines: Lock::new(lines),
+                multibyte_chars: Lock::new(multibyte_chars),
+                non_narrow_chars: Lock::new(non_narrow_chars),
                 name_hash,
             })
         })
@@ -882,12 +889,12 @@ pub fn new(name: FileName,
             crate_of_origin: 0,
             src: Some(Lrc::new(src)),
             src_hash,
-            external_src: RefCell::new(ExternalSource::Unneeded),
+            external_src: Lock::new(ExternalSource::Unneeded),
             start_pos,
             end_pos: Pos::from_usize(end_pos),
-            lines: RefCell::new(Vec::new()),
-            multibyte_chars: RefCell::new(Vec::new()),
-            non_narrow_chars: RefCell::new(Vec::new()),
+            lines: Lock::new(Vec::new()),
+            multibyte_chars: Lock::new(Vec::new()),
+            non_narrow_chars: Lock::new(Vec::new()),
             name_hash,
         }
     }
@@ -919,19 +926,24 @@ pub fn add_external_src<F>(&self, get_src: F) -> bool
         if *self.external_src.borrow() == ExternalSource::AbsentOk {
             let src = get_src();
             let mut external_src = self.external_src.borrow_mut();
-            if let Some(src) = src {
-                let mut hasher: StableHasher<u128> = StableHasher::new();
-                hasher.write(src.as_bytes());
-
-                if hasher.finish() == self.src_hash {
-                    *external_src = ExternalSource::Present(src);
-                    return true;
+            // Check that no-one else have provided the source while we were getting it
+            if *external_src == ExternalSource::AbsentOk {
+                if let Some(src) = src {
+                    let mut hasher: StableHasher<u128> = StableHasher::new();
+                    hasher.write(src.as_bytes());
+
+                    if hasher.finish() == self.src_hash {
+                        *external_src = ExternalSource::Present(src);
+                        return true;
+                    }
+                } else {
+                    *external_src = ExternalSource::AbsentErr;
                 }
+
+                false
             } else {
-                *external_src = ExternalSource::AbsentErr;
+                self.src.is_some() || external_src.get_source().is_some()
             }
-
-            false
         } else {
             self.src.is_some() || self.external_src.borrow().get_source().is_some()
         }
@@ -951,14 +963,16 @@ fn get_until_newline(src: &str, begin: usize) -> &str {
             }
         }
 
-        let lines = self.lines.borrow();
-        let line = if let Some(line) = lines.get(line_number) {
-            line
-        } else {
-            return None;
+        let begin = {
+            let lines = self.lines.borrow();
+            let line = if let Some(line) = lines.get(line_number) {
+                line
+            } else {
+                return None;
+            };
+            let begin: BytePos = *line - self.start_pos;
+            begin.to_usize()
         };
-        let begin: BytePos = *line - self.start_pos;
-        let begin = begin.to_usize();
 
         if let Some(ref src) = self.src {
             Some(Cow::from(get_until_newline(src, begin)))
index e95079f7c88dd412db2455fa1a0bbe4b81bdd398..0cba094da641d234b6d7bbcd8c61614714a2a02e 100644 (file)
@@ -261,73 +261,77 @@ pub fn fresh() -> Self {
 declare_keywords! {
     // Special reserved identifiers used internally for elided lifetimes,
     // unnamed method parameters, crate root module, error recovery etc.
-    (0,  Invalid,        "")
-    (1,  CrateRoot,      "{{root}}")
-    (2,  DollarCrate,    "$crate")
+    (0,  Invalid,            "")
+    (1,  CrateRoot,          "{{root}}")
+    (2,  DollarCrate,        "$crate")
+    (3,  Underscore,         "_")
 
     // Keywords used in the language.
-    (3,  As,             "as")
-    (4,  Box,            "box")
-    (5,  Break,          "break")
-    (6,  Const,          "const")
-    (7,  Continue,       "continue")
-    (8,  Crate,          "crate")
-    (9,  Else,           "else")
-    (10, Enum,           "enum")
-    (11, Extern,         "extern")
-    (12, False,          "false")
-    (13, Fn,             "fn")
-    (14, For,            "for")
-    (15, If,             "if")
-    (16, Impl,           "impl")
-    (17, In,             "in")
-    (18, Let,            "let")
-    (19, Loop,           "loop")
-    (20, Match,          "match")
-    (21, Mod,            "mod")
-    (22, Move,           "move")
-    (23, Mut,            "mut")
-    (24, Pub,            "pub")
-    (25, Ref,            "ref")
-    (26, Return,         "return")
-    (27, SelfValue,      "self")
-    (28, SelfType,       "Self")
-    (29, Static,         "static")
-    (30, Struct,         "struct")
-    (31, Super,          "super")
-    (32, Trait,          "trait")
-    (33, True,           "true")
-    (34, Type,           "type")
-    (35, Unsafe,         "unsafe")
-    (36, Use,            "use")
-    (37, Where,          "where")
-    (38, While,          "while")
+    (4,  As,                 "as")
+    (5,  Box,                "box")
+    (6,  Break,              "break")
+    (7,  Const,              "const")
+    (8,  Continue,           "continue")
+    (9,  Crate,              "crate")
+    (10, Else,               "else")
+    (11, Enum,               "enum")
+    (12, Extern,             "extern")
+    (13, False,              "false")
+    (14, Fn,                 "fn")
+    (15, For,                "for")
+    (16, If,                 "if")
+    (17, Impl,               "impl")
+    (18, In,                 "in")
+    (19, Let,                "let")
+    (20, Loop,               "loop")
+    (21, Match,              "match")
+    (22, Mod,                "mod")
+    (23, Move,               "move")
+    (24, Mut,                "mut")
+    (25, Pub,                "pub")
+    (26, Ref,                "ref")
+    (27, Return,             "return")
+    (28, SelfValue,          "self")
+    (29, SelfType,           "Self")
+    (30, Static,             "static")
+    (31, Struct,             "struct")
+    (32, Super,              "super")
+    (33, Trait,              "trait")
+    (34, True,               "true")
+    (35, Type,               "type")
+    (36, Unsafe,             "unsafe")
+    (37, Use,                "use")
+    (38, Where,              "where")
+    (39, While,              "while")
 
     // Keywords reserved for future use.
-    (39, Abstract,       "abstract")
-    (40, Alignof,        "alignof")
-    (41, Become,         "become")
-    (42, Do,             "do")
-    (43, Final,          "final")
-    (44, Macro,          "macro")
-    (45, Offsetof,       "offsetof")
-    (46, Override,       "override")
-    (47, Priv,           "priv")
-    (48, Proc,           "proc")
-    (49, Pure,           "pure")
-    (50, Sizeof,         "sizeof")
-    (51, Typeof,         "typeof")
-    (52, Unsized,        "unsized")
-    (53, Virtual,        "virtual")
-    (54, Yield,          "yield")
+    (40, Abstract,           "abstract")
+    (41, Alignof,            "alignof")
+    (42, Become,             "become")
+    (43, Do,                 "do")
+    (44, Final,              "final")
+    (45, Macro,              "macro")
+    (46, Offsetof,           "offsetof")
+    (47, Override,           "override")
+    (48, Priv,               "priv")
+    (49, Proc,               "proc")
+    (50, Pure,               "pure")
+    (51, Sizeof,             "sizeof")
+    (52, Typeof,             "typeof")
+    (53, Unsized,            "unsized")
+    (54, Virtual,            "virtual")
+    (55, Yield,              "yield")
+
+    // Special lifetime names
+    (56, UnderscoreLifetime, "'_")
+    (57, StaticLifetime,     "'static")
 
     // Weak keywords, have special meaning only in specific contexts.
-    (55, Auto,           "auto")
-    (56, Catch,          "catch")
-    (57, Default,        "default")
-    (58, Dyn,            "dyn")
-    (59, StaticLifetime, "'static")
-    (60, Union,          "union")
+    (58, Auto,               "auto")
+    (59, Catch,              "catch")
+    (60, Default,            "default")
+    (61, Dyn,                "dyn")
+    (62, Union,              "union")
 }
 
 // If an interner exists, return it. Otherwise, prepare a fresh one.
index 27d5496f57628c4c7d6c05c41a6fee03f12357c3..a5644d6f9e2e1fab9edd6278eb8110ef8dae8d15 100644 (file)
@@ -21,6 +21,8 @@
 
 #if LLVM_VERSION_GE(5, 0)
 #include "llvm/ADT/Optional.h"
+#else
+#include <cstdlib>
 #endif
 
 //===----------------------------------------------------------------------===
@@ -1395,3 +1397,98 @@ LLVMRustModuleCost(LLVMModuleRef M) {
   auto f = unwrap(M)->functions();
   return std::distance(std::begin(f), std::end(f));
 }
+
+// Vector reductions:
+#if LLVM_VERSION_GE(5, 0)
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceFAdd(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) {
+    return wrap(unwrap(B)->CreateFAddReduce(unwrap(Acc),unwrap(Src)));
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceFMul(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) {
+    return wrap(unwrap(B)->CreateFMulReduce(unwrap(Acc),unwrap(Src)));
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceAdd(LLVMBuilderRef B, LLVMValueRef Src) {
+    return wrap(unwrap(B)->CreateAddReduce(unwrap(Src)));
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceMul(LLVMBuilderRef B, LLVMValueRef Src) {
+    return wrap(unwrap(B)->CreateMulReduce(unwrap(Src)));
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceAnd(LLVMBuilderRef B, LLVMValueRef Src) {
+    return wrap(unwrap(B)->CreateAndReduce(unwrap(Src)));
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceOr(LLVMBuilderRef B, LLVMValueRef Src) {
+    return wrap(unwrap(B)->CreateOrReduce(unwrap(Src)));
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceXor(LLVMBuilderRef B, LLVMValueRef Src) {
+    return wrap(unwrap(B)->CreateXorReduce(unwrap(Src)));
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceMin(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) {
+    return wrap(unwrap(B)->CreateIntMinReduce(unwrap(Src), IsSigned));
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceMax(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) {
+    return wrap(unwrap(B)->CreateIntMaxReduce(unwrap(Src), IsSigned));
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceFMin(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) {
+   return wrap(unwrap(B)->CreateFPMinReduce(unwrap(Src), NoNaN));
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceFMax(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) {
+  return wrap(unwrap(B)->CreateFPMaxReduce(unwrap(Src), NoNaN));
+}
+
+#else
+
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceFAdd(LLVMBuilderRef, LLVMValueRef, LLVMValueRef) {
+  return nullptr;
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceFMul(LLVMBuilderRef, LLVMValueRef, LLVMValueRef) {
+  return nullptr;
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceAdd(LLVMBuilderRef, LLVMValueRef) {
+  return nullptr;
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceMul(LLVMBuilderRef, LLVMValueRef) {
+  return nullptr;
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceAnd(LLVMBuilderRef, LLVMValueRef) {
+  return nullptr;
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceOr(LLVMBuilderRef, LLVMValueRef) {
+  return nullptr;
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceXor(LLVMBuilderRef, LLVMValueRef) {
+  return nullptr;
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceMin(LLVMBuilderRef, LLVMValueRef, bool) {
+  return nullptr;
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceMax(LLVMBuilderRef, LLVMValueRef, bool) {
+  return nullptr;
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceFMin(LLVMBuilderRef, LLVMValueRef, bool) {
+  return nullptr;
+}
+extern "C" LLVMValueRef
+LLVMRustBuildVectorReduceFMax(LLVMBuilderRef, LLVMValueRef, bool) {
+  return nullptr;
+}
+#endif
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
 
diff --git a/src/test/compile-fail/auxiliary/unstable-macros.rs b/src/test/compile-fail/auxiliary/unstable-macros.rs
new file mode 100644 (file)
index 0000000..6462c11
--- /dev/null
@@ -0,0 +1,16 @@
+// 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.
+
+#![feature(staged_api)]
+#![stable(feature = "unit_test", since = "0.0.0")]
+
+#[unstable(feature = "unstable_macros", issue = "0")]
+#[macro_export]
+macro_rules! unstable_macro{ () => () }
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)]
diff --git a/src/test/compile-fail/issue-47309.rs b/src/test/compile-fail/issue-47309.rs
new file mode 100644 (file)
index 0000000..7141bd6
--- /dev/null
@@ -0,0 +1,31 @@
+// 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.
+
+// Make sure that the mono-item collector does not crash when trying to
+// instantiate a default impl of a method with lifetime parameters.
+// See https://github.com/rust-lang/rust/issues/47309
+
+// compile-flags:-Clink-dead-code
+// must-compile-successfully
+
+#![crate_type="rlib"]
+
+pub trait EnvFuture {
+    type Item;
+
+    fn boxed_result<'a>(self) where Self: Sized, Self::Item: 'a, {
+    }
+}
+
+struct Foo;
+
+impl<'a> EnvFuture for &'a Foo {
+    type Item = ();
+}
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 1c0401ec56b853bbbde4ced5ec2aef8f51b75ab3..214a03c13f4e56bde68d486ad77b99e0427e2687 100644 (file)
@@ -9,12 +9,12 @@
 // except according to those terms.
 
 #![deny(unused_import_braces)]
-#![allow(dead_code)]
-#![allow(unused_imports)]
 
 use test::{A}; //~ ERROR braces around A is unnecessary
 
 mod test {
+    use test::{self}; // OK
+    use test::{self as rename}; // OK
     pub struct A;
 }
 
diff --git a/src/test/compile-fail/macro-stability.rs b/src/test/compile-fail/macro-stability.rs
new file mode 100644 (file)
index 0000000..a4b922c
--- /dev/null
@@ -0,0 +1,22 @@
+// 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.
+
+// aux-build:unstable-macros.rs
+
+#![feature(staged_api)]
+#[macro_use] extern crate unstable_macros;
+
+#[unstable(feature = "local_unstable", issue = "0")]
+macro_rules! local_unstable { () => () }
+
+fn main() {
+    local_unstable!();
+    unstable_macro!(); //~ ERROR: macro unstable_macro! is unstable
+}
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() {
diff --git a/src/test/compile-fail/simd-intrinsic-generic-reduction.rs b/src/test/compile-fail/simd-intrinsic-generic-reduction.rs
new file mode 100644 (file)
index 0000000..57e4bb7
--- /dev/null
@@ -0,0 +1,82 @@
+// 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.
+
+// min-llvm-version 5.0
+// ignore-emscripten
+
+// Test that the simd_reduce_{op} intrinsics produce ok-ish error
+// messages when misused.
+
+#![feature(repr_simd, platform_intrinsics)]
+#![allow(non_camel_case_types)]
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+pub struct f32x4(pub f32, pub f32, pub f32, pub f32);
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+pub struct u32x4(pub u32, pub u32, pub u32, pub u32);
+
+
+extern "platform-intrinsic" {
+    fn simd_reduce_add_ordered<T, U>(x: T, y: U) -> U;
+    fn simd_reduce_mul_ordered<T, U>(x: T, y: U) -> U;
+    fn simd_reduce_and<T, U>(x: T) -> U;
+    fn simd_reduce_or<T, U>(x: T) -> U;
+    fn simd_reduce_xor<T, U>(x: T) -> U;
+    fn simd_reduce_all<T>(x: T) -> bool;
+    fn simd_reduce_any<T>(x: T) -> bool;
+}
+
+fn main() {
+    let x = u32x4(0, 0, 0, 0);
+    let z = f32x4(0.0, 0.0, 0.0, 0.0);
+
+    unsafe {
+        simd_reduce_add_ordered(z, 0_f32);
+        simd_reduce_mul_ordered(z, 1_f32);
+
+        simd_reduce_add_ordered(z, 2_f32);
+        //~^ ERROR accumulator of simd_reduce_add_ordered is not 0.0
+        simd_reduce_mul_ordered(z, 3_f32);
+        //~^ ERROR accumulator of simd_reduce_mul_ordered is not 1.0
+
+        let _: f32 = simd_reduce_and(x);
+        //~^ ERROR expected return type `u32` (element of input `u32x4`), found `f32`
+        let _: f32 = simd_reduce_or(x);
+        //~^ ERROR expected return type `u32` (element of input `u32x4`), found `f32`
+        let _: f32 = simd_reduce_xor(x);
+        //~^ ERROR expected return type `u32` (element of input `u32x4`), found `f32`
+
+        let _: f32 = simd_reduce_and(z);
+        //~^ ERROR unsupported simd_reduce_and from `f32x4` with element `f32` to `f32`
+        let _: f32 = simd_reduce_or(z);
+        //~^ ERROR unsupported simd_reduce_or from `f32x4` with element `f32` to `f32`
+        let _: f32 = simd_reduce_xor(z);
+        //~^ ERROR unsupported simd_reduce_xor from `f32x4` with element `f32` to `f32`
+
+        let _: bool = simd_reduce_all(z);
+        //~^ ERROR unsupported simd_reduce_all from `f32x4` with element `f32` to `bool`
+        let _: bool = simd_reduce_any(z);
+        //~^ ERROR unsupported simd_reduce_any from `f32x4` with element `f32` to `bool`
+
+        foo(0_f32);
+    }
+}
+
+#[inline(never)]
+unsafe fn foo(x: f32) {
+    let z = f32x4(0.0, 0.0, 0.0, 0.0);
+    simd_reduce_add_ordered(z, x);
+    //~^ ERROR accumulator of simd_reduce_add_ordered is not a constant
+    simd_reduce_mul_ordered(z, x);
+    //~^ ERROR accumulator of simd_reduce_mul_ordered is not a constant
+}
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 f29c1fa27940071dff6f6e2677ddbf0ce1ad5ae4..21db2f5051703dffd4c3582b3d874150bdc8da93 100644 (file)
@@ -16,7 +16,5 @@ fn main() {
     let _ = 0;
     let mut b = 0;
     let mut _b = 0;
-    let mut _ = 0; //~ ERROR expected identifier, found `_`
-    //~^ NOTE `_` is a wildcard pattern, not an identifier
-    //~| NOTE expected identifier
+    let mut _ = 0; //~ ERROR expected identifier, found reserved identifier `_`
 }
index 49380a03e156a27598ea472f49c64a4f897fe67a..6fd32f842f1353131e9b1e4913ffa9549d0512a1 100644 (file)
@@ -39,5 +39,5 @@ enum Test4 {
         }
     }
     // still recover later
-    let bad_syntax = _; //~ ERROR: found `_`
+    let bad_syntax = _; //~ ERROR: expected expression, found reserved identifier `_`
 }
index df7d9aa374dce948bd094241a51566c7693a9fd2..8327217e6f286bb3cf4c98b33669c05a8d5f50c1 100644 (file)
@@ -9,5 +9,6 @@
 // except according to those terms.
 
 fn main() {
-    let a = 42._; //~ ERROR unexpected token: `_`
+    let a = 42._; //~ ERROR expected identifier, found reserved identifier `_`
+                  //~^ ERROR `{integer}` is a primitive type and therefore doesn't have fields
 }
index 9e87268e6999da1ec81d5193fa093d19ab68776e..e266b0f5e834744e25371dd838a50844ccfd6147 100644 (file)
@@ -28,7 +28,7 @@
 struct TheBackend(Box<TransCrate>);
 
 impl TransCrate for TheBackend {
-    fn metadata_loader(&self) -> Box<MetadataLoader> {
+    fn metadata_loader(&self) -> Box<MetadataLoader + Sync> {
         self.0.metadata_loader()
     }
 
index 8da2ae8b29abe48dbb00b44ff555709b74c67453..231ed2898f1db6af7ebf332911343c57e5284fd3 100644 (file)
@@ -53,5 +53,6 @@ pub fn plugin_registrar(reg: &mut Registry) {
             def_info: None,
             allow_internal_unstable: false,
             allow_internal_unsafe: false,
+            unstable_feature: None,
         });
 }
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;
diff --git a/src/test/run-pass/assert-escape.rs b/src/test/run-pass/assert-escape.rs
new file mode 100644 (file)
index 0000000..d340806
--- /dev/null
@@ -0,0 +1,13 @@
+// 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.
+
+fn main() {
+    assert!(r#"☃\backslash"#.contains("\\"));
+}
diff --git a/src/test/run-pass/auxiliary/unstable-macros.rs b/src/test/run-pass/auxiliary/unstable-macros.rs
new file mode 100644 (file)
index 0000000..6462c11
--- /dev/null
@@ -0,0 +1,16 @@
+// 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.
+
+#![feature(staged_api)]
+#![stable(feature = "unit_test", since = "0.0.0")]
+
+#[unstable(feature = "unstable_macros", issue = "0")]
+#[macro_export]
+macro_rules! unstable_macro{ () => () }
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 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 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;
diff --git a/src/test/run-pass/macro-stability.rs b/src/test/run-pass/macro-stability.rs
new file mode 100644 (file)
index 0000000..9afcd51
--- /dev/null
@@ -0,0 +1,23 @@
+// 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.
+
+// aux-build:unstable-macros.rs
+
+#![feature(unstable_macros)]
+
+#[macro_use] extern crate unstable_macros;
+
+#[unstable(feature = "local_unstable", issue = "0")]
+macro_rules! local_unstable { () => () }
+
+fn main() {
+    unstable_macro!();
+    local_unstable!();
+}
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)]
diff --git a/src/test/run-pass/simd-intrinsic-generic-reduction.rs b/src/test/run-pass/simd-intrinsic-generic-reduction.rs
new file mode 100644 (file)
index 0000000..9a1214d
--- /dev/null
@@ -0,0 +1,172 @@
+// 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.
+
+// min-llvm-version 5.0
+// ignore-emscripten
+
+// Test that the simd_reduce_{op} intrinsics produce the correct results.
+
+#![feature(repr_simd, platform_intrinsics)]
+#[allow(non_camel_case_types)]
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+struct i32x4(pub i32, pub i32, pub i32, pub i32);
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+struct u32x4(pub u32, pub u32, pub u32, pub u32);
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+struct f32x4(pub f32, pub f32, pub f32, pub f32);
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+struct b8x4(pub i8, pub i8, pub i8, pub i8);
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+struct b8x16(
+    pub i8, pub i8, pub i8, pub i8,
+    pub i8, pub i8, pub i8, pub i8,
+    pub i8, pub i8, pub i8, pub i8,
+    pub i8, pub i8, pub i8, pub i8
+);
+
+extern "platform-intrinsic" {
+    fn simd_reduce_add_unordered<T, U>(x: T) -> U;
+    fn simd_reduce_mul_unordered<T, U>(x: T) -> U;
+    fn simd_reduce_add_ordered<T, U>(x: T, acc: U) -> U;
+    fn simd_reduce_mul_ordered<T, U>(x: T, acc: U) -> U;
+    fn simd_reduce_min<T, U>(x: T) -> U;
+    fn simd_reduce_max<T, U>(x: T) -> U;
+    fn simd_reduce_min_nanless<T, U>(x: T) -> U;
+    fn simd_reduce_max_nanless<T, U>(x: T) -> U;
+    fn simd_reduce_and<T, U>(x: T) -> U;
+    fn simd_reduce_or<T, U>(x: T) -> U;
+    fn simd_reduce_xor<T, U>(x: T) -> U;
+    fn simd_reduce_all<T>(x: T) -> bool;
+    fn simd_reduce_any<T>(x: T) -> bool;
+}
+
+fn main() {
+    unsafe {
+        let x = i32x4(1, -2, 3, 4);
+        let r: i32 = simd_reduce_add_unordered(x);
+        assert_eq!(r, 6_i32);
+        let r: i32 = simd_reduce_mul_unordered(x);
+        assert_eq!(r, -24_i32);
+        let r: i32 = simd_reduce_add_ordered(x, -1);
+        assert_eq!(r, 5_i32);
+        let r: i32 = simd_reduce_mul_ordered(x, -1);
+        assert_eq!(r, 24_i32);
+
+        let r: i32 = simd_reduce_min(x);
+        assert_eq!(r, -2_i32);
+        let r: i32 = simd_reduce_max(x);
+        assert_eq!(r, 4_i32);
+
+        let x = i32x4(-1, -1, -1, -1);
+        let r: i32 = simd_reduce_and(x);
+        assert_eq!(r, -1_i32);
+        let r: i32 = simd_reduce_or(x);
+        assert_eq!(r, -1_i32);
+        let r: i32 = simd_reduce_xor(x);
+        assert_eq!(r, 0_i32);
+
+        let x = i32x4(-1, -1, 0, -1);
+        let r: i32 = simd_reduce_and(x);
+        assert_eq!(r, 0_i32);
+        let r: i32 = simd_reduce_or(x);
+        assert_eq!(r, -1_i32);
+        let r: i32 = simd_reduce_xor(x);
+        assert_eq!(r, -1_i32);
+    }
+
+    unsafe {
+        let x = u32x4(1, 2, 3, 4);
+        let r: u32 = simd_reduce_add_unordered(x);
+        assert_eq!(r, 10_u32);
+        let r: u32 = simd_reduce_mul_unordered(x);
+        assert_eq!(r, 24_u32);
+        let r: u32 = simd_reduce_add_ordered(x, 1);
+        assert_eq!(r, 11_u32);
+        let r: u32 = simd_reduce_mul_ordered(x, 2);
+        assert_eq!(r, 48_u32);
+
+        let r: u32 = simd_reduce_min(x);
+        assert_eq!(r, 1_u32);
+        let r: u32 = simd_reduce_max(x);
+        assert_eq!(r, 4_u32);
+
+        let t = u32::max_value();
+        let x = u32x4(t, t, t, t);
+        let r: u32 = simd_reduce_and(x);
+        assert_eq!(r, t);
+        let r: u32 = simd_reduce_or(x);
+        assert_eq!(r, t);
+        let r: u32 = simd_reduce_xor(x);
+        assert_eq!(r, 0_u32);
+
+        let x = u32x4(t, t, 0, t);
+        let r: u32 = simd_reduce_and(x);
+        assert_eq!(r, 0_u32);
+        let r: u32 = simd_reduce_or(x);
+        assert_eq!(r, t);
+        let r: u32 = simd_reduce_xor(x);
+        assert_eq!(r, t);
+    }
+
+    unsafe {
+        let x = f32x4(1., -2., 3., 4.);
+        let r: f32 = simd_reduce_add_unordered(x);
+        assert_eq!(r, 6_f32);
+        let r: f32 = simd_reduce_mul_unordered(x);
+        assert_eq!(r, -24_f32);
+        // FIXME: only works correctly for accumulator, 0:
+        // https://bugs.llvm.org/show_bug.cgi?id=36734
+        let r: f32 = simd_reduce_add_ordered(x, 0.);
+        assert_eq!(r, 6_f32);
+        // FIXME: only works correctly for accumulator, 1:
+        // https://bugs.llvm.org/show_bug.cgi?id=36734
+        let r: f32 = simd_reduce_mul_ordered(x, 1.);
+        assert_eq!(r, -24_f32);
+
+        let r: f32 = simd_reduce_min(x);
+        assert_eq!(r, -2_f32);
+        let r: f32 = simd_reduce_max(x);
+        assert_eq!(r, 4_f32);
+        let r: f32 = simd_reduce_min_nanless(x);
+        assert_eq!(r, -2_f32);
+        let r: f32 = simd_reduce_max_nanless(x);
+        assert_eq!(r, 4_f32);
+    }
+
+    unsafe {
+        let x = b8x4(!0, !0, !0, !0);
+        let r: bool = simd_reduce_all(x);
+        assert_eq!(r, true);
+        let r: bool = simd_reduce_any(x);
+        assert_eq!(r, true);
+
+        let x = b8x4(!0, !0, 0, !0);
+        let r: bool = simd_reduce_all(x);
+        assert_eq!(r, false);
+        let r: bool = simd_reduce_any(x);
+        assert_eq!(r, true);
+
+        let x = b8x4(0, 0, 0, 0);
+        let r: bool = simd_reduce_all(x);
+        assert_eq!(r, false);
+        let r: bool = simd_reduce_any(x);
+        assert_eq!(r, false);
+    }
+}
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
    |             ^^^^^^
diff --git a/src/test/ui/chalkify/lower_impl.rs b/src/test/ui/chalkify/lower_impl.rs
new file mode 100644 (file)
index 0000000..2083ada
--- /dev/null
@@ -0,0 +1,20 @@
+// 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.
+
+#![feature(rustc_attrs)]
+
+trait Foo { }
+
+#[rustc_dump_program_clauses] //~ ERROR Implemented(T: Foo) :-
+impl<T: 'static> Foo for T where T: Iterator<Item = i32> { }
+
+fn main() {
+    println!("hello");
+}
diff --git a/src/test/ui/chalkify/lower_impl.stderr b/src/test/ui/chalkify/lower_impl.stderr
new file mode 100644 (file)
index 0000000..b5d791d
--- /dev/null
@@ -0,0 +1,8 @@
+error: Implemented(T: Foo) :- ProjectionEq(<T as std::iter::Iterator>::Item == i32), TypeOutlives(T : 'static), Implemented(T: std::iter::Iterator), Implemented(T: std::marker::Sized).
+  --> $DIR/lower_impl.rs:15:1
+   |
+LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(T: Foo) :-
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
index e3a4920d951fd5deb7ef79ad76d9da08ef4c5f5d..c71c28ed62520d23d1b80e2affdff5fc02d55d22 100644 (file)
@@ -10,4 +10,5 @@
 
 fn main() {
     assert!("foo");
+    //~^ ERROR cannot apply unary operator `!`
 }
index 53fde4a628db6c29d2458043f8b616cea9b3d647..2c8a33d95c03a23e57839323ea4f1d5feb7afb90 100644 (file)
@@ -3,8 +3,6 @@ error[E0600]: cannot apply unary operator `!` to type `&'static str`
    |
 LL |     assert!("foo");
    |     ^^^^^^^^^^^^^^^
-   |
-   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
 
 error: aborting due to previous error
 
index a9db5214e6a2eabdc1c8a326373890bb6ef662f1..41a2172d2958024535d5e9e542e01f8e6305087b 100644 (file)
@@ -1,4 +1,4 @@
-error: expected expression, found `_`
+error: expected expression, found reserved identifier `_`
   --> $DIR/underscore.rs:18:9
    |
 LL |         _
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
+
diff --git a/src/test/ui/issue-49074.rs b/src/test/ui/issue-49074.rs
new file mode 100644 (file)
index 0000000..2e7e118
--- /dev/null
@@ -0,0 +1,24 @@
+// 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.
+
+// Check that unknown attribute error is shown even if there are unresolved macros.
+
+#[marco_use] // typo
+//~^ ERROR The attribute `marco_use` is currently unknown to the compiler
+mod foo {
+    macro_rules! bar {
+        () => ();
+    }
+}
+
+fn main() {
+   bar!();
+   //~^ ERROR cannot find macro `bar!`
+}
diff --git a/src/test/ui/issue-49074.stderr b/src/test/ui/issue-49074.stderr
new file mode 100644 (file)
index 0000000..c9984ea
--- /dev/null
@@ -0,0 +1,19 @@
+error: cannot find macro `bar!` in this scope
+  --> $DIR/issue-49074.rs:22:4
+   |
+LL |    bar!();
+   |    ^^^
+   |
+   = help: have you added the `#[macro_use]` on the module/import?
+
+error[E0658]: The attribute `marco_use` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/issue-49074.rs:13:1
+   |
+LL | #[marco_use] // typo
+   | ^^^^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
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`.
diff --git a/src/test/ui/underscore-ident-matcher.rs b/src/test/ui/underscore-ident-matcher.rs
new file mode 100644 (file)
index 0000000..eee9929
--- /dev/null
@@ -0,0 +1,19 @@
+// 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.
+
+macro_rules! identity {
+    ($i: ident) => (
+        $i
+    )
+}
+
+fn main() {
+    let identity!(_) = 10; //~ ERROR no rules expected the token `_`
+}
diff --git a/src/test/ui/underscore-ident-matcher.stderr b/src/test/ui/underscore-ident-matcher.stderr
new file mode 100644 (file)
index 0000000..7f2b6ac
--- /dev/null
@@ -0,0 +1,8 @@
+error: no rules expected the token `_`
+  --> $DIR/underscore-ident-matcher.rs:18:19
+   |
+LL |     let identity!(_) = 10; //~ ERROR no rules expected the token `_`
+   |                   ^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.rs b/src/test/ui/underscore-lifetime/dyn-trait-underscore.rs
new file mode 100644 (file)
index 0000000..c247622
--- /dev/null
@@ -0,0 +1,32 @@
+// 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.
+
+// Check that the `'_` in `dyn Trait + '_` acts like ordinary elision,
+// and not like an object lifetime default.
+//
+// cc #48468
+
+#![feature(dyn_trait)]
+#![feature(underscore_lifetimes)]
+
+fn a<T>(items: &[T]) -> Box<dyn Iterator<Item=&T>> {
+    //                      ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static`
+    Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime
+}
+
+fn b<T>(items: &[T]) -> Box<dyn Iterator<Item=&T> + '_> {
+    Box::new(items.iter()) // OK, equivalent to c
+}
+
+fn c<'a, T>(items: &'a [T]) -> Box<dyn Iterator<Item=&'a T> + 'a> {
+    Box::new(items.iter()) // OK, equivalent to b
+}
+
+fn main() { }
diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr
new file mode 100644 (file)
index 0000000..cb3035f
--- /dev/null
@@ -0,0 +1,27 @@
+error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
+  --> $DIR/dyn-trait-underscore.rs:21:20
+   |
+LL |     Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime
+   |                    ^^^^
+   |
+note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the function body at 19:1...
+  --> $DIR/dyn-trait-underscore.rs:19:1
+   |
+LL | / fn a<T>(items: &[T]) -> Box<dyn Iterator<Item=&T>> {
+LL | |     //                      ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static`
+LL | |     Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime
+LL | | }
+   | |_^
+note: ...so that reference does not outlive borrowed content
+  --> $DIR/dyn-trait-underscore.rs:21:14
+   |
+LL |     Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime
+   |              ^^^^^
+   = note: but, the lifetime must be valid for the static lifetime...
+   = note: ...so that the expression is assignable:
+           expected std::boxed::Box<std::iter::Iterator<Item=&T> + 'static>
+              found std::boxed::Box<std::iter::Iterator<Item=&T>>
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0495`.
index 5f83bb4044f32b60d06717c609610f67411fc671..d10ec661b06420654bbc4ed0ccd32295698aa1dc 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 5f83bb4044f32b60d06717c609610f67411fc671
+Subproject commit d10ec661b06420654bbc4ed0ccd32295698aa1dc
index d5e233a720495c52af25d8f6dcc9e55e1193beb9..4edd140e57cce900fa930e1439bab469f5bbce46 160000 (submodule)
@@ -1 +1 @@
-Subproject commit d5e233a720495c52af25d8f6dcc9e55e1193beb9
+Subproject commit 4edd140e57cce900fa930e1439bab469f5bbce46
index 61833b9aeab8bf8f0c0c0e42b7c96b6eceb37d0d..d4712ca37500f26bbcbf97edcb27820717f769f7 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 61833b9aeab8bf8f0c0c0e42b7c96b6eceb37d0d
+Subproject commit d4712ca37500f26bbcbf97edcb27820717f769f7
index b6c52443424977bd92cf7ed127f7771fe9c285da..567fb6d74cca9ccbfae2440c688035400b51e3c6 160000 (submodule)
@@ -1 +1 @@
-Subproject commit b6c52443424977bd92cf7ed127f7771fe9c285da
+Subproject commit 567fb6d74cca9ccbfae2440c688035400b51e3c6
index 346238f49740d6c98102a6a59811b1625c73a9d7..87180d9065e7c8070c0ba46eb48ddf8779ef89ac 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 346238f49740d6c98102a6a59811b1625c73a9d7
+Subproject commit 87180d9065e7c8070c0ba46eb48ddf8779ef89ac