]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #48570 - Amanieu:aarch64_features, r=alexcrichton
authorkennytm <kennytm@gmail.com>
Thu, 1 Mar 2018 13:37:18 +0000 (21:37 +0800)
committerManish Goregaokar <manishsmail@gmail.com>
Thu, 1 Mar 2018 17:29:43 +0000 (09:29 -0800)
Add AArch64 features to whitelist

86 files changed:
.travis.yml
README.md
src/Cargo.lock
src/bootstrap/builder.rs
src/bootstrap/compile.rs
src/bootstrap/test.rs
src/ci/docker/x86_64-gnu-tools/Dockerfile
src/ci/docker/x86_64-gnu-tools/checkregression.py [new file with mode: 0755]
src/ci/docker/x86_64-gnu-tools/checktools.sh
src/doc/man/rustc.1
src/doc/unstable-book/src/compiler-flags/remap-path-prefix.md [deleted file]
src/libcore/iter/iterator.rs
src/libcore/panicking.rs
src/libpanic_unwind/gcc.rs
src/libpanic_unwind/lib.rs
src/libpanic_unwind/seh64_gnu.rs
src/libpanic_unwind/windows.rs
src/libproc_macro/lib.rs
src/librustc/hir/lowering.rs
src/librustc/lib.rs
src/librustc/lint/builtin.rs
src/librustc/lint/context.rs
src/librustc/lint/levels.rs
src/librustc/lint/mod.rs
src/librustc/session/config.rs
src/librustc/session/mod.rs
src/librustc/ty/context.rs
src/librustc_driver/driver.rs
src/librustc_driver/lib.rs
src/librustc_lint/builtin.rs
src/librustc_lint/lib.rs
src/librustc_metadata/encoder.rs
src/librustc_mir/build/mod.rs
src/librustc_mir/lib.rs
src/librustc_mir/transform/mod.rs
src/librustc_mir/transform/uniform_array_move_out.rs
src/librustc_resolve/diagnostics.rs
src/librustc_resolve/lib.rs
src/librustc_trans/mir/mod.rs
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/wfcheck.rs
src/librustc_typeck/diagnostics.rs
src/libstd/io/stdio.rs
src/libstd/panicking.rs
src/libstd/path.rs
src/libstd/thread/local.rs
src/libstd/thread/mod.rs
src/libsyntax/ast.rs
src/libsyntax/attr.rs
src/libsyntax/codemap.rs
src/libsyntax/diagnostic_list.rs
src/libsyntax/feature_gate.rs
src/libsyntax/fold.rs
src/libsyntax/parse/parser.rs
src/libsyntax/print/pprust.rs
src/libsyntax/visit.rs
src/libsyntax_pos/lib.rs
src/libunwind/libunwind.rs
src/test/codegen/extern-functions.rs
src/test/codegen/remap_path_prefix/auxiliary/remap_path_prefix_aux.rs
src/test/codegen/remap_path_prefix/main.rs
src/test/compile-fail/trait-bounds-not-on-struct.rs
src/test/incremental/remapped_paths_cc/auxiliary/extern_crate.rs
src/test/mir-opt/uniform_array_move_out.rs
src/test/parse-fail/pat-tuple-2.rs
src/test/parse-fail/pat-tuple-6.rs [deleted file]
src/test/run-make/longjmp-across-rust/Makefile [new file with mode: 0644]
src/test/run-make/longjmp-across-rust/foo.c [new file with mode: 0644]
src/test/run-make/longjmp-across-rust/main.rs [new file with mode: 0644]
src/test/run-pass/abort-on-c-abi.rs
src/test/run-pass/defaults-well-formedness.rs [new file with mode: 0644]
src/test/run-pass/issue-48508-aux.rs [new file with mode: 0644]
src/test/run-pass/issue-48508.rs [new file with mode: 0644]
src/test/run-pass/issue-48551.rs [new file with mode: 0644]
src/test/run-pass/pat-tuple-7.rs [new file with mode: 0644]
src/test/run-pass/tls-init-on-init.rs
src/test/run-pass/tls-try-with.rs
src/test/run-pass/type-macros-simple.rs
src/test/ui/error-codes/E0404.rs
src/test/ui/error-codes/E0404.stderr
src/test/ui/feature-gate-pattern_parentheses.rs [new file with mode: 0644]
src/test/ui/feature-gate-pattern_parentheses.stderr [new file with mode: 0644]
src/test/ui/type-check-defaults.rs [new file with mode: 0644]
src/test/ui/type-check-defaults.stderr [new file with mode: 0644]
src/tools/publish_toolstate.py
src/tools/rls

index 280da056995068fd58d6a8e1082f94f3d88be2f9..0d8641e45ed157b90b56fb3dd940ad611b89da99 100644 (file)
@@ -188,7 +188,7 @@ matrix:
       script:
         MESSAGE_FILE=$(mktemp -t msg.XXXXXX);
         . src/ci/docker/x86_64-gnu-tools/repo.sh;
-        commit_toolstate_change "$MESSAGE_FILE" "$TRAVIS_BUILD_DIR/src/tools/publish_toolstate.py" "$(git rev-parse HEAD)" "$(git log --format=%s -n1 HEAD)" "$MESSAGE_FILE"
+        commit_toolstate_change "$MESSAGE_FILE" "$TRAVIS_BUILD_DIR/src/tools/publish_toolstate.py" "$(git rev-parse HEAD)" "$(git log --format=%s -n1 HEAD)" "$MESSAGE_FILE" "$TOOLSTATE_REPO_ACCESS_TOKEN";
 
 env:
   global:
index fd35606ec0dbb21ccad4ba00f59d5f983f3ef843..e78bbb82711abdcf48b909cf6a88fa6616b20cfa 100644 (file)
--- a/README.md
+++ b/README.md
@@ -233,7 +233,7 @@ find out how various parts of the compiler work.
 [IRC]: https://en.wikipedia.org/wiki/Internet_Relay_Chat
 [#rust]: irc://irc.mozilla.org/rust
 [#rust-beginners]: irc://irc.mozilla.org/rust-beginners
-[rustc-guide]: https://rust-lang-nursery.github.io/rustc-guide/about-this-guide.html
+[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/about-this-guide.html
 
 ## License
 [license]: #license
index 8f25820d3a5278a4d5a866b17033bcbccceea5c6..53744dca0a01229a8bf48f5f52f4bf1d12c982a6 100644 (file)
@@ -68,6 +68,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 name = "arena"
 version = "0.0.0"
 
+[[package]]
+name = "arrayvec"
+version = "0.4.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "atty"
 version = "0.2.6"
@@ -356,15 +364,6 @@ dependencies = [
  "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
-[[package]]
-name = "coco"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "commoncrypto"
 version = "0.2.0"
@@ -468,6 +467,37 @@ name = "crossbeam"
 version = "0.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "crossbeam-deque"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "crossbeam-epoch 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "crossbeam-epoch"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "crossbeam-utils"
+version = "0.2.2"
+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)",
+]
+
 [[package]]
 name = "crypto-hash"
 version = "0.3.0"
@@ -1113,6 +1143,11 @@ dependencies = [
  "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "memoffset"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "miniz-sys"
 version = "0.1.10"
@@ -1176,6 +1211,11 @@ dependencies = [
  "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "nodrop"
+version = "0.1.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "num"
 version = "0.1.41"
@@ -1443,16 +1483,25 @@ version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rayon-core 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rayon-core 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "rayon"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rayon-core 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rayon-core"
-version = "1.3.0"
+version = "1.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "coco 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "crossbeam-deque 0.2.0 (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.36 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1523,9 +1572,10 @@ version = "0.1.0"
 
 [[package]]
 name = "rls"
-version = "0.125.0"
+version = "0.126.0"
 dependencies = [
  "cargo 0.26.0",
+ "cargo_metadata 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "clippy_lints 0.0.186 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1536,13 +1586,13 @@ dependencies = [
  "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)",
  "racer 2.0.12 (registry+https://github.com/rust-lang/crates.io-index)",
- "rayon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rls-analysis 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rayon 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rls-analysis 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-blacklist 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-data 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-rustc 0.2.1 (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.4 (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.3.8",
  "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1552,7 +1602,7 @@ dependencies = [
 
 [[package]]
 name = "rls-analysis"
-version = "0.11.0"
+version = "0.11.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "derive-new 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1596,7 +1646,7 @@ dependencies = [
 
 [[package]]
 name = "rls-vfs"
-version = "0.4.4"
+version = "0.4.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "racer 2.0.12 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2775,6 +2825,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "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 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.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8352656fd42c30a0c3c89d26dea01e3b77c0ab2af18230835c15e2e13cd51859"
 "checksum backtrace 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ebbbf59b1c43eefa8c3ede390fcc36820b4999f7914104015be25025e0d62af2"
 "checksum backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "44585761d6161b0f57afc49482ab6bd067e4edef48c12a152c237eb0203f7661"
@@ -2791,7 +2842,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum clap 2.29.0 (registry+https://github.com/rust-lang/crates.io-index)" = "110d43e343eb29f4f51c1db31beb879d546db27998577e5715270a54bcf41d3f"
 "checksum clippy_lints 0.0.186 (registry+https://github.com/rust-lang/crates.io-index)" = "a3864104a4e6092e644b985dd7543e5f24e99aa7262f5ee400bcb17cfeec1bf5"
 "checksum cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)" = "56d741ea7a69e577f6d06b36b7dff4738f680593dc27a701ffa8506b73ce28bb"
-"checksum coco 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c06169f5beb7e31c7c67ebf5540b8b472d23e3eade3b2ec7d1f5b504a85f91bd"
 "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"
@@ -2799,6 +2849,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum core-foundation-sys 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "152195421a2e6497a8179195672e9d4ee8e45ed8c465b626f1606d27a08ebcd5"
 "checksum crossbeam 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "bd66663db5a988098a89599d4857919b3acf7f61402e61365acfd3919857b9be"
 "checksum crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "24ce9782d4d5c53674646a6a4c1863a21a8fc0cb649b3c94dfc16e45071dea19"
+"checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3"
+"checksum crossbeam-epoch 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "59796cc6cbbdc6bb319161349db0c3250ec73ec7fcb763a51065ec4e2e158552"
+"checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9"
 "checksum crypto-hash 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "34903878eec1694faf53cae8473a088df333181de421d4d3d48061d6559fe602"
 "checksum curl 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b70fd6394677d3c0e239ff4be6f2b3176e171ffd1c23ffdc541e78dea2b8bb5e"
 "checksum curl-sys 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f46e49c7125131f5afaded06944d6888b55cbdf8eba05dae73c954019b907961"
@@ -2863,11 +2916,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum mdbook 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fef236caad7ba3b5b3944df946f19ab3e190bca53c111dd00fe05fa8d879f2fd"
 "checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20"
 "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 net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)" = "3a80f842784ef6c9a958b68b7516bc7e35883c614004dd94959a4dca1b716c09"
 "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.41 (registry+https://github.com/rust-lang/crates.io-index)" = "cc4083e14b542ea3eb9b5f33ff48bd373a92d78687e74f4cc0a30caeb754f0ca"
 "checksum num-bigint 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "bdc1494b5912f088f260b775799468d9b9209ac60885d8186a547a0476289e23"
 "checksum num-complex 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "58de7b4bf7cf5dbecb635a5797d489864eadd03b107930cbccf9e0fd7428b47c"
@@ -2896,19 +2951,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum radix_trie 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "211c49b6a9995cac0fd1dd9ca60b42cf3a51e151a12eb954b3a9e75513426ee8"
 "checksum rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)" = "512870020642bb8c221bf68baa1b2573da814f6ccfe5c9699b1c303047abe9b1"
 "checksum rayon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ed02d09394c94ffbdfdc755ad62a132e94c3224a8354e78a1200ced34df12edf"
-"checksum rayon-core 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e64b609139d83da75902f88fd6c01820046840a18471e4dfcd5ac7c0f46bea53"
+"checksum rayon 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "485541959c8ecc49865526fe6c4de9653dd6e60d829d6edf0be228167b60372d"
+"checksum rayon-core 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9d24ad214285a7729b174ed6d3bcfcb80177807f959d95fafd5bfc5c4f201ac8"
 "checksum redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "0d92eecebad22b767915e4d529f89f28ee96dbbf5a4810d2b844373f136417fd"
 "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
 "checksum regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f"
 "checksum regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "744554e01ccbd98fff8c457c3b092cd67af62a555a43bfe97ae8a0451f7799fa"
 "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 rls-analysis 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "30b08808959205a5cf23c68ace2d9d6defdd6867f3cd5d62981cf50fb52f8882"
+"checksum rls-analysis 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39461c31c9ec26c2f15821d6aaa349216bf71e24e69550d9f8eeded78dc435e1"
 "checksum rls-blacklist 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "56fb7b8e4850b988fbcf277fbdb1eff36879070d02fc1ca243b559273866973d"
 "checksum rls-data 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bea04462e94b5512a78499837eecb7db182ff082144cd1b4bc32ef5d43de6510"
 "checksum rls-rustc 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "85cfb9dde19e313da3e47738008f8a472e470cc42d910b71595a9238494701f2"
 "checksum rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d7c7046dc6a92f2ae02ed302746db4382e75131b9ce20ce967259f6b5867a6a"
-"checksum rls-vfs 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ffd34691a510938bb67fe0444fb363103c73ffb31c121d1e16bc92d8945ea8ff"
+"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"
index b5946b44e05ef6316ab5881d7250f1e923548b61..1df85323c41ef203ebbc4899d93bb24a60606737 100644 (file)
@@ -231,7 +231,7 @@ pub struct ShouldRun<'a> {
     paths: BTreeSet<PathSet>,
 
     // If this is a default rule, this is an additional constraint placed on
-    // it's run. Generally something like compiler docs being enabled.
+    // its run. Generally something like compiler docs being enabled.
     is_really_default: bool,
 }
 
@@ -326,7 +326,9 @@ macro_rules! describe {
                 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::Docs, test::ErrorIndex, test::Distcheck,
+                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),
             Kind::Bench => describe!(test::Crate, test::CrateLibrustc),
             Kind::Doc => describe!(doc::UnstableBook, doc::UnstableBookGen, doc::TheBook,
index 2c9f0ddb6c33d197f8bd05df8ef36359a4abb5f4..408d63be6c6bfeed21bbeadfe722bb66f9b220d3 100644 (file)
@@ -629,6 +629,8 @@ fn run(self, builder: &Builder) {
             .arg(build.src.join("src/librustc_trans/Cargo.toml"));
         rustc_cargo_env(build, &mut cargo);
 
+        let _folder = build.fold_output(|| format!("stage{}-rustc_trans", compiler.stage));
+
         match &*self.backend {
             "llvm" | "emscripten" => {
                 // Build LLVM for our target. This will implicitly build the
@@ -642,7 +644,6 @@ fn run(self, builder: &Builder) {
                     features.push_str(" emscripten");
                 }
 
-                let _folder = build.fold_output(|| format!("stage{}-rustc_trans", compiler.stage));
                 println!("Building stage{} codegen artifacts ({} -> {}, {})",
                          compiler.stage, &compiler.host, target, self.backend);
 
index bd8c36a296c095d8772ce29f1633f8c173bf52a2..b27ddfdbc5e583e2a3a91dfe7907390caf412e74 100644 (file)
@@ -78,15 +78,17 @@ fn try_run(build: &Build, cmd: &mut Command) -> bool {
     true
 }
 
-fn try_run_quiet(build: &Build, cmd: &mut Command) {
+fn try_run_quiet(build: &Build, cmd: &mut Command) -> bool {
     if !build.fail_fast {
         if !build.try_run_quiet(cmd) {
             let mut failures = build.delayed_failures.borrow_mut();
             failures.push(format!("{:?}", cmd));
+            return false;
         }
     } else {
         build.run_quiet(cmd);
     }
+    true
 }
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
@@ -994,23 +996,19 @@ fn run(self, builder: &Builder) {
 }
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
-pub struct Docs {
+struct DocTest {
     compiler: Compiler,
+    path: &'static str,
+    name: &'static str,
+    is_ext_doc: bool,
 }
 
-impl Step for Docs {
+impl Step for DocTest {
     type Output = ();
-    const DEFAULT: bool = true;
     const ONLY_HOSTS: bool = true;
 
     fn should_run(run: ShouldRun) -> ShouldRun {
-        run.path("src/doc")
-    }
-
-    fn make_run(run: RunConfig) {
-        run.builder.ensure(Docs {
-            compiler: run.builder.compiler(run.builder.top_stage, run.host),
-        });
+        run.never()
     }
 
     /// Run `rustdoc --test` for all documentation in `src/doc`.
@@ -1026,9 +1024,9 @@ fn run(self, builder: &Builder) {
 
         // Do a breadth-first traversal of the `src/doc` directory and just run
         // tests for all files that end in `*.md`
-        let mut stack = vec![build.src.join("src/doc")];
+        let mut stack = vec![build.src.join(self.path)];
         let _time = util::timeit();
-        let _folder = build.fold_output(|| "test_docs");
+        let _folder = build.fold_output(|| format!("test_{}", self.name));
 
         while let Some(p) = stack.pop() {
             if p.is_dir() {
@@ -1046,11 +1044,64 @@ fn run(self, builder: &Builder) {
                 continue;
             }
 
-            markdown_test(builder, compiler, &p);
+            let test_result = markdown_test(builder, compiler, &p);
+            if self.is_ext_doc {
+                let toolstate = if test_result {
+                    ToolState::TestPass
+                } else {
+                    ToolState::TestFail
+                };
+                build.save_toolstate(self.name, toolstate);
+            }
         }
     }
 }
 
+macro_rules! test_book {
+    ($($name:ident, $path:expr, $book_name:expr, default=$default:expr;)+) => {
+        $(
+            #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+            pub struct $name {
+                compiler: Compiler,
+            }
+
+            impl Step for $name {
+                type Output = ();
+                const DEFAULT: bool = $default;
+                const ONLY_HOSTS: bool = true;
+
+                fn should_run(run: ShouldRun) -> ShouldRun {
+                    run.path($path)
+                }
+
+                fn make_run(run: RunConfig) {
+                    run.builder.ensure($name {
+                        compiler: run.builder.compiler(run.builder.top_stage, run.host),
+                    });
+                }
+
+                fn run(self, builder: &Builder) {
+                    builder.ensure(DocTest {
+                        compiler: self.compiler,
+                        path: $path,
+                        name: $book_name,
+                        is_ext_doc: !$default,
+                    });
+                }
+            }
+        )+
+    }
+}
+
+test_book!(
+    Nomicon, "src/doc/nomicon", "nomicon", default=false;
+    Reference, "src/doc/reference", "reference", default=false;
+    RustdocBook, "src/doc/rustdoc", "rustdoc", default=true;
+    RustByExample, "src/doc/rust-by-example", "rust-by-example", default=false;
+    TheBook, "src/doc/book", "book", default=false;
+    UnstableBook, "src/doc/unstable-book", "unstable-book", default=true;
+);
+
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
 pub struct ErrorIndex {
     compiler: Compiler,
@@ -1101,13 +1152,13 @@ fn run(self, builder: &Builder) {
     }
 }
 
-fn markdown_test(builder: &Builder, compiler: Compiler, markdown: &Path) {
+fn markdown_test(builder: &Builder, compiler: Compiler, markdown: &Path) -> bool {
     let build = builder.build;
     let mut file = t!(File::open(markdown));
     let mut contents = String::new();
     t!(file.read_to_string(&mut contents));
     if !contents.contains("```") {
-        return;
+        return true;
     }
 
     println!("doc tests for: {}", markdown.display());
@@ -1121,9 +1172,9 @@ fn markdown_test(builder: &Builder, compiler: Compiler, markdown: &Path) {
     cmd.arg("--test-args").arg(test_args);
 
     if build.config.quiet_tests {
-        try_run_quiet(build, &mut cmd);
+        try_run_quiet(build, &mut cmd)
     } else {
-        try_run(build, &mut cmd);
+        try_run(build, &mut cmd)
     }
 }
 
index 8975d419d2055e01f5a5ea5a79e89fe8a13ae809..bab9145cbcb9c78ed68ee5c5a06fdf28cca932a6 100644 (file)
@@ -17,6 +17,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
+COPY x86_64-gnu-tools/checkregression.py /tmp/
 COPY x86_64-gnu-tools/checktools.sh /tmp/
 COPY x86_64-gnu-tools/repo.sh /tmp/
 
diff --git a/src/ci/docker/x86_64-gnu-tools/checkregression.py b/src/ci/docker/x86_64-gnu-tools/checkregression.py
new file mode 100755 (executable)
index 0000000..df791d1
--- /dev/null
@@ -0,0 +1,40 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# 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.
+
+import sys
+import json
+
+if __name__ == '__main__':
+    os_name = sys.argv[1]
+    toolstate_file = sys.argv[2]
+    current_state = sys.argv[3]
+
+    with open(toolstate_file, 'r') as f:
+        toolstate = json.load(f)
+    with open(current_state, 'r') as f:
+        current = json.load(f)
+
+    regressed = False
+    for cur in current:
+        tool = cur['tool']
+        state = cur[os_name]
+        new_state = toolstate.get(tool, '')
+        if new_state < state:
+            print(
+                'Error: The state of "{}" has regressed from "{}" to "{}"'
+                .format(tool, state, new_state)
+            )
+            regressed = True
+
+    if regressed:
+        sys.exit(1)
index 61bb5a84d21ac150e5f15cb7e7e9610d4ab6debb..da89aa9423b2daa18cf9a9bc500fd63c717ecc64 100755 (executable)
@@ -17,11 +17,18 @@ TOOLSTATE_FILE="$(realpath $2)"
 OS="$3"
 COMMIT="$(git rev-parse HEAD)"
 CHANGED_FILES="$(git diff --name-status HEAD HEAD^)"
+SIX_WEEK_CYCLE="$(( ($(date +%s) / 604800 - 3) % 6 ))"
+# ^ 1970 Jan 1st is a Thursday, and our release dates are also on Thursdays,
+#   thus we could divide by 604800 (7 days in seconds) directly.
 
 touch "$TOOLSTATE_FILE"
 
 set +e
 python2.7 "$X_PY" test --no-fail-fast \
+    src/doc/book \
+    src/doc/nomicon \
+    src/doc/reference \
+    src/doc/rust-by-example \
     src/tools/rls \
     src/tools/rustfmt \
     src/tools/miri \
@@ -29,27 +36,38 @@ python2.7 "$X_PY" test --no-fail-fast \
 set -e
 
 cat "$TOOLSTATE_FILE"
+echo
 
-# If this PR is intended to update one of these tools, do not let the build pass
-# when they do not test-pass.
-for TOOL in rls rustfmt clippy; do
-    echo "Verifying status of $TOOL..."
-    if echo "$CHANGED_FILES" | grep -q "^M[[:blank:]]src/tools/$TOOL$"; then
-        echo "This PR updated 'src/tools/$TOOL', verifying if status is 'test-pass'..."
-        if grep -vq '"'"$TOOL"'[^"]*":"test-pass"' "$TOOLSTATE_FILE"; then
+verify_status() {
+    echo "Verifying status of $1..."
+    if echo "$CHANGED_FILES" | grep -q "^M[[:blank:]]$2$"; then
+        echo "This PR updated '$2', verifying if status is 'test-pass'..."
+        if grep -vq '"'"$1"'":"test-pass"' "$TOOLSTATE_FILE"; then
             echo
-            echo "โš ๏ธ We detected that this PR updated '$TOOL', but its tests failed."
+            echo "โš ๏ธ We detected that this PR updated '$1', but its tests failed."
             echo
-            echo "If you do intend to update '$TOOL', please check the error messages above and"
+            echo "If you do intend to update '$1', please check the error messages above and"
             echo "commit another update."
             echo
-            echo "If you do NOT intend to update '$TOOL', please ensure you did not accidentally"
-            echo "change the submodule at 'src/tools/$TOOL'. You may ask your reviewer for the"
+            echo "If you do NOT intend to update '$1', please ensure you did not accidentally"
+            echo "change the submodule at '$2'. You may ask your reviewer for the"
             echo "proper steps."
             exit 3
         fi
     fi
-done
+}
+
+# If this PR is intended to update one of these tools, do not let the build pass
+# when they do not test-pass.
+
+verify_status book src/doc/book
+verify_status nomicon src/doc/nomicon
+verify_status reference src/doc/reference
+verify_status rust-by-example src/doc/rust-by-example
+verify_status rls src/tool/rls
+verify_status rustfmt src/tool/rustfmt
+verify_status clippy-driver src/tool/clippy
+#verify_status miri src/tool/miri
 
 if [ "$RUST_RELEASE_CHANNEL" = nightly -a -n "${TOOLSTATE_REPO_ACCESS_TOKEN+is_set}" ]; then
     . "$(dirname $0)/repo.sh"
@@ -59,6 +77,11 @@ if [ "$RUST_RELEASE_CHANNEL" = nightly -a -n "${TOOLSTATE_REPO_ACCESS_TOKEN+is_s
         sed -i "1 a\\
 $COMMIT\t$(cat "$TOOLSTATE_FILE")
 " "history/$OS.tsv"
+    # if we are at the last week in the 6-week release cycle, reject any kind of regression.
+    if [ $SIX_WEEK_CYCLE -eq 5 ]; then
+        python2.7 "$(dirname $0)/checkregression.py" \
+            "$OS" "$TOOLSTATE_FILE" "rust-toolstate/_data/latest.json"
+    fi
     rm -f "$MESSAGE_FILE"
     exit 0
 fi
index 19f6cc9ac619d0d677392ce548efead407789349..39d105399594535a5f0885e67369a796f918e696 100644 (file)
@@ -125,6 +125,16 @@ Print version info and exit.
 \fB\-v\fR, \fB\-\-verbose\fR
 Use verbose output.
 .TP
+\fB\-\-remap\-path\-prefix\fR \fIfrom\fR=\fIto\fR
+Remap source path prefixes in all output, including compiler diagnostics, debug information,
+macro expansions, etc. The \fIfrom\fR=\fIto\fR parameter is scanned from right to left, so \fIfrom\fR
+may contain '=', but \fIto\fR may not.
+
+This is useful for normalizing build products, for example by removing the current directory out of
+pathnames emitted into the object files. The replacement is purely textual, with no consideration of
+the current system's pathname syntax. For example \fI\-\-remap\-path\-prefix foo=bar\fR will
+match \fBfoo/lib.rs\fR but not \fB./foo/lib.rs\fR.
+.TP
 \fB\-\-extern\fR \fINAME\fR=\fIPATH\fR
 Specify where an external rust library is located. These should match
 \fIextern\fR declarations in the crate's source code.
diff --git a/src/doc/unstable-book/src/compiler-flags/remap-path-prefix.md b/src/doc/unstable-book/src/compiler-flags/remap-path-prefix.md
deleted file mode 100644 (file)
index 8ca04d2..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-# `remap-path-prefix`
-
-The tracking issue for this feature is: [#41555](https://github.com/rust-lang/rust/issues/41555)
-
-------------------------
-
-The `-Z remap-path-prefix-from`, `-Z remap-path-prefix-to` commandline option
-pair allows to replace prefixes of any file paths the compiler emits in various
-places. This is useful for bringing debuginfo paths into a well-known form and
-for achieving reproducible builds independent of the directory the compiler was
-executed in. All paths emitted by the compiler are affected, including those in
-error messages.
-
-In order to map all paths starting with `/home/foo/my-project/src` to
-`/sources/my-project`, one would invoke the compiler as follows:
-
-```text
-rustc -Zremap-path-prefix-from="/home/foo/my-project/src" -Zremap-path-prefix-to="/sources/my-project"
-```
-
-Debuginfo for code from the file `/home/foo/my-project/src/foo/mod.rs`,
-for example, would then point debuggers to `/sources/my-project/foo/mod.rs`
-instead of the original file.
-
-The options can be specified multiple times when multiple prefixes should be
-mapped:
-
-```text
-rustc -Zremap-path-prefix-from="/home/foo/my-project/src" \
-      -Zremap-path-prefix-to="/sources/my-project" \
-      -Zremap-path-prefix-from="/home/foo/my-project/build-dir" \
-      -Zremap-path-prefix-to="/stable-build-dir"
-```
-
-When the options are given multiple times, the nth `-from` will be matched up
-with the nth `-to` and they can appear anywhere on the commandline. Mappings
-specified later on the line will take precedence over earlier ones.
index 9d8a71250f88ad508c561d08d05d9e45ea1079e5..b06534c9c1ec9c29ed9051ce118d91826fff1ed9 100644 (file)
@@ -1062,8 +1062,8 @@ fn flat_map<U, F>(self, f: F) -> FlatMap<Self, U, F>
     /// assert_eq!(merged, "alphabetagamma");
     /// ```
     ///
-    /// You can also rewrite this in terms of [`flat_map()`] which is preferable
-    /// in this case since that conveys intent clearer:
+    /// You can also rewrite this in terms of [`flat_map()`], which is preferable
+    /// in this case since it conveys intent more clearly:
     ///
     /// ```
     /// let words = ["alpha", "beta", "gamma"];
index 4170d91e5fce274fcde59ba2ed64abf45ea08a2c..94db0baa3f95f883f9eb73855ce0c0ff24b939fa 100644 (file)
@@ -64,7 +64,8 @@ pub fn panic_fmt(fmt: fmt::Arguments, file_line_col: &(&'static str, u32, u32))
     #[allow(improper_ctypes)]
     extern {
         #[lang = "panic_fmt"]
-        #[unwind]
+        #[cfg_attr(stage0, unwind)]
+        #[cfg_attr(not(stage0), unwind(allowed))]
         fn panic_impl(fmt: fmt::Arguments, file: &'static str, line: u32, col: u32) -> !;
     }
     let (file, line, col) = *file_line_col;
index 63e44f71a3a8f3d7249b084cd79e97fcd159580f..ca2fd561cadcfcc75d9bb719cc5937fee4227b31 100644 (file)
@@ -286,7 +286,8 @@ unsafe fn find_eh_action(context: *mut uw::_Unwind_Context)
 // See docs in the `unwind` module.
 #[cfg(all(target_os="windows", target_arch = "x86", target_env="gnu"))]
 #[lang = "eh_unwind_resume"]
-#[unwind]
+#[cfg_attr(stage0, unwind)]
+#[cfg_attr(not(stage0), unwind(allowed))]
 unsafe extern "C" fn rust_eh_unwind_resume(panic_ctx: *mut u8) -> ! {
     uw::_Unwind_Resume(panic_ctx as *mut uw::_Unwind_Exception);
 }
index 92e40e8f26d40d646221b720edc1af9035ac35f2..a5cebc3e4d04b6eee6b74854f82d1146508878d9 100644 (file)
 // Entry point for raising an exception, just delegates to the platform-specific
 // implementation.
 #[no_mangle]
-#[unwind]
+#[cfg_attr(stage0, unwind)]
+#[cfg_attr(not(stage0), unwind(allowed))]
 pub unsafe extern "C" fn __rust_start_panic(data: usize, vtable: usize) -> u32 {
     imp::panic(mem::transmute(raw::TraitObject {
         data: data as *mut (),
index 0a9fa7d9a80b44e637cb453dcc6df449a0c82847..090cd095380ee8dfcaffdaeb3600e664130105b3 100644 (file)
@@ -108,7 +108,8 @@ pub unsafe fn cleanup(ptr: *mut u8) -> Box<Any + Send> {
 }
 
 #[lang = "eh_unwind_resume"]
-#[unwind]
+#[cfg_attr(stage0, unwind)]
+#[cfg_attr(not(stage0), unwind(allowed))]
 unsafe extern "C" fn rust_eh_unwind_resume(panic_ctx: c::LPVOID) -> ! {
     let params = [panic_ctx as c::ULONG_PTR];
     c::RaiseException(RUST_PANIC,
index a7e90071ceae87386524cc92450d6f831341dbbf..50fba5faee747facb0f1309ebd900411f912982e 100644 (file)
@@ -79,18 +79,21 @@ pub enum EXCEPTION_DISPOSITION {
 pub use self::EXCEPTION_DISPOSITION::*;
 
 extern "system" {
-    #[unwind]
+    #[cfg_attr(stage0, unwind)]
+    #[cfg_attr(not(stage0), unwind(allowed))]
     pub fn RaiseException(dwExceptionCode: DWORD,
                           dwExceptionFlags: DWORD,
                           nNumberOfArguments: DWORD,
                           lpArguments: *const ULONG_PTR);
-    #[unwind]
+    #[cfg_attr(stage0, unwind)]
+    #[cfg_attr(not(stage0), unwind(allowed))]
     pub fn RtlUnwindEx(TargetFrame: LPVOID,
                        TargetIp: LPVOID,
                        ExceptionRecord: *const EXCEPTION_RECORD,
                        ReturnValue: LPVOID,
                        OriginalContext: *const CONTEXT,
                        HistoryTable: *const UNWIND_HISTORY_TABLE);
-    #[unwind]
+    #[cfg_attr(stage0, unwind)]
+    #[cfg_attr(not(stage0), unwind(allowed))]
     pub fn _CxxThrowException(pExceptionObject: *mut c_void, pThrowInfo: *mut u8);
 }
index 878a536836d23a4450e092fa3505a20c6a706248..b18bb5a24b695dce2a29686ca243bbd141a78e6f 100644 (file)
@@ -316,7 +316,7 @@ impl SourceFile {
     /// If the code span associated with this `SourceFile` was generated by an external macro, this
     /// may not be an actual path on the filesystem. Use [`is_real`] to check.
     ///
-    /// Also note that even if `is_real` returns `true`, if `-Z remap-path-prefix-*` was passed on
+    /// Also note that even if `is_real` returns `true`, if `--remap-path-prefix` was passed on
     /// the command line, the path as given may not actually be valid.
     ///
     /// [`is_real`]: #method.is_real
index 89ed47ea194fb7e51859e9748946561b024046d6..a41ac5bceed27d51b8813e56afb5fe83e23b2239 100644 (file)
@@ -46,7 +46,7 @@
 use hir::map::{Definitions, DefKey, DefPathData};
 use hir::def_id::{DefIndex, DefId, CRATE_DEF_INDEX, DefIndexAddressSpace};
 use hir::def::{Def, PathResolution};
-use lint::builtin::PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES;
+use lint::builtin::{self, PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES};
 use middle::cstore::CrateStore;
 use rustc_data_structures::indexed_vec::IndexVec;
 use session::Session;
@@ -912,7 +912,11 @@ fn lower_ty(&mut self, t: &Ty, itctx: ImplTraitContext) -> P<hir::Ty> {
             TyKind::Path(ref qself, ref path) => {
                 let id = self.lower_node_id(t.id);
                 let qpath = self.lower_qpath(t.id, qself, path, ParamMode::Explicit, itctx);
-                return self.ty_path(id, t.span, qpath);
+                let ty = self.ty_path(id, t.span, qpath);
+                if let hir::TyTraitObject(..) = ty.node {
+                    self.maybe_lint_bare_trait(t.span, t.id, qself.is_none() && path.is_global());
+                }
+                return ty;
             }
             TyKind::ImplicitSelf => {
                 hir::TyPath(hir::QPath::Resolved(None, P(hir::Path {
@@ -931,7 +935,7 @@ fn lower_ty(&mut self, t: &Ty, itctx: ImplTraitContext) -> P<hir::Ty> {
                 let expr = self.lower_body(None, |this| this.lower_expr(expr));
                 hir::TyTypeof(expr)
             }
-            TyKind::TraitObject(ref bounds, ..) => {
+            TyKind::TraitObject(ref bounds, kind) => {
                 let mut lifetime_bound = None;
                 let bounds = bounds.iter().filter_map(|bound| {
                     match *bound {
@@ -950,6 +954,9 @@ fn lower_ty(&mut self, t: &Ty, itctx: ImplTraitContext) -> P<hir::Ty> {
                 let lifetime_bound = lifetime_bound.unwrap_or_else(|| {
                     self.elided_lifetime(t.span)
                 });
+                if kind != TraitObjectSyntax::Dyn {
+                    self.maybe_lint_bare_trait(t.span, t.id, false);
+                }
                 hir::TyTraitObject(bounds, lifetime_bound)
             }
             TyKind::ImplTrait(ref bounds) => {
@@ -2465,86 +2472,88 @@ fn lower_binop(&mut self, b: BinOp) -> hir::BinOp {
     }
 
     fn lower_pat(&mut self, p: &Pat) -> P<hir::Pat> {
-        let LoweredNodeId { node_id, hir_id } = self.lower_node_id(p.id);
+        let node = match p.node {
+            PatKind::Wild => hir::PatKind::Wild,
+            PatKind::Ident(ref binding_mode, pth1, ref sub) => {
+                match self.resolver.get_resolution(p.id).map(|d| d.base_def()) {
+                    // `None` can occur in body-less function signatures
+                    def @ None | def @ Some(Def::Local(_)) => {
+                        let canonical_id = match def {
+                            Some(Def::Local(id)) => id,
+                            _ => p.id
+                        };
+                        hir::PatKind::Binding(self.lower_binding_mode(binding_mode),
+                                                canonical_id,
+                                                respan(pth1.span, pth1.node.name),
+                                                sub.as_ref().map(|x| self.lower_pat(x)))
+                    }
+                    Some(def) => {
+                        hir::PatKind::Path(hir::QPath::Resolved(None, P(hir::Path {
+                            span: pth1.span,
+                            def,
+                            segments: hir_vec![
+                                hir::PathSegment::from_name(pth1.node.name)
+                            ],
+                        })))
+                    }
+                }
+            }
+            PatKind::Lit(ref e) => hir::PatKind::Lit(P(self.lower_expr(e))),
+            PatKind::TupleStruct(ref path, ref pats, ddpos) => {
+                let qpath = self.lower_qpath(p.id, &None, path, ParamMode::Optional,
+                                                ImplTraitContext::Disallowed);
+                hir::PatKind::TupleStruct(qpath,
+                                            pats.iter().map(|x| self.lower_pat(x)).collect(),
+                                            ddpos)
+            }
+            PatKind::Path(ref qself, ref path) => {
+                hir::PatKind::Path(self.lower_qpath(p.id, qself, path, ParamMode::Optional,
+                                                    ImplTraitContext::Disallowed))
+            }
+            PatKind::Struct(ref path, ref fields, etc) => {
+                let qpath = self.lower_qpath(p.id, &None, path, ParamMode::Optional,
+                                                ImplTraitContext::Disallowed);
+
+                let fs = fields.iter()
+                                .map(|f| {
+                                    Spanned {
+                                        span: f.span,
+                                        node: hir::FieldPat {
+                                            name: self.lower_ident(f.node.ident),
+                                            pat: self.lower_pat(&f.node.pat),
+                                            is_shorthand: f.node.is_shorthand,
+                                        },
+                                    }
+                                })
+                                .collect();
+                hir::PatKind::Struct(qpath, fs, etc)
+            }
+            PatKind::Tuple(ref elts, ddpos) => {
+                hir::PatKind::Tuple(elts.iter().map(|x| self.lower_pat(x)).collect(), ddpos)
+            }
+            PatKind::Box(ref inner) => hir::PatKind::Box(self.lower_pat(inner)),
+            PatKind::Ref(ref inner, mutbl) => {
+                hir::PatKind::Ref(self.lower_pat(inner), self.lower_mutability(mutbl))
+            }
+            PatKind::Range(ref e1, ref e2, ref end) => {
+                hir::PatKind::Range(P(self.lower_expr(e1)),
+                                    P(self.lower_expr(e2)),
+                                    self.lower_range_end(end))
+            }
+            PatKind::Slice(ref before, ref slice, ref after) => {
+                hir::PatKind::Slice(before.iter().map(|x| self.lower_pat(x)).collect(),
+                            slice.as_ref().map(|x| self.lower_pat(x)),
+                            after.iter().map(|x| self.lower_pat(x)).collect())
+            }
+            PatKind::Paren(ref inner) => return self.lower_pat(inner),
+            PatKind::Mac(_) => panic!("Shouldn't exist here"),
+        };
 
+        let LoweredNodeId { node_id, hir_id } = self.lower_node_id(p.id);
         P(hir::Pat {
             id: node_id,
             hir_id,
-            node: match p.node {
-                PatKind::Wild => hir::PatKind::Wild,
-                PatKind::Ident(ref binding_mode, pth1, ref sub) => {
-                    match self.resolver.get_resolution(p.id).map(|d| d.base_def()) {
-                        // `None` can occur in body-less function signatures
-                        def @ None | def @ Some(Def::Local(_)) => {
-                            let canonical_id = match def {
-                                Some(Def::Local(id)) => id,
-                                _ => p.id
-                            };
-                            hir::PatKind::Binding(self.lower_binding_mode(binding_mode),
-                                                  canonical_id,
-                                                  respan(pth1.span, pth1.node.name),
-                                                  sub.as_ref().map(|x| self.lower_pat(x)))
-                        }
-                        Some(def) => {
-                            hir::PatKind::Path(hir::QPath::Resolved(None, P(hir::Path {
-                                span: pth1.span,
-                                def,
-                                segments: hir_vec![
-                                    hir::PathSegment::from_name(pth1.node.name)
-                                ],
-                            })))
-                        }
-                    }
-                }
-                PatKind::Lit(ref e) => hir::PatKind::Lit(P(self.lower_expr(e))),
-                PatKind::TupleStruct(ref path, ref pats, ddpos) => {
-                    let qpath = self.lower_qpath(p.id, &None, path, ParamMode::Optional,
-                                                 ImplTraitContext::Disallowed);
-                    hir::PatKind::TupleStruct(qpath,
-                                              pats.iter().map(|x| self.lower_pat(x)).collect(),
-                                              ddpos)
-                }
-                PatKind::Path(ref qself, ref path) => {
-                    hir::PatKind::Path(self.lower_qpath(p.id, qself, path, ParamMode::Optional,
-                                                        ImplTraitContext::Disallowed))
-                }
-                PatKind::Struct(ref path, ref fields, etc) => {
-                    let qpath = self.lower_qpath(p.id, &None, path, ParamMode::Optional,
-                                                 ImplTraitContext::Disallowed);
-
-                    let fs = fields.iter()
-                                   .map(|f| {
-                                       Spanned {
-                                           span: f.span,
-                                           node: hir::FieldPat {
-                                               name: self.lower_ident(f.node.ident),
-                                               pat: self.lower_pat(&f.node.pat),
-                                               is_shorthand: f.node.is_shorthand,
-                                           },
-                                       }
-                                   })
-                                   .collect();
-                    hir::PatKind::Struct(qpath, fs, etc)
-                }
-                PatKind::Tuple(ref elts, ddpos) => {
-                    hir::PatKind::Tuple(elts.iter().map(|x| self.lower_pat(x)).collect(), ddpos)
-                }
-                PatKind::Box(ref inner) => hir::PatKind::Box(self.lower_pat(inner)),
-                PatKind::Ref(ref inner, mutbl) => {
-                    hir::PatKind::Ref(self.lower_pat(inner), self.lower_mutability(mutbl))
-                }
-                PatKind::Range(ref e1, ref e2, ref end) => {
-                    hir::PatKind::Range(P(self.lower_expr(e1)),
-                                        P(self.lower_expr(e2)),
-                                        self.lower_range_end(end))
-                }
-                PatKind::Slice(ref before, ref slice, ref after) => {
-                    hir::PatKind::Slice(before.iter().map(|x| self.lower_pat(x)).collect(),
-                                slice.as_ref().map(|x| self.lower_pat(x)),
-                                after.iter().map(|x| self.lower_pat(x)).collect())
-                }
-                PatKind::Mac(_) => panic!("Shouldn't exist here"),
-            },
+            node,
             span: p.span,
         })
     }
@@ -3685,7 +3694,6 @@ fn ty_path(&mut self, id: LoweredNodeId, span: Span, qpath: hir::QPath) -> P<hir
                     // The original ID is taken by the `PolyTraitRef`,
                     // so the `Ty` itself needs a different one.
                     id = self.next_id();
-
                     hir::TyTraitObject(hir_vec![principal], self.elided_lifetime(span))
                 } else {
                     hir::TyPath(hir::QPath::Resolved(None, path))
@@ -3703,6 +3711,16 @@ fn elided_lifetime(&mut self, span: Span) -> hir::Lifetime {
             name: hir::LifetimeName::Implicit,
         }
     }
+
+    fn maybe_lint_bare_trait(&self, span: Span, id: NodeId, is_global: bool) {
+        if self.sess.features.borrow().dyn_trait {
+            self.sess.buffer_lint_with_diagnostic(
+                builtin::BARE_TRAIT_OBJECT, id, span,
+                "trait objects without an explicit `dyn` are deprecated",
+                builtin::BuiltinLintDiagnostics::BareTraitObject(span, is_global)
+            )
+        }
+    }
 }
 
 fn body_ids(bodies: &BTreeMap<hir::BodyId, hir::Body>) -> Vec<hir::BodyId> {
index d08a41010ab166ab452ac807e248f1b2479d35bc..f05ed0a460d87cc18bbd278feea4085889df7b73 100644 (file)
@@ -41,6 +41,8 @@
        html_root_url = "https://doc.rust-lang.org/nightly/")]
 #![deny(warnings)]
 
+#![cfg_attr(not(stage0), allow(bare_trait_object))]
+
 #![feature(box_patterns)]
 #![feature(box_syntax)]
 #![feature(conservative_impl_trait)]
index 0577800f3f4113f92e9534a3a4b5d991126af718..b68b7dc6c067256d1fea467c43f8749517006ce2 100644 (file)
 //! compiler code, rather than using their own custom pass. Those
 //! lints are all available in `rustc_lint::builtin`.
 
+use errors::DiagnosticBuilder;
 use lint::{LintPass, LateLintPass, LintArray};
+use session::Session;
+use session::config::Epoch;
+use syntax::codemap::Span;
 
 declare_lint! {
     pub CONST_ERR,
     "hidden lifetime parameters are deprecated, try `Foo<'_>`"
 }
 
+declare_lint! {
+    pub BARE_TRAIT_OBJECT,
+    Warn,
+    "suggest using `dyn Trait` for trait objects",
+    Epoch::Epoch2018
+}
+
 /// Does nothing as a lint pass, but registers some `Lint`s
 /// which are used by other parts of the compiler.
 #[derive(Copy, Clone)]
@@ -298,10 +309,34 @@ fn get_lints(&self) -> LintArray {
             COERCE_NEVER,
             SINGLE_USE_LIFETIME,
             TYVAR_BEHIND_RAW_POINTER,
-            ELIDED_LIFETIME_IN_PATH
-
+            ELIDED_LIFETIME_IN_PATH,
+            BARE_TRAIT_OBJECT
         )
     }
 }
 
+// this could be a closure, but then implementing derive traits
+// becomes hacky (and it gets allocated)
+#[derive(PartialEq, RustcEncodable, RustcDecodable, Debug)]
+pub enum BuiltinLintDiagnostics {
+    Normal,
+    BareTraitObject(Span, /* is_global */ bool)
+}
+
+impl BuiltinLintDiagnostics {
+    pub fn run(self, sess: &Session, db: &mut DiagnosticBuilder) {
+        match self {
+            BuiltinLintDiagnostics::Normal => (),
+            BuiltinLintDiagnostics::BareTraitObject(span, is_global) => {
+                let sugg = match sess.codemap().span_to_snippet(span) {
+                    Ok(ref s) if is_global => format!("dyn ({})", s),
+                    Ok(s) => format!("dyn {}", s),
+                    Err(_) => format!("dyn <type>")
+                };
+                db.span_suggestion(span, "use `dyn`", sugg);
+            }
+        }
+    }
+}
+
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for HardwiredLints {}
index ed937046e5ed747b6ece8e486bcfbc250e79140e..bfd2034dd6cfe4e577089a0d8cf3b9ddd763731c 100644 (file)
@@ -29,6 +29,7 @@
 use std::slice;
 use lint::{EarlyLintPassObject, LateLintPassObject};
 use lint::{Level, Lint, LintId, LintPass, LintBuffer};
+use lint::builtin::BuiltinLintDiagnostics;
 use lint::levels::{LintLevelSets, LintLevelsBuilder};
 use middle::privacy::AccessLevels;
 use rustc_serialize::{Decoder, Decodable, Encoder, Encodable};
@@ -92,6 +93,7 @@ pub struct BufferedEarlyLint {
     pub ast_id: ast::NodeId,
     pub span: MultiSpan,
     pub msg: String,
+    pub diagnostic: BuiltinLintDiagnostics,
 }
 
 /// Extra information for a future incompatibility lint. See the call
@@ -99,7 +101,11 @@ pub struct BufferedEarlyLint {
 /// guidelines.
 pub struct FutureIncompatibleInfo {
     pub id: LintId,
-    pub reference: &'static str // e.g., a URL for an issue/PR/RFC or error code
+    /// e.g., a URL for an issue/PR/RFC or error code
+    pub reference: &'static str,
+    /// If this is an epoch fixing lint, the epoch in which
+    /// this lint becomes obsolete
+    pub epoch: Option<config::Epoch>,
 }
 
 /// The target of the `by_name` map, which accounts for renaming/deprecation.
@@ -194,11 +200,24 @@ fn push_pass<P: LintPass + ?Sized + 'static>(&mut self,
     pub fn register_future_incompatible(&mut self,
                                         sess: Option<&Session>,
                                         lints: Vec<FutureIncompatibleInfo>) {
-        let ids = lints.iter().map(|f| f.id).collect();
-        self.register_group(sess, false, "future_incompatible", ids);
-        for info in lints {
-            self.future_incompatible.insert(info.id, info);
+
+        for epoch in config::ALL_EPOCHS {
+            let lints = lints.iter().filter(|f| f.epoch == Some(*epoch)).map(|f| f.id)
+                             .collect::<Vec<_>>();
+            if !lints.is_empty() {
+                self.register_group(sess, false, epoch.lint_name(), lints)
+            }
         }
+
+        let mut future_incompatible = vec![];
+        for lint in lints {
+            future_incompatible.push(lint.id);
+            self.future_incompatible.insert(lint.id, lint);
+        }
+
+        self.register_group(sess, false, "future_incompatible", future_incompatible);
+
+
     }
 
     pub fn future_incompatible(&self, id: LintId) -> Option<&FutureIncompatibleInfo> {
@@ -429,6 +448,16 @@ fn lookup_and_emit<S: Into<MultiSpan>>(&self,
         self.lookup(lint, span, msg).emit();
     }
 
+    fn lookup_and_emit_with_diagnostics<S: Into<MultiSpan>>(&self,
+                                                            lint: &'static Lint,
+                                                            span: Option<S>,
+                                                            msg: &str,
+                                                            diagnostic: BuiltinLintDiagnostics) {
+        let mut db = self.lookup(lint, span, msg);
+        diagnostic.run(self.sess(), &mut db);
+        db.emit();
+    }
+
     fn lookup<S: Into<MultiSpan>>(&self,
                                   lint: &'static Lint,
                                   span: Option<S>,
@@ -499,9 +528,10 @@ fn new(sess: &'a Session,
 
     fn check_id(&mut self, id: ast::NodeId) {
         for early_lint in self.buffered.take(id) {
-            self.lookup_and_emit(early_lint.lint_id.lint,
-                                 Some(early_lint.span.clone()),
-                                 &early_lint.msg);
+            self.lookup_and_emit_with_diagnostics(early_lint.lint_id.lint,
+                                                  Some(early_lint.span.clone()),
+                                                  &early_lint.msg,
+                                                  early_lint.diagnostic);
         }
     }
 }
@@ -1054,7 +1084,7 @@ pub fn check_ast_crate(sess: &Session, krate: &ast::Crate) {
     if !sess.opts.actually_rustdoc {
         for (_id, lints) in cx.buffered.map {
             for early_lint in lints {
-                span_bug!(early_lint.span, "failed to process buffered lint here");
+                sess.delay_span_bug(early_lint.span, "failed to process buffered lint here");
             }
         }
     }
index 4bc37747f2a76b1dc01c4c3ad23fedf0727b0f04..909904b4fc36cd9d16838ca91b21ba6deaf2e70f 100644 (file)
@@ -89,14 +89,15 @@ fn process_command_line(&mut self, sess: &Session) {
     fn get_lint_level(&self,
                       lint: &'static Lint,
                       idx: u32,
-                      aux: Option<&FxHashMap<LintId, (Level, LintSource)>>)
+                      aux: Option<&FxHashMap<LintId, (Level, LintSource)>>,
+                      sess: &Session)
         -> (Level, LintSource)
     {
         let (level, mut src) = self.get_lint_id_level(LintId::of(lint), idx, aux);
 
         // If `level` is none then we actually assume the default level for this
         // lint.
-        let mut level = level.unwrap_or(lint.default_level);
+        let mut level = level.unwrap_or(lint.default_level(sess));
 
         // If we're about to issue a warning, check at the last minute for any
         // directives against the warnings "lint". If, for example, there's an
@@ -235,7 +236,8 @@ pub fn push(&mut self, attrs: &[ast::Attribute]) -> BuilderPush {
                         let lint = builtin::RENAMED_AND_REMOVED_LINTS;
                         let (level, src) = self.sets.get_lint_level(lint,
                                                                     self.cur,
-                                                                    Some(&specs));
+                                                                    Some(&specs),
+                                                                    &sess);
                         lint::struct_lint_level(self.sess,
                                                 lint,
                                                 level,
@@ -248,7 +250,8 @@ pub fn push(&mut self, attrs: &[ast::Attribute]) -> BuilderPush {
                         let lint = builtin::UNKNOWN_LINTS;
                         let (level, src) = self.sets.get_lint_level(lint,
                                                                     self.cur,
-                                                                    Some(&specs));
+                                                                    Some(&specs),
+                                                                    self.sess);
                         let msg = format!("unknown lint: `{}`", name);
                         let mut db = lint::struct_lint_level(self.sess,
                                                 lint,
@@ -342,7 +345,7 @@ pub fn struct_lint(&self,
                        msg: &str)
         -> DiagnosticBuilder<'a>
     {
-        let (level, src) = self.sets.get_lint_level(lint, self.cur, None);
+        let (level, src) = self.sets.get_lint_level(lint, self.cur, None, self.sess);
         lint::struct_lint_level(self.sess, lint, level, src, span, msg)
     }
 
@@ -377,11 +380,11 @@ impl LintLevelMap {
     /// If the `id` was not previously registered, returns `None`. If `None` is
     /// returned then the parent of `id` should be acquired and this function
     /// should be called again.
-    pub fn level_and_source(&self, lint: &'static Lint, id: HirId)
+    pub fn level_and_source(&self, lint: &'static Lint, id: HirId, session: &Session)
         -> Option<(Level, LintSource)>
     {
         self.id_to_set.get(&id).map(|idx| {
-            self.sets.get_lint_level(lint, *idx, None)
+            self.sets.get_lint_level(lint, *idx, None, session)
         })
     }
 
index b2a9859f68a3eb523988460518fc4c9780cca07a..a51d06c06edd3a1ebb1a7fd9b5ac8cbe09669555 100644 (file)
@@ -37,7 +37,8 @@
 use hir::def_id::{CrateNum, LOCAL_CRATE};
 use hir::intravisit::{self, FnKind};
 use hir;
-use session::{Session, DiagnosticMessageId};
+use lint::builtin::BuiltinLintDiagnostics;
+use session::{config, Session, DiagnosticMessageId};
 use std::hash;
 use syntax::ast;
 use syntax::codemap::MultiSpan;
@@ -74,6 +75,9 @@ pub struct Lint {
     ///
     /// e.g. "imports that are never used"
     pub desc: &'static str,
+
+    /// Deny lint after this epoch
+    pub epoch_deny: Option<config::Epoch>,
 }
 
 impl Lint {
@@ -81,18 +85,36 @@ impl Lint {
     pub fn name_lower(&self) -> String {
         self.name.to_ascii_lowercase()
     }
+
+    pub fn default_level(&self, session: &Session) -> Level {
+        if let Some(epoch_deny) = self.epoch_deny {
+            if session.epoch() >= epoch_deny {
+                return Level::Deny
+            }
+        }
+        self.default_level
+    }
 }
 
 /// Declare a static item of type `&'static Lint`.
 #[macro_export]
 macro_rules! declare_lint {
+    ($vis: vis $NAME: ident, $Level: ident, $desc: expr, $epoch: expr) => (
+        $vis static $NAME: &$crate::lint::Lint = &$crate::lint::Lint {
+            name: stringify!($NAME),
+            default_level: $crate::lint::$Level,
+            desc: $desc,
+            epoch_deny: Some($epoch)
+        };
+    );
     ($vis: vis $NAME: ident, $Level: ident, $desc: expr) => (
         $vis static $NAME: &$crate::lint::Lint = &$crate::lint::Lint {
             name: stringify!($NAME),
             default_level: $crate::lint::$Level,
-            desc: $desc
+            desc: $desc,
+            epoch_deny: None,
         };
-    )
+    );
 }
 
 /// Declare a static `LintArray` and return it as an expression.
@@ -304,7 +326,7 @@ pub fn to_string(&self) -> String {
 /// Setting for how to handle a lint.
 #[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
 pub enum Level {
-    Allow, Warn, Deny, Forbid
+    Allow, Warn, Deny, Forbid,
 }
 
 impl_stable_hash_for!(enum self::Level {
@@ -378,12 +400,14 @@ pub fn add_lint(&mut self,
                     lint: &'static Lint,
                     id: ast::NodeId,
                     sp: MultiSpan,
-                    msg: &str) {
+                    msg: &str,
+                    diagnostic: BuiltinLintDiagnostics) {
         let early_lint = BufferedEarlyLint {
             lint_id: LintId::of(lint),
             ast_id: id,
             span: sp,
             msg: msg.to_string(),
+            diagnostic
         };
         let arr = self.map.entry(id).or_insert(Vec::new());
         if !arr.contains(&early_lint) {
index 919badfa4aa5efbe0bc9f72a9ec38c79f20a42a7..b69f5d6c8bdd79fe98870e314d5e955d0bca4ca5 100644 (file)
@@ -41,7 +41,7 @@
 use std::collections::btree_map::Keys as BTreeMapKeysIter;
 use std::collections::btree_map::Values as BTreeMapValuesIter;
 
-use std::fmt;
+use std::{fmt, str};
 use std::hash::Hasher;
 use std::collections::hash_map::DefaultHasher;
 use std::collections::HashSet;
@@ -113,7 +113,7 @@ pub enum OutputType {
 }
 
 /// The epoch of the compiler (RFC 2052)
-#[derive(Clone, Copy, Hash, PartialOrd, Ord, Eq, PartialEq)]
+#[derive(Clone, Copy, Hash, PartialOrd, Ord, Eq, PartialEq, Debug)]
 #[non_exhaustive]
 pub enum Epoch {
     // epochs must be kept in order, newest to oldest
@@ -137,6 +137,37 @@ pub enum Epoch {
     // as well as changing the default Cargo template.
 }
 
+pub const ALL_EPOCHS: &[Epoch] = &[Epoch::Epoch2015, Epoch::Epoch2018];
+
+impl ToString for Epoch {
+    fn to_string(&self) -> String {
+        match *self {
+            Epoch::Epoch2015 => "2015".into(),
+            Epoch::Epoch2018 => "2018".into(),
+        }
+    }
+}
+
+impl Epoch {
+    pub fn lint_name(&self) -> &'static str {
+        match *self {
+            Epoch::Epoch2015 => "epoch_2015",
+            Epoch::Epoch2018 => "epoch_2018",
+        }
+    }
+}
+
+impl str::FromStr for Epoch {
+    type Err = ();
+    fn from_str(s: &str) -> Result<Self, ()> {
+        match s {
+            "2015" => Ok(Epoch::Epoch2015),
+            "2018" => Ok(Epoch::Epoch2018),
+            _ => Err(())
+        }
+    }
+}
+
 impl_stable_hash_for!(enum self::OutputType {
     Bitcode,
     Assembly,
@@ -435,6 +466,9 @@ pub struct Options {
         // if we otherwise use the defaults of rustc.
         cli_forced_codegen_units: Option<usize> [UNTRACKED],
         cli_forced_thinlto_off: bool [UNTRACKED],
+
+        // Remap source path prefixes in all output (messages, object files, debug, etc)
+        remap_path_prefix: Vec<(PathBuf, PathBuf)> [UNTRACKED],
     }
 );
 
@@ -617,6 +651,7 @@ pub fn basic_options() -> Options {
         actually_rustdoc: false,
         cli_forced_codegen_units: None,
         cli_forced_thinlto_off: false,
+        remap_path_prefix: Vec::new(),
     }
 }
 
@@ -635,11 +670,7 @@ pub fn enable_dep_node_debug_strs(&self) -> bool {
     }
 
     pub fn file_path_mapping(&self) -> FilePathMapping {
-        FilePathMapping::new(
-            self.debugging_opts.remap_path_prefix_from.iter().zip(
-                self.debugging_opts.remap_path_prefix_to.iter()
-            ).map(|(src, dst)| (src.clone(), dst.clone())).collect()
-        )
+        FilePathMapping::new(self.remap_path_prefix.clone())
     }
 
     /// True if there will be an output file generated
@@ -1021,11 +1052,17 @@ fn parse_lto(slot: &mut Lto, v: Option<&str>) -> bool {
 
         fn parse_epoch(slot: &mut Epoch, v: Option<&str>) -> bool {
             match v {
-                Some("2015") => *slot = Epoch::Epoch2015,
-                Some("2018") => *slot = Epoch::Epoch2018,
-                _ => return false,
+                Some(s) => {
+                    let epoch = s.parse();
+                    if let Ok(parsed) = epoch {
+                        *slot = parsed;
+                        true
+                    } else {
+                        false
+                    }
+                }
+                _ => false,
             }
-            true
         }
     }
 ) }
@@ -1269,10 +1306,6 @@ fn parse_epoch(slot: &mut Epoch, v: Option<&str>) -> bool {
         "set the optimization fuel quota for a crate"),
     print_fuel: Option<String> = (None, parse_opt_string, [TRACKED],
         "make Rustc print the total optimization fuel used by a crate"),
-    remap_path_prefix_from: Vec<PathBuf> = (vec![], parse_pathbuf_push, [UNTRACKED],
-        "add a source pattern to the file path remapping config"),
-    remap_path_prefix_to: Vec<PathBuf> = (vec![], parse_pathbuf_push, [UNTRACKED],
-        "add a mapping target to the file path remapping config"),
     force_unstable_if_unmarked: bool = (false, parse_bool, [TRACKED],
         "force all crates to be `rustc_private` unstable"),
     pre_link_arg: Vec<String> = (vec![], parse_string_push, [UNTRACKED],
@@ -1597,6 +1630,7 @@ pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
                   `expanded` (crates expanded), or
                   `expanded,identified` (fully parenthesized, AST nodes with IDs).",
                  "TYPE"),
+        opt::multi_s("", "remap-path-prefix", "remap source names in output", "FROM=TO"),
     ]);
     opts
 }
@@ -1720,23 +1754,6 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches)
         output_types.insert(OutputType::Exe, None);
     }
 
-    let remap_path_prefix_sources = debugging_opts.remap_path_prefix_from.len();
-    let remap_path_prefix_targets = debugging_opts.remap_path_prefix_to.len();
-
-    if remap_path_prefix_targets < remap_path_prefix_sources {
-        for source in &debugging_opts.remap_path_prefix_from[remap_path_prefix_targets..] {
-            early_error(error_format,
-                &format!("option `-Zremap-path-prefix-from='{}'` does not have \
-                         a corresponding `-Zremap-path-prefix-to`", source.display()))
-        }
-    } else if remap_path_prefix_targets > remap_path_prefix_sources {
-        for target in &debugging_opts.remap_path_prefix_to[remap_path_prefix_sources..] {
-            early_error(error_format,
-                &format!("option `-Zremap-path-prefix-to='{}'` does not have \
-                          a corresponding `-Zremap-path-prefix-from`", target.display()))
-        }
-    }
-
     let mut cg = build_codegen_options(matches, error_format);
     let mut codegen_units = cg.codegen_units;
     let mut disable_thinlto = false;
@@ -1970,6 +1987,20 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches)
 
     let crate_name = matches.opt_str("crate-name");
 
+    let remap_path_prefix = matches.opt_strs("remap-path-prefix")
+        .into_iter()
+        .map(|remap| {
+            let mut parts = remap.rsplitn(2, '='); // reverse iterator
+            let to = parts.next();
+            let from = parts.next();
+            match (from, to) {
+                (Some(from), Some(to)) => (PathBuf::from(from), PathBuf::from(to)),
+                _ => early_error(error_format,
+                        "--remap-path-prefix must contain '=' between FROM and TO"),
+            }
+        })
+        .collect();
+
     (Options {
         crate_types,
         optimize: opt_level,
@@ -1997,6 +2028,7 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches)
         actually_rustdoc: false,
         cli_forced_codegen_units: codegen_units,
         cli_forced_thinlto_off: disable_thinlto,
+        remap_path_prefix,
     },
     cfg)
 }
index 939154fac7ab0041cbfefdcca531fb93598e733d..2437eaadc6d480381598dd24a43fe4fd8d1fc2f3 100644 (file)
@@ -16,6 +16,7 @@
 
 use ich;
 use lint;
+use lint::builtin::BuiltinLintDiagnostics;
 use middle::allocator::AllocatorKind;
 use middle::dependency_format;
 use session::search_paths::PathKind;
@@ -341,7 +342,18 @@ pub fn buffer_lint<S: Into<MultiSpan>>(&self,
                                            sp: S,
                                            msg: &str) {
         match *self.buffered_lints.borrow_mut() {
-            Some(ref mut buffer) => buffer.add_lint(lint, id, sp.into(), msg),
+            Some(ref mut buffer) => buffer.add_lint(lint, id, sp.into(),
+                                                    msg, BuiltinLintDiagnostics::Normal),
+            None => bug!("can't buffer lints after HIR lowering"),
+        }
+    }
+
+    pub fn buffer_lint_with_diagnostic<S: Into<MultiSpan>>(&self,
+        lint: &'static lint::Lint, id: ast::NodeId, sp: S,
+        msg: &str, diagnostic: BuiltinLintDiagnostics) {
+        match *self.buffered_lints.borrow_mut() {
+            Some(ref mut buffer) => buffer.add_lint(lint, id, sp.into(),
+                                                    msg, diagnostic),
             None => bug!("can't buffer lints after HIR lowering"),
         }
     }
@@ -869,6 +881,10 @@ pub fn teach(&self, code: &DiagnosticId) -> bool {
     pub fn rust_2018(&self) -> bool {
         self.opts.debugging_opts.epoch >= Epoch::Epoch2018
     }
+
+    pub fn epoch(&self) -> Epoch {
+        self.opts.debugging_opts.epoch
+    }
 }
 
 pub fn build_session(sopts: config::Options,
index 3613a34f66af6505f6552ef12b87ccf0c8c6cdd5..a39d63d05eeafdf93bcf578db76b68de8edd5136 100644 (file)
@@ -2234,7 +2234,7 @@ pub fn lint_level_at_node(self, lint: &'static Lint, mut id: NodeId)
             let sets = self.lint_levels(LOCAL_CRATE);
             loop {
                 let hir_id = self.hir.definitions().node_to_hir_id(id);
-                if let Some(pair) = sets.level_and_source(lint, hir_id) {
+                if let Some(pair) = sets.level_and_source(lint, hir_id, self.sess) {
                     return pair
                 }
                 let next = self.hir.get_parent_node(id);
index b03108ed807da0060ecf67e8c37db32cf901ef0f..2ae800e8cdc96ebc0fe5664d8e5ab89d07facb61 100644 (file)
@@ -737,7 +737,7 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session,
 
     // Lint plugins are registered; now we can process command line flags.
     if sess.opts.describe_lints {
-        super::describe_lints(&sess.lint_store.borrow(), true);
+        super::describe_lints(&sess, &sess.lint_store.borrow(), true);
         return Err(CompileIncomplete::Stopped);
     }
 
index 6af7a23f66d73919c344d4ea214ee9e07048f571..22c26b0643050546ca85a90e255c0254e25537b1 100644 (file)
@@ -787,15 +787,15 @@ fn no_input(&mut self,
                 -> Option<(Input, Option<PathBuf>)> {
         match matches.free.len() {
             0 => {
+                let mut sess = build_session(sopts.clone(),
+                    None,
+                    descriptions.clone());
                 if sopts.describe_lints {
                     let mut ls = lint::LintStore::new();
-                    rustc_lint::register_builtins(&mut ls, None);
-                    describe_lints(&ls, false);
+                    rustc_lint::register_builtins(&mut ls, Some(&sess));
+                    describe_lints(&sess, &ls, false);
                     return None;
                 }
-                let mut sess = build_session(sopts.clone(),
-                    None,
-                    descriptions.clone());
                 rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
                 let mut cfg = config::build_configuration(&sess, cfg.clone());
                 let trans = get_trans(&sess);
@@ -1134,7 +1134,7 @@ fn usage(verbose: bool, include_unstable_options: bool) {
              verbose_help);
 }
 
-fn describe_lints(lint_store: &lint::LintStore, loaded_plugins: bool) {
+fn describe_lints(sess: &Session, lint_store: &lint::LintStore, loaded_plugins: bool) {
     println!("
 Available lint options:
     -W <foo>           Warn about <foo>
@@ -1146,10 +1146,10 @@ fn describe_lints(lint_store: &lint::LintStore, loaded_plugins: bool) {
 
 ");
 
-    fn sort_lints(lints: Vec<(&'static Lint, bool)>) -> Vec<&'static Lint> {
+    fn sort_lints(sess: &Session, lints: Vec<(&'static Lint, bool)>) -> Vec<&'static Lint> {
         let mut lints: Vec<_> = lints.into_iter().map(|(x, _)| x).collect();
         lints.sort_by(|x: &&Lint, y: &&Lint| {
-            match x.default_level.cmp(&y.default_level) {
+            match x.default_level(sess).cmp(&y.default_level(sess)) {
                 // The sort doesn't case-fold but it's doubtful we care.
                 Equal => x.name.cmp(y.name),
                 r => r,
@@ -1172,8 +1172,8 @@ fn sort_lint_groups(lints: Vec<(&'static str, Vec<lint::LintId>, bool)>)
                                                    .iter()
                                                    .cloned()
                                                    .partition(|&(_, p)| p);
-    let plugin = sort_lints(plugin);
-    let builtin = sort_lints(builtin);
+    let plugin = sort_lints(sess, plugin);
+    let builtin = sort_lints(sess, builtin);
 
     let (plugin_groups, builtin_groups): (Vec<_>, _) = lint_store.get_lint_groups()
                                                                  .iter()
index de55710bdf3d0bce54d919117777403d9fe3d6cc..66f34a72edf2d4fce674ae9c15ba32a980861595 100644 (file)
@@ -737,6 +737,7 @@ fn check_pat(&mut self, cx: &EarlyContext, pat: &ast::Pat) {
                 PatKind::TupleStruct(..) |
                 PatKind::Ref(..) |
                 PatKind::Box(..) |
+                PatKind::Paren(..) |
                 PatKind::Slice(..) => (),
 
                 // Extract the expressions and check them
index f3c6ff2f2b3a10ba8aeb720eb8adabb67e4bc157..9dc6d977851b147d9c28ab04982e140ce1dacdd6 100644 (file)
@@ -191,75 +191,98 @@ macro_rules! add_lint_group {
         FutureIncompatibleInfo {
             id: LintId::of(PRIVATE_IN_PUBLIC),
             reference: "issue #34537 <https://github.com/rust-lang/rust/issues/34537>",
+            epoch: None,
         },
         FutureIncompatibleInfo {
             id: LintId::of(PUB_USE_OF_PRIVATE_EXTERN_CRATE),
             reference: "issue #34537 <https://github.com/rust-lang/rust/issues/34537>",
+            epoch: None,
         },
         FutureIncompatibleInfo {
             id: LintId::of(PATTERNS_IN_FNS_WITHOUT_BODY),
             reference: "issue #35203 <https://github.com/rust-lang/rust/issues/35203>",
+            epoch: None,
         },
         FutureIncompatibleInfo {
             id: LintId::of(SAFE_EXTERN_STATICS),
             reference: "issue #36247 <https://github.com/rust-lang/rust/issues/36247>",
+            epoch: None,
         },
         FutureIncompatibleInfo {
             id: LintId::of(INVALID_TYPE_PARAM_DEFAULT),
             reference: "issue #36887 <https://github.com/rust-lang/rust/issues/36887>",
+            epoch: None,
         },
         FutureIncompatibleInfo {
             id: LintId::of(LEGACY_DIRECTORY_OWNERSHIP),
             reference: "issue #37872 <https://github.com/rust-lang/rust/issues/37872>",
+            epoch: None,
         },
         FutureIncompatibleInfo {
             id: LintId::of(LEGACY_IMPORTS),
             reference: "issue #38260 <https://github.com/rust-lang/rust/issues/38260>",
+            epoch: None,
         },
         FutureIncompatibleInfo {
             id: LintId::of(LEGACY_CONSTRUCTOR_VISIBILITY),
             reference: "issue #39207 <https://github.com/rust-lang/rust/issues/39207>",
+            epoch: None,
         },
         FutureIncompatibleInfo {
             id: LintId::of(RESOLVE_TRAIT_ON_DEFAULTED_UNIT),
             reference: "issue #39216 <https://github.com/rust-lang/rust/issues/39216>",
+            epoch: None,
         },
         FutureIncompatibleInfo {
             id: LintId::of(MISSING_FRAGMENT_SPECIFIER),
             reference: "issue #40107 <https://github.com/rust-lang/rust/issues/40107>",
+            epoch: None,
         },
         FutureIncompatibleInfo {
             id: LintId::of(ILLEGAL_FLOATING_POINT_LITERAL_PATTERN),
             reference: "issue #41620 <https://github.com/rust-lang/rust/issues/41620>",
+            epoch: None,
         },
         FutureIncompatibleInfo {
             id: LintId::of(ANONYMOUS_PARAMETERS),
             reference: "issue #41686 <https://github.com/rust-lang/rust/issues/41686>",
+            epoch: None,
         },
         FutureIncompatibleInfo {
             id: LintId::of(PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES),
             reference: "issue #42238 <https://github.com/rust-lang/rust/issues/42238>",
+            epoch: None,
         },
         FutureIncompatibleInfo {
             id: LintId::of(LATE_BOUND_LIFETIME_ARGUMENTS),
             reference: "issue #42868 <https://github.com/rust-lang/rust/issues/42868>",
+            epoch: None,
         },
         FutureIncompatibleInfo {
             id: LintId::of(SAFE_PACKED_BORROWS),
             reference: "issue #46043 <https://github.com/rust-lang/rust/issues/46043>",
+            epoch: None,
         },
         FutureIncompatibleInfo {
             id: LintId::of(INCOHERENT_FUNDAMENTAL_IMPLS),
             reference: "issue #46205 <https://github.com/rust-lang/rust/issues/46205>",
+            epoch: None,
         },
         FutureIncompatibleInfo {
             id: LintId::of(COERCE_NEVER),
             reference: "issue #46325 <https://github.com/rust-lang/rust/issues/46325>",
+            epoch: None,
         },
         FutureIncompatibleInfo {
             id: LintId::of(TYVAR_BEHIND_RAW_POINTER),
             reference: "issue #46906 <https://github.com/rust-lang/rust/issues/46906>",
+            epoch: None,
         },
+         FutureIncompatibleInfo {
+             id: LintId::of(lint::builtin::BARE_TRAIT_OBJECT),
+             reference: "issue #48457 <https://github.com/rust-lang/rust/issues/48457>",
+             epoch: Some(session::config::Epoch::Epoch2018),
+         }
         ]);
 
     // Register renamed and removed lints
index 78578ca179c8218505122361f99002f79b147965..d140b135416c9c7148bf66c6911d97fa4f33f4f6 100644 (file)
@@ -323,7 +323,7 @@ fn encode_codemap(&mut self) -> LazySeq<syntax_pos::FileMap> {
                 // paths because any relative paths are potentially relative to
                 // a wrong directory.
                 // However, if a path has been modified via
-                // `-Zremap-path-prefix` we assume the user has already set
+                // `--remap-path-prefix` we assume the user has already set
                 // things up the way they want and don't touch the path values
                 // anymore.
                 match filemap.name {
index 57059cd31a1bc35131096bf30cf71149b985cbcf..a325cfe3eaae33cab4a84971cc58eadcab21502b 100644 (file)
@@ -28,6 +28,7 @@
 use std::u32;
 use syntax::abi::Abi;
 use syntax::ast;
+use syntax::attr::{self, UnwindAttr};
 use syntax::symbol::keywords;
 use syntax_pos::Span;
 use transform::MirSource;
@@ -355,10 +356,9 @@ macro_rules! unpack {
 }
 
 fn should_abort_on_panic<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
-                                         fn_id: ast::NodeId,
+                                         fn_def_id: DefId,
                                          abi: Abi)
                                          -> bool {
-
     // Not callable from C, so we can safely unwind through these
     if abi == Abi::Rust || abi == Abi::RustCall { return false; }
 
@@ -370,9 +370,17 @@ fn should_abort_on_panic<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
 
     // This is a special case: some functions have a C abi but are meant to
     // unwind anyway. Don't stop them.
-    if tcx.has_attr(tcx.hir.local_def_id(fn_id), "unwind") { return false; }
+    let attrs = &tcx.get_attrs(fn_def_id);
+    match attr::find_unwind_attr(Some(tcx.sess.diagnostic()), attrs) {
+        None => {
+            // FIXME(rust-lang/rust#48251) -- Had to disable
+            // abort-on-panic for backwards compatibility reasons.
+            false
+        }
 
-    return true;
+        Some(UnwindAttr::Allowed) => false,
+        Some(UnwindAttr::Aborts) => true,
+    }
 }
 
 ///////////////////////////////////////////////////////////////////////////
@@ -399,13 +407,14 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
         safety,
         return_ty);
 
+    let fn_def_id = tcx.hir.local_def_id(fn_id);
     let call_site_scope = region::Scope::CallSite(body.value.hir_id.local_id);
     let arg_scope = region::Scope::Arguments(body.value.hir_id.local_id);
     let mut block = START_BLOCK;
     let source_info = builder.source_info(span);
     let call_site_s = (call_site_scope, source_info);
     unpack!(block = builder.in_scope(call_site_s, LintLevel::Inherited, block, |builder| {
-        if should_abort_on_panic(tcx, fn_id, abi) {
+        if should_abort_on_panic(tcx, fn_def_id, abi) {
             builder.schedule_abort();
         }
 
index 8c15d1cf8b03afc7efabe3bb149d70e11b8e51f5..9887ac82a2ea66079f5c5af3483a27a3bec6dcfa 100644 (file)
@@ -15,6 +15,7 @@
 */
 
 #![deny(warnings)]
+#![cfg_attr(not(stage0), allow(bare_trait_object))]
 
 #![feature(box_patterns)]
 #![feature(box_syntax)]
index b16c1436a1cbee682cb7e2cc131656318e239b8f..54a7a0eafe0af6019ef249b259f56039f427bf13 100644 (file)
@@ -257,6 +257,7 @@ fn optimized_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx
 
 
         // Optimizations begin.
+        uniform_array_move_out::RestoreSubsliceArrayMoveOut,
         inline::Inline,
 
         // Lowering generator control-flow and variables
index 0db5ecf0eb2702f29a890313c3932e5e06514ed8..e46de170479861dc07e47b1bfe137dc40e8bb627 100644 (file)
 //  and mir statement _11 = move _2[-1 of 1]; replaced by:
 //  _11 = move _2[2 of 3];
 //
-// FIXME: convert to Subslice back for performance reason
 // FIXME: integrate this transformation to the mir build
 
 use rustc::ty;
 use rustc::ty::TyCtxt;
 use rustc::mir::*;
-use rustc::mir::visit::Visitor;
+use rustc::mir::visit::{Visitor, PlaceContext};
 use transform::{MirPass, MirSource};
 use util::patch::MirPatch;
+use rustc_data_structures::indexed_vec::{IndexVec};
 
 pub struct UniformArrayMoveOut;
 
@@ -67,12 +67,12 @@ struct UniformArrayMoveOutVisitor<'a, 'tcx: 'a> {
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for UniformArrayMoveOutVisitor<'a, 'tcx> {
-    fn visit_statement(&mut self,
-                       block: BasicBlock,
-                       statement: &Statement<'tcx>,
-                       location: Location) {
-        if let StatementKind::Assign(ref dst_place,
-                                     Rvalue::Use(Operand::Move(ref src_place))) = statement.kind {
+    fn visit_assign(&mut self,
+                    block: BasicBlock,
+                    dst_place: &Place<'tcx>,
+                    rvalue: &Rvalue<'tcx>,
+                    location: Location) {
+        if let Rvalue::Use(Operand::Move(ref src_place)) = rvalue {
             if let Place::Projection(ref proj) = *src_place {
                 if let ProjectionElem::ConstantIndex{offset: _,
                                                      min_length: _,
@@ -92,7 +92,7 @@ fn visit_statement(&mut self,
                 }
             }
         }
-        return self.super_statement(block, statement, location);
+        self.super_assign(block, dst_place, rvalue, location)
     }
 }
 
@@ -104,7 +104,7 @@ fn uniform(&mut self,
                item_ty: &'tcx ty::TyS<'tcx>,
                size: u32) {
         match proj.elem {
-            // uniform _10 = move _2[:-1];
+            // uniforms statements like_10 = move _2[:-1];
             ProjectionElem::Subslice{from, to} => {
                 self.patch.make_nop(location);
                 let temps : Vec<_> = (from..(size-to)).map(|i| {
@@ -133,7 +133,7 @@ fn uniform(&mut self,
                     self.patch.add_statement(location, StatementKind::StorageDead(temp));
                 }
             }
-            // _11 = move _2[-1 of 1];
+            // uniforms statements like _11 = move _2[-1 of 1];
             ProjectionElem::ConstantIndex{offset, min_length: _, from_end: true} => {
                 self.patch.make_nop(location);
                 self.patch.add_assign(location,
@@ -151,3 +151,179 @@ fn uniform(&mut self,
         }
     }
 }
+
+// Restore Subslice move out after analysis
+// Example:
+//
+//  next statements:
+//   StorageLive(_12);
+//   _12 = move _2[0 of 3];
+//   StorageLive(_13);
+//   _13 = move _2[1 of 3];
+//   _10 = [move _12, move _13]
+//   StorageDead(_12);
+//   StorageDead(_13);
+//
+// replaced by _10 = move _2[:-1];
+
+pub struct RestoreSubsliceArrayMoveOut;
+
+impl MirPass for RestoreSubsliceArrayMoveOut {
+    fn run_pass<'a, 'tcx>(&self,
+                          tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                          _src: MirSource,
+                          mir: &mut Mir<'tcx>) {
+        let mut patch = MirPatch::new(mir);
+        {
+            let mut visitor = RestoreDataCollector {
+                locals_use: IndexVec::from_elem(LocalUse::new(), &mir.local_decls),
+                candidates: vec![],
+            };
+            visitor.visit_mir(mir);
+
+            for candidate in &visitor.candidates {
+                let statement = &mir[candidate.block].statements[candidate.statement_index];
+                if let StatementKind::Assign(ref dst_place, ref rval) = statement.kind {
+                    if let Rvalue::Aggregate(box AggregateKind::Array(_), ref items) = *rval {
+                        let items : Vec<_> = items.iter().map(|item| {
+                            if let Operand::Move(Place::Local(local)) = item {
+                                let local_use = &visitor.locals_use[*local];
+                                let opt_index_and_place = Self::try_get_item_source(local_use, mir);
+                                // each local should be used twice:
+                                //  in assign and in aggregate statments
+                                if local_use.use_count == 2 && opt_index_and_place.is_some() {
+                                    let (index, src_place) = opt_index_and_place.unwrap();
+                                    return Some((local_use, index, src_place));
+                                }
+                            }
+                            None
+                        }).collect();
+
+                        let opt_src_place = items.first().and_then(|x| *x).map(|x| x.2);
+                        let opt_size = opt_src_place.and_then(|src_place| {
+                            let src_ty = src_place.ty(mir, tcx).to_ty(tcx);
+                            if let ty::TyArray(_, ref size_o) = src_ty.sty {
+                                size_o.val.to_const_int().and_then(|v| v.to_u64())
+                            } else {
+                                None
+                            }
+                        });
+                        Self::check_and_patch(*candidate, &items, opt_size, &mut patch, dst_place);
+                    }
+                }
+            }
+        }
+        patch.apply(mir);
+    }
+}
+
+impl RestoreSubsliceArrayMoveOut {
+    // Checks that source has size, all locals are inited from same source place and
+    // indices is an integer interval. If all checks pass do the replacent.
+    // items are Vec<Option<LocalUse, index in source array, source place for init local>>
+    fn check_and_patch<'tcx>(candidate: Location,
+                             items: &Vec<Option<(&LocalUse, u32, &Place<'tcx>)>>,
+                             opt_size: Option<u64>,
+                             patch: &mut MirPatch<'tcx>,
+                             dst_place: &Place<'tcx>) {
+        let opt_src_place = items.first().and_then(|x| *x).map(|x| x.2);
+
+        if opt_size.is_some() && items.iter().all(
+            |l| l.is_some() && l.unwrap().2 == opt_src_place.unwrap()) {
+
+            let indicies: Vec<_> = items.iter().map(|x| x.unwrap().1).collect();
+            for i in 1..indicies.len() {
+                if indicies[i - 1] + 1 != indicies[i] {
+                    return;
+                }
+            }
+
+            let min = *indicies.first().unwrap();
+            let max = *indicies.last().unwrap();
+
+            for item in items {
+                let locals_use = item.unwrap().0;
+                patch.make_nop(locals_use.alive.unwrap());
+                patch.make_nop(locals_use.dead.unwrap());
+                patch.make_nop(locals_use.first_use.unwrap());
+            }
+            patch.make_nop(candidate);
+            let size = opt_size.unwrap() as u32;
+            patch.add_assign(candidate,
+                             dst_place.clone(),
+                             Rvalue::Use(
+                                 Operand::Move(
+                                     Place::Projection(box PlaceProjection{
+                                         base: opt_src_place.unwrap().clone(),
+                                         elem: ProjectionElem::Subslice{
+                                             from: min, to: size - max - 1}}))));
+        }
+    }
+
+    fn try_get_item_source<'a, 'tcx>(local_use: &LocalUse,
+                                     mir: &'a Mir<'tcx>) -> Option<(u32, &'a Place<'tcx>)> {
+        if let Some(location) = local_use.first_use {
+            let block = &mir[location.block];
+            if block.statements.len() > location.statement_index {
+                let statement = &block.statements[location.statement_index];
+                if let StatementKind::Assign(
+                    Place::Local(_),
+                    Rvalue::Use(Operand::Move(Place::Projection(box PlaceProjection{
+                        ref base, elem: ProjectionElem::ConstantIndex{
+                            offset, min_length: _, from_end: false}})))) = statement.kind {
+                    return Some((offset, base))
+                }
+            }
+        }
+        None
+    }
+}
+
+#[derive(Copy, Clone, Debug)]
+struct LocalUse {
+    alive: Option<Location>,
+    dead: Option<Location>,
+    use_count: u32,
+    first_use: Option<Location>,
+}
+
+impl LocalUse {
+    pub fn new() -> Self {
+        LocalUse{alive: None, dead: None, use_count: 0, first_use: None}
+    }
+}
+
+struct RestoreDataCollector {
+    locals_use: IndexVec<Local, LocalUse>,
+    candidates: Vec<Location>,
+}
+
+impl<'tcx> Visitor<'tcx> for RestoreDataCollector {
+    fn visit_assign(&mut self,
+                    block: BasicBlock,
+                    place: &Place<'tcx>,
+                    rvalue: &Rvalue<'tcx>,
+                    location: Location) {
+        if let Rvalue::Aggregate(box AggregateKind::Array(_), _) = *rvalue {
+            self.candidates.push(location);
+        }
+        self.super_assign(block, place, rvalue, location)
+    }
+
+    fn visit_local(&mut self,
+                   local: &Local,
+                   context: PlaceContext<'tcx>,
+                   location: Location) {
+        let local_use = &mut self.locals_use[*local];
+        match context {
+            PlaceContext::StorageLive => local_use.alive = Some(location),
+            PlaceContext::StorageDead => local_use.dead = Some(location),
+            _ => {
+                local_use.use_count += 1;
+                if local_use.first_use.is_none() {
+                    local_use.first_use = Some(location);
+                }
+            }
+        }
+    }
+}
index c1e6b4f5a17d933ca2cea989efffa62ab0816a3a..a0fc5533f8e5445ce7923538da20163bd9126f58 100644 (file)
@@ -542,7 +542,7 @@ fn foo<T, T>(s: T, u: T) {} // error: the name `T` is already used for a type
                             //        parameter in this type parameter list
 ```
 
-Please verify that none of the type parameterss are misspelled, and rename any
+Please verify that none of the type parameters are misspelled, and rename any
 clashing parameters. Example:
 
 ```
@@ -551,7 +551,8 @@ fn foo<T, Y>(s: T, u: Y) {} // ok!
 "##,
 
 E0404: r##"
-You tried to implement something which was not a trait on an object.
+You tried to use something which is not a trait in a trait position, such as
+a bound or `impl`.
 
 Erroneous code example:
 
@@ -562,6 +563,14 @@ fn foo<T, Y>(s: T, u: Y) {} // ok!
 impl Foo for Bar {} // error: `Foo` is not a trait
 ```
 
+Another erroneous code example:
+
+```compile_fail,E0404
+struct Foo;
+
+fn bar<T: Foo>(t: T) {} // error: `Foo` is not a trait
+```
+
 Please verify that you didn't misspell the trait's name or otherwise use the
 wrong identifier. Example:
 
@@ -575,6 +584,17 @@ impl Foo for Bar { // ok!
     // functions implementation
 }
 ```
+
+or
+
+```
+trait Foo {
+    // some functions
+}
+
+fn bar<T: Foo>(t: T) {} // ok!
+```
+
 "##,
 
 E0405: r##"
index e4e9ee58330cc58b775692491e72a68164b0b412..42bcc62f291c81e44b4a698cfe6d3181369da6f8 100644 (file)
@@ -2163,6 +2163,7 @@ fn with_current_self_type<T, F>(&mut self, self_type: &Ty, f: F) -> T
         result
     }
 
+    /// This is called to resolve a trait reference from an `impl` (i.e. `impl Trait for Foo`)
     fn with_optional_trait_ref<T, F>(&mut self, opt_trait_ref: Option<&TraitRef>, f: F) -> T
         where F: FnOnce(&mut Resolver, Option<DefId>) -> T
     {
@@ -2172,13 +2173,14 @@ fn with_optional_trait_ref<T, F>(&mut self, opt_trait_ref: Option<&TraitRef>, f:
             let path: Vec<_> = trait_ref.path.segments.iter()
                 .map(|seg| respan(seg.span, seg.identifier))
                 .collect();
-            let def = self.smart_resolve_path_fragment(trait_ref.ref_id,
-                                                       None,
-                                                       &path,
-                                                       trait_ref.path.span,
-                                                       trait_ref.path.segments.last().unwrap().span,
-                                                       PathSource::Trait(AliasPossibility::No))
-                .base_def();
+            let def = self.smart_resolve_path_fragment(
+                trait_ref.ref_id,
+                None,
+                &path,
+                trait_ref.path.span,
+                trait_ref.path.segments.last().unwrap().span,
+                PathSource::Trait(AliasPossibility::No)
+            ).base_def();
             if def != Def::Err {
                 new_id = Some(def.def_id());
                 let span = trait_ref.path.span;
index da01592d9118a9e1e9cd3f804adad15e5732adc2..99e3a59e2c4f42c8dfa08491446aad33e0aa0269 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use common::{C_i32, C_null};
 use libc::c_uint;
 use llvm::{self, ValueRef, BasicBlockRef};
 use llvm::debuginfo::DIScope;
@@ -23,6 +24,7 @@
 use debuginfo::{self, declare_local, VariableAccess, VariableKind, FunctionDebugContext};
 use monomorphize::Instance;
 use abi::{ArgAttribute, FnType, PassMode};
+use type_::Type;
 
 use syntax_pos::{DUMMY_SP, NO_EXPANSION, BytePos, Span};
 use syntax::symbol::keywords;
@@ -222,7 +224,7 @@ pub fn trans_mir<'a, 'tcx: 'a>(
 
     // Compute debuginfo scopes from MIR scopes.
     let scopes = debuginfo::create_mir_scopes(cx, mir, &debug_context);
-    let (landing_pads, funclets) = create_funclets(&bx, &cleanup_kinds, &block_bxs);
+    let (landing_pads, funclets) = create_funclets(mir, &bx, &cleanup_kinds, &block_bxs);
 
     let mut fx = FunctionCx {
         mir,
@@ -333,6 +335,7 @@ pub fn trans_mir<'a, 'tcx: 'a>(
 }
 
 fn create_funclets<'a, 'tcx>(
+    mir: &'a Mir<'tcx>,
     bx: &Builder<'a, 'tcx>,
     cleanup_kinds: &IndexVec<mir::BasicBlock, CleanupKind>,
     block_bxs: &IndexVec<mir::BasicBlock, BasicBlockRef>)
@@ -341,14 +344,59 @@ fn create_funclets<'a, 'tcx>(
 {
     block_bxs.iter_enumerated().zip(cleanup_kinds).map(|((bb, &llbb), cleanup_kind)| {
         match *cleanup_kind {
-            CleanupKind::Funclet if base::wants_msvc_seh(bx.sess()) => {
+            CleanupKind::Funclet if base::wants_msvc_seh(bx.sess()) => {}
+            _ => return (None, None)
+        }
+
+        let cleanup;
+        let ret_llbb;
+        match mir[bb].terminator.as_ref().map(|t| &t.kind) {
+            // This is a basic block that we're aborting the program for,
+            // notably in an `extern` function. These basic blocks are inserted
+            // so that we assert that `extern` functions do indeed not panic,
+            // and if they do we abort the process.
+            //
+            // On MSVC these are tricky though (where we're doing funclets). If
+            // we were to do a cleanuppad (like below) the normal functions like
+            // `longjmp` would trigger the abort logic, terminating the
+            // program. Instead we insert the equivalent of `catch(...)` for C++
+            // which magically doesn't trigger when `longjmp` files over this
+            // frame.
+            //
+            // Lots more discussion can be found on #48251 but this codegen is
+            // modeled after clang's for:
+            //
+            //      try {
+            //          foo();
+            //      } catch (...) {
+            //          bar();
+            //      }
+            Some(&mir::TerminatorKind::Abort) => {
+                let cs_bx = bx.build_sibling_block(&format!("cs_funclet{:?}", bb));
+                let cp_bx = bx.build_sibling_block(&format!("cp_funclet{:?}", bb));
+                ret_llbb = cs_bx.llbb();
+
+                let cs = cs_bx.catch_switch(None, None, 1);
+                cs_bx.add_handler(cs, cp_bx.llbb());
+
+                // The "null" here is actually a RTTI type descriptor for the
+                // C++ personality function, but `catch (...)` has no type so
+                // it's null. The 64 here is actually a bitfield which
+                // represents that this is a catch-all block.
+                let null = C_null(Type::i8p(bx.cx));
+                let sixty_four = C_i32(bx.cx, 64);
+                cleanup = cp_bx.catch_pad(cs, &[null, sixty_four, null]);
+                cp_bx.br(llbb);
+            }
+            _ => {
                 let cleanup_bx = bx.build_sibling_block(&format!("funclet_{:?}", bb));
-                let cleanup = cleanup_bx.cleanup_pad(None, &[]);
+                ret_llbb = cleanup_bx.llbb();
+                cleanup = cleanup_bx.cleanup_pad(None, &[]);
                 cleanup_bx.br(llbb);
-                (Some(cleanup_bx.llbb()), Some(Funclet::new(cleanup)))
             }
-            _ => (None, None)
-        }
+        };
+
+        (Some(ret_llbb), Some(Funclet::new(cleanup)))
     }).unzip()
 }
 
index 650e530519887a71de58fd81c538aa7cf303ae39..782638af13f736daea16db0991fbbba48046cbdf 100644 (file)
@@ -313,7 +313,7 @@ fn create_substs_for_ast_path(&self,
 
     /// Instantiates the path for the given trait reference, assuming that it's
     /// bound to a valid trait type. Returns the def_id for the defining trait.
-    /// Fails if the type is a type other than a trait type.
+    /// The type _cannot_ be a type other than a trait type.
     ///
     /// If the `projections` argument is `None`, then assoc type bindings like `Foo<T=X>`
     /// are disallowed. Otherwise, they are pushed onto the vector given.
@@ -331,6 +331,7 @@ pub fn instantiate_mono_trait_ref(&self,
                                         trait_ref.path.segments.last().unwrap())
     }
 
+    /// Get the DefId of the given trait ref. It _must_ actually be a trait.
     fn trait_def_id(&self, trait_ref: &hir::TraitRef) -> DefId {
         let path = &trait_ref.path;
         match path.def {
@@ -339,13 +340,11 @@ fn trait_def_id(&self, trait_ref: &hir::TraitRef) -> DefId {
             Def::Err => {
                 self.tcx().sess.fatal("cannot continue compilation due to previous error");
             }
-            _ => {
-                span_fatal!(self.tcx().sess, path.span, E0245, "`{}` is not a trait",
-                            self.tcx().hir.node_to_pretty_string(trait_ref.ref_id));
-            }
+            _ => unreachable!(),
         }
     }
 
+    /// The given `trait_ref` must actually be trait.
     pub(super) fn instantiate_poly_trait_ref_inner(&self,
         trait_ref: &hir::TraitRef,
         self_ty: Ty<'tcx>,
index 3668fc46ddc27b0e0fbba290fa762cc4f809f757..39e757c52ff2974ed709d62b6e0d3dbb56d8b781 100644 (file)
@@ -185,10 +185,7 @@ fn check_associated_item(&mut self,
                     reject_shadowing_type_parameters(fcx.tcx, item.def_id);
                     let sig = fcx.tcx.fn_sig(item.def_id);
                     let sig = fcx.normalize_associated_types_in(span, &sig);
-                    let predicates = fcx.tcx.predicates_of(item.def_id)
-                        .instantiate_identity(fcx.tcx);
-                    let predicates = fcx.normalize_associated_types_in(span, &predicates);
-                    this.check_fn_or_method(fcx, span, sig, &predicates,
+                    this.check_fn_or_method(fcx, span, sig,
                                             item.def_id, &mut implied_bounds);
                     let sig_if_method = sig_if_method.expect("bad signature for method");
                     this.check_method_receiver(fcx, sig_if_method, &item, self_ty);
@@ -272,9 +269,7 @@ fn check_type_defn<F>(&mut self, item: &hir::Item, all_sized: bool, mut lookup_f
                 }
             }
 
-            let predicates = fcx.tcx.predicates_of(def_id).instantiate_identity(fcx.tcx);
-            let predicates = fcx.normalize_associated_types_in(item.span, &predicates);
-            this.check_where_clauses(fcx, item.span, &predicates);
+            self.check_where_clauses(fcx, item.span, def_id);
 
             vec![] // no implied bounds in a struct def'n
         });
@@ -282,10 +277,8 @@ fn check_type_defn<F>(&mut self, item: &hir::Item, all_sized: bool, mut lookup_f
 
     fn check_trait(&mut self, item: &hir::Item) {
         let trait_def_id = self.tcx.hir.local_def_id(item.id);
-        self.for_item(item).with_fcx(|fcx, this| {
-            let predicates = fcx.tcx.predicates_of(trait_def_id).instantiate_identity(fcx.tcx);
-            let predicates = fcx.normalize_associated_types_in(item.span, &predicates);
-            this.check_where_clauses(fcx, item.span, &predicates);
+        self.for_item(item).with_fcx(|fcx, _| {
+            self.check_where_clauses(fcx, item.span, trait_def_id);
             vec![]
         });
     }
@@ -295,12 +288,8 @@ fn check_item_fn(&mut self, item: &hir::Item) {
             let def_id = fcx.tcx.hir.local_def_id(item.id);
             let sig = fcx.tcx.fn_sig(def_id);
             let sig = fcx.normalize_associated_types_in(item.span, &sig);
-
-            let predicates = fcx.tcx.predicates_of(def_id).instantiate_identity(fcx.tcx);
-            let predicates = fcx.normalize_associated_types_in(item.span, &predicates);
-
             let mut implied_bounds = vec![];
-            this.check_fn_or_method(fcx, item.span, sig, &predicates,
+            this.check_fn_or_method(fcx, item.span, sig,
                                     def_id, &mut implied_bounds);
             implied_bounds
         })
@@ -354,19 +343,96 @@ fn check_impl(&mut self,
                 }
             }
 
-            let predicates = fcx.tcx.predicates_of(item_def_id).instantiate_identity(fcx.tcx);
-            let predicates = fcx.normalize_associated_types_in(item.span, &predicates);
-            this.check_where_clauses(fcx, item.span, &predicates);
+            this.check_where_clauses(fcx, item.span, item_def_id);
 
             fcx.impl_implied_bounds(item_def_id, item.span)
         });
     }
 
+    /// Checks where clauses and inline bounds that are declared on def_id.
     fn check_where_clauses<'fcx, 'tcx>(&mut self,
                                        fcx: &FnCtxt<'fcx, 'gcx, 'tcx>,
                                        span: Span,
-                                       predicates: &ty::InstantiatedPredicates<'tcx>)
-    {
+                                       def_id: DefId) {
+        use ty::subst::Subst;
+        use rustc::ty::TypeFoldable;
+
+        let mut predicates = fcx.tcx.predicates_of(def_id);
+        let mut substituted_predicates = Vec::new();
+
+        let generics = self.tcx.generics_of(def_id);
+        let is_our_default = |def: &ty::TypeParameterDef|
+                                def.has_default && def.index >= generics.parent_count() as u32;
+
+        // Check that concrete defaults are well-formed. See test `type-check-defaults.rs`.
+        // For example this forbids the declaration:
+        // struct Foo<T = Vec<[u32]>> { .. }
+        // Here the default `Vec<[u32]>` is not WF because `[u32]: Sized` does not hold.
+        for d in generics.types.iter().cloned().filter(is_our_default).map(|p| p.def_id) {
+            let ty = fcx.tcx.type_of(d);
+            // ignore dependent defaults -- that is, where the default of one type
+            // parameter includes another (e.g., <T, U = T>). In those cases, we can't
+            // be sure if it will error or not as user might always specify the other.
+            if !ty.needs_subst() {
+                fcx.register_wf_obligation(ty, fcx.tcx.def_span(d), self.code.clone());
+            }
+        }
+
+        // Check that trait predicates are WF when params are substituted by their defaults.
+        // We don't want to overly constrain the predicates that may be written but we want to
+        // catch cases where a default my never be applied such as `struct Foo<T: Copy = String>`.
+        // Therefore we check if a predicate which contains a single type param
+        // with a concrete default is WF with that default substituted.
+        // For more examples see tests `defaults-well-formedness.rs` and `type-check-defaults.rs`.
+        //
+        // First we build the defaulted substitution.
+        let substs = ty::subst::Substs::for_item(fcx.tcx, def_id, |def, _| {
+                // All regions are identity.
+                fcx.tcx.mk_region(ty::ReEarlyBound(def.to_early_bound_region_data()))
+            }, |def, _| {
+                // If the param has a default,
+                if is_our_default(def) {
+                    let default_ty = fcx.tcx.type_of(def.def_id);
+                    // and it's not a dependent default
+                    if !default_ty.needs_subst() {
+                        // then substitute with the default.
+                        return default_ty;
+                    }
+                }
+                // Mark unwanted params as err.
+                fcx.tcx.types.err
+            });
+        // Now we build the substituted predicates.
+        for &pred in predicates.predicates.iter() {
+            struct CountParams { params: FxHashSet<u32> }
+            impl<'tcx> ty::fold::TypeVisitor<'tcx> for CountParams {
+                fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
+                    match t.sty {
+                        ty::TyParam(p) => {
+                            self.params.insert(p.idx);
+                            t.super_visit_with(self)
+                        }
+                        _ => t.super_visit_with(self)
+                    }
+                }
+            }
+            let mut param_count = CountParams { params: FxHashSet() };
+            pred.visit_with(&mut param_count);
+            let substituted_pred = pred.subst(fcx.tcx, substs);
+            // Don't check non-defaulted params, dependent defaults or preds with multiple params.
+            if substituted_pred.references_error() || param_count.params.len() > 1 {
+                continue;
+            }
+            // Avoid duplication of predicates that contain no parameters, for example.
+            if !predicates.predicates.contains(&substituted_pred) {
+                substituted_predicates.push(substituted_pred);
+            }
+        }
+
+        predicates.predicates.extend(substituted_predicates);
+        let predicates = predicates.instantiate_identity(fcx.tcx);
+        let predicates = fcx.normalize_associated_types_in(span, &predicates);
+
         let obligations =
             predicates.predicates
                       .iter()
@@ -385,7 +451,6 @@ fn check_fn_or_method<'fcx, 'tcx>(&mut self,
                                       fcx: &FnCtxt<'fcx, 'gcx, 'tcx>,
                                       span: Span,
                                       sig: ty::PolyFnSig<'tcx>,
-                                      predicates: &ty::InstantiatedPredicates<'tcx>,
                                       def_id: DefId,
                                       implied_bounds: &mut Vec<Ty<'tcx>>)
     {
@@ -402,7 +467,7 @@ fn check_fn_or_method<'fcx, 'tcx>(&mut self,
         // FIXME(#25759) return types should not be implied bounds
         implied_bounds.push(sig.output());
 
-        self.check_where_clauses(fcx, span, predicates);
+        self.check_where_clauses(fcx, span, def_id);
     }
 
     fn check_method_receiver<'fcx, 'tcx>(&mut self,
index 1c0e084832ebc9cc0fed91ee4ea1b61e895d3ab3..6c195a991c24e9f2b2b8a29a74e55f77d919f24e 100644 (file)
@@ -4802,7 +4802,7 @@ fn is_null(self: *const Self) -> bool {
 //  E0240,
 //  E0241,
 //  E0242,
-    E0245, // not a trait
+//  E0245, // not a trait
 //  E0246, // invalid recursive type
 //  E0247,
 //  E0248, // value used as a type, now reported earlier during resolution as E0412
index 831688bb73d1cd49bb0528e3599101ddddf42bf6..1f73054e3beed01f7e93b253a442992b57b66407 100644 (file)
@@ -17,7 +17,7 @@
 use sync::{Arc, Mutex, MutexGuard};
 use sys::stdio;
 use sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard};
-use thread::{LocalKey, LocalKeyState};
+use thread::LocalKey;
 
 /// Stdout used by print! and println! macros
 thread_local! {
@@ -663,29 +663,31 @@ pub fn set_print(sink: Option<Box<Write + Send>>) -> Option<Box<Write + Send>> {
 ///
 /// This function is used to print error messages, so it takes extra
 /// care to avoid causing a panic when `local_stream` is unusable.
-/// For instance, if the TLS key for the local stream is uninitialized
-/// or already destroyed, or if the local stream is locked by another
+/// For instance, if the TLS key for the local stream is
+/// already destroyed, or if the local stream is locked by another
 /// thread, it will just fall back to the global stream.
 ///
 /// However, if the actual I/O causes an error, this function does panic.
-fn print_to<T>(args: fmt::Arguments,
-               local_s: &'static LocalKey<RefCell<Option<Box<Write+Send>>>>,
-               global_s: fn() -> T,
-               label: &str) where T: Write {
-    let result = match local_s.state() {
-        LocalKeyState::Uninitialized |
-        LocalKeyState::Destroyed => global_s().write_fmt(args),
-        LocalKeyState::Valid => {
-            local_s.with(|s| {
-                if let Ok(mut borrowed) = s.try_borrow_mut() {
-                    if let Some(w) = borrowed.as_mut() {
-                        return w.write_fmt(args);
-                    }
-                }
-                global_s().write_fmt(args)
-            })
+fn print_to<T>(
+    args: fmt::Arguments,
+    local_s: &'static LocalKey<RefCell<Option<Box<Write+Send>>>>,
+    global_s: fn() -> T,
+    label: &str,
+)
+where
+    T: Write,
+{
+    let result = local_s.try_with(|s| {
+        if let Ok(mut borrowed) = s.try_borrow_mut() {
+            if let Some(w) = borrowed.as_mut() {
+                return w.write_fmt(args);
+            }
         }
-    };
+        global_s().write_fmt(args)
+    }).unwrap_or_else(|_| {
+        global_s().write_fmt(args)
+    });
+
     if let Err(e) = result {
         panic!("failed printing to {}: {}", label, e);
     }
index 161c3fc7113a7eea96980c8cefc06b0df55c918e..454ac64735c67900e37f40cf5212da99e247d7fe 100644 (file)
@@ -55,7 +55,8 @@ fn __rust_maybe_catch_panic(f: fn(*mut u8),
                                 data: *mut u8,
                                 data_ptr: *mut usize,
                                 vtable_ptr: *mut usize) -> u32;
-    #[unwind]
+    #[cfg_attr(stage0, unwind)]
+    #[cfg_attr(not(stage0), unwind(allowed))]
     fn __rust_start_panic(data: usize, vtable: usize) -> u32;
 }
 
@@ -315,7 +316,8 @@ pub fn panicking() -> bool {
 /// Entry point of panic from the libcore crate.
 #[cfg(not(test))]
 #[lang = "panic_fmt"]
-#[unwind]
+#[cfg_attr(stage0, unwind)]
+#[cfg_attr(not(stage0), unwind(allowed))]
 pub extern fn rust_begin_panic(msg: fmt::Arguments,
                                file: &'static str,
                                line: u32,
index 4bbad30a5a3152cac16732144274c154196b6bf1..1608a752a463fdac287f7d309d9068fd10a659d8 100644 (file)
@@ -1035,6 +1035,50 @@ fn cmp(&self, other: &Components<'a>) -> cmp::Ordering {
     }
 }
 
+/// An iterator over [`Path`] and its ancestors.
+///
+/// This `struct` is created by the [`ancestors`] method on [`Path`].
+/// See its documentation for more.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(path_ancestors)]
+///
+/// use std::path::Path;
+///
+/// let path = Path::new("/foo/bar");
+///
+/// for ancestor in path.ancestors() {
+///     println!("{}", ancestor.display());
+/// }
+/// ```
+///
+/// [`ancestors`]: struct.Path.html#method.ancestors
+/// [`Path`]: struct.Path.html
+#[derive(Copy, Clone, Debug)]
+#[unstable(feature = "path_ancestors", issue = "48581")]
+pub struct Ancestors<'a> {
+    next: Option<&'a Path>,
+}
+
+#[unstable(feature = "path_ancestors", issue = "48581")]
+impl<'a> Iterator for Ancestors<'a> {
+    type Item = &'a Path;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        let next = self.next;
+        self.next = match next {
+            Some(path) => path.parent(),
+            None => None,
+        };
+        next
+    }
+}
+
+#[unstable(feature = "fused", issue = "35602")]
+impl<'a> FusedIterator for Ancestors<'a> {}
+
 ////////////////////////////////////////////////////////////////////////////////
 // Basic types and traits
 ////////////////////////////////////////////////////////////////////////////////
@@ -1820,6 +1864,37 @@ pub fn parent(&self) -> Option<&Path> {
         })
     }
 
+    /// Produces an iterator over `Path` and its ancestors.
+    ///
+    /// The iterator will yield the `Path` that is returned if the [`parent`] method is used zero
+    /// or more times. That means, the iterator will yield `&self`, `&self.parent().unwrap()`,
+    /// `&self.parent().unwrap().parent().unwrap()` and so on. If the [`parent`] method returns
+    /// [`None`], the iterator will do likewise. The iterator will always yield at least one value,
+    /// namely `&self`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(path_ancestors)]
+    ///
+    /// use std::path::Path;
+    ///
+    /// let mut ancestors = Path::new("/foo/bar").ancestors();
+    /// assert_eq!(ancestors.next(), Some(Path::new("/foo/bar")));
+    /// assert_eq!(ancestors.next(), Some(Path::new("/foo")));
+    /// assert_eq!(ancestors.next(), Some(Path::new("/")));
+    /// assert_eq!(ancestors.next(), None);
+    /// ```
+    ///
+    /// [`None`]: ../../std/option/enum.Option.html#variant.None
+    /// [`parent`]: struct.Path.html#method.parent
+    #[unstable(feature = "path_ancestors", issue = "48581")]
+    pub fn ancestors(&self) -> Ancestors {
+        Ancestors {
+            next: Some(&self),
+        }
+    }
+
     /// Returns the final component of the `Path`, if there is one.
     ///
     /// If the path is a normal file, this is the file name. If it's the path of a directory, this
index fcbca38a98f0bc3b5023246fc6e0e991614e45c8..99479bc56eff30ed9388c04d14168ed90174f331 100644 (file)
@@ -195,64 +195,20 @@ unsafe fn __getit() -> $crate::option::Option<
     }
 }
 
-/// Indicator of the state of a thread local storage key.
-#[unstable(feature = "thread_local_state",
-           reason = "state querying was recently added",
-           issue = "27716")]
-#[derive(Debug, Eq, PartialEq, Copy, Clone)]
-pub enum LocalKeyState {
-    /// All keys are in this state whenever a thread starts. Keys will
-    /// transition to the `Valid` state once the first call to [`with`] happens
-    /// and the initialization expression succeeds.
-    ///
-    /// Keys in the `Uninitialized` state will yield a reference to the closure
-    /// passed to [`with`] so long as the initialization routine does not panic.
-    ///
-    /// [`with`]: ../../std/thread/struct.LocalKey.html#method.with
-    Uninitialized,
-
-    /// Once a key has been accessed successfully, it will enter the `Valid`
-    /// state. Keys in the `Valid` state will remain so until the thread exits,
-    /// at which point the destructor will be run and the key will enter the
-    /// `Destroyed` state.
-    ///
-    /// Keys in the `Valid` state will be guaranteed to yield a reference to the
-    /// closure passed to [`with`].
-    ///
-    /// [`with`]: ../../std/thread/struct.LocalKey.html#method.with
-    Valid,
-
-    /// When a thread exits, the destructors for keys will be run (if
-    /// necessary). While a destructor is running, and possibly after a
-    /// destructor has run, a key is in the `Destroyed` state.
-    ///
-    /// Keys in the `Destroyed` states will trigger a panic when accessed via
-    /// [`with`].
-    ///
-    /// [`with`]: ../../std/thread/struct.LocalKey.html#method.with
-    Destroyed,
-}
-
 /// An error returned by [`LocalKey::try_with`](struct.LocalKey.html#method.try_with).
-#[unstable(feature = "thread_local_state",
-           reason = "state querying was recently added",
-           issue = "27716")]
+#[stable(feature = "thread_local_try_with", since = "1.26.0")]
 pub struct AccessError {
     _private: (),
 }
 
-#[unstable(feature = "thread_local_state",
-           reason = "state querying was recently added",
-           issue = "27716")]
+#[stable(feature = "thread_local_try_with", since = "1.26.0")]
 impl fmt::Debug for AccessError {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.debug_struct("AccessError").finish()
     }
 }
 
-#[unstable(feature = "thread_local_state",
-           reason = "state querying was recently added",
-           issue = "27716")]
+#[stable(feature = "thread_local_try_with", since = "1.26.0")]
 impl fmt::Display for AccessError {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         fmt::Display::fmt("already destroyed", f)
@@ -312,64 +268,21 @@ unsafe fn init(&self, slot: &UnsafeCell<Option<T>>) -> &T {
         (*ptr).as_ref().unwrap()
     }
 
-    /// Query the current state of this key.
-    ///
-    /// A key is initially in the `Uninitialized` state whenever a thread
-    /// starts. It will remain in this state up until the first call to [`with`]
-    /// within a thread has run the initialization expression successfully.
-    ///
-    /// Once the initialization expression succeeds, the key transitions to the
-    /// `Valid` state which will guarantee that future calls to [`with`] will
-    /// succeed within the thread. Some keys might skip the `Uninitialized`
-    /// state altogether and start in the `Valid` state as an optimization
-    /// (e.g. keys initialized with a constant expression), but no guarantees
-    /// are made.
-    ///
-    /// When a thread exits, each key will be destroyed in turn, and as keys are
-    /// destroyed they will enter the `Destroyed` state just before the
-    /// destructor starts to run. Keys may remain in the `Destroyed` state after
-    /// destruction has completed. Keys without destructors (e.g. with types
-    /// that are [`Copy`]), may never enter the `Destroyed` state.
-    ///
-    /// Keys in the `Uninitialized` state can be accessed so long as the
-    /// initialization does not panic. Keys in the `Valid` state are guaranteed
-    /// to be able to be accessed. Keys in the `Destroyed` state will panic on
-    /// any call to [`with`].
-    ///
-    /// [`with`]: ../../std/thread/struct.LocalKey.html#method.with
-    /// [`Copy`]: ../../std/marker/trait.Copy.html
-    #[unstable(feature = "thread_local_state",
-               reason = "state querying was recently added",
-               issue = "27716")]
-    pub fn state(&'static self) -> LocalKeyState {
-        unsafe {
-            match (self.inner)() {
-                Some(cell) => {
-                    match *cell.get() {
-                        Some(..) => LocalKeyState::Valid,
-                        None => LocalKeyState::Uninitialized,
-                    }
-                }
-                None => LocalKeyState::Destroyed,
-            }
-        }
-    }
-
     /// Acquires a reference to the value in this TLS key.
     ///
     /// This will lazily initialize the value if this thread has not referenced
     /// this key yet. If the key has been destroyed (which may happen if this is called
-    /// in a destructor), this function will return a ThreadLocalError.
+    /// in a destructor), this function will return a `ThreadLocalError`.
     ///
     /// # Panics
     ///
     /// This function will still `panic!()` if the key is uninitialized and the
     /// key's initializer panics.
-    #[unstable(feature = "thread_local_state",
-               reason = "state querying was recently added",
-               issue = "27716")]
+    #[stable(feature = "thread_local_try_with", since = "1.26.0")]
     pub fn try_with<F, R>(&'static self, f: F) -> Result<R, AccessError>
-                      where F: FnOnce(&T) -> R {
+    where
+        F: FnOnce(&T) -> R,
+    {
         unsafe {
             let slot = (self.inner)().ok_or(AccessError {
                 _private: (),
@@ -530,7 +443,6 @@ pub unsafe fn get(&'static self) -> Option<&'static UnsafeCell<Option<T>>> {
 mod tests {
     use sync::mpsc::{channel, Sender};
     use cell::{Cell, UnsafeCell};
-    use super::LocalKeyState;
     use thread;
 
     struct Foo(Sender<()>);
@@ -569,21 +481,13 @@ fn states() {
         struct Foo;
         impl Drop for Foo {
             fn drop(&mut self) {
-                assert!(FOO.state() == LocalKeyState::Destroyed);
+                assert!(FOO.try_with(|_| ()).is_err());
             }
         }
-        fn foo() -> Foo {
-            assert!(FOO.state() == LocalKeyState::Uninitialized);
-            Foo
-        }
-        thread_local!(static FOO: Foo = foo());
+        thread_local!(static FOO: Foo = Foo);
 
         thread::spawn(|| {
-            assert!(FOO.state() == LocalKeyState::Uninitialized);
-            FOO.with(|_| {
-                assert!(FOO.state() == LocalKeyState::Valid);
-            });
-            assert!(FOO.state() == LocalKeyState::Valid);
+            assert!(FOO.try_with(|_| ()).is_ok());
         }).join().ok().unwrap();
     }
 
@@ -613,7 +517,7 @@ impl Drop for S1 {
             fn drop(&mut self) {
                 unsafe {
                     HITS += 1;
-                    if K2.state() == LocalKeyState::Destroyed {
+                    if K2.try_with(|_| ()).is_err() {
                         assert_eq!(HITS, 3);
                     } else {
                         if HITS == 1 {
@@ -629,7 +533,7 @@ impl Drop for S2 {
             fn drop(&mut self) {
                 unsafe {
                     HITS += 1;
-                    assert!(K1.state() != LocalKeyState::Destroyed);
+                    assert!(K1.try_with(|_| ()).is_ok());
                     assert_eq!(HITS, 2);
                     K1.with(|s| *s.get() = Some(S1));
                 }
@@ -648,7 +552,7 @@ fn self_referential() {
 
         impl Drop for S1 {
             fn drop(&mut self) {
-                assert!(K1.state() == LocalKeyState::Destroyed);
+                assert!(K1.try_with(|_| ()).is_err());
             }
         }
 
@@ -672,9 +576,7 @@ impl Drop for S1 {
             fn drop(&mut self) {
                 let S1(ref tx) = *self;
                 unsafe {
-                    if K2.state() != LocalKeyState::Destroyed {
-                        K2.with(|s| *s.get() = Some(Foo(tx.clone())));
-                    }
+                    let _ = K2.try_with(|s| *s.get() = Some(Foo(tx.clone())));
                 }
             }
         }
index ff121e2d7ee4e57edec3f1f467be4db462bcdf72..71aee673cfe3ee57e7893a54c1e1823493713693 100644 (file)
 #[macro_use] mod local;
 
 #[stable(feature = "rust1", since = "1.0.0")]
-pub use self::local::{LocalKey, LocalKeyState, AccessError};
+pub use self::local::{LocalKey, AccessError};
 
 // The types used by the thread_local! macro to access TLS keys. Note that there
 // are two types, the "OS" type and the "fast" type. The OS thread local key
index 6609b77b132c62f27dec7f5c3ea4c61c182a1bc9..40000bc378ed0aba6c22f44ee291bae5385b5d9e 100644 (file)
@@ -562,7 +562,7 @@ pub fn walk<F>(&self, it: &mut F) -> bool
             PatKind::TupleStruct(_, ref s, _) | PatKind::Tuple(ref s, _) => {
                 s.iter().all(|p| p.walk(it))
             }
-            PatKind::Box(ref s) | PatKind::Ref(ref s, _) => {
+            PatKind::Box(ref s) | PatKind::Ref(ref s, _) | PatKind::Paren(ref s) => {
                 s.walk(it)
             }
             PatKind::Slice(ref before, ref slice, ref after) => {
@@ -656,6 +656,8 @@ pub enum PatKind {
     /// `[a, b, ..i, y, z]` is represented as:
     ///     `PatKind::Slice(box [a, b], Some(i), box [y, z])`
     Slice(Vec<P<Pat>>, Option<P<Pat>>, Vec<P<Pat>>),
+    /// Parentheses in patters used for grouping, i.e. `(PAT)`.
+    Paren(P<Pat>),
     /// A macro pattern; pre-expansion
     Mac(Mac),
 }
index d18d6f5e6bd0d8a9b05447c6aec2eee9ffded2b3..d0822b69aa692d079bc926331595db5ed2f2cc67 100644 (file)
@@ -565,6 +565,51 @@ pub fn find_inline_attr(diagnostic: Option<&Handler>, attrs: &[Attribute]) -> In
     })
 }
 
+#[derive(Copy, Clone, PartialEq)]
+pub enum UnwindAttr {
+    Allowed,
+    Aborts,
+}
+
+/// Determine what `#[unwind]` attribute is present in `attrs`, if any.
+pub fn find_unwind_attr(diagnostic: Option<&Handler>, attrs: &[Attribute]) -> Option<UnwindAttr> {
+    let syntax_error = |attr: &Attribute| {
+        mark_used(attr);
+        diagnostic.map(|d| {
+            span_err!(d, attr.span, E0633, "malformed `#[unwind]` attribute");
+        });
+        None
+    };
+
+    attrs.iter().fold(None, |ia, attr| {
+        if attr.path != "unwind" {
+            return ia;
+        }
+        let meta = match attr.meta() {
+            Some(meta) => meta.node,
+            None => return ia,
+        };
+        match meta {
+            MetaItemKind::Word => {
+                syntax_error(attr)
+            }
+            MetaItemKind::List(ref items) => {
+                mark_used(attr);
+                if items.len() != 1 {
+                    syntax_error(attr)
+                } else if list_contains_name(&items[..], "allowed") {
+                    Some(UnwindAttr::Allowed)
+                } else if list_contains_name(&items[..], "aborts") {
+                    Some(UnwindAttr::Aborts)
+                } else {
+                    syntax_error(attr)
+                }
+            }
+            _ => ia,
+        }
+    })
+}
+
 /// True if `#[inline]` or `#[inline(always)]` is present in `attrs`.
 pub fn requests_inline(attrs: &[Attribute]) -> bool {
     match find_inline_attr(None, attrs) {
index df5845f6c217d5bfc2b82ca3c2135c0c5f34a415..fcd2b236213c023d81b1f955171076ed3796b875 100644 (file)
@@ -129,7 +129,7 @@ pub struct CodeMap {
     pub(super) files: RefCell<Vec<Rc<FileMap>>>,
     file_loader: Box<FileLoader>,
     // This is used to apply the file path remapping as specified via
-    // -Zremap-path-prefix to all FileMaps allocated within this CodeMap.
+    // --remap-path-prefix to all FileMaps allocated within this CodeMap.
     path_mapping: FilePathMapping,
     stable_id_to_filemap: RefCell<FxHashMap<StableFilemapId, Rc<FileMap>>>,
     /// In case we are in a doctest, replace all file names with the PathBuf,
@@ -705,17 +705,20 @@ fn find_width_of_character_at_span(&self, sp: Span, forwards: bool) -> u32 {
         };
         debug!("find_width_of_character_at_span: snippet=`{:?}`", snippet);
 
-        let file_start_pos = local_begin.fm.start_pos.to_usize();
-        let file_end_pos = local_begin.fm.end_pos.to_usize();
-        debug!("find_width_of_character_at_span: file_start_pos=`{:?}` file_end_pos=`{:?}`",
-               file_start_pos, file_end_pos);
-
         let mut target = if forwards { end_index + 1 } else { end_index - 1 };
         debug!("find_width_of_character_at_span: initial target=`{:?}`", target);
 
-        while !snippet.is_char_boundary(target - start_index)
-                && target >= file_start_pos && target <= file_end_pos {
-            target = if forwards { target + 1 } else { target - 1 };
+        while !snippet.is_char_boundary(target - start_index) && target < source_len {
+            target = if forwards {
+                target + 1
+            } else {
+                match target.checked_sub(1) {
+                    Some(target) => target,
+                    None => {
+                        break;
+                    }
+                }
+            };
             debug!("find_width_of_character_at_span: target=`{:?}`", target);
         }
         debug!("find_width_of_character_at_span: final target=`{:?}`", target);
index d841281e48580f6bc994b8dfdf32103036e9fa7c..84ab0336f1671ceb5ac88a31008ad3be9eb2f9bc 100644 (file)
@@ -342,6 +342,33 @@ fn main() {
 ```
 "##,
 
+E0633: r##"
+The `unwind` attribute was malformed.
+
+Erroneous code example:
+
+```ignore (compile_fail not working here; see Issue #43707)
+#[unwind()] // error: expected one argument
+pub extern fn something() {}
+
+fn main() {}
+```
+
+The `#[unwind]` attribute should be used as follows:
+
+- `#[unwind(aborts)]` -- specifies that if a non-Rust ABI function
+  should abort the process if it attempts to unwind. This is the safer
+  and preferred option.
+
+- `#[unwind(allowed)]` -- specifies that a non-Rust ABI function
+  should be allowed to unwind. This can easily result in Undefined
+  Behavior (UB), so be careful.
+
+NB. The default behavior here is "allowed", but this is unspecified
+and likely to change in the future.
+
+"##,
+
 }
 
 register_diagnostics! {
index 1ebf52e9fe8c016a43512c48e545e10d563a9d48..70ea015de4e309a6b67d8af90a96979b9ef33972 100644 (file)
@@ -233,7 +233,7 @@ pub fn new() -> Features {
     // allow `extern "platform-intrinsic" { ... }`
     (active, platform_intrinsics, "1.4.0", Some(27731)),
 
-    // allow `#[unwind]`
+    // allow `#[unwind(..)]`
     // rust runtime internal
     (active, unwind_attributes, "1.4.0", None),
 
@@ -449,6 +449,9 @@ pub fn new() -> Features {
 
     // Multiple patterns with `|` in `if let` and `while let`
     (active, if_while_or_patterns, "1.26.0", Some(48215)),
+
+    // Parentheses in patterns
+    (active, pattern_parentheses, "1.26.0", None),
 );
 
 declare_features! (
@@ -1663,6 +1666,10 @@ fn visit_pat(&mut self, pattern: &'a ast::Pat) {
                 gate_feature_post!(&self, dotdoteq_in_patterns, pattern.span,
                                    "`..=` syntax in patterns is experimental");
             }
+            PatKind::Paren(..) => {
+                gate_feature_post!(&self, pattern_parentheses, pattern.span,
+                                   "parentheses in patterns are unstable");
+            }
             _ => {}
         }
         visit::walk_pat(self, pattern)
index e8eb75f5e6018e6e97e1c39d6cdbd1caf8d79130..1963ab45f1a3281e7fabf567710b07d9cbf5d4a9 100644 (file)
@@ -1148,6 +1148,7 @@ pub fn noop_fold_pat<T: Folder>(p: P<Pat>, folder: &mut T) -> P<Pat> {
                        slice.map(|x| folder.fold_pat(x)),
                        after.move_map(|x| folder.fold_pat(x)))
             }
+            PatKind::Paren(inner) => PatKind::Paren(folder.fold_pat(inner)),
             PatKind::Mac(mac) => PatKind::Mac(folder.fold_mac(mac))
         },
         span: folder.new_span(span)
index 09dd00fa5fa3a2953b54bd8a7af1994e3579439b..881e3e412d4eb4052db4debcabd1a5a8fcf1e9b3 100644 (file)
@@ -3484,33 +3484,47 @@ fn parse_pats(&mut self) -> PResult<'a, Vec<P<Pat>>> {
         };
     }
 
-    fn parse_pat_tuple_elements(&mut self, unary_needs_comma: bool)
-                                -> PResult<'a, (Vec<P<Pat>>, Option<usize>)> {
-        let mut fields = vec![];
-        let mut ddpos = None;
+    // Parses a parenthesized list of patterns like
+    // `()`, `(p)`, `(p,)`, `(p, q)`, or `(p, .., q)`. Returns:
+    // - a vector of the patterns that were parsed
+    // - an option indicating the index of the `..` element
+    // - a boolean indicating whether a trailing comma was present.
+    // Trailing commas are significant because (p) and (p,) are different patterns.
+    fn parse_parenthesized_pat_list(&mut self) -> PResult<'a, (Vec<P<Pat>>, Option<usize>, bool)> {
+        self.expect(&token::OpenDelim(token::Paren))?;
 
-        while !self.check(&token::CloseDelim(token::Paren)) {
-            if ddpos.is_none() && self.eat(&token::DotDot) {
-                ddpos = Some(fields.len());
-                if self.eat(&token::Comma) {
-                    // `..` needs to be followed by `)` or `, pat`, `..,)` is disallowed.
-                    fields.push(self.parse_pat()?);
+        let mut fields = Vec::new();
+        let mut ddpos = None;
+        let mut trailing_comma = false;
+        loop {
+            if self.eat(&token::DotDot) {
+                if ddpos.is_none() {
+                    ddpos = Some(fields.len());
+                } else {
+                    // Emit a friendly error, ignore `..` and continue parsing
+                    self.span_err(self.prev_span,
+                                  "`..` can only be used once per tuple or tuple struct pattern");
                 }
-            } else if ddpos.is_some() && self.eat(&token::DotDot) {
-                // Emit a friendly error, ignore `..` and continue parsing
-                self.span_err(self.prev_span, "`..` can only be used once per \
-                                               tuple or tuple struct pattern");
-            } else {
+            } else if !self.check(&token::CloseDelim(token::Paren)) {
                 fields.push(self.parse_pat()?);
+            } else {
+                break
             }
 
-            if !self.check(&token::CloseDelim(token::Paren)) ||
-                    (unary_needs_comma && fields.len() == 1 && ddpos.is_none()) {
-                self.expect(&token::Comma)?;
+            trailing_comma = self.eat(&token::Comma);
+            if !trailing_comma {
+                break
             }
         }
 
-        Ok((fields, ddpos))
+        if ddpos == Some(fields.len()) && trailing_comma {
+            // `..` needs to be followed by `)` or `, pat`, `..,)` is disallowed.
+            self.span_err(self.prev_span, "trailing comma is not permitted after `..`");
+        }
+
+        self.expect(&token::CloseDelim(token::Paren))?;
+
+        Ok((fields, ddpos, trailing_comma))
     }
 
     fn parse_pat_vec_elements(
@@ -3714,10 +3728,12 @@ pub fn parse_pat(&mut self) -> PResult<'a, P<Pat>> {
             }
             token::OpenDelim(token::Paren) => {
                 // Parse (pat,pat,pat,...) as tuple pattern
-                self.bump();
-                let (fields, ddpos) = self.parse_pat_tuple_elements(true)?;
-                self.expect(&token::CloseDelim(token::Paren))?;
-                pat = PatKind::Tuple(fields, ddpos);
+                let (fields, ddpos, trailing_comma) = self.parse_parenthesized_pat_list()?;
+                pat = if fields.len() == 1 && ddpos.is_none() && !trailing_comma {
+                    PatKind::Paren(fields.into_iter().nth(0).unwrap())
+                } else {
+                    PatKind::Tuple(fields, ddpos)
+                };
             }
             token::OpenDelim(token::Bracket) => {
                 // Parse [pat,pat,...] as slice pattern
@@ -3807,9 +3823,7 @@ pub fn parse_pat(&mut self) -> PResult<'a, P<Pat>> {
                             return Err(self.fatal("unexpected `(` after qualified path"));
                         }
                         // Parse tuple struct or enum pattern
-                        self.bump();
-                        let (fields, ddpos) = self.parse_pat_tuple_elements(false)?;
-                        self.expect(&token::CloseDelim(token::Paren))?;
+                        let (fields, ddpos, _) = self.parse_parenthesized_pat_list()?;
                         pat = PatKind::TupleStruct(path, fields, ddpos)
                     }
                     _ => pat = PatKind::Path(qself, path),
index 9cad9f46e98cfef05af3906fc9d24a2a763a16d5..77afafbb4e003525fd80f89f0d7e84d978023725 100644 (file)
@@ -2659,6 +2659,11 @@ pub fn print_pat(&mut self, pat: &ast::Pat) -> io::Result<()> {
                                    |s, p| s.print_pat(p))?;
                 self.s.word("]")?;
             }
+            PatKind::Paren(ref inner) => {
+                self.popen()?;
+                self.print_pat(inner)?;
+                self.pclose()?;
+            }
             PatKind::Mac(ref m) => self.print_mac(m, token::Paren)?,
         }
         self.ann.post(self, NodePat(pat))
index 640f90ecb4a4367e57d9b4b32b4f1bf1966f6279..5a24c61cb5aaf8588f28ab255251aadbf2e3ab40 100644 (file)
@@ -425,7 +425,8 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) {
             walk_list!(visitor, visit_pat, tuple_elements);
         }
         PatKind::Box(ref subpattern) |
-        PatKind::Ref(ref subpattern, _) => {
+        PatKind::Ref(ref subpattern, _) |
+        PatKind::Paren(ref subpattern) => {
             visitor.visit_pat(subpattern)
         }
         PatKind::Ident(_, ref pth1, ref optional_subpattern) => {
index 0f6dbc39e217a1a16a3642e3f2257c9107621918..e2c6b1b0c928f793240d697259d0d5dd9c31c5c1 100644 (file)
@@ -670,7 +670,7 @@ pub struct FileMap {
     /// originate from files has names between angle brackets by convention,
     /// e.g. `<anon>`
     pub name: FileName,
-    /// True if the `name` field above has been modified by -Zremap-path-prefix
+    /// True if the `name` field above has been modified by --remap-path-prefix
     pub name_was_remapped: bool,
     /// The unmapped path of the file that the source came from.
     /// Set to `None` if the FileMap was imported from an external crate.
index e6fff7963f79c31e24a0357f66ad078f38f9f868..aa73b11fb3813683534bc7286c502c13d36bfd54 100644 (file)
@@ -83,7 +83,8 @@ pub enum _Unwind_Context {}
 pub type _Unwind_Exception_Cleanup_Fn = extern "C" fn(unwind_code: _Unwind_Reason_Code,
                                                       exception: *mut _Unwind_Exception);
 extern "C" {
-    #[unwind]
+    #[cfg_attr(stage0, unwind)]
+    #[cfg_attr(not(stage0), unwind(allowed))]
     pub fn _Unwind_Resume(exception: *mut _Unwind_Exception) -> !;
     pub fn _Unwind_DeleteException(exception: *mut _Unwind_Exception);
     pub fn _Unwind_GetLanguageSpecificData(ctx: *mut _Unwind_Context) -> *mut c_void;
@@ -220,7 +221,8 @@ pub unsafe fn _Unwind_FindEnclosingFunction(pc: *mut c_void) -> *mut c_void {
 if #[cfg(not(all(target_os = "ios", target_arch = "arm")))] {
     // Not 32-bit iOS
     extern "C" {
-        #[unwind]
+        #[cfg_attr(stage0, unwind)]
+        #[cfg_attr(not(stage0), unwind(allowed))]
         pub fn _Unwind_RaiseException(exception: *mut _Unwind_Exception) -> _Unwind_Reason_Code;
         pub fn _Unwind_Backtrace(trace: _Unwind_Trace_Fn,
                                  trace_argument: *mut c_void)
@@ -229,7 +231,8 @@ pub fn _Unwind_Backtrace(trace: _Unwind_Trace_Fn,
 } else {
     // 32-bit iOS uses SjLj and does not provide _Unwind_Backtrace()
     extern "C" {
-        #[unwind]
+        #[cfg_attr(stage0, unwind)]
+        #[cfg_attr(not(stage0), unwind(allowed))]
         pub fn _Unwind_SjLj_RaiseException(e: *mut _Unwind_Exception) -> _Unwind_Reason_Code;
     }
 
index 7ee31070b2635ea3895e5a5966c87b79a7345b8d..90ee0c75680dce81eea4e1b04ec8eb8271199f7b 100644 (file)
@@ -19,7 +19,7 @@
     fn extern_fn();
 // CHECK-NOT: Function Attrs: nounwind
 // CHECK: declare void @unwinding_extern_fn
-    #[unwind]
+    #[unwind(allowed)]
     fn unwinding_extern_fn();
 }
 
index 5543a091680f17fd52cf6396c2fd7937d7a13e5b..3ef0ff9ef0687164b71b33c5a1a1006eef2ebf41 100644 (file)
@@ -10,7 +10,7 @@
 
 // ignore-tidy-linelength
 
-// compile-flags: -g  -Zremap-path-prefix-from={{cwd}} -Zremap-path-prefix-to=/the/aux-cwd -Zremap-path-prefix-from={{src-base}}/remap_path_prefix/auxiliary -Zremap-path-prefix-to=/the/aux-src
+// compile-flags: -g  --remap-path-prefix={{cwd}}=/the/aux-cwd --remap-path-prefix={{src-base}}/remap_path_prefix/auxiliary=/the/aux-src
 
 #[inline]
 pub fn some_aux_function() -> i32 {
index ea0c9ad2b83244c8902ee0cdf13e95e46cd62fb6..2f46b6c5d48da28412ce3e08d00f337afb4a4c34 100644 (file)
@@ -11,7 +11,7 @@
 // ignore-windows
 // ignore-tidy-linelength
 
-// compile-flags: -g  -C no-prepopulate-passes -Zremap-path-prefix-from={{cwd}} -Zremap-path-prefix-to=/the/cwd -Zremap-path-prefix-from={{src-base}} -Zremap-path-prefix-to=/the/src
+// compile-flags: -g  -C no-prepopulate-passes --remap-path-prefix={{cwd}}=/the/cwd --remap-path-prefix={{src-base}}=/the/src
 // aux-build:remap_path_prefix_aux.rs
 
 extern crate remap_path_prefix_aux;
index 6cd439167314bd9ba4f684f4538b26b1bb8b45b5..0dd1a4e7d73358401a55e57094b95f959414ec07 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 #![feature(dyn_trait)]
+#![allow(bare_trait_object)]
 
 struct Foo;
 
index 1483bf92c9708ec30bd567f7a37563c37f144ca2..c80b334623b43f0112523c34a14907e12180ca95 100644 (file)
@@ -12,7 +12,7 @@
 
 //[rpass1] compile-flags: -g
 //[rpass2] compile-flags: -g
-//[rpass3] compile-flags: -g -Zremap-path-prefix-from={{src-base}} -Zremap-path-prefix-to=/the/src
+//[rpass3] compile-flags: -g --remap-path-prefix={{src-base}}=/the/src
 
 #![feature(rustc_attrs)]
 #![crate_type="rlib"]
index 4a310255aac576a3d3d7ede99bff59ef38f2fb87..482b69a59ddbc1bcdd34a065f669194081758001 100644 (file)
@@ -57,3 +57,28 @@ fn main() {
 //     nop;
 //     _0 = ();
 // END rustc.move_out_by_subslice.UniformArrayMoveOut.after.mir
+
+// START rustc.move_out_by_subslice.RestoreSubsliceArrayMoveOut.before.mir
+//     StorageLive(_6);
+//     StorageLive(_7);
+//     _7 = move _1[0 of 2];
+//     StorageLive(_8);
+//     _8 = move _1[1 of 2];
+//     _6 = [move _7, move _8];
+//     StorageDead(_7);
+//     StorageDead(_8);
+//     _0 = ();
+// END rustc.move_out_by_subslice.RestoreSubsliceArrayMoveOut.before.mir
+
+// START rustc.move_out_by_subslice.RestoreSubsliceArrayMoveOut.after.mir
+//     StorageLive(_6);
+//     nop;
+//     nop;
+//     nop;
+//     nop;
+//     _6 = move _1[0:];
+//     nop;
+//     nop;
+//     nop;
+//     _0 = ();
+// END rustc.move_out_by_subslice.RestoreSubsliceArrayMoveOut.after.mir
index ad52fa578700747983f67ef43593eafc67462e2c..07b391d327984731a650138ebccd55c624fcdc78 100644 (file)
@@ -12,6 +12,6 @@
 
 fn main() {
     match 0 {
-        (pat, ..,) => {} //~ ERROR expected pattern, found `)`
+        (pat, ..,) => {} //~ ERROR trailing comma is not permitted after `..`
     }
 }
diff --git a/src/test/parse-fail/pat-tuple-6.rs b/src/test/parse-fail/pat-tuple-6.rs
deleted file mode 100644 (file)
index 3252d92..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-// 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.
-
-// compile-flags: -Z parse-only
-
-fn main() {
-    match 0 {
-        (pat) => {} //~ ERROR expected one of `,` or `@`, found `)`
-    }
-}
diff --git a/src/test/run-make/longjmp-across-rust/Makefile b/src/test/run-make/longjmp-across-rust/Makefile
new file mode 100644 (file)
index 0000000..9d71ed8
--- /dev/null
@@ -0,0 +1,5 @@
+-include ../tools.mk
+
+all: $(call NATIVE_STATICLIB,foo)
+       $(RUSTC) main.rs
+       $(call RUN,main)
diff --git a/src/test/run-make/longjmp-across-rust/foo.c b/src/test/run-make/longjmp-across-rust/foo.c
new file mode 100644 (file)
index 0000000..eb99395
--- /dev/null
@@ -0,0 +1,28 @@
+// 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.
+
+#include <assert.h>
+#include <setjmp.h>
+
+static jmp_buf ENV;
+
+extern void test_middle();
+
+void test_start(void(*f)()) {
+  if (setjmp(ENV) != 0)
+    return;
+  f();
+  assert(0);
+}
+
+void test_end() {
+  longjmp(ENV, 1);
+  assert(0);
+}
diff --git a/src/test/run-make/longjmp-across-rust/main.rs b/src/test/run-make/longjmp-across-rust/main.rs
new file mode 100644 (file)
index 0000000..c420473
--- /dev/null
@@ -0,0 +1,40 @@
+// 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.
+
+#[link(name = "foo", kind = "static")]
+extern {
+    fn test_start(f: extern fn());
+    fn test_end();
+}
+
+fn main() {
+    unsafe {
+        test_start(test_middle);
+    }
+}
+
+struct A;
+
+impl Drop for A {
+    fn drop(&mut self) {
+    }
+}
+
+extern fn test_middle() {
+    let _a = A;
+    foo();
+}
+
+fn foo() {
+    let _a = A;
+    unsafe {
+        test_end();
+    }
+}
index 17661c0b1209707a36a8068d950429d966fdbf71..ef368ed604bea810890c7df702b1336b9c4e7214 100644 (file)
 // ignore-cloudabi no env and process
 // ignore-emscripten no processes
 
+#![feature(unwind_attributes)]
+
 use std::{env, panic};
 use std::io::prelude::*;
 use std::io;
 use std::process::{Command, Stdio};
 
+#[unwind(aborts)]
 extern "C" fn panic_in_ffi() {
     panic!("Test");
 }
diff --git a/src/test/run-pass/defaults-well-formedness.rs b/src/test/run-pass/defaults-well-formedness.rs
new file mode 100644 (file)
index 0000000..f359467
--- /dev/null
@@ -0,0 +1,30 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait Trait<T> {}
+struct Foo<U, V=i32>(U, V) where U: Trait<V>;
+
+trait Marker {}
+struct TwoParams<T, U>(T, U);
+impl Marker for TwoParams<i32, i32> {}
+
+// Clauses with more than 1 param are not checked.
+struct IndividuallyBogus<T = i32, U = i32>(TwoParams<T, U>) where TwoParams<T, U>: Marker;
+struct BogusTogether<T = u32, U = i32>(T, U) where TwoParams<T, U>: Marker;
+// Clauses with non-defaulted params are not checked.
+struct NonDefaultedInClause<T, U = i32>(TwoParams<T, U>) where TwoParams<T, U>: Marker;
+struct DefaultedLhs<U, V=i32>(U, V) where V: Trait<U>;
+// Dependent defaults are not checked.
+struct Dependent<T, U = T>(T, U) where U: Copy;
+trait SelfBound<T: Copy=Self> {}
+// Not even for well-formedness.
+struct WellFormedProjection<A, T=<A as Iterator>::Item>(A, T);
+
+fn main() {}
diff --git a/src/test/run-pass/issue-48508-aux.rs b/src/test/run-pass/issue-48508-aux.rs
new file mode 100644 (file)
index 0000000..a00361a
--- /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.
+
+// ignore-test Not a test. Used by issue-48508.rs
+
+pub fn other() -> f64 {
+    let ยต = 1.0;
+    ยต
+}
diff --git a/src/test/run-pass/issue-48508.rs b/src/test/run-pass/issue-48508.rs
new file mode 100644 (file)
index 0000000..1b10d87
--- /dev/null
@@ -0,0 +1,28 @@
+// 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.
+
+// Regression test for issue #48508:
+//
+// Confusion between global and local file offsets caused incorrect handling of multibyte character
+// spans when compiling multiple files. One visible effect was an ICE generating debug information
+// when a multibyte character is at the end of a scope. The problematic code is actually in
+// issue-48508-aux.rs
+
+// compile-flags:-g
+// ignore-pretty issue #37195
+
+#![feature(non_ascii_idents)]
+
+#[path = "issue-48508-aux.rs"]
+mod other_file;
+
+fn main() {
+    other_file::other();
+}
diff --git a/src/test/run-pass/issue-48551.rs b/src/test/run-pass/issue-48551.rs
new file mode 100644 (file)
index 0000000..93bddbc
--- /dev/null
@@ -0,0 +1,43 @@
+// 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.
+
+// Regression test for #48551. Covers a case where duplicate candidates
+// arose during associated type projection.
+
+use std::ops::{Mul, MulAssign};
+
+pub trait ClosedMul<Right>: Sized + Mul<Right, Output = Self> + MulAssign<Right> {}
+impl<T, Right> ClosedMul<Right> for T
+where
+    T: Mul<Right, Output = T> + MulAssign<Right>,
+{
+}
+
+pub trait InnerSpace: ClosedMul<<Self as InnerSpace>::Real> {
+    type Real;
+}
+
+pub trait FiniteDimVectorSpace: ClosedMul<<Self as FiniteDimVectorSpace>::Field> {
+    type Field;
+}
+
+pub trait FiniteDimInnerSpace
+    : InnerSpace + FiniteDimVectorSpace<Field = <Self as InnerSpace>::Real> {
+}
+
+pub trait EuclideanSpace: ClosedMul<<Self as EuclideanSpace>::Real> {
+    type Coordinates: FiniteDimInnerSpace<Real = Self::Real>
+        + Mul<Self::Real, Output = Self::Coordinates>
+        + MulAssign<Self::Real>;
+
+    type Real;
+}
+
+fn main() {}
diff --git a/src/test/run-pass/pat-tuple-7.rs b/src/test/run-pass/pat-tuple-7.rs
new file mode 100644 (file)
index 0000000..6d51df6
--- /dev/null
@@ -0,0 +1,17 @@
+// 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.
+
+#![feature(pattern_parentheses)]
+
+fn main() {
+    match 0 {
+        (pat) => assert_eq!(pat, 0)
+    }
+}
index b44c535d3a487f4755b4454cefeb8c0d9e4d5f7c..48a0d4a99ecc9e97a5e15d8bd6f55e6b2751ddb3 100644 (file)
@@ -10,9 +10,9 @@
 
 // ignore-emscripten no threads support
 
-#![feature(thread_local_state)]
+#![feature(thread_local_try_with)]
 
-use std::thread::{self, LocalKeyState};
+use std::thread;
 use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
 
 struct Foo { cnt: usize }
@@ -37,10 +37,8 @@ fn drop(&mut self) {
             FOO.with(|foo| assert_eq!(foo.cnt, 0));
         } else {
             assert_eq!(self.cnt, 0);
-            match FOO.state() {
-                LocalKeyState::Valid => panic!("should not be in valid state"),
-                LocalKeyState::Uninitialized |
-                LocalKeyState::Destroyed => {}
+            if FOO.try_with(|_| ()).is_ok() {
+                panic!("should not be in valid state");
             }
         }
     }
index c072ec0679d73d9c081dfcf53e645adee71e22f5..552f4c5e829e157655c6b4f8b7ba1c6d18239409 100644 (file)
@@ -10,7 +10,7 @@
 
 // ignore-emscripten no threads support
 
-#![feature(thread_local_state)]
+#![feature(thread_local_try_with)]
 
 use std::thread;
 
index c61133f795b345c36676868fb8815d9d86a0b5ef..67b1d2c06e314cb650befe8cfe85160843f96623 100644 (file)
@@ -34,3 +34,4 @@ fn index(&self, i: m!()) -> &m!() {
 }
 
 trait Trait<T> {}
+impl Trait<i32> for i32 {}
index 1c088a71d7d4b1c9681b682c1994df06153e0418..1c6ff5ae8413dec99737f86fc81b0a67810eaee9 100644 (file)
@@ -13,5 +13,6 @@
 
 impl Foo for Bar {} //~ ERROR E0404
 
-fn main() {
-}
+fn main() {}
+
+fn baz<T: Foo>(_: T) {} //~ ERROR E0404
index d49c0f3ea5e19a7e635f94375d130ca723dec026..ac1d2a00cf44842a8f6e36eeb9d0ae6e025ee60d 100644 (file)
@@ -4,6 +4,12 @@ error[E0404]: expected trait, found struct `Foo`
 LL | impl Foo for Bar {} //~ ERROR E0404
    |      ^^^ not a trait
 
+error[E0404]: expected trait, found struct `Foo`
+  --> $DIR/E0404.rs:18:11
+   |
+LL | fn baz<T: Foo>(_: T) {} //~ ERROR E0404
+   |           ^^^ not a trait
+
 error: cannot continue compilation due to previous error
 
 If you want more information on this error, try using "rustc --explain E0404"
diff --git a/src/test/ui/feature-gate-pattern_parentheses.rs b/src/test/ui/feature-gate-pattern_parentheses.rs
new file mode 100644 (file)
index 0000000..2976801
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2017 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() {
+    match 0 {
+        (pat) => {} //~ ERROR parentheses in patterns are unstable
+    }
+}
diff --git a/src/test/ui/feature-gate-pattern_parentheses.stderr b/src/test/ui/feature-gate-pattern_parentheses.stderr
new file mode 100644 (file)
index 0000000..4fc1441
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0658]: parentheses in patterns are unstable
+  --> $DIR/feature-gate-pattern_parentheses.rs:13:9
+   |
+LL |         (pat) => {} //~ ERROR parentheses in patterns are unstable
+   |         ^^^^^
+   |
+   = help: add #![feature(pattern_parentheses)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+If you want more information on this error, try using "rustc --explain E0658"
diff --git a/src/test/ui/type-check-defaults.rs b/src/test/ui/type-check-defaults.rs
new file mode 100644 (file)
index 0000000..f916df5
--- /dev/null
@@ -0,0 +1,37 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::iter::FromIterator;
+use std::vec::IntoIter;
+use std::ops::Add;
+
+struct Foo<T, U: FromIterator<T>>(T, U);
+struct WellFormed<Z = Foo<i32, i32>>(Z);
+//~^ error: the trait bound `i32: std::iter::FromIterator<i32>` is not satisfied [E0277]
+struct WellFormedNoBounds<Z:?Sized = Foo<i32, i32>>(Z);
+//~^ error: the trait bound `i32: std::iter::FromIterator<i32>` is not satisfied [E0277]
+
+struct Bounds<T:Copy=String>(T);
+//~^ error: the trait bound `std::string::String: std::marker::Copy` is not satisfied [E0277]
+
+struct WhereClause<T=String>(T) where T: Copy;
+//~^ error: the trait bound `std::string::String: std::marker::Copy` is not satisfied [E0277]
+
+trait TraitBound<T:Copy=String> {}
+//~^ error: the trait bound `std::string::String: std::marker::Copy` is not satisfied [E0277]
+
+trait Super<T: Copy> { }
+trait Base<T = String>: Super<T> { }
+//~^ error: the trait bound `T: std::marker::Copy` is not satisfied [E0277]
+
+trait ProjectionPred<T:Iterator = IntoIter<i32>> where T::Item : Add<u8> {}
+//~^ error:  cannot add `u8` to `i32` [E0277]
+
+fn main() { }
diff --git a/src/test/ui/type-check-defaults.stderr b/src/test/ui/type-check-defaults.stderr
new file mode 100644 (file)
index 0000000..f39b7dc
--- /dev/null
@@ -0,0 +1,75 @@
+error[E0277]: the trait bound `i32: std::iter::FromIterator<i32>` is not satisfied
+  --> $DIR/type-check-defaults.rs:16:19
+   |
+LL | struct WellFormed<Z = Foo<i32, i32>>(Z);
+   |                   ^ a collection of type `i32` cannot be built from an iterator over elements of type `i32`
+   |
+   = help: the trait `std::iter::FromIterator<i32>` is not implemented for `i32`
+note: required by `Foo`
+  --> $DIR/type-check-defaults.rs:15:1
+   |
+LL | struct Foo<T, U: FromIterator<T>>(T, U);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `i32: std::iter::FromIterator<i32>` is not satisfied
+  --> $DIR/type-check-defaults.rs:18:27
+   |
+LL | struct WellFormedNoBounds<Z:?Sized = Foo<i32, i32>>(Z);
+   |                           ^ a collection of type `i32` cannot be built from an iterator over elements of type `i32`
+   |
+   = help: the trait `std::iter::FromIterator<i32>` is not implemented for `i32`
+note: required by `Foo`
+  --> $DIR/type-check-defaults.rs:15:1
+   |
+LL | struct Foo<T, U: FromIterator<T>>(T, U);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied
+  --> $DIR/type-check-defaults.rs:21:1
+   |
+LL | struct Bounds<T:Copy=String>(T);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String`
+   |
+   = note: required by `std::marker::Copy`
+
+error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied
+  --> $DIR/type-check-defaults.rs:24:1
+   |
+LL | struct WhereClause<T=String>(T) where T: Copy;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String`
+   |
+   = note: required by `std::marker::Copy`
+
+error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied
+  --> $DIR/type-check-defaults.rs:27:1
+   |
+LL | trait TraitBound<T:Copy=String> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String`
+   |
+   = note: required by `std::marker::Copy`
+
+error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
+  --> $DIR/type-check-defaults.rs:31:1
+   |
+LL | trait Base<T = String>: Super<T> { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
+   |
+   = help: consider adding a `where T: std::marker::Copy` bound
+note: required by `Super`
+  --> $DIR/type-check-defaults.rs:30:1
+   |
+LL | trait Super<T: Copy> { }
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: cannot add `u8` to `i32`
+  --> $DIR/type-check-defaults.rs:34:1
+   |
+LL | trait ProjectionPred<T:Iterator = IntoIter<i32>> where T::Item : Add<u8> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `i32 + u8`
+   |
+   = help: the trait `std::ops::Add<u8>` is not implemented for `i32`
+   = note: required by `std::ops::Add`
+
+error: aborting due to 7 previous errors
+
+If you want more information on this error, try using "rustc --explain E0277"
index b90947e5a434a3f03725779456dceb6aa0fe33b9..8e23519f57ebca5130913b5ceda69605ff964cfa 100755 (executable)
@@ -17,6 +17,11 @@ import json
 import copy
 import datetime
 import collections
+import textwrap
+try:
+    import urllib2
+except ImportError:
+    import urllib.request as urllib2
 
 # List of people to ping when the status of a tool changed.
 MAINTAINERS = {
@@ -24,6 +29,10 @@ MAINTAINERS = {
     'clippy-driver': '@Manishearth @llogiq @mcarton @oli-obk',
     'rls': '@nrc',
     'rustfmt': '@nrc',
+    'book': '@carols10cents @steveklabnik',
+    'nomicon': '@frewsxcv @Gankro',
+    'reference': '@steveklabnik @Havvy @matthewjasper @alercah',
+    'rust-by-example': '@steveklabnik @marioidival @projektir',
 }
 
 
@@ -38,7 +47,12 @@ def read_current_status(current_commit, path):
     return {}
 
 
-def update_latest(current_commit, relevant_pr_number, current_datetime):
+def update_latest(
+    current_commit,
+    relevant_pr_number,
+    relevant_pr_url,
+    current_datetime
+):
     '''Updates `_data/latest.json` to match build result of the given commit.
     '''
     with open('_data/latest.json', 'rb+') as f:
@@ -50,8 +64,13 @@ def update_latest(current_commit, relevant_pr_number, current_datetime):
         }
 
         slug = 'rust-lang/rust'
-        message = '๐Ÿ“ฃ Toolstate changed by {}!\n\nTested on commit {}@{}.\n\n' \
-            .format(relevant_pr_number, slug, current_commit)
+        message = textwrap.dedent('''\
+            ๐Ÿ“ฃ Toolstate changed by {}!
+
+            Tested on commit {}@{}.
+            Direct link to PR: <{}>
+
+        ''').format(relevant_pr_number, slug, current_commit, relevant_pr_url)
         anything_changed = False
         for status in latest:
             tool = status['tool']
@@ -68,7 +87,7 @@ def update_latest(current_commit, relevant_pr_number, current_datetime):
                 elif new < old:
                     changed = True
                     message += '๐Ÿ’” {} on {}: {} โ†’ {} (cc {}).\n' \
-                        .format(tool, os, old, new, MAINTAINERS[tool])
+                        .format(tool, os, old, new, MAINTAINERS.get(tool))
 
             if changed:
                 status['commit'] = current_commit
@@ -89,17 +108,41 @@ if __name__ == '__main__':
     cur_datetime = datetime.datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ')
     cur_commit_msg = sys.argv[2]
     save_message_to_path = sys.argv[3]
+    github_token = sys.argv[4]
 
-    relevant_pr_match = re.search('#[0-9]+', cur_commit_msg)
+    relevant_pr_match = re.search('#([0-9]+)', cur_commit_msg)
     if relevant_pr_match:
-        relevant_pr_number = 'rust-lang/rust' + relevant_pr_match.group(0)
+        number = relevant_pr_match.group(1)
+        relevant_pr_number = 'rust-lang/rust#' + number
+        relevant_pr_url = 'https://github.com/rust-lang/rust/pull/' + number
     else:
+        number = '-1'
         relevant_pr_number = '<unknown PR>'
-
-    message = update_latest(cur_commit, relevant_pr_number, cur_datetime)
-    if message:
-        print(message)
-        with open(save_message_to_path, 'w') as f:
-            f.write(message)
-    else:
+        relevant_pr_url = '<unknown>'
+
+    message = update_latest(
+        cur_commit,
+        relevant_pr_number,
+        relevant_pr_url,
+        cur_datetime
+    )
+    if not message:
         print('<Nothing changed>')
+        sys.exit(0)
+
+    print(message)
+    with open(save_message_to_path, 'w') as f:
+        f.write(message)
+
+    # Write the toolstate comment on the PR as well.
+    gh_url = 'https://api.github.com/repos/rust-lang/rust/issues/{}/comments' \
+        .format(number)
+    response = urllib2.urlopen(urllib2.Request(
+        gh_url,
+        json.dumps({'body': message}),
+        {
+            'Authorization': 'token ' + github_token,
+            'Content-Type': 'application/json',
+        }
+    ))
+    response.read()
index f01491115e821e10217574ad4091b08015b7b1c8..d4f0b29d0ce01f0716d3b147d68125d520b63ae5 160000 (submodule)
@@ -1 +1 @@
-Subproject commit f01491115e821e10217574ad4091b08015b7b1c8
+Subproject commit d4f0b29d0ce01f0716d3b147d68125d520b63ae5