]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #63055 - Mark-Simulacrum:save-analysis-clean-2, r=Xanewok
authorMazdak Farrokhzad <twingoow@gmail.com>
Mon, 29 Jul 2019 00:10:54 +0000 (02:10 +0200)
committerGitHub <noreply@github.com>
Mon, 29 Jul 2019 00:10:54 +0000 (02:10 +0200)
Various cleanups to save analysis

370 files changed:
.azure-pipelines/steps/run.yml
Cargo.lock
src/bootstrap/bin/main.rs
src/bootstrap/bin/rustc.rs
src/bootstrap/bin/rustdoc.rs
src/bootstrap/lib.rs
src/build_helper/lib.rs
src/ci/awscli-requirements.txt [deleted file]
src/ci/docker/dist-powerpc-linux/Dockerfile
src/ci/docker/x86_64-gnu-tools/checkregression.py
src/ci/docker/x86_64-gnu-tools/checktools.sh
src/ci/docker/x86_64-gnu-tools/repo.sh
src/ci/install-awscli.sh [new file with mode: 0755]
src/doc/unstable-book/src/language-features/slice-patterns.md
src/liballoc/collections/btree/map.rs
src/liballoc/collections/linked_list.rs
src/liballoc/collections/vec_deque.rs
src/liballoc/lib.rs
src/liballoc/rc.rs
src/liballoc/string.rs
src/liballoc/sync.rs
src/liballoc/tests/lib.rs
src/liballoc/vec.rs
src/libarena/lib.rs
src/libcore/alloc.rs
src/libcore/array.rs
src/libcore/iter/adapters/mod.rs
src/libcore/iter/mod.rs
src/libcore/iter/traits/accum.rs
src/libcore/lib.rs
src/libcore/mem/manually_drop.rs
src/libcore/option.rs
src/libcore/pin.rs
src/libcore/ptr/unique.rs
src/libcore/result.rs
src/libcore/slice/mod.rs
src/libcore/str/lossy.rs
src/libcore/tests/lib.rs
src/libcore/tests/slice.rs
src/libfmt_macros/lib.rs
src/libgraphviz/lib.rs
src/libpanic_abort/lib.rs
src/libpanic_unwind/lib.rs
src/libproc_macro/bridge/scoped_cell.rs
src/libproc_macro/lib.rs
src/libprofiler_builtins/lib.rs
src/librustc/error_codes.rs
src/librustc/hir/intravisit.rs
src/librustc/hir/lowering.rs
src/librustc/hir/map/collector.rs
src/librustc/hir/map/mod.rs
src/librustc/hir/mod.rs
src/librustc/hir/print.rs
src/librustc/lib.rs
src/librustc/lint/context.rs
src/librustc/lint/mod.rs
src/librustc/middle/resolve_lifetime.rs
src/librustc/session/config.rs
src/librustc/ty/query/job.rs
src/librustc_apfloat/lib.rs
src/librustc_asan/lib.rs
src/librustc_ast_borrowck/lib.rs
src/librustc_codegen_llvm/debuginfo/metadata.rs
src/librustc_codegen_llvm/error_codes.rs
src/librustc_codegen_llvm/intrinsic.rs
src/librustc_codegen_llvm/lib.rs
src/librustc_codegen_llvm/llvm/ffi.rs
src/librustc_codegen_llvm/llvm/mod.rs
src/librustc_codegen_llvm/type_.rs
src/librustc_codegen_ssa/back/link.rs
src/librustc_codegen_ssa/back/linker.rs
src/librustc_codegen_ssa/back/mod.rs
src/librustc_codegen_ssa/back/wasm.rs [deleted file]
src/librustc_codegen_ssa/base.rs
src/librustc_codegen_ssa/error_codes.rs
src/librustc_codegen_ssa/lib.rs
src/librustc_codegen_utils/codegen_backend.rs
src/librustc_codegen_utils/lib.rs
src/librustc_data_structures/graph/mod.rs
src/librustc_data_structures/lib.rs
src/librustc_data_structures/owning_ref/mod.rs
src/librustc_data_structures/owning_ref/tests.rs
src/librustc_driver/Cargo.toml
src/librustc_driver/lib.rs
src/librustc_errors/lib.rs
src/librustc_fs_util/lib.rs
src/librustc_incremental/lib.rs
src/librustc_interface/interface.rs
src/librustc_interface/lib.rs
src/librustc_interface/passes.rs
src/librustc_interface/queries.rs
src/librustc_interface/util.rs
src/librustc_lint/lib.rs
src/librustc_llvm/lib.rs
src/librustc_lsan/lib.rs
src/librustc_macros/src/lib.rs
src/librustc_metadata/Cargo.toml
src/librustc_metadata/creader.rs
src/librustc_metadata/cstore_impl.rs
src/librustc_metadata/error_codes.rs
src/librustc_metadata/lib.rs
src/librustc_mir/borrow_check/conflict_errors.rs
src/librustc_mir/borrow_check/nll/type_check/mod.rs
src/librustc_mir/build/mod.rs
src/librustc_mir/error_codes.rs
src/librustc_mir/hair/pattern/mod.rs
src/librustc_mir/lib.rs
src/librustc_msan/lib.rs
src/librustc_passes/Cargo.toml
src/librustc_passes/ast_validation.rs
src/librustc_passes/error_codes.rs
src/librustc_passes/hir_stats.rs
src/librustc_passes/lib.rs
src/librustc_plugin/error_codes.rs
src/librustc_plugin/lib.rs
src/librustc_privacy/error_codes.rs
src/librustc_privacy/lib.rs
src/librustc_resolve/build_reduced_graph.rs
src/librustc_resolve/error_codes.rs
src/librustc_resolve/lib.rs
src/librustc_save_analysis/lib.rs
src/librustc_target/abi/call/hexagon.rs
src/librustc_target/abi/mod.rs
src/librustc_target/lib.rs
src/librustc_target/spec/wasm32_base.rs
src/librustc_traits/lib.rs
src/librustc_tsan/lib.rs
src/librustc_typeck/check/_match.rs
src/librustc_typeck/check/demand.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/error_codes.rs
src/librustc_typeck/lib.rs
src/librustdoc/Cargo.toml
src/librustdoc/html/render.rs
src/librustdoc/lib.rs
src/libserialize/lib.rs
src/libstd/Cargo.toml
src/libstd/build.rs
src/libstd/io/mod.rs
src/libstd/lib.rs
src/libstd/sys/unix/alloc.rs
src/libstd/sys/unix/process/process_unix.rs
src/libstd/sys/wasi/mod.rs
src/libstd/sys/wasm/fast_thread_local.rs [new file with mode: 0644]
src/libstd/sys/wasm/mod.rs
src/libstd/sys/wasm/thread.rs
src/libstd/sys/wasm/thread_local.rs
src/libstd/sys/wasm/thread_local_atomics.rs [deleted file]
src/libstd/time.rs
src/libsyntax/ast.rs
src/libsyntax/diagnostics/plugin.rs
src/libsyntax/error_codes.rs
src/libsyntax/ext/base.rs
src/libsyntax/ext/build.rs
src/libsyntax/ext/derive.rs [deleted file]
src/libsyntax/ext/expand.rs
src/libsyntax/ext/proc_macro.rs [new file with mode: 0644]
src/libsyntax/ext/proc_macro_server.rs [new file with mode: 0644]
src/libsyntax/ext/source_util.rs [deleted file]
src/libsyntax/feature_gate.rs
src/libsyntax/json.rs
src/libsyntax/lib.rs
src/libsyntax/mut_visit.rs
src/libsyntax/parse/attr.rs
src/libsyntax/parse/diagnostics.rs
src/libsyntax/parse/lexer/mod.rs
src/libsyntax/parse/mod.rs
src/libsyntax/parse/parser.rs
src/libsyntax/print/pprust.rs
src/libsyntax/std_inject.rs [deleted file]
src/libsyntax/test.rs [deleted file]
src/libsyntax/visit.rs
src/libsyntax_ext/Cargo.toml
src/libsyntax_ext/deriving/custom.rs [deleted file]
src/libsyntax_ext/deriving/generic/mod.rs
src/libsyntax_ext/deriving/generic/ty.rs
src/libsyntax_ext/deriving/mod.rs
src/libsyntax_ext/error_codes.rs
src/libsyntax_ext/lib.rs
src/libsyntax_ext/proc_macro_decls.rs [deleted file]
src/libsyntax_ext/proc_macro_harness.rs [new file with mode: 0644]
src/libsyntax_ext/proc_macro_impl.rs [deleted file]
src/libsyntax_ext/proc_macro_server.rs [deleted file]
src/libsyntax_ext/source_util.rs [new file with mode: 0644]
src/libsyntax_ext/standard_library_imports.rs [new file with mode: 0644]
src/libsyntax_ext/test.rs
src/libsyntax_ext/test_case.rs [deleted file]
src/libsyntax_ext/test_harness.rs [new file with mode: 0644]
src/libsyntax_pos/lib.rs
src/libterm/lib.rs
src/libtest/lib.rs
src/libunwind/lib.rs
src/llvm-project
src/test/mir-opt/uniform_array_move_out.rs
src/test/run-make-fulldeps/issue-19371/foo.rs
src/test/ui-fulldeps/plugin-as-extern-crate.rs
src/test/ui-fulldeps/plugin-as-extern-crate.stderr
src/test/ui/array-slice-vec/vec-matching-fold.rs
src/test/ui/array-slice-vec/vec-matching-legal-tail-element-borrow.rs
src/test/ui/array-slice-vec/vec-matching.rs
src/test/ui/array-slice-vec/vec-tail-matching.rs
src/test/ui/associated-path-shl.rs
src/test/ui/associated-path-shl.stderr
src/test/ui/async-await/recursive-async-impl-trait-type.stderr
src/test/ui/binding/irrefutable-slice-patterns.rs
src/test/ui/binding/zero_sized_subslice_match.rs
src/test/ui/borrowck/borrowck-describe-lvalue.nll.stderr
src/test/ui/borrowck/borrowck-describe-lvalue.rs
src/test/ui/borrowck/borrowck-describe-lvalue.stderr
src/test/ui/borrowck/borrowck-move-out-from-array.rs
src/test/ui/borrowck/borrowck-move-out-from-array.stderr
src/test/ui/borrowck/borrowck-move-out-of-vec-tail.rs
src/test/ui/borrowck/borrowck-slice-pattern-element-loan-rpass.rs
src/test/ui/borrowck/borrowck-slice-pattern-element-loan.rs
src/test/ui/borrowck/borrowck-slice-pattern-element-loan.stderr
src/test/ui/borrowck/borrowck-vec-pattern-element-loan.rs
src/test/ui/borrowck/borrowck-vec-pattern-loan-from-mut.rs
src/test/ui/borrowck/borrowck-vec-pattern-move-tail.rs
src/test/ui/borrowck/borrowck-vec-pattern-move-tail.stderr
src/test/ui/borrowck/borrowck-vec-pattern-nesting.rs
src/test/ui/borrowck/borrowck-vec-pattern-nesting.stderr
src/test/ui/borrowck/borrowck-vec-pattern-tail-element-loan.rs
src/test/ui/borrowck/return-local-binding-from-desugaring.rs [new file with mode: 0644]
src/test/ui/borrowck/return-local-binding-from-desugaring.stderr [new file with mode: 0644]
src/test/ui/const-generics/array-impls/alloc-traits-impls-length-32.rs [new file with mode: 0644]
src/test/ui/const-generics/array-impls/alloc-traits-no-impls-length-33.rs [new file with mode: 0644]
src/test/ui/const-generics/array-impls/alloc-traits-no-impls-length-33.stderr [new file with mode: 0644]
src/test/ui/drop/dynamic-drop-async.rs
src/test/ui/drop/dynamic-drop.rs
src/test/ui/enable-unstable-lib-feature.rs
src/test/ui/enable-unstable-lib-feature.stderr
src/test/ui/error-codes/E0254.rs
src/test/ui/error-codes/E0259.rs
src/test/ui/error-codes/E0259.stderr
src/test/ui/error-codes/E0260.rs
src/test/ui/error-codes/E0260.stderr
src/test/ui/error-codes/E0528.rs
src/test/ui/error-codes/E0528.stderr
src/test/ui/error-codes/e0119/auxiliary/issue-23563-a.rs
src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision.rs
src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision.stderr
src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision2.rs
src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision2.stderr
src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision3.rs
src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision3.stderr
src/test/ui/feature-gates/feature-gate-slice-patterns.rs
src/test/ui/feature-gates/feature-gate-slice-patterns.stderr
src/test/ui/issues/issue-12369.rs
src/test/ui/issues/issue-12369.stderr
src/test/ui/issues/issue-15080.rs
src/test/ui/issues/issue-15104.rs
src/test/ui/issues/issue-17877.rs
src/test/ui/issues/issue-26158.rs [deleted file]
src/test/ui/issues/issue-26158.stderr [deleted file]
src/test/ui/issues/issue-36881.rs
src/test/ui/issues/issue-36881.stderr
src/test/ui/issues/issue-37598.rs
src/test/ui/issues/issue-45296.stderr
src/test/ui/issues/issue-7784.rs
src/test/ui/lint/lint-stability-deprecated.rs
src/test/ui/lint/lint-stability-deprecated.stderr
src/test/ui/lint/lint-unused-mut-variables.rs
src/test/ui/lint/lint-unused-mut-variables.stderr
src/test/ui/lint/lint-unused-variables.rs [new file with mode: 0644]
src/test/ui/lint/lint-unused-variables.stderr [new file with mode: 0644]
src/test/ui/macros/macro-use-bad-args-1.rs
src/test/ui/macros/macro-use-bad-args-1.stderr
src/test/ui/macros/macro-use-bad-args-2.rs
src/test/ui/macros/macro-use-bad-args-2.stderr
src/test/ui/match/issue-50900.rs [new file with mode: 0644]
src/test/ui/match/issue-50900.stderr [new file with mode: 0644]
src/test/ui/match/match-vec-mismatch.rs
src/test/ui/match/match-vec-mismatch.stderr
src/test/ui/match/match-vec-unreachable.rs
src/test/ui/mismatched_types/issue-38371.stderr
src/test/ui/no-std-inject.rs
src/test/ui/no-std-inject.stderr
src/test/ui/non-exhaustive/non-exhaustive-match.rs
src/test/ui/non-exhaustive/non-exhaustive-pattern-witness.rs
src/test/ui/parser/attr.stderr
src/test/ui/parser/inner-attr-after-doc-comment.stderr
src/test/ui/parser/inner-attr.stderr
src/test/ui/parser/issue-62973.rs [new file with mode: 0644]
src/test/ui/parser/issue-62973.stderr [new file with mode: 0644]
src/test/ui/parser/match-vec-invalid.rs
src/test/ui/parser/match-vec-invalid.stderr
src/test/ui/parser/pat-lt-bracket-6.rs
src/test/ui/parser/pat-lt-bracket-6.stderr
src/test/ui/parser/pat-lt-bracket-7.rs
src/test/ui/parser/pat-lt-bracket-7.stderr
src/test/ui/parser/pat-tuple-2.rs
src/test/ui/parser/pat-tuple-2.stderr [deleted file]
src/test/ui/parser/pat-tuple-3.rs
src/test/ui/parser/pat-tuple-3.stderr
src/test/ui/parser/pat-tuple-4.rs
src/test/ui/parser/pat-tuple-4.stderr
src/test/ui/parser/pat-tuple-5.rs
src/test/ui/parser/pat-tuple-5.stderr
src/test/ui/parser/recover-range-pats.rs [new file with mode: 0644]
src/test/ui/parser/recover-range-pats.stderr [new file with mode: 0644]
src/test/ui/parser/recover-tuple-pat.rs
src/test/ui/parser/recover-tuple-pat.stderr
src/test/ui/resolve/resolve-conflict-extern-crate-vs-extern-crate.rs
src/test/ui/resolve/resolve-conflict-extern-crate-vs-extern-crate.stderr
src/test/ui/resolve_self_super_hint.rs
src/test/ui/resolve_self_super_hint.stderr
src/test/ui/rfc-2005-default-binding-mode/slice.rs
src/test/ui/rfc-2565-param-attrs/param-attrs-allowed.rs
src/test/ui/rfc-2565-param-attrs/param-attrs-cfg.rs
src/test/ui/rfc-2565-param-attrs/param-attrs-cfg.stderr
src/test/ui/rfc-2565-param-attrs/param-attrs-feature-gate.rs
src/test/ui/rfc-2565-param-attrs/param-attrs-feature-gate.stderr
src/test/ui/rfcs/rfc-2005-default-binding-mode/slice.rs
src/test/ui/self/arbitrary_self_types_pin_lifetime.rs [new file with mode: 0644]
src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.nll.stderr [new file with mode: 0644]
src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.rs [new file with mode: 0644]
src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr [new file with mode: 0644]
src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.nll.stderr [new file with mode: 0644]
src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.rs [new file with mode: 0644]
src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.stderr [new file with mode: 0644]
src/test/ui/self/elision/README.md [new file with mode: 0644]
src/test/ui/self/elision/alias.rs [new file with mode: 0644]
src/test/ui/self/elision/assoc.rs [new file with mode: 0644]
src/test/ui/self/elision/lt-alias.rs [new file with mode: 0644]
src/test/ui/self/elision/lt-assoc.rs [new file with mode: 0644]
src/test/ui/self/elision/lt-ref-self.nll.stderr [new file with mode: 0644]
src/test/ui/self/elision/lt-ref-self.rs [new file with mode: 0644]
src/test/ui/self/elision/lt-ref-self.stderr [new file with mode: 0644]
src/test/ui/self/elision/lt-self.rs [new file with mode: 0644]
src/test/ui/self/elision/lt-struct.rs [new file with mode: 0644]
src/test/ui/self/elision/multiple-ref-self.rs [new file with mode: 0644]
src/test/ui/self/elision/ref-alias.rs [new file with mode: 0644]
src/test/ui/self/elision/ref-assoc.rs [new file with mode: 0644]
src/test/ui/self/elision/ref-mut-alias.rs [new file with mode: 0644]
src/test/ui/self/elision/ref-mut-self.nll.stderr [new file with mode: 0644]
src/test/ui/self/elision/ref-mut-self.rs [new file with mode: 0644]
src/test/ui/self/elision/ref-mut-self.stderr [new file with mode: 0644]
src/test/ui/self/elision/ref-mut-struct.nll.stderr [new file with mode: 0644]
src/test/ui/self/elision/ref-mut-struct.rs [new file with mode: 0644]
src/test/ui/self/elision/ref-mut-struct.stderr [new file with mode: 0644]
src/test/ui/self/elision/ref-self.nll.stderr [new file with mode: 0644]
src/test/ui/self/elision/ref-self.rs [new file with mode: 0644]
src/test/ui/self/elision/ref-self.stderr [new file with mode: 0644]
src/test/ui/self/elision/ref-struct.nll.stderr [new file with mode: 0644]
src/test/ui/self/elision/ref-struct.rs [new file with mode: 0644]
src/test/ui/self/elision/ref-struct.stderr [new file with mode: 0644]
src/test/ui/self/elision/self.rs [new file with mode: 0644]
src/test/ui/self/elision/struct.rs [new file with mode: 0644]
src/test/ui/self/self_lifetime.rs [new file with mode: 0644]
src/test/ui/trailing-comma.rs
src/tools/build-manifest/src/main.rs
src/tools/cargotest/main.rs
src/tools/clippy
src/tools/compiletest/src/main.rs
src/tools/error_index_generator/main.rs
src/tools/linkchecker/main.rs
src/tools/publish_toolstate.py
src/tools/remote-test-client/src/main.rs
src/tools/remote-test-server/src/main.rs
src/tools/rustbook/src/main.rs
src/tools/rustc-std-workspace-core/lib.rs
src/tools/rustdoc-themes/main.rs
src/tools/rustdoc/main.rs
src/tools/tidy/src/lib.rs
src/tools/tidy/src/libcoretest.rs [deleted file]
src/tools/tidy/src/main.rs
src/tools/tidy/src/style.rs
src/tools/tidy/src/unit_tests.rs [new file with mode: 0644]
src/tools/unstable-book-gen/src/main.rs
triagebot.toml

index 015fd8348855038e5c3aa79c3cd7a25c56414a56..1e49cc00921cd7ad5a6ff17828aa814eb93df8a4 100644 (file)
@@ -138,43 +138,11 @@ steps:
 
 # Ensure the `aws` CLI is installed so we can deploy later on, cache docker
 # images, etc.
-- bash: |
-    set -e
-    # Temporary code to debug #62967.
-    debug_failed_connections() {
-        echo "trying to ping pypi.org"
-        ping pypi.org -c10 || true
-        echo "trying to ping google.com"
-        ping google.com -c10 || true
-        echo "trying to ping 8.8.8.8"
-        ping 8.8.8.8 -c10 || true
-        echo "trying to download pypi.org"
-        curl https://pypi.org || true
-        echo "trying to download from our S3 bucket"
-        curl https://rust-lang-ci2.s3.amazonaws.com || true
-        echo "trying to dig pypi.org"
-        dig pypi.org || true
-        echo "trying to dig files.pythonhosted.org"
-        dig files.pythonhosted.org || true
-        echo "trying to connect to pypi.org with openssl"
-        echo | openssl s_client -connect pypi.org:443 || true
-        echo "trying to connect to files.pythonhosted.org with openssl"
-        echo | openssl s_client -connect files.pythonhosted.org:443 || true
-    }
-    debug_failed_connections_and_fail() {
-        debug_failed_connections
-        return 1
-    }
-    source src/ci/shared.sh
-    sudo apt-get install -y python3-setuptools
-    debug_failed_connections
-    retry pip3 install -r src/ci/awscli-requirements.txt --upgrade --user || debug_failed_connections_and_fail
-    echo "##vso[task.prependpath]$HOME/.local/bin"
-  displayName: Install awscli (Linux)
-  condition: and(succeeded(), not(variables.SKIP_JOB), eq(variables['Agent.OS'], 'Linux'))
-- script: pip install -r src/ci/awscli-requirements.txt
-  displayName: Install awscli (non-Linux)
-  condition: and(succeeded(), not(variables.SKIP_JOB), ne(variables['Agent.OS'], 'Linux'))
+- bash: src/ci/install-awscli.sh
+  env:
+    AGENT_OS: $(Agent.OS)
+  condition: and(succeeded(), not(variables.SKIP_JOB))
+  displayName: Install awscli
 
 # Configure our CI_JOB_NAME variable which log analyzers can use for the main
 # step to see what's going on.
index 6384560b672b1a97b7afc29fde3a70a680e7f6bb..c08d7444d14eae91f12218f5930c78d51828baef 100644 (file)
@@ -590,7 +590,7 @@ name = "crossbeam-deque"
 version = "0.6.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "crossbeam-epoch 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -610,15 +610,15 @@ dependencies = [
 
 [[package]]
 name = "crossbeam-epoch"
-version = "0.7.0"
+version = "0.7.2"
 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.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1671,6 +1671,14 @@ name = "memoffset"
 version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "memoffset"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "mime"
 version = "0.3.13"
@@ -1692,7 +1700,7 @@ dependencies = [
 
 [[package]]
 name = "minifier"
-version = "0.0.30"
+version = "0.0.33"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "macro-utils 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2863,31 +2871,20 @@ dependencies = [
 name = "rustc_driver"
 version = "0.0.0"
 dependencies = [
- "arena 0.0.0",
  "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "graphviz 0.0.0",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
- "rustc-rayon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_ast_borrowck 0.0.0",
  "rustc_codegen_utils 0.0.0",
  "rustc_data_structures 0.0.0",
  "rustc_errors 0.0.0",
- "rustc_incremental 0.0.0",
  "rustc_interface 0.0.0",
- "rustc_lint 0.0.0",
  "rustc_metadata 0.0.0",
  "rustc_mir 0.0.0",
- "rustc_passes 0.0.0",
- "rustc_plugin 0.0.0",
- "rustc_privacy 0.0.0",
- "rustc_resolve 0.0.0",
  "rustc_save_analysis 0.0.0",
  "rustc_target 0.0.0",
- "rustc_traits 0.0.0",
- "rustc_typeck 0.0.0",
  "serialize 0.0.0",
- "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "syntax 0.0.0",
  "syntax_pos 0.0.0",
 ]
@@ -3019,7 +3016,6 @@ dependencies = [
  "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "stable_deref_trait 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "syntax 0.0.0",
- "syntax_ext 0.0.0",
  "syntax_pos 0.0.0",
 ]
 
@@ -3064,9 +3060,7 @@ dependencies = [
  "rustc 0.0.0",
  "rustc_data_structures 0.0.0",
  "rustc_errors 0.0.0",
- "rustc_mir 0.0.0",
  "syntax 0.0.0",
- "syntax_ext 0.0.0",
  "syntax_pos 0.0.0",
 ]
 
@@ -3201,7 +3195,7 @@ dependencies = [
 name = "rustdoc"
 version = "0.0.0"
 dependencies = [
- "minifier 0.0.30 (registry+https://github.com/rust-lang/crates.io-index)",
+ "minifier 0.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "pulldown-cmark 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-rayon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3312,6 +3306,11 @@ name = "scopeguard"
 version = "0.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "scopeguard"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "security-framework"
 version = "0.3.1"
@@ -4330,7 +4329,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3"
 "checksum crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "05e44b8cf3e1a625844d1750e1f7820da46044ff6d28f4d43e455ba3e5bb2c13"
 "checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150"
-"checksum crossbeam-epoch 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f10a4f8f409aaac4b16a5474fb233624238fcdeefb9ba50d5ea059aab63ba31c"
+"checksum crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9"
 "checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b"
 "checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9"
 "checksum crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c"
@@ -4440,9 +4439,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39"
 "checksum memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2ffa2c986de11a9df78620c01eeaaf27d94d3ff02bf81bfcca953102dd0c6ff"
 "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3"
+"checksum memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ce6075db033bbbb7ee5a0bbd3a3186bbae616f57fb001c485c7ff77955f8177f"
 "checksum mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "3e27ca21f40a310bd06d9031785f4801710d566c184a6e15bad4f1d9b65f9425"
 "checksum mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "30de2e4613efcba1ec63d8133f344076952090c122992a903359be5a4f99c3ed"
-"checksum minifier 0.0.30 (registry+https://github.com/rust-lang/crates.io-index)" = "4c909e78edf61f3aa0dd2086da168cdf304329044bbf248768ca3d20253ec8c0"
+"checksum minifier 0.0.33 (registry+https://github.com/rust-lang/crates.io-index)" = "70bf0db2475f5e627787da77ca52fe33c294063f49f4134b8bc662eedb5e7332"
 "checksum miniz-sys 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "0300eafb20369952951699b68243ab4334f4b10a88f411c221d444b36c40e649"
 "checksum miniz_oxide 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5ad30a47319c16cde58d0314f5d98202a80c9083b5f61178457403dfb14e509c"
 "checksum miniz_oxide_c_api 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "28edaef377517fd9fe3e085c37d892ce7acd1fbeab9239c5a36eec352d8a8b7e"
@@ -4542,6 +4542,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2"
 "checksum scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8"
 "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
+"checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d"
 "checksum security-framework 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eee63d0f4a9ec776eeb30e220f0bc1e092c3ad744b2a379e3993070364d3adc2"
 "checksum security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9636f8989cbf61385ae4824b98c1aaa54c994d7d8b41f11c601ed799f0549a56"
 "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
index 0732cb83f39c63ea3dd7f0ad61d1f28186d73f6d..bd1a87c5744d39d8c1a552a0925ff18a53b627d8 100644 (file)
@@ -5,7 +5,8 @@
 //! parent directory, and otherwise documentation can be found throughout the `build`
 //! directory in each respective module.
 
-#![deny(warnings)]
+// NO-RUSTC-WRAPPER
+#![deny(warnings, rust_2018_idioms, unused_lifetimes)]
 
 use std::env;
 
index a9225f2870f55aa0639e9622eb6805fbcce4c72c..23f81c2c8769242f015a11d28a3b72710ec5cd13 100644 (file)
@@ -15,7 +15,8 @@
 //! switching compilers for the bootstrap and for build scripts will probably
 //! never get replaced.
 
-#![deny(warnings)]
+// NO-RUSTC-WRAPPER
+#![deny(warnings, rust_2018_idioms, unused_lifetimes)]
 
 use std::env;
 use std::ffi::OsString;
@@ -126,8 +127,11 @@ fn main() {
 
     if env::var_os("RUSTC_DENY_WARNINGS").is_some() &&
        env::var_os("RUSTC_EXTERNAL_TOOL").is_none() {
+        // When extending this list, search for `NO-RUSTC-WRAPPER` and add the new lints
+        // there as well, some code doesn't go through this `rustc` wrapper.
         cmd.arg("-Dwarnings");
         cmd.arg("-Drust_2018_idioms");
+        cmd.arg("-Dunused_lifetimes");
         // cfg(not(bootstrap)): Remove this during the next stage 0 compiler update.
         // `-Drustc::internal` is a new feature and `rustc_version` mis-reports the `stage`.
         let cfg_not_bootstrap = stage != "0" && crate_name != Some("rustc_version");
index 1c9f6e1ab285c67a71c5d6cb6b03ad3de13a826a..ff38ee8788f5652c2c551ff3db1a120a89a27c2c 100644 (file)
@@ -2,7 +2,8 @@
 //!
 //! See comments in `src/bootstrap/rustc.rs` for more information.
 
-#![deny(warnings)]
+// NO-RUSTC-WRAPPER
+#![deny(warnings, rust_2018_idioms, unused_lifetimes)]
 
 use std::env;
 use std::process::Command;
index 7011b7f1664c7832ce5fa03c357d468bebad7cb3..c2e64ef51a746e13e5b8aafab226465d9f324553 100644 (file)
 //! More documentation can be found in each respective module below, and you can
 //! also check out the `src/bootstrap/README.md` file for more information.
 
-#![deny(rust_2018_idioms)]
-#![deny(warnings)]
+// NO-RUSTC-WRAPPER
+#![deny(warnings, rust_2018_idioms, unused_lifetimes)]
+
 #![feature(core_intrinsics)]
 #![feature(drain_filter)]
 
@@ -1312,7 +1313,7 @@ fn chmod(path: &Path, perms: u32) {
 fn chmod(_path: &Path, _perms: u32) {}
 
 
-impl<'a> Compiler {
+impl Compiler {
     pub fn with_stage(mut self, stage: u32) -> Compiler {
         self.stage = stage;
         self
index 8b00c1d81b08c4b6baf841b8c94d7b9daa2d5312..c30307f3a1b28d7a09ed09f3631b3bf619bee66b 100644 (file)
@@ -1,4 +1,5 @@
-#![deny(rust_2018_idioms)]
+// NO-RUSTC-WRAPPER
+#![deny(warnings, rust_2018_idioms, unused_lifetimes)]
 
 use std::fs::File;
 use std::path::{Path, PathBuf};
diff --git a/src/ci/awscli-requirements.txt b/src/ci/awscli-requirements.txt
deleted file mode 100644 (file)
index c1ffa52..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-awscli==1.16.201
-botocore==1.12.191
-colorama==0.3.9
-docutils==0.14
-jmespath==0.9.4
-pyasn1==0.4.5
-python-dateutil==2.8.0
-PyYAML==5.1
-rsa==3.4.2
-s3transfer==0.2.1
-six==1.12.0
-urllib3==1.25.3
-futures==3.3.0; python_version < '3.0'
index f03aff060c1034065c5361930ac2fdf917129320..8c052db1b0dde9283d4b856c615ca09db410db23 100644 (file)
@@ -36,7 +36,3 @@ ENV HOSTS=powerpc-unknown-linux-gnu
 
 ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs
 ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS
-
-# FIXME(#36150) this will fail the bootstrap. Probably means something bad is
-#               happening!
-ENV NO_LLVM_ASSERTIONS 1
index 0cc0a6329e5bf779060a19762329296fd935c8dd..4fbb8c4d2034900dda85f48c5d4afa55b2834c4f 100755 (executable)
@@ -1,9 +1,18 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
+## This script has two purposes: detect any tool that *regressed*, which is used
+## during the week before the beta branches to reject PRs; and detect any tool
+## that *changed* to see if we need to update the toolstate repo.
+
 import sys
 import json
 
+# Regressions for these tools during the beta cutoff week do not cause failure.
+# See `status_check` in `checktools.sh` for tools that have to pass on the
+# beta/stable branches.
+REGRESSION_OK = ["rustc-guide", "miri", "embedded-book"]
+
 if __name__ == '__main__':
     os_name = sys.argv[1]
     toolstate_file = sys.argv[2]
@@ -32,7 +41,8 @@ if __name__ == '__main__':
                 'The state of "{}" has {} from "{}" to "{}"'
                 .format(tool, verb, state, new_state)
             )
-            regressed = True
+            if not (verb == 'regressed' and tool in REGRESSION_OK):
+                regressed = True
 
     if regressed:
         sys.exit(1)
index 2191d5d6e4680ce443cdae19d4bdbbccf3d1e1d3..4243effdf9b4b22074af2022a0e49feb53d62580 100755 (executable)
@@ -25,6 +25,7 @@ python2.7 "$X_PY" test --no-fail-fast \
     src/doc/rust-by-example \
     src/doc/embedded-book \
     src/doc/edition-guide \
+    src/doc/rustc-guide \
     src/tools/clippy \
     src/tools/rls \
     src/tools/rustfmt \
@@ -41,7 +42,7 @@ check_tool_failed() {
 }
 
 # This function checks that if a tool's submodule changed, the tool's state must improve
-verify_status() {
+verify_submodule_changed() {
     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'..."
@@ -66,7 +67,7 @@ verify_status() {
 check_dispatch() {
     if [ "$1" = submodule_changed ]; then
         # ignore $2 (branch id)
-        verify_status $3 $4
+        verify_submodule_changed $3 $4
     elif [ "$2" = beta ]; then
         echo "Requiring test passing for $3..."
         if check_tool_failed "$3"; then
@@ -75,7 +76,12 @@ check_dispatch() {
     fi
 }
 
-# list all tools here
+# List all tools here.
+# This function gets called with "submodule_changed" for each PR that changed a submodule,
+# and with "beta_required" for each PR that lands on beta/stable.
+# The purpose of this function is to *reject* PRs if a tool is not "test-pass" and
+# (a) the tool's submodule has been updated, or (b) we landed on beta/stable and the
+# tool has to "test-pass" on that branch.
 status_check() {
     check_dispatch $1 beta book src/doc/book
     check_dispatch $1 beta nomicon src/doc/nomicon
@@ -85,7 +91,10 @@ status_check() {
     check_dispatch $1 beta rls src/tools/rls
     check_dispatch $1 beta rustfmt src/tools/rustfmt
     check_dispatch $1 beta clippy-driver src/tools/clippy
-    # these tools are not required for beta to successfully branch
+    # These tools are not required on the beta/stable branches, but they *do* cause
+    # PRs to fail if a submodule update does not fix them.
+    # They will still cause failure during the beta cutoff week, unless `checkregression.py`
+    # exempts them from that.
     check_dispatch $1 nightly miri src/tools/miri
     check_dispatch $1 nightly embedded-book src/doc/embedded-book
     check_dispatch $1 nightly rustc-guide src/doc/rustc-guide
@@ -97,12 +106,14 @@ status_check() {
 status_check "submodule_changed"
 
 CHECK_NOT="$(readlink -f "$(dirname $0)/checkregression.py")"
+# This callback is called by `commit_toolstate_change`, see `repo.sh`.
 change_toolstate() {
     # only update the history
     if python2.7 "$CHECK_NOT" "$OS" "$TOOLSTATE_FILE" "_data/latest.json" changed; then
         echo 'Toolstate is not changed. Not updating.'
     else
         if [ $SIX_WEEK_CYCLE -ge 35 ]; then
+            # Reject any regressions during the week before beta cutoff.
             python2.7 "$CHECK_NOT" "$OS" "$TOOLSTATE_FILE" "_data/latest.json" regressed
         fi
         sed -i "1 a\\
index 56186a8b6a686b3288807e69bc2731c48d20711a..145f671a8cba59f3a6e900e6bd66e307096f5d0d 100644 (file)
@@ -42,6 +42,13 @@ commit_toolstate_change() {
     MESSAGE_FILE="$1"
     shift
     for RETRY_COUNT in 1 2 3 4 5; do
+        # Call the callback.
+        # - If we are in the `auto` branch (pre-landing), this is called from `checktools.sh` and
+        #   the callback is `change_toolstate` in that file. The purpose of this is to publish the
+        #   test results (the new commit-to-toolstate mapping) in the toolstate repo.
+        # - If we are in the `master` branch (post-landing), this is called by the CI pipeline
+        #   and the callback is `src/tools/publish_toolstate.py`. The purpose is to publish
+        #   the new "current" toolstate in the toolstate repo.
         "$@"
         # `git commit` failing means nothing to commit.
         FAILURE=0
diff --git a/src/ci/install-awscli.sh b/src/ci/install-awscli.sh
new file mode 100755 (executable)
index 0000000..d491b9f
--- /dev/null
@@ -0,0 +1,35 @@
+#!/bin/bash
+# This script downloads and installs awscli from the packages mirrored in our
+# own S3 bucket. This follows the recommendations at:
+#
+#    https://packaging.python.org/guides/index-mirrors-and-caches/#caching-with-pip
+#
+# To create a new mirrored copy you can run the command:
+#
+#    pip wheel awscli
+#
+# Before compressing please make sure all the wheels end with `-none-any.whl`.
+# If that's not the case you'll need to remove the non-cross-platform ones and
+# replace them with the .tar.gz downloaded from https://pypi.org. Also make
+# sure it's possible to call this script with both Python 2 and Python 3.
+
+set -euo pipefail
+IFS=$'\n\t'
+
+MIRROR="https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/2019-07-27-awscli.tar"
+DEPS_DIR="/tmp/awscli-deps"
+
+pip="pip"
+pipflags=""
+if [[ "${AGENT_OS}" == "Linux" ]]; then
+    pip="pip3"
+    pipflags="--user"
+
+    sudo apt-get install -y python3-setuptools
+    echo "##vso[task.prependpath]$HOME/.local/bin"
+fi
+
+mkdir -p "${DEPS_DIR}"
+curl "${MIRROR}" | tar xf - -C "${DEPS_DIR}"
+"${pip}" install ${pipflags} --no-index "--find-links=${DEPS_DIR}" awscli
+rm -rf "${DEPS_DIR}"
index 00c81f03ba17394be62146924357395aa5a0d194..cdb74495884a8e6e8d027992e147814ed44946ee 100644 (file)
@@ -17,7 +17,7 @@ matched against that pattern. For example:
 fn is_symmetric(list: &[u32]) -> bool {
     match list {
         &[] | &[_] => true,
-        &[x, ref inside.., y] if x == y => is_symmetric(inside),
+        &[x, ref inside @ .., y] if x == y => is_symmetric(inside),
         &[..] => false,
     }
 }
index 7cf779b3e72814363f7ca9664ecb07f7ac26df85..1683b8105567f7f10c135f1dd1dca1abea12e13c 100644 (file)
@@ -200,7 +200,7 @@ fn clone_subtree<'a, K: Clone, V: Clone>(
             }
         }
 
-        if self.len() == 0 {
+        if self.is_empty() {
             // Ideally we'd call `BTreeMap::new` here, but that has the `K:
             // Ord` constraint, which this method lacks.
             BTreeMap {
@@ -759,12 +759,12 @@ pub fn remove<Q: ?Sized>(&mut self, key: &Q) -> Option<V>
     #[stable(feature = "btree_append", since = "1.11.0")]
     pub fn append(&mut self, other: &mut Self) {
         // Do we have to append anything at all?
-        if other.len() == 0 {
+        if other.is_empty() {
             return;
         }
 
         // We can just swap `self` and `other` if `self` is empty.
-        if self.len() == 0 {
+        if self.is_empty() {
             mem::swap(self, other);
             return;
         }
index db0d6e2f9b9d4ac7246783c97a13555c0d3974be..bbb96725ea00a6a9e37cf61b6588b65b37c16539 100644 (file)
@@ -237,15 +237,15 @@ unsafe fn unlink_node(&mut self, mut node: NonNull<Node<T>>) {
 
         // Not creating new mutable (unique!) references overlapping `element`.
         match node.prev {
-            Some(prev) => (*prev.as_ptr()).next = node.next.clone(),
+            Some(prev) => (*prev.as_ptr()).next = node.next,
             // this node is the head node
-            None => self.head = node.next.clone(),
+            None => self.head = node.next,
         };
 
         match node.next {
-            Some(next) => (*next.as_ptr()).prev = node.prev.clone(),
+            Some(next) => (*next.as_ptr()).prev = node.prev,
             // this node is the tail node
-            None => self.tail = node.prev.clone(),
+            None => self.tail = node.prev,
         };
 
         self.len -= 1;
index d149f742b01347fea3b3b5a415d251d685e4cdee..495165f7786e0bb21c7b0ce798abc7aea1a69a02 100644 (file)
@@ -9,6 +9,7 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
+use core::array::LengthAtMost32;
 use core::cmp::{self, Ordering};
 use core::fmt;
 use core::iter::{repeat_with, FromIterator, FusedIterator};
@@ -2571,13 +2572,14 @@ fn eq(&self, other: &VecDeque<A>) -> bool {
 impl<A: Eq> Eq for VecDeque<A> {}
 
 macro_rules! __impl_slice_eq1 {
-    ($Lhs: ty, $Rhs: ty) => {
-        __impl_slice_eq1! { $Lhs, $Rhs, Sized }
-    };
-    ($Lhs: ty, $Rhs: ty, $Bound: ident) => {
+    ([$($vars:tt)*] $lhs:ty, $rhs:ty, $($constraints:tt)*) => {
         #[stable(feature = "vec_deque_partial_eq_slice", since = "1.17.0")]
-        impl<A: $Bound, B> PartialEq<$Rhs> for $Lhs where A: PartialEq<B> {
-            fn eq(&self, other: &$Rhs) -> bool {
+        impl<A, B, $($vars)*> PartialEq<$rhs> for $lhs
+        where
+            A: PartialEq<B>,
+            $($constraints)*
+        {
+            fn eq(&self, other: &$rhs) -> bool {
                 if self.len() != other.len() {
                     return false;
                 }
@@ -2589,26 +2591,12 @@ fn eq(&self, other: &$Rhs) -> bool {
     }
 }
 
-__impl_slice_eq1! { VecDeque<A>, Vec<B> }
-__impl_slice_eq1! { VecDeque<A>, &[B] }
-__impl_slice_eq1! { VecDeque<A>, &mut [B] }
-
-macro_rules! array_impls {
-    ($($N: expr)+) => {
-        $(
-            __impl_slice_eq1! { VecDeque<A>, [B; $N] }
-            __impl_slice_eq1! { VecDeque<A>, &[B; $N] }
-            __impl_slice_eq1! { VecDeque<A>, &mut [B; $N] }
-        )+
-    }
-}
-
-array_impls! {
-     0  1  2  3  4  5  6  7  8  9
-    10 11 12 13 14 15 16 17 18 19
-    20 21 22 23 24 25 26 27 28 29
-    30 31 32
-}
+__impl_slice_eq1! { [] VecDeque<A>, Vec<B>, }
+__impl_slice_eq1! { [] VecDeque<A>, &[B], }
+__impl_slice_eq1! { [] VecDeque<A>, &mut [B], }
+__impl_slice_eq1! { [const N: usize] VecDeque<A>, [B; N], [B; N]: LengthAtMost32 }
+__impl_slice_eq1! { [const N: usize] VecDeque<A>, &[B; N], [B; N]: LengthAtMost32 }
+__impl_slice_eq1! { [const N: usize] VecDeque<A>, &mut [B; N], [B; N]: LengthAtMost32 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<A: PartialOrd> PartialOrd for VecDeque<A> {
index dbc1f3b47c80dc0dc36da2c46de85c695ad83c37..c0f345443b90715aeeddefac52f478e5cfd4b160 100644 (file)
@@ -62,8 +62,6 @@
 #![warn(missing_docs)]
 #![warn(missing_debug_implementations)]
 #![deny(intra_doc_link_resolution_failure)] // rustdoc is run without -D warnings
-
-#![deny(rust_2018_idioms)]
 #![allow(explicit_outlives_requirements)]
 
 #![cfg_attr(not(test), feature(generator_trait))]
@@ -78,6 +76,8 @@
 #![feature(cfg_target_has_atomic)]
 #![feature(coerce_unsized)]
 #![cfg_attr(not(bootstrap), feature(const_in_array_repeat_expressions))]
+#![feature(const_generic_impls_guard)]
+#![feature(const_generics)]
 #![feature(dispatch_from_dyn)]
 #![feature(core_intrinsics)]
 #![feature(dropck_eyepatch)]
index 36d5465679581bff307c70718d681a3d62c2ad86..0d0ff7c16f130e5eb8470368e7a2d083a8827369 100644 (file)
@@ -815,7 +815,7 @@ fn drop(&mut self) {
                     let slice = from_raw_parts_mut(self.elems, self.n_elems);
                     ptr::drop_in_place(slice);
 
-                    Global.dealloc(self.mem, self.layout.clone());
+                    Global.dealloc(self.mem, self.layout);
                 }
             }
         }
index 366191e2c85f39f38aa7ad5de472056705b456fd..eca726cd41032f28d1638398de4d593a019af07f 100644 (file)
@@ -1838,6 +1838,7 @@ fn ne(&self, other: &String) -> bool {
 macro_rules! impl_eq {
     ($lhs:ty, $rhs: ty) => {
         #[stable(feature = "rust1", since = "1.0.0")]
+        #[allow(unused_lifetimes)]
         impl<'a, 'b> PartialEq<$rhs> for $lhs {
             #[inline]
             fn eq(&self, other: &$rhs) -> bool { PartialEq::eq(&self[..], &other[..]) }
@@ -1846,6 +1847,7 @@ fn ne(&self, other: &$rhs) -> bool { PartialEq::ne(&self[..], &other[..]) }
         }
 
         #[stable(feature = "rust1", since = "1.0.0")]
+        #[allow(unused_lifetimes)]
         impl<'a, 'b> PartialEq<$lhs> for $rhs {
             #[inline]
             fn eq(&self, other: &$lhs) -> bool { PartialEq::eq(&self[..], &other[..]) }
index 7cb826ee0242ff6b78126861720bfb5a88456c69..93aff73372498c91dab420280c08a9446ca174fa 100644 (file)
@@ -703,7 +703,7 @@ fn drop(&mut self) {
                     let slice = from_raw_parts_mut(self.elems, self.n_elems);
                     ptr::drop_in_place(slice);
 
-                    Global.dealloc(self.mem.cast(), self.layout.clone());
+                    Global.dealloc(self.mem.cast(), self.layout);
                 }
             }
         }
index 5a43c8e09a2a8a5b4b82b655e1adeb1842c974e0..6d774f3fecd9267cf1cf812895100ea6e30e7874 100644 (file)
@@ -8,7 +8,6 @@
 #![feature(trusted_len)]
 #![feature(try_reserve)]
 #![feature(unboxed_closures)]
-#![deny(rust_2018_idioms)]
 
 use std::hash::{Hash, Hasher};
 use std::collections::hash_map::DefaultHasher;
index c076584cc3863bc1c2afe7cb57ccdfbd5d1ad117..dac04e4e624032be1d6222e1bcc019d6400e6939 100644 (file)
@@ -56,6 +56,7 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
+use core::array::LengthAtMost32;
 use core::cmp::{self, Ordering};
 use core::fmt;
 use core::hash::{self, Hash};
@@ -2171,47 +2172,36 @@ fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {
 }
 
 macro_rules! __impl_slice_eq1 {
-    ($Lhs: ty, $Rhs: ty) => {
-        __impl_slice_eq1! { $Lhs, $Rhs, Sized }
-    };
-    ($Lhs: ty, $Rhs: ty, $Bound: ident) => {
+    ([$($vars:tt)*] $lhs:ty, $rhs:ty, $($constraints:tt)*) => {
         #[stable(feature = "rust1", since = "1.0.0")]
-        impl<'a, 'b, A: $Bound, B> PartialEq<$Rhs> for $Lhs where A: PartialEq<B> {
+        impl<A, B, $($vars)*> PartialEq<$rhs> for $lhs
+        where
+            A: PartialEq<B>,
+            $($constraints)*
+        {
             #[inline]
-            fn eq(&self, other: &$Rhs) -> bool { self[..] == other[..] }
+            fn eq(&self, other: &$rhs) -> bool { self[..] == other[..] }
             #[inline]
-            fn ne(&self, other: &$Rhs) -> bool { self[..] != other[..] }
+            fn ne(&self, other: &$rhs) -> bool { self[..] != other[..] }
         }
     }
 }
 
-__impl_slice_eq1! { Vec<A>, Vec<B> }
-__impl_slice_eq1! { Vec<A>, &'b [B] }
-__impl_slice_eq1! { Vec<A>, &'b mut [B] }
-__impl_slice_eq1! { Cow<'a, [A]>, &'b [B], Clone }
-__impl_slice_eq1! { Cow<'a, [A]>, &'b mut [B], Clone }
-__impl_slice_eq1! { Cow<'a, [A]>, Vec<B>, Clone }
+__impl_slice_eq1! { [] Vec<A>, Vec<B>, }
+__impl_slice_eq1! { [] Vec<A>, &[B], }
+__impl_slice_eq1! { [] Vec<A>, &mut [B], }
+__impl_slice_eq1! { [] Cow<'_, [A]>, &[B], A: Clone }
+__impl_slice_eq1! { [] Cow<'_, [A]>, &mut [B], A: Clone }
+__impl_slice_eq1! { [] Cow<'_, [A]>, Vec<B>, A: Clone }
+__impl_slice_eq1! { [const N: usize] Vec<A>, [B; N], [B; N]: LengthAtMost32 }
+__impl_slice_eq1! { [const N: usize] Vec<A>, &[B; N], [B; N]: LengthAtMost32 }
 
-macro_rules! array_impls {
-    ($($N: expr)+) => {
-        $(
-            // NOTE: some less important impls are omitted to reduce code bloat
-            __impl_slice_eq1! { Vec<A>, [B; $N] }
-            __impl_slice_eq1! { Vec<A>, &'b [B; $N] }
-            // __impl_slice_eq1! { Vec<A>, &'b mut [B; $N] }
-            // __impl_slice_eq1! { Cow<'a, [A]>, [B; $N], Clone }
-            // __impl_slice_eq1! { Cow<'a, [A]>, &'b [B; $N], Clone }
-            // __impl_slice_eq1! { Cow<'a, [A]>, &'b mut [B; $N], Clone }
-        )+
-    }
-}
-
-array_impls! {
-     0  1  2  3  4  5  6  7  8  9
-    10 11 12 13 14 15 16 17 18 19
-    20 21 22 23 24 25 26 27 28 29
-    30 31 32
-}
+// NOTE: some less important impls are omitted to reduce code bloat
+// FIXME(Centril): Reconsider this?
+//__impl_slice_eq1! { [const N: usize] Vec<A>, &mut [B; N], [B; N]: LengthAtMost32 }
+//__impl_slice_eq1! { [const N: usize] Cow<'a, [A]>, [B; N], [B; N]: LengthAtMost32 }
+//__impl_slice_eq1! { [const N: usize] Cow<'a, [A]>, &[B; N], [B; N]: LengthAtMost32 }
+//__impl_slice_eq1! { [const N: usize] Cow<'a, [A]>, &mut [B; N], [B; N]: LengthAtMost32 }
 
 /// Implements comparison of vectors, lexicographically.
 #[stable(feature = "rust1", since = "1.0.0")]
index 967b4ad4720521c965be215ff0dc1c6def4ce70a..690d8344acff96b8667fefe0b10f2972a8e0c650 100644 (file)
@@ -11,9 +11,6 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/",
        test(no_crate_inject, attr(deny(warnings))))]
 
-#![deny(rust_2018_idioms)]
-#![deny(unused_lifetimes)]
-
 #![feature(core_intrinsics)]
 #![feature(dropck_eyepatch)]
 #![feature(raw_vec_internals)]
index 487f3b76fc75f7296aa119deb050f71ba6b28936..5d0333d5226d20b43a2a8de996742d5b9fb657e1 100644 (file)
@@ -827,11 +827,11 @@ unsafe fn realloc(&mut self,
         let old_size = layout.size();
 
         if new_size >= old_size {
-            if let Ok(()) = self.grow_in_place(ptr, layout.clone(), new_size) {
+            if let Ok(()) = self.grow_in_place(ptr, layout, new_size) {
                 return Ok(ptr);
             }
         } else if new_size < old_size {
-            if let Ok(()) = self.shrink_in_place(ptr, layout.clone(), new_size) {
+            if let Ok(()) = self.shrink_in_place(ptr, layout, new_size) {
                 return Ok(ptr);
             }
         }
index 6ecc0487fae1b16fdadaf00c94d36a3117a9b373..517893a1967dc63b39801bc06ec2e4e4891a2e70 100644 (file)
@@ -217,7 +217,7 @@ fn into_iter(self) -> IterMut<'a, T> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, 'b, A, B, const N: usize> PartialEq<[B; N]> for [A; N]
+impl<A, B, const N: usize> PartialEq<[B; N]> for [A; N]
 where
     A: PartialEq<B>,
     [A; N]: LengthAtMost32,
@@ -234,7 +234,7 @@ fn into_iter(self) -> IterMut<'a, T> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, 'b, A, B, const N: usize> PartialEq<[B]> for [A; N]
+impl<A, B, const N: usize> PartialEq<[B]> for [A; N]
 where
     A: PartialEq<B>,
     [A; N]: LengthAtMost32,
@@ -250,7 +250,7 @@ fn ne(&self, other: &[B]) -> bool {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, 'b, A, B, const N: usize> PartialEq<[A; N]> for [B]
+impl<A, B, const N: usize> PartialEq<[A; N]> for [B]
 where
     B: PartialEq<A>,
     [A; N]: LengthAtMost32,
@@ -266,7 +266,7 @@ fn ne(&self, other: &[B]) -> bool {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, 'b, A, B, const N: usize> PartialEq<&'b [B]> for [A; N]
+impl<'b, A, B, const N: usize> PartialEq<&'b [B]> for [A; N]
 where
     A: PartialEq<B>,
     [A; N]: LengthAtMost32,
@@ -282,7 +282,7 @@ fn ne(&self, other: &&'b [B]) -> bool {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, 'b, A, B, const N: usize> PartialEq<[A; N]> for &'b [B]
+impl<'b, A, B, const N: usize> PartialEq<[A; N]> for &'b [B]
 where
     B: PartialEq<A>,
     [A; N]: LengthAtMost32,
@@ -298,7 +298,7 @@ fn ne(&self, other: &&'b [B]) -> bool {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, 'b, A, B, const N: usize> PartialEq<&'b mut [B]> for [A; N]
+impl<'b, A, B, const N: usize> PartialEq<&'b mut [B]> for [A; N]
 where
     A: PartialEq<B>,
     [A; N]: LengthAtMost32,
@@ -314,7 +314,7 @@ fn ne(&self, other: &&'b mut [B]) -> bool {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, 'b, A, B, const N: usize> PartialEq<[A; N]> for &'b mut [B]
+impl<'b, A, B, const N: usize> PartialEq<[A; N]> for &'b mut [B]
 where
     B: PartialEq<A>,
     [A; N]: LengthAtMost32,
index c2edcd22f953b45d0fecc20167b3d8eea20af3a9..8eae52ffd3277e43a2b44048a53b83be93a72b8d 100644 (file)
@@ -2062,3 +2062,138 @@ fn is_empty(&self) -> bool {
 #[stable(feature = "fused", since = "1.26.0")]
 impl<I: FusedIterator, F> FusedIterator for Inspect<I, F>
     where F: FnMut(&I::Item) {}
+
+/// An iterator adapter that produces output as long as the underlying
+/// iterator produces `Option::Some` values.
+pub(crate) struct OptionShunt<I> {
+    iter: I,
+    exited_early: bool,
+}
+
+impl<I, T> OptionShunt<I>
+where
+    I: Iterator<Item = Option<T>>,
+{
+    /// Process the given iterator as if it yielded a `T` instead of a
+    /// `Option<T>`. Any `None` value will stop the inner iterator and
+    /// the overall result will be a `None`.
+    pub fn process<F, U>(iter: I, mut f: F) -> Option<U>
+    where
+        F: FnMut(&mut Self) -> U,
+    {
+        let mut shunt = OptionShunt::new(iter);
+        let value = f(shunt.by_ref());
+        shunt.reconstruct(value)
+    }
+
+    fn new(iter: I) -> Self {
+        OptionShunt {
+            iter,
+            exited_early: false,
+        }
+    }
+
+    /// Consume the adapter and rebuild a `Option` value.
+    fn reconstruct<U>(self, val: U) -> Option<U> {
+        if self.exited_early {
+            None
+        } else {
+            Some(val)
+        }
+    }
+}
+
+impl<I, T> Iterator for OptionShunt<I>
+where
+    I: Iterator<Item = Option<T>>,
+{
+    type Item = T;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        match self.iter.next() {
+            Some(Some(v)) => Some(v),
+            Some(None) => {
+                self.exited_early = true;
+                None
+            }
+            None => None,
+        }
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        if self.exited_early {
+            (0, Some(0))
+        } else {
+            let (_, upper) = self.iter.size_hint();
+            (0, upper)
+        }
+    }
+}
+
+/// An iterator adapter that produces output as long as the underlying
+/// iterator produces `Result::Ok` values.
+///
+/// If an error is encountered, the iterator stops and the error is
+/// stored. The error may be recovered later via `reconstruct`.
+pub(crate) struct ResultShunt<I, E> {
+    iter: I,
+    error: Option<E>,
+}
+
+impl<I, T, E> ResultShunt<I, E>
+    where I: Iterator<Item = Result<T, E>>
+{
+    /// Process the given iterator as if it yielded a `T` instead of a
+    /// `Result<T, _>`. Any errors will stop the inner iterator and
+    /// the overall result will be an error.
+    pub fn process<F, U>(iter: I, mut f: F) -> Result<U, E>
+        where F: FnMut(&mut Self) -> U
+    {
+        let mut shunt = ResultShunt::new(iter);
+        let value = f(shunt.by_ref());
+        shunt.reconstruct(value)
+    }
+
+    fn new(iter: I) -> Self {
+        ResultShunt {
+            iter,
+            error: None,
+        }
+    }
+
+    /// Consume the adapter and rebuild a `Result` value. This should
+    /// *always* be called, otherwise any potential error would be
+    /// lost.
+    fn reconstruct<U>(self, val: U) -> Result<U, E> {
+        match self.error {
+            None => Ok(val),
+            Some(e) => Err(e),
+        }
+    }
+}
+
+impl<I, T, E> Iterator for ResultShunt<I, E>
+    where I: Iterator<Item = Result<T, E>>
+{
+    type Item = T;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        match self.iter.next() {
+            Some(Ok(v)) => Some(v),
+            Some(Err(e)) => {
+                self.error = Some(e);
+                None
+            }
+            None => None,
+        }
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        if self.error.is_some() {
+            (0, Some(0))
+        } else {
+            let (_, upper) = self.iter.size_hint();
+            (0, upper)
+        }
+    }
+}
index 6eccb9d1ea86d294c9527dff5361fd870f1d89b7..4a7d7f96b9b041c2a86acab81f9862837171e347 100644 (file)
 #[stable(feature = "iter_copied", since = "1.36.0")]
 pub use self::adapters::Copied;
 
-pub(crate) use self::adapters::TrustedRandomAccess;
+pub(crate) use self::adapters::{TrustedRandomAccess, OptionShunt, ResultShunt};
 
 mod range;
 mod sources;
index adfb639bae341ceb0aca1aea55ef4723d32333d6..01b64fb08acf760da1ab29445a1e4867a8eadc8f 100644 (file)
@@ -1,5 +1,6 @@
 use crate::ops::{Mul, Add};
 use crate::num::Wrapping;
+use crate::iter::adapters::{OptionShunt, ResultShunt};
 
 /// Trait to represent types that can be created by summing up an iterator.
 ///
@@ -114,74 +115,6 @@ fn product<I: Iterator<Item=&'a $a>>(iter: I) -> $a {
 integer_sum_product! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize }
 float_sum_product! { f32 f64 }
 
-/// An iterator adapter that produces output as long as the underlying
-/// iterator produces `Result::Ok` values.
-///
-/// If an error is encountered, the iterator stops and the error is
-/// stored. The error may be recovered later via `reconstruct`.
-struct ResultShunt<I, E> {
-    iter: I,
-    error: Option<E>,
-}
-
-impl<I, T, E> ResultShunt<I, E>
-    where I: Iterator<Item = Result<T, E>>
-{
-    /// Process the given iterator as if it yielded a `T` instead of a
-    /// `Result<T, _>`. Any errors will stop the inner iterator and
-    /// the overall result will be an error.
-    pub fn process<F, U>(iter: I, mut f: F) -> Result<U, E>
-        where F: FnMut(&mut Self) -> U
-    {
-        let mut shunt = ResultShunt::new(iter);
-        let value = f(shunt.by_ref());
-        shunt.reconstruct(value)
-    }
-
-    fn new(iter: I) -> Self {
-        ResultShunt {
-            iter,
-            error: None,
-        }
-    }
-
-    /// Consume the adapter and rebuild a `Result` value. This should
-    /// *always* be called, otherwise any potential error would be
-    /// lost.
-    fn reconstruct<U>(self, val: U) -> Result<U, E> {
-        match self.error {
-            None => Ok(val),
-            Some(e) => Err(e),
-        }
-    }
-}
-
-impl<I, T, E> Iterator for ResultShunt<I, E>
-    where I: Iterator<Item = Result<T, E>>
-{
-    type Item = T;
-
-    fn next(&mut self) -> Option<Self::Item> {
-        match self.iter.next() {
-            Some(Ok(v)) => Some(v),
-            Some(Err(e)) => {
-                self.error = Some(e);
-                None
-            }
-            None => None,
-        }
-    }
-
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        if self.error.is_some() {
-            (0, Some(0))
-        } else {
-            let (_, upper) = self.iter.size_hint();
-            (0, upper)
-        }
-    }
-}
-
 #[stable(feature = "iter_arith_traits_result", since="1.16.0")]
 impl<T, U, E> Sum<Result<U, E>> for Result<T, E>
     where T: Sum<U>,
@@ -224,73 +157,6 @@ fn product<I>(iter: I) -> Result<T, E>
     }
 }
 
-/// An iterator adapter that produces output as long as the underlying
-/// iterator produces `Option::Some` values.
-struct OptionShunt<I> {
-    iter: I,
-    exited_early: bool,
-}
-
-impl<I, T> OptionShunt<I>
-where
-    I: Iterator<Item = Option<T>>,
-{
-    /// Process the given iterator as if it yielded a `T` instead of a
-    /// `Option<T>`. Any `None` value will stop the inner iterator and
-    /// the overall result will be a `None`.
-    pub fn process<F, U>(iter: I, mut f: F) -> Option<U>
-    where
-        F: FnMut(&mut Self) -> U,
-    {
-        let mut shunt = OptionShunt::new(iter);
-        let value = f(shunt.by_ref());
-        shunt.reconstruct(value)
-    }
-
-    fn new(iter: I) -> Self {
-        OptionShunt {
-            iter,
-            exited_early: false,
-        }
-    }
-
-    /// Consume the adapter and rebuild a `Option` value.
-    fn reconstruct<U>(self, val: U) -> Option<U> {
-        if self.exited_early {
-            None
-        } else {
-            Some(val)
-        }
-    }
-}
-
-impl<I, T> Iterator for OptionShunt<I>
-where
-    I: Iterator<Item = Option<T>>,
-{
-    type Item = T;
-
-    fn next(&mut self) -> Option<Self::Item> {
-        match self.iter.next() {
-            Some(Some(v)) => Some(v),
-            Some(None) => {
-                self.exited_early = true;
-                None
-            }
-            None => None,
-        }
-    }
-
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        if self.exited_early {
-            (0, Some(0))
-        } else {
-            let (_, upper) = self.iter.size_hint();
-            (0, upper)
-        }
-    }
-}
-
 #[stable(feature = "iter_arith_traits_option", since = "1.37.0")]
 impl<T, U> Sum<Option<U>> for Option<T>
 where
index 2bb941b490e56097d20a4940bed90eb27393e015..bdfc1e66fd494a7c99efad7d49854739889f542b 100644 (file)
@@ -62,8 +62,6 @@
 #![warn(missing_docs)]
 #![warn(missing_debug_implementations)]
 #![deny(intra_doc_link_resolution_failure)] // rustdoc is run without -D warnings
-
-#![deny(rust_2018_idioms)]
 #![allow(explicit_outlives_requirements)]
 
 #![feature(allow_internal_unstable)]
index 3ad1223e331ece91ca1b996e2e87bcc94c3e5786..bb353993236289b2ae4d131d9d4352fb34b0b8b4 100644 (file)
@@ -119,6 +119,8 @@ impl<T: ?Sized> ManuallyDrop<T> {
     /// This function runs the destructor of the contained value and thus the wrapped value
     /// now represents uninitialized data. It is up to the user of this method to ensure the
     /// uninitialized data is not actually used.
+    /// In particular, this function can only be called called at most once
+    /// for a given instance of `ManuallyDrop<T>`.
     ///
     /// [`ManuallyDrop::into_inner`]: #method.into_inner
     #[stable(feature = "manually_drop", since = "1.20.0")]
index abc8883d3985f2ab447721e32e92b2fb1dc8e094..70a87cfe5a78ab5ca87f0f90edc76ebbae526751 100644 (file)
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-use crate::iter::{FromIterator, FusedIterator, TrustedLen};
+use crate::iter::{FromIterator, FusedIterator, TrustedLen, OptionShunt};
 use crate::{convert, fmt, hint, mem, ops::{self, Deref, DerefMut}};
 use crate::pin::Pin;
 
@@ -1499,45 +1499,7 @@ fn from_iter<I: IntoIterator<Item=Option<A>>>(iter: I) -> Option<V> {
         // FIXME(#11084): This could be replaced with Iterator::scan when this
         // performance bug is closed.
 
-        struct Adapter<Iter> {
-            iter: Iter,
-            found_none: bool,
-        }
-
-        impl<T, Iter: Iterator<Item=Option<T>>> Iterator for Adapter<Iter> {
-            type Item = T;
-
-            #[inline]
-            fn next(&mut self) -> Option<T> {
-                match self.iter.next() {
-                    Some(Some(value)) => Some(value),
-                    Some(None) => {
-                        self.found_none = true;
-                        None
-                    }
-                    None => None,
-                }
-            }
-
-            #[inline]
-            fn size_hint(&self) -> (usize, Option<usize>) {
-                if self.found_none {
-                    (0, Some(0))
-                } else {
-                    let (_, upper) = self.iter.size_hint();
-                    (0, upper)
-                }
-            }
-        }
-
-        let mut adapter = Adapter { iter: iter.into_iter(), found_none: false };
-        let v: V = FromIterator::from_iter(adapter.by_ref());
-
-        if adapter.found_none {
-            None
-        } else {
-            Some(v)
-        }
+        OptionShunt::process(iter.into_iter(), |i| i.collect())
     }
 }
 
index 2feaab7a09c9362d48d273244b7f69901cde7e92..88a56174629f9ed2846008708ba0d07f39b36970 100644 (file)
@@ -775,7 +775,7 @@ impl<P, U> CoerceUnsized<Pin<U>> for Pin<P>
 {}
 
 #[stable(feature = "pin", since = "1.33.0")]
-impl<'a, P, U> DispatchFromDyn<Pin<U>> for Pin<P>
+impl<P, U> DispatchFromDyn<Pin<U>> for Pin<P>
 where
     P: DispatchFromDyn<U>,
 {}
index d2517e51fc5a62801fa8c77018cb79196d532be7..f0d011fe6b2c0c02f779d26ad0a4937e23e54efe 100644 (file)
@@ -172,7 +172,7 @@ fn from(reference: &T) -> Self {
 }
 
 #[unstable(feature = "ptr_internals", issue = "0")]
-impl<'a, T: ?Sized> From<NonNull<T>> for Unique<T> {
+impl<T: ?Sized> From<NonNull<T>> for Unique<T> {
     #[inline]
     fn from(p: NonNull<T>) -> Self {
         unsafe { Unique::new_unchecked(p.as_ptr()) }
index cb6bc058730d147d6cdcef8ead07caefeb9afb99..559877ddd5a1ce0e166dd4afb5d0bf61a72fa4d6 100644 (file)
 #![stable(feature = "rust1", since = "1.0.0")]
 
 use crate::fmt;
-use crate::iter::{FromIterator, FusedIterator, TrustedLen};
+use crate::iter::{FromIterator, FusedIterator, TrustedLen, ResultShunt};
 use crate::ops::{self, Deref, DerefMut};
 
 /// `Result` is a type that represents either success ([`Ok`]) or failure ([`Err`]).
@@ -1343,39 +1343,7 @@ fn from_iter<I: IntoIterator<Item=Result<A, E>>>(iter: I) -> Result<V, E> {
         // FIXME(#11084): This could be replaced with Iterator::scan when this
         // performance bug is closed.
 
-        struct Adapter<Iter, E> {
-            iter: Iter,
-            err: Option<E>,
-        }
-
-        impl<T, E, Iter: Iterator<Item=Result<T, E>>> Iterator for Adapter<Iter, E> {
-            type Item = T;
-
-            #[inline]
-            fn next(&mut self) -> Option<T> {
-                match self.iter.next() {
-                    Some(Ok(value)) => Some(value),
-                    Some(Err(err)) => {
-                        self.err = Some(err);
-                        None
-                    }
-                    None => None,
-                }
-            }
-
-            fn size_hint(&self) -> (usize, Option<usize>) {
-                let (_min, max) = self.iter.size_hint();
-                (0, max)
-            }
-        }
-
-        let mut adapter = Adapter { iter: iter.into_iter(), err: None };
-        let v: V = FromIterator::from_iter(adapter.by_ref());
-
-        match adapter.err {
-            Some(err) => Err(err),
-            None => Ok(v),
-        }
+        ResultShunt::process(iter.into_iter(), |i| i.collect())
     }
 }
 
index e7b820e79e5cf8cc1ded819a456036b4cf1dbd04..b06511cad975ce8120bb845993792e3315354f5d 100644 (file)
@@ -4339,6 +4339,25 @@ fn next_back(&mut self) -> Option<&'a mut [T]> {
             Some(tail)
         }
     }
+
+    #[inline]
+    fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
+        let len = self.len();
+        if n >= len {
+            self.v = &mut [];
+            None
+        } else {
+            let start = (len - 1 - n) * self.chunk_size;
+            let end = match start.checked_add(self.chunk_size) {
+                Some(res) => cmp::min(res, self.v.len()),
+                None => self.v.len(),
+            };
+            let (temp, _tail) = mem::replace(&mut self.v, &mut []).split_at_mut(end);
+            let (head, nth_back) = temp.split_at_mut(start);
+            self.v = head;
+            Some(nth_back)
+        }
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
index b291579553a642b4c78097c15faa5f7d47d002c6..e8f747f1a67d5fc8c73070b4959c63787893f07e 100644 (file)
@@ -46,7 +46,7 @@ impl<'a> Iterator for Utf8LossyChunksIter<'a> {
     type Item = Utf8LossyChunk<'a>;
 
     fn next(&mut self) -> Option<Utf8LossyChunk<'a>> {
-        if self.source.len() == 0 {
+        if self.source.is_empty() {
             return None;
         }
 
@@ -141,7 +141,7 @@ impl fmt::Display for Utf8Lossy {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         // If we're the empty string then our iterator won't actually yield
         // anything, so perform the formatting manually
-        if self.bytes.len() == 0 {
+        if self.bytes.is_empty() {
             return "".fmt(f)
         }
 
index 505f8b0a261d72616d3b26d366ca5a310093ffbb..a3b108b2e9cea00bc07f9e3f55504336c7f5e222 100644 (file)
@@ -32,7 +32,6 @@
 #![feature(const_fn)]
 #![feature(iter_partition_in_place)]
 #![feature(iter_is_partitioned)]
-#![warn(rust_2018_idioms)]
 
 extern crate test;
 
index 42ec9d451f7901dfbb9aeb00ebcb6d083b595290..b046c3ce5ce6ab94a51f285be5cc4e46cc1677d7 100644 (file)
@@ -222,6 +222,28 @@ fn test_chunks_mut_nth() {
     assert_eq!(c2.next(), None);
 }
 
+#[test]
+fn test_chunks_mut_nth_back() {
+    let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
+    let mut c = v.chunks_mut(2);
+    assert_eq!(c.nth_back(1).unwrap(), &[2, 3]);
+    assert_eq!(c.next().unwrap(), &[0, 1]);
+
+    let v1: &mut [i32] = &mut [0, 1, 2, 3, 4];
+    let mut c1 = v1.chunks_mut(3);
+    assert_eq!(c1.nth_back(1).unwrap(), &[0, 1, 2]);
+    assert_eq!(c1.next(), None);
+
+    let v3: &mut [i32] = &mut [0, 1, 2, 3, 4];
+    let mut c3 = v3.chunks_mut(10);
+    assert_eq!(c3.nth_back(0).unwrap(), &[0, 1, 2, 3, 4]);
+    assert_eq!(c3.next(), None);
+
+    let v4: &mut [i32] = &mut [0, 1, 2];
+    let mut c4 = v4.chunks_mut(10);
+    assert_eq!(c4.nth_back(1_000_000_000usize), None);
+}
+
 #[test]
 fn test_chunks_mut_last() {
     let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
index f1c2b1fb8713363a83997e06f234f994f37a05eb..83e24a48ea0085cb2885fd10d8b27ce915ac8a3d 100644 (file)
@@ -8,9 +8,6 @@
        html_playground_url = "https://play.rust-lang.org/",
        test(attr(deny(warnings))))]
 
-#![deny(rust_2018_idioms)]
-#![deny(unused_lifetimes)]
-
 #![feature(nll)]
 #![feature(rustc_private)]
 #![feature(unicode_internals)]
index a34e4fb89ff27457ea5b21ec033438c50f21927f..bb996e5f906d75c888e6b928308d0df2db005462 100644 (file)
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/",
        test(attr(allow(unused_variables), deny(warnings))))]
 
-#![deny(rust_2018_idioms)]
-
 #![feature(nll)]
 
 use LabelText::*;
index 8c20a6ea55ad03cdcd55aa9add54041f46ea6850..ee9dd858ef45fd15be349e6dba2f29296305b7a6 100644 (file)
@@ -10,7 +10,6 @@
 #![panic_runtime]
 
 #![allow(unused_features)]
-#![deny(rust_2018_idioms)]
 
 #![feature(core_intrinsics)]
 #![feature(libc)]
index 2bb9ce6ab220b650a64c950a5a84235aa1e40f8d..06e6e768f459c03a36f4ef3324a95284c4cbd00c 100644 (file)
@@ -17,8 +17,6 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/",
        issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/")]
 
-#![deny(rust_2018_idioms)]
-
 #![feature(core_intrinsics)]
 #![feature(lang_items)]
 #![feature(libc)]
index 89fb707001589339874dbf48609ffd63ebeef200..2cde1f65adf9c484ab0aee45fe6c978fda30cbb9 100644 (file)
@@ -5,6 +5,7 @@
 use std::ops::{Deref, DerefMut};
 
 /// Type lambda application, with a lifetime.
+#[allow(unused_lifetimes)]
 pub trait ApplyL<'a> {
     type Out;
 }
index 2c097238b95b24801d6590aa4b60221699bb5cb4..c0f7714ca211af612fa2cb61fd026056d7ade99e 100644 (file)
@@ -17,8 +17,6 @@
        test(no_crate_inject, attr(deny(warnings))),
        test(attr(allow(dead_code, deprecated, unused_variables, unused_mut))))]
 
-#![deny(rust_2018_idioms)]
-
 #![feature(nll)]
 #![feature(staged_api)]
 #![feature(const_fn)]
index 2ce1a110b44c0c8f8d080599ee008f71a7f0dabb..0d12ba01c87a2ed5deb9ba1cdea6f1d42d8c3114 100644 (file)
@@ -7,4 +7,3 @@
 #![allow(unused_features)]
 #![feature(nll)]
 #![feature(staged_api)]
-#![deny(rust_2018_idioms)]
index 655028324e157f84371c3caff798c9564ddd87ad..1edadbd5bae1a9aca5d20b9cb57f1920d5b22bb3 100644 (file)
@@ -1,5 +1,3 @@
-#![allow(non_snake_case)]
-
 // Error messages for EXXXX errors.
 // Each message should start and end with a new line, and be wrapped to 80 characters.
 // In vim you can `:set tw=80` and use `gq` to wrap paragraphs. Use `:set tw=0` to disable.
index 2d82314f86ac233887006f1b686eb2011b28ec65..3781d7df1764c7a49ff0cbc96a677ac9866d1a61 100644 (file)
@@ -210,6 +210,10 @@ fn visit_nested_body(&mut self, id: BodyId) {
         }
     }
 
+    fn visit_arg(&mut self, arg: &'v Arg) {
+        walk_arg(self, arg)
+    }
+
     /// Visits the top-level item and (optionally) nested items / impl items. See
     /// `visit_nested_item` for details.
     fn visit_item(&mut self, i: &'v Item) {
@@ -396,10 +400,7 @@ pub fn walk_mod<'v, V: Visitor<'v>>(visitor: &mut V, module: &'v Mod, mod_hir_id
 }
 
 pub fn walk_body<'v, V: Visitor<'v>>(visitor: &mut V, body: &'v Body) {
-    for argument in &body.arguments {
-        visitor.visit_id(argument.hir_id);
-        visitor.visit_pat(&argument.pat);
-    }
+    walk_list!(visitor, visit_arg, &body.arguments);
     visitor.visit_expr(&body.value);
 }
 
@@ -452,6 +453,12 @@ pub fn walk_trait_ref<'v, V>(visitor: &mut V, trait_ref: &'v TraitRef)
     visitor.visit_path(&trait_ref.path, trait_ref.hir_ref_id)
 }
 
+pub fn walk_arg<'v, V: Visitor<'v>>(visitor: &mut V, arg: &'v Arg) {
+    visitor.visit_id(arg.hir_id);
+    visitor.visit_pat(&arg.pat);
+    walk_list!(visitor, visit_attribute, &arg.attrs);
+}
+
 pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
     visitor.visit_vis(&item.vis);
     visitor.visit_ident(item.ident);
index 639994ed14d86dac521ccc67afed785a24e41d0a..4ddd7818bb1aa8f2f7fa33192c1f9fdd37c753b4 100644 (file)
 use smallvec::SmallVec;
 use syntax::attr;
 use syntax::ast;
+use syntax::ptr::P as AstP;
 use syntax::ast::*;
 use syntax::errors;
 use syntax::ext::hygiene::ExpnId;
 use syntax::print::pprust;
 use syntax::source_map::{respan, ExpnInfo, ExpnKind, DesugaringKind, Spanned};
-use syntax::std_inject;
 use syntax::symbol::{kw, sym, Symbol};
 use syntax::tokenstream::{TokenStream, TokenTree};
 use syntax::parse::token::{self, Token};
@@ -241,7 +241,7 @@ pub fn lower_crate(
     dep_graph.assert_ignored();
 
     LoweringContext {
-        crate_root: std_inject::injected_crate_name().map(Symbol::intern),
+        crate_root: sess.parse_sess.injected_crate_name.try_get().copied(),
         sess,
         cstore,
         resolver,
@@ -468,7 +468,7 @@ impl<'tcx, 'interner> Visitor<'tcx> for MiscCollector<'tcx, 'interner> {
             fn visit_pat(&mut self, p: &'tcx Pat) {
                 match p.node {
                     // Doesn't generate a HIR node
-                    PatKind::Paren(..) => {},
+                    PatKind::Paren(..) | PatKind::Rest => {},
                     _ => {
                         if let Some(owner) = self.hir_id_owner {
                             self.lctx.lower_node_id_with_owner(p.id, owner);
@@ -1157,7 +1157,7 @@ fn make_async_expr(
         &mut self,
         capture_clause: CaptureBy,
         closure_node_id: NodeId,
-        ret_ty: Option<syntax::ptr::P<Ty>>,
+        ret_ty: Option<AstP<Ty>>,
         span: Span,
         body: impl FnOnce(&mut LoweringContext<'_>) -> hir::Expr,
     ) -> hir::ExprKind {
@@ -2461,8 +2461,10 @@ fn lower_mutability(&mut self, m: Mutability) -> hir::Mutability {
 
     fn lower_arg(&mut self, arg: &Arg) -> hir::Arg {
         hir::Arg {
+            attrs: self.lower_attrs(&arg.attrs),
             hir_id: self.lower_node_id(arg.id),
             pat: self.lower_pat(&arg.pat),
+            span: arg.span,
         }
     }
 
@@ -3279,19 +3281,29 @@ fn lower_maybe_async_body(
                 //
                 // If this is the simple case, this argument will end up being the same as the
                 // original argument, but with a different pattern id.
+                let mut stmt_attrs = ThinVec::new();
+                stmt_attrs.extend(argument.attrs.iter().cloned());
                 let (new_argument_pat, new_argument_id) = this.pat_ident(desugared_span, ident);
                 let new_argument = hir::Arg {
+                    attrs: argument.attrs,
                     hir_id: argument.hir_id,
                     pat: new_argument_pat,
+                    span: argument.span,
                 };
 
+
                 if is_simple_argument {
                     // If this is the simple case, then we only insert one statement that is
                     // `let <pat> = <pat>;`. We re-use the original argument's pattern so that
                     // `HirId`s are densely assigned.
                     let expr = this.expr_ident(desugared_span, ident, new_argument_id);
                     let stmt = this.stmt_let_pat(
-                        desugared_span, Some(P(expr)), argument.pat, hir::LocalSource::AsyncFn);
+                        stmt_attrs,
+                        desugared_span,
+                        Some(P(expr)),
+                        argument.pat,
+                        hir::LocalSource::AsyncFn
+                    );
                     statements.push(stmt);
                 } else {
                     // If this is not the simple case, then we construct two statements:
@@ -3313,14 +3325,23 @@ fn lower_maybe_async_body(
                         desugared_span, ident, hir::BindingAnnotation::Mutable);
                     let move_expr = this.expr_ident(desugared_span, ident, new_argument_id);
                     let move_stmt = this.stmt_let_pat(
-                        desugared_span, Some(P(move_expr)), move_pat, hir::LocalSource::AsyncFn);
+                        ThinVec::new(),
+                        desugared_span,
+                        Some(P(move_expr)),
+                        move_pat,
+                        hir::LocalSource::AsyncFn
+                    );
 
                     // Construct the `let <pat> = __argN;` statement. We re-use the original
                     // argument's pattern so that `HirId`s are densely assigned.
                     let pattern_expr = this.expr_ident(desugared_span, ident, move_id);
                     let pattern_stmt = this.stmt_let_pat(
-                        desugared_span, Some(P(pattern_expr)), argument.pat,
-                        hir::LocalSource::AsyncFn);
+                        stmt_attrs,
+                        desugared_span,
+                        Some(P(pattern_expr)),
+                        argument.pat,
+                        hir::LocalSource::AsyncFn
+                    );
 
                     statements.push(move_stmt);
                     statements.push(pattern_stmt);
@@ -4172,33 +4193,11 @@ fn lower_pat(&mut self, p: &Pat) -> P<hir::Pat> {
         let node = match p.node {
             PatKind::Wild => hir::PatKind::Wild,
             PatKind::Ident(ref binding_mode, ident, ref sub) => {
-                match self.resolver.get_partial_res(p.id).map(|d| d.base_res()) {
-                    // `None` can occur in body-less function signatures
-                    res @ None | res @ Some(Res::Local(_)) => {
-                        let canonical_id = match res {
-                            Some(Res::Local(id)) => id,
-                            _ => p.id,
-                        };
-
-                        hir::PatKind::Binding(
-                            self.lower_binding_mode(binding_mode),
-                            self.lower_node_id(canonical_id),
-                            ident,
-                            sub.as_ref().map(|x| self.lower_pat(x)),
-                        )
-                    }
-                    Some(res) => hir::PatKind::Path(hir::QPath::Resolved(
-                        None,
-                        P(hir::Path {
-                            span: ident.span,
-                            res: self.lower_res(res),
-                            segments: hir_vec![hir::PathSegment::from_ident(ident)],
-                        }),
-                    )),
-                }
+                let lower_sub = |this: &mut Self| sub.as_ref().map(|x| this.lower_pat(x));
+                self.lower_pat_ident(p, binding_mode, ident, lower_sub)
             }
             PatKind::Lit(ref e) => hir::PatKind::Lit(P(self.lower_expr(e))),
-            PatKind::TupleStruct(ref path, ref pats, ddpos) => {
+            PatKind::TupleStruct(ref path, ref pats) => {
                 let qpath = self.lower_qpath(
                     p.id,
                     &None,
@@ -4206,11 +4205,8 @@ fn lower_pat(&mut self, p: &Pat) -> P<hir::Pat> {
                     ParamMode::Optional,
                     ImplTraitContext::disallowed(),
                 );
-                hir::PatKind::TupleStruct(
-                    qpath,
-                    pats.iter().map(|x| self.lower_pat(x)).collect(),
-                    ddpos,
-                )
+                let (pats, ddpos) = self.lower_pat_tuple(pats, "tuple struct");
+                hir::PatKind::TupleStruct(qpath, pats, ddpos)
             }
             PatKind::Path(ref qself, ref path) => {
                 let qpath = self.lower_qpath(
@@ -4247,8 +4243,9 @@ fn lower_pat(&mut self, p: &Pat) -> P<hir::Pat> {
                     .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::Tuple(ref pats) => {
+                let (pats, ddpos) = self.lower_pat_tuple(pats, "tuple");
+                hir::PatKind::Tuple(pats, ddpos)
             }
             PatKind::Box(ref inner) => hir::PatKind::Box(self.lower_pat(inner)),
             PatKind::Ref(ref inner, mutbl) => {
@@ -4259,15 +4256,138 @@ fn lower_pat(&mut self, p: &Pat) -> P<hir::Pat> {
                 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::Slice(ref pats) => self.lower_pat_slice(pats),
+            PatKind::Rest => {
+                // If we reach here the `..` pattern is not semantically allowed.
+                self.ban_illegal_rest_pat(p.span)
+            }
             PatKind::Paren(ref inner) => return self.lower_pat(inner),
             PatKind::Mac(_) => panic!("Shouldn't exist here"),
         };
 
+        self.pat_with_node_id_of(p, node)
+    }
+
+    fn lower_pat_tuple(
+        &mut self,
+        pats: &[AstP<Pat>],
+        ctx: &str,
+    ) -> (HirVec<P<hir::Pat>>, Option<usize>) {
+        let mut elems = Vec::with_capacity(pats.len());
+        let mut rest = None;
+
+        let mut iter = pats.iter().enumerate();
+        while let Some((idx, pat)) = iter.next() {
+            // Interpret the first `..` pattern as a subtuple pattern.
+            if pat.is_rest() {
+                rest = Some((idx, pat.span));
+                break;
+            }
+            // It was not a subslice pattern so lower it normally.
+            elems.push(self.lower_pat(pat));
+        }
+
+        while let Some((_, pat)) = iter.next() {
+            // There was a previous subtuple pattern; make sure we don't allow more.
+            if pat.is_rest() {
+                self.ban_extra_rest_pat(pat.span, rest.unwrap().1, ctx);
+            } else {
+                elems.push(self.lower_pat(pat));
+            }
+        }
+
+        (elems.into(), rest.map(|(ddpos, _)| ddpos))
+    }
+
+    fn lower_pat_slice(&mut self, pats: &[AstP<Pat>]) -> hir::PatKind {
+        let mut before = Vec::new();
+        let mut after = Vec::new();
+        let mut slice = None;
+        let mut prev_rest_span = None;
+
+        let mut iter = pats.iter();
+        while let Some(pat) = iter.next() {
+            // Interpret the first `((ref mut?)? x @)? ..` pattern as a subslice pattern.
+            match pat.node {
+                PatKind::Rest => {
+                    prev_rest_span = Some(pat.span);
+                    slice = Some(self.pat_wild_with_node_id_of(pat));
+                    break;
+                },
+                PatKind::Ident(ref bm, ident, Some(ref sub)) if sub.is_rest() => {
+                    prev_rest_span = Some(sub.span);
+                    let lower_sub = |this: &mut Self| Some(this.pat_wild_with_node_id_of(sub));
+                    let node = self.lower_pat_ident(pat, bm, ident, lower_sub);
+                    slice = Some(self.pat_with_node_id_of(pat, node));
+                    break;
+                },
+                _ => {}
+            }
+
+            // It was not a subslice pattern so lower it normally.
+            before.push(self.lower_pat(pat));
+        }
+
+        while let Some(pat) = iter.next() {
+            // There was a previous subslice pattern; make sure we don't allow more.
+            let rest_span = match pat.node {
+                PatKind::Rest => Some(pat.span),
+                PatKind::Ident(.., Some(ref sub)) if sub.is_rest() => {
+                    // The `HirValidator` is merciless; add a `_` pattern to avoid ICEs.
+                    after.push(self.pat_wild_with_node_id_of(pat));
+                    Some(sub.span)
+                },
+                _ => None,
+            };
+            if let Some(rest_span) = rest_span {
+                self.ban_extra_rest_pat(rest_span, prev_rest_span.unwrap(), "slice");
+            } else {
+                after.push(self.lower_pat(pat));
+            }
+        }
+
+        hir::PatKind::Slice(before.into(), slice, after.into())
+    }
+
+    fn lower_pat_ident(
+        &mut self,
+        p: &Pat,
+        binding_mode: &BindingMode,
+        ident: Ident,
+        lower_sub: impl FnOnce(&mut Self) -> Option<P<hir::Pat>>,
+    ) -> hir::PatKind {
+        match self.resolver.get_partial_res(p.id).map(|d| d.base_res()) {
+            // `None` can occur in body-less function signatures
+            res @ None | res @ Some(Res::Local(_)) => {
+                let canonical_id = match res {
+                    Some(Res::Local(id)) => id,
+                    _ => p.id,
+                };
+
+                hir::PatKind::Binding(
+                    self.lower_binding_mode(binding_mode),
+                    self.lower_node_id(canonical_id),
+                    ident,
+                    lower_sub(self),
+                )
+            }
+            Some(res) => hir::PatKind::Path(hir::QPath::Resolved(
+                None,
+                P(hir::Path {
+                    span: ident.span,
+                    res: self.lower_res(res),
+                    segments: hir_vec![hir::PathSegment::from_ident(ident)],
+                }),
+            )),
+        }
+    }
+
+    fn pat_wild_with_node_id_of(&mut self, p: &Pat) -> P<hir::Pat> {
+        self.pat_with_node_id_of(p, hir::PatKind::Wild)
+    }
+
+    /// Construct a `Pat` with the `HirId` of `p.id` lowered.
+    fn pat_with_node_id_of(&mut self, p: &Pat, node: hir::PatKind) -> P<hir::Pat> {
         P(hir::Pat {
             hir_id: self.lower_node_id(p.id),
             node,
@@ -4275,6 +4395,28 @@ fn lower_pat(&mut self, p: &Pat) -> P<hir::Pat> {
         })
     }
 
+    /// Emit a friendly error for extra `..` patterns in a tuple/tuple struct/slice pattern.
+    fn ban_extra_rest_pat(&self, sp: Span, prev_sp: Span, ctx: &str) {
+        self.diagnostic()
+            .struct_span_err(sp, &format!("`..` can only be used once per {} pattern", ctx))
+            .span_label(sp, &format!("can only be used once per {} pattern", ctx))
+            .span_label(prev_sp, "previously used here")
+            .emit();
+    }
+
+    /// Used to ban the `..` pattern in places it shouldn't be semantically.
+    fn ban_illegal_rest_pat(&self, sp: Span) -> hir::PatKind {
+        self.diagnostic()
+            .struct_span_err(sp, "`..` patterns are not allowed here")
+            .note("only allowed in tuple, tuple struct, and slice patterns")
+            .emit();
+
+        // We're not in a list context so `..` can be reasonably treated
+        // as `_` because it should always be valid and roughly matches the
+        // intent of `..` (notice that the rest of a single slot is that slot).
+        hir::PatKind::Wild
+    }
+
     fn lower_range_end(&mut self, e: &RangeEnd) -> hir::RangeEnd {
         match *e {
             RangeEnd::Included(_) => hir::RangeEnd::Included,
@@ -4909,6 +5051,7 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
 
                 // `let mut __next`
                 let next_let = self.stmt_let_pat(
+                    ThinVec::new(),
                     desugared_span,
                     None,
                     next_pat,
@@ -4918,6 +5061,7 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
                 // `let <pat> = __next`
                 let pat = self.lower_pat(pat);
                 let pat_let = self.stmt_let_pat(
+                    ThinVec::new(),
                     head_sp,
                     Some(next_expr),
                     pat,
@@ -5412,19 +5556,20 @@ fn stmt(&mut self, span: Span, node: hir::StmtKind) -> hir::Stmt {
 
     fn stmt_let_pat(
         &mut self,
+        attrs: ThinVec<Attribute>,
         span: Span,
         init: Option<P<hir::Expr>>,
         pat: P<hir::Pat>,
         source: hir::LocalSource,
     ) -> hir::Stmt {
         let local = hir::Local {
-            pat,
-            ty: None,
-            init,
+            attrs,
             hir_id: self.next_id(),
-            span,
+            init,
+            pat,
             source,
-            attrs: ThinVec::new()
+            span,
+            ty: None,
         };
         self.stmt(span, hir::StmtKind::Local(P(local)))
     }
@@ -5838,6 +5983,7 @@ fn lower_await(
             hir::BindingAnnotation::Mutable,
         );
         let pinned_let = self.stmt_let_pat(
+            ThinVec::new(),
             span,
             Some(expr),
             pinned_pat,
index 12ea772c1fb3160c2e59424fbdd026ce15bc3540..b6807f7d3bbd2e60b1db88e12a220ddad70066d6 100644 (file)
@@ -363,6 +363,14 @@ fn visit_nested_body(&mut self, id: BodyId) {
         self.currently_in_body = prev_in_body;
     }
 
+    fn visit_arg(&mut self, arg: &'hir Arg) {
+        let node = Node::Arg(arg);
+        self.insert(arg.pat.span, arg.hir_id, node);
+        self.with_parent(arg.hir_id, |this| {
+            intravisit::walk_arg(this, arg);
+        });
+    }
+
     fn visit_item(&mut self, i: &'hir Item) {
         debug!("visit_item: {:?}", i);
         debug_assert_eq!(i.hir_id.owner,
index 43b1dbb6216d7498b5c7f11c4df8afbbe3defa60..5a28d9e7b7db6ce2a7da4544d9229ac9165dd436 100644 (file)
@@ -360,6 +360,7 @@ fn def_kind(&self, hir_id: HirId) -> Option<DefKind> {
             Node::Pat(_) |
             Node::Binding(_) |
             Node::Local(_) |
+            Node::Arg(_) |
             Node::Arm(_) |
             Node::Lifetime(_) |
             Node::Visibility(_) |
@@ -932,6 +933,7 @@ pub fn name(&self, id: HirId) -> Name {
     pub fn attrs(&self, id: HirId) -> &'hir [ast::Attribute] {
         self.read(id); // reveals attributes on the node
         let attrs = match self.find_entry(id).map(|entry| entry.node) {
+            Some(Node::Arg(a)) => Some(&a.attrs[..]),
             Some(Node::Local(l)) => Some(&l.attrs[..]),
             Some(Node::Item(i)) => Some(&i.attrs[..]),
             Some(Node::ForeignItem(fi)) => Some(&fi.attrs[..]),
@@ -995,6 +997,7 @@ pub fn nodes_matching_suffix<'a>(&'a self, parts: &'a [String])
     pub fn span(&self, hir_id: HirId) -> Span {
         self.read(hir_id); // reveals span from node
         match self.find_entry(hir_id).map(|entry| entry.node) {
+            Some(Node::Arg(arg)) => arg.span,
             Some(Node::Item(item)) => item.span,
             Some(Node::ForeignItem(foreign_item)) => foreign_item.span,
             Some(Node::TraitItem(trait_method)) => trait_method.span,
@@ -1197,6 +1200,7 @@ fn nested(&self, state: &mut print::State<'_>, nested: print::Nested) {
 impl<'a> print::State<'a> {
     pub fn print_node(&mut self, node: Node<'_>) {
         match node {
+            Node::Arg(a)          => self.print_arg(&a),
             Node::Item(a)         => self.print_item(&a),
             Node::ForeignItem(a)  => self.print_foreign_item(&a),
             Node::TraitItem(a)    => self.print_trait_item(a),
@@ -1338,6 +1342,9 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId, include_id: bool) -> String {
         Some(Node::Pat(_)) => {
             format!("pat {}{}", map.hir_to_pretty_string(id), id_str)
         }
+        Some(Node::Arg(_)) => {
+            format!("arg {}{}", map.hir_to_pretty_string(id), id_str)
+        }
         Some(Node::Arm(_)) => {
             format!("arm {}{}", map.hir_to_pretty_string(id), id_str)
         }
index 3708a905a4b03c72b082eeb34a58a1520ab28172..f9a4944780195784ee7cb5fe547ffdfd60092d5f 100644 (file)
@@ -2010,8 +2010,10 @@ pub struct InlineAsm {
 /// Represents an argument in a function header.
 #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub struct Arg {
-    pub pat: P<Pat>,
+    pub attrs: HirVec<Attribute>,
     pub hir_id: HirId,
+    pub pat: P<Pat>,
+    pub span: Span,
 }
 
 /// Represents the header (not the body) of a function declaration.
@@ -2701,6 +2703,7 @@ pub fn contains_extern_indicator(&self) -> bool {
 
 #[derive(Copy, Clone, Debug)]
 pub enum Node<'hir> {
+    Arg(&'hir Arg),
     Item(&'hir Item),
     ForeignItem(&'hir ForeignItem),
     TraitItem(&'hir TraitItem),
index da4a25e0860b11b0228f2264a09a6496c4e5b847..9c32831cf88e8f797053915d88db89957501ac31 100644 (file)
@@ -1767,6 +1767,11 @@ pub fn print_pat(&mut self, pat: &hir::Pat) {
         self.ann.post(self, AnnNode::Pat(pat))
     }
 
+    pub fn print_arg(&mut self, arg: &hir::Arg) {
+        self.print_outer_attributes(&arg.attrs);
+        self.print_pat(&arg.pat);
+    }
+
     pub fn print_arm(&mut self, arm: &hir::Arm) {
         // I have no idea why this check is necessary, but here it
         // is :(
index 79f60778d3cf397e65ebbb2a311fa965e99f6771..4b3fefcd4debbaf0afa859d0018ea65cce298e6d 100644 (file)
@@ -28,9 +28,6 @@
 
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
 
-#![deny(rust_2018_idioms)]
-#![deny(unused_lifetimes)]
-
 #![feature(arbitrary_self_types)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
@@ -81,8 +78,7 @@
 
 // Use the test crate here so we depend on getopts through it. This allow tools to link to both
 // librustc_driver and libtest.
-#[allow(unused_extern_crates)]
-extern crate test;
+extern crate test as _;
 
 #[macro_use]
 mod macros;
index 859bc86d3a07d160b970dacfb39335e5b29224ea..de812410e8bd83260f66925bcabbe285fbc0ee7d 100644 (file)
@@ -966,6 +966,13 @@ fn visit_nested_body(&mut self, body: hir::BodyId) {
         self.context.tables = old_tables;
     }
 
+    fn visit_arg(&mut self, arg: &'tcx hir::Arg) {
+        self.with_lint_attrs(arg.hir_id, &arg.attrs, |cx| {
+            lint_callback!(cx, check_arg, arg);
+            hir_visit::walk_arg(cx, arg);
+        });
+    }
+
     fn visit_body(&mut self, body: &'tcx hir::Body) {
         lint_callback!(self, check_body, body);
         hir_visit::walk_body(self, body);
@@ -1156,6 +1163,13 @@ fn visit_attribute(&mut self, attr: &'tcx ast::Attribute) {
 }
 
 impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> {
+    fn visit_arg(&mut self, arg: &'a ast::Arg) {
+        self.with_lint_attrs(arg.id, &arg.attrs, |cx| {
+            run_early_pass!(cx, check_arg, arg);
+            ast_visit::walk_arg(cx, arg);
+        });
+    }
+
     fn visit_item(&mut self, it: &'a ast::Item) {
         self.with_lint_attrs(it.id, &it.attrs, |cx| {
             run_early_pass!(cx, check_item, it);
index dddbc31ccd4ea7e05d256a92f7c033025943958f..8ddf4603490a199366f352fd22a39335ddd34bb5 100644 (file)
@@ -206,6 +206,7 @@ macro_rules! declare_lint_pass {
 macro_rules! late_lint_methods {
     ($macro:path, $args:tt, [$hir:tt]) => (
         $macro!($args, [$hir], [
+            fn check_arg(a: &$hir hir::Arg);
             fn check_body(a: &$hir hir::Body);
             fn check_body_post(a: &$hir hir::Body);
             fn check_name(a: Span, b: ast::Name);
@@ -358,6 +359,7 @@ fn get_lints(&self) -> LintArray {
 macro_rules! early_lint_methods {
     ($macro:path, $args:tt) => (
         $macro!($args, [
+            fn check_arg(a: &ast::Arg);
             fn check_ident(a: ast::Ident);
             fn check_crate(a: &ast::Crate);
             fn check_crate_post(a: &ast::Crate);
@@ -495,8 +497,6 @@ fn get_lints(&self) -> LintArray {
 pub type LateLintPassObject = Box<dyn for<'a, 'tcx> LateLintPass<'a, 'tcx> + sync::Send
                                                                            + sync::Sync + 'static>;
 
-
-
 /// Identifies a lint known to the compiler.
 #[derive(Clone, Copy, Debug)]
 pub struct LintId {
@@ -812,6 +812,12 @@ fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'thi
         intravisit::NestedVisitorMap::All(&self.tcx.hir())
     }
 
+    fn visit_arg(&mut self, arg: &'tcx hir::Arg) {
+        self.with_lint_attrs(arg.hir_id, &arg.attrs, |builder| {
+            intravisit::walk_arg(builder, arg);
+        });
+    }
+
     fn visit_item(&mut self, it: &'tcx hir::Item) {
         self.with_lint_attrs(it.hir_id, &it.attrs, |builder| {
             intravisit::walk_item(builder, it);
index abb896a7c9bebdbddfb6ce7d3c70ae00132581df..e2b1b54cef39f8ac423b1ba888ea7d1f783df666 100644 (file)
@@ -2146,48 +2146,77 @@ fn visit_fn_like_elision(&mut self, inputs: &'tcx [hir::Ty], output: Option<&'tc
         // First (determined here), if `self` is by-reference, then the
         // implied output region is the region of the self parameter.
         if has_self {
-            // Look for `self: &'a Self` - also desugared from `&'a self`,
-            // and if that matches, use it for elision and return early.
-            let is_self_ty = |res: Res| {
-                if let Res::SelfTy(..) = res {
-                    return true;
-                }
-
-                // Can't always rely on literal (or implied) `Self` due
-                // to the way elision rules were originally specified.
-                let impl_self = impl_self.map(|ty| &ty.node);
-                if let Some(&hir::TyKind::Path(hir::QPath::Resolved(None, ref path))) = impl_self {
-                    match path.res {
-                        // Whitelist the types that unambiguously always
-                        // result in the same type constructor being used
-                        // (it can't differ between `Self` and `self`).
-                        Res::Def(DefKind::Struct, _)
-                        | Res::Def(DefKind::Union, _)
-                        | Res::Def(DefKind::Enum, _)
-                        | Res::PrimTy(_) => {
-                            return res == path.res
+            struct SelfVisitor<'a> {
+                map: &'a NamedRegionMap,
+                impl_self: Option<&'a hir::TyKind>,
+                lifetime: Set1<Region>,
+            }
+
+            impl SelfVisitor<'_> {
+                // Look for `self: &'a Self` - also desugared from `&'a self`,
+                // and if that matches, use it for elision and return early.
+                fn is_self_ty(&self, res: Res) -> bool {
+                    if let Res::SelfTy(..) = res {
+                        return true;
+                    }
+
+                    // Can't always rely on literal (or implied) `Self` due
+                    // to the way elision rules were originally specified.
+                    if let Some(&hir::TyKind::Path(hir::QPath::Resolved(None, ref path))) =
+                        self.impl_self
+                    {
+                        match path.res {
+                            // Whitelist the types that unambiguously always
+                            // result in the same type constructor being used
+                            // (it can't differ between `Self` and `self`).
+                            Res::Def(DefKind::Struct, _)
+                            | Res::Def(DefKind::Union, _)
+                            | Res::Def(DefKind::Enum, _)
+                            | Res::PrimTy(_) => {
+                                return res == path.res
+                            }
+                            _ => {}
                         }
-                        _ => {}
                     }
+
+                    false
                 }
+            }
 
-                false
-            };
+            impl<'a> Visitor<'a> for SelfVisitor<'a> {
+                fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'a> {
+                    NestedVisitorMap::None
+                }
 
-            if let hir::TyKind::Rptr(lifetime_ref, ref mt) = inputs[0].node {
-                if let hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) = mt.ty.node {
-                    if is_self_ty(path.res) {
-                        if let Some(&lifetime) = self.map.defs.get(&lifetime_ref.hir_id) {
-                            let scope = Scope::Elision {
-                                elide: Elide::Exact(lifetime),
-                                s: self.scope,
-                            };
-                            self.with(scope, |_, this| this.visit_ty(output));
-                            return;
+                fn visit_ty(&mut self, ty: &'a hir::Ty) {
+                    if let hir::TyKind::Rptr(lifetime_ref, ref mt) = ty.node {
+                        if let hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) = mt.ty.node
+                        {
+                            if self.is_self_ty(path.res) {
+                                if let Some(lifetime) = self.map.defs.get(&lifetime_ref.hir_id) {
+                                    self.lifetime.insert(*lifetime);
+                                }
+                            }
                         }
                     }
+                    intravisit::walk_ty(self, ty)
                 }
             }
+
+            let mut visitor = SelfVisitor {
+                map: self.map,
+                impl_self: impl_self.map(|ty| &ty.node),
+                lifetime: Set1::Empty,
+            };
+            visitor.visit_ty(&inputs[0]);
+            if let Set1::One(lifetime) = visitor.lifetime {
+                let scope = Scope::Elision {
+                    elide: Elide::Exact(lifetime),
+                    s: self.scope,
+                };
+                self.with(scope, |_, this| this.visit_ty(output));
+                return;
+            }
         }
 
         // Second, if there was exactly one lifetime (either a substitution or a
index 74653d4fbda73fd3f96dccf724ff644ced9ab051..886915db4498ce40167565482e04743f1c802e0b 100644 (file)
@@ -1628,7 +1628,7 @@ pub fn unstable<F>(name: &'static str, f: F) -> RustcOptGroup
 // *unstable* options, i.e., options that are only enabled when the
 // user also passes the `-Z unstable-options` debugging flag.
 mod opt {
-    // The `fn opt_u` etc below are written so that we can use them
+    // The `fn flag*` etc below are written so that we can use them
     // in the future; do not warn about them not being used right now.
     #![allow(dead_code)]
 
index dcc467a61b5416fbed4ba659c1e193be1dd9069c..a25560ff762a1115d1bb74b4fa69df1ab98204f6 100644 (file)
@@ -1,35 +1,25 @@
-#![allow(warnings)]
-
-use std::mem;
-use std::process;
-use std::{fmt, ptr};
+use crate::ty::context::TyCtxt;
+use crate::ty::query::plumbing::CycleError;
+use crate::ty::query::Query;
+use crate::ty::tls;
 
-use rustc_data_structures::fx::FxHashSet;
-use rustc_data_structures::sync::{Lock, LockGuard, Lrc, Weak};
-use rustc_data_structures::OnDrop;
-use rustc_data_structures::jobserver;
+use rustc_data_structures::sync::Lrc;
 use syntax_pos::Span;
 
-use crate::ty::tls;
-use crate::ty::query::Query;
-use crate::ty::query::plumbing::CycleError;
 #[cfg(not(parallel_compiler))]
-use crate::ty::query::{
-    plumbing::TryGetJob,
-    config::QueryDescription,
-};
-use crate::ty::context::TyCtxt;
+use std::ptr;
 
 #[cfg(parallel_compiler)]
 use {
-    rustc_rayon_core as rayon_core,
     parking_lot::{Mutex, Condvar},
-    std::sync::atomic::Ordering,
-    std::thread,
-    std::iter,
-    std::iter::FromIterator,
+    rustc_data_structures::{jobserver, OnDrop},
+    rustc_data_structures::fx::FxHashSet,
+    rustc_data_structures::stable_hasher::{StableHasher, HashStable},
+    rustc_data_structures::sync::Lock,
+    rustc_rayon_core as rayon_core,
     syntax_pos::DUMMY_SP,
-    rustc_data_structures::stable_hasher::{StableHasherResult, StableHasher, HashStable},
+    std::{mem, process, thread},
+    std::iter::FromIterator,
 };
 
 /// Indicates the state of a query for a given key in a query map.
@@ -81,7 +71,7 @@ pub(super) fn r#await(
         span: Span,
     ) -> Result<(), CycleError<'tcx>> {
         tls::with_related_context(tcx, move |icx| {
-            let mut waiter = Lrc::new(QueryWaiter {
+            let waiter = Lrc::new(QueryWaiter {
                 query: icx.query.clone(),
                 span,
                 cycle: Lock::new(None),
@@ -138,6 +128,7 @@ pub fn signal_complete(&self) {
         self.latch.set();
     }
 
+    #[cfg(parallel_compiler)]
     fn as_ptr(&self) -> *const QueryJob<'tcx> {
         self as *const _
     }
@@ -431,7 +422,7 @@ fn remove_cycle<'tcx>(
         let usage = usage.as_ref().map(|(span, query)| (*span, query.info.query.clone()));
 
         // Create the cycle error
-        let mut error = CycleError {
+        let error = CycleError {
             usage,
             cycle: stack.iter().map(|&(s, ref q)| QueryInfo {
                 span: s,
@@ -463,9 +454,6 @@ fn remove_cycle<'tcx>(
 /// Must only be called when a deadlock is about to happen.
 #[cfg(parallel_compiler)]
 pub unsafe fn handle_deadlock() {
-    use syntax;
-    use syntax_pos;
-
     let registry = rayon_core::Registry::current();
 
     let gcx_ptr = tls::GCX_PTR.with(|gcx_ptr| {
@@ -473,11 +461,6 @@ pub unsafe fn handle_deadlock() {
     });
     let gcx_ptr = &*gcx_ptr;
 
-    let syntax_globals = syntax::GLOBALS.with(|syntax_globals| {
-        syntax_globals as *const _
-    });
-    let syntax_globals = &*syntax_globals;
-
     let syntax_pos_globals = syntax_pos::GLOBALS.with(|syntax_pos_globals| {
         syntax_pos_globals as *const _
     });
index ceade5d2788380841ab4d1d1ead04fb66ea91f3c..9e6d5a6f62434e95dbf458c7192fff5ebfdb490e 100644 (file)
@@ -32,7 +32,6 @@
 
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
 #![forbid(unsafe_code)]
-#![deny(rust_2018_idioms)]
 
 #![feature(nll)]
 
index 3bdb86d313dcbb703db8bc2763a3baf9c71f1ab3..d6c8e54c18db7ea9e9f6d9bdefc1e2ce0d5e3dd3 100644 (file)
@@ -6,5 +6,3 @@
 #![unstable(feature = "sanitizer_runtime_lib",
             reason = "internal implementation detail of sanitizers",
             issue = "0")]
-
-#![deny(rust_2018_idioms)]
index b857c625ec2e76c8b0d4cca48928f53b07453985..dc818278a4b748c03799c0ce9df9850b3dfb157f 100644 (file)
@@ -1,8 +1,6 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
 
 #![allow(non_camel_case_types)]
-#![deny(rust_2018_idioms)]
-#![deny(unused_lifetimes)]
 
 #![feature(in_band_lifetimes)]
 #![feature(nll)]
index fbeda43af42b0aef48fa2cff6a4fed28e2651e13..f0bdb0018efe7f71fc415390eb4c7a6697640edd 100644 (file)
@@ -913,9 +913,12 @@ pub fn compile_unit_metadata(
     }
 
     debug!("compile_unit_metadata: {:?}", name_in_debuginfo);
+    let rustc_producer = format!(
+        "rustc version {}",
+        option_env!("CFG_VERSION").expect("CFG_VERSION"),
+    );
     // FIXME(#41252) Remove "clang LLVM" if we can get GDB and LLVM to play nice.
-    let producer = format!("clang LLVM (rustc version {})",
-                           (option_env!("CFG_VERSION")).expect("CFG_VERSION"));
+    let producer = format!("clang LLVM ({})", rustc_producer);
 
     let name_in_debuginfo = name_in_debuginfo.to_string_lossy();
     let name_in_debuginfo = SmallCStr::new(&name_in_debuginfo);
@@ -980,6 +983,21 @@ pub fn compile_unit_metadata(
                                               gcov_metadata);
         }
 
+        // Insert `llvm.ident` metadata on the wasm32 targets since that will
+        // get hooked up to the "producer" sections `processed-by` information.
+        if tcx.sess.opts.target_triple.triple().starts_with("wasm32") {
+            let name_metadata = llvm::LLVMMDStringInContext(
+                debug_context.llcontext,
+                rustc_producer.as_ptr() as *const _,
+                rustc_producer.as_bytes().len() as c_uint,
+            );
+            llvm::LLVMAddNamedMetadataOperand(
+                debug_context.llmod,
+                const_cstr!("llvm.ident").as_ptr(),
+                llvm::LLVMMDNodeInContext(debug_context.llcontext, &name_metadata, 1),
+            );
+        }
+
         return unit_metadata;
     };
 
index 872fa424e4cfb51128983c95da2a48d12f1e430d..c6b5dc03a6f0ab04dc8eac39d5250c8667cdf49e 100644 (file)
@@ -1,5 +1,3 @@
-#![allow(non_snake_case)]
-
 register_long_diagnostics! {
 
 E0511: r##"
index 44b3eff2ac5c9d91a8e3c5aba4f279b13e9c600a..199170182e4b467bc1fd3d1427cfeee6611cfc5e 100644 (file)
@@ -1,5 +1,3 @@
-#![allow(non_upper_case_globals)]
-
 use crate::attributes;
 use crate::llvm;
 use crate::llvm_util;
index 8dd241bd81a0a1490cb0da0b6af4e42d8225c8e5..a630817fb33866960ba5b7cb049f940ab04484f9 100644 (file)
@@ -12,7 +12,6 @@
 #![feature(crate_visibility_modifier)]
 #![feature(extern_types)]
 #![feature(in_band_lifetimes)]
-#![allow(unused_attributes)]
 #![feature(libc)]
 #![feature(nll)]
 #![feature(rustc_diagnostic_macros)]
@@ -22,8 +21,6 @@
 #![feature(static_nobundle)]
 #![feature(trusted_len)]
 #![feature(mem_take)]
-#![deny(rust_2018_idioms)]
-#![deny(unused_lifetimes)]
 
 use back::write::{create_target_machine, create_informational_target_machine};
 use syntax_pos::symbol::Symbol;
index 8c6ea00eb8c872646147e37257e4c20ab66a029c..d82e1c68df094726ea6497ddaac7b8c50980b8d8 100644 (file)
@@ -1,3 +1,6 @@
+#![allow(non_camel_case_types)]
+#![allow(non_upper_case_globals)]
+
 use super::debuginfo::{
     DIBuilder, DIDescriptor, DIFile, DILexicalBlock, DISubprogram, DIType,
     DIBasicType, DIDerivedType, DICompositeType, DIScope, DIVariable,
index 543cc912930fddbc97e998b5599ae177a99195a7..57815933af02b2961b52bc79a87cc84199a3ae07 100644 (file)
@@ -1,7 +1,4 @@
-#![allow(non_upper_case_globals)]
-#![allow(non_camel_case_types)]
 #![allow(non_snake_case)]
-#![deny(bare_trait_objects)]
 
 pub use self::IntPredicate::*;
 pub use self::RealPredicate::*;
index 2c167256ad56c5280ff2887cede1e6f6b8a0e1d7..8d6cd0bcf474bd4efe947111bf7dbf74cc968951 100644 (file)
@@ -1,5 +1,3 @@
-#![allow(non_upper_case_globals)]
-
 pub use crate::llvm::Type;
 
 use crate::llvm;
index 707b7cae16ce73f1d58fa79a05d3dbd1e0dc6b02..3f6a1a72ea61ebb674fe212b29665e2520ab5ec2 100644 (file)
@@ -678,14 +678,6 @@ fn escape_string(s: &[u8]) -> String {
             sess.fatal(&format!("failed to run dsymutil: {}", e))
         }
     }
-
-    if sess.opts.target_triple.triple() == "wasm32-unknown-unknown" {
-        super::wasm::add_producer_section(
-            &out_filename,
-            &sess.edition().to_string(),
-            option_env!("CFG_VERSION").unwrap_or("unknown"),
-        );
-    }
 }
 
 /// Returns a boolean indicating whether the specified crate should be ignored
index cb8870d0be90cb234d7ed53d3c75e41a04d8ca5c..26091005f25aa72fca26efa45df8de1367482442 100644 (file)
@@ -901,7 +901,45 @@ pub struct WasmLd<'a> {
 }
 
 impl<'a> WasmLd<'a> {
-    fn new(cmd: Command, sess: &'a Session, info: &'a LinkerInfo) -> WasmLd<'a> {
+    fn new(mut cmd: Command, sess: &'a Session, info: &'a LinkerInfo) -> WasmLd<'a> {
+        // If the atomics feature is enabled for wasm then we need a whole bunch
+        // of flags:
+        //
+        // * `--shared-memory` - the link won't even succeed without this, flags
+        //   the one linear memory as `shared`
+        //
+        // * `--max-memory=1G` - when specifying a shared memory this must also
+        //   be specified. We conservatively choose 1GB but users should be able
+        //   to override this with `-C link-arg`.
+        //
+        // * `--import-memory` - it doesn't make much sense for memory to be
+        //   exported in a threaded module because typically you're
+        //   sharing memory and instantiating the module multiple times. As a
+        //   result if it were exported then we'd just have no sharing.
+        //
+        // * `--passive-segments` - all memory segments should be passive to
+        //   prevent each module instantiation from reinitializing memory.
+        //
+        // * `--export=__wasm_init_memory` - when using `--passive-segments` the
+        //   linker will synthesize this function, and so we need to make sure
+        //   that our usage of `--export` below won't accidentally cause this
+        //   function to get deleted.
+        //
+        // * `--export=*tls*` - when `#[thread_local]` symbols are used these
+        //   symbols are how the TLS segments are initialized and configured.
+        let atomics = sess.opts.cg.target_feature.contains("+atomics") ||
+            sess.target.target.options.features.contains("+atomics");
+        if atomics {
+            cmd.arg("--shared-memory");
+            cmd.arg("--max-memory=1073741824");
+            cmd.arg("--import-memory");
+            cmd.arg("--passive-segments");
+            cmd.arg("--export=__wasm_init_memory");
+            cmd.arg("--export=__wasm_init_tls");
+            cmd.arg("--export=__tls_size");
+            cmd.arg("--export=__tls_align");
+            cmd.arg("--export=__tls_base");
+        }
         WasmLd { cmd, sess, info }
     }
 }
@@ -1004,6 +1042,13 @@ fn export_symbols(&mut self, _tmpdir: &Path, crate_type: CrateType) {
         for sym in self.info.exports[&crate_type].iter() {
             self.cmd.arg("--export").arg(&sym);
         }
+
+        // LLD will hide these otherwise-internal symbols since our `--export`
+        // list above is a whitelist of what to export. Various bits and pieces
+        // of tooling use this, so be sure these symbols make their way out of
+        // the linker as well.
+        self.cmd.arg("--export=__heap_base");
+        self.cmd.arg("--export=__data_end");
     }
 
     fn subsystem(&mut self, _subsystem: &str) {
index a16d099ee3e4d0f16120b6ae1eea3dbcd354b36a..901891d85a465f397b921c2332a59fe218e53260 100644 (file)
@@ -6,4 +6,3 @@
 pub mod symbol_export;
 pub mod archive;
 pub mod rpath;
-pub mod wasm;
diff --git a/src/librustc_codegen_ssa/back/wasm.rs b/src/librustc_codegen_ssa/back/wasm.rs
deleted file mode 100644 (file)
index 2a9e81a..0000000
+++ /dev/null
@@ -1,191 +0,0 @@
-use std::fs;
-use std::path::Path;
-use std::str;
-
-use rustc_serialize::leb128;
-
-// https://webassembly.github.io/spec/core/binary/modules.html#binary-importsec
-const WASM_CUSTOM_SECTION_ID: u8 = 0;
-
-/// Adds or augment the existing `producers` section to encode information about
-/// the Rust compiler used to produce the wasm file.
-pub fn add_producer_section(
-    path: &Path,
-    rust_version: &str,
-    rustc_version: &str,
-) {
-    struct Field<'a> {
-        name: &'a str,
-        values: Vec<FieldValue<'a>>,
-    }
-
-    #[derive(Copy, Clone)]
-    struct FieldValue<'a> {
-        name: &'a str,
-        version: &'a str,
-    }
-
-    let wasm = fs::read(path).expect("failed to read wasm output");
-    let mut ret = WasmEncoder::new();
-    ret.data.extend(&wasm[..8]);
-
-    // skip the 8 byte wasm/version header
-    let rustc_value = FieldValue {
-        name: "rustc",
-        version: rustc_version,
-    };
-    let rust_value = FieldValue {
-        name: "Rust",
-        version: rust_version,
-    };
-    let mut fields = Vec::new();
-    let mut wrote_rustc = false;
-    let mut wrote_rust = false;
-
-    // Move all sections from the original wasm file to our output, skipping
-    // everything except the producers section
-    for (id, raw) in WasmSections(WasmDecoder::new(&wasm[8..])) {
-        if id != WASM_CUSTOM_SECTION_ID {
-            ret.byte(id);
-            ret.bytes(raw);
-            continue
-        }
-        let mut decoder = WasmDecoder::new(raw);
-        if decoder.str() != "producers" {
-            ret.byte(id);
-            ret.bytes(raw);
-            continue
-        }
-
-        // Read off the producers section into our fields outside the loop,
-        // we'll re-encode the producers section when we're done (to handle an
-        // entirely missing producers section as well).
-        info!("rewriting existing producers section");
-
-        for _ in 0..decoder.u32() {
-            let name = decoder.str();
-            let mut values = Vec::new();
-            for _ in 0..decoder.u32() {
-                let name = decoder.str();
-                let version = decoder.str();
-                values.push(FieldValue { name, version });
-            }
-
-            if name == "language" {
-                values.push(rust_value);
-                wrote_rust = true;
-            } else if name == "processed-by" {
-                values.push(rustc_value);
-                wrote_rustc = true;
-            }
-            fields.push(Field { name, values });
-        }
-    }
-
-    if !wrote_rust {
-        fields.push(Field {
-            name: "language",
-            values: vec![rust_value],
-        });
-    }
-    if !wrote_rustc {
-        fields.push(Field {
-            name: "processed-by",
-            values: vec![rustc_value],
-        });
-    }
-
-    // Append the producers section to the end of the wasm file.
-    let mut section = WasmEncoder::new();
-    section.str("producers");
-    section.u32(fields.len() as u32);
-    for field in fields {
-        section.str(field.name);
-        section.u32(field.values.len() as u32);
-        for value in field.values {
-            section.str(value.name);
-            section.str(value.version);
-        }
-    }
-    ret.byte(WASM_CUSTOM_SECTION_ID);
-    ret.bytes(&section.data);
-
-    fs::write(path, &ret.data).expect("failed to write wasm output");
-}
-
-struct WasmSections<'a>(WasmDecoder<'a>);
-
-impl<'a> Iterator for WasmSections<'a> {
-    type Item = (u8, &'a [u8]);
-
-    fn next(&mut self) -> Option<(u8, &'a [u8])> {
-        if self.0.data.is_empty() {
-            return None
-        }
-
-        // see https://webassembly.github.io/spec/core/binary/modules.html#sections
-        let id = self.0.byte();
-        let section_len = self.0.u32();
-        info!("new section {} / {} bytes", id, section_len);
-        let section = self.0.skip(section_len as usize);
-        Some((id, section))
-    }
-}
-
-struct WasmDecoder<'a> {
-    data: &'a [u8],
-}
-
-impl<'a> WasmDecoder<'a> {
-    fn new(data: &'a [u8]) -> WasmDecoder<'a> {
-        WasmDecoder { data }
-    }
-
-    fn byte(&mut self) -> u8 {
-        self.skip(1)[0]
-    }
-
-    fn u32(&mut self) -> u32 {
-        let (n, l1) = leb128::read_u32_leb128(self.data);
-        self.data = &self.data[l1..];
-        return n
-    }
-
-    fn skip(&mut self, amt: usize) -> &'a [u8] {
-        let (data, rest) = self.data.split_at(amt);
-        self.data = rest;
-        data
-    }
-
-    fn str(&mut self) -> &'a str {
-        let len = self.u32();
-        str::from_utf8(self.skip(len as usize)).unwrap()
-    }
-}
-
-struct WasmEncoder {
-    data: Vec<u8>,
-}
-
-impl WasmEncoder {
-    fn new() -> WasmEncoder {
-        WasmEncoder { data: Vec::new() }
-    }
-
-    fn u32(&mut self, val: u32) {
-        leb128::write_u32_leb128(&mut self.data, val);
-    }
-
-    fn byte(&mut self, val: u8) {
-        self.data.push(val);
-    }
-
-    fn bytes(&mut self, val: &[u8]) {
-        self.u32(val.len() as u32);
-        self.data.extend_from_slice(val);
-    }
-
-    fn str(&mut self, val: &str) {
-        self.bytes(val.as_bytes())
-    }
-}
index 00471095f2f3517efcba016c7b74307bfe4fdba7..fc04976f511b38d065b6c0777e66028041fc066f 100644 (file)
@@ -781,12 +781,6 @@ pub fn new(tcx: TyCtxt<'_>) -> CrateInfo {
     }
 }
 
-fn is_codegened_item(tcx: TyCtxt<'_>, id: DefId) -> bool {
-    let (all_mono_items, _) =
-        tcx.collect_and_partition_mono_items(LOCAL_CRATE);
-    all_mono_items.contains(&id)
-}
-
 pub fn provide_both(providers: &mut Providers<'_>) {
     providers.backend_optimization_level = |tcx, cratenum| {
         let for_speed = match tcx.sess.opts.optimize {
index e7ef178cfabfba62793df0d2f37dfffd92ad9fef..8d46dcb7c09c38f26f792e568044ca227bfe04ab 100644 (file)
@@ -1,5 +1,3 @@
-#![allow(non_snake_case)]
-
 register_long_diagnostics! {
 
 E0668: r##"
index d0f4b0a870b5ab0a6cfca6202be00ff41c183380..73ef16e0091460ee6e8b16f593b2001ec79d9b7c 100644 (file)
 #![feature(nll)]
 #![feature(trusted_len)]
 #![feature(mem_take)]
-#![allow(unused_attributes)]
-#![allow(dead_code)]
-#![deny(rust_2018_idioms)]
-#![deny(unused_lifetimes)]
 
 #![recursion_limit="256"]
 
index 7a7a50a25faf09fe62f2a2cc72c40cb99850a08e..262cfb1658ef99c79f07a1de6ab4d114189bcd08 100644 (file)
@@ -5,8 +5,6 @@
 //! This API is completely unstable and subject to change.
 
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
-#![deny(warnings)]
-#![feature(box_syntax)]
 
 use std::any::Any;
 use std::sync::mpsc;
index f38b672afd939ac61c57719185e5c0003ecdf162..4ea375b59b2c02f55189efcff63c9f9618c3091c 100644 (file)
 #![feature(core_intrinsics)]
 #![feature(never_type)]
 #![feature(nll)]
-#![allow(unused_attributes)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(in_band_lifetimes)]
 
 #![recursion_limit="256"]
 
-#![deny(rust_2018_idioms)]
-#![deny(unused_lifetimes)]
-
 #[macro_use]
 extern crate rustc;
 
index e59085a9e3a95e3ea8fd8a7eb2cbe830e410aed7..749709521e86688983df241104475e2fbffd6870 100644 (file)
@@ -39,6 +39,7 @@ fn depth_first_search(&self, from: Self::Node) -> iterate::DepthFirstSearch<'_,
     }
 }
 
+#[allow(unused_lifetimes)]
 pub trait GraphSuccessors<'graph> {
     type Item;
     type Iter: Iterator<Item = Self::Item>;
@@ -54,6 +55,7 @@ fn predecessors(
     ) -> <Self as GraphPredecessors<'_>>::Iter;
 }
 
+#[allow(unused_lifetimes)]
 pub trait GraphPredecessors<'graph> {
     type Item;
     type Iter: Iterator<Item = Self::Item>;
index 3047119029abc6834e8c1dc9aab42bdec2adf517..bb27637912b316902da5cf3b9a953462454783e7 100644 (file)
@@ -26,7 +26,6 @@
 #![cfg_attr(unix, feature(libc))]
 #![cfg_attr(test, feature(test))]
 
-#![deny(rust_2018_idioms)]
 #![cfg_attr(not(bootstrap), allow(rustc::default_hash_types))]
 
 #[macro_use]
index a7af615fa5000fae1423c087d2ebb2311c4c783b..ea9c5283aee7dd5c5c8718d86680667624dc52a1 100644 (file)
@@ -10,7 +10,7 @@
 This can sometimes be useful because Rust borrowing rules normally prevent
 moving a type that has been moved from. For example, this kind of code gets rejected:
 
-```rust,ignore
+```compile_fail,E0515
 fn return_owned_and_referenced<'a>() -> (Vec<u8>, &'a [u8]) {
     let v = vec![1, 2, 3, 4];
     let s = &v[1..3];
@@ -43,7 +43,8 @@ fn return_owned_and_referenced() -> OwningRef<Vec<u8>, [u8]> {
 as provided by `Box<T>`, `Rc<T>`, etc.
 
 Also provided are typedefs for common owner type combinations,
-which allow for less verbose type signatures. For example, `BoxRef<T>` instead of `OwningRef<Box<T>, T>`.
+which allow for less verbose type signatures.
+For example, `BoxRef<T>` instead of `OwningRef<Box<T>, T>`.
 
 The crate also provides the more advanced `OwningHandle` type,
 which allows more freedom in bundling a dependent handle object
@@ -283,6 +284,7 @@ impl<T> Erased for T {}
 /// Helper trait for erasing the concrete type of what an owner dereferences to,
 /// for example `Box<T> -> Box<Erased>`. This would be unneeded with
 /// higher kinded types support in the language.
+#[allow(unused_lifetimes)]
 pub unsafe trait IntoErased<'a> {
     /// Owner with the dereference type substituted to `Erased`.
     type Erased;
@@ -293,6 +295,7 @@ pub unsafe trait IntoErased<'a> {
 /// Helper trait for erasing the concrete type of what an owner dereferences to,
 /// for example `Box<T> -> Box<Erased + Send>`. This would be unneeded with
 /// higher kinded types support in the language.
+#[allow(unused_lifetimes)]
 pub unsafe trait IntoErasedSend<'a> {
     /// Owner with the dereference type substituted to `Erased + Send`.
     type Erased: Send;
@@ -303,6 +306,7 @@ pub unsafe trait IntoErasedSend<'a> {
 /// Helper trait for erasing the concrete type of what an owner dereferences to,
 /// for example `Box<T> -> Box<Erased + Send + Sync>`. This would be unneeded with
 /// higher kinded types support in the language.
+#[allow(unused_lifetimes)]
 pub unsafe trait IntoErasedSendSync<'a> {
     /// Owner with the dereference type substituted to `Erased + Send + Sync`.
     type Erased: Send + Sync;
@@ -495,7 +499,8 @@ pub fn erase_send_owner<'a>(self) -> OwningRef<O::Erased, T>
         }
     }
 
-    /// Erases the concrete base type of the owner with a trait object which implements `Send` and `Sync`.
+    /// Erases the concrete base type of the owner with a trait object
+    /// which implements `Send` and `Sync`.
     ///
     /// This allows mixing of owned references with different owner base types.
     pub fn erase_send_sync_owner<'a>(self) -> OwningRef<O::Erased, T>
@@ -507,7 +512,7 @@ pub fn erase_send_sync_owner<'a>(self) -> OwningRef<O::Erased, T>
         }
     }
 
-    // TODO: wrap_owner
+    // UNIMPLEMENTED: wrap_owner
 
     // FIXME: Naming convention?
     /// A getter for the underlying owner.
@@ -753,7 +758,7 @@ pub fn erase_owner<'a>(self) -> OwningRefMut<O::Erased, T>
         }
     }
 
-    // TODO: wrap_owner
+    // UNIMPLEMENTED: wrap_owner
 
     // FIXME: Naming convention?
     /// A getter for the underlying owner.
index d368219cab3eb3fd090de5581bddfcb58a7b6f7d..5bff5e035b5298594711d832c2e6d5fe905570bc 100644 (file)
@@ -274,7 +274,9 @@ fn owning_handle() {
         use std::cell::RefCell;
         let cell = Rc::new(RefCell::new(2));
         let cell_ref = RcRef::new(cell);
-        let mut handle = OwningHandle::new_with_fn(cell_ref, |x| unsafe { x.as_ref() }.unwrap().borrow_mut());
+        let mut handle = OwningHandle::new_with_fn(cell_ref, |x| {
+            unsafe { x.as_ref() }.unwrap().borrow_mut()
+        });
         assert_eq!(*handle, 2);
         *handle = 3;
         assert_eq!(*handle, 3);
@@ -319,8 +321,12 @@ fn nested() {
         let result = {
             let complex = Rc::new(RefCell::new(Arc::new(RwLock::new("someString"))));
             let curr = RcRef::new(complex);
-            let curr = OwningHandle::new_with_fn(curr, |x| unsafe { x.as_ref() }.unwrap().borrow_mut());
-            let mut curr = OwningHandle::new_with_fn(curr, |x| unsafe { x.as_ref() }.unwrap().try_write().unwrap());
+            let curr = OwningHandle::new_with_fn(curr, |x| {
+                unsafe { x.as_ref() }.unwrap().borrow_mut()
+            });
+            let mut curr = OwningHandle::new_with_fn(curr, |x| {
+                unsafe { x.as_ref() }.unwrap().try_write().unwrap()
+            });
             assert_eq!(*curr, "someString");
             *curr = "someOtherString";
             curr
@@ -353,8 +359,12 @@ fn owning_handle_safe_2() {
         let result = {
             let complex = Rc::new(RefCell::new(Arc::new(RwLock::new("someString"))));
             let curr = RcRef::new(complex);
-            let curr = OwningHandle::new_with_fn(curr, |x| unsafe { x.as_ref() }.unwrap().borrow_mut());
-            let mut curr = OwningHandle::new_with_fn(curr, |x| unsafe { x.as_ref() }.unwrap().try_write().unwrap());
+            let curr = OwningHandle::new_with_fn(curr, |x| {
+                unsafe { x.as_ref() }.unwrap().borrow_mut()
+            });
+            let mut curr = OwningHandle::new_with_fn(curr, |x| {
+                unsafe { x.as_ref() }.unwrap().try_write().unwrap()
+            });
             assert_eq!(*curr, "someString");
             *curr = "someOtherString";
             curr
index e8c9828a202efdc4e0ca0a96427cb0010a3bd995..42aa8203cba0eb21882745ff5287fed5bdc557a6 100644 (file)
@@ -10,30 +10,19 @@ path = "lib.rs"
 crate-type = ["dylib"]
 
 [dependencies]
-arena = { path = "../libarena" }
 graphviz = { path = "../libgraphviz" }
 log = "0.4"
 env_logger = { version = "0.5", default-features = false }
-rayon = { version = "0.2.0", package = "rustc-rayon" }
 rustc = { path = "../librustc" }
 rustc_target = { path = "../librustc_target" }
 rustc_ast_borrowck = { path = "../librustc_ast_borrowck" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 errors = { path = "../librustc_errors", package = "rustc_errors" }
-rustc_incremental = { path = "../librustc_incremental" }
-rustc_lint = { path = "../librustc_lint" }
 rustc_metadata = { path = "../librustc_metadata" }
 rustc_mir = { path = "../librustc_mir" }
-rustc_passes = { path = "../librustc_passes" }
-rustc_plugin = { path = "../librustc_plugin" }
-rustc_privacy = { path = "../librustc_privacy" }
-rustc_resolve = { path = "../librustc_resolve" }
 rustc_save_analysis = { path = "../librustc_save_analysis" }
-rustc_traits = { path = "../librustc_traits" }
 rustc_codegen_utils = { path = "../librustc_codegen_utils" }
-rustc_typeck = { path = "../librustc_typeck" }
 rustc_interface = { path = "../librustc_interface" }
 rustc_serialize = { path = "../libserialize", package = "serialize" }
 syntax = { path = "../libsyntax" }
-smallvec = { version = "0.6.7", features = ["union", "may_dangle"] }
 syntax_pos = { path = "../libsyntax_pos" }
index c139be07aa1d384011fcf523de1c71d9a9896d25..77b7ef96d3f6ca941851075aef24660aa682f1bb 100644 (file)
@@ -16,9 +16,6 @@
 
 #![recursion_limit="256"]
 
-#![deny(rust_2018_idioms)]
-#![deny(unused_lifetimes)]
-
 pub extern crate getopts;
 #[cfg(unix)]
 extern crate libc;
index 0a6c02c0ca68f66d5e495fcbd795d61cc15829b3..3b6a6a824c86d3d5099d90cada304aa658e5d297 100644 (file)
@@ -5,12 +5,9 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
 
 #![feature(crate_visibility_modifier)]
-#![allow(unused_attributes)]
 #![cfg_attr(unix, feature(libc))]
 #![feature(nll)]
 #![feature(optin_builtin_traits)]
-#![deny(rust_2018_idioms)]
-#![deny(unused_lifetimes)]
 
 pub use emitter::ColorConfig;
 
@@ -226,7 +223,8 @@ fn push_trailing(buf: &mut String,
                         }
                     }
                     if let Some(cur_line) = fm.get_line(cur_lo.line - 1) {
-                        buf.push_str(&cur_line[..cur_lo.col.to_usize()]);
+                        let end = std::cmp::min(cur_line.len(), cur_lo.col.to_usize());
+                        buf.push_str(&cur_line[..end]);
                     }
                 }
                 buf.push_str(&part.snippet);
index ce63bcafd797c9ac38d206ed71e0d4e648c7632b..eaf08d76b9905c16ef7f9b41ceeca31ebfb24430 100644 (file)
@@ -1,5 +1,3 @@
-#![deny(rust_2018_idioms)]
-
 use std::path::{Path, PathBuf};
 use std::ffi::CString;
 use std::fs;
index 55aba7caa9d42e46e99540e54f84d110ddb03b0d..b257311138587bb8055cd41ec7c6dd72af058d8f 100644 (file)
@@ -8,9 +8,6 @@
 
 #![recursion_limit="256"]
 
-#![deny(rust_2018_idioms)]
-#![deny(unused_lifetimes)]
-
 #[macro_use] extern crate rustc;
 #[macro_use] extern crate log;
 
index 674b2b60e44a2520dcfe81209b47399b61863b46..fef60a47dc4e7adfbed803e2978c168f918bafe2 100644 (file)
@@ -12,7 +12,6 @@
 use rustc_data_structures::sync::Lrc;
 use rustc_data_structures::fx::{FxHashSet, FxHashMap};
 use rustc_metadata::cstore::CStore;
-use std::io::Write;
 use std::path::PathBuf;
 use std::result;
 use std::sync::{Arc, Mutex};
index 4bc50c24e817c216889e7ce06b4d63625f312b87..2e593d441553a014c28a85bafb16e1b033e272f4 100644 (file)
@@ -6,11 +6,6 @@
 #![feature(generators)]
 #![cfg_attr(unix, feature(libc))]
 
-#![deny(rust_2018_idioms)]
-#![deny(unused_lifetimes)]
-
-#![allow(unused_imports)]
-
 #![recursion_limit="256"]
 
 #[cfg(unix)]
index 2754c55ea06853d25c9aa037c4b2e4a3b3f01f43..8dd2595967fd79130e0e108b86d52650070cab87 100644 (file)
@@ -2,7 +2,7 @@
 use crate::util;
 use crate::proc_macro_decls;
 
-use log::{debug, info, warn, log_enabled};
+use log::{info, warn, log_enabled};
 use rustc::dep_graph::DepGraph;
 use rustc::hir;
 use rustc::hir::lowering::lower_crate;
 use rustc::lint;
 use rustc::middle::{self, reachable, resolve_lifetime, stability};
 use rustc::middle::cstore::CrateStore;
-use rustc::middle::privacy::AccessLevels;
 use rustc::ty::{self, AllArenas, Resolutions, TyCtxt, GlobalCtxt};
 use rustc::ty::steal::Steal;
 use rustc::traits;
 use rustc::util::common::{time, ErrorReported};
-use rustc::util::profiling::ProfileCategory;
-use rustc::session::{CompileResult, CrateDisambiguator, Session};
+use rustc::session::Session;
 use rustc::session::config::{self, CrateType, Input, OutputFilenames, OutputType};
 use rustc::session::search_paths::PathKind;
-use rustc_allocator as allocator;
 use rustc_ast_borrowck as borrowck;
 use rustc_codegen_ssa::back::link::emit_metadata;
 use rustc_codegen_utils::codegen_backend::CodegenBackend;
 use rustc_codegen_utils::link::filename_for_metadata;
 use rustc_data_structures::{box_region_allow_access, declare_box_region_type, parallel};
-use rustc_data_structures::fingerprint::Fingerprint;
-use rustc_data_structures::stable_hasher::StableHasher;
 use rustc_data_structures::sync::{Lrc, ParallelIterator, par_iter};
 use rustc_incremental;
-use rustc_incremental::DepGraphFuture;
 use rustc_metadata::creader::CrateLoader;
 use rustc_metadata::cstore::{self, CStore};
 use rustc_mir as mir;
-use rustc_passes::{self, ast_validation, hir_stats, loops, rvalue_promotion, layout_test};
+use rustc_passes::{self, ast_validation, hir_stats, layout_test};
 use rustc_plugin as plugin;
 use rustc_plugin::registry::Registry;
 use rustc_privacy;
 use rustc_resolve::{Resolver, ResolverArenas};
 use rustc_traits;
 use rustc_typeck as typeck;
-use syntax::{self, ast, attr, diagnostics, visit};
+use syntax::{self, ast, diagnostics, visit};
 use syntax::early_buffered_lints::BufferedEarlyLint;
 use syntax::ext::base::{NamedSyntaxExtension, ExtCtxt};
 use syntax::mut_visit::MutVisitor;
 use syntax::parse::{self, PResult};
 use syntax::util::node_count::NodeCounter;
-use syntax::util::lev_distance::find_best_match_for_name;
 use syntax::symbol::Symbol;
 use syntax::feature_gate::AttributeType;
-use syntax_pos::{FileName, edition::Edition, hygiene};
+use syntax_pos::FileName;
 use syntax_ext;
 
 use rustc_serialize::json;
 use std::fs;
 use std::io::{self, Write};
 use std::iter;
-use std::path::{Path, PathBuf};
+use std::path::PathBuf;
 use std::sync::mpsc;
 use std::cell::RefCell;
 use std::rc::Rc;
 use std::mem;
-use std::ops::Generator;
 
 pub fn parse<'a>(sess: &'a Session, input: &Input) -> PResult<'a, ast::Crate> {
     sess.diagnostic()
@@ -278,7 +270,12 @@ pub fn register_plugins<'a>(
 
     krate = time(sess, "crate injection", || {
         let alt_std_name = sess.opts.alt_std_name.as_ref().map(|s| &**s);
-        syntax::std_inject::maybe_inject_crates_ref(krate, alt_std_name, sess.edition())
+        let (krate, name) =
+            syntax_ext::standard_library_imports::inject(krate, alt_std_name, sess.edition());
+        if let Some(name) = name {
+            sess.parse_sess.injected_crate_name.set(name);
+        }
+        krate
     });
 
     let registrars = time(sess, "plugin loading", || {
@@ -456,7 +453,7 @@ fn configure_and_expand_inner<'a>(
     sess.profiler(|p| p.end_activity("macro expansion"));
 
     time(sess, "maybe building test harness", || {
-        syntax::test::modify_for_testing(
+        syntax_ext::test_harness::inject(
             &sess.parse_sess,
             &mut resolver,
             sess.opts.test,
@@ -485,7 +482,7 @@ fn configure_and_expand_inner<'a>(
             let num_crate_types = crate_types.len();
             let is_proc_macro_crate = crate_types.contains(&config::CrateType::ProcMacro);
             let is_test_crate = sess.opts.test;
-            syntax_ext::proc_macro_decls::modify(
+            syntax_ext::proc_macro_harness::inject(
                 &sess.parse_sess,
                 &mut resolver,
                 krate,
index 9b79dc6350ca67c086ebaf9a2e531a991a5efd21..2e7952cd004477d99e311946a49fee1fac8b6b7d 100644 (file)
@@ -2,30 +2,18 @@
 use crate::passes::{self, BoxedResolver, ExpansionResult, BoxedGlobalCtxt, PluginInfo};
 
 use rustc_incremental::DepGraphFuture;
-use rustc_data_structures::sync::Lrc;
-use rustc::session::config::{Input, OutputFilenames, OutputType};
-use rustc::session::Session;
+use rustc::session::config::{OutputFilenames, OutputType};
 use rustc::util::common::{time, ErrorReported};
-use rustc::util::profiling::ProfileCategory;
-use rustc::lint;
 use rustc::hir;
 use rustc::hir::def_id::LOCAL_CRATE;
-use rustc::ty;
 use rustc::ty::steal::Steal;
 use rustc::dep_graph::DepGraph;
-use rustc_passes::hir_stats;
-use rustc_plugin::registry::Registry;
-use rustc_serialize::json;
 use std::cell::{Ref, RefMut, RefCell};
-use std::ops::Deref;
 use std::rc::Rc;
 use std::sync::mpsc;
 use std::any::Any;
 use std::mem;
-use syntax::parse::{self, PResult};
-use syntax::util::node_count::NodeCounter;
-use syntax::{self, ast, attr, diagnostics, visit};
-use syntax_pos::hygiene;
+use syntax::{self, ast};
 
 /// Represent the result of a query.
 /// This result can be stolen with the `take` method and returned with the `give` method.
index 6ae5e94b11af389d9afc90388c08642785500bda..f007a0cf2abee5ef23437a4d0ff8a7abedf27606 100644 (file)
@@ -203,8 +203,6 @@ pub fn spawn_thread_pool<F: FnOnce() -> R + Send, R: Send>(
     f: F,
 ) -> R {
     use rayon::{ThreadPool, ThreadPoolBuilder};
-    use syntax;
-    use syntax_pos;
 
     let gcx_ptr = &Lock::new(0);
 
index c7a8c2b892351839dedd8533b4dd31b331f1152f..d3975360525d0673e7c2029d3e5c379003701bc9 100644 (file)
@@ -19,9 +19,6 @@
 
 #![recursion_limit="256"]
 
-#![deny(rust_2018_idioms)]
-#![deny(unused_lifetimes)]
-
 #[macro_use]
 extern crate rustc;
 
index dea7e6ae0a2abf85088602bf6eafbc3e01b7b700..647d473f01572ac24a74ace2e7d5fab2dd6448b8 100644 (file)
@@ -1,4 +1,3 @@
-#![deny(rust_2018_idioms)]
 #![feature(nll)]
 #![feature(static_nobundle)]
 
index 3bdb86d313dcbb703db8bc2763a3baf9c71f1ab3..d6c8e54c18db7ea9e9f6d9bdefc1e2ce0d5e3dd3 100644 (file)
@@ -6,5 +6,3 @@
 #![unstable(feature = "sanitizer_runtime_lib",
             reason = "internal implementation detail of sanitizers",
             issue = "0")]
-
-#![deny(rust_2018_idioms)]
index 53bbecd0e6a1d242ac127d544253f06b1d1c1ddc..85e2247ebd7e38b50f91b7427194b93771e87da4 100644 (file)
@@ -1,5 +1,4 @@
 #![feature(proc_macro_hygiene)]
-#![deny(rust_2018_idioms)]
 #![cfg_attr(not(bootstrap), allow(rustc::default_hash_types))]
 
 #![recursion_limit="128"]
index a9f054d5e8be80a32e02c194ddc4d03d27afe643..5ff60a9267bad52ba8dbde98a128679ceace9f42 100644 (file)
@@ -21,5 +21,4 @@ rustc_target = { path = "../librustc_target" }
 rustc_serialize = { path = "../libserialize", package = "serialize" }
 stable_deref_trait = "1.0.0"
 syntax = { path = "../libsyntax" }
-syntax_ext = { path = "../libsyntax_ext" }
 syntax_pos = { path = "../libsyntax_pos" }
index 3404ec5e173bdfd93aed4325d61c8da79d86c8d9..d5f1e715186f4ca984eb3c1f1a218bfe0aa4630d 100644 (file)
@@ -586,8 +586,7 @@ fn load_derive_macros(&mut self, root: &CrateRoot<'_>, dylib: Option<PathBuf>, s
         use std::{env, mem};
         use crate::dynamic_lib::DynamicLibrary;
         use proc_macro::bridge::client::ProcMacro;
-        use syntax_ext::deriving::custom::ProcMacroDerive;
-        use syntax_ext::proc_macro_impl::{AttrProcMacro, BangProcMacro};
+        use syntax::ext::proc_macro::{BangProcMacro, AttrProcMacro, ProcMacroDerive};
 
         let path = match dylib {
             Some(dylib) => dylib,
index 914084d7e9ece4f489ef6dc9ee62a71c8a201b4e..ee1175e798d806cddfb85c3f0618a316979b3e33 100644 (file)
 use syntax::source_map;
 use syntax::edition::Edition;
 use syntax::ext::base::{SyntaxExtension, SyntaxExtensionKind};
+use syntax::ext::proc_macro::BangProcMacro;
 use syntax::parse::source_file_to_stream;
 use syntax::parse::parser::emit_unclosed_delims;
 use syntax::symbol::{Symbol, sym};
-use syntax_ext::proc_macro_impl::BangProcMacro;
 use syntax_pos::{Span, NO_EXPANSION, FileName};
 use rustc_data_structures::bit_set::BitSet;
 
index 909fca2ab586f2e983894772c5cf87231422616d..0708a6243bf296c92f96dbbc8c1d71a882975209 100644 (file)
@@ -1,5 +1,3 @@
-#![allow(non_snake_case)]
-
 use syntax::{register_diagnostics, register_long_diagnostics};
 
 register_long_diagnostics! {
index 8db3ec491df8331d0e3ab58ce7c8b2291cf5f284..c96d02d9b37dee5649ee9626642a26e2a3476b0d 100644 (file)
@@ -15,9 +15,6 @@
 
 #![recursion_limit="256"]
 
-#![deny(rust_2018_idioms)]
-#![deny(unused_lifetimes)]
-
 extern crate libc;
 extern crate proc_macro;
 
index 5d0e490ebea5a0549ae4e43bfa4b9d994d66bfee..77e5ac2f865142d2615999739c729910b1ab8f34 100644 (file)
@@ -1140,19 +1140,18 @@ fn try_report_cannot_return_reference_to_local(
                 bug!("try_report_cannot_return_reference_to_local: not a local")
             };
             match self.body.local_kind(*local) {
-                LocalKind::ReturnPointer | LocalKind::Temp => {
-                    (
-                        "temporary value".to_string(),
-                        "temporary value created here".to_string(),
-                    )
-                }
-                LocalKind::Arg => {
-                    (
-                        "function parameter".to_string(),
-                        "function parameter borrowed here".to_string(),
-                    )
-                },
-                LocalKind::Var => bug!("local variable without a name"),
+                LocalKind::ReturnPointer | LocalKind::Temp => (
+                    "temporary value".to_string(),
+                    "temporary value created here".to_string(),
+                ),
+                LocalKind::Arg => (
+                    "function parameter".to_string(),
+                    "function parameter borrowed here".to_string(),
+                ),
+                LocalKind::Var => (
+                    "local binding".to_string(),
+                    "local binding introduced here".to_string(),
+                ),
             }
         };
 
index 45b806bd286d8286c8d77fd0f2497a0e53b4a373..50c0640f885f2f25a1102812bee95aa6ce1cf67b 100644 (file)
@@ -1,7 +1,5 @@
 //! This pass type-checks the MIR to ensure it is not broken.
 
-#![allow(unreachable_code)]
-
 use crate::borrow_check::borrow_set::BorrowSet;
 use crate::borrow_check::location::LocationTable;
 use crate::borrow_check::nll::constraints::{OutlivesConstraintSet, OutlivesConstraint};
index 8948d1c4b3663db2e3740850577df43c2e0d9664..4e970aee42cf47ca9b077d50791941005c19fdf7 100644 (file)
@@ -121,7 +121,7 @@ pub fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> Body<'_> {
                             self_arg = None;
                         }
 
-                        ArgInfo(fn_sig.inputs()[index], opt_ty_info, Some(&*arg.pat), self_arg)
+                        ArgInfo(fn_sig.inputs()[index], opt_ty_info, Some(&arg), self_arg)
                     });
 
             let arguments = implicit_argument.into_iter().chain(explicit_arguments);
@@ -511,7 +511,7 @@ fn should_abort_on_panic(tcx: TyCtxt<'_>, fn_def_id: DefId, abi: Abi) -> bool {
 ///////////////////////////////////////////////////////////////////////////
 /// the main entry point for building MIR for a function
 
-struct ArgInfo<'tcx>(Ty<'tcx>, Option<Span>, Option<&'tcx hir::Pat>, Option<ImplicitSelfKind>);
+struct ArgInfo<'tcx>(Ty<'tcx>, Option<Span>, Option<&'tcx hir::Arg>, Option<ImplicitSelfKind>);
 
 fn construct_fn<'a, 'tcx, A>(
     hir: Cx<'a, 'tcx>,
@@ -782,13 +782,13 @@ fn args_and_body(&mut self,
                      -> BlockAnd<()>
     {
         // Allocate locals for the function arguments
-        for &ArgInfo(ty, _, pattern, _) in arguments.iter() {
+        for &ArgInfo(ty, _, arg_opt, _) in arguments.iter() {
             // If this is a simple binding pattern, give the local a name for
             // debuginfo and so that error reporting knows that this is a user
             // variable. For any other pattern the pattern introduces new
             // variables which will be named instead.
-            let (name, span) = if let Some(pat) = pattern {
-                (pat.simple_ident().map(|ident| ident.name), pat.span)
+            let (name, span) = if let Some(arg) = arg_opt {
+                (arg.pat.simple_ident().map(|ident| ident.name), arg.pat.span)
             } else {
                 (None, self.fn_span)
             };
@@ -813,18 +813,19 @@ fn args_and_body(&mut self,
             // Function arguments always get the first Local indices after the return place
             let local = Local::new(index + 1);
             let place = Place::from(local);
-            let &ArgInfo(ty, opt_ty_info, pattern, ref self_binding) = arg_info;
+            let &ArgInfo(ty, opt_ty_info, arg_opt, ref self_binding) = arg_info;
 
             // Make sure we drop (parts of) the argument even when not matched on.
             self.schedule_drop(
-                pattern.as_ref().map_or(ast_body.span, |pat| pat.span),
+                arg_opt.as_ref().map_or(ast_body.span, |arg| arg.pat.span),
                 argument_scope, local, ty, DropKind::Value,
             );
 
-            if let Some(pattern) = pattern {
-                let pattern = self.hir.pattern_from_hir(pattern);
+            if let Some(arg) = arg_opt {
+                let pattern = self.hir.pattern_from_hir(&arg.pat);
+                let original_source_scope = self.source_scope;
                 let span = pattern.span;
-
+                self.set_correct_source_scope_for_arg(arg.hir_id, original_source_scope, span);
                 match *pattern.kind {
                     // Don't introduce extra copies for simple bindings
                     PatternKind::Binding {
@@ -835,6 +836,7 @@ fn args_and_body(&mut self,
                         ..
                     } => {
                         self.local_decls[local].mutability = mutability;
+                        self.local_decls[local].source_info.scope = self.source_scope;
                         self.local_decls[local].is_user_variable =
                             if let Some(kind) = self_binding {
                                 Some(ClearCrossCrate::Set(BindingForm::ImplicitSelf(*kind)))
@@ -860,6 +862,7 @@ fn args_and_body(&mut self,
                         unpack!(block = self.place_into_pattern(block, pattern, &place, false));
                     }
                 }
+                self.source_scope = original_source_scope;
             }
         }
 
@@ -872,6 +875,30 @@ fn args_and_body(&mut self,
         self.into(&Place::RETURN_PLACE, block, body)
     }
 
+    fn set_correct_source_scope_for_arg(
+        &mut self,
+        arg_hir_id: hir::HirId,
+        original_source_scope: SourceScope,
+        pattern_span: Span
+    ) {
+        let tcx = self.hir.tcx();
+        let current_root = tcx.maybe_lint_level_root_bounded(
+            arg_hir_id,
+            self.hir.root_lint_level
+        );
+        let parent_root = tcx.maybe_lint_level_root_bounded(
+            self.source_scope_local_data[original_source_scope].lint_root,
+            self.hir.root_lint_level,
+        );
+        if current_root != parent_root {
+            self.source_scope = self.new_source_scope(
+                pattern_span,
+                LintLevel::Explicit(current_root),
+                None
+            );
+        }
+    }
+
     fn get_unit_temp(&mut self) -> Place<'tcx> {
         match self.unit_temp {
             Some(ref tmp) => tmp.clone(),
index 83d441b90be720aacb650654f8c62facba121e69..a5e44a1933c9d3602346aa0e2130e57e4e23d14f 100644 (file)
@@ -1,5 +1,3 @@
-#![allow(non_snake_case)]
-
 register_long_diagnostics! {
 
 
index 1baeda41498ed0d50392d679e6dc886d501ef1a0..f759ec7f219d12d68ec5b8cb80d79548111b7937 100644 (file)
@@ -162,7 +162,7 @@ pub enum PatternKind<'tcx> {
 
     /// Matches against a slice, checking the length and extracting elements.
     /// irrefutable when there is a slice pattern and both `prefix` and `suffix` are empty.
-    /// e.g., `&[ref xs..]`.
+    /// e.g., `&[ref xs @ ..]`.
     Slice {
         prefix: Vec<Pattern<'tcx>>,
         slice: Option<Pattern<'tcx>>,
index 964f04d79b960723fd3bb0cf0ab5897c17510125..20d5e54d2ce4939683a1dbf2d10dc4847cf9ed29 100644 (file)
@@ -26,9 +26,6 @@
 
 #![recursion_limit="256"]
 
-#![deny(rust_2018_idioms)]
-#![deny(unused_lifetimes)]
-
 #[macro_use] extern crate log;
 #[macro_use] extern crate rustc;
 #[macro_use] extern crate rustc_data_structures;
index 3bdb86d313dcbb703db8bc2763a3baf9c71f1ab3..d6c8e54c18db7ea9e9f6d9bdefc1e2ce0d5e3dd3 100644 (file)
@@ -6,5 +6,3 @@
 #![unstable(feature = "sanitizer_runtime_lib",
             reason = "internal implementation detail of sanitizers",
             issue = "0")]
-
-#![deny(rust_2018_idioms)]
index de2476775b07e361ae1fccba0d13934d2f140999..596ec6c19bcbfd0b5e419173ca1d6541a47270df 100644 (file)
@@ -11,9 +11,7 @@ path = "lib.rs"
 [dependencies]
 log = "0.4"
 rustc = { path = "../librustc" }
-rustc_mir = { path = "../librustc_mir"}
 rustc_data_structures = { path = "../librustc_data_structures" }
 syntax = { path = "../libsyntax" }
-syntax_ext = { path = "../libsyntax_ext" }
 syntax_pos = { path = "../libsyntax_pos" }
 errors = { path = "../librustc_errors", package = "rustc_errors" }
index b550029d9786d33bdc962ac0e3f718825d2525df..7ad37e65f7178a324dbafa825289f18d16aeb052 100644 (file)
 use rustc_data_structures::fx::FxHashMap;
 use syntax::ast::*;
 use syntax::attr;
+use syntax::ext::proc_macro::is_proc_macro_attr;
 use syntax::feature_gate::is_builtin_attr;
 use syntax::source_map::Spanned;
 use syntax::symbol::{kw, sym};
 use syntax::visit::{self, Visitor};
 use syntax::{span_err, struct_span_err, walk_list};
-use syntax_ext::proc_macro_decls::is_proc_macro_attr;
 use syntax_pos::{Span, MultiSpan};
 use errors::{Applicability, FatalError};
 
@@ -287,7 +287,7 @@ fn no_questions_in_bounds(&self, bounds: &GenericBounds, where_: &str, is_trait:
     // ```
     fn check_expr_within_pat(&self, expr: &Expr, allow_paths: bool) {
         match expr.node {
-            ExprKind::Lit(..) => {}
+            ExprKind::Lit(..) | ExprKind::Err => {}
             ExprKind::Path(..) if allow_paths => {}
             ExprKind::Unary(UnOp::Neg, ref inner)
                 if match inner.node { ExprKind::Lit(_) => true, _ => false } => {}
index 36ebe5cf455ff6a46e677767e98f0f09b3d4a909..cd33943e77e203c0921294ec4cedbd11d3cca1ec 100644 (file)
@@ -1,5 +1,3 @@
-#![allow(non_snake_case)]
-
 use syntax::{register_diagnostics, register_long_diagnostics};
 
 register_long_diagnostics! {
index e7f6abc410a32f90e945347af9089453dc77ac32..8fba3256ec429585697557c7334eeef38ea3effc 100644 (file)
@@ -94,6 +94,11 @@ fn print(&self, title: &str) {
 }
 
 impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
+    fn visit_arg(&mut self, arg: &'v hir::Arg) {
+        self.record("Arg", Id::Node(arg.hir_id), arg);
+        hir_visit::walk_arg(self, arg)
+    }
+
     fn nested_visit_map<'this>(&'this mut self) -> hir_visit::NestedVisitorMap<'this, 'v> {
         panic!("visit_nested_xxx must be manually implemented in this visitor")
     }
index 0a96ad3e3445e7bc59becea63d2779586bd39e3f..5614b570b927aa646265747fbeca93a79dac03d0 100644 (file)
@@ -13,9 +13,6 @@
 
 #![recursion_limit="256"]
 
-#![deny(rust_2018_idioms)]
-#![deny(unused_lifetimes)]
-
 #[macro_use]
 extern crate rustc;
 
index 9e76f52a111b57e02a345947a598524e5f067ba1..b5f6a8d905d314542f6e9c14f89aa9a886bf6fdf 100644 (file)
@@ -1,5 +1,3 @@
-#![allow(non_snake_case)]
-
 use syntax::{register_diagnostics, register_long_diagnostics};
 
 register_long_diagnostics! {
index 6520cdc306203eb3cdffeecd458e016348cd43f5..25a7a8cdeb6d67c717a480dff1ca1d35deb05ea1 100644 (file)
@@ -59,8 +59,6 @@
 
 #![recursion_limit="256"]
 
-#![deny(rust_2018_idioms)]
-
 pub use registry::Registry;
 
 mod error_codes;
index fa4df53e47b318146a0c3333bb5c58d5c1d76b52..70a799d426a07f5ce686d4343cee538742714b79 100644 (file)
@@ -1,5 +1,3 @@
-#![allow(non_snake_case)]
-
 register_long_diagnostics! {
 
 E0445: r##"
index 05df3a6f6bc2eeba279a37fb4c84a517b491b6cd..e291f40ffd27d9c7140ae94bb2e5c42dd9303883 100644 (file)
@@ -1,8 +1,5 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
 
-#![deny(rust_2018_idioms)]
-#![deny(unused_lifetimes)]
-
 #![feature(in_band_lifetimes)]
 #![feature(nll)]
 #![feature(rustc_diagnostic_macros)]
index f52f7d9cfb3c307b88822e45611905956dc4df0d..41349cf72a16024c5ef48bcc6a333cbc084e4c39 100644 (file)
@@ -34,7 +34,6 @@
 use syntax::feature_gate::is_builtin_attr;
 use syntax::parse::token::{self, Token};
 use syntax::span_err;
-use syntax::std_inject::injected_crate_name;
 use syntax::symbol::{kw, sym};
 use syntax::visit::{self, Visitor};
 
@@ -367,8 +366,10 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent_scope: ParentScop
                 };
 
                 self.populate_module_if_necessary(module);
-                if injected_crate_name().map_or(false, |name| ident.name.as_str() == name) {
-                    self.injected_crate = Some(module);
+                if let Some(name) = self.session.parse_sess.injected_crate_name.try_get() {
+                    if name.as_str() == ident.name.as_str() {
+                        self.injected_crate = Some(module);
+                    }
                 }
 
                 let used = self.process_legacy_macro_imports(item, module, &parent_scope);
index 15194a5d1463bea2c4afa02d9f4e31693766abe0..e01f53786edab2cd3a239c928fda288f0c4e10cd 100644 (file)
@@ -1,5 +1,3 @@
-#![allow(non_snake_case)]
-
 use syntax::{register_diagnostics, register_long_diagnostics};
 
 // Error messages for EXXXX errors.  Each message should start and end with a
index a5e498fa75643999e5a4647e6abe48e076d1703f..bc5898fe78da7872686e68ce302bd44fe7af64b6 100644 (file)
@@ -10,9 +10,6 @@
 
 #![recursion_limit="256"]
 
-#![deny(rust_2018_idioms)]
-#![deny(unused_lifetimes)]
-
 pub use rustc::hir::def::{Namespace, PerNS};
 
 use Determinacy::*;
index 5e66b11bfe30dc6686064c9db2864c8d9a6b2c0e..25dcd4664a624590fe9ff3f267906e1d1e009776 100644 (file)
@@ -1,12 +1,8 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
 #![feature(nll)]
-#![deny(rust_2018_idioms)]
-#![deny(unused_lifetimes)]
-#![allow(unused_attributes)]
 
 #![recursion_limit="256"]
 
-
 mod dumper;
 mod dump_visitor;
 #[macro_use]
index db8c915cdb4bdb4c490b87ed30f0c1884163e611..1aec990064a86f001553210ce0dbcd3e87c8f21e 100644 (file)
@@ -1,5 +1,3 @@
-#![allow(non_upper_case_globals)]
-
 use crate::abi::call::{FnType, ArgType};
 
 fn classify_ret_ty<Ty>(ret: &mut ArgType<'_, Ty>) {
index 4a4c6799c005e0f5d35326aeea4b8b8c8ed800c2..80fcb45d0b9bc0157347b90a80c8c745120767d5 100644 (file)
@@ -105,20 +105,34 @@ pub fn parse(target: &Target) -> Result<TargetDataLayout, String> {
         let mut dl = TargetDataLayout::default();
         let mut i128_align_src = 64;
         for spec in target.data_layout.split('-') {
-            match spec.split(':').collect::<Vec<_>>()[..] {
+            let spec_parts = spec.split(':').collect::<Vec<_>>();
+
+            match &*spec_parts {
                 ["e"] => dl.endian = Endian::Little,
                 ["E"] => dl.endian = Endian::Big,
                 [p] if p.starts_with("P") => {
                     dl.instruction_address_space = parse_address_space(&p[1..], "P")?
                 }
-                ["a", ref a..] => dl.aggregate_align = align(a, "a")?,
-                ["f32", ref a..] => dl.f32_align = align(a, "f32")?,
-                ["f64", ref a..] => dl.f64_align = align(a, "f64")?,
-                [p @ "p", s, ref a..] | [p @ "p0", s, ref a..] => {
+                // FIXME: Ping cfg(bootstrap) -- Use `ref a @ ..` with new bootstrap compiler.
+                ["a", ..] => {
+                    let a = &spec_parts[1..]; // FIXME inline into pattern.
+                    dl.aggregate_align = align(a, "a")?
+                }
+                ["f32", ..] => {
+                    let a = &spec_parts[1..]; // FIXME inline into pattern.
+                    dl.f32_align = align(a, "f32")?
+                }
+                ["f64", ..] => {
+                    let a = &spec_parts[1..]; // FIXME inline into pattern.
+                    dl.f64_align = align(a, "f64")?
+                }
+                [p @ "p", s, ..] | [p @ "p0", s, ..] => {
+                    let a = &spec_parts[2..]; // FIXME inline into pattern.
                     dl.pointer_size = size(s, p)?;
                     dl.pointer_align = align(a, p)?;
                 }
-                [s, ref a..] if s.starts_with("i") => {
+                [s, ..] if s.starts_with("i") => {
+                    let a = &spec_parts[1..]; // FIXME inline into pattern.
                     let bits = match s[1..].parse::<u64>() {
                         Ok(bits) => bits,
                         Err(_) => {
@@ -142,7 +156,8 @@ pub fn parse(target: &Target) -> Result<TargetDataLayout, String> {
                         dl.i128_align = a;
                     }
                 }
-                [s, ref a..] if s.starts_with("v") => {
+                [s, ..] if s.starts_with("v") => {
+                    let a = &spec_parts[1..]; // FIXME inline into pattern.
                     let v_size = size(&s[1..], "v")?;
                     let a = align(a, s)?;
                     if let Some(v) = dl.vector_align.iter_mut().find(|v| v.0 == v_size) {
index a14bc66cc3833318585a34c29dd550cc76a3d9a8..a349dc26e834cc295599239f6f80a52fb0fc0ce9 100644 (file)
@@ -13,9 +13,6 @@
 #![feature(nll)]
 #![feature(slice_patterns)]
 
-#![deny(rust_2018_idioms)]
-#![deny(unused_lifetimes)]
-
 #[macro_use] extern crate log;
 
 pub mod abi;
index 39a8ce9282573aaa1e4dba529dcb9871ff1a2416..6f00245b009411e738c31a597efa6483ce025d06 100644 (file)
@@ -132,6 +132,14 @@ pub fn options() -> TargetOptions {
         // non-relative calls and such later on).
         relocation_model: "static".to_string(),
 
+        // When the atomics feature is activated then these two keys matter,
+        // otherwise they're basically ignored by the standard library. In this
+        // mode, however, the `#[thread_local]` attribute works (i.e.
+        // `has_elf_tls`) and we need to get it to work by specifying
+        // `local-exec` as that's all that's implemented in LLVM today for wasm.
+        has_elf_tls: true,
+        tls_model: "local-exec".to_string(),
+
         .. Default::default()
     }
 }
index 12b19a2648d7f6d8577d66efbdd6f80fce80c992..ebe6b7c6138850b346c6fda8bbb3388b33aec267 100644 (file)
@@ -1,9 +1,6 @@
 //! New recursive solver modeled on Chalk's recursive solver. Most of
 //! the guts are broken up into modules; see the comments in those modules.
 
-#![deny(rust_2018_idioms)]
-#![deny(unused_lifetimes)]
-
 #![feature(crate_visibility_modifier)]
 #![feature(in_band_lifetimes)]
 #![feature(nll)]
index 3bdb86d313dcbb703db8bc2763a3baf9c71f1ab3..d6c8e54c18db7ea9e9f6d9bdefc1e2ce0d5e3dd3 100644 (file)
@@ -6,5 +6,3 @@
 #![unstable(feature = "sanitizer_runtime_lib",
             reason = "internal implementation detail of sanitizers",
             issue = "0")]
-
-#![deny(rust_2018_idioms)]
index 3f0604b84b7d723029cd8cdae8aef45f4e90edd3..e4dda20c822bf26f8d996768d5ced26ac7da2501 100644 (file)
@@ -196,7 +196,11 @@ pub fn check_pat_walk(
                 let rhs_ty = self.check_expr(end);
 
                 // Check that both end-points are of numeric or char type.
-                let numeric_or_char = |ty: Ty<'_>| ty.is_numeric() || ty.is_char();
+                let numeric_or_char = |ty: Ty<'_>| {
+                    ty.is_numeric()
+                    || ty.is_char()
+                    || ty.references_error()
+                };
                 let lhs_compat = numeric_or_char(lhs_ty);
                 let rhs_compat = numeric_or_char(rhs_ty);
 
@@ -551,21 +555,18 @@ fn borrow_pat_suggestion(
     ) {
         let tcx = self.tcx;
         if let PatKind::Binding(..) = inner.node {
-            let parent_id = tcx.hir().get_parent_node(pat.hir_id);
-            let parent = tcx.hir().get(parent_id);
-            debug!("inner {:?} pat {:?} parent {:?}", inner, pat, parent);
-            match parent {
-                hir::Node::Item(hir::Item { node: hir::ItemKind::Fn(..), .. }) |
-                hir::Node::ForeignItem(hir::ForeignItem {
-                    node: hir::ForeignItemKind::Fn(..), ..
-                }) |
-                hir::Node::TraitItem(hir::TraitItem { node: hir::TraitItemKind::Method(..), .. }) |
-                hir::Node::ImplItem(hir::ImplItem { node: hir::ImplItemKind::Method(..), .. }) => {
-                    // this pat is likely an argument
+            let binding_parent_id = tcx.hir().get_parent_node(pat.hir_id);
+            let binding_parent = tcx.hir().get(binding_parent_id);
+            debug!("inner {:?} pat {:?} parent {:?}", inner, pat, binding_parent);
+            match binding_parent {
+                hir::Node::Arg(hir::Arg { span, .. }) => {
                     if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(inner.span) {
-                        // FIXME: turn into structured suggestion, will need a span that also
-                        // includes the the arg's type.
-                        err.help(&format!("did you mean `{}: &{}`?", snippet, expected));
+                        err.span_suggestion(
+                            *span,
+                            &format!("did you mean `{}`", snippet),
+                            format!(" &{}", expected),
+                            Applicability::MachineApplicable,
+                        );
                     }
                 }
                 hir::Node::Arm(_) |
index 14c38ae053d23d4cb5001411b8aa7c6db2a617d7..3229d49841e79794a1fabf310162ff1e6bca31a3 100644 (file)
@@ -235,40 +235,56 @@ fn can_use_as_ref(
         &self,
         expr: &hir::Expr,
     ) -> Option<(Span, &'static str, String)> {
-        if let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) = expr.node {
-            if let hir::def::Res::Local(id) = path.res {
-                let parent = self.tcx.hir().get_parent_node(id);
-                if let Some(Node::Expr(hir::Expr {
-                    hir_id,
-                    node: hir::ExprKind::Closure(_, decl, ..),
-                    ..
-                })) = self.tcx.hir().find(parent) {
-                    let parent = self.tcx.hir().get_parent_node(*hir_id);
-                    if let (Some(Node::Expr(hir::Expr {
-                        node: hir::ExprKind::MethodCall(path, span, expr),
-                        ..
-                    })), 1) = (self.tcx.hir().find(parent), decl.inputs.len()) {
-                        let self_ty = self.tables.borrow().node_type(expr[0].hir_id);
-                        let self_ty = format!("{:?}", self_ty);
-                        let name = path.ident.as_str();
-                        let is_as_ref_able = (
-                            self_ty.starts_with("&std::option::Option") ||
-                            self_ty.starts_with("&std::result::Result") ||
-                            self_ty.starts_with("std::option::Option") ||
-                            self_ty.starts_with("std::result::Result")
-                        ) && (name == "map" || name == "and_then");
-                        match (is_as_ref_able, self.sess().source_map().span_to_snippet(*span)) {
-                            (true, Ok(src)) => {
-                                return Some((*span, "consider using `as_ref` instead",
-                                             format!("as_ref().{}", src)));
-                            },
-                            _ => ()
-                        }
-                    }
-                }
-            }
+        let path = match expr.node {
+            hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) => path,
+            _ => return None
+        };
+
+        let local_id = match path.res {
+            hir::def::Res::Local(id) => id,
+            _ => return None
+        };
+
+        let local_parent = self.tcx.hir().get_parent_node(local_id);
+        let arg_hir_id = match self.tcx.hir().find(local_parent) {
+            Some(Node::Arg(hir::Arg { hir_id, .. })) => hir_id,
+            _ => return None
+        };
+
+        let arg_parent = self.tcx.hir().get_parent_node(*arg_hir_id);
+        let (expr_hir_id, closure_fn_decl) = match self.tcx.hir().find(arg_parent) {
+            Some(Node::Expr(
+                hir::Expr { hir_id, node: hir::ExprKind::Closure(_, decl, ..), .. }
+            )) => (hir_id, decl),
+            _ => return None
+        };
+
+        let expr_parent = self.tcx.hir().get_parent_node(*expr_hir_id);
+        let hir = self.tcx.hir().find(expr_parent);
+        let closure_params_len = closure_fn_decl.inputs.len();
+        let (method_path, method_span, method_expr) = match (hir, closure_params_len) {
+            (Some(Node::Expr(
+                hir::Expr { node: hir::ExprKind::MethodCall(path, span, expr), .. }
+            )), 1) => (path, span, expr),
+            _ => return None
+        };
+
+        let self_ty = self.tables.borrow().node_type(method_expr[0].hir_id);
+        let self_ty = format!("{:?}", self_ty);
+        let name = method_path.ident.as_str();
+        let is_as_ref_able = (
+            self_ty.starts_with("&std::option::Option") ||
+            self_ty.starts_with("&std::result::Result") ||
+            self_ty.starts_with("std::option::Option") ||
+            self_ty.starts_with("std::result::Result")
+        ) && (name == "map" || name == "and_then");
+        match (is_as_ref_able, self.sess().source_map().span_to_snippet(*method_span)) {
+            (true, Ok(src)) => {
+                let suggestion = format!("as_ref().{}", src);
+                Some((*method_span, "consider using `as_ref` instead", suggestion))
+            },
+            _ => None
         }
-        None
     }
 
     crate fn is_hir_id_from_struct_pattern_shorthand_field(
index 36977b878dd7e88307798e6442a22c317cfd9852..1b4dbfe4be6df1a8608ed85e4a78a95b043d7fb6 100644 (file)
@@ -1325,19 +1325,35 @@ fn check_union(tcx: TyCtxt<'_>, id: hir::HirId, span: Span) {
     check_packed(tcx, span, def_id);
 }
 
-fn check_opaque<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, substs: SubstsRef<'tcx>, span: Span) {
+fn check_opaque<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    def_id: DefId,
+    substs: SubstsRef<'tcx>,
+    span: Span,
+    origin: &hir::ExistTyOrigin
+) {
     if let Err(partially_expanded_type) = tcx.try_expand_impl_trait_type(def_id, substs) {
-        let mut err = struct_span_err!(
-            tcx.sess, span, E0720,
-            "opaque type expands to a recursive type",
-        );
-        err.span_label(span, "expands to a recursive type");
-        if let ty::Opaque(..) = partially_expanded_type.sty {
-            err.note("type resolves to itself");
+        if let hir::ExistTyOrigin::AsyncFn = origin {
+            struct_span_err!(
+                tcx.sess, span, E0733,
+                "recursion in an `async fn` requires boxing",
+            )
+            .span_label(span, "an `async fn` cannot invoke itself directly")
+            .note("a recursive `async fn` must be rewritten to return a boxed future.")
+            .emit();
         } else {
-            err.note(&format!("expanded type is `{}`", partially_expanded_type));
+            let mut err = struct_span_err!(
+                tcx.sess, span, E0720,
+                "opaque type expands to a recursive type",
+            );
+            err.span_label(span, "expands to a recursive type");
+            if let ty::Opaque(..) = partially_expanded_type.sty {
+                err.note("type resolves to itself");
+            } else {
+                err.note(&format!("expanded type is `{}`", partially_expanded_type));
+            }
+            err.emit();
         }
-        err.emit();
     }
 }
 
@@ -1387,11 +1403,11 @@ pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, it: &'tcx hir::Item) {
         hir::ItemKind::Union(..) => {
             check_union(tcx, it.hir_id, it.span);
         }
-        hir::ItemKind::Existential(..) => {
+        hir::ItemKind::Existential(hir::ExistTy{origin, ..}) => {
             let def_id = tcx.hir().local_def_id(it.hir_id);
 
             let substs = InternalSubsts::identity_for_item(tcx, def_id);
-            check_opaque(tcx, def_id, substs, it.span);
+            check_opaque(tcx, def_id, substs, it.span, &origin);
         }
         hir::ItemKind::Ty(..) => {
             let def_id = tcx.hir().local_def_id(it.hir_id);
@@ -1818,7 +1834,9 @@ fn bad_variant_count<'tcx>(tcx: TyCtxt<'tcx>, adt: &'tcx ty::AdtDef, sp: Span, d
     );
     let mut err = struct_span_err!(tcx.sess, sp, E0731, "transparent enum {}", msg);
     err.span_label(sp, &msg);
-    if let &[ref start.., ref end] = &variant_spans[..] {
+    if let &[.., ref end] = &variant_spans[..] {
+        // FIXME: Ping cfg(bootstrap) -- Use `ref start @ ..` with new bootstrap compiler.
+        let start = &variant_spans[..variant_spans.len() - 1];
         for variant_span in start {
             err.span_label(*variant_span, "");
         }
index 19d5e8b3e84470eae62ca5a4bb878b4b6d99f237..90118a9f191d9d2cc1e5bb897591fefbcb4761f3 100644 (file)
@@ -1,7 +1,5 @@
 // ignore-tidy-filelength
 
-#![allow(non_snake_case)]
-
 register_long_diagnostics! {
 
 E0023: r##"
@@ -3497,8 +3495,8 @@ fn fly(&self) {} // And now that's ok!
 
 let r = &[1, 2];
 match r {
-    &[a, b, c, rest..] => { // error: pattern requires at least 3
-                            //        elements but array has 2
+    &[a, b, c, rest @ ..] => { // error: pattern requires at least 3
+                               //        elements but array has 2
         println!("a={}, b={}, c={} rest={:?}", a, b, c, rest);
     }
 }
@@ -3512,7 +3510,7 @@ fn fly(&self) {} // And now that's ok!
 
 let r = &[1, 2, 3, 4, 5];
 match r {
-    &[a, b, c, rest..] => { // ok!
+    &[a, b, c, rest @ ..] => { // ok!
         // prints `a=1, b=2, c=3 rest=[4, 5]`
         println!("a={}, b={}, c={} rest={:?}", a, b, c, rest);
     }
@@ -4765,7 +4763,53 @@ fn discriminant(v : &Enum) -> u8 {
 ```
 "##,
 
+E0733: r##"
+Recursion in an `async fn` requires boxing. For example, this will not compile:
+
+```edition2018,compile_fail,E0733
+#![feature(async_await)]
+async fn foo(n: usize) {
+    if n > 0 {
+        foo(n - 1).await;
+    }
+}
+```
+
+To achieve async recursion, the `async fn` needs to be desugared
+such that the `Future` is explicit in the return type:
+
+```edition2018,compile_fail,E0720
+# #![feature(async_await)]
+use std::future::Future;
+fn foo_desugered(n: usize) -> impl Future<Output = ()> {
+    async move {
+        if n > 0 {
+            foo_desugered(n - 1).await;
+        }
+    }
+}
+```
+
+Finally, the future is wrapped in a pinned box:
+
+```edition2018
+# #![feature(async_await)]
+use std::future::Future;
+use std::pin::Pin;
+fn foo_recursive(n: usize) -> Pin<Box<dyn Future<Output = ()>>> {
+    Box::pin(async move {
+        if n > 0 {
+            foo_recursive(n - 1).await;
+        }
+    })
 }
+```
+
+The `Box<...>` ensures that the result is of known size,
+and the pin is required to keep it in the same place in memory.
+"##,
+
+}  // (end of detailed error messages)
 
 register_diagnostics! {
 //  E0035, merged into E0087/E0089
index 934fc684eaeda1a24d74d3e90d2b2ad594787d05..a34b137aca97196c09dc1eda3410597451015082 100644 (file)
@@ -73,9 +73,6 @@
 
 #![recursion_limit="256"]
 
-#![deny(rust_2018_idioms)]
-#![deny(unused_lifetimes)]
-
 #[macro_use] extern crate log;
 #[macro_use] extern crate syntax;
 
index ce0d82ec7b10550309e0a2dfd22ab171cd0a36c4..334dc74c6c8f74a63ef34623dcb335bf5faed09e 100644 (file)
@@ -10,7 +10,7 @@ path = "lib.rs"
 
 [dependencies]
 pulldown-cmark = { version = "0.5.3", default-features = false }
-minifier = "0.0.30"
+minifier = "0.0.33"
 rayon = { version = "0.2.0", package = "rustc-rayon" }
 tempfile = "3"
 parking_lot = "0.7"
index 6270ed37859055c0e99067f2877ed35c8a13d14b..87c6a0b4235787db414670e6d984b3c6e3d000c3 100644 (file)
@@ -1322,13 +1322,13 @@ fn write_minify_replacer<W: Write>(
                  {
                     let tokens: Tokens<'_> = simple_minify(contents)
                         .into_iter()
-                        .filter(|f| {
+                        .filter(|(f, next)| {
                             // We keep backlines.
-                            minifier::js::clean_token_except(f, &|c: &Token<'_>| {
+                            minifier::js::clean_token_except(f, next, &|c: &Token<'_>| {
                                 c.get_char() != Some(ReservedChar::Backline)
                             })
                         })
-                        .map(|f| {
+                        .map(|(f, _)| {
                             minifier::js::replace_token_with(f, &|t: &Token<'_>| {
                                 match *t {
                                     Token::Keyword(Keyword::Null) => Some(Token::Other("N")),
@@ -1363,7 +1363,7 @@ fn write_minify_replacer<W: Write>(
                             // shouldn't be aggregated.
                             |tokens, pos| {
                                 pos < 2 ||
-                                !tokens[pos - 1].is_char(ReservedChar::OpenBracket) ||
+                                !tokens[pos - 1].eq_char(ReservedChar::OpenBracket) ||
                                 tokens[pos - 2].get_other() != Some("searchIndex")
                             }
                         )
index 3627ce6a5aa501865a4435448d17492c908d221e..a8d7ff4a2eb8bd8a7c7b3a66e26b49baa301ccf4 100644 (file)
@@ -1,6 +1,3 @@
-#![deny(rust_2018_idioms)]
-#![deny(unused_lifetimes)]
-
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/",
        html_playground_url = "https://play.rust-lang.org/")]
 
index b8eeb4d2b34af30c1bf25db7ca5661687612a8d9..2ad85c603d1e4930ada216b78c5e987e837abb79 100644 (file)
@@ -8,8 +8,6 @@
        html_playground_url = "https://play.rust-lang.org/",
        test(attr(allow(unused_variables), deny(warnings))))]
 
-#![deny(rust_2018_idioms)]
-
 #![feature(box_syntax)]
 #![feature(core_intrinsics)]
 #![feature(specialization)]
index 6da77ab57d11e8a741594cbad8215eef0db76251..2e0da0409eb09766c9594455fb7a51484ec8ef73 100644 (file)
@@ -75,11 +75,6 @@ panic_immediate_abort = ["core/panic_immediate_abort"]
 # requires rebuilding the standard library to use it.
 wasm_syscall = []
 
-# An off-by-default features to enable libstd to assume that wasm-bindgen is in
-# the environment for hooking up some thread-related information like the
-# current thread id and accessing/getting the current thread's TCB
-wasm-bindgen-threads = []
-
 # Enable std_detect default features for stdarch/crates/std_detect:
 # https://github.com/rust-lang/stdarch/blob/master/crates/std_detect/Cargo.toml
 std_detect_file_io = []
index 20397369387cb1ec040f19009565413c503afba9..8db7bc12cd3088e0266be92c537670c2762cd532 100644 (file)
@@ -1,5 +1,3 @@
-#![deny(warnings)]
-
 use std::env;
 
 fn main() {
index e951b575773b39cee8444b1227b176d22cd3136d..09b6b694f7bcc2c52a0c7f78ec118eea9c399adc 100644 (file)
@@ -1923,7 +1923,7 @@ impl<T: Read, U: Read> Read for Chain<T, U> {
     fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
         if !self.done_first {
             match self.first.read(buf)? {
-                0 if buf.len() != 0 => self.done_first = true,
+                0 if !buf.is_empty() => self.done_first = true,
                 n => return Ok(n),
             }
         }
@@ -1955,7 +1955,7 @@ impl<T: BufRead, U: BufRead> BufRead for Chain<T, U> {
     fn fill_buf(&mut self) -> Result<&[u8]> {
         if !self.done_first {
             match self.first.fill_buf()? {
-                buf if buf.len() == 0 => { self.done_first = true; }
+                buf if buf.is_empty() => { self.done_first = true; }
                 buf => return Ok(buf),
             }
         }
index 722c08a22a6b659263363ac7aba79a017a23c358..8fd76eabe394371a0b569c496cf4031a6b876086 100644 (file)
 #![warn(missing_docs)]
 #![warn(missing_debug_implementations)]
 #![deny(intra_doc_link_resolution_failure)] // rustdoc is run without -D warnings
-
-#![deny(rust_2018_idioms)]
 #![allow(explicit_outlives_requirements)]
+#![allow(unused_lifetimes)]
 
 // Tell the compiler to link to either panic_abort or panic_unwind
 #![needs_panic_runtime]
index 2c2dd3b77eae9791d31a7b3cb2c5ed6a9d95a3d9..f47dc92d2de93d5e9a06d151cc82812782185a5f 100644 (file)
@@ -29,7 +29,7 @@ unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
         if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() {
             libc::calloc(layout.size(), 1) as *mut u8
         } else {
-            let ptr = self.alloc(layout.clone());
+            let ptr = self.alloc(layout);
             if !ptr.is_null() {
                 ptr::write_bytes(ptr, 0, layout.size());
             }
index be38a1334ec32acfa25690b7f9c7f01e39f1e9c6..fc1e33137c8a9a0e3e9ee0bbc4565dfbdd8e30f0 100644 (file)
@@ -277,7 +277,7 @@ fn posix_spawn(&mut self, stdio: &ChildPipes, envp: Option<&CStringArray>)
         if self.get_gid().is_some() ||
             self.get_uid().is_some() ||
             self.env_saw_path() ||
-            self.get_closures().len() != 0 {
+            !self.get_closures().is_empty() {
             return Ok(None)
         }
 
index e22434439f5bba61cf96266afd29e8eafeb57633..f842869e08ee69e0c628a99dccceb7f662e5df38 100644 (file)
@@ -47,6 +47,8 @@
 pub mod thread;
 #[path = "../wasm/thread_local.rs"]
 pub mod thread_local;
+#[path = "../wasm/fast_thread_local.rs"]
+pub mod fast_thread_local;
 pub mod time;
 pub mod ext;
 
diff --git a/src/libstd/sys/wasm/fast_thread_local.rs b/src/libstd/sys/wasm/fast_thread_local.rs
new file mode 100644 (file)
index 0000000..ff21981
--- /dev/null
@@ -0,0 +1,9 @@
+#![unstable(feature = "thread_local_internals", issue = "0")]
+
+pub unsafe fn register_dtor(_t: *mut u8, _dtor: unsafe extern fn(*mut u8)) {
+    // FIXME: right now there is no concept of "thread exit", but this is likely
+    // going to show up at some point in the form of an exported symbol that the
+    // wasm runtime is oging to be expected to call. For now we basically just
+    // ignore the arguments, but if such a function starts to exist it will
+    // likely look like the OSX implementation in `unix/fast_thread_local.rs`
+}
index 7d157709eb6bf410ad1f2a3bdd0acd8df5e19820..56cbafcfdb8a2af1196c8d38ae24c61ce695d646 100644 (file)
@@ -37,6 +37,8 @@
 pub mod thread;
 pub mod time;
 pub mod stdio;
+pub mod thread_local;
+pub mod fast_thread_local;
 
 pub use crate::sys_common::os_str_bytes as os_str;
 
         pub mod mutex;
         #[path = "rwlock_atomics.rs"]
         pub mod rwlock;
-        #[path = "thread_local_atomics.rs"]
-        pub mod thread_local;
     } else {
         pub mod condvar;
         pub mod mutex;
         pub mod rwlock;
-        pub mod thread_local;
     }
 }
 
index 61b4003cd3d148e473bfb2c7c31e678bef77566f..d06965f3278498eda3a5924a0cb3e60251855a3e 100644 (file)
@@ -59,48 +59,40 @@ pub unsafe fn current() -> Option<Guard> { None }
     pub unsafe fn init() -> Option<Guard> { None }
 }
 
-cfg_if::cfg_if! {
-    if #[cfg(all(target_feature = "atomics", feature = "wasm-bindgen-threads"))] {
-        #[link(wasm_import_module = "__wbindgen_thread_xform__")]
-        extern {
-            fn __wbindgen_current_id() -> u32;
-            fn __wbindgen_tcb_get() -> u32;
-            fn __wbindgen_tcb_set(ptr: u32);
+// This is only used by atomics primitives when the `atomics` feature is
+// enabled. In that mode we currently just use our own thread-local to store our
+// current thread's ID, and then we lazily initialize it to something allocated
+// from a global counter.
+#[cfg(target_feature = "atomics")]
+pub fn my_id() -> u32 {
+    use crate::sync::atomic::{AtomicU32, Ordering::SeqCst};
+
+    static NEXT_ID: AtomicU32 = AtomicU32::new(0);
+
+    #[thread_local]
+    static mut MY_ID: u32 = 0;
+
+    unsafe {
+        // If our thread ID isn't set yet then we need to allocate one. Do so
+        // with with a simple "atomically add to a global counter" strategy.
+        // This strategy doesn't handled what happens when the counter
+        // overflows, however, so just abort everything once the counter
+        // overflows and eventually we could have some sort of recycling scheme
+        // (or maybe this is all totally irrelevant by that point!). In any case
+        // though we're using a CAS loop instead of a `fetch_add` to ensure that
+        // the global counter never overflows.
+        if MY_ID == 0 {
+            let mut cur = NEXT_ID.load(SeqCst);
+            MY_ID = loop {
+                let next = cur.checked_add(1).unwrap_or_else(|| {
+                    crate::arch::wasm32::unreachable()
+                });
+                match NEXT_ID.compare_exchange(cur, next, SeqCst, SeqCst) {
+                    Ok(_) => break next,
+                    Err(i) => cur = i,
+                }
+            };
         }
-        pub fn my_id() -> u32 {
-            unsafe { __wbindgen_current_id() }
-        }
-
-        // These are currently only ever used in `thread_local_atomics.rs`, if
-        // you'd like to use them be sure to update that and make sure everyone
-        // agrees what's what.
-        pub fn tcb_get() -> *mut u8 {
-            use crate::mem;
-            assert_eq!(mem::size_of::<*mut u8>(), mem::size_of::<u32>());
-            unsafe { __wbindgen_tcb_get() as *mut u8 }
-        }
-
-        pub fn tcb_set(ptr: *mut u8) {
-            unsafe { __wbindgen_tcb_set(ptr as u32); }
-        }
-
-        // FIXME: still need something for hooking exiting a thread to free
-        // data...
-
-    } else if #[cfg(target_feature = "atomics")] {
-        pub fn my_id() -> u32 {
-            panic!("thread ids not implemented on wasm with atomics yet")
-        }
-
-        pub fn tcb_get() -> *mut u8 {
-            panic!("thread local data not implemented on wasm with atomics yet")
-        }
-
-        pub fn tcb_set(_ptr: *mut u8) {
-            panic!("thread local data not implemented on wasm with atomics yet")
-        }
-    } else {
-        // stubbed out because no functions actually access these intrinsics
-        // unless atomics are enabled
+        MY_ID
     }
 }
index 29e9854bcfccb1f984981a39bcb55ff3efd6a35e..8a0ca6f3d25a8f47cf88ab90c19d9a04a2d42037 100644 (file)
@@ -1,40 +1,26 @@
-use crate::boxed::Box;
-use crate::ptr;
-
 pub type Key = usize;
 
-struct Allocated {
-    value: *mut u8,
-    dtor: Option<unsafe extern fn(*mut u8)>,
-}
-
 #[inline]
-pub unsafe fn create(dtor: Option<unsafe extern fn(*mut u8)>) -> Key {
-    Box::into_raw(Box::new(Allocated {
-        value: ptr::null_mut(),
-        dtor,
-    })) as usize
+pub unsafe fn create(_dtor: Option<unsafe extern fn(*mut u8)>) -> Key {
+    panic!("should not be used on the wasm target");
 }
 
 #[inline]
-pub unsafe fn set(key: Key, value: *mut u8) {
-    (*(key as *mut Allocated)).value = value;
+pub unsafe fn set(_key: Key, _value: *mut u8) {
+    panic!("should not be used on the wasm target");
 }
 
 #[inline]
-pub unsafe fn get(key: Key) -> *mut u8 {
-    (*(key as *mut Allocated)).value
+pub unsafe fn get(_key: Key) -> *mut u8 {
+    panic!("should not be used on the wasm target");
 }
 
 #[inline]
-pub unsafe fn destroy(key: Key) {
-    let key = Box::from_raw(key as *mut Allocated);
-    if let Some(f) = key.dtor {
-        f(key.value);
-    }
+pub unsafe fn destroy(_key: Key) {
+    panic!("should not be used on the wasm target");
 }
 
 #[inline]
 pub fn requires_synchronized_create() -> bool {
-    false
+    panic!("should not be used on the wasm target");
 }
diff --git a/src/libstd/sys/wasm/thread_local_atomics.rs b/src/libstd/sys/wasm/thread_local_atomics.rs
deleted file mode 100644 (file)
index 3dc0bb2..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-use crate::sys::thread;
-use crate::sync::atomic::{AtomicUsize, Ordering::SeqCst};
-
-const MAX_KEYS: usize = 128;
-static NEXT_KEY: AtomicUsize = AtomicUsize::new(0);
-
-struct ThreadControlBlock {
-    keys: [*mut u8; MAX_KEYS],
-}
-
-impl ThreadControlBlock {
-    fn new() -> ThreadControlBlock {
-        ThreadControlBlock {
-            keys: [core::ptr::null_mut(); MAX_KEYS],
-        }
-    }
-
-    fn get() -> *mut ThreadControlBlock {
-        let ptr = thread::tcb_get();
-        if !ptr.is_null() {
-            return ptr as *mut ThreadControlBlock
-        }
-        let tcb = Box::into_raw(Box::new(ThreadControlBlock::new()));
-        thread::tcb_set(tcb as *mut u8);
-        tcb
-    }
-}
-
-pub type Key = usize;
-
-pub unsafe fn create(dtor: Option<unsafe extern fn(*mut u8)>) -> Key {
-    drop(dtor); // FIXME: need to figure out how to hook thread exit to run this
-    let key = NEXT_KEY.fetch_add(1, SeqCst);
-    if key >= MAX_KEYS {
-        NEXT_KEY.store(MAX_KEYS, SeqCst);
-        panic!("cannot allocate space for more TLS keys");
-    }
-    // offset by 1 so we never hand out 0. This is currently required by
-    // `sys_common/thread_local.rs` where it can't cope with keys of value 0
-    // because it messes up the atomic management.
-    return key + 1
-}
-
-pub unsafe fn set(key: Key, value: *mut u8) {
-    (*ThreadControlBlock::get()).keys[key - 1] = value;
-}
-
-pub unsafe fn get(key: Key) -> *mut u8 {
-    (*ThreadControlBlock::get()).keys[key - 1]
-}
-
-pub unsafe fn destroy(_key: Key) {
-    // FIXME: should implement this somehow, this isn't typically called but it
-    // can be called if two threads race to initialize a TLS slot and one ends
-    // up not being needed.
-}
-
-#[inline]
-pub fn requires_synchronized_create() -> bool {
-    false
-}
index dc97f8c04a83912cb26561121d40adb5b925c501..98371b9ba3d7e5b52624e368a8d032b44bae20bb 100644 (file)
@@ -396,6 +396,7 @@ pub fn now() -> SystemTime {
     /// This function may fail because measurements taken earlier are not
     /// guaranteed to always be before later measurements (due to anomalies such
     /// as the system clock being adjusted either forwards or backwards).
+    /// [`Instant`] can be used to measure elapsed time without this risk of failure.
     ///
     /// If successful, [`Ok`]`(`[`Duration`]`)` is returned where the duration represents
     /// the amount of time elapsed from the specified measurement to this one.
@@ -406,6 +407,7 @@ pub fn now() -> SystemTime {
     /// [`Ok`]: ../../std/result/enum.Result.html#variant.Ok
     /// [`Duration`]: ../../std/time/struct.Duration.html
     /// [`Err`]: ../../std/result/enum.Result.html#variant.Err
+    /// [`Instant`]: ../../std/time/struct.Instant.html
     ///
     /// # Examples
     ///
@@ -414,7 +416,7 @@ pub fn now() -> SystemTime {
     ///
     /// let sys_time = SystemTime::now();
     /// let difference = sys_time.duration_since(sys_time)
-    ///                          .expect("SystemTime::duration_since failed");
+    ///                          .expect("Clock may have gone backwards");
     /// println!("{:?}", difference);
     /// ```
     #[stable(feature = "time2", since = "1.8.0")]
@@ -423,7 +425,8 @@ pub fn duration_since(&self, earlier: SystemTime)
         self.0.sub_time(&earlier.0).map_err(SystemTimeError)
     }
 
-    /// Returns the amount of time elapsed since this system time was created.
+    /// Returns the difference between the clock time when this
+    /// system time was created, and the current clock time.
     ///
     /// This function may fail as the underlying system clock is susceptible to
     /// drift and updates (e.g., the system clock could go backwards), so this
@@ -431,12 +434,15 @@ pub fn duration_since(&self, earlier: SystemTime)
     /// returned where the duration represents the amount of time elapsed from
     /// this time measurement to the current time.
     ///
+    /// To measure elapsed time reliably, use [`Instant`] instead.
+    ///
     /// Returns an [`Err`] if `self` is later than the current system time, and
     /// the error contains how far from the current system time `self` is.
     ///
     /// [`Ok`]: ../../std/result/enum.Result.html#variant.Ok
     /// [`Duration`]: ../../std/time/struct.Duration.html
     /// [`Err`]: ../../std/result/enum.Result.html#variant.Err
+    /// [`Instant`]: ../../std/time/struct.Instant.html
     ///
     /// # Examples
     ///
index dbfad3ef7f4def966752958c786a5d91eabd0177..58a1c4aee9ad90e53542d530cb3dd52f37f6c89e 100644 (file)
@@ -519,21 +519,28 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 }
 
 impl Pat {
+    /// Attempt reparsing the pattern as a type.
+    /// This is intended for use by diagnostics.
     pub(super) fn to_ty(&self) -> Option<P<Ty>> {
         let node = match &self.node {
+            // In a type expression `_` is an inference variable.
             PatKind::Wild => TyKind::Infer,
+            // An IDENT pattern with no binding mode would be valid as path to a type. E.g. `u32`.
             PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), ident, None) => {
                 TyKind::Path(None, Path::from_ident(*ident))
             }
             PatKind::Path(qself, path) => TyKind::Path(qself.clone(), path.clone()),
             PatKind::Mac(mac) => TyKind::Mac(mac.clone()),
+            // `&mut? P` can be reinterpreted as `&mut? T` where `T` is `P` reparsed as a type.
             PatKind::Ref(pat, mutbl) => pat
                 .to_ty()
                 .map(|ty| TyKind::Rptr(None, MutTy { ty, mutbl: *mutbl }))?,
-            PatKind::Slice(pats, None, _) if pats.len() == 1 => {
-                pats[0].to_ty().map(TyKind::Slice)?
-            }
-            PatKind::Tuple(pats, None) => {
+            // A slice/array pattern `[P]` can be reparsed as `[T]`, an unsized array,
+            // when `P` can be reparsed as a type `T`.
+            PatKind::Slice(pats) if pats.len() == 1 => pats[0].to_ty().map(TyKind::Slice)?,
+            // A tuple pattern `(P0, .., Pn)` can be reparsed as `(T0, .., Tn)`
+            // assuming `T0` to `Tn` are all syntactically valid as types.
+            PatKind::Tuple(pats) => {
                 let mut tys = Vec::with_capacity(pats.len());
                 // FIXME(#48994) - could just be collected into an Option<Vec>
                 for pat in pats {
@@ -559,19 +566,15 @@ pub fn walk<F>(&self, it: &mut F) -> bool
             return false;
         }
 
-        match self.node {
-            PatKind::Ident(_, _, Some(ref p)) => p.walk(it),
-            PatKind::Struct(_, ref fields, _) => fields.iter().all(|field| field.node.pat.walk(it)),
-            PatKind::TupleStruct(_, ref s, _) | PatKind::Tuple(ref s, _) => {
+        match &self.node {
+            PatKind::Ident(_, _, Some(p)) => p.walk(it),
+            PatKind::Struct(_, fields, _) => fields.iter().all(|field| field.node.pat.walk(it)),
+            PatKind::TupleStruct(_, s) | PatKind::Tuple(s) | PatKind::Slice(s) => {
                 s.iter().all(|p| p.walk(it))
             }
-            PatKind::Box(ref s) | PatKind::Ref(ref s, _) | PatKind::Paren(ref s) => s.walk(it),
-            PatKind::Slice(ref before, ref slice, ref after) => {
-                before.iter().all(|p| p.walk(it))
-                    && slice.iter().all(|p| p.walk(it))
-                    && after.iter().all(|p| p.walk(it))
-            }
+            PatKind::Box(s) | PatKind::Ref(s, _) | PatKind::Paren(s) => s.walk(it),
             PatKind::Wild
+            | PatKind::Rest
             | PatKind::Lit(_)
             | PatKind::Range(..)
             | PatKind::Ident(..)
@@ -579,6 +582,14 @@ pub fn walk<F>(&self, it: &mut F) -> bool
             | PatKind::Mac(_) => true,
         }
     }
+
+    /// Is this a `..` pattern?
+    pub fn is_rest(&self) -> bool {
+        match self.node {
+            PatKind::Rest => true,
+            _ => false,
+        }
+    }
 }
 
 /// A single field in a struct pattern
@@ -630,9 +641,7 @@ pub enum PatKind {
     Struct(Path, Vec<Spanned<FieldPat>>, /* recovered */ bool),
 
     /// A tuple struct/variant pattern (`Variant(x, y, .., z)`).
-    /// If the `..` pattern fragment is present, then `Option<usize>` denotes its position.
-    /// `0 <= position <= subpats.len()`.
-    TupleStruct(Path, Vec<P<Pat>>, Option<usize>),
+    TupleStruct(Path, Vec<P<Pat>>),
 
     /// A possibly qualified path pattern.
     /// Unqualified path patterns `A::B::C` can legally refer to variants, structs, constants
@@ -641,9 +650,7 @@ pub enum PatKind {
     Path(Option<QSelf>, Path),
 
     /// A tuple pattern (`(a, b)`).
-    /// If the `..` pattern fragment is present, then `Option<usize>` denotes its position.
-    /// `0 <= position <= subpats.len()`.
-    Tuple(Vec<P<Pat>>, Option<usize>),
+    Tuple(Vec<P<Pat>>),
 
     /// A `box` pattern.
     Box(P<Pat>),
@@ -657,9 +664,22 @@ pub enum PatKind {
     /// A range pattern (e.g., `1...2`, `1..=2` or `1..2`).
     Range(P<Expr>, P<Expr>, Spanned<RangeEnd>),
 
-    /// `[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>>),
+    /// A slice pattern `[a, b, c]`.
+    Slice(Vec<P<Pat>>),
+
+    /// A rest pattern `..`.
+    ///
+    /// Syntactically it is valid anywhere.
+    ///
+    /// Semantically however, it only has meaning immediately inside:
+    /// - a slice pattern: `[a, .., b]`,
+    /// - a binding pattern immediately inside a slice pattern: `[a, r @ ..]`,
+    /// - a tuple pattern: `(a, .., b)`,
+    /// - a tuple struct/variant pattern: `$path(a, .., b)`.
+    ///
+    /// In all of these cases, an additional restriction applies,
+    /// only one rest pattern may occur in the pattern sequences.
+    Rest,
 
     /// Parentheses in patterns used for grouping (i.e., `(PAT)`).
     Paren(P<Pat>),
@@ -1776,6 +1796,7 @@ pub struct Arg {
     pub ty: P<Ty>,
     pub pat: P<Pat>,
     pub id: NodeId,
+    pub span: Span,
 }
 
 /// Alternative representation for `Arg`s describing `self` parameter of methods.
@@ -1834,6 +1855,7 @@ pub fn from_self(attrs: ThinVec<Attribute>, eself: ExplicitSelf, eself_ident: Id
                 node: PatKind::Ident(BindingMode::ByValue(mutbl), eself_ident, None),
                 span,
             }),
+            span,
             ty,
             id: DUMMY_NODE_ID,
         };
index ee640a1603a6ca688c54a648102efa6b7bee3d7a..e5e55a6444a2eb8012d5231eec876a333bc2f1f1 100644 (file)
@@ -123,7 +123,6 @@ pub fn expand_register_diagnostic<'cx>(ecx: &'cx mut ExtCtxt<'_>,
     MacEager::items(smallvec![])
 }
 
-#[allow(deprecated)]
 pub fn expand_build_diagnostic_array<'cx>(ecx: &'cx mut ExtCtxt<'_>,
                                           span: Span,
                                           token_tree: &[TokenTree])
@@ -149,7 +148,7 @@ pub fn expand_build_diagnostic_array<'cx>(ecx: &'cx mut ExtCtxt<'_>,
                 ecx.span_bug(span, &format!(
                     "error writing metadata for triple `{}` and crate `{}`, error: {}, \
                      cause: {:?}",
-                    target_triple, crate_name, e.description(), e.cause()
+                    target_triple, crate_name, e.description(), e.source()
                 ));
             }
         });
index 029ce73498c68881d71a87aa8f59e8e3b14156eb..1ba29011f75a40cf867b8039292a2e27d9b2e2de 100644 (file)
@@ -1,5 +1,3 @@
-#![allow(non_snake_case)]
-
 // Error messages for EXXXX errors.
 // Each message should start and end with a new line, and be wrapped to 80 characters.
 // In vim you can `:set tw=80` and use `gq` to wrap paragraphs. Use `:set tw=0` to disable.
index 0ab14bee160da7aeacceea42b73eca6146152788..bb7834a133f039a564681a514b1ab064d758071a 100644 (file)
@@ -1,6 +1,6 @@
 use crate::ast::{self, Attribute, Name, PatKind};
 use crate::attr::{HasAttrs, Stability, Deprecation};
-use crate::source_map::{SourceMap, Spanned, FileName, respan};
+use crate::source_map::{SourceMap, Spanned, respan};
 use crate::edition::Edition;
 use crate::ext::expand::{self, AstFragment, Invocation};
 use crate::ext::hygiene::{ExpnId, SyntaxContext, Transparency};
@@ -14,7 +14,7 @@
 
 use errors::{DiagnosticBuilder, DiagnosticId};
 use smallvec::{smallvec, SmallVec};
-use syntax_pos::{Span, MultiSpan, DUMMY_SP};
+use syntax_pos::{FileName, Span, MultiSpan, DUMMY_SP};
 use syntax_pos::hygiene::{ExpnInfo, ExpnKind};
 
 use rustc_data_structures::fx::FxHashMap;
index baf1031de1e7c40ddbe0f5f84be5bfa792f25ed6..b30fefe5b9676382d6a25f91ab7babdf2d5f61bf 100644 (file)
@@ -840,14 +840,14 @@ fn pat_path(&self, span: Span, path: ast::Path) -> P<ast::Pat> {
     }
     fn pat_tuple_struct(&self, span: Span, path: ast::Path,
                         subpats: Vec<P<ast::Pat>>) -> P<ast::Pat> {
-        self.pat(span, PatKind::TupleStruct(path, subpats, None))
+        self.pat(span, PatKind::TupleStruct(path, subpats))
     }
     fn pat_struct(&self, span: Span, path: ast::Path,
                   field_pats: Vec<Spanned<ast::FieldPat>>) -> P<ast::Pat> {
         self.pat(span, PatKind::Struct(path, field_pats, false))
     }
     fn pat_tuple(&self, span: Span, pats: Vec<P<ast::Pat>>) -> P<ast::Pat> {
-        self.pat(span, PatKind::Tuple(pats, None))
+        self.pat(span, PatKind::Tuple(pats))
     }
 
     fn pat_some(&self, span: Span, pat: P<ast::Pat>) -> P<ast::Pat> {
@@ -966,6 +966,7 @@ fn arg(&self, span: Span, ident: ast::Ident, ty: P<ast::Ty>) -> ast::Arg {
             attrs: ThinVec::default(),
             id: ast::DUMMY_NODE_ID,
             pat: arg_pat,
+            span,
             ty,
         }
     }
diff --git a/src/libsyntax/ext/derive.rs b/src/libsyntax/ext/derive.rs
deleted file mode 100644 (file)
index ff9ad46..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-use crate::attr::HasAttrs;
-use crate::ast;
-use crate::source_map::{ExpnInfo, ExpnKind};
-use crate::ext::base::{ExtCtxt, MacroKind};
-use crate::ext::build::AstBuilder;
-use crate::parse::parser::PathStyle;
-use crate::symbol::{Symbol, sym};
-use crate::errors::Applicability;
-
-use syntax_pos::Span;
-use rustc_data_structures::fx::FxHashSet;
-
-pub fn collect_derives(cx: &mut ExtCtxt<'_>, attrs: &mut Vec<ast::Attribute>) -> Vec<ast::Path> {
-    let mut result = Vec::new();
-    attrs.retain(|attr| {
-        if attr.path != sym::derive {
-            return true;
-        }
-        if !attr.is_meta_item_list() {
-            cx.struct_span_err(attr.span, "malformed `derive` attribute input")
-                .span_suggestion(
-                    attr.span,
-                    "missing traits to be derived",
-                    "#[derive(Trait1, Trait2, ...)]".to_owned(),
-                    Applicability::HasPlaceholders,
-                ).emit();
-            return false;
-        }
-
-        match attr.parse_list(cx.parse_sess,
-                              |parser| parser.parse_path_allowing_meta(PathStyle::Mod)) {
-            Ok(traits) => {
-                result.extend(traits);
-                true
-            }
-            Err(mut e) => {
-                e.emit();
-                false
-            }
-        }
-    });
-    result
-}
-
-pub fn add_derived_markers<T>(cx: &mut ExtCtxt<'_>, span: Span, traits: &[ast::Path], item: &mut T)
-    where T: HasAttrs,
-{
-    let (mut names, mut pretty_name) = (FxHashSet::default(), String::new());
-    for (i, path) in traits.iter().enumerate() {
-        if i > 0 {
-            pretty_name.push_str(", ");
-        }
-        pretty_name.push_str(&path.to_string());
-        names.insert(unwrap_or!(path.segments.get(0), continue).ident.name);
-    }
-
-    let span = span.fresh_expansion(cx.current_expansion.id, ExpnInfo::allow_unstable(
-        ExpnKind::Macro(MacroKind::Derive, Symbol::intern(&pretty_name)), span,
-        cx.parse_sess.edition, cx.allow_derive_markers.clone(),
-    ));
-
-    item.visit_attrs(|attrs| {
-        if names.contains(&sym::Eq) && names.contains(&sym::PartialEq) {
-            let meta = cx.meta_word(span, sym::structural_match);
-            attrs.push(cx.attribute(span, meta));
-        }
-        if names.contains(&sym::Copy) {
-            let meta = cx.meta_word(span, sym::rustc_copy_clone_marker);
-            attrs.push(cx.attribute(span, meta));
-        }
-    });
-}
index 640daaccc3a2c8b911c0534cb5b53e07871bd682..cd602d08c5baaf0e886cc9be4422800173a4eb06 100644 (file)
@@ -4,7 +4,7 @@
 use crate::source_map::{dummy_spanned, respan};
 use crate::config::StripUnconfigured;
 use crate::ext::base::*;
-use crate::ext::derive::{add_derived_markers, collect_derives};
+use crate::ext::proc_macro::{add_derived_markers, collect_derives};
 use crate::ext::hygiene::{ExpnId, SyntaxContext, ExpnInfo, ExpnKind};
 use crate::ext::placeholders::{placeholder, PlaceholderExpander};
 use crate::feature_gate::{self, Features, GateIssue, is_builtin_attr, emit_feature_err};
diff --git a/src/libsyntax/ext/proc_macro.rs b/src/libsyntax/ext/proc_macro.rs
new file mode 100644 (file)
index 0000000..425b981
--- /dev/null
@@ -0,0 +1,249 @@
+use crate::ast::{self, ItemKind, Attribute, Mac};
+use crate::attr::{mark_used, mark_known, HasAttrs};
+use crate::errors::{Applicability, FatalError};
+use crate::ext::base::{self, *};
+use crate::ext::build::AstBuilder;
+use crate::ext::proc_macro_server;
+use crate::parse::{self, token};
+use crate::parse::parser::PathStyle;
+use crate::symbol::{sym, Symbol};
+use crate::tokenstream::{self, TokenStream};
+use crate::visit::Visitor;
+
+use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::sync::Lrc;
+use syntax_pos::hygiene::{ExpnInfo, ExpnKind};
+use syntax_pos::{Span, DUMMY_SP};
+
+const EXEC_STRATEGY: proc_macro::bridge::server::SameThread =
+    proc_macro::bridge::server::SameThread;
+
+pub struct BangProcMacro {
+    pub client: proc_macro::bridge::client::Client<
+        fn(proc_macro::TokenStream) -> proc_macro::TokenStream,
+    >,
+}
+
+impl base::ProcMacro for BangProcMacro {
+    fn expand<'cx>(&self,
+                   ecx: &'cx mut ExtCtxt<'_>,
+                   span: Span,
+                   input: TokenStream)
+                   -> TokenStream {
+        let server = proc_macro_server::Rustc::new(ecx);
+        match self.client.run(&EXEC_STRATEGY, server, input) {
+            Ok(stream) => stream,
+            Err(e) => {
+                let msg = "proc macro panicked";
+                let mut err = ecx.struct_span_fatal(span, msg);
+                if let Some(s) = e.as_str() {
+                    err.help(&format!("message: {}", s));
+                }
+
+                err.emit();
+                FatalError.raise();
+            }
+        }
+    }
+}
+
+pub struct AttrProcMacro {
+    pub client: proc_macro::bridge::client::Client<
+        fn(proc_macro::TokenStream, proc_macro::TokenStream) -> proc_macro::TokenStream,
+    >,
+}
+
+impl base::AttrProcMacro for AttrProcMacro {
+    fn expand<'cx>(&self,
+                   ecx: &'cx mut ExtCtxt<'_>,
+                   span: Span,
+                   annotation: TokenStream,
+                   annotated: TokenStream)
+                   -> TokenStream {
+        let server = proc_macro_server::Rustc::new(ecx);
+        match self.client.run(&EXEC_STRATEGY, server, annotation, annotated) {
+            Ok(stream) => stream,
+            Err(e) => {
+                let msg = "custom attribute panicked";
+                let mut err = ecx.struct_span_fatal(span, msg);
+                if let Some(s) = e.as_str() {
+                    err.help(&format!("message: {}", s));
+                }
+
+                err.emit();
+                FatalError.raise();
+            }
+        }
+    }
+}
+
+pub struct ProcMacroDerive {
+    pub client: proc_macro::bridge::client::Client<
+        fn(proc_macro::TokenStream) -> proc_macro::TokenStream,
+    >,
+    pub attrs: Vec<ast::Name>,
+}
+
+impl MultiItemModifier for ProcMacroDerive {
+    fn expand(&self,
+              ecx: &mut ExtCtxt<'_>,
+              span: Span,
+              _meta_item: &ast::MetaItem,
+              item: Annotatable)
+              -> Vec<Annotatable> {
+        let item = match item {
+            Annotatable::Item(item) => item,
+            Annotatable::ImplItem(_) |
+            Annotatable::TraitItem(_) |
+            Annotatable::ForeignItem(_) |
+            Annotatable::Stmt(_) |
+            Annotatable::Expr(_) => {
+                ecx.span_err(span, "proc-macro derives may only be \
+                                    applied to a struct, enum, or union");
+                return Vec::new()
+            }
+        };
+        match item.node {
+            ItemKind::Struct(..) |
+            ItemKind::Enum(..) |
+            ItemKind::Union(..) => {},
+            _ => {
+                ecx.span_err(span, "proc-macro derives may only be \
+                                    applied to a struct, enum, or union");
+                return Vec::new()
+            }
+        }
+
+        // Mark attributes as known, and used.
+        MarkAttrs(&self.attrs).visit_item(&item);
+
+        let token = token::Interpolated(Lrc::new(token::NtItem(item)));
+        let input = tokenstream::TokenTree::token(token, DUMMY_SP).into();
+
+        let server = proc_macro_server::Rustc::new(ecx);
+        let stream = match self.client.run(&EXEC_STRATEGY, server, input) {
+            Ok(stream) => stream,
+            Err(e) => {
+                let msg = "proc-macro derive panicked";
+                let mut err = ecx.struct_span_fatal(span, msg);
+                if let Some(s) = e.as_str() {
+                    err.help(&format!("message: {}", s));
+                }
+
+                err.emit();
+                FatalError.raise();
+            }
+        };
+
+        let error_count_before = ecx.parse_sess.span_diagnostic.err_count();
+        let msg = "proc-macro derive produced unparseable tokens";
+
+        let mut parser = parse::stream_to_parser(ecx.parse_sess, stream, Some("proc-macro derive"));
+        let mut items = vec![];
+
+        loop {
+            match parser.parse_item() {
+                Ok(None) => break,
+                Ok(Some(item)) => {
+                    items.push(Annotatable::Item(item))
+                }
+                Err(mut err) => {
+                    // FIXME: handle this better
+                    err.cancel();
+                    ecx.struct_span_fatal(span, msg).emit();
+                    FatalError.raise();
+                }
+            }
+        }
+
+
+        // fail if there have been errors emitted
+        if ecx.parse_sess.span_diagnostic.err_count() > error_count_before {
+            ecx.struct_span_fatal(span, msg).emit();
+            FatalError.raise();
+        }
+
+        items
+    }
+}
+
+struct MarkAttrs<'a>(&'a [ast::Name]);
+
+impl<'a> Visitor<'a> for MarkAttrs<'a> {
+    fn visit_attribute(&mut self, attr: &Attribute) {
+        if let Some(ident) = attr.ident() {
+            if self.0.contains(&ident.name) {
+                mark_used(attr);
+                mark_known(attr);
+            }
+        }
+    }
+
+    fn visit_mac(&mut self, _mac: &Mac) {}
+}
+
+pub fn is_proc_macro_attr(attr: &Attribute) -> bool {
+    [sym::proc_macro, sym::proc_macro_attribute, sym::proc_macro_derive]
+        .iter().any(|kind| attr.check_name(*kind))
+}
+
+crate fn collect_derives(cx: &mut ExtCtxt<'_>, attrs: &mut Vec<ast::Attribute>) -> Vec<ast::Path> {
+    let mut result = Vec::new();
+    attrs.retain(|attr| {
+        if attr.path != sym::derive {
+            return true;
+        }
+        if !attr.is_meta_item_list() {
+            cx.struct_span_err(attr.span, "malformed `derive` attribute input")
+                .span_suggestion(
+                    attr.span,
+                    "missing traits to be derived",
+                    "#[derive(Trait1, Trait2, ...)]".to_owned(),
+                    Applicability::HasPlaceholders,
+                ).emit();
+            return false;
+        }
+
+        match attr.parse_list(cx.parse_sess,
+                              |parser| parser.parse_path_allowing_meta(PathStyle::Mod)) {
+            Ok(traits) => {
+                result.extend(traits);
+                true
+            }
+            Err(mut e) => {
+                e.emit();
+                false
+            }
+        }
+    });
+    result
+}
+
+crate fn add_derived_markers<T: HasAttrs>(
+    cx: &mut ExtCtxt<'_>, span: Span, traits: &[ast::Path], item: &mut T
+) {
+    let (mut names, mut pretty_name) = (FxHashSet::default(), String::new());
+    for (i, path) in traits.iter().enumerate() {
+        if i > 0 {
+            pretty_name.push_str(", ");
+        }
+        pretty_name.push_str(&path.to_string());
+        names.insert(unwrap_or!(path.segments.get(0), continue).ident.name);
+    }
+
+    let span = span.fresh_expansion(cx.current_expansion.id, ExpnInfo::allow_unstable(
+        ExpnKind::Macro(MacroKind::Derive, Symbol::intern(&pretty_name)), span,
+        cx.parse_sess.edition, cx.allow_derive_markers.clone(),
+    ));
+
+    item.visit_attrs(|attrs| {
+        if names.contains(&sym::Eq) && names.contains(&sym::PartialEq) {
+            let meta = cx.meta_word(span, sym::structural_match);
+            attrs.push(cx.attribute(span, meta));
+        }
+        if names.contains(&sym::Copy) {
+            let meta = cx.meta_word(span, sym::rustc_copy_clone_marker);
+            attrs.push(cx.attribute(span, meta));
+        }
+    });
+}
diff --git a/src/libsyntax/ext/proc_macro_server.rs b/src/libsyntax/ext/proc_macro_server.rs
new file mode 100644 (file)
index 0000000..8d0023c
--- /dev/null
@@ -0,0 +1,715 @@
+use crate::ast;
+use crate::ext::base::ExtCtxt;
+use crate::parse::{self, token, ParseSess};
+use crate::parse::lexer::comments;
+use crate::tokenstream::{self, DelimSpan, IsJoint::*, TokenStream, TreeAndJoint};
+
+use errors::{Diagnostic, DiagnosticBuilder};
+use rustc_data_structures::sync::Lrc;
+use syntax_pos::{BytePos, FileName, MultiSpan, Pos, SourceFile, Span};
+use syntax_pos::hygiene::{SyntaxContext, Transparency};
+use syntax_pos::symbol::{kw, sym, Symbol};
+
+use proc_macro::{Delimiter, Level, LineColumn, Spacing};
+use proc_macro::bridge::{server, TokenTree};
+use std::{ascii, panic};
+use std::ops::Bound;
+
+trait FromInternal<T> {
+    fn from_internal(x: T) -> Self;
+}
+
+trait ToInternal<T> {
+    fn to_internal(self) -> T;
+}
+
+impl FromInternal<token::DelimToken> for Delimiter {
+    fn from_internal(delim: token::DelimToken) -> Delimiter {
+        match delim {
+            token::Paren => Delimiter::Parenthesis,
+            token::Brace => Delimiter::Brace,
+            token::Bracket => Delimiter::Bracket,
+            token::NoDelim => Delimiter::None,
+        }
+    }
+}
+
+impl ToInternal<token::DelimToken> for Delimiter {
+    fn to_internal(self) -> token::DelimToken {
+        match self {
+            Delimiter::Parenthesis => token::Paren,
+            Delimiter::Brace => token::Brace,
+            Delimiter::Bracket => token::Bracket,
+            Delimiter::None => token::NoDelim,
+        }
+    }
+}
+
+impl FromInternal<(TreeAndJoint, &'_ ParseSess, &'_ mut Vec<Self>)>
+    for TokenTree<Group, Punct, Ident, Literal>
+{
+    fn from_internal(((tree, is_joint), sess, stack): (TreeAndJoint, &ParseSess, &mut Vec<Self>))
+                    -> Self {
+        use crate::parse::token::*;
+
+        let joint = is_joint == Joint;
+        let Token { kind, span } = match tree {
+            tokenstream::TokenTree::Delimited(span, delim, tts) => {
+                let delimiter = Delimiter::from_internal(delim);
+                return TokenTree::Group(Group {
+                    delimiter,
+                    stream: tts.into(),
+                    span,
+                });
+            }
+            tokenstream::TokenTree::Token(token) => token,
+        };
+
+        macro_rules! tt {
+            ($ty:ident { $($field:ident $(: $value:expr)*),+ $(,)? }) => (
+                TokenTree::$ty(self::$ty {
+                    $($field $(: $value)*,)+
+                    span,
+                })
+            );
+            ($ty:ident::$method:ident($($value:expr),*)) => (
+                TokenTree::$ty(self::$ty::$method($($value,)* span))
+            );
+        }
+        macro_rules! op {
+            ($a:expr) => {
+                tt!(Punct::new($a, joint))
+            };
+            ($a:expr, $b:expr) => {{
+                stack.push(tt!(Punct::new($b, joint)));
+                tt!(Punct::new($a, true))
+            }};
+            ($a:expr, $b:expr, $c:expr) => {{
+                stack.push(tt!(Punct::new($c, joint)));
+                stack.push(tt!(Punct::new($b, true)));
+                tt!(Punct::new($a, true))
+            }};
+        }
+
+        match kind {
+            Eq => op!('='),
+            Lt => op!('<'),
+            Le => op!('<', '='),
+            EqEq => op!('=', '='),
+            Ne => op!('!', '='),
+            Ge => op!('>', '='),
+            Gt => op!('>'),
+            AndAnd => op!('&', '&'),
+            OrOr => op!('|', '|'),
+            Not => op!('!'),
+            Tilde => op!('~'),
+            BinOp(Plus) => op!('+'),
+            BinOp(Minus) => op!('-'),
+            BinOp(Star) => op!('*'),
+            BinOp(Slash) => op!('/'),
+            BinOp(Percent) => op!('%'),
+            BinOp(Caret) => op!('^'),
+            BinOp(And) => op!('&'),
+            BinOp(Or) => op!('|'),
+            BinOp(Shl) => op!('<', '<'),
+            BinOp(Shr) => op!('>', '>'),
+            BinOpEq(Plus) => op!('+', '='),
+            BinOpEq(Minus) => op!('-', '='),
+            BinOpEq(Star) => op!('*', '='),
+            BinOpEq(Slash) => op!('/', '='),
+            BinOpEq(Percent) => op!('%', '='),
+            BinOpEq(Caret) => op!('^', '='),
+            BinOpEq(And) => op!('&', '='),
+            BinOpEq(Or) => op!('|', '='),
+            BinOpEq(Shl) => op!('<', '<', '='),
+            BinOpEq(Shr) => op!('>', '>', '='),
+            At => op!('@'),
+            Dot => op!('.'),
+            DotDot => op!('.', '.'),
+            DotDotDot => op!('.', '.', '.'),
+            DotDotEq => op!('.', '.', '='),
+            Comma => op!(','),
+            Semi => op!(';'),
+            Colon => op!(':'),
+            ModSep => op!(':', ':'),
+            RArrow => op!('-', '>'),
+            LArrow => op!('<', '-'),
+            FatArrow => op!('=', '>'),
+            Pound => op!('#'),
+            Dollar => op!('$'),
+            Question => op!('?'),
+            SingleQuote => op!('\''),
+
+            Ident(name, false) if name == kw::DollarCrate => tt!(Ident::dollar_crate()),
+            Ident(name, is_raw) => tt!(Ident::new(name, is_raw)),
+            Lifetime(name) => {
+                let ident = ast::Ident::new(name, span).without_first_quote();
+                stack.push(tt!(Ident::new(ident.name, false)));
+                tt!(Punct::new('\'', true))
+            }
+            Literal(lit) => tt!(Literal { lit }),
+            DocComment(c) => {
+                let style = comments::doc_comment_style(&c.as_str());
+                let stripped = comments::strip_doc_comment_decoration(&c.as_str());
+                let mut escaped = String::new();
+                for ch in stripped.chars() {
+                    escaped.extend(ch.escape_debug());
+                }
+                let stream = vec![
+                    Ident(sym::doc, false),
+                    Eq,
+                    TokenKind::lit(token::Str, Symbol::intern(&escaped), None),
+                ]
+                .into_iter()
+                .map(|kind| tokenstream::TokenTree::token(kind, span))
+                .collect();
+                stack.push(TokenTree::Group(Group {
+                    delimiter: Delimiter::Bracket,
+                    stream,
+                    span: DelimSpan::from_single(span),
+                }));
+                if style == ast::AttrStyle::Inner {
+                    stack.push(tt!(Punct::new('!', false)));
+                }
+                tt!(Punct::new('#', false))
+            }
+
+            Interpolated(nt) => {
+                let stream = nt.to_tokenstream(sess, span);
+                TokenTree::Group(Group {
+                    delimiter: Delimiter::None,
+                    stream,
+                    span: DelimSpan::from_single(span),
+                })
+            }
+
+            OpenDelim(..) | CloseDelim(..) => unreachable!(),
+            Whitespace | Comment | Shebang(..) | Eof => unreachable!(),
+        }
+    }
+}
+
+impl ToInternal<TokenStream> for TokenTree<Group, Punct, Ident, Literal> {
+    fn to_internal(self) -> TokenStream {
+        use crate::parse::token::*;
+
+        let (ch, joint, span) = match self {
+            TokenTree::Punct(Punct { ch, joint, span }) => (ch, joint, span),
+            TokenTree::Group(Group {
+                delimiter,
+                stream,
+                span,
+            }) => {
+                return tokenstream::TokenTree::Delimited(
+                    span,
+                    delimiter.to_internal(),
+                    stream.into(),
+                )
+                .into();
+            }
+            TokenTree::Ident(self::Ident { sym, is_raw, span }) => {
+                return tokenstream::TokenTree::token(Ident(sym, is_raw), span).into();
+            }
+            TokenTree::Literal(self::Literal {
+                lit: token::Lit { kind: token::Integer, symbol, suffix },
+                span,
+            }) if symbol.as_str().starts_with("-") => {
+                let minus = BinOp(BinOpToken::Minus);
+                let symbol = Symbol::intern(&symbol.as_str()[1..]);
+                let integer = TokenKind::lit(token::Integer, symbol, suffix);
+                let a = tokenstream::TokenTree::token(minus, span);
+                let b = tokenstream::TokenTree::token(integer, span);
+                return vec![a, b].into_iter().collect();
+            }
+            TokenTree::Literal(self::Literal {
+                lit: token::Lit { kind: token::Float, symbol, suffix },
+                span,
+            }) if symbol.as_str().starts_with("-") => {
+                let minus = BinOp(BinOpToken::Minus);
+                let symbol = Symbol::intern(&symbol.as_str()[1..]);
+                let float = TokenKind::lit(token::Float, symbol, suffix);
+                let a = tokenstream::TokenTree::token(minus, span);
+                let b = tokenstream::TokenTree::token(float, span);
+                return vec![a, b].into_iter().collect();
+            }
+            TokenTree::Literal(self::Literal { lit, span }) => {
+                return tokenstream::TokenTree::token(Literal(lit), span).into()
+            }
+        };
+
+        let kind = match ch {
+            '=' => Eq,
+            '<' => Lt,
+            '>' => Gt,
+            '!' => Not,
+            '~' => Tilde,
+            '+' => BinOp(Plus),
+            '-' => BinOp(Minus),
+            '*' => BinOp(Star),
+            '/' => BinOp(Slash),
+            '%' => BinOp(Percent),
+            '^' => BinOp(Caret),
+            '&' => BinOp(And),
+            '|' => BinOp(Or),
+            '@' => At,
+            '.' => Dot,
+            ',' => Comma,
+            ';' => Semi,
+            ':' => Colon,
+            '#' => Pound,
+            '$' => Dollar,
+            '?' => Question,
+            '\'' => SingleQuote,
+            _ => unreachable!(),
+        };
+
+        let tree = tokenstream::TokenTree::token(kind, span);
+        TokenStream::new(vec![(tree, if joint { Joint } else { NonJoint })])
+    }
+}
+
+impl ToInternal<errors::Level> for Level {
+    fn to_internal(self) -> errors::Level {
+        match self {
+            Level::Error => errors::Level::Error,
+            Level::Warning => errors::Level::Warning,
+            Level::Note => errors::Level::Note,
+            Level::Help => errors::Level::Help,
+            _ => unreachable!("unknown proc_macro::Level variant: {:?}", self),
+        }
+    }
+}
+
+#[derive(Clone)]
+pub struct TokenStreamIter {
+    cursor: tokenstream::Cursor,
+    stack: Vec<TokenTree<Group, Punct, Ident, Literal>>,
+}
+
+#[derive(Clone)]
+pub struct Group {
+    delimiter: Delimiter,
+    stream: TokenStream,
+    span: DelimSpan,
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, Hash)]
+pub struct Punct {
+    ch: char,
+    // NB. not using `Spacing` here because it doesn't implement `Hash`.
+    joint: bool,
+    span: Span,
+}
+
+impl Punct {
+    fn new(ch: char, joint: bool, span: Span) -> Punct {
+        const LEGAL_CHARS: &[char] = &['=', '<', '>', '!', '~', '+', '-', '*', '/', '%', '^',
+                                       '&', '|', '@', '.', ',', ';', ':', '#', '$', '?', '\''];
+        if !LEGAL_CHARS.contains(&ch) {
+            panic!("unsupported character `{:?}`", ch)
+        }
+        Punct { ch, joint, span }
+    }
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, Hash)]
+pub struct Ident {
+    sym: Symbol,
+    is_raw: bool,
+    span: Span,
+}
+
+impl Ident {
+    fn is_valid(string: &str) -> bool {
+        let mut chars = string.chars();
+        if let Some(start) = chars.next() {
+            (start == '_' || start.is_xid_start())
+                && chars.all(|cont| cont == '_' || cont.is_xid_continue())
+        } else {
+            false
+        }
+    }
+    fn new(sym: Symbol, is_raw: bool, span: Span) -> Ident {
+        let string = sym.as_str();
+        if !Self::is_valid(&string) {
+            panic!("`{:?}` is not a valid identifier", string)
+        }
+        // Get rid of gensyms to conservatively check rawness on the string contents only.
+        if is_raw && !sym.as_interned_str().as_symbol().can_be_raw() {
+            panic!("`{}` cannot be a raw identifier", string);
+        }
+        Ident { sym, is_raw, span }
+    }
+    fn dollar_crate(span: Span) -> Ident {
+        // `$crate` is accepted as an ident only if it comes from the compiler.
+        Ident { sym: kw::DollarCrate, is_raw: false, span }
+    }
+}
+
+// FIXME(eddyb) `Literal` should not expose internal `Debug` impls.
+#[derive(Clone, Debug)]
+pub struct Literal {
+    lit: token::Lit,
+    span: Span,
+}
+
+pub(crate) struct Rustc<'a> {
+    sess: &'a ParseSess,
+    def_site: Span,
+    call_site: Span,
+}
+
+impl<'a> Rustc<'a> {
+    pub fn new(cx: &'a ExtCtxt<'_>) -> Self {
+        // No way to determine def location for a proc macro right now, so use call location.
+        let location = cx.current_expansion.id.expn_info().unwrap().call_site;
+        let to_span = |transparency| {
+            location.with_ctxt(
+                SyntaxContext::empty()
+                    .apply_mark_with_transparency(cx.current_expansion.id, transparency),
+            )
+        };
+        Rustc {
+            sess: cx.parse_sess,
+            def_site: to_span(Transparency::Opaque),
+            call_site: to_span(Transparency::Transparent),
+        }
+    }
+
+    fn lit(&mut self, kind: token::LitKind, symbol: Symbol, suffix: Option<Symbol>) -> Literal {
+        Literal {
+            lit: token::Lit::new(kind, symbol, suffix),
+            span: server::Span::call_site(self),
+        }
+    }
+}
+
+impl server::Types for Rustc<'_> {
+    type TokenStream = TokenStream;
+    type TokenStreamBuilder = tokenstream::TokenStreamBuilder;
+    type TokenStreamIter = TokenStreamIter;
+    type Group = Group;
+    type Punct = Punct;
+    type Ident = Ident;
+    type Literal = Literal;
+    type SourceFile = Lrc<SourceFile>;
+    type MultiSpan = Vec<Span>;
+    type Diagnostic = Diagnostic;
+    type Span = Span;
+}
+
+impl server::TokenStream for Rustc<'_> {
+    fn new(&mut self) -> Self::TokenStream {
+        TokenStream::empty()
+    }
+    fn is_empty(&mut self, stream: &Self::TokenStream) -> bool {
+        stream.is_empty()
+    }
+    fn from_str(&mut self, src: &str) -> Self::TokenStream {
+        parse::parse_stream_from_source_str(
+            FileName::proc_macro_source_code(src),
+            src.to_string(),
+            self.sess,
+            Some(self.call_site),
+        )
+    }
+    fn to_string(&mut self, stream: &Self::TokenStream) -> String {
+        stream.to_string()
+    }
+    fn from_token_tree(
+        &mut self,
+        tree: TokenTree<Self::Group, Self::Punct, Self::Ident, Self::Literal>,
+    ) -> Self::TokenStream {
+        tree.to_internal()
+    }
+    fn into_iter(&mut self, stream: Self::TokenStream) -> Self::TokenStreamIter {
+        TokenStreamIter {
+            cursor: stream.trees(),
+            stack: vec![],
+        }
+    }
+}
+
+impl server::TokenStreamBuilder for Rustc<'_> {
+    fn new(&mut self) -> Self::TokenStreamBuilder {
+        tokenstream::TokenStreamBuilder::new()
+    }
+    fn push(&mut self, builder: &mut Self::TokenStreamBuilder, stream: Self::TokenStream) {
+        builder.push(stream);
+    }
+    fn build(&mut self, builder: Self::TokenStreamBuilder) -> Self::TokenStream {
+        builder.build()
+    }
+}
+
+impl server::TokenStreamIter for Rustc<'_> {
+    fn next(
+        &mut self,
+        iter: &mut Self::TokenStreamIter,
+    ) -> Option<TokenTree<Self::Group, Self::Punct, Self::Ident, Self::Literal>> {
+        loop {
+            let tree = iter.stack.pop().or_else(|| {
+                let next = iter.cursor.next_with_joint()?;
+                Some(TokenTree::from_internal((next, self.sess, &mut iter.stack)))
+            })?;
+            // HACK: The condition "dummy span + group with empty delimiter" represents an AST
+            // fragment approximately converted into a token stream. This may happen, for
+            // example, with inputs to proc macro attributes, including derives. Such "groups"
+            // need to flattened during iteration over stream's token trees.
+            // Eventually this needs to be removed in favor of keeping original token trees
+            // and not doing the roundtrip through AST.
+            if let TokenTree::Group(ref group) = tree {
+                if group.delimiter == Delimiter::None && group.span.entire().is_dummy() {
+                    iter.cursor.append(group.stream.clone());
+                    continue;
+                }
+            }
+            return Some(tree);
+        }
+    }
+}
+
+impl server::Group for Rustc<'_> {
+    fn new(&mut self, delimiter: Delimiter, stream: Self::TokenStream) -> Self::Group {
+        Group {
+            delimiter,
+            stream,
+            span: DelimSpan::from_single(server::Span::call_site(self)),
+        }
+    }
+    fn delimiter(&mut self, group: &Self::Group) -> Delimiter {
+        group.delimiter
+    }
+    fn stream(&mut self, group: &Self::Group) -> Self::TokenStream {
+        group.stream.clone()
+    }
+    fn span(&mut self, group: &Self::Group) -> Self::Span {
+        group.span.entire()
+    }
+    fn span_open(&mut self, group: &Self::Group) -> Self::Span {
+        group.span.open
+    }
+    fn span_close(&mut self, group: &Self::Group) -> Self::Span {
+        group.span.close
+    }
+    fn set_span(&mut self, group: &mut Self::Group, span: Self::Span) {
+        group.span = DelimSpan::from_single(span);
+    }
+}
+
+impl server::Punct for Rustc<'_> {
+    fn new(&mut self, ch: char, spacing: Spacing) -> Self::Punct {
+        Punct::new(ch, spacing == Spacing::Joint, server::Span::call_site(self))
+    }
+    fn as_char(&mut self, punct: Self::Punct) -> char {
+        punct.ch
+    }
+    fn spacing(&mut self, punct: Self::Punct) -> Spacing {
+        if punct.joint {
+            Spacing::Joint
+        } else {
+            Spacing::Alone
+        }
+    }
+    fn span(&mut self, punct: Self::Punct) -> Self::Span {
+        punct.span
+    }
+    fn with_span(&mut self, punct: Self::Punct, span: Self::Span) -> Self::Punct {
+        Punct { span, ..punct }
+    }
+}
+
+impl server::Ident for Rustc<'_> {
+    fn new(&mut self, string: &str, span: Self::Span, is_raw: bool) -> Self::Ident {
+        Ident::new(Symbol::intern(string), is_raw, span)
+    }
+    fn span(&mut self, ident: Self::Ident) -> Self::Span {
+        ident.span
+    }
+    fn with_span(&mut self, ident: Self::Ident, span: Self::Span) -> Self::Ident {
+        Ident { span, ..ident }
+    }
+}
+
+impl server::Literal for Rustc<'_> {
+    // FIXME(eddyb) `Literal` should not expose internal `Debug` impls.
+    fn debug(&mut self, literal: &Self::Literal) -> String {
+        format!("{:?}", literal)
+    }
+    fn integer(&mut self, n: &str) -> Self::Literal {
+        self.lit(token::Integer, Symbol::intern(n), None)
+    }
+    fn typed_integer(&mut self, n: &str, kind: &str) -> Self::Literal {
+        self.lit(token::Integer, Symbol::intern(n), Some(Symbol::intern(kind)))
+    }
+    fn float(&mut self, n: &str) -> Self::Literal {
+        self.lit(token::Float, Symbol::intern(n), None)
+    }
+    fn f32(&mut self, n: &str) -> Self::Literal {
+        self.lit(token::Float, Symbol::intern(n), Some(sym::f32))
+    }
+    fn f64(&mut self, n: &str) -> Self::Literal {
+        self.lit(token::Float, Symbol::intern(n), Some(sym::f64))
+    }
+    fn string(&mut self, string: &str) -> Self::Literal {
+        let mut escaped = String::new();
+        for ch in string.chars() {
+            escaped.extend(ch.escape_debug());
+        }
+        self.lit(token::Str, Symbol::intern(&escaped), None)
+    }
+    fn character(&mut self, ch: char) -> Self::Literal {
+        let mut escaped = String::new();
+        escaped.extend(ch.escape_unicode());
+        self.lit(token::Char, Symbol::intern(&escaped), None)
+    }
+    fn byte_string(&mut self, bytes: &[u8]) -> Self::Literal {
+        let string = bytes
+            .iter()
+            .cloned()
+            .flat_map(ascii::escape_default)
+            .map(Into::<char>::into)
+            .collect::<String>();
+        self.lit(token::ByteStr, Symbol::intern(&string), None)
+    }
+    fn span(&mut self, literal: &Self::Literal) -> Self::Span {
+        literal.span
+    }
+    fn set_span(&mut self, literal: &mut Self::Literal, span: Self::Span) {
+        literal.span = span;
+    }
+    fn subspan(
+        &mut self,
+        literal: &Self::Literal,
+        start: Bound<usize>,
+        end: Bound<usize>,
+    ) -> Option<Self::Span> {
+        let span = literal.span;
+        let length = span.hi().to_usize() - span.lo().to_usize();
+
+        let start = match start {
+            Bound::Included(lo) => lo,
+            Bound::Excluded(lo) => lo + 1,
+            Bound::Unbounded => 0,
+        };
+
+        let end = match end {
+            Bound::Included(hi) => hi + 1,
+            Bound::Excluded(hi) => hi,
+            Bound::Unbounded => length,
+        };
+
+        // Bounds check the values, preventing addition overflow and OOB spans.
+        if start > u32::max_value() as usize
+            || end > u32::max_value() as usize
+            || (u32::max_value() - start as u32) < span.lo().to_u32()
+            || (u32::max_value() - end as u32) < span.lo().to_u32()
+            || start >= end
+            || end > length
+        {
+            return None;
+        }
+
+        let new_lo = span.lo() + BytePos::from_usize(start);
+        let new_hi = span.lo() + BytePos::from_usize(end);
+        Some(span.with_lo(new_lo).with_hi(new_hi))
+    }
+}
+
+impl server::SourceFile for Rustc<'_> {
+    fn eq(&mut self, file1: &Self::SourceFile, file2: &Self::SourceFile) -> bool {
+        Lrc::ptr_eq(file1, file2)
+    }
+    fn path(&mut self, file: &Self::SourceFile) -> String {
+        match file.name {
+            FileName::Real(ref path) => path
+                .to_str()
+                .expect("non-UTF8 file path in `proc_macro::SourceFile::path`")
+                .to_string(),
+            _ => file.name.to_string(),
+        }
+    }
+    fn is_real(&mut self, file: &Self::SourceFile) -> bool {
+        file.is_real_file()
+    }
+}
+
+impl server::MultiSpan for Rustc<'_> {
+    fn new(&mut self) -> Self::MultiSpan {
+        vec![]
+    }
+    fn push(&mut self, spans: &mut Self::MultiSpan, span: Self::Span) {
+        spans.push(span)
+    }
+}
+
+impl server::Diagnostic for Rustc<'_> {
+    fn new(&mut self, level: Level, msg: &str, spans: Self::MultiSpan) -> Self::Diagnostic {
+        let mut diag = Diagnostic::new(level.to_internal(), msg);
+        diag.set_span(MultiSpan::from_spans(spans));
+        diag
+    }
+    fn sub(
+        &mut self,
+        diag: &mut Self::Diagnostic,
+        level: Level,
+        msg: &str,
+        spans: Self::MultiSpan,
+    ) {
+        diag.sub(level.to_internal(), msg, MultiSpan::from_spans(spans), None);
+    }
+    fn emit(&mut self, diag: Self::Diagnostic) {
+        DiagnosticBuilder::new_diagnostic(&self.sess.span_diagnostic, diag).emit()
+    }
+}
+
+impl server::Span for Rustc<'_> {
+    fn debug(&mut self, span: Self::Span) -> String {
+        format!("{:?} bytes({}..{})", span.ctxt(), span.lo().0, span.hi().0)
+    }
+    fn def_site(&mut self) -> Self::Span {
+        self.def_site
+    }
+    fn call_site(&mut self) -> Self::Span {
+        self.call_site
+    }
+    fn source_file(&mut self, span: Self::Span) -> Self::SourceFile {
+        self.sess.source_map().lookup_char_pos(span.lo()).file
+    }
+    fn parent(&mut self, span: Self::Span) -> Option<Self::Span> {
+        span.ctxt().outer_expn_info().map(|i| i.call_site)
+    }
+    fn source(&mut self, span: Self::Span) -> Self::Span {
+        span.source_callsite()
+    }
+    fn start(&mut self, span: Self::Span) -> LineColumn {
+        let loc = self.sess.source_map().lookup_char_pos(span.lo());
+        LineColumn {
+            line: loc.line,
+            column: loc.col.to_usize(),
+        }
+    }
+    fn end(&mut self, span: Self::Span) -> LineColumn {
+        let loc = self.sess.source_map().lookup_char_pos(span.hi());
+        LineColumn {
+            line: loc.line,
+            column: loc.col.to_usize(),
+        }
+    }
+    fn join(&mut self, first: Self::Span, second: Self::Span) -> Option<Self::Span> {
+        let self_loc = self.sess.source_map().lookup_char_pos(first.lo());
+        let other_loc = self.sess.source_map().lookup_char_pos(second.lo());
+
+        if self_loc.file.name != other_loc.file.name {
+            return None;
+        }
+
+        Some(first.to(second))
+    }
+    fn resolved_at(&mut self, span: Self::Span, at: Self::Span) -> Self::Span {
+        span.with_ctxt(at.ctxt())
+    }
+    fn source_text(&mut self,  span: Self::Span) -> Option<String> {
+        self.sess.source_map().span_to_snippet(span).ok()
+    }
+}
diff --git a/src/libsyntax/ext/source_util.rs b/src/libsyntax/ext/source_util.rs
deleted file mode 100644 (file)
index ae080c0..0000000
+++ /dev/null
@@ -1,165 +0,0 @@
-use crate::ast;
-use crate::ext::base::{self, *};
-use crate::ext::build::AstBuilder;
-use crate::parse::{self, token, DirectoryOwnership};
-use crate::print::pprust;
-use crate::ptr::P;
-use crate::symbol::Symbol;
-use crate::tokenstream;
-
-use smallvec::SmallVec;
-use syntax_pos::{self, Pos, Span};
-
-use std::fs;
-use std::io::ErrorKind;
-use rustc_data_structures::sync::Lrc;
-
-// These macros all relate to the file system; they either return
-// the column/row/filename of the expression, or they include
-// a given file into the current one.
-
-/// line!(): expands to the current line number
-pub fn expand_line(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTree])
-                   -> Box<dyn base::MacResult+'static> {
-    base::check_zero_tts(cx, sp, tts, "line!");
-
-    let topmost = cx.expansion_cause().unwrap_or(sp);
-    let loc = cx.source_map().lookup_char_pos(topmost.lo());
-
-    base::MacEager::expr(cx.expr_u32(topmost, loc.line as u32))
-}
-
-/* column!(): expands to the current column number */
-pub fn expand_column(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTree])
-                  -> Box<dyn base::MacResult+'static> {
-    base::check_zero_tts(cx, sp, tts, "column!");
-
-    let topmost = cx.expansion_cause().unwrap_or(sp);
-    let loc = cx.source_map().lookup_char_pos(topmost.lo());
-
-    base::MacEager::expr(cx.expr_u32(topmost, loc.col.to_usize() as u32 + 1))
-}
-
-/// file!(): expands to the current filename */
-/// The source_file (`loc.file`) contains a bunch more information we could spit
-/// out if we wanted.
-pub fn expand_file(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTree])
-                   -> Box<dyn base::MacResult+'static> {
-    base::check_zero_tts(cx, sp, tts, "file!");
-
-    let topmost = cx.expansion_cause().unwrap_or(sp);
-    let loc = cx.source_map().lookup_char_pos(topmost.lo());
-    base::MacEager::expr(cx.expr_str(topmost, Symbol::intern(&loc.file.name.to_string())))
-}
-
-pub fn expand_stringify(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTree])
-                        -> Box<dyn base::MacResult+'static> {
-    let s = pprust::tts_to_string(tts);
-    base::MacEager::expr(cx.expr_str(sp, Symbol::intern(&s)))
-}
-
-pub fn expand_mod(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTree])
-                  -> Box<dyn base::MacResult+'static> {
-    base::check_zero_tts(cx, sp, tts, "module_path!");
-    let mod_path = &cx.current_expansion.module.mod_path;
-    let string = mod_path.iter().map(|x| x.to_string()).collect::<Vec<String>>().join("::");
-
-    base::MacEager::expr(cx.expr_str(sp, Symbol::intern(&string)))
-}
-
-/// include! : parse the given file as an expr
-/// This is generally a bad idea because it's going to behave
-/// unhygienically.
-pub fn expand_include<'cx>(cx: &'cx mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTree])
-                           -> Box<dyn base::MacResult+'cx> {
-    let file = match get_single_str_from_tts(cx, sp, tts, "include!") {
-        Some(f) => f,
-        None => return DummyResult::any(sp),
-    };
-    // The file will be added to the code map by the parser
-    let file = cx.resolve_path(file, sp);
-    let directory_ownership = DirectoryOwnership::Owned { relative: None };
-    let p = parse::new_sub_parser_from_file(cx.parse_sess(), &file, directory_ownership, None, sp);
-
-    struct ExpandResult<'a> {
-        p: parse::parser::Parser<'a>,
-    }
-    impl<'a> base::MacResult for ExpandResult<'a> {
-        fn make_expr(mut self: Box<ExpandResult<'a>>) -> Option<P<ast::Expr>> {
-            Some(panictry!(self.p.parse_expr()))
-        }
-
-        fn make_items(mut self: Box<ExpandResult<'a>>) -> Option<SmallVec<[P<ast::Item>; 1]>> {
-            let mut ret = SmallVec::new();
-            while self.p.token != token::Eof {
-                match panictry!(self.p.parse_item()) {
-                    Some(item) => ret.push(item),
-                    None => self.p.diagnostic().span_fatal(self.p.token.span,
-                                                           &format!("expected item, found `{}`",
-                                                                    self.p.this_token_to_string()))
-                                               .raise()
-                }
-            }
-            Some(ret)
-        }
-    }
-
-    Box::new(ExpandResult { p })
-}
-
-// include_str! : read the given file, insert it as a literal string expr
-pub fn expand_include_str(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTree])
-                          -> Box<dyn base::MacResult+'static> {
-    let file = match get_single_str_from_tts(cx, sp, tts, "include_str!") {
-        Some(f) => f,
-        None => return DummyResult::expr(sp)
-    };
-    let file = cx.resolve_path(file, sp);
-    match fs::read_to_string(&file) {
-        Ok(src) => {
-            let interned_src = Symbol::intern(&src);
-
-            // Add this input file to the code map to make it available as
-            // dependency information
-            cx.source_map().new_source_file(file.into(), src);
-
-            base::MacEager::expr(cx.expr_str(sp, interned_src))
-        },
-        Err(ref e) if e.kind() == ErrorKind::InvalidData => {
-            cx.span_err(sp, &format!("{} wasn't a utf-8 file", file.display()));
-            DummyResult::expr(sp)
-        }
-        Err(e) => {
-            cx.span_err(sp, &format!("couldn't read {}: {}", file.display(), e));
-            DummyResult::expr(sp)
-        }
-    }
-}
-
-pub fn expand_include_bytes(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTree])
-                            -> Box<dyn base::MacResult+'static> {
-    let file = match get_single_str_from_tts(cx, sp, tts, "include_bytes!") {
-        Some(f) => f,
-        None => return DummyResult::expr(sp)
-    };
-    let file = cx.resolve_path(file, sp);
-    match fs::read(&file) {
-        Ok(bytes) => {
-            // Add the contents to the source map if it contains UTF-8.
-            let (contents, bytes) = match String::from_utf8(bytes) {
-                Ok(s) => {
-                    let bytes = s.as_bytes().to_owned();
-                    (s, bytes)
-                },
-                Err(e) => (String::new(), e.into_bytes()),
-            };
-            cx.source_map().new_source_file(file.into(), contents);
-
-            base::MacEager::expr(cx.expr_lit(sp, ast::LitKind::ByteStr(Lrc::new(bytes))))
-        },
-        Err(e) => {
-            cx.span_err(sp, &format!("couldn't read {}: {}", file.display(), e));
-            DummyResult::expr(sp)
-        }
-    }
-}
index 72184b0bd6400374f59ad582793a44c6707a9b25..384474b08f6ee28a33c46bc66b2179693f258de5 100644 (file)
@@ -2151,11 +2151,23 @@ fn visit_arm(&mut self, arm: &'a ast::Arm) {
     }
 
     fn visit_pat(&mut self, pattern: &'a ast::Pat) {
-        match pattern.node {
-            PatKind::Slice(_, Some(ref subslice), _) => {
-                gate_feature_post!(&self, slice_patterns,
-                                   subslice.span,
-                                   "syntax for subslices in slice patterns is not yet stabilized");
+        match &pattern.node {
+            PatKind::Slice(pats) => {
+                for pat in &*pats {
+                    let span = pat.span;
+                    let inner_pat = match &pat.node {
+                        PatKind::Ident(.., Some(pat)) => pat,
+                        _ => pat,
+                    };
+                    if inner_pat.is_rest() {
+                        gate_feature_post!(
+                            &self,
+                            slice_patterns,
+                            span,
+                            "subslice patterns are unstable"
+                        );
+                    }
+                }
             }
             PatKind::Box(..) => {
                 gate_feature_post!(&self, box_patterns,
index ec0222d90eb7a2430cc71fdd284b6f0f88806f0e..83c9c692bd30c9fb7e993b2e36bdecc40fe6d435 100644 (file)
@@ -122,7 +122,6 @@ struct Diagnostic {
 }
 
 #[derive(RustcEncodable)]
-#[allow(unused_attributes)]
 struct DiagnosticSpan {
     file_name: String,
     byte_start: u32,
index 75b4e89ec01c259572a5322e20ca94aa355a88f8..1fd20fa0b31285a2b60680ead343ed8f55c130a7 100644 (file)
@@ -7,9 +7,6 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/",
        test(attr(deny(warnings))))]
 
-#![deny(rust_2018_idioms)]
-#![deny(unused_lifetimes)]
-
 #![feature(bind_by_move_pattern_guards)]
 #![feature(box_syntax)]
 #![feature(const_fn)]
 #![feature(label_break_value)]
 #![feature(mem_take)]
 #![feature(nll)]
+#![feature(proc_macro_diagnostic)]
+#![feature(proc_macro_internals)]
+#![feature(proc_macro_span)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(try_trait)]
 #![feature(unicode_internals)]
 
 #![recursion_limit="256"]
 
+extern crate proc_macro;
+
 pub use errors;
 use rustc_data_structures::sync::Lock;
 use rustc_data_structures::bit_set::GrowableBitSet;
@@ -37,6 +39,7 @@
 // way towards a non-panic!-prone parser. It should be used for fatal parsing
 // errors; eventually we plan to convert all code using panictry to just use
 // normal try.
+#[macro_export]
 macro_rules! panictry {
     ($e:expr) => ({
         use std::result::Result::{Ok, Err};
@@ -147,10 +150,8 @@ pub mod util {
 pub mod parse;
 pub mod ptr;
 pub mod show_span;
-pub mod std_inject;
 pub use syntax_pos::edition;
 pub use syntax_pos::symbol;
-pub mod test;
 pub mod tokenstream;
 pub mod visit;
 
@@ -161,14 +162,15 @@ pub mod print {
 }
 
 pub mod ext {
+    mod placeholders;
+    mod proc_macro_server;
+
     pub use syntax_pos::hygiene;
     pub mod allocator;
     pub mod base;
     pub mod build;
-    pub mod derive;
     pub mod expand;
-    pub mod placeholders;
-    pub mod source_util;
+    pub mod proc_macro;
 
     pub mod tt {
         pub mod transcribe;
index dc656222fbc1082659d2915a62abe979dccc5169..43b6bea69d9ed5522decbdf2d10c1332fb44e83c 100644 (file)
@@ -558,10 +558,11 @@ pub fn noop_visit_meta_item<T: MutVisitor>(mi: &mut MetaItem, vis: &mut T) {
     vis.visit_span(span);
 }
 
-pub fn noop_visit_arg<T: MutVisitor>(Arg { attrs, id, pat, ty }: &mut Arg, vis: &mut T) {
+pub fn noop_visit_arg<T: MutVisitor>(Arg { attrs, id, pat, span, ty }: &mut Arg, vis: &mut T) {
     vis.visit_id(id);
     visit_thin_attrs(attrs, vis);
     vis.visit_pat(pat);
+    vis.visit_span(span);
     vis.visit_ty(ty);
 }
 
@@ -1020,15 +1021,15 @@ pub fn noop_visit_pat<T: MutVisitor>(pat: &mut P<Pat>, vis: &mut T) {
     let Pat { id, node, span } = pat.deref_mut();
     vis.visit_id(id);
     match node {
-        PatKind::Wild => {}
+        PatKind::Wild | PatKind::Rest => {}
         PatKind::Ident(_binding_mode, ident, sub) => {
             vis.visit_ident(ident);
             visit_opt(sub, |sub| vis.visit_pat(sub));
         }
         PatKind::Lit(e) => vis.visit_expr(e),
-        PatKind::TupleStruct(path, pats, _ddpos) => {
+        PatKind::TupleStruct(path, elems) => {
             vis.visit_path(path);
-            visit_vec(pats, |pat| vis.visit_pat(pat));
+            visit_vec(elems, |elem| vis.visit_pat(elem));
         }
         PatKind::Path(qself, path) => {
             vis.visit_qself(qself);
@@ -1043,7 +1044,7 @@ pub fn noop_visit_pat<T: MutVisitor>(pat: &mut P<Pat>, vis: &mut T) {
                 vis.visit_span(span);
             };
         }
-        PatKind::Tuple(elts, _ddpos) => visit_vec(elts, |elt| vis.visit_pat(elt)),
+        PatKind::Tuple(elems) => visit_vec(elems, |elem| vis.visit_pat(elem)),
         PatKind::Box(inner) => vis.visit_pat(inner),
         PatKind::Ref(inner, _mutbl) => vis.visit_pat(inner),
         PatKind::Range(e1, e2, Spanned { span: _, node: _ }) => {
@@ -1051,11 +1052,7 @@ pub fn noop_visit_pat<T: MutVisitor>(pat: &mut P<Pat>, vis: &mut T) {
             vis.visit_expr(e2);
             vis.visit_span(span);
         }
-        PatKind::Slice(before, slice, after) => {
-            visit_vec(before, |pat| vis.visit_pat(pat));
-            visit_opt(slice, |slice| vis.visit_pat(slice));
-            visit_vec(after, |pat| vis.visit_pat(pat));
-        }
+        PatKind::Slice(elems) => visit_vec(elems, |elem| vis.visit_pat(elem)),
         PatKind::Paren(inner) => vis.visit_pat(inner),
         PatKind::Mac(mac) => vis.visit_mac(mac),
     }
index 1758d0b0bb947781bcef87b8afa132918f53a351..af484c886ab35b7d796995d6eea834fd2938251d 100644 (file)
@@ -4,6 +4,7 @@
 use crate::parse::token::{self, Nonterminal, DelimToken};
 use crate::parse::parser::{Parser, TokenType, PathStyle};
 use crate::tokenstream::{TokenStream, TokenTree};
+use crate::source_map::Span;
 
 use log::debug;
 use smallvec::smallvec;
@@ -11,7 +12,7 @@
 #[derive(Debug)]
 enum InnerAttributeParsePolicy<'a> {
     Permitted,
-    NotPermitted { reason: &'a str },
+    NotPermitted { reason: &'a str, saw_doc_comment: bool, prev_attr_sp: Option<Span> },
 }
 
 const DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG: &str = "an inner attribute is not \
@@ -42,7 +43,11 @@ impl<'a> Parser<'a> {
                         DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG
                     };
                     let inner_parse_policy =
-                        InnerAttributeParsePolicy::NotPermitted { reason: inner_error_reason };
+                        InnerAttributeParsePolicy::NotPermitted {
+                            reason: inner_error_reason,
+                            saw_doc_comment: just_parsed_doc_comment,
+                            prev_attr_sp: attrs.last().and_then(|a| Some(a.span))
+                        };
                     let attr = self.parse_attribute_with_inner_parse_policy(inner_parse_policy)?;
                     attrs.push(attr);
                     just_parsed_doc_comment = false;
@@ -76,8 +81,11 @@ pub fn parse_attribute(&mut self, permit_inner: bool) -> PResult<'a, ast::Attrib
         let inner_parse_policy = if permit_inner {
             InnerAttributeParsePolicy::Permitted
         } else {
-            InnerAttributeParsePolicy::NotPermitted
-                { reason: DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG }
+            InnerAttributeParsePolicy::NotPermitted {
+                reason: DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG,
+                saw_doc_comment: false,
+                prev_attr_sp: None
+            }
         };
         self.parse_attribute_with_inner_parse_policy(inner_parse_policy)
     }
@@ -98,19 +106,9 @@ fn parse_attribute_with_inner_parse_policy(&mut self,
                 if let InnerAttributeParsePolicy::Permitted = inner_parse_policy {
                     self.expected_tokens.push(TokenType::Token(token::Not));
                 }
+
                 let style = if self.token == token::Not {
                     self.bump();
-                    if let InnerAttributeParsePolicy::NotPermitted { reason } = inner_parse_policy
-                    {
-                        let span = self.token.span;
-                        self.diagnostic()
-                            .struct_span_err(span, reason)
-                            .note("inner attributes, like `#![no_std]`, annotate the item \
-                                   enclosing them, and are usually found at the beginning of \
-                                   source files. Outer attributes, like `#[test]`, annotate the \
-                                   item following them.")
-                            .emit()
-                    }
                     ast::AttrStyle::Inner
                 } else {
                     ast::AttrStyle::Outer
@@ -121,7 +119,38 @@ fn parse_attribute_with_inner_parse_policy(&mut self,
                 self.expect(&token::CloseDelim(token::Bracket))?;
                 let hi = self.prev_span;
 
-                (lo.to(hi), path, tokens, style)
+                let attr_sp = lo.to(hi);
+
+                // Emit error if inner attribute is encountered and not permitted
+                if style == ast::AttrStyle::Inner {
+                    if let InnerAttributeParsePolicy::NotPermitted { reason,
+                        saw_doc_comment, prev_attr_sp } = inner_parse_policy {
+                        let prev_attr_note = if saw_doc_comment {
+                            "previous doc comment"
+                        } else {
+                            "previous outer attribute"
+                        };
+
+                        let mut diagnostic = self
+                            .diagnostic()
+                            .struct_span_err(attr_sp, reason);
+
+                        if let Some(prev_attr_sp) = prev_attr_sp {
+                            diagnostic
+                                .span_label(attr_sp, "not permitted following an outer attibute")
+                                .span_label(prev_attr_sp, prev_attr_note);
+                        }
+
+                        diagnostic
+                            .note("inner attributes, like `#![no_std]`, annotate the item \
+                                   enclosing them, and are usually found at the beginning of \
+                                   source files. Outer attributes, like `#[test]`, annotate the \
+                                   item following them.")
+                            .emit()
+                    }
+                }
+
+                (attr_sp, path, tokens, style)
             }
             _ => {
                 let token_str = self.this_token_to_string();
index f4fc87506f357247666cca64a661a88d750cc84d..39cb5042fbc115a99932d11d19bcf1a2f83093bf 100644 (file)
@@ -30,7 +30,7 @@
         span: ident.span,
         id: ast::DUMMY_NODE_ID
     };
-    Arg { attrs: ThinVec::default(), id: ast::DUMMY_NODE_ID, pat, ty: P(ty) }
+    Arg { attrs: ThinVec::default(), id: ast::DUMMY_NODE_ID, pat, span: ident.span, ty: P(ty) }
 }
 
 pub enum Error {
index 52f65e1b474754b5927eb12c59136fefd4bf03f8..3cd5464f35710c4fd67c6c57cc3a57a409a0462c 100644 (file)
@@ -794,7 +794,7 @@ mod tests {
     use std::path::PathBuf;
     use syntax_pos::{BytePos, Span, NO_EXPANSION, edition::Edition};
     use rustc_data_structures::fx::{FxHashSet, FxHashMap};
-    use rustc_data_structures::sync::Lock;
+    use rustc_data_structures::sync::{Lock, Once};
 
     fn mk_sess(sm: Lrc<SourceMap>) -> ParseSess {
         let emitter = errors::emitter::EmitterWriter::new(Box::new(io::sink()),
@@ -817,6 +817,7 @@ fn mk_sess(sm: Lrc<SourceMap>) -> ParseSess {
             param_attr_spans: Lock::new(Vec::new()),
             let_chains_spans: Lock::new(Vec::new()),
             async_closure_spans: Lock::new(Vec::new()),
+            injected_crate_name: Once::new(),
         }
     }
 
index 225065c1cf11f84a7886bb1df712f74b3b4971df..1aac8bbb7aa46589d9d07a3af0017a1757f838ef 100644 (file)
 use crate::tokenstream::{TokenStream, TokenTree};
 use crate::diagnostics::plugin::ErrorMap;
 use crate::print::pprust;
+use crate::symbol::Symbol;
 
 use errors::{Applicability, FatalError, Level, Handler, ColorConfig, Diagnostic, DiagnosticBuilder};
-use rustc_data_structures::sync::{Lrc, Lock};
+use rustc_data_structures::sync::{Lrc, Lock, Once};
 use syntax_pos::{Span, SourceFile, FileName, MultiSpan};
 use syntax_pos::edition::Edition;
 
@@ -58,6 +59,7 @@ pub struct ParseSess {
     pub let_chains_spans: Lock<Vec<Span>>,
     // Places where `async || ..` exprs were used and should be feature gated.
     pub async_closure_spans: Lock<Vec<Span>>,
+    pub injected_crate_name: Once<Symbol>,
 }
 
 impl ParseSess {
@@ -86,6 +88,7 @@ pub fn with_span_handler(handler: Handler, source_map: Lrc<SourceMap>) -> ParseS
             param_attr_spans: Lock::new(Vec::new()),
             let_chains_spans: Lock::new(Vec::new()),
             async_closure_spans: Lock::new(Vec::new()),
+            injected_crate_name: Once::new(),
         }
     }
 
index a5b6f0d683629342ee2573c018e77ec72ce347c7..6cb965bf817d170892e56254d973553e1ff4c440 100644 (file)
@@ -890,14 +890,13 @@ fn expect_gt(&mut self) -> PResult<'a, ()> {
     /// Parses a sequence, including the closing delimiter. The function
     /// `f` must consume tokens until reaching the next separator or
     /// closing bracket.
-    pub fn parse_seq_to_end<T, F>(&mut self,
-                                  ket: &TokenKind,
-                                  sep: SeqSep,
-                                  f: F)
-                                  -> PResult<'a, Vec<T>> where
-        F: FnMut(&mut Parser<'a>) -> PResult<'a,  T>,
-    {
-        let (val, recovered) = self.parse_seq_to_before_end(ket, sep, f)?;
+    pub fn parse_seq_to_end<T>(
+        &mut self,
+        ket: &TokenKind,
+        sep: SeqSep,
+        f: impl FnMut(&mut Parser<'a>) -> PResult<'a,  T>,
+    ) -> PResult<'a, Vec<T>> {
+        let (val, _, recovered) = self.parse_seq_to_before_end(ket, sep, f)?;
         if !recovered {
             self.bump();
         }
@@ -907,39 +906,39 @@ pub fn parse_seq_to_end<T, F>(&mut self,
     /// Parses a sequence, not including the closing delimiter. The function
     /// `f` must consume tokens until reaching the next separator or
     /// closing bracket.
-    pub fn parse_seq_to_before_end<T, F>(
+    pub fn parse_seq_to_before_end<T>(
         &mut self,
         ket: &TokenKind,
         sep: SeqSep,
-        f: F,
-    ) -> PResult<'a, (Vec<T>, bool)>
-        where F: FnMut(&mut Parser<'a>) -> PResult<'a, T>
-    {
+        f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
+    ) -> PResult<'a, (Vec<T>, bool, bool)> {
         self.parse_seq_to_before_tokens(&[ket], sep, TokenExpectType::Expect, f)
     }
 
-    crate fn parse_seq_to_before_tokens<T, F>(
+    fn expect_any_with_type(&mut self, kets: &[&TokenKind], expect: TokenExpectType) -> bool {
+        kets.iter().any(|k| {
+            match expect {
+                TokenExpectType::Expect => self.check(k),
+                TokenExpectType::NoExpect => self.token == **k,
+            }
+        })
+    }
+
+    crate fn parse_seq_to_before_tokens<T>(
         &mut self,
         kets: &[&TokenKind],
         sep: SeqSep,
         expect: TokenExpectType,
-        mut f: F,
-    ) -> PResult<'a, (Vec<T>, bool /* recovered */)>
-        where F: FnMut(&mut Parser<'a>) -> PResult<'a, T>
-    {
+        mut f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
+    ) -> PResult<'a, (Vec<T>, bool /* trailing */, bool /* recovered */)> {
         let mut first = true;
         let mut recovered = false;
+        let mut trailing = false;
         let mut v = vec![];
-        while !kets.iter().any(|k| {
-                match expect {
-                    TokenExpectType::Expect => self.check(k),
-                    TokenExpectType::NoExpect => self.token == **k,
-                }
-            }) {
-            match self.token.kind {
-                token::CloseDelim(..) | token::Eof => break,
-                _ => {}
-            };
+        while !self.expect_any_with_type(kets, expect) {
+            if let token::CloseDelim(..) | token::Eof = self.token.kind {
+                break
+            }
             if let Some(ref t) = sep.sep {
                 if first {
                     first = false;
@@ -973,12 +972,8 @@ pub fn parse_seq_to_before_end<T, F>(
                     }
                 }
             }
-            if sep.trailing_sep_allowed && kets.iter().any(|k| {
-                match expect {
-                    TokenExpectType::Expect => self.check(k),
-                    TokenExpectType::NoExpect => self.token == **k,
-                }
-            }) {
+            if sep.trailing_sep_allowed && self.expect_any_with_type(kets, expect) {
+                trailing = true;
                 break;
             }
 
@@ -986,27 +981,45 @@ pub fn parse_seq_to_before_end<T, F>(
             v.push(t);
         }
 
-        Ok((v, recovered))
+        Ok((v, trailing, recovered))
     }
 
     /// Parses a sequence, including the closing delimiter. The function
     /// `f` must consume tokens until reaching the next separator or
     /// closing bracket.
-    fn parse_unspanned_seq<T, F>(
+    fn parse_unspanned_seq<T>(
         &mut self,
         bra: &TokenKind,
         ket: &TokenKind,
         sep: SeqSep,
-        f: F,
-    ) -> PResult<'a, Vec<T>> where
-        F: FnMut(&mut Parser<'a>) -> PResult<'a, T>,
-    {
+        f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
+    ) -> PResult<'a, (Vec<T>, bool)> {
         self.expect(bra)?;
-        let (result, recovered) = self.parse_seq_to_before_end(ket, sep, f)?;
+        let (result, trailing, recovered) = self.parse_seq_to_before_end(ket, sep, f)?;
         if !recovered {
             self.eat(ket);
         }
-        Ok(result)
+        Ok((result, trailing))
+    }
+
+    fn parse_delim_comma_seq<T>(
+        &mut self,
+        delim: DelimToken,
+        f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
+    ) -> PResult<'a, (Vec<T>, bool)> {
+        self.parse_unspanned_seq(
+            &token::OpenDelim(delim),
+            &token::CloseDelim(delim),
+            SeqSep::trailing_allowed(token::Comma),
+            f,
+        )
+    }
+
+    fn parse_paren_comma_seq<T>(
+        &mut self,
+        f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
+    ) -> PResult<'a, (Vec<T>, bool)> {
+        self.parse_delim_comma_seq(token::Paren, f)
     }
 
     /// Advance the parser by one token
@@ -1502,6 +1515,7 @@ fn parse_arg_general<F>(
     where
         F: Fn(&token::Token) -> bool
     {
+        let lo = self.token.span;
         let attrs = self.parse_arg_attributes()?;
         if let Some(mut arg) = self.parse_self_arg()? {
             arg.attrs = attrs.into();
@@ -1565,11 +1579,14 @@ fn parse_arg_general<F>(
             }
         };
 
-        Ok(Arg { attrs: attrs.into(), id: ast::DUMMY_NODE_ID, pat, ty })
+        let span = lo.to(self.token.span);
+
+        Ok(Arg { attrs: attrs.into(), id: ast::DUMMY_NODE_ID, pat, span, ty })
     }
 
     /// Parses an argument in a lambda header (e.g., `|arg, arg|`).
     fn parse_fn_block_arg(&mut self) -> PResult<'a, Arg> {
+        let lo = self.token.span;
         let attrs = self.parse_arg_attributes()?;
         let pat = self.parse_pat(Some("argument name"))?;
         let t = if self.eat(&token::Colon) {
@@ -1581,10 +1598,12 @@ fn parse_fn_block_arg(&mut self) -> PResult<'a, Arg> {
                 span: self.prev_span,
             })
         };
+        let span = lo.to(self.token.span);
         Ok(Arg {
             attrs: attrs.into(),
             ty: t,
             pat,
+            span,
             id: ast::DUMMY_NODE_ID
         })
     }
@@ -1804,15 +1823,7 @@ fn parse_path_segment(&mut self, style: PathStyle) -> PResult<'a, PathSegment> {
                 AngleBracketedArgs { args, constraints, span }.into()
             } else {
                 // `(T, U) -> R`
-                self.bump(); // `(`
-                let (inputs, recovered) = self.parse_seq_to_before_tokens(
-                    &[&token::CloseDelim(token::Paren)],
-                    SeqSep::trailing_allowed(token::Comma),
-                    TokenExpectType::Expect,
-                    |p| p.parse_ty())?;
-                if !recovered {
-                    self.bump(); // `)`
-                }
+                let (inputs, _) = self.parse_paren_comma_seq(|p| p.parse_ty())?;
                 let span = lo.to(self.prev_span);
                 let output = if self.eat(&token::RArrow) {
                     Some(self.parse_ty_common(false, false, false)?)
@@ -2516,12 +2527,7 @@ fn parse_dot_suffix(&mut self, self_arg: P<Expr>, lo: Span) -> PResult<'a, P<Exp
         Ok(match self.token.kind {
             token::OpenDelim(token::Paren) => {
                 // Method call `expr.f()`
-                let mut args = self.parse_unspanned_seq(
-                    &token::OpenDelim(token::Paren),
-                    &token::CloseDelim(token::Paren),
-                    SeqSep::trailing_allowed(token::Comma),
-                    |p| Ok(p.parse_expr()?)
-                )?;
+                let mut args = self.parse_paren_expr_seq()?;
                 args.insert(0, self_arg);
 
                 let span = lo.to(self.prev_span);
@@ -2606,12 +2612,7 @@ fn parse_dot_or_call_expr_with_(&mut self, e0: P<Expr>, lo: Span) -> PResult<'a,
             match self.token.kind {
                 // expr(...)
                 token::OpenDelim(token::Paren) => {
-                    let seq = self.parse_unspanned_seq(
-                        &token::OpenDelim(token::Paren),
-                        &token::CloseDelim(token::Paren),
-                        SeqSep::trailing_allowed(token::Comma),
-                        |p| Ok(p.parse_expr()?)
-                    ).map(|es| {
+                    let seq = self.parse_paren_expr_seq().map(|es| {
                         let nd = self.mk_call(e, es);
                         let hi = self.prev_span;
                         self.mk_expr(lo.to(hi), nd, ThinVec::new())
@@ -2635,6 +2636,10 @@ fn parse_dot_or_call_expr_with_(&mut self, e0: P<Expr>, lo: Span) -> PResult<'a,
         return Ok(e);
     }
 
+    fn parse_paren_expr_seq(&mut self) -> PResult<'a, Vec<P<Expr>>> {
+        self.parse_paren_comma_seq(|p| p.parse_expr()).map(|(r, _)| r)
+    }
+
     crate fn process_potential_macro_variable(&mut self) {
         self.token = match self.token.kind {
             token::Dollar if self.token.span.ctxt() != SyntaxContext::empty() &&
@@ -3536,122 +3541,6 @@ fn parse_pats(&mut self) -> PResult<'a, Vec<P<Pat>>> {
         };
     }
 
-    // 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))?;
-        let result = match self.parse_pat_list() {
-            Ok(result) => result,
-            Err(mut err) => { // recover from parse error in tuple pattern list
-                err.emit();
-                self.consume_block(token::Paren);
-                return Ok((vec![], Some(0), false));
-            }
-        };
-        self.expect(&token::CloseDelim(token::Paren))?;
-        Ok(result)
-    }
-
-    fn parse_pat_list(&mut self) -> PResult<'a, (Vec<P<Pat>>, Option<usize>, bool)> {
-        let mut fields = Vec::new();
-        let mut ddpos = None;
-        let mut prev_dd_sp = None;
-        let mut trailing_comma = false;
-        loop {
-            if self.eat(&token::DotDot) {
-                if ddpos.is_none() {
-                    ddpos = Some(fields.len());
-                    prev_dd_sp = Some(self.prev_span);
-                } else {
-                    // Emit a friendly error, ignore `..` and continue parsing
-                    let mut err = self.struct_span_err(
-                        self.prev_span,
-                        "`..` can only be used once per tuple or tuple struct pattern",
-                    );
-                    err.span_label(self.prev_span, "can only be used once per pattern");
-                    if let Some(sp) = prev_dd_sp {
-                        err.span_label(sp, "previously present here");
-                    }
-                    err.emit();
-                }
-            } else if !self.check(&token::CloseDelim(token::Paren)) {
-                fields.push(self.parse_pat(None)?);
-            } else {
-                break
-            }
-
-            trailing_comma = self.eat(&token::Comma);
-            if !trailing_comma {
-                break
-            }
-        }
-
-        if ddpos == Some(fields.len()) && trailing_comma {
-            // `..` needs to be followed by `)` or `, pat`, `..,)` is disallowed.
-            let msg = "trailing comma is not permitted after `..`";
-            self.struct_span_err(self.prev_span, msg)
-                .span_label(self.prev_span, msg)
-                .emit();
-        }
-
-        Ok((fields, ddpos, trailing_comma))
-    }
-
-    fn parse_pat_vec_elements(
-        &mut self,
-    ) -> PResult<'a, (Vec<P<Pat>>, Option<P<Pat>>, Vec<P<Pat>>)> {
-        let mut before = Vec::new();
-        let mut slice = None;
-        let mut after = Vec::new();
-        let mut first = true;
-        let mut before_slice = true;
-
-        while self.token != token::CloseDelim(token::Bracket) {
-            if first {
-                first = false;
-            } else {
-                self.expect(&token::Comma)?;
-
-                if self.token == token::CloseDelim(token::Bracket)
-                        && (before_slice || !after.is_empty()) {
-                    break
-                }
-            }
-
-            if before_slice {
-                if self.eat(&token::DotDot) {
-
-                    if self.check(&token::Comma) ||
-                            self.check(&token::CloseDelim(token::Bracket)) {
-                        slice = Some(P(Pat {
-                            id: ast::DUMMY_NODE_ID,
-                            node: PatKind::Wild,
-                            span: self.prev_span,
-                        }));
-                        before_slice = false;
-                    }
-                    continue
-                }
-            }
-
-            let subpat = self.parse_pat(None)?;
-            if before_slice && self.eat(&token::DotDot) {
-                slice = Some(subpat);
-                before_slice = false;
-            } else if before_slice {
-                before.push(subpat);
-            } else {
-                after.push(subpat);
-            }
-        }
-
-        Ok((before, slice, after))
-    }
-
     fn parse_pat_field(
         &mut self,
         lo: Span,
@@ -3847,20 +3736,34 @@ fn parse_pat_range_end(&mut self) -> PResult<'a, P<Expr>> {
         }
     }
 
-    // helper function to decide whether to parse as ident binding or to try to do
-    // something more complex like range patterns
+    /// Is the current token suitable as the start of a range patterns end?
+    fn is_pat_range_end_start(&self) -> bool {
+        self.token.is_path_start() // e.g. `MY_CONST`;
+            || self.token == token::Dot // e.g. `.5` for recovery;
+            || self.token.can_begin_literal_or_bool() // e.g. `42`.
+    }
+
+    // Helper function to decide whether to parse as ident binding
+    // or to try to do something more complex like range patterns.
     fn parse_as_ident(&mut self) -> bool {
         self.look_ahead(1, |t| match t.kind {
             token::OpenDelim(token::Paren) | token::OpenDelim(token::Brace) |
-            token::DotDotDot | token::DotDotEq | token::ModSep | token::Not => Some(false),
-            // ensure slice patterns [a, b.., c] and [a, b, c..] don't go into the
-            // range pattern branch
-            token::DotDot => None,
-            _ => Some(true),
-        }).unwrap_or_else(|| self.look_ahead(2, |t| match t.kind {
-            token::Comma | token::CloseDelim(token::Bracket) => true,
-            _ => false,
-        }))
+            token::DotDotDot | token::DotDotEq | token::DotDot |
+            token::ModSep | token::Not => false,
+            _ => true,
+        })
+    }
+
+    /// Parse and throw away a parentesized comma separated
+    /// sequence of patterns until `)` is reached.
+    fn skip_pat_list(&mut self) -> PResult<'a, ()> {
+        while !self.check(&token::CloseDelim(token::Paren)) {
+            self.parse_pat(None)?;
+            if !self.eat(&token::Comma) {
+                return Ok(())
+            }
+        }
+        Ok(())
     }
 
     /// A wrapper around `parse_pat` with some special error handling for the
@@ -3876,7 +3779,7 @@ fn parse_top_level_pat(&mut self) -> PResult<'a, P<Pat>> {
             // later.
             let comma_span = self.token.span;
             self.bump();
-            if let Err(mut err) = self.parse_pat_list() {
+            if let Err(mut err) = self.skip_pat_list() {
                 // We didn't expect this to work anyway; we just wanted
                 // to advance to the end of the comma-sequence so we know
                 // the span to suggest parenthesizing
@@ -3908,6 +3811,53 @@ pub fn parse_pat(&mut self, expected: Option<&'static str>) -> PResult<'a, P<Pat
         self.parse_pat_with_range_pat(true, expected)
     }
 
+    /// Parse a range-to pattern, e.g. `..X` and `..=X` for recovery.
+    fn parse_pat_range_to(&mut self, re: RangeEnd, form: &str) -> PResult<'a, PatKind> {
+        let lo = self.prev_span;
+        let end = self.parse_pat_range_end()?;
+        let range_span = lo.to(end.span);
+        let begin = self.mk_expr(range_span, ExprKind::Err, ThinVec::new());
+
+        self.diagnostic()
+            .struct_span_err(range_span, &format!("`{}X` range patterns are not supported", form))
+            .span_suggestion(
+                range_span,
+                "try using the minimum value for the type",
+                format!("MIN{}{}", form, pprust::expr_to_string(&end)),
+                Applicability::HasPlaceholders,
+            )
+            .emit();
+
+        Ok(PatKind::Range(begin, end, respan(lo, re)))
+    }
+
+    /// Parse the end of a `X..Y`, `X..=Y`, or `X...Y` range pattern  or recover
+    /// if that end is missing treating it as `X..`, `X..=`, or `X...` respectively.
+    fn parse_pat_range_end_opt(&mut self, begin: &Expr, form: &str) -> PResult<'a, P<Expr>> {
+        if self.is_pat_range_end_start() {
+            // Parsing e.g. `X..=Y`.
+            self.parse_pat_range_end()
+        } else {
+            // Parsing e.g. `X..`.
+            let range_span = begin.span.to(self.prev_span);
+
+            self.diagnostic()
+                .struct_span_err(
+                    range_span,
+                    &format!("`X{}` range patterns are not supported", form),
+                )
+                .span_suggestion(
+                    range_span,
+                    "try using the maximum value for the type",
+                    format!("{}{}MAX", pprust::expr_to_string(&begin), form),
+                    Applicability::HasPlaceholders,
+                )
+                .emit();
+
+            Ok(self.mk_expr(range_span, ExprKind::Err, ThinVec::new()))
+        }
+    }
+
     /// Parses a pattern, with a setting whether modern range patterns (e.g., `a..=b`, `a..b` are
     /// allowed).
     fn parse_pat_with_range_pat(
@@ -3934,20 +3884,41 @@ fn parse_pat_with_range_pat(
                 pat = PatKind::Ref(subpat, mutbl);
             }
             token::OpenDelim(token::Paren) => {
-                // Parse (pat,pat,pat,...) as tuple pattern
-                let (fields, ddpos, trailing_comma) = self.parse_parenthesized_pat_list()?;
-                pat = if fields.len() == 1 && ddpos.is_none() && !trailing_comma {
+                // Parse a tuple or parenthesis pattern.
+                let (fields, trailing_comma) = self.parse_paren_comma_seq(|p| p.parse_pat(None))?;
+
+                // Here, `(pat,)` is a tuple pattern.
+                // For backward compatibility, `(..)` is a tuple pattern as well.
+                pat = if fields.len() == 1 && !(trailing_comma || fields[0].is_rest()) {
                     PatKind::Paren(fields.into_iter().nth(0).unwrap())
                 } else {
-                    PatKind::Tuple(fields, ddpos)
+                    PatKind::Tuple(fields)
                 };
             }
             token::OpenDelim(token::Bracket) => {
-                // Parse [pat,pat,...] as slice pattern
+                // Parse `[pat, pat,...]` as a slice pattern.
+                let (slice, _) = self.parse_delim_comma_seq(token::Bracket, |p| p.parse_pat(None))?;
+                pat = PatKind::Slice(slice);
+            }
+            token::DotDot => {
                 self.bump();
-                let (before, slice, after) = self.parse_pat_vec_elements()?;
-                self.expect(&token::CloseDelim(token::Bracket))?;
-                pat = PatKind::Slice(before, slice, after);
+                pat = if self.is_pat_range_end_start() {
+                    // Parse `..42` for recovery.
+                    self.parse_pat_range_to(RangeEnd::Excluded, "..")?
+                } else {
+                    // A rest pattern `..`.
+                    PatKind::Rest
+                };
+            }
+            token::DotDotEq => {
+                // Parse `..=42` for recovery.
+                self.bump();
+                pat = self.parse_pat_range_to(RangeEnd::Included(RangeSyntax::DotDotEq), "..=")?;
+            }
+            token::DotDotDot => {
+                // Parse `...42` for recovery.
+                self.bump();
+                pat = self.parse_pat_range_to(RangeEnd::Included(RangeSyntax::DotDotDot), "...")?;
             }
             // At this point, token != &, &&, (, [
             _ => if self.eat_keyword(kw::Underscore) {
@@ -4004,10 +3975,10 @@ fn parse_pat_with_range_pat(
                         pat = PatKind::Mac(mac);
                     }
                     token::DotDotDot | token::DotDotEq | token::DotDot => {
-                        let end_kind = match self.token.kind {
-                            token::DotDot => RangeEnd::Excluded,
-                            token::DotDotDot => RangeEnd::Included(RangeSyntax::DotDotDot),
-                            token::DotDotEq => RangeEnd::Included(RangeSyntax::DotDotEq),
+                        let (end_kind, form) = match self.token.kind {
+                            token::DotDot => (RangeEnd::Excluded, ".."),
+                            token::DotDotDot => (RangeEnd::Included(RangeSyntax::DotDotDot), "..."),
+                            token::DotDotEq => (RangeEnd::Included(RangeSyntax::DotDotEq), "..="),
                             _ => panic!("can only parse `..`/`...`/`..=` for ranges \
                                          (checked above)"),
                         };
@@ -4016,9 +3987,8 @@ fn parse_pat_with_range_pat(
                         let span = lo.to(self.prev_span);
                         let begin = self.mk_expr(span, ExprKind::Path(qself, path), ThinVec::new());
                         self.bump();
-                        let end = self.parse_pat_range_end()?;
-                        let op = Spanned { span: op_span, node: end_kind };
-                        pat = PatKind::Range(begin, end, op);
+                        let end = self.parse_pat_range_end_opt(&begin, form)?;
+                        pat = PatKind::Range(begin, end, respan(op_span, end_kind));
                     }
                     token::OpenDelim(token::Brace) => {
                         if qself.is_some() {
@@ -4045,8 +4015,8 @@ fn parse_pat_with_range_pat(
                             return Err(err);
                         }
                         // Parse tuple struct or enum pattern
-                        let (fields, ddpos, _) = self.parse_parenthesized_pat_list()?;
-                        pat = PatKind::TupleStruct(path, fields, ddpos)
+                        let (fields, _) = self.parse_paren_comma_seq(|p| p.parse_pat(None))?;
+                        pat = PatKind::TupleStruct(path, fields)
                     }
                     _ => pat = PatKind::Path(qself, path),
                 }
@@ -4057,19 +4027,18 @@ fn parse_pat_with_range_pat(
                         let op_span = self.token.span;
                         if self.check(&token::DotDot) || self.check(&token::DotDotEq) ||
                                 self.check(&token::DotDotDot) {
-                            let end_kind = if self.eat(&token::DotDotDot) {
-                                RangeEnd::Included(RangeSyntax::DotDotDot)
+                            let (end_kind, form) = if self.eat(&token::DotDotDot) {
+                                (RangeEnd::Included(RangeSyntax::DotDotDot), "...")
                             } else if self.eat(&token::DotDotEq) {
-                                RangeEnd::Included(RangeSyntax::DotDotEq)
+                                (RangeEnd::Included(RangeSyntax::DotDotEq), "..=")
                             } else if self.eat(&token::DotDot) {
-                                RangeEnd::Excluded
+                                (RangeEnd::Excluded, "..")
                             } else {
                                 panic!("impossible case: we already matched \
                                         on a range-operator token")
                             };
-                            let end = self.parse_pat_range_end()?;
-                            let op = Spanned { span: op_span, node: end_kind };
-                            pat = PatKind::Range(begin, end, op);
+                            let end = self.parse_pat_range_end_opt(&begin, form)?;
+                            pat = PatKind::Range(begin, end, respan(op_span, end_kind))
                         } else {
                             pat = PatKind::Lit(begin);
                         }
@@ -5359,59 +5328,48 @@ fn parse_where_clause(&mut self) -> PResult<'a, WhereClause> {
 
     fn parse_fn_args(&mut self, named_args: bool, allow_c_variadic: bool)
                      -> PResult<'a, (Vec<Arg> , bool)> {
-        self.expect(&token::OpenDelim(token::Paren))?;
-
         let sp = self.token.span;
         let mut c_variadic = false;
-        let (args, recovered): (Vec<Option<Arg>>, bool) =
-            self.parse_seq_to_before_end(
-                &token::CloseDelim(token::Paren),
-                SeqSep::trailing_allowed(token::Comma),
-                |p| {
-                    let do_not_enforce_named_arguments_for_c_variadic =
-                        |token: &token::Token| -> bool {
-                            if token == &token::DotDotDot {
-                                false
-                            } else {
-                                named_args
-                            }
-                        };
-                    match p.parse_arg_general(
-                        false,
-                        allow_c_variadic,
-                        do_not_enforce_named_arguments_for_c_variadic
-                    ) {
-                        Ok(arg) => {
-                            if let TyKind::CVarArgs = arg.ty.node {
-                                c_variadic = true;
-                                if p.token != token::CloseDelim(token::Paren) {
-                                    let span = p.token.span;
-                                    p.span_err(span,
-                                        "`...` must be the last argument of a C-variadic function");
-                                    Ok(None)
-                                } else {
-                                    Ok(Some(arg))
-                                }
-                            } else {
-                                Ok(Some(arg))
-                            }
-                        },
-                        Err(mut e) => {
-                            e.emit();
-                            let lo = p.prev_span;
-                            // Skip every token until next possible arg or end.
-                            p.eat_to_tokens(&[&token::Comma, &token::CloseDelim(token::Paren)]);
-                            // Create a placeholder argument for proper arg count (issue #34264).
-                            let span = lo.to(p.prev_span);
-                            Ok(Some(dummy_arg(Ident::new(kw::Invalid, span))))
+        let (args, _): (Vec<Option<Arg>>, _) = self.parse_paren_comma_seq(|p| {
+            let do_not_enforce_named_arguments_for_c_variadic =
+                |token: &token::Token| -> bool {
+                    if token == &token::DotDotDot {
+                        false
+                    } else {
+                        named_args
+                    }
+                };
+            match p.parse_arg_general(
+                false,
+                allow_c_variadic,
+                do_not_enforce_named_arguments_for_c_variadic
+            ) {
+                Ok(arg) => {
+                    if let TyKind::CVarArgs = arg.ty.node {
+                        c_variadic = true;
+                        if p.token != token::CloseDelim(token::Paren) {
+                            let span = p.token.span;
+                            p.span_err(span,
+                                "`...` must be the last argument of a C-variadic function");
+                            Ok(None)
+                        } else {
+                            Ok(Some(arg))
                         }
+                    } else {
+                        Ok(Some(arg))
                     }
+                },
+                Err(mut e) => {
+                    e.emit();
+                    let lo = p.prev_span;
+                    // Skip every token until next possible arg or end.
+                    p.eat_to_tokens(&[&token::Comma, &token::CloseDelim(token::Paren)]);
+                    // Create a placeholder argument for proper arg count (issue #34264).
+                    let span = lo.to(p.prev_span);
+                    Ok(Some(dummy_arg(Ident::new(kw::Invalid, span))))
                 }
-            )?;
-
-        if !recovered {
-            self.eat(&token::CloseDelim(token::Paren));
-        }
+            }
+        })?;
 
         let args: Vec<_> = args.into_iter().filter_map(|x| x).collect();
 
@@ -5573,7 +5531,7 @@ fn parse_fn_decl_with_self<F>(&mut self, parse_arg_fn: F) -> PResult<'a, P<FnDec
                 (vec![self_arg], false)
             } else if self.eat(&token::Comma) {
                 let mut fn_inputs = vec![self_arg];
-                let (mut input, recovered) = self.parse_seq_to_before_end(
+                let (mut input, _, recovered) = self.parse_seq_to_before_end(
                     &token::CloseDelim(token::Paren), sep, parse_arg_fn)?;
                 fn_inputs.append(&mut input);
                 (fn_inputs, recovered)
@@ -5584,7 +5542,9 @@ fn parse_fn_decl_with_self<F>(&mut self, parse_arg_fn: F) -> PResult<'a, P<FnDec
                 }
             }
         } else {
-            self.parse_seq_to_before_end(&token::CloseDelim(token::Paren), sep, parse_arg_fn)?
+            let (input, _, recovered) =
+                self.parse_seq_to_before_end(&token::CloseDelim(token::Paren), sep, parse_arg_fn)?;
+            (input, recovered)
         };
 
         if !recovered {
@@ -6185,26 +6145,20 @@ fn parse_record_struct_body(
     fn parse_tuple_struct_body(&mut self) -> PResult<'a, Vec<StructField>> {
         // This is the case where we find `struct Foo<T>(T) where T: Copy;`
         // Unit like structs are handled in parse_item_struct function
-        let fields = self.parse_unspanned_seq(
-            &token::OpenDelim(token::Paren),
-            &token::CloseDelim(token::Paren),
-            SeqSep::trailing_allowed(token::Comma),
-            |p| {
-                let attrs = p.parse_outer_attributes()?;
-                let lo = p.token.span;
-                let vis = p.parse_visibility(true)?;
-                let ty = p.parse_ty()?;
-                Ok(StructField {
-                    span: lo.to(ty.span),
-                    vis,
-                    ident: None,
-                    id: ast::DUMMY_NODE_ID,
-                    ty,
-                    attrs,
-                })
-            })?;
-
-        Ok(fields)
+        self.parse_paren_comma_seq(|p| {
+            let attrs = p.parse_outer_attributes()?;
+            let lo = p.token.span;
+            let vis = p.parse_visibility(true)?;
+            let ty = p.parse_ty()?;
+            Ok(StructField {
+                span: lo.to(ty.span),
+                vis,
+                ident: None,
+                id: ast::DUMMY_NODE_ID,
+                ty,
+                attrs,
+            })
+        }).map(|(r, _)| r)
     }
 
     /// Parses a structure field declaration.
@@ -7786,11 +7740,8 @@ fn parse_use_tree(&mut self) -> PResult<'a, UseTree> {
     /// USE_TREE_LIST = Ã˜ | (USE_TREE `,`)* USE_TREE [`,`]
     /// ```
     fn parse_use_tree_list(&mut self) -> PResult<'a, Vec<(UseTree, ast::NodeId)>> {
-        self.parse_unspanned_seq(&token::OpenDelim(token::Brace),
-                                 &token::CloseDelim(token::Brace),
-                                 SeqSep::trailing_allowed(token::Comma), |this| {
-            Ok((this.parse_use_tree()?, ast::DUMMY_NODE_ID))
-        })
+        self.parse_delim_comma_seq(token::Brace, |p| Ok((p.parse_use_tree()?, ast::DUMMY_NODE_ID)))
+            .map(|(r, _)| r)
     }
 
     fn parse_rename(&mut self) -> PResult<'a, Option<Ident>> {
index 16e0bace925842eb69eb6d762259f2a1975ed8b0..c7be0b123023d501b86cb8665163af4ca724f5d6 100644 (file)
@@ -10,7 +10,6 @@
 use crate::print::pp::{self, Breaks};
 use crate::print::pp::Breaks::{Consistent, Inconsistent};
 use crate::ptr::P;
-use crate::std_inject;
 use crate::symbol::{kw, sym};
 use crate::tokenstream::{self, TokenStream, TokenTree};
 
@@ -114,7 +113,7 @@ pub fn print_crate<'a>(cm: &'a SourceMap,
         is_expanded,
     };
 
-    if is_expanded && std_inject::injected_crate_name().is_some() {
+    if is_expanded && sess.injected_crate_name.try_get().is_some() {
         // We need to print `#![no_std]` (and its feature gate) so that
         // compiling pretty-printed source won't inject libstd again.
         // However we don't want these attributes in the AST because
@@ -2369,22 +2368,10 @@ fn print_qpath(&mut self,
                     self.print_pat(p);
                 }
             }
-            PatKind::TupleStruct(ref path, ref elts, ddpos) => {
+            PatKind::TupleStruct(ref path, ref elts) => {
                 self.print_path(path, true, 0);
                 self.popen();
-                if let Some(ddpos) = ddpos {
-                    self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(p));
-                    if ddpos != 0 {
-                        self.word_space(",");
-                    }
-                    self.s.word("..");
-                    if ddpos != elts.len() {
-                        self.s.word(",");
-                        self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(p));
-                    }
-                } else {
-                    self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(p));
-                }
+                self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(p));
                 self.pclose();
             }
             PatKind::Path(None, ref path) => {
@@ -2416,23 +2403,11 @@ fn print_qpath(&mut self,
                 self.s.space();
                 self.s.word("}");
             }
-            PatKind::Tuple(ref elts, ddpos) => {
+            PatKind::Tuple(ref elts) => {
                 self.popen();
-                if let Some(ddpos) = ddpos {
-                    self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(p));
-                    if ddpos != 0 {
-                        self.word_space(",");
-                    }
-                    self.s.word("..");
-                    if ddpos != elts.len() {
-                        self.s.word(",");
-                        self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(p));
-                    }
-                } else {
-                    self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(p));
-                    if elts.len() == 1 {
-                        self.s.word(",");
-                    }
+                self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(p));
+                if elts.len() == 1 {
+                    self.s.word(",");
                 }
                 self.pclose();
             }
@@ -2458,26 +2433,12 @@ fn print_qpath(&mut self,
                 }
                 self.print_expr(end);
             }
-            PatKind::Slice(ref before, ref slice, ref after) => {
+            PatKind::Slice(ref elts) => {
                 self.s.word("[");
-                self.commasep(Inconsistent,
-                                   &before[..],
-                                   |s, p| s.print_pat(p));
-                if let Some(ref p) = *slice {
-                    if !before.is_empty() { self.word_space(","); }
-                    if let PatKind::Wild = p.node {
-                        // Print nothing
-                    } else {
-                        self.print_pat(p);
-                    }
-                    self.s.word("..");
-                    if !after.is_empty() { self.word_space(","); }
-                }
-                self.commasep(Inconsistent,
-                                   &after[..],
-                                   |s, p| s.print_pat(p));
+                self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(p));
                 self.s.word("]");
             }
+            PatKind::Rest => self.s.word(".."),
             PatKind::Paren(ref inner) => {
                 self.popen();
                 self.print_pat(inner);
diff --git a/src/libsyntax/std_inject.rs b/src/libsyntax/std_inject.rs
deleted file mode 100644 (file)
index 3fba81c..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-use crate::ast;
-use crate::attr;
-use crate::edition::Edition;
-use crate::ext::hygiene::{ExpnId, MacroKind};
-use crate::symbol::{Ident, Symbol, kw, sym};
-use crate::source_map::{ExpnInfo, ExpnKind, dummy_spanned, respan};
-use crate::ptr::P;
-use crate::tokenstream::TokenStream;
-
-use std::cell::Cell;
-use std::iter;
-use syntax_pos::DUMMY_SP;
-
-pub fn injected_crate_name() -> Option<&'static str> {
-    INJECTED_CRATE_NAME.with(|name| name.get())
-}
-
-thread_local! {
-    // A `Symbol` might make more sense here, but it doesn't work, probably for
-    // reasons relating to the use of thread-local storage for the Symbol
-    // interner.
-    static INJECTED_CRATE_NAME: Cell<Option<&'static str>> = Cell::new(None);
-}
-
-pub fn maybe_inject_crates_ref(
-    mut krate: ast::Crate,
-    alt_std_name: Option<&str>,
-    edition: Edition,
-) -> ast::Crate {
-    let rust_2018 = edition >= Edition::Edition2018;
-
-    // the first name in this list is the crate name of the crate with the prelude
-    let names: &[&str] = if attr::contains_name(&krate.attrs, sym::no_core) {
-        return krate;
-    } else if attr::contains_name(&krate.attrs, sym::no_std) {
-        if attr::contains_name(&krate.attrs, sym::compiler_builtins) {
-            &["core"]
-        } else {
-            &["core", "compiler_builtins"]
-        }
-    } else {
-        &["std"]
-    };
-
-    // .rev() to preserve ordering above in combination with insert(0, ...)
-    let alt_std_name = alt_std_name.map(Symbol::intern);
-    for orig_name_str in names.iter().rev() {
-        // HACK(eddyb) gensym the injected crates on the Rust 2018 edition,
-        // so they don't accidentally interfere with the new import paths.
-        let orig_name_sym = Symbol::intern(orig_name_str);
-        let orig_name_ident = Ident::with_empty_ctxt(orig_name_sym);
-        let (rename, orig_name) = if rust_2018 {
-            (orig_name_ident.gensym(), Some(orig_name_sym))
-        } else {
-            (orig_name_ident, None)
-        };
-        krate.module.items.insert(0, P(ast::Item {
-            attrs: vec![attr::mk_attr_outer(
-                DUMMY_SP,
-                attr::mk_attr_id(),
-                attr::mk_word_item(ast::Ident::with_empty_ctxt(sym::macro_use))
-            )],
-            vis: dummy_spanned(ast::VisibilityKind::Inherited),
-            node: ast::ItemKind::ExternCrate(alt_std_name.or(orig_name)),
-            ident: rename,
-            id: ast::DUMMY_NODE_ID,
-            span: DUMMY_SP,
-            tokens: None,
-        }));
-    }
-
-    // the crates have been injected, the assumption is that the first one is the one with
-    // the prelude.
-    let name = names[0];
-
-    INJECTED_CRATE_NAME.with(|opt_name| opt_name.set(Some(name)));
-
-    let span = DUMMY_SP.fresh_expansion(ExpnId::root(), ExpnInfo::allow_unstable(
-        ExpnKind::Macro(MacroKind::Attr, sym::std_inject), DUMMY_SP, edition,
-        [sym::prelude_import][..].into(),
-    ));
-
-    krate.module.items.insert(0, P(ast::Item {
-        attrs: vec![ast::Attribute {
-            style: ast::AttrStyle::Outer,
-            path: ast::Path::from_ident(ast::Ident::new(sym::prelude_import, span)),
-            tokens: TokenStream::empty(),
-            id: attr::mk_attr_id(),
-            is_sugared_doc: false,
-            span,
-        }],
-        vis: respan(span.shrink_to_lo(), ast::VisibilityKind::Inherited),
-        node: ast::ItemKind::Use(P(ast::UseTree {
-            prefix: ast::Path {
-                segments: iter::once(ast::Ident::with_empty_ctxt(kw::PathRoot))
-                    .chain(
-                        [name, "prelude", "v1"].iter().cloned()
-                            .map(ast::Ident::from_str)
-                    ).map(ast::PathSegment::from_ident).collect(),
-                span,
-            },
-            kind: ast::UseTreeKind::Glob,
-            span,
-        })),
-        id: ast::DUMMY_NODE_ID,
-        ident: ast::Ident::invalid(),
-        span,
-        tokens: None,
-    }));
-
-    krate
-}
diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs
deleted file mode 100644 (file)
index 2ada710..0000000
+++ /dev/null
@@ -1,424 +0,0 @@
-// Code that generates a test runner to run all the tests in a crate
-
-#![allow(dead_code)]
-#![allow(unused_imports)]
-
-use HasTestSignature::*;
-
-use std::iter;
-use std::slice;
-use std::mem;
-use std::vec;
-
-use log::debug;
-use smallvec::{smallvec, SmallVec};
-use syntax_pos::{DUMMY_SP, NO_EXPANSION, Span, SourceFile, BytePos};
-
-use crate::attr::{self, HasAttrs};
-use crate::source_map::{self, SourceMap, ExpnInfo, ExpnKind, dummy_spanned, respan};
-use crate::config;
-use crate::entry::{self, EntryPointType};
-use crate::ext::base::{ExtCtxt, Resolver};
-use crate::ext::build::AstBuilder;
-use crate::ext::expand::ExpansionConfig;
-use crate::ext::hygiene::{self, ExpnId, SyntaxContext, MacroKind};
-use crate::mut_visit::{*, ExpectOne};
-use crate::feature_gate::Features;
-use crate::util::map_in_place::MapInPlace;
-use crate::parse::{token, ParseSess};
-use crate::ast::{self, Ident};
-use crate::ptr::P;
-use crate::symbol::{self, Symbol, kw, sym};
-use crate::ThinVec;
-
-struct Test {
-    span: Span,
-    path: Vec<Ident>,
-}
-
-struct TestCtxt<'a> {
-    span_diagnostic: &'a errors::Handler,
-    path: Vec<Ident>,
-    ext_cx: ExtCtxt<'a>,
-    test_cases: Vec<Test>,
-    reexport_test_harness_main: Option<Symbol>,
-    is_libtest: bool,
-    features: &'a Features,
-    test_runner: Option<ast::Path>,
-
-    // top-level re-export submodule, filled out after folding is finished
-    toplevel_reexport: Option<Ident>,
-}
-
-// Traverse the crate, collecting all the test functions, eliding any
-// existing main functions, and synthesizing a main test harness
-pub fn modify_for_testing(sess: &ParseSess,
-                          resolver: &mut dyn Resolver,
-                          should_test: bool,
-                          krate: &mut ast::Crate,
-                          span_diagnostic: &errors::Handler,
-                          features: &Features) {
-    // Check for #[reexport_test_harness_main = "some_name"] which
-    // creates a `use __test::main as some_name;`. This needs to be
-    // unconditional, so that the attribute is still marked as used in
-    // non-test builds.
-    let reexport_test_harness_main =
-        attr::first_attr_value_str_by_name(&krate.attrs, sym::reexport_test_harness_main);
-
-    // Do this here so that the test_runner crate attribute gets marked as used
-    // even in non-test builds
-    let test_runner = get_test_runner(span_diagnostic, &krate);
-
-    if should_test {
-        generate_test_harness(sess, resolver, reexport_test_harness_main,
-                              krate, span_diagnostic, features, test_runner)
-    }
-}
-
-struct TestHarnessGenerator<'a> {
-    cx: TestCtxt<'a>,
-    tests: Vec<Ident>,
-
-    // submodule name, gensym'd identifier for re-exports
-    tested_submods: Vec<(Ident, Ident)>,
-}
-
-impl<'a> MutVisitor for TestHarnessGenerator<'a> {
-    fn visit_crate(&mut self, c: &mut ast::Crate) {
-        noop_visit_crate(c, self);
-
-        // Create a main function to run our tests
-        let test_main = {
-            let unresolved = mk_main(&mut self.cx);
-            self.cx.ext_cx.monotonic_expander().flat_map_item(unresolved).pop().unwrap()
-        };
-
-        c.module.items.push(test_main);
-    }
-
-    fn flat_map_item(&mut self, i: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
-        let ident = i.ident;
-        if ident.name != kw::Invalid {
-            self.cx.path.push(ident);
-        }
-        debug!("current path: {}", path_name_i(&self.cx.path));
-
-        let mut item = i.into_inner();
-        if is_test_case(&item) {
-            debug!("this is a test item");
-
-            let test = Test {
-                span: item.span,
-                path: self.cx.path.clone(),
-            };
-            self.cx.test_cases.push(test);
-            self.tests.push(item.ident);
-        }
-
-        // We don't want to recurse into anything other than mods, since
-        // mods or tests inside of functions will break things
-        if let ast::ItemKind::Mod(mut module) = item.node {
-            let tests = mem::take(&mut self.tests);
-            let tested_submods = mem::take(&mut self.tested_submods);
-            noop_visit_mod(&mut module, self);
-            let tests = mem::replace(&mut self.tests, tests);
-            let tested_submods = mem::replace(&mut self.tested_submods, tested_submods);
-
-            if !tests.is_empty() || !tested_submods.is_empty() {
-                let (it, sym) = mk_reexport_mod(&mut self.cx, item.id, tests, tested_submods);
-                module.items.push(it);
-
-                if !self.cx.path.is_empty() {
-                    self.tested_submods.push((self.cx.path[self.cx.path.len()-1], sym));
-                } else {
-                    debug!("pushing nothing, sym: {:?}", sym);
-                    self.cx.toplevel_reexport = Some(sym);
-                }
-            }
-            item.node = ast::ItemKind::Mod(module);
-        }
-        if ident.name != kw::Invalid {
-            self.cx.path.pop();
-        }
-        smallvec![P(item)]
-    }
-
-    fn visit_mac(&mut self, _mac: &mut ast::Mac) {
-        // Do nothing.
-    }
-}
-
-/// A folder used to remove any entry points (like fn main) because the harness
-/// generator will provide its own
-struct EntryPointCleaner {
-    // Current depth in the ast
-    depth: usize,
-}
-
-impl MutVisitor for EntryPointCleaner {
-    fn flat_map_item(&mut self, i: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
-        self.depth += 1;
-        let item = noop_flat_map_item(i, self).expect_one("noop did something");
-        self.depth -= 1;
-
-        // Remove any #[main] or #[start] from the AST so it doesn't
-        // clash with the one we're going to add, but mark it as
-        // #[allow(dead_code)] to avoid printing warnings.
-        let item = match entry::entry_point_type(&item, self.depth) {
-            EntryPointType::MainNamed |
-            EntryPointType::MainAttr |
-            EntryPointType::Start =>
-                item.map(|ast::Item {id, ident, attrs, node, vis, span, tokens}| {
-                    let allow_ident = Ident::with_empty_ctxt(sym::allow);
-                    let dc_nested = attr::mk_nested_word_item(Ident::from_str("dead_code"));
-                    let allow_dead_code_item = attr::mk_list_item(DUMMY_SP, allow_ident,
-                                                                  vec![dc_nested]);
-                    let allow_dead_code = attr::mk_attr_outer(DUMMY_SP,
-                                                              attr::mk_attr_id(),
-                                                              allow_dead_code_item);
-
-                    ast::Item {
-                        id,
-                        ident,
-                        attrs: attrs.into_iter()
-                            .filter(|attr| {
-                                !attr.check_name(sym::main) && !attr.check_name(sym::start)
-                            })
-                            .chain(iter::once(allow_dead_code))
-                            .collect(),
-                        node,
-                        vis,
-                        span,
-                        tokens,
-                    }
-                }),
-            EntryPointType::None |
-            EntryPointType::OtherMain => item,
-        };
-
-        smallvec![item]
-    }
-
-    fn visit_mac(&mut self, _mac: &mut ast::Mac) {
-        // Do nothing.
-    }
-}
-
-/// Creates an item (specifically a module) that "pub use"s the tests passed in.
-/// Each tested submodule will contain a similar reexport module that we will export
-/// under the name of the original module. That is, `submod::__test_reexports` is
-/// reexported like so `pub use submod::__test_reexports as submod`.
-fn mk_reexport_mod(cx: &mut TestCtxt<'_>,
-                   parent: ast::NodeId,
-                   tests: Vec<Ident>,
-                   tested_submods: Vec<(Ident, Ident)>)
-                   -> (P<ast::Item>, Ident) {
-    let super_ = Ident::with_empty_ctxt(kw::Super);
-
-    let items = tests.into_iter().map(|r| {
-        cx.ext_cx.item_use_simple(DUMMY_SP, dummy_spanned(ast::VisibilityKind::Public),
-                                  cx.ext_cx.path(DUMMY_SP, vec![super_, r]))
-    }).chain(tested_submods.into_iter().map(|(r, sym)| {
-        let path = cx.ext_cx.path(DUMMY_SP, vec![super_, r, sym]);
-        cx.ext_cx.item_use_simple_(DUMMY_SP, dummy_spanned(ast::VisibilityKind::Public),
-                                   Some(r), path)
-    })).collect();
-
-    let reexport_mod = ast::Mod {
-        inline: true,
-        inner: DUMMY_SP,
-        items,
-    };
-
-    let name = Ident::from_str("__test_reexports").gensym();
-    let parent = if parent == ast::DUMMY_NODE_ID { ast::CRATE_NODE_ID } else { parent };
-    cx.ext_cx.current_expansion.id = cx.ext_cx.resolver.get_module_scope(parent);
-    let it = cx.ext_cx.monotonic_expander().flat_map_item(P(ast::Item {
-        ident: name,
-        attrs: Vec::new(),
-        id: ast::DUMMY_NODE_ID,
-        node: ast::ItemKind::Mod(reexport_mod),
-        vis: dummy_spanned(ast::VisibilityKind::Public),
-        span: DUMMY_SP,
-        tokens: None,
-    })).pop().unwrap();
-
-    (it, name)
-}
-
-/// Crawl over the crate, inserting test reexports and the test main function
-fn generate_test_harness(sess: &ParseSess,
-                         resolver: &mut dyn Resolver,
-                         reexport_test_harness_main: Option<Symbol>,
-                         krate: &mut ast::Crate,
-                         sd: &errors::Handler,
-                         features: &Features,
-                         test_runner: Option<ast::Path>) {
-    // Remove the entry points
-    let mut cleaner = EntryPointCleaner { depth: 0 };
-    cleaner.visit_crate(krate);
-
-    let mut econfig = ExpansionConfig::default("test".to_string());
-    econfig.features = Some(features);
-
-    let cx = TestCtxt {
-        span_diagnostic: sd,
-        ext_cx: ExtCtxt::new(sess, econfig, resolver),
-        path: Vec::new(),
-        test_cases: Vec::new(),
-        reexport_test_harness_main,
-        // N.B., doesn't consider the value of `--crate-name` passed on the command line.
-        is_libtest: attr::find_crate_name(&krate.attrs)
-            .map(|s| s == sym::test).unwrap_or(false),
-        toplevel_reexport: None,
-        features,
-        test_runner
-    };
-
-    TestHarnessGenerator {
-        cx,
-        tests: Vec::new(),
-        tested_submods: Vec::new(),
-    }.visit_crate(krate);
-}
-
-enum HasTestSignature {
-    Yes,
-    No(BadTestSignature),
-}
-
-#[derive(PartialEq)]
-enum BadTestSignature {
-    NotEvenAFunction,
-    WrongTypeSignature,
-    NoArgumentsAllowed,
-    ShouldPanicOnlyWithNoArgs,
-}
-
-/// Creates a function item for use as the main function of a test build.
-/// This function will call the `test_runner` as specified by the crate attribute
-fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
-    // Writing this out by hand:
-    //        pub fn main() {
-    //            #![main]
-    //            test::test_main_static(&[..tests]);
-    //        }
-    let sp = DUMMY_SP.fresh_expansion(ExpnId::root(), ExpnInfo::allow_unstable(
-        ExpnKind::Macro(MacroKind::Attr, sym::test_case), DUMMY_SP, cx.ext_cx.parse_sess.edition,
-        [sym::main, sym::test, sym::rustc_attrs][..].into(),
-    ));
-    let ecx = &cx.ext_cx;
-    let test_id = Ident::with_empty_ctxt(sym::test);
-
-    // test::test_main_static(...)
-    let mut test_runner = cx.test_runner.clone().unwrap_or(
-        ecx.path(sp, vec![
-            test_id, ecx.ident_of("test_main_static")
-        ]));
-
-    test_runner.span = sp;
-
-    let test_main_path_expr = ecx.expr_path(test_runner);
-    let call_test_main = ecx.expr_call(sp, test_main_path_expr,
-                                       vec![mk_tests_slice(cx)]);
-    let call_test_main = ecx.stmt_expr(call_test_main);
-
-    // #![main]
-    let main_meta = ecx.meta_word(sp, sym::main);
-    let main_attr = ecx.attribute(sp, main_meta);
-
-    // extern crate test as test_gensym
-    let test_extern_stmt = ecx.stmt_item(sp, ecx.item(sp,
-        test_id,
-        vec![],
-        ast::ItemKind::ExternCrate(None)
-    ));
-
-    // pub fn main() { ... }
-    let main_ret_ty = ecx.ty(sp, ast::TyKind::Tup(vec![]));
-
-    // If no test runner is provided we need to import the test crate
-    let main_body = if cx.test_runner.is_none() {
-        ecx.block(sp, vec![test_extern_stmt, call_test_main])
-    } else {
-        ecx.block(sp, vec![call_test_main])
-    };
-
-    let main = ast::ItemKind::Fn(ecx.fn_decl(vec![], ast::FunctionRetTy::Ty(main_ret_ty)),
-                           ast::FnHeader::default(),
-                           ast::Generics::default(),
-                           main_body);
-
-    // Honor the reexport_test_harness_main attribute
-    let main_id = match cx.reexport_test_harness_main {
-        Some(sym) => Ident::new(sym, sp),
-        None => Ident::from_str_and_span("main", sp).gensym(),
-    };
-
-    P(ast::Item {
-        ident: main_id,
-        attrs: vec![main_attr],
-        id: ast::DUMMY_NODE_ID,
-        node: main,
-        vis: dummy_spanned(ast::VisibilityKind::Public),
-        span: sp,
-        tokens: None,
-    })
-
-}
-
-fn path_name_i(idents: &[Ident]) -> String {
-    let mut path_name = "".to_string();
-    let mut idents_iter = idents.iter().peekable();
-    while let Some(ident) = idents_iter.next() {
-        path_name.push_str(&ident.as_str());
-        if idents_iter.peek().is_some() {
-            path_name.push_str("::")
-        }
-    }
-    path_name
-}
-
-/// Creates a slice containing every test like so:
-/// &[path::to::test1, path::to::test2]
-fn mk_tests_slice(cx: &TestCtxt<'_>) -> P<ast::Expr> {
-    debug!("building test vector from {} tests", cx.test_cases.len());
-    let ref ecx = cx.ext_cx;
-
-    ecx.expr_vec_slice(DUMMY_SP,
-        cx.test_cases.iter().map(|test| {
-            ecx.expr_addr_of(test.span,
-                ecx.expr_path(ecx.path(test.span, visible_path(cx, &test.path))))
-        }).collect())
-}
-
-/// Creates a path from the top-level __test module to the test via __test_reexports
-fn visible_path(cx: &TestCtxt<'_>, path: &[Ident]) -> Vec<Ident>{
-    let mut visible_path = vec![];
-    match cx.toplevel_reexport {
-        Some(id) => visible_path.push(id),
-        None => {
-            cx.span_diagnostic.bug("expected to find top-level re-export name, but found None");
-        }
-    }
-    visible_path.extend_from_slice(path);
-    visible_path
-}
-
-fn is_test_case(i: &ast::Item) -> bool {
-    attr::contains_name(&i.attrs, sym::rustc_test_marker)
-}
-
-fn get_test_runner(sd: &errors::Handler, krate: &ast::Crate) -> Option<ast::Path> {
-    let test_attr = attr::find_by_name(&krate.attrs, sym::test_runner)?;
-    test_attr.meta_item_list().map(|meta_list| {
-        if meta_list.len() != 1 {
-            sd.span_fatal(test_attr.span,
-                "`#![test_runner(..)]` accepts exactly 1 argument").raise()
-        }
-        match meta_list[0].meta_item() {
-            Some(meta_item) if meta_item.is_word() => meta_item.path.clone(),
-            _ => sd.span_fatal(test_attr.span, "`test_runner` argument must be a path").raise()
-        }
-    })
-}
index 9ec9550f93ab93f1d42c44ade154f630c80ac6ec..50be8c68f7f8c62e6f2641ee95714d7f67993375 100644 (file)
@@ -66,6 +66,7 @@ fn visit_item(&mut self, i: &'ast Item) { walk_item(self, i) }
     fn visit_local(&mut self, l: &'ast Local) { walk_local(self, l) }
     fn visit_block(&mut self, b: &'ast Block) { walk_block(self, b) }
     fn visit_stmt(&mut self, s: &'ast Stmt) { walk_stmt(self, s) }
+    fn visit_arg(&mut self, arg: &'ast Arg) { walk_arg(self, arg) }
     fn visit_arm(&mut self, a: &'ast Arm) { walk_arm(self, a) }
     fn visit_pat(&mut self, p: &'ast Pat) { walk_pat(self, p) }
     fn visit_anon_const(&mut self, c: &'ast AnonConst) { walk_anon_const(self, c) }
@@ -428,9 +429,9 @@ pub fn walk_assoc_ty_constraint<'a, V: Visitor<'a>>(visitor: &mut V,
 
 pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) {
     match pattern.node {
-        PatKind::TupleStruct(ref path, ref children, _) => {
+        PatKind::TupleStruct(ref path, ref elems) => {
             visitor.visit_path(path, pattern.id);
-            walk_list!(visitor, visit_pat, children);
+            walk_list!(visitor, visit_pat, elems);
         }
         PatKind::Path(ref opt_qself, ref path) => {
             if let Some(ref qself) = *opt_qself {
@@ -446,8 +447,8 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) {
                 visitor.visit_pat(&field.node.pat)
             }
         }
-        PatKind::Tuple(ref tuple_elements, _) => {
-            walk_list!(visitor, visit_pat, tuple_elements);
+        PatKind::Tuple(ref elems) => {
+            walk_list!(visitor, visit_pat, elems);
         }
         PatKind::Box(ref subpattern) |
         PatKind::Ref(ref subpattern, _) |
@@ -463,11 +464,9 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) {
             visitor.visit_expr(lower_bound);
             visitor.visit_expr(upper_bound);
         }
-        PatKind::Wild => (),
-        PatKind::Slice(ref prepatterns, ref slice_pattern, ref postpatterns) => {
-            walk_list!(visitor, visit_pat, prepatterns);
-            walk_list!(visitor, visit_pat, slice_pattern);
-            walk_list!(visitor, visit_pat, postpatterns);
+        PatKind::Wild | PatKind::Rest => {},
+        PatKind::Slice(ref elems) => {
+            walk_list!(visitor, visit_pat, elems);
         }
         PatKind::Mac(ref mac) => visitor.visit_mac(mac),
     }
@@ -549,12 +548,10 @@ pub fn walk_fn_ret_ty<'a, V: Visitor<'a>>(visitor: &mut V, ret_ty: &'a FunctionR
 }
 
 pub fn walk_fn_decl<'a, V: Visitor<'a>>(visitor: &mut V, function_declaration: &'a FnDecl) {
-    for argument in &function_declaration.inputs {
-        walk_list!(visitor, visit_attribute, argument.attrs.iter());
-        visitor.visit_pat(&argument.pat);
-        visitor.visit_ty(&argument.ty);
+    for arg in &function_declaration.inputs {
+        visitor.visit_arg(arg);
     }
-    visitor.visit_fn_ret_ty(&function_declaration.output)
+    visitor.visit_fn_ret_ty(&function_declaration.output);
 }
 
 pub fn walk_fn<'a, V>(visitor: &mut V, kind: FnKind<'a>, declaration: &'a FnDecl, _span: Span)
@@ -824,6 +821,12 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
     visitor.visit_expr_post(expression)
 }
 
+pub fn walk_arg<'a, V: Visitor<'a>>(visitor: &mut V, arg: &'a Arg) {
+    walk_list!(visitor, visit_attribute, arg.attrs.iter());
+    visitor.visit_pat(&arg.pat);
+    visitor.visit_ty(&arg.ty);
+}
+
 pub fn walk_arm<'a, V: Visitor<'a>>(visitor: &mut V, arm: &'a Arm) {
     walk_list!(visitor, visit_pat, &arm.pats);
     if let Some(ref e) = &arm.guard {
index eafbe6371a3c56f3332f983227643a74025edaf4..73310df305b32cb9892b5e5ce2e1327f6ac794c7 100644 (file)
@@ -10,11 +10,11 @@ path = "lib.rs"
 doctest = false
 
 [dependencies]
-fmt_macros = { path = "../libfmt_macros" }
 errors = { path = "../librustc_errors", package = "rustc_errors" }
-syntax = { path = "../libsyntax" }
-syntax_pos = { path = "../libsyntax_pos" }
+fmt_macros = { path = "../libfmt_macros" }
+log = "0.4"
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_target = { path = "../librustc_target" }
 smallvec = { version = "0.6.7", features = ["union", "may_dangle"] }
-log = "0.4"
+syntax = { path = "../libsyntax" }
+syntax_pos = { path = "../libsyntax_pos" }
diff --git a/src/libsyntax_ext/deriving/custom.rs b/src/libsyntax_ext/deriving/custom.rs
deleted file mode 100644 (file)
index 98465d7..0000000
+++ /dev/null
@@ -1,119 +0,0 @@
-use crate::proc_macro_impl::EXEC_STRATEGY;
-use crate::proc_macro_server;
-
-use errors::FatalError;
-use rustc_data_structures::sync::Lrc;
-use syntax::ast::{self, ItemKind, Attribute, Mac};
-use syntax::attr::{mark_used, mark_known};
-use syntax::source_map::Span;
-use syntax::ext::base::*;
-use syntax::parse;
-use syntax::parse::token;
-use syntax::tokenstream;
-use syntax::visit::Visitor;
-use syntax_pos::DUMMY_SP;
-
-struct MarkAttrs<'a>(&'a [ast::Name]);
-
-impl<'a> Visitor<'a> for MarkAttrs<'a> {
-    fn visit_attribute(&mut self, attr: &Attribute) {
-        if let Some(ident) = attr.ident() {
-            if self.0.contains(&ident.name) {
-                mark_used(attr);
-                mark_known(attr);
-            }
-        }
-    }
-
-    fn visit_mac(&mut self, _mac: &Mac) {}
-}
-
-pub struct ProcMacroDerive {
-    pub client: proc_macro::bridge::client::Client<
-        fn(proc_macro::TokenStream) -> proc_macro::TokenStream,
-    >,
-    pub attrs: Vec<ast::Name>,
-}
-
-impl MultiItemModifier for ProcMacroDerive {
-    fn expand(&self,
-              ecx: &mut ExtCtxt<'_>,
-              span: Span,
-              _meta_item: &ast::MetaItem,
-              item: Annotatable)
-              -> Vec<Annotatable> {
-        let item = match item {
-            Annotatable::Item(item) => item,
-            Annotatable::ImplItem(_) |
-            Annotatable::TraitItem(_) |
-            Annotatable::ForeignItem(_) |
-            Annotatable::Stmt(_) |
-            Annotatable::Expr(_) => {
-                ecx.span_err(span, "proc-macro derives may only be \
-                                    applied to a struct, enum, or union");
-                return Vec::new()
-            }
-        };
-        match item.node {
-            ItemKind::Struct(..) |
-            ItemKind::Enum(..) |
-            ItemKind::Union(..) => {},
-            _ => {
-                ecx.span_err(span, "proc-macro derives may only be \
-                                    applied to a struct, enum, or union");
-                return Vec::new()
-            }
-        }
-
-        // Mark attributes as known, and used.
-        MarkAttrs(&self.attrs).visit_item(&item);
-
-        let token = token::Interpolated(Lrc::new(token::NtItem(item)));
-        let input = tokenstream::TokenTree::token(token, DUMMY_SP).into();
-
-        let server = proc_macro_server::Rustc::new(ecx);
-        let stream = match self.client.run(&EXEC_STRATEGY, server, input) {
-            Ok(stream) => stream,
-            Err(e) => {
-                let msg = "proc-macro derive panicked";
-                let mut err = ecx.struct_span_fatal(span, msg);
-                if let Some(s) = e.as_str() {
-                    err.help(&format!("message: {}", s));
-                }
-
-                err.emit();
-                FatalError.raise();
-            }
-        };
-
-        let error_count_before = ecx.parse_sess.span_diagnostic.err_count();
-        let msg = "proc-macro derive produced unparseable tokens";
-
-        let mut parser = parse::stream_to_parser(ecx.parse_sess, stream, Some("proc-macro derive"));
-        let mut items = vec![];
-
-        loop {
-            match parser.parse_item() {
-                Ok(None) => break,
-                Ok(Some(item)) => {
-                    items.push(Annotatable::Item(item))
-                }
-                Err(mut err) => {
-                    // FIXME: handle this better
-                    err.cancel();
-                    ecx.struct_span_fatal(span, msg).emit();
-                    FatalError.raise();
-                }
-            }
-        }
-
-
-        // fail if there have been errors emitted
-        if ecx.parse_sess.span_diagnostic.err_count() > error_count_before {
-            ecx.struct_span_fatal(span, msg).emit();
-            FatalError.raise();
-        }
-
-        items
-    }
-}
index 12482f7248e90b5eb43a71ea90ecde045eb96ead..7f27769f236e29b97b4a1c098980254b5a1d8a8e 100644 (file)
@@ -1770,50 +1770,6 @@ pub fn cs_fold1<F, B>(use_foldl: bool,
     }
 }
 
-/// Call the method that is being derived on all the fields, and then
-/// process the collected results. i.e.
-///
-/// ```ignore (only-for-syntax-highlight)
-/// f(cx, span, vec![self_1.method(__arg_1_1, __arg_2_1),
-///                  self_2.method(__arg_1_2, __arg_2_2)])
-/// ```
-#[inline]
-pub fn cs_same_method<F>(f: F,
-                         mut enum_nonmatch_f: EnumNonMatchCollapsedFunc<'_>,
-                         cx: &mut ExtCtxt<'_>,
-                         trait_span: Span,
-                         substructure: &Substructure<'_>)
-                         -> P<Expr>
-    where F: FnOnce(&mut ExtCtxt<'_>, Span, Vec<P<Expr>>) -> P<Expr>
-{
-    match *substructure.fields {
-        EnumMatching(.., ref all_fields) |
-        Struct(_, ref all_fields) => {
-            // call self_n.method(other_1_n, other_2_n, ...)
-            let called = all_fields.iter()
-                .map(|field| {
-                    cx.expr_method_call(field.span,
-                                        field.self_.clone(),
-                                        substructure.method_ident,
-                                        field.other
-                                            .iter()
-                                            .map(|e| cx.expr_addr_of(field.span, e.clone()))
-                                            .collect())
-                })
-                .collect();
-
-            f(cx, trait_span, called)
-        }
-        EnumNonMatchingCollapsed(ref all_self_args, _, tuple) => {
-            enum_nonmatch_f(cx,
-                            trait_span,
-                            (&all_self_args[..], tuple),
-                            substructure.nonself_args)
-        }
-        StaticEnum(..) | StaticStruct(..) => cx.span_bug(trait_span, "static function in `derive`"),
-    }
-}
-
 /// Returns `true` if the type has no value fields
 /// (for an enum, no variant has any fields)
 pub fn is_type_without_fields(item: &Annotatable) -> bool {
index fef1b4eebcf965d30691b9937b9dcfa6196a401e..394beb141712d8b7ad254120a04677da7496e578 100644 (file)
@@ -18,6 +18,7 @@ pub enum PtrTy<'a> {
     /// &'lifetime mut
     Borrowed(Option<&'a str>, ast::Mutability),
     /// *mut
+    #[allow(dead_code)]
     Raw(ast::Mutability),
 }
 
@@ -107,13 +108,6 @@ pub enum Ty<'a> {
     Tuple(Vec<Ty<'a>>),
 }
 
-/// A const expression. Supports literals and blocks.
-#[derive(Clone, Eq, PartialEq)]
-pub enum Const {
-    Literal,
-    Block,
-}
-
 pub fn borrowed_ptrty<'r>() -> PtrTy<'r> {
     Borrowed(None, ast::Mutability::Immutable)
 }
index 1a86509928841f5e6e168b9dd7fd7ca4c7160be8..cad79917af284a623841f5e7104a718482f96a2b 100644 (file)
@@ -26,7 +26,6 @@
 pub mod hash;
 pub mod debug;
 pub mod default;
-pub mod custom;
 
 #[path="cmp/partial_eq.rs"]
 pub mod partial_eq;
index 9ec551b439529b0d35a69b11669601a0b9942992..5982a4df226c2d189062369b234c1ad3c7790781 100644 (file)
@@ -1,5 +1,3 @@
-#![allow(non_snake_case)]
-
 use syntax::register_long_diagnostics;
 
 // Error messages for EXXXX errors.
index 7940abed2459777a8e9d245525a549f28044f6fa..da11f2ff23fb572116802327e024463dfee53a34 100644 (file)
@@ -1,27 +1,19 @@
-//! Syntax extensions in the Rust compiler.
+//! This crate contains implementations of built-in macros and other code generating facilities
+//! injecting code into the crate before it is lowered to HIR.
 
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
 
-#![deny(rust_2018_idioms)]
-#![deny(unused_lifetimes)]
-
 #![feature(crate_visibility_modifier)]
 #![feature(decl_macro)]
+#![feature(mem_take)]
 #![feature(nll)]
-#![feature(proc_macro_diagnostic)]
-#![feature(proc_macro_internals)]
-#![feature(proc_macro_span)]
 #![feature(rustc_diagnostic_macros)]
-#![feature(unicode_internals)]
-
-extern crate proc_macro;
 
 use crate::deriving::*;
 
 use syntax::ast::Ident;
 use syntax::edition::Edition;
 use syntax::ext::base::{SyntaxExtension, SyntaxExtensionKind, MacroExpanderFn};
-use syntax::ext::source_util;
 use syntax::symbol::sym;
 
 mod error_codes;
 mod compile_error;
 mod concat;
 mod concat_idents;
+mod deriving;
 mod env;
 mod format;
 mod format_foreign;
 mod global_allocator;
 mod global_asm;
 mod log_syntax;
-mod proc_macro_server;
+mod source_util;
 mod test;
-mod test_case;
 mod trace_macros;
 
-pub mod deriving;
 pub mod plugin_macro_defs;
-pub mod proc_macro_decls;
-pub mod proc_macro_impl;
+pub mod proc_macro_harness;
+pub mod standard_library_imports;
+pub mod test_harness;
 
 pub fn register_builtin_macros(resolver: &mut dyn syntax::ext::base::Resolver, edition: Edition) {
     let mut register = |name, kind| resolver.register_builtin_macro(
@@ -93,7 +85,7 @@ pub fn register_builtin_macros(resolver: &mut dyn syntax::ext::base::Resolver, e
         bench: test::expand_bench,
         global_allocator: global_allocator::expand,
         test: test::expand_test,
-        test_case: test_case::expand,
+        test_case: test::expand_test_case,
     }
 
     register_derive! {
diff --git a/src/libsyntax_ext/proc_macro_decls.rs b/src/libsyntax_ext/proc_macro_decls.rs
deleted file mode 100644 (file)
index 303d5f0..0000000
+++ /dev/null
@@ -1,424 +0,0 @@
-use std::mem;
-
-use syntax::ast::{self, Ident};
-use syntax::attr;
-use syntax::source_map::{ExpnInfo, ExpnKind, respan};
-use syntax::ext::base::{ExtCtxt, MacroKind};
-use syntax::ext::build::AstBuilder;
-use syntax::ext::expand::ExpansionConfig;
-use syntax::ext::hygiene::ExpnId;
-use syntax::mut_visit::MutVisitor;
-use syntax::parse::ParseSess;
-use syntax::ptr::P;
-use syntax::symbol::Symbol;
-use syntax::symbol::{kw, sym};
-use syntax::visit::{self, Visitor};
-
-use syntax_pos::{Span, DUMMY_SP};
-
-const PROC_MACRO_KINDS: [Symbol; 3] = [
-    sym::proc_macro_derive,
-    sym::proc_macro_attribute,
-    sym::proc_macro
-];
-
-struct ProcMacroDerive {
-    trait_name: ast::Name,
-    function_name: Ident,
-    span: Span,
-    attrs: Vec<ast::Name>,
-}
-
-struct ProcMacroDef {
-    function_name: Ident,
-    span: Span,
-}
-
-struct CollectProcMacros<'a> {
-    derives: Vec<ProcMacroDerive>,
-    attr_macros: Vec<ProcMacroDef>,
-    bang_macros: Vec<ProcMacroDef>,
-    in_root: bool,
-    handler: &'a errors::Handler,
-    is_proc_macro_crate: bool,
-    is_test_crate: bool,
-}
-
-pub fn modify(sess: &ParseSess,
-              resolver: &mut dyn (::syntax::ext::base::Resolver),
-              mut krate: ast::Crate,
-              is_proc_macro_crate: bool,
-              has_proc_macro_decls: bool,
-              is_test_crate: bool,
-              num_crate_types: usize,
-              handler: &errors::Handler) -> ast::Crate {
-    let ecfg = ExpansionConfig::default("proc_macro".to_string());
-    let mut cx = ExtCtxt::new(sess, ecfg, resolver);
-
-    let (derives, attr_macros, bang_macros) = {
-        let mut collect = CollectProcMacros {
-            derives: Vec::new(),
-            attr_macros: Vec::new(),
-            bang_macros: Vec::new(),
-            in_root: true,
-            handler,
-            is_proc_macro_crate,
-            is_test_crate,
-        };
-        if has_proc_macro_decls || is_proc_macro_crate {
-            visit::walk_crate(&mut collect, &krate);
-        }
-        (collect.derives, collect.attr_macros, collect.bang_macros)
-    };
-
-    if !is_proc_macro_crate {
-        return krate
-    }
-
-    if num_crate_types > 1 {
-        handler.err("cannot mix `proc-macro` crate type with others");
-    }
-
-    if is_test_crate {
-        return krate;
-    }
-
-    krate.module.items.push(mk_decls(&mut cx, &derives, &attr_macros, &bang_macros));
-
-    krate
-}
-
-pub fn is_proc_macro_attr(attr: &ast::Attribute) -> bool {
-    PROC_MACRO_KINDS.iter().any(|kind| attr.check_name(*kind))
-}
-
-impl<'a> CollectProcMacros<'a> {
-    fn check_not_pub_in_root(&self, vis: &ast::Visibility, sp: Span) {
-        if self.is_proc_macro_crate && self.in_root && vis.node.is_pub() {
-            self.handler.span_err(sp,
-                                  "`proc-macro` crate types cannot \
-                                   export any items other than functions \
-                                   tagged with `#[proc_macro_derive]` currently");
-        }
-    }
-
-    fn collect_custom_derive(&mut self, item: &'a ast::Item, attr: &'a ast::Attribute) {
-        // Once we've located the `#[proc_macro_derive]` attribute, verify
-        // that it's of the form `#[proc_macro_derive(Foo)]` or
-        // `#[proc_macro_derive(Foo, attributes(A, ..))]`
-        let list = match attr.meta_item_list() {
-            Some(list) => list,
-            None => return,
-        };
-        if list.len() != 1 && list.len() != 2 {
-            self.handler.span_err(attr.span,
-                                  "attribute must have either one or two arguments");
-            return
-        }
-        let trait_attr = match list[0].meta_item() {
-            Some(meta_item) => meta_item,
-            _ => {
-                self.handler.span_err(list[0].span(), "not a meta item");
-                return
-            }
-        };
-        let trait_ident = match trait_attr.ident() {
-            Some(trait_ident) if trait_attr.is_word() => trait_ident,
-            _ => {
-                self.handler.span_err(trait_attr.span, "must only be one word");
-                return
-            }
-        };
-
-        if !trait_ident.name.can_be_raw() {
-            self.handler.span_err(trait_attr.span,
-                                  &format!("`{}` cannot be a name of derive macro", trait_ident));
-        }
-
-        let attributes_attr = list.get(1);
-        let proc_attrs: Vec<_> = if let Some(attr) = attributes_attr {
-            if !attr.check_name(sym::attributes) {
-                self.handler.span_err(attr.span(), "second argument must be `attributes`")
-            }
-            attr.meta_item_list().unwrap_or_else(|| {
-                self.handler.span_err(attr.span(),
-                                      "attribute must be of form: `attributes(foo, bar)`");
-                &[]
-            }).into_iter().filter_map(|attr| {
-                let attr = match attr.meta_item() {
-                    Some(meta_item) => meta_item,
-                    _ => {
-                        self.handler.span_err(attr.span(), "not a meta item");
-                        return None;
-                    }
-                };
-
-                let ident = match attr.ident() {
-                    Some(ident) if attr.is_word() => ident,
-                    _ => {
-                        self.handler.span_err(attr.span, "must only be one word");
-                        return None;
-                    }
-                };
-                if !ident.name.can_be_raw() {
-                    self.handler.span_err(
-                        attr.span,
-                        &format!("`{}` cannot be a name of derive helper attribute", ident),
-                    );
-                }
-
-                Some(ident.name)
-            }).collect()
-        } else {
-            Vec::new()
-        };
-
-        if self.in_root && item.vis.node.is_pub() {
-            self.derives.push(ProcMacroDerive {
-                span: item.span,
-                trait_name: trait_ident.name,
-                function_name: item.ident,
-                attrs: proc_attrs,
-            });
-        } else {
-            let msg = if !self.in_root {
-                "functions tagged with `#[proc_macro_derive]` must \
-                 currently reside in the root of the crate"
-            } else {
-                "functions tagged with `#[proc_macro_derive]` must be `pub`"
-            };
-            self.handler.span_err(item.span, msg);
-        }
-    }
-
-    fn collect_attr_proc_macro(&mut self, item: &'a ast::Item) {
-        if self.in_root && item.vis.node.is_pub() {
-            self.attr_macros.push(ProcMacroDef {
-                span: item.span,
-                function_name: item.ident,
-            });
-        } else {
-            let msg = if !self.in_root {
-                "functions tagged with `#[proc_macro_attribute]` must \
-                 currently reside in the root of the crate"
-            } else {
-                "functions tagged with `#[proc_macro_attribute]` must be `pub`"
-            };
-            self.handler.span_err(item.span, msg);
-        }
-    }
-
-    fn collect_bang_proc_macro(&mut self, item: &'a ast::Item) {
-        if self.in_root && item.vis.node.is_pub() {
-            self.bang_macros.push(ProcMacroDef {
-                span: item.span,
-                function_name: item.ident,
-            });
-        } else {
-            let msg = if !self.in_root {
-                "functions tagged with `#[proc_macro]` must \
-                 currently reside in the root of the crate"
-            } else {
-                "functions tagged with `#[proc_macro]` must be `pub`"
-            };
-            self.handler.span_err(item.span, msg);
-        }
-    }
-}
-
-impl<'a> Visitor<'a> for CollectProcMacros<'a> {
-    fn visit_item(&mut self, item: &'a ast::Item) {
-        if let ast::ItemKind::MacroDef(..) = item.node {
-            if self.is_proc_macro_crate && attr::contains_name(&item.attrs, sym::macro_export) {
-                let msg =
-                    "cannot export macro_rules! macros from a `proc-macro` crate type currently";
-                self.handler.span_err(item.span, msg);
-            }
-        }
-
-        // First up, make sure we're checking a bare function. If we're not then
-        // we're just not interested in this item.
-        //
-        // If we find one, try to locate a `#[proc_macro_derive]` attribute on it.
-        let is_fn = match item.node {
-            ast::ItemKind::Fn(..) => true,
-            _ => false,
-        };
-
-        let mut found_attr: Option<&'a ast::Attribute> = None;
-
-        for attr in &item.attrs {
-            if is_proc_macro_attr(&attr) {
-                if let Some(prev_attr) = found_attr {
-                    let msg = if attr.path.segments[0].ident.name ==
-                                 prev_attr.path.segments[0].ident.name {
-                        format!("only one `#[{}]` attribute is allowed on any given function",
-                                attr.path)
-                    } else {
-                        format!("`#[{}]` and `#[{}]` attributes cannot both be applied \
-                                to the same function", attr.path, prev_attr.path)
-                    };
-
-                    self.handler.struct_span_err(attr.span, &msg)
-                        .span_note(prev_attr.span, "previous attribute here")
-                        .emit();
-
-                    return;
-                }
-
-                found_attr = Some(attr);
-            }
-        }
-
-        let attr = match found_attr {
-            None => {
-                self.check_not_pub_in_root(&item.vis, item.span);
-                let prev_in_root = mem::replace(&mut self.in_root, false);
-                visit::walk_item(self, item);
-                self.in_root = prev_in_root;
-                return;
-            },
-            Some(attr) => attr,
-        };
-
-        if !is_fn {
-            let msg = format!("the `#[{}]` attribute may only be used on bare functions",
-                              attr.path);
-
-            self.handler.span_err(attr.span, &msg);
-            return;
-        }
-
-        if self.is_test_crate {
-            return;
-        }
-
-        if !self.is_proc_macro_crate {
-            let msg = format!("the `#[{}]` attribute is only usable with crates of the \
-                              `proc-macro` crate type", attr.path);
-
-            self.handler.span_err(attr.span, &msg);
-            return;
-        }
-
-        if attr.check_name(sym::proc_macro_derive) {
-            self.collect_custom_derive(item, attr);
-        } else if attr.check_name(sym::proc_macro_attribute) {
-            self.collect_attr_proc_macro(item);
-        } else if attr.check_name(sym::proc_macro) {
-            self.collect_bang_proc_macro(item);
-        };
-
-        let prev_in_root = mem::replace(&mut self.in_root, false);
-        visit::walk_item(self, item);
-        self.in_root = prev_in_root;
-    }
-
-    fn visit_mac(&mut self, mac: &'a ast::Mac) {
-        visit::walk_mac(self, mac)
-    }
-}
-
-// Creates a new module which looks like:
-//
-//      #[doc(hidden)]
-//      mod $gensym {
-//          extern crate proc_macro;
-//
-//          use proc_macro::bridge::client::ProcMacro;
-//
-//          #[rustc_proc_macro_decls]
-//          static DECLS: &[ProcMacro] = &[
-//              ProcMacro::custom_derive($name_trait1, &[], ::$name1);
-//              ProcMacro::custom_derive($name_trait2, &["attribute_name"], ::$name2);
-//              // ...
-//          ];
-//      }
-fn mk_decls(
-    cx: &mut ExtCtxt<'_>,
-    custom_derives: &[ProcMacroDerive],
-    custom_attrs: &[ProcMacroDef],
-    custom_macros: &[ProcMacroDef],
-) -> P<ast::Item> {
-    let span = DUMMY_SP.fresh_expansion(ExpnId::root(), ExpnInfo::allow_unstable(
-        ExpnKind::Macro(MacroKind::Attr, sym::proc_macro), DUMMY_SP, cx.parse_sess.edition,
-        [sym::rustc_attrs, sym::proc_macro_internals][..].into(),
-    ));
-
-    let hidden = cx.meta_list_item_word(span, sym::hidden);
-    let doc = cx.meta_list(span, sym::doc, vec![hidden]);
-    let doc_hidden = cx.attribute(span, doc);
-
-    let proc_macro = Ident::with_empty_ctxt(sym::proc_macro);
-    let krate = cx.item(span,
-                        proc_macro,
-                        Vec::new(),
-                        ast::ItemKind::ExternCrate(None));
-
-    let bridge = Ident::from_str("bridge");
-    let client = Ident::from_str("client");
-    let proc_macro_ty = Ident::from_str("ProcMacro");
-    let custom_derive = Ident::from_str("custom_derive");
-    let attr = Ident::from_str("attr");
-    let bang = Ident::from_str("bang");
-    let crate_kw = Ident::with_empty_ctxt(kw::Crate);
-
-    let decls = {
-        let local_path = |sp: Span, name| {
-            cx.expr_path(cx.path(sp.with_ctxt(span.ctxt()), vec![crate_kw, name]))
-        };
-        let proc_macro_ty_method_path = |method| cx.expr_path(cx.path(span, vec![
-            proc_macro, bridge, client, proc_macro_ty, method,
-        ]));
-        custom_derives.iter().map(|cd| {
-            cx.expr_call(span, proc_macro_ty_method_path(custom_derive), vec![
-                cx.expr_str(cd.span, cd.trait_name),
-                cx.expr_vec_slice(
-                    span,
-                    cd.attrs.iter().map(|&s| cx.expr_str(cd.span, s)).collect::<Vec<_>>()
-                ),
-                local_path(cd.span, cd.function_name),
-            ])
-        }).chain(custom_attrs.iter().map(|ca| {
-            cx.expr_call(span, proc_macro_ty_method_path(attr), vec![
-                cx.expr_str(ca.span, ca.function_name.name),
-                local_path(ca.span, ca.function_name),
-            ])
-        })).chain(custom_macros.iter().map(|cm| {
-            cx.expr_call(span, proc_macro_ty_method_path(bang), vec![
-                cx.expr_str(cm.span, cm.function_name.name),
-                local_path(cm.span, cm.function_name),
-            ])
-        })).collect()
-    };
-
-    let decls_static = cx.item_static(
-        span,
-        Ident::from_str("_DECLS"),
-        cx.ty_rptr(span,
-            cx.ty(span, ast::TyKind::Slice(
-                cx.ty_path(cx.path(span,
-                    vec![proc_macro, bridge, client, proc_macro_ty])))),
-            None, ast::Mutability::Immutable),
-        ast::Mutability::Immutable,
-        cx.expr_vec_slice(span, decls),
-    ).map(|mut i| {
-        let attr = cx.meta_word(span, sym::rustc_proc_macro_decls);
-        i.attrs.push(cx.attribute(span, attr));
-        i.vis = respan(span, ast::VisibilityKind::Public);
-        i
-    });
-
-    let module = cx.item_mod(
-        span,
-        span,
-        ast::Ident::from_str("decls").gensym(),
-        vec![doc_hidden],
-        vec![krate, decls_static],
-    ).map(|mut i| {
-        i.vis = respan(span, ast::VisibilityKind::Public);
-        i
-    });
-
-    cx.monotonic_expander().flat_map_item(module).pop().unwrap()
-}
diff --git a/src/libsyntax_ext/proc_macro_harness.rs b/src/libsyntax_ext/proc_macro_harness.rs
new file mode 100644 (file)
index 0000000..fc6cd5d
--- /dev/null
@@ -0,0 +1,414 @@
+use std::mem;
+
+use syntax::ast::{self, Ident};
+use syntax::attr;
+use syntax::source_map::{ExpnInfo, ExpnKind, respan};
+use syntax::ext::base::{ExtCtxt, MacroKind};
+use syntax::ext::build::AstBuilder;
+use syntax::ext::expand::ExpansionConfig;
+use syntax::ext::hygiene::ExpnId;
+use syntax::ext::proc_macro::is_proc_macro_attr;
+use syntax::mut_visit::MutVisitor;
+use syntax::parse::ParseSess;
+use syntax::ptr::P;
+use syntax::symbol::{kw, sym};
+use syntax::visit::{self, Visitor};
+
+use syntax_pos::{Span, DUMMY_SP};
+
+struct ProcMacroDerive {
+    trait_name: ast::Name,
+    function_name: Ident,
+    span: Span,
+    attrs: Vec<ast::Name>,
+}
+
+struct ProcMacroDef {
+    function_name: Ident,
+    span: Span,
+}
+
+struct CollectProcMacros<'a> {
+    derives: Vec<ProcMacroDerive>,
+    attr_macros: Vec<ProcMacroDef>,
+    bang_macros: Vec<ProcMacroDef>,
+    in_root: bool,
+    handler: &'a errors::Handler,
+    is_proc_macro_crate: bool,
+    is_test_crate: bool,
+}
+
+pub fn inject(sess: &ParseSess,
+              resolver: &mut dyn (::syntax::ext::base::Resolver),
+              mut krate: ast::Crate,
+              is_proc_macro_crate: bool,
+              has_proc_macro_decls: bool,
+              is_test_crate: bool,
+              num_crate_types: usize,
+              handler: &errors::Handler) -> ast::Crate {
+    let ecfg = ExpansionConfig::default("proc_macro".to_string());
+    let mut cx = ExtCtxt::new(sess, ecfg, resolver);
+
+    let (derives, attr_macros, bang_macros) = {
+        let mut collect = CollectProcMacros {
+            derives: Vec::new(),
+            attr_macros: Vec::new(),
+            bang_macros: Vec::new(),
+            in_root: true,
+            handler,
+            is_proc_macro_crate,
+            is_test_crate,
+        };
+        if has_proc_macro_decls || is_proc_macro_crate {
+            visit::walk_crate(&mut collect, &krate);
+        }
+        (collect.derives, collect.attr_macros, collect.bang_macros)
+    };
+
+    if !is_proc_macro_crate {
+        return krate
+    }
+
+    if num_crate_types > 1 {
+        handler.err("cannot mix `proc-macro` crate type with others");
+    }
+
+    if is_test_crate {
+        return krate;
+    }
+
+    krate.module.items.push(mk_decls(&mut cx, &derives, &attr_macros, &bang_macros));
+
+    krate
+}
+
+impl<'a> CollectProcMacros<'a> {
+    fn check_not_pub_in_root(&self, vis: &ast::Visibility, sp: Span) {
+        if self.is_proc_macro_crate && self.in_root && vis.node.is_pub() {
+            self.handler.span_err(sp,
+                                  "`proc-macro` crate types cannot \
+                                   export any items other than functions \
+                                   tagged with `#[proc_macro_derive]` currently");
+        }
+    }
+
+    fn collect_custom_derive(&mut self, item: &'a ast::Item, attr: &'a ast::Attribute) {
+        // Once we've located the `#[proc_macro_derive]` attribute, verify
+        // that it's of the form `#[proc_macro_derive(Foo)]` or
+        // `#[proc_macro_derive(Foo, attributes(A, ..))]`
+        let list = match attr.meta_item_list() {
+            Some(list) => list,
+            None => return,
+        };
+        if list.len() != 1 && list.len() != 2 {
+            self.handler.span_err(attr.span,
+                                  "attribute must have either one or two arguments");
+            return
+        }
+        let trait_attr = match list[0].meta_item() {
+            Some(meta_item) => meta_item,
+            _ => {
+                self.handler.span_err(list[0].span(), "not a meta item");
+                return
+            }
+        };
+        let trait_ident = match trait_attr.ident() {
+            Some(trait_ident) if trait_attr.is_word() => trait_ident,
+            _ => {
+                self.handler.span_err(trait_attr.span, "must only be one word");
+                return
+            }
+        };
+
+        if !trait_ident.name.can_be_raw() {
+            self.handler.span_err(trait_attr.span,
+                                  &format!("`{}` cannot be a name of derive macro", trait_ident));
+        }
+
+        let attributes_attr = list.get(1);
+        let proc_attrs: Vec<_> = if let Some(attr) = attributes_attr {
+            if !attr.check_name(sym::attributes) {
+                self.handler.span_err(attr.span(), "second argument must be `attributes`")
+            }
+            attr.meta_item_list().unwrap_or_else(|| {
+                self.handler.span_err(attr.span(),
+                                      "attribute must be of form: `attributes(foo, bar)`");
+                &[]
+            }).into_iter().filter_map(|attr| {
+                let attr = match attr.meta_item() {
+                    Some(meta_item) => meta_item,
+                    _ => {
+                        self.handler.span_err(attr.span(), "not a meta item");
+                        return None;
+                    }
+                };
+
+                let ident = match attr.ident() {
+                    Some(ident) if attr.is_word() => ident,
+                    _ => {
+                        self.handler.span_err(attr.span, "must only be one word");
+                        return None;
+                    }
+                };
+                if !ident.name.can_be_raw() {
+                    self.handler.span_err(
+                        attr.span,
+                        &format!("`{}` cannot be a name of derive helper attribute", ident),
+                    );
+                }
+
+                Some(ident.name)
+            }).collect()
+        } else {
+            Vec::new()
+        };
+
+        if self.in_root && item.vis.node.is_pub() {
+            self.derives.push(ProcMacroDerive {
+                span: item.span,
+                trait_name: trait_ident.name,
+                function_name: item.ident,
+                attrs: proc_attrs,
+            });
+        } else {
+            let msg = if !self.in_root {
+                "functions tagged with `#[proc_macro_derive]` must \
+                 currently reside in the root of the crate"
+            } else {
+                "functions tagged with `#[proc_macro_derive]` must be `pub`"
+            };
+            self.handler.span_err(item.span, msg);
+        }
+    }
+
+    fn collect_attr_proc_macro(&mut self, item: &'a ast::Item) {
+        if self.in_root && item.vis.node.is_pub() {
+            self.attr_macros.push(ProcMacroDef {
+                span: item.span,
+                function_name: item.ident,
+            });
+        } else {
+            let msg = if !self.in_root {
+                "functions tagged with `#[proc_macro_attribute]` must \
+                 currently reside in the root of the crate"
+            } else {
+                "functions tagged with `#[proc_macro_attribute]` must be `pub`"
+            };
+            self.handler.span_err(item.span, msg);
+        }
+    }
+
+    fn collect_bang_proc_macro(&mut self, item: &'a ast::Item) {
+        if self.in_root && item.vis.node.is_pub() {
+            self.bang_macros.push(ProcMacroDef {
+                span: item.span,
+                function_name: item.ident,
+            });
+        } else {
+            let msg = if !self.in_root {
+                "functions tagged with `#[proc_macro]` must \
+                 currently reside in the root of the crate"
+            } else {
+                "functions tagged with `#[proc_macro]` must be `pub`"
+            };
+            self.handler.span_err(item.span, msg);
+        }
+    }
+}
+
+impl<'a> Visitor<'a> for CollectProcMacros<'a> {
+    fn visit_item(&mut self, item: &'a ast::Item) {
+        if let ast::ItemKind::MacroDef(..) = item.node {
+            if self.is_proc_macro_crate && attr::contains_name(&item.attrs, sym::macro_export) {
+                let msg =
+                    "cannot export macro_rules! macros from a `proc-macro` crate type currently";
+                self.handler.span_err(item.span, msg);
+            }
+        }
+
+        // First up, make sure we're checking a bare function. If we're not then
+        // we're just not interested in this item.
+        //
+        // If we find one, try to locate a `#[proc_macro_derive]` attribute on it.
+        let is_fn = match item.node {
+            ast::ItemKind::Fn(..) => true,
+            _ => false,
+        };
+
+        let mut found_attr: Option<&'a ast::Attribute> = None;
+
+        for attr in &item.attrs {
+            if is_proc_macro_attr(&attr) {
+                if let Some(prev_attr) = found_attr {
+                    let msg = if attr.path.segments[0].ident.name ==
+                                 prev_attr.path.segments[0].ident.name {
+                        format!("only one `#[{}]` attribute is allowed on any given function",
+                                attr.path)
+                    } else {
+                        format!("`#[{}]` and `#[{}]` attributes cannot both be applied \
+                                to the same function", attr.path, prev_attr.path)
+                    };
+
+                    self.handler.struct_span_err(attr.span, &msg)
+                        .span_note(prev_attr.span, "previous attribute here")
+                        .emit();
+
+                    return;
+                }
+
+                found_attr = Some(attr);
+            }
+        }
+
+        let attr = match found_attr {
+            None => {
+                self.check_not_pub_in_root(&item.vis, item.span);
+                let prev_in_root = mem::replace(&mut self.in_root, false);
+                visit::walk_item(self, item);
+                self.in_root = prev_in_root;
+                return;
+            },
+            Some(attr) => attr,
+        };
+
+        if !is_fn {
+            let msg = format!("the `#[{}]` attribute may only be used on bare functions",
+                              attr.path);
+
+            self.handler.span_err(attr.span, &msg);
+            return;
+        }
+
+        if self.is_test_crate {
+            return;
+        }
+
+        if !self.is_proc_macro_crate {
+            let msg = format!("the `#[{}]` attribute is only usable with crates of the \
+                              `proc-macro` crate type", attr.path);
+
+            self.handler.span_err(attr.span, &msg);
+            return;
+        }
+
+        if attr.check_name(sym::proc_macro_derive) {
+            self.collect_custom_derive(item, attr);
+        } else if attr.check_name(sym::proc_macro_attribute) {
+            self.collect_attr_proc_macro(item);
+        } else if attr.check_name(sym::proc_macro) {
+            self.collect_bang_proc_macro(item);
+        };
+
+        let prev_in_root = mem::replace(&mut self.in_root, false);
+        visit::walk_item(self, item);
+        self.in_root = prev_in_root;
+    }
+
+    fn visit_mac(&mut self, mac: &'a ast::Mac) {
+        visit::walk_mac(self, mac)
+    }
+}
+
+// Creates a new module which looks like:
+//
+//      #[doc(hidden)]
+//      mod $gensym {
+//          extern crate proc_macro;
+//
+//          use proc_macro::bridge::client::ProcMacro;
+//
+//          #[rustc_proc_macro_decls]
+//          static DECLS: &[ProcMacro] = &[
+//              ProcMacro::custom_derive($name_trait1, &[], ::$name1);
+//              ProcMacro::custom_derive($name_trait2, &["attribute_name"], ::$name2);
+//              // ...
+//          ];
+//      }
+fn mk_decls(
+    cx: &mut ExtCtxt<'_>,
+    custom_derives: &[ProcMacroDerive],
+    custom_attrs: &[ProcMacroDef],
+    custom_macros: &[ProcMacroDef],
+) -> P<ast::Item> {
+    let span = DUMMY_SP.fresh_expansion(ExpnId::root(), ExpnInfo::allow_unstable(
+        ExpnKind::Macro(MacroKind::Attr, sym::proc_macro), DUMMY_SP, cx.parse_sess.edition,
+        [sym::rustc_attrs, sym::proc_macro_internals][..].into(),
+    ));
+
+    let hidden = cx.meta_list_item_word(span, sym::hidden);
+    let doc = cx.meta_list(span, sym::doc, vec![hidden]);
+    let doc_hidden = cx.attribute(span, doc);
+
+    let proc_macro = Ident::with_empty_ctxt(sym::proc_macro);
+    let krate = cx.item(span,
+                        proc_macro,
+                        Vec::new(),
+                        ast::ItemKind::ExternCrate(None));
+
+    let bridge = Ident::from_str("bridge");
+    let client = Ident::from_str("client");
+    let proc_macro_ty = Ident::from_str("ProcMacro");
+    let custom_derive = Ident::from_str("custom_derive");
+    let attr = Ident::from_str("attr");
+    let bang = Ident::from_str("bang");
+    let crate_kw = Ident::with_empty_ctxt(kw::Crate);
+
+    let decls = {
+        let local_path = |sp: Span, name| {
+            cx.expr_path(cx.path(sp.with_ctxt(span.ctxt()), vec![crate_kw, name]))
+        };
+        let proc_macro_ty_method_path = |method| cx.expr_path(cx.path(span, vec![
+            proc_macro, bridge, client, proc_macro_ty, method,
+        ]));
+        custom_derives.iter().map(|cd| {
+            cx.expr_call(span, proc_macro_ty_method_path(custom_derive), vec![
+                cx.expr_str(cd.span, cd.trait_name),
+                cx.expr_vec_slice(
+                    span,
+                    cd.attrs.iter().map(|&s| cx.expr_str(cd.span, s)).collect::<Vec<_>>()
+                ),
+                local_path(cd.span, cd.function_name),
+            ])
+        }).chain(custom_attrs.iter().map(|ca| {
+            cx.expr_call(span, proc_macro_ty_method_path(attr), vec![
+                cx.expr_str(ca.span, ca.function_name.name),
+                local_path(ca.span, ca.function_name),
+            ])
+        })).chain(custom_macros.iter().map(|cm| {
+            cx.expr_call(span, proc_macro_ty_method_path(bang), vec![
+                cx.expr_str(cm.span, cm.function_name.name),
+                local_path(cm.span, cm.function_name),
+            ])
+        })).collect()
+    };
+
+    let decls_static = cx.item_static(
+        span,
+        Ident::from_str("_DECLS"),
+        cx.ty_rptr(span,
+            cx.ty(span, ast::TyKind::Slice(
+                cx.ty_path(cx.path(span,
+                    vec![proc_macro, bridge, client, proc_macro_ty])))),
+            None, ast::Mutability::Immutable),
+        ast::Mutability::Immutable,
+        cx.expr_vec_slice(span, decls),
+    ).map(|mut i| {
+        let attr = cx.meta_word(span, sym::rustc_proc_macro_decls);
+        i.attrs.push(cx.attribute(span, attr));
+        i.vis = respan(span, ast::VisibilityKind::Public);
+        i
+    });
+
+    let module = cx.item_mod(
+        span,
+        span,
+        ast::Ident::from_str("decls").gensym(),
+        vec![doc_hidden],
+        vec![krate, decls_static],
+    ).map(|mut i| {
+        i.vis = respan(span, ast::VisibilityKind::Public);
+        i
+    });
+
+    cx.monotonic_expander().flat_map_item(module).pop().unwrap()
+}
diff --git a/src/libsyntax_ext/proc_macro_impl.rs b/src/libsyntax_ext/proc_macro_impl.rs
deleted file mode 100644 (file)
index f0fc639..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-use crate::proc_macro_server;
-
-use errors::FatalError;
-use syntax::source_map::Span;
-use syntax::ext::base::{self, *};
-use syntax::tokenstream::TokenStream;
-
-pub const EXEC_STRATEGY: proc_macro::bridge::server::SameThread =
-    proc_macro::bridge::server::SameThread;
-
-pub struct AttrProcMacro {
-    pub client: proc_macro::bridge::client::Client<
-        fn(proc_macro::TokenStream, proc_macro::TokenStream) -> proc_macro::TokenStream,
-    >,
-}
-
-impl base::AttrProcMacro for AttrProcMacro {
-    fn expand<'cx>(&self,
-                   ecx: &'cx mut ExtCtxt<'_>,
-                   span: Span,
-                   annotation: TokenStream,
-                   annotated: TokenStream)
-                   -> TokenStream {
-        let server = proc_macro_server::Rustc::new(ecx);
-        match self.client.run(&EXEC_STRATEGY, server, annotation, annotated) {
-            Ok(stream) => stream,
-            Err(e) => {
-                let msg = "custom attribute panicked";
-                let mut err = ecx.struct_span_fatal(span, msg);
-                if let Some(s) = e.as_str() {
-                    err.help(&format!("message: {}", s));
-                }
-
-                err.emit();
-                FatalError.raise();
-            }
-        }
-    }
-}
-
-pub struct BangProcMacro {
-    pub client: proc_macro::bridge::client::Client<
-        fn(proc_macro::TokenStream) -> proc_macro::TokenStream,
-    >,
-}
-
-impl base::ProcMacro for BangProcMacro {
-    fn expand<'cx>(&self,
-                   ecx: &'cx mut ExtCtxt<'_>,
-                   span: Span,
-                   input: TokenStream)
-                   -> TokenStream {
-        let server = proc_macro_server::Rustc::new(ecx);
-        match self.client.run(&EXEC_STRATEGY, server, input) {
-            Ok(stream) => stream,
-            Err(e) => {
-                let msg = "proc macro panicked";
-                let mut err = ecx.struct_span_fatal(span, msg);
-                if let Some(s) = e.as_str() {
-                    err.help(&format!("message: {}", s));
-                }
-
-                err.emit();
-                FatalError.raise();
-            }
-        }
-    }
-}
diff --git a/src/libsyntax_ext/proc_macro_server.rs b/src/libsyntax_ext/proc_macro_server.rs
deleted file mode 100644 (file)
index e94d79a..0000000
+++ /dev/null
@@ -1,717 +0,0 @@
-use errors::{Diagnostic, DiagnosticBuilder};
-
-use std::panic;
-
-use proc_macro::bridge::{server, TokenTree};
-use proc_macro::{Delimiter, Level, LineColumn, Spacing};
-
-use rustc_data_structures::sync::Lrc;
-use std::ascii;
-use std::ops::Bound;
-use syntax::ast;
-use syntax::ext::base::ExtCtxt;
-use syntax::parse::lexer::comments;
-use syntax::parse::{self, token, ParseSess};
-use syntax::tokenstream::{self, DelimSpan, IsJoint::*, TokenStream, TreeAndJoint};
-use syntax_pos::hygiene::{SyntaxContext, Transparency};
-use syntax_pos::symbol::{kw, sym, Symbol};
-use syntax_pos::{BytePos, FileName, MultiSpan, Pos, SourceFile, Span};
-
-trait FromInternal<T> {
-    fn from_internal(x: T) -> Self;
-}
-
-trait ToInternal<T> {
-    fn to_internal(self) -> T;
-}
-
-impl FromInternal<token::DelimToken> for Delimiter {
-    fn from_internal(delim: token::DelimToken) -> Delimiter {
-        match delim {
-            token::Paren => Delimiter::Parenthesis,
-            token::Brace => Delimiter::Brace,
-            token::Bracket => Delimiter::Bracket,
-            token::NoDelim => Delimiter::None,
-        }
-    }
-}
-
-impl ToInternal<token::DelimToken> for Delimiter {
-    fn to_internal(self) -> token::DelimToken {
-        match self {
-            Delimiter::Parenthesis => token::Paren,
-            Delimiter::Brace => token::Brace,
-            Delimiter::Bracket => token::Bracket,
-            Delimiter::None => token::NoDelim,
-        }
-    }
-}
-
-impl FromInternal<(TreeAndJoint, &'_ ParseSess, &'_ mut Vec<Self>)>
-    for TokenTree<Group, Punct, Ident, Literal>
-{
-    fn from_internal(((tree, is_joint), sess, stack): (TreeAndJoint, &ParseSess, &mut Vec<Self>))
-                    -> Self {
-        use syntax::parse::token::*;
-
-        let joint = is_joint == Joint;
-        let Token { kind, span } = match tree {
-            tokenstream::TokenTree::Delimited(span, delim, tts) => {
-                let delimiter = Delimiter::from_internal(delim);
-                return TokenTree::Group(Group {
-                    delimiter,
-                    stream: tts.into(),
-                    span,
-                });
-            }
-            tokenstream::TokenTree::Token(token) => token,
-        };
-
-        macro_rules! tt {
-            ($ty:ident { $($field:ident $(: $value:expr)*),+ $(,)? }) => (
-                TokenTree::$ty(self::$ty {
-                    $($field $(: $value)*,)+
-                    span,
-                })
-            );
-            ($ty:ident::$method:ident($($value:expr),*)) => (
-                TokenTree::$ty(self::$ty::$method($($value,)* span))
-            );
-        }
-        macro_rules! op {
-            ($a:expr) => {
-                tt!(Punct::new($a, joint))
-            };
-            ($a:expr, $b:expr) => {{
-                stack.push(tt!(Punct::new($b, joint)));
-                tt!(Punct::new($a, true))
-            }};
-            ($a:expr, $b:expr, $c:expr) => {{
-                stack.push(tt!(Punct::new($c, joint)));
-                stack.push(tt!(Punct::new($b, true)));
-                tt!(Punct::new($a, true))
-            }};
-        }
-
-        match kind {
-            Eq => op!('='),
-            Lt => op!('<'),
-            Le => op!('<', '='),
-            EqEq => op!('=', '='),
-            Ne => op!('!', '='),
-            Ge => op!('>', '='),
-            Gt => op!('>'),
-            AndAnd => op!('&', '&'),
-            OrOr => op!('|', '|'),
-            Not => op!('!'),
-            Tilde => op!('~'),
-            BinOp(Plus) => op!('+'),
-            BinOp(Minus) => op!('-'),
-            BinOp(Star) => op!('*'),
-            BinOp(Slash) => op!('/'),
-            BinOp(Percent) => op!('%'),
-            BinOp(Caret) => op!('^'),
-            BinOp(And) => op!('&'),
-            BinOp(Or) => op!('|'),
-            BinOp(Shl) => op!('<', '<'),
-            BinOp(Shr) => op!('>', '>'),
-            BinOpEq(Plus) => op!('+', '='),
-            BinOpEq(Minus) => op!('-', '='),
-            BinOpEq(Star) => op!('*', '='),
-            BinOpEq(Slash) => op!('/', '='),
-            BinOpEq(Percent) => op!('%', '='),
-            BinOpEq(Caret) => op!('^', '='),
-            BinOpEq(And) => op!('&', '='),
-            BinOpEq(Or) => op!('|', '='),
-            BinOpEq(Shl) => op!('<', '<', '='),
-            BinOpEq(Shr) => op!('>', '>', '='),
-            At => op!('@'),
-            Dot => op!('.'),
-            DotDot => op!('.', '.'),
-            DotDotDot => op!('.', '.', '.'),
-            DotDotEq => op!('.', '.', '='),
-            Comma => op!(','),
-            Semi => op!(';'),
-            Colon => op!(':'),
-            ModSep => op!(':', ':'),
-            RArrow => op!('-', '>'),
-            LArrow => op!('<', '-'),
-            FatArrow => op!('=', '>'),
-            Pound => op!('#'),
-            Dollar => op!('$'),
-            Question => op!('?'),
-            SingleQuote => op!('\''),
-
-            Ident(name, false) if name == kw::DollarCrate => tt!(Ident::dollar_crate()),
-            Ident(name, is_raw) => tt!(Ident::new(name, is_raw)),
-            Lifetime(name) => {
-                let ident = ast::Ident::new(name, span).without_first_quote();
-                stack.push(tt!(Ident::new(ident.name, false)));
-                tt!(Punct::new('\'', true))
-            }
-            Literal(lit) => tt!(Literal { lit }),
-            DocComment(c) => {
-                let style = comments::doc_comment_style(&c.as_str());
-                let stripped = comments::strip_doc_comment_decoration(&c.as_str());
-                let mut escaped = String::new();
-                for ch in stripped.chars() {
-                    escaped.extend(ch.escape_debug());
-                }
-                let stream = vec![
-                    Ident(sym::doc, false),
-                    Eq,
-                    TokenKind::lit(token::Str, Symbol::intern(&escaped), None),
-                ]
-                .into_iter()
-                .map(|kind| tokenstream::TokenTree::token(kind, span))
-                .collect();
-                stack.push(TokenTree::Group(Group {
-                    delimiter: Delimiter::Bracket,
-                    stream,
-                    span: DelimSpan::from_single(span),
-                }));
-                if style == ast::AttrStyle::Inner {
-                    stack.push(tt!(Punct::new('!', false)));
-                }
-                tt!(Punct::new('#', false))
-            }
-
-            Interpolated(nt) => {
-                let stream = nt.to_tokenstream(sess, span);
-                TokenTree::Group(Group {
-                    delimiter: Delimiter::None,
-                    stream,
-                    span: DelimSpan::from_single(span),
-                })
-            }
-
-            OpenDelim(..) | CloseDelim(..) => unreachable!(),
-            Whitespace | Comment | Shebang(..) | Eof => unreachable!(),
-        }
-    }
-}
-
-impl ToInternal<TokenStream> for TokenTree<Group, Punct, Ident, Literal> {
-    fn to_internal(self) -> TokenStream {
-        use syntax::parse::token::*;
-
-        let (ch, joint, span) = match self {
-            TokenTree::Punct(Punct { ch, joint, span }) => (ch, joint, span),
-            TokenTree::Group(Group {
-                delimiter,
-                stream,
-                span,
-            }) => {
-                return tokenstream::TokenTree::Delimited(
-                    span,
-                    delimiter.to_internal(),
-                    stream.into(),
-                )
-                .into();
-            }
-            TokenTree::Ident(self::Ident { sym, is_raw, span }) => {
-                return tokenstream::TokenTree::token(Ident(sym, is_raw), span).into();
-            }
-            TokenTree::Literal(self::Literal {
-                lit: token::Lit { kind: token::Integer, symbol, suffix },
-                span,
-            }) if symbol.as_str().starts_with("-") => {
-                let minus = BinOp(BinOpToken::Minus);
-                let symbol = Symbol::intern(&symbol.as_str()[1..]);
-                let integer = TokenKind::lit(token::Integer, symbol, suffix);
-                let a = tokenstream::TokenTree::token(minus, span);
-                let b = tokenstream::TokenTree::token(integer, span);
-                return vec![a, b].into_iter().collect();
-            }
-            TokenTree::Literal(self::Literal {
-                lit: token::Lit { kind: token::Float, symbol, suffix },
-                span,
-            }) if symbol.as_str().starts_with("-") => {
-                let minus = BinOp(BinOpToken::Minus);
-                let symbol = Symbol::intern(&symbol.as_str()[1..]);
-                let float = TokenKind::lit(token::Float, symbol, suffix);
-                let a = tokenstream::TokenTree::token(minus, span);
-                let b = tokenstream::TokenTree::token(float, span);
-                return vec![a, b].into_iter().collect();
-            }
-            TokenTree::Literal(self::Literal { lit, span }) => {
-                return tokenstream::TokenTree::token(Literal(lit), span).into()
-            }
-        };
-
-        let kind = match ch {
-            '=' => Eq,
-            '<' => Lt,
-            '>' => Gt,
-            '!' => Not,
-            '~' => Tilde,
-            '+' => BinOp(Plus),
-            '-' => BinOp(Minus),
-            '*' => BinOp(Star),
-            '/' => BinOp(Slash),
-            '%' => BinOp(Percent),
-            '^' => BinOp(Caret),
-            '&' => BinOp(And),
-            '|' => BinOp(Or),
-            '@' => At,
-            '.' => Dot,
-            ',' => Comma,
-            ';' => Semi,
-            ':' => Colon,
-            '#' => Pound,
-            '$' => Dollar,
-            '?' => Question,
-            '\'' => SingleQuote,
-            _ => unreachable!(),
-        };
-
-        let tree = tokenstream::TokenTree::token(kind, span);
-        TokenStream::new(vec![(tree, if joint { Joint } else { NonJoint })])
-    }
-}
-
-impl ToInternal<errors::Level> for Level {
-    fn to_internal(self) -> errors::Level {
-        match self {
-            Level::Error => errors::Level::Error,
-            Level::Warning => errors::Level::Warning,
-            Level::Note => errors::Level::Note,
-            Level::Help => errors::Level::Help,
-            _ => unreachable!("unknown proc_macro::Level variant: {:?}", self),
-        }
-    }
-}
-
-#[derive(Clone)]
-pub struct TokenStreamIter {
-    cursor: tokenstream::Cursor,
-    stack: Vec<TokenTree<Group, Punct, Ident, Literal>>,
-}
-
-#[derive(Clone)]
-pub struct Group {
-    delimiter: Delimiter,
-    stream: TokenStream,
-    span: DelimSpan,
-}
-
-#[derive(Copy, Clone, PartialEq, Eq, Hash)]
-pub struct Punct {
-    ch: char,
-    // NB. not using `Spacing` here because it doesn't implement `Hash`.
-    joint: bool,
-    span: Span,
-}
-
-impl Punct {
-    fn new(ch: char, joint: bool, span: Span) -> Punct {
-        const LEGAL_CHARS: &[char] = &['=', '<', '>', '!', '~', '+', '-', '*', '/', '%', '^',
-                                       '&', '|', '@', '.', ',', ';', ':', '#', '$', '?', '\''];
-        if !LEGAL_CHARS.contains(&ch) {
-            panic!("unsupported character `{:?}`", ch)
-        }
-        Punct { ch, joint, span }
-    }
-}
-
-#[derive(Copy, Clone, PartialEq, Eq, Hash)]
-pub struct Ident {
-    sym: Symbol,
-    is_raw: bool,
-    span: Span,
-}
-
-impl Ident {
-    fn is_valid(string: &str) -> bool {
-        let mut chars = string.chars();
-        if let Some(start) = chars.next() {
-            (start == '_' || start.is_xid_start())
-                && chars.all(|cont| cont == '_' || cont.is_xid_continue())
-        } else {
-            false
-        }
-    }
-    fn new(sym: Symbol, is_raw: bool, span: Span) -> Ident {
-        let string = sym.as_str();
-        if !Self::is_valid(&string) {
-            panic!("`{:?}` is not a valid identifier", string)
-        }
-        // Get rid of gensyms to conservatively check rawness on the string contents only.
-        if is_raw && !sym.as_interned_str().as_symbol().can_be_raw() {
-            panic!("`{}` cannot be a raw identifier", string);
-        }
-        Ident { sym, is_raw, span }
-    }
-    fn dollar_crate(span: Span) -> Ident {
-        // `$crate` is accepted as an ident only if it comes from the compiler.
-        Ident { sym: kw::DollarCrate, is_raw: false, span }
-    }
-}
-
-// FIXME(eddyb) `Literal` should not expose internal `Debug` impls.
-#[derive(Clone, Debug)]
-pub struct Literal {
-    lit: token::Lit,
-    span: Span,
-}
-
-pub(crate) struct Rustc<'a> {
-    sess: &'a ParseSess,
-    def_site: Span,
-    call_site: Span,
-}
-
-impl<'a> Rustc<'a> {
-    pub fn new(cx: &'a ExtCtxt<'_>) -> Self {
-        // No way to determine def location for a proc macro right now, so use call location.
-        let location = cx.current_expansion.id.expn_info().unwrap().call_site;
-        let to_span = |transparency| {
-            location.with_ctxt(
-                SyntaxContext::empty()
-                    .apply_mark_with_transparency(cx.current_expansion.id, transparency),
-            )
-        };
-        Rustc {
-            sess: cx.parse_sess,
-            def_site: to_span(Transparency::Opaque),
-            call_site: to_span(Transparency::Transparent),
-        }
-    }
-
-    fn lit(&mut self, kind: token::LitKind, symbol: Symbol, suffix: Option<Symbol>) -> Literal {
-        Literal {
-            lit: token::Lit::new(kind, symbol, suffix),
-            span: server::Span::call_site(self),
-        }
-    }
-}
-
-impl server::Types for Rustc<'_> {
-    type TokenStream = TokenStream;
-    type TokenStreamBuilder = tokenstream::TokenStreamBuilder;
-    type TokenStreamIter = TokenStreamIter;
-    type Group = Group;
-    type Punct = Punct;
-    type Ident = Ident;
-    type Literal = Literal;
-    type SourceFile = Lrc<SourceFile>;
-    type MultiSpan = Vec<Span>;
-    type Diagnostic = Diagnostic;
-    type Span = Span;
-}
-
-impl server::TokenStream for Rustc<'_> {
-    fn new(&mut self) -> Self::TokenStream {
-        TokenStream::empty()
-    }
-    fn is_empty(&mut self, stream: &Self::TokenStream) -> bool {
-        stream.is_empty()
-    }
-    fn from_str(&mut self, src: &str) -> Self::TokenStream {
-        parse::parse_stream_from_source_str(
-            FileName::proc_macro_source_code(src),
-            src.to_string(),
-            self.sess,
-            Some(self.call_site),
-        )
-    }
-    fn to_string(&mut self, stream: &Self::TokenStream) -> String {
-        stream.to_string()
-    }
-    fn from_token_tree(
-        &mut self,
-        tree: TokenTree<Self::Group, Self::Punct, Self::Ident, Self::Literal>,
-    ) -> Self::TokenStream {
-        tree.to_internal()
-    }
-    fn into_iter(&mut self, stream: Self::TokenStream) -> Self::TokenStreamIter {
-        TokenStreamIter {
-            cursor: stream.trees(),
-            stack: vec![],
-        }
-    }
-}
-
-impl server::TokenStreamBuilder for Rustc<'_> {
-    fn new(&mut self) -> Self::TokenStreamBuilder {
-        tokenstream::TokenStreamBuilder::new()
-    }
-    fn push(&mut self, builder: &mut Self::TokenStreamBuilder, stream: Self::TokenStream) {
-        builder.push(stream);
-    }
-    fn build(&mut self, builder: Self::TokenStreamBuilder) -> Self::TokenStream {
-        builder.build()
-    }
-}
-
-impl server::TokenStreamIter for Rustc<'_> {
-    fn next(
-        &mut self,
-        iter: &mut Self::TokenStreamIter,
-    ) -> Option<TokenTree<Self::Group, Self::Punct, Self::Ident, Self::Literal>> {
-        loop {
-            let tree = iter.stack.pop().or_else(|| {
-                let next = iter.cursor.next_with_joint()?;
-                Some(TokenTree::from_internal((next, self.sess, &mut iter.stack)))
-            })?;
-            // HACK: The condition "dummy span + group with empty delimiter" represents an AST
-            // fragment approximately converted into a token stream. This may happen, for
-            // example, with inputs to proc macro attributes, including derives. Such "groups"
-            // need to flattened during iteration over stream's token trees.
-            // Eventually this needs to be removed in favor of keeping original token trees
-            // and not doing the roundtrip through AST.
-            if let TokenTree::Group(ref group) = tree {
-                if group.delimiter == Delimiter::None && group.span.entire().is_dummy() {
-                    iter.cursor.append(group.stream.clone());
-                    continue;
-                }
-            }
-            return Some(tree);
-        }
-    }
-}
-
-impl server::Group for Rustc<'_> {
-    fn new(&mut self, delimiter: Delimiter, stream: Self::TokenStream) -> Self::Group {
-        Group {
-            delimiter,
-            stream,
-            span: DelimSpan::from_single(server::Span::call_site(self)),
-        }
-    }
-    fn delimiter(&mut self, group: &Self::Group) -> Delimiter {
-        group.delimiter
-    }
-    fn stream(&mut self, group: &Self::Group) -> Self::TokenStream {
-        group.stream.clone()
-    }
-    fn span(&mut self, group: &Self::Group) -> Self::Span {
-        group.span.entire()
-    }
-    fn span_open(&mut self, group: &Self::Group) -> Self::Span {
-        group.span.open
-    }
-    fn span_close(&mut self, group: &Self::Group) -> Self::Span {
-        group.span.close
-    }
-    fn set_span(&mut self, group: &mut Self::Group, span: Self::Span) {
-        group.span = DelimSpan::from_single(span);
-    }
-}
-
-impl server::Punct for Rustc<'_> {
-    fn new(&mut self, ch: char, spacing: Spacing) -> Self::Punct {
-        Punct::new(ch, spacing == Spacing::Joint, server::Span::call_site(self))
-    }
-    fn as_char(&mut self, punct: Self::Punct) -> char {
-        punct.ch
-    }
-    fn spacing(&mut self, punct: Self::Punct) -> Spacing {
-        if punct.joint {
-            Spacing::Joint
-        } else {
-            Spacing::Alone
-        }
-    }
-    fn span(&mut self, punct: Self::Punct) -> Self::Span {
-        punct.span
-    }
-    fn with_span(&mut self, punct: Self::Punct, span: Self::Span) -> Self::Punct {
-        Punct { span, ..punct }
-    }
-}
-
-impl server::Ident for Rustc<'_> {
-    fn new(&mut self, string: &str, span: Self::Span, is_raw: bool) -> Self::Ident {
-        Ident::new(Symbol::intern(string), is_raw, span)
-    }
-    fn span(&mut self, ident: Self::Ident) -> Self::Span {
-        ident.span
-    }
-    fn with_span(&mut self, ident: Self::Ident, span: Self::Span) -> Self::Ident {
-        Ident { span, ..ident }
-    }
-}
-
-impl server::Literal for Rustc<'_> {
-    // FIXME(eddyb) `Literal` should not expose internal `Debug` impls.
-    fn debug(&mut self, literal: &Self::Literal) -> String {
-        format!("{:?}", literal)
-    }
-    fn integer(&mut self, n: &str) -> Self::Literal {
-        self.lit(token::Integer, Symbol::intern(n), None)
-    }
-    fn typed_integer(&mut self, n: &str, kind: &str) -> Self::Literal {
-        self.lit(token::Integer, Symbol::intern(n), Some(Symbol::intern(kind)))
-    }
-    fn float(&mut self, n: &str) -> Self::Literal {
-        self.lit(token::Float, Symbol::intern(n), None)
-    }
-    fn f32(&mut self, n: &str) -> Self::Literal {
-        self.lit(token::Float, Symbol::intern(n), Some(sym::f32))
-    }
-    fn f64(&mut self, n: &str) -> Self::Literal {
-        self.lit(token::Float, Symbol::intern(n), Some(sym::f64))
-    }
-    fn string(&mut self, string: &str) -> Self::Literal {
-        let mut escaped = String::new();
-        for ch in string.chars() {
-            escaped.extend(ch.escape_debug());
-        }
-        self.lit(token::Str, Symbol::intern(&escaped), None)
-    }
-    fn character(&mut self, ch: char) -> Self::Literal {
-        let mut escaped = String::new();
-        escaped.extend(ch.escape_unicode());
-        self.lit(token::Char, Symbol::intern(&escaped), None)
-    }
-    fn byte_string(&mut self, bytes: &[u8]) -> Self::Literal {
-        let string = bytes
-            .iter()
-            .cloned()
-            .flat_map(ascii::escape_default)
-            .map(Into::<char>::into)
-            .collect::<String>();
-        self.lit(token::ByteStr, Symbol::intern(&string), None)
-    }
-    fn span(&mut self, literal: &Self::Literal) -> Self::Span {
-        literal.span
-    }
-    fn set_span(&mut self, literal: &mut Self::Literal, span: Self::Span) {
-        literal.span = span;
-    }
-    fn subspan(
-        &mut self,
-        literal: &Self::Literal,
-        start: Bound<usize>,
-        end: Bound<usize>,
-    ) -> Option<Self::Span> {
-        let span = literal.span;
-        let length = span.hi().to_usize() - span.lo().to_usize();
-
-        let start = match start {
-            Bound::Included(lo) => lo,
-            Bound::Excluded(lo) => lo + 1,
-            Bound::Unbounded => 0,
-        };
-
-        let end = match end {
-            Bound::Included(hi) => hi + 1,
-            Bound::Excluded(hi) => hi,
-            Bound::Unbounded => length,
-        };
-
-        // Bounds check the values, preventing addition overflow and OOB spans.
-        if start > u32::max_value() as usize
-            || end > u32::max_value() as usize
-            || (u32::max_value() - start as u32) < span.lo().to_u32()
-            || (u32::max_value() - end as u32) < span.lo().to_u32()
-            || start >= end
-            || end > length
-        {
-            return None;
-        }
-
-        let new_lo = span.lo() + BytePos::from_usize(start);
-        let new_hi = span.lo() + BytePos::from_usize(end);
-        Some(span.with_lo(new_lo).with_hi(new_hi))
-    }
-}
-
-impl server::SourceFile for Rustc<'_> {
-    fn eq(&mut self, file1: &Self::SourceFile, file2: &Self::SourceFile) -> bool {
-        Lrc::ptr_eq(file1, file2)
-    }
-    fn path(&mut self, file: &Self::SourceFile) -> String {
-        match file.name {
-            FileName::Real(ref path) => path
-                .to_str()
-                .expect("non-UTF8 file path in `proc_macro::SourceFile::path`")
-                .to_string(),
-            _ => file.name.to_string(),
-        }
-    }
-    fn is_real(&mut self, file: &Self::SourceFile) -> bool {
-        file.is_real_file()
-    }
-}
-
-impl server::MultiSpan for Rustc<'_> {
-    fn new(&mut self) -> Self::MultiSpan {
-        vec![]
-    }
-    fn push(&mut self, spans: &mut Self::MultiSpan, span: Self::Span) {
-        spans.push(span)
-    }
-}
-
-impl server::Diagnostic for Rustc<'_> {
-    fn new(&mut self, level: Level, msg: &str, spans: Self::MultiSpan) -> Self::Diagnostic {
-        let mut diag = Diagnostic::new(level.to_internal(), msg);
-        diag.set_span(MultiSpan::from_spans(spans));
-        diag
-    }
-    fn sub(
-        &mut self,
-        diag: &mut Self::Diagnostic,
-        level: Level,
-        msg: &str,
-        spans: Self::MultiSpan,
-    ) {
-        diag.sub(level.to_internal(), msg, MultiSpan::from_spans(spans), None);
-    }
-    fn emit(&mut self, diag: Self::Diagnostic) {
-        DiagnosticBuilder::new_diagnostic(&self.sess.span_diagnostic, diag).emit()
-    }
-}
-
-impl server::Span for Rustc<'_> {
-    fn debug(&mut self, span: Self::Span) -> String {
-        format!("{:?} bytes({}..{})", span.ctxt(), span.lo().0, span.hi().0)
-    }
-    fn def_site(&mut self) -> Self::Span {
-        self.def_site
-    }
-    fn call_site(&mut self) -> Self::Span {
-        self.call_site
-    }
-    fn source_file(&mut self, span: Self::Span) -> Self::SourceFile {
-        self.sess.source_map().lookup_char_pos(span.lo()).file
-    }
-    fn parent(&mut self, span: Self::Span) -> Option<Self::Span> {
-        span.ctxt().outer_expn_info().map(|i| i.call_site)
-    }
-    fn source(&mut self, span: Self::Span) -> Self::Span {
-        span.source_callsite()
-    }
-    fn start(&mut self, span: Self::Span) -> LineColumn {
-        let loc = self.sess.source_map().lookup_char_pos(span.lo());
-        LineColumn {
-            line: loc.line,
-            column: loc.col.to_usize(),
-        }
-    }
-    fn end(&mut self, span: Self::Span) -> LineColumn {
-        let loc = self.sess.source_map().lookup_char_pos(span.hi());
-        LineColumn {
-            line: loc.line,
-            column: loc.col.to_usize(),
-        }
-    }
-    fn join(&mut self, first: Self::Span, second: Self::Span) -> Option<Self::Span> {
-        let self_loc = self.sess.source_map().lookup_char_pos(first.lo());
-        let other_loc = self.sess.source_map().lookup_char_pos(second.lo());
-
-        if self_loc.file.name != other_loc.file.name {
-            return None;
-        }
-
-        Some(first.to(second))
-    }
-    fn resolved_at(&mut self, span: Self::Span, at: Self::Span) -> Self::Span {
-        span.with_ctxt(at.ctxt())
-    }
-    fn source_text(&mut self,  span: Self::Span) -> Option<String> {
-        self.sess.source_map().span_to_snippet(span).ok()
-    }
-}
diff --git a/src/libsyntax_ext/source_util.rs b/src/libsyntax_ext/source_util.rs
new file mode 100644 (file)
index 0000000..8ecfd4d
--- /dev/null
@@ -0,0 +1,165 @@
+use syntax::{ast, panictry};
+use syntax::ext::base::{self, *};
+use syntax::ext::build::AstBuilder;
+use syntax::parse::{self, token, DirectoryOwnership};
+use syntax::print::pprust;
+use syntax::ptr::P;
+use syntax::symbol::Symbol;
+use syntax::tokenstream;
+
+use smallvec::SmallVec;
+use syntax_pos::{self, Pos, Span};
+
+use std::fs;
+use std::io::ErrorKind;
+use rustc_data_structures::sync::Lrc;
+
+// These macros all relate to the file system; they either return
+// the column/row/filename of the expression, or they include
+// a given file into the current one.
+
+/// line!(): expands to the current line number
+pub fn expand_line(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTree])
+                   -> Box<dyn base::MacResult+'static> {
+    base::check_zero_tts(cx, sp, tts, "line!");
+
+    let topmost = cx.expansion_cause().unwrap_or(sp);
+    let loc = cx.source_map().lookup_char_pos(topmost.lo());
+
+    base::MacEager::expr(cx.expr_u32(topmost, loc.line as u32))
+}
+
+/* column!(): expands to the current column number */
+pub fn expand_column(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTree])
+                  -> Box<dyn base::MacResult+'static> {
+    base::check_zero_tts(cx, sp, tts, "column!");
+
+    let topmost = cx.expansion_cause().unwrap_or(sp);
+    let loc = cx.source_map().lookup_char_pos(topmost.lo());
+
+    base::MacEager::expr(cx.expr_u32(topmost, loc.col.to_usize() as u32 + 1))
+}
+
+/// file!(): expands to the current filename */
+/// The source_file (`loc.file`) contains a bunch more information we could spit
+/// out if we wanted.
+pub fn expand_file(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTree])
+                   -> Box<dyn base::MacResult+'static> {
+    base::check_zero_tts(cx, sp, tts, "file!");
+
+    let topmost = cx.expansion_cause().unwrap_or(sp);
+    let loc = cx.source_map().lookup_char_pos(topmost.lo());
+    base::MacEager::expr(cx.expr_str(topmost, Symbol::intern(&loc.file.name.to_string())))
+}
+
+pub fn expand_stringify(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTree])
+                        -> Box<dyn base::MacResult+'static> {
+    let s = pprust::tts_to_string(tts);
+    base::MacEager::expr(cx.expr_str(sp, Symbol::intern(&s)))
+}
+
+pub fn expand_mod(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTree])
+                  -> Box<dyn base::MacResult+'static> {
+    base::check_zero_tts(cx, sp, tts, "module_path!");
+    let mod_path = &cx.current_expansion.module.mod_path;
+    let string = mod_path.iter().map(|x| x.to_string()).collect::<Vec<String>>().join("::");
+
+    base::MacEager::expr(cx.expr_str(sp, Symbol::intern(&string)))
+}
+
+/// include! : parse the given file as an expr
+/// This is generally a bad idea because it's going to behave
+/// unhygienically.
+pub fn expand_include<'cx>(cx: &'cx mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTree])
+                           -> Box<dyn base::MacResult+'cx> {
+    let file = match get_single_str_from_tts(cx, sp, tts, "include!") {
+        Some(f) => f,
+        None => return DummyResult::any(sp),
+    };
+    // The file will be added to the code map by the parser
+    let file = cx.resolve_path(file, sp);
+    let directory_ownership = DirectoryOwnership::Owned { relative: None };
+    let p = parse::new_sub_parser_from_file(cx.parse_sess(), &file, directory_ownership, None, sp);
+
+    struct ExpandResult<'a> {
+        p: parse::parser::Parser<'a>,
+    }
+    impl<'a> base::MacResult for ExpandResult<'a> {
+        fn make_expr(mut self: Box<ExpandResult<'a>>) -> Option<P<ast::Expr>> {
+            Some(panictry!(self.p.parse_expr()))
+        }
+
+        fn make_items(mut self: Box<ExpandResult<'a>>) -> Option<SmallVec<[P<ast::Item>; 1]>> {
+            let mut ret = SmallVec::new();
+            while self.p.token != token::Eof {
+                match panictry!(self.p.parse_item()) {
+                    Some(item) => ret.push(item),
+                    None => self.p.sess.span_diagnostic.span_fatal(self.p.token.span,
+                                                           &format!("expected item, found `{}`",
+                                                                    self.p.this_token_to_string()))
+                                               .raise()
+                }
+            }
+            Some(ret)
+        }
+    }
+
+    Box::new(ExpandResult { p })
+}
+
+// include_str! : read the given file, insert it as a literal string expr
+pub fn expand_include_str(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTree])
+                          -> Box<dyn base::MacResult+'static> {
+    let file = match get_single_str_from_tts(cx, sp, tts, "include_str!") {
+        Some(f) => f,
+        None => return DummyResult::expr(sp)
+    };
+    let file = cx.resolve_path(file, sp);
+    match fs::read_to_string(&file) {
+        Ok(src) => {
+            let interned_src = Symbol::intern(&src);
+
+            // Add this input file to the code map to make it available as
+            // dependency information
+            cx.source_map().new_source_file(file.into(), src);
+
+            base::MacEager::expr(cx.expr_str(sp, interned_src))
+        },
+        Err(ref e) if e.kind() == ErrorKind::InvalidData => {
+            cx.span_err(sp, &format!("{} wasn't a utf-8 file", file.display()));
+            DummyResult::expr(sp)
+        }
+        Err(e) => {
+            cx.span_err(sp, &format!("couldn't read {}: {}", file.display(), e));
+            DummyResult::expr(sp)
+        }
+    }
+}
+
+pub fn expand_include_bytes(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTree])
+                            -> Box<dyn base::MacResult+'static> {
+    let file = match get_single_str_from_tts(cx, sp, tts, "include_bytes!") {
+        Some(f) => f,
+        None => return DummyResult::expr(sp)
+    };
+    let file = cx.resolve_path(file, sp);
+    match fs::read(&file) {
+        Ok(bytes) => {
+            // Add the contents to the source map if it contains UTF-8.
+            let (contents, bytes) = match String::from_utf8(bytes) {
+                Ok(s) => {
+                    let bytes = s.as_bytes().to_owned();
+                    (s, bytes)
+                },
+                Err(e) => (String::new(), e.into_bytes()),
+            };
+            cx.source_map().new_source_file(file.into(), contents);
+
+            base::MacEager::expr(cx.expr_lit(sp, ast::LitKind::ByteStr(Lrc::new(bytes))))
+        },
+        Err(e) => {
+            cx.span_err(sp, &format!("couldn't read {}: {}", file.display(), e));
+            DummyResult::expr(sp)
+        }
+    }
+}
diff --git a/src/libsyntax_ext/standard_library_imports.rs b/src/libsyntax_ext/standard_library_imports.rs
new file mode 100644 (file)
index 0000000..81bb32d
--- /dev/null
@@ -0,0 +1,95 @@
+use syntax::{ast, attr};
+use syntax::edition::Edition;
+use syntax::ext::hygiene::{ExpnId, MacroKind};
+use syntax::ptr::P;
+use syntax::source_map::{ExpnInfo, ExpnKind, dummy_spanned, respan};
+use syntax::symbol::{Ident, Symbol, kw, sym};
+use syntax::tokenstream::TokenStream;
+use syntax_pos::DUMMY_SP;
+
+use std::iter;
+
+pub fn inject(
+    mut krate: ast::Crate, alt_std_name: Option<&str>, edition: Edition
+) -> (ast::Crate, Option<Symbol>) {
+    let rust_2018 = edition >= Edition::Edition2018;
+
+    // the first name in this list is the crate name of the crate with the prelude
+    let names: &[&str] = if attr::contains_name(&krate.attrs, sym::no_core) {
+        return (krate, None);
+    } else if attr::contains_name(&krate.attrs, sym::no_std) {
+        if attr::contains_name(&krate.attrs, sym::compiler_builtins) {
+            &["core"]
+        } else {
+            &["core", "compiler_builtins"]
+        }
+    } else {
+        &["std"]
+    };
+
+    // .rev() to preserve ordering above in combination with insert(0, ...)
+    let alt_std_name = alt_std_name.map(Symbol::intern);
+    for orig_name_str in names.iter().rev() {
+        // HACK(eddyb) gensym the injected crates on the Rust 2018 edition,
+        // so they don't accidentally interfere with the new import paths.
+        let orig_name_sym = Symbol::intern(orig_name_str);
+        let orig_name_ident = Ident::with_empty_ctxt(orig_name_sym);
+        let (rename, orig_name) = if rust_2018 {
+            (orig_name_ident.gensym(), Some(orig_name_sym))
+        } else {
+            (orig_name_ident, None)
+        };
+        krate.module.items.insert(0, P(ast::Item {
+            attrs: vec![attr::mk_attr_outer(
+                DUMMY_SP,
+                attr::mk_attr_id(),
+                attr::mk_word_item(ast::Ident::with_empty_ctxt(sym::macro_use))
+            )],
+            vis: dummy_spanned(ast::VisibilityKind::Inherited),
+            node: ast::ItemKind::ExternCrate(alt_std_name.or(orig_name)),
+            ident: rename,
+            id: ast::DUMMY_NODE_ID,
+            span: DUMMY_SP,
+            tokens: None,
+        }));
+    }
+
+    // the crates have been injected, the assumption is that the first one is the one with
+    // the prelude.
+    let name = names[0];
+
+    let span = DUMMY_SP.fresh_expansion(ExpnId::root(), ExpnInfo::allow_unstable(
+        ExpnKind::Macro(MacroKind::Attr, sym::std_inject), DUMMY_SP, edition,
+        [sym::prelude_import][..].into(),
+    ));
+
+    krate.module.items.insert(0, P(ast::Item {
+        attrs: vec![ast::Attribute {
+            style: ast::AttrStyle::Outer,
+            path: ast::Path::from_ident(ast::Ident::new(sym::prelude_import, span)),
+            tokens: TokenStream::empty(),
+            id: attr::mk_attr_id(),
+            is_sugared_doc: false,
+            span,
+        }],
+        vis: respan(span.shrink_to_lo(), ast::VisibilityKind::Inherited),
+        node: ast::ItemKind::Use(P(ast::UseTree {
+            prefix: ast::Path {
+                segments: iter::once(ast::Ident::with_empty_ctxt(kw::PathRoot))
+                    .chain(
+                        [name, "prelude", "v1"].iter().cloned()
+                            .map(ast::Ident::from_str)
+                    ).map(ast::PathSegment::from_ident).collect(),
+                span,
+            },
+            kind: ast::UseTreeKind::Glob,
+            span,
+        })),
+        id: ast::DUMMY_NODE_ID,
+        ident: ast::Ident::invalid(),
+        span,
+        tokens: None,
+    }));
+
+    (krate, Some(Symbol::intern(name)))
+}
index d381c42f9ce84a1b543912144a35272f90c1e7d1..a2d93d01cec5623c9e463008ad69cb6baa11f0db 100644 (file)
@@ -7,11 +7,44 @@
 use syntax::ext::build::AstBuilder;
 use syntax::ext::hygiene::SyntaxContext;
 use syntax::print::pprust;
+use syntax::source_map::respan;
 use syntax::symbol::{Symbol, sym};
 use syntax_pos::Span;
 
 use std::iter;
 
+// #[test_case] is used by custom test authors to mark tests
+// When building for test, it needs to make the item public and gensym the name
+// Otherwise, we'll omit the item. This behavior means that any item annotated
+// with #[test_case] is never addressable.
+//
+// We mark item with an inert attribute "rustc_test_marker" which the test generation
+// logic will pick up on.
+pub fn expand_test_case(
+    ecx: &mut ExtCtxt<'_>,
+    attr_sp: Span,
+    meta_item: &ast::MetaItem,
+    anno_item: Annotatable
+) -> Vec<Annotatable> {
+    check_builtin_macro_attribute(ecx, meta_item, sym::test_case);
+
+    if !ecx.ecfg.should_test { return vec![]; }
+
+    let sp = attr_sp.with_ctxt(SyntaxContext::empty().apply_mark(ecx.current_expansion.id));
+    let mut item = anno_item.expect_item();
+    item = item.map(|mut item| {
+        item.vis = respan(item.vis.span, ast::VisibilityKind::Public);
+        item.ident = item.ident.gensym();
+        item.attrs.push(
+            ecx.attribute(sp,
+                ecx.meta_word(sp, sym::rustc_test_marker))
+        );
+        item
+    });
+
+    return vec![Annotatable::Item(item)]
+}
+
 pub fn expand_test(
     cx: &mut ExtCtxt<'_>,
     attr_sp: Span,
diff --git a/src/libsyntax_ext/test_case.rs b/src/libsyntax_ext/test_case.rs
deleted file mode 100644 (file)
index ea4a8d5..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-// http://rust-lang.org/COPYRIGHT.
-//
-
-// #[test_case] is used by custom test authors to mark tests
-// When building for test, it needs to make the item public and gensym the name
-// Otherwise, we'll omit the item. This behavior means that any item annotated
-// with #[test_case] is never addressable.
-//
-// We mark item with an inert attribute "rustc_test_marker" which the test generation
-// logic will pick up on.
-
-use syntax::ast;
-use syntax::attr::check_builtin_macro_attribute;
-use syntax::ext::base::*;
-use syntax::ext::build::AstBuilder;
-use syntax::ext::hygiene::SyntaxContext;
-use syntax::source_map::respan;
-use syntax::symbol::sym;
-use syntax_pos::Span;
-
-pub fn expand(
-    ecx: &mut ExtCtxt<'_>,
-    attr_sp: Span,
-    meta_item: &ast::MetaItem,
-    anno_item: Annotatable
-) -> Vec<Annotatable> {
-    check_builtin_macro_attribute(ecx, meta_item, sym::test_case);
-
-    if !ecx.ecfg.should_test { return vec![]; }
-
-    let sp = attr_sp.with_ctxt(SyntaxContext::empty().apply_mark(ecx.current_expansion.id));
-    let mut item = anno_item.expect_item();
-    item = item.map(|mut item| {
-        item.vis = respan(item.vis.span, ast::VisibilityKind::Public);
-        item.ident = item.ident.gensym();
-        item.attrs.push(
-            ecx.attribute(sp,
-                ecx.meta_word(sp, sym::rustc_test_marker))
-        );
-        item
-    });
-
-    return vec![Annotatable::Item(item)]
-}
diff --git a/src/libsyntax_ext/test_harness.rs b/src/libsyntax_ext/test_harness.rs
new file mode 100644 (file)
index 0000000..848c797
--- /dev/null
@@ -0,0 +1,394 @@
+// Code that generates a test runner to run all the tests in a crate
+
+use log::debug;
+use smallvec::{smallvec, SmallVec};
+use syntax::ast::{self, Ident};
+use syntax::attr;
+use syntax::entry::{self, EntryPointType};
+use syntax::ext::base::{ExtCtxt, Resolver};
+use syntax::ext::build::AstBuilder;
+use syntax::ext::expand::ExpansionConfig;
+use syntax::ext::hygiene::{ExpnId, MacroKind};
+use syntax::feature_gate::Features;
+use syntax::mut_visit::{*, ExpectOne};
+use syntax::parse::ParseSess;
+use syntax::ptr::P;
+use syntax::source_map::{ExpnInfo, ExpnKind, dummy_spanned};
+use syntax::symbol::{kw, sym, Symbol};
+use syntax_pos::{Span, DUMMY_SP};
+
+use std::{iter, mem};
+
+struct Test {
+    span: Span,
+    path: Vec<Ident>,
+}
+
+struct TestCtxt<'a> {
+    span_diagnostic: &'a errors::Handler,
+    path: Vec<Ident>,
+    ext_cx: ExtCtxt<'a>,
+    test_cases: Vec<Test>,
+    reexport_test_harness_main: Option<Symbol>,
+    test_runner: Option<ast::Path>,
+    // top-level re-export submodule, filled out after folding is finished
+    toplevel_reexport: Option<Ident>,
+}
+
+// Traverse the crate, collecting all the test functions, eliding any
+// existing main functions, and synthesizing a main test harness
+pub fn inject(
+    sess: &ParseSess,
+    resolver: &mut dyn Resolver,
+    should_test: bool,
+    krate: &mut ast::Crate,
+    span_diagnostic: &errors::Handler,
+    features: &Features,
+) {
+    // Check for #[reexport_test_harness_main = "some_name"] which
+    // creates a `use __test::main as some_name;`. This needs to be
+    // unconditional, so that the attribute is still marked as used in
+    // non-test builds.
+    let reexport_test_harness_main =
+        attr::first_attr_value_str_by_name(&krate.attrs, sym::reexport_test_harness_main);
+
+    // Do this here so that the test_runner crate attribute gets marked as used
+    // even in non-test builds
+    let test_runner = get_test_runner(span_diagnostic, &krate);
+
+    if should_test {
+        generate_test_harness(sess, resolver, reexport_test_harness_main,
+                              krate, span_diagnostic, features, test_runner)
+    }
+}
+
+struct TestHarnessGenerator<'a> {
+    cx: TestCtxt<'a>,
+    tests: Vec<Ident>,
+
+    // submodule name, gensym'd identifier for re-exports
+    tested_submods: Vec<(Ident, Ident)>,
+}
+
+impl<'a> MutVisitor for TestHarnessGenerator<'a> {
+    fn visit_crate(&mut self, c: &mut ast::Crate) {
+        noop_visit_crate(c, self);
+
+        // Create a main function to run our tests
+        let test_main = {
+            let unresolved = mk_main(&mut self.cx);
+            self.cx.ext_cx.monotonic_expander().flat_map_item(unresolved).pop().unwrap()
+        };
+
+        c.module.items.push(test_main);
+    }
+
+    fn flat_map_item(&mut self, i: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
+        let ident = i.ident;
+        if ident.name != kw::Invalid {
+            self.cx.path.push(ident);
+        }
+        debug!("current path: {}", path_name_i(&self.cx.path));
+
+        let mut item = i.into_inner();
+        if is_test_case(&item) {
+            debug!("this is a test item");
+
+            let test = Test {
+                span: item.span,
+                path: self.cx.path.clone(),
+            };
+            self.cx.test_cases.push(test);
+            self.tests.push(item.ident);
+        }
+
+        // We don't want to recurse into anything other than mods, since
+        // mods or tests inside of functions will break things
+        if let ast::ItemKind::Mod(mut module) = item.node {
+            let tests = mem::take(&mut self.tests);
+            let tested_submods = mem::take(&mut self.tested_submods);
+            noop_visit_mod(&mut module, self);
+            let tests = mem::replace(&mut self.tests, tests);
+            let tested_submods = mem::replace(&mut self.tested_submods, tested_submods);
+
+            if !tests.is_empty() || !tested_submods.is_empty() {
+                let (it, sym) = mk_reexport_mod(&mut self.cx, item.id, tests, tested_submods);
+                module.items.push(it);
+
+                if !self.cx.path.is_empty() {
+                    self.tested_submods.push((self.cx.path[self.cx.path.len()-1], sym));
+                } else {
+                    debug!("pushing nothing, sym: {:?}", sym);
+                    self.cx.toplevel_reexport = Some(sym);
+                }
+            }
+            item.node = ast::ItemKind::Mod(module);
+        }
+        if ident.name != kw::Invalid {
+            self.cx.path.pop();
+        }
+        smallvec![P(item)]
+    }
+
+    fn visit_mac(&mut self, _mac: &mut ast::Mac) {
+        // Do nothing.
+    }
+}
+
+/// A folder used to remove any entry points (like fn main) because the harness
+/// generator will provide its own
+struct EntryPointCleaner {
+    // Current depth in the ast
+    depth: usize,
+}
+
+impl MutVisitor for EntryPointCleaner {
+    fn flat_map_item(&mut self, i: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
+        self.depth += 1;
+        let item = noop_flat_map_item(i, self).expect_one("noop did something");
+        self.depth -= 1;
+
+        // Remove any #[main] or #[start] from the AST so it doesn't
+        // clash with the one we're going to add, but mark it as
+        // #[allow(dead_code)] to avoid printing warnings.
+        let item = match entry::entry_point_type(&item, self.depth) {
+            EntryPointType::MainNamed |
+            EntryPointType::MainAttr |
+            EntryPointType::Start =>
+                item.map(|ast::Item {id, ident, attrs, node, vis, span, tokens}| {
+                    let allow_ident = Ident::with_empty_ctxt(sym::allow);
+                    let dc_nested = attr::mk_nested_word_item(Ident::from_str("dead_code"));
+                    let allow_dead_code_item = attr::mk_list_item(DUMMY_SP, allow_ident,
+                                                                  vec![dc_nested]);
+                    let allow_dead_code = attr::mk_attr_outer(DUMMY_SP,
+                                                              attr::mk_attr_id(),
+                                                              allow_dead_code_item);
+
+                    ast::Item {
+                        id,
+                        ident,
+                        attrs: attrs.into_iter()
+                            .filter(|attr| {
+                                !attr.check_name(sym::main) && !attr.check_name(sym::start)
+                            })
+                            .chain(iter::once(allow_dead_code))
+                            .collect(),
+                        node,
+                        vis,
+                        span,
+                        tokens,
+                    }
+                }),
+            EntryPointType::None |
+            EntryPointType::OtherMain => item,
+        };
+
+        smallvec![item]
+    }
+
+    fn visit_mac(&mut self, _mac: &mut ast::Mac) {
+        // Do nothing.
+    }
+}
+
+/// Creates an item (specifically a module) that "pub use"s the tests passed in.
+/// Each tested submodule will contain a similar reexport module that we will export
+/// under the name of the original module. That is, `submod::__test_reexports` is
+/// reexported like so `pub use submod::__test_reexports as submod`.
+fn mk_reexport_mod(cx: &mut TestCtxt<'_>,
+                   parent: ast::NodeId,
+                   tests: Vec<Ident>,
+                   tested_submods: Vec<(Ident, Ident)>)
+                   -> (P<ast::Item>, Ident) {
+    let super_ = Ident::with_empty_ctxt(kw::Super);
+
+    let items = tests.into_iter().map(|r| {
+        cx.ext_cx.item_use_simple(DUMMY_SP, dummy_spanned(ast::VisibilityKind::Public),
+                                  cx.ext_cx.path(DUMMY_SP, vec![super_, r]))
+    }).chain(tested_submods.into_iter().map(|(r, sym)| {
+        let path = cx.ext_cx.path(DUMMY_SP, vec![super_, r, sym]);
+        cx.ext_cx.item_use_simple_(DUMMY_SP, dummy_spanned(ast::VisibilityKind::Public),
+                                   Some(r), path)
+    })).collect();
+
+    let reexport_mod = ast::Mod {
+        inline: true,
+        inner: DUMMY_SP,
+        items,
+    };
+
+    let name = Ident::from_str("__test_reexports").gensym();
+    let parent = if parent == ast::DUMMY_NODE_ID { ast::CRATE_NODE_ID } else { parent };
+    cx.ext_cx.current_expansion.id = cx.ext_cx.resolver.get_module_scope(parent);
+    let it = cx.ext_cx.monotonic_expander().flat_map_item(P(ast::Item {
+        ident: name,
+        attrs: Vec::new(),
+        id: ast::DUMMY_NODE_ID,
+        node: ast::ItemKind::Mod(reexport_mod),
+        vis: dummy_spanned(ast::VisibilityKind::Public),
+        span: DUMMY_SP,
+        tokens: None,
+    })).pop().unwrap();
+
+    (it, name)
+}
+
+/// Crawl over the crate, inserting test reexports and the test main function
+fn generate_test_harness(sess: &ParseSess,
+                         resolver: &mut dyn Resolver,
+                         reexport_test_harness_main: Option<Symbol>,
+                         krate: &mut ast::Crate,
+                         sd: &errors::Handler,
+                         features: &Features,
+                         test_runner: Option<ast::Path>) {
+    // Remove the entry points
+    let mut cleaner = EntryPointCleaner { depth: 0 };
+    cleaner.visit_crate(krate);
+
+    let mut econfig = ExpansionConfig::default("test".to_string());
+    econfig.features = Some(features);
+
+    let cx = TestCtxt {
+        span_diagnostic: sd,
+        ext_cx: ExtCtxt::new(sess, econfig, resolver),
+        path: Vec::new(),
+        test_cases: Vec::new(),
+        reexport_test_harness_main,
+        toplevel_reexport: None,
+        test_runner
+    };
+
+    TestHarnessGenerator {
+        cx,
+        tests: Vec::new(),
+        tested_submods: Vec::new(),
+    }.visit_crate(krate);
+}
+
+/// Creates a function item for use as the main function of a test build.
+/// This function will call the `test_runner` as specified by the crate attribute
+fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
+    // Writing this out by hand:
+    //        pub fn main() {
+    //            #![main]
+    //            test::test_main_static(&[..tests]);
+    //        }
+    let sp = DUMMY_SP.fresh_expansion(ExpnId::root(), ExpnInfo::allow_unstable(
+        ExpnKind::Macro(MacroKind::Attr, sym::test_case), DUMMY_SP, cx.ext_cx.parse_sess.edition,
+        [sym::main, sym::test, sym::rustc_attrs][..].into(),
+    ));
+    let ecx = &cx.ext_cx;
+    let test_id = Ident::with_empty_ctxt(sym::test);
+
+    // test::test_main_static(...)
+    let mut test_runner = cx.test_runner.clone().unwrap_or(
+        ecx.path(sp, vec![
+            test_id, ecx.ident_of("test_main_static")
+        ]));
+
+    test_runner.span = sp;
+
+    let test_main_path_expr = ecx.expr_path(test_runner);
+    let call_test_main = ecx.expr_call(sp, test_main_path_expr,
+                                       vec![mk_tests_slice(cx)]);
+    let call_test_main = ecx.stmt_expr(call_test_main);
+
+    // #![main]
+    let main_meta = ecx.meta_word(sp, sym::main);
+    let main_attr = ecx.attribute(sp, main_meta);
+
+    // extern crate test as test_gensym
+    let test_extern_stmt = ecx.stmt_item(sp, ecx.item(sp,
+        test_id,
+        vec![],
+        ast::ItemKind::ExternCrate(None)
+    ));
+
+    // pub fn main() { ... }
+    let main_ret_ty = ecx.ty(sp, ast::TyKind::Tup(vec![]));
+
+    // If no test runner is provided we need to import the test crate
+    let main_body = if cx.test_runner.is_none() {
+        ecx.block(sp, vec![test_extern_stmt, call_test_main])
+    } else {
+        ecx.block(sp, vec![call_test_main])
+    };
+
+    let main = ast::ItemKind::Fn(ecx.fn_decl(vec![], ast::FunctionRetTy::Ty(main_ret_ty)),
+                           ast::FnHeader::default(),
+                           ast::Generics::default(),
+                           main_body);
+
+    // Honor the reexport_test_harness_main attribute
+    let main_id = match cx.reexport_test_harness_main {
+        Some(sym) => Ident::new(sym, sp),
+        None => Ident::from_str_and_span("main", sp).gensym(),
+    };
+
+    P(ast::Item {
+        ident: main_id,
+        attrs: vec![main_attr],
+        id: ast::DUMMY_NODE_ID,
+        node: main,
+        vis: dummy_spanned(ast::VisibilityKind::Public),
+        span: sp,
+        tokens: None,
+    })
+
+}
+
+fn path_name_i(idents: &[Ident]) -> String {
+    let mut path_name = "".to_string();
+    let mut idents_iter = idents.iter().peekable();
+    while let Some(ident) = idents_iter.next() {
+        path_name.push_str(&ident.as_str());
+        if idents_iter.peek().is_some() {
+            path_name.push_str("::")
+        }
+    }
+    path_name
+}
+
+/// Creates a slice containing every test like so:
+/// &[path::to::test1, path::to::test2]
+fn mk_tests_slice(cx: &TestCtxt<'_>) -> P<ast::Expr> {
+    debug!("building test vector from {} tests", cx.test_cases.len());
+    let ref ecx = cx.ext_cx;
+
+    ecx.expr_vec_slice(DUMMY_SP,
+        cx.test_cases.iter().map(|test| {
+            ecx.expr_addr_of(test.span,
+                ecx.expr_path(ecx.path(test.span, visible_path(cx, &test.path))))
+        }).collect())
+}
+
+/// Creates a path from the top-level __test module to the test via __test_reexports
+fn visible_path(cx: &TestCtxt<'_>, path: &[Ident]) -> Vec<Ident>{
+    let mut visible_path = vec![];
+    match cx.toplevel_reexport {
+        Some(id) => visible_path.push(id),
+        None => {
+            cx.span_diagnostic.bug("expected to find top-level re-export name, but found None");
+        }
+    }
+    visible_path.extend_from_slice(path);
+    visible_path
+}
+
+fn is_test_case(i: &ast::Item) -> bool {
+    attr::contains_name(&i.attrs, sym::rustc_test_marker)
+}
+
+fn get_test_runner(sd: &errors::Handler, krate: &ast::Crate) -> Option<ast::Path> {
+    let test_attr = attr::find_by_name(&krate.attrs, sym::test_runner)?;
+    test_attr.meta_item_list().map(|meta_list| {
+        if meta_list.len() != 1 {
+            sd.span_fatal(test_attr.span,
+                "`#![test_runner(..)]` accepts exactly 1 argument").raise()
+        }
+        match meta_list[0].meta_item() {
+            Some(meta_item) if meta_item.is_word() => meta_item.path.clone(),
+            _ => sd.span_fatal(test_attr.span, "`test_runner` argument must be a path").raise()
+        }
+    })
+}
index e5f0892b37be8dcdd726d10a9fadcb461e2deb0e..acc13aec4022999c39c0c2271c67238b3a90b93f 100644 (file)
@@ -6,9 +6,6 @@
 
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
 
-#![deny(rust_2018_idioms)]
-#![deny(unused_lifetimes)]
-
 #![feature(const_fn)]
 #![feature(crate_visibility_modifier)]
 #![feature(nll)]
index 3b5ac7baf20bd29b3c0d6213ee86045d4b9fa3cb..ad1a83316be7c316cc78d8c71d8532595f4f695b 100644 (file)
@@ -35,8 +35,6 @@
        test(attr(deny(warnings))))]
 #![deny(missing_docs)]
 
-#![deny(rust_2018_idioms)]
-
 #![cfg_attr(windows, feature(libc))]
 
 use std::io::prelude::*;
index fa45c9d7d9d796a81369a1d1f3ea7c482fc52909..653dce32e50cac6734cf9ac4962a8ae59fadb0f4 100644 (file)
@@ -17,7 +17,6 @@
 // this crate, which relies on this attribute (rather than the value of `--crate-name` passed by
 // cargo) to detect this crate.
 
-#![deny(rust_2018_idioms)]
 #![crate_name = "test"]
 #![unstable(feature = "test", issue = "27812")]
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/", test(attr(deny(warnings))))]
index 9182e349b196ea1893d48243c952fa40e480b40d..b9ce71b6b847ec1dddc6bcb331d62ac1afe0ad8c 100644 (file)
@@ -1,8 +1,6 @@
 #![no_std]
 #![unstable(feature = "panic_unwind", issue = "32837")]
 
-#![deny(rust_2018_idioms)]
-
 #![feature(link_cfg)]
 #![feature(nll)]
 #![feature(staged_api)]
index f6446fa8e9629ffb1861303f17930c3aa83ef660..9b64ca5b7e1e3583978f9ac8af6d93b220a13d90 160000 (submodule)
@@ -1 +1 @@
-Subproject commit f6446fa8e9629ffb1861303f17930c3aa83ef660
+Subproject commit 9b64ca5b7e1e3583978f9ac8af6d93b220a13d90
index fac5ef3b03ce16798d1be23dea7a7e2460bc8a51..c249154c71e23b19e08de5cc599ece1a267d3c6d 100644 (file)
@@ -8,7 +8,7 @@ fn move_out_from_end() {
 
 fn move_out_by_subslice() {
     let a = [box 1, box 2];
-    let [_y..] = a;
+    let [_y @ ..] = a;
 }
 
 fn main() {
index 3c4f2cd541f4eec09859ac0677a4f11cafa604a2..afc92638fda978c767f917da8872e07b149d8878 100644 (file)
@@ -2,8 +2,7 @@
 
 extern crate rustc;
 extern crate rustc_interface;
-#[allow(unused_extern_crates)]
-extern crate rustc_driver;
+extern crate rustc_driver as _;
 extern crate syntax;
 
 use rustc::session::DiagnosticOutput;
index c671ab581efbe55f942160c788455ccca95b6370..dde73ba69f7bf30f0de9732d52172caa35e25cad 100644 (file)
@@ -5,7 +5,6 @@
 // libsyntax is not compiled for it.
 
 #![deny(plugin_as_library)]
-#![allow(unused_extern_crates)]
 
 extern crate attr_plugin_test; //~ ERROR compiler plugin used as an ordinary library
 
index ccc9580a60c2980b28c1d2e5076fe1ce856ef4e0..4daa4a2c821208660fd16ddd62c3df4dd79d105e 100644 (file)
@@ -1,5 +1,5 @@
 error: compiler plugin used as an ordinary library
-  --> $DIR/plugin-as-extern-crate.rs:10:1
+  --> $DIR/plugin-as-extern-crate.rs:9:1
    |
 LL | extern crate attr_plugin_test;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
index 2b19c49c42700d1e06a43505fb8b06e4463aeba9..f416160db242247af496b9fcec2a33b7e61fc6a5 100644 (file)
@@ -11,7 +11,7 @@ fn foldl<T, U, F>(values: &[T],
     U: Clone+Debug, T:Debug,
     F: FnMut(U, &T) -> U,
 {    match values {
-        &[ref head, ref tail..] =>
+        &[ref head, ref tail @ ..] =>
             foldl(tail, function(initial, head), function),
         &[] => {
             // FIXME: call guards
@@ -28,7 +28,7 @@ fn foldr<T, U, F>(values: &[T],
     F: FnMut(&T, U) -> U,
 {
     match values {
-        &[ref head.., ref tail] =>
+        &[ref head @ .., ref tail] =>
             foldr(head, function(tail, initial), function),
         &[] => {
             // FIXME: call guards
index bce03b3375e5160ff07d74a23c8307991918fc3d..f0602c328b071af010092e6b513c8970b72ede24 100644 (file)
@@ -8,7 +8,7 @@ pub fn main() {
     let x: &[isize] = &[1, 2, 3, 4, 5];
     if !x.is_empty() {
         let el = match x {
-            &[1, ref tail..] => &tail[0],
+            &[1, ref tail @ ..] => &tail[0],
             _ => unreachable!()
         };
         println!("{}", *el);
index a37c25160fa76e317bf1887cf20ee56738e875e7..49c736bd72847377503b7942da89fa5e126d0986 100644 (file)
@@ -14,7 +14,7 @@ fn a() {
 fn b() {
     let x = [1, 2, 3];
     match x {
-        [a, b, c..] => {
+        [a, b, c @ ..] => {
             assert_eq!(a, 1);
             assert_eq!(b, 2);
             let expected: &[_] = &[3];
@@ -22,7 +22,7 @@ fn b() {
         }
     }
     match x {
-        [a.., b, c] => {
+        [a @ .., b, c] => {
             let expected: &[_] = &[1];
             assert_eq!(a, expected);
             assert_eq!(b, 2);
@@ -30,7 +30,7 @@ fn b() {
         }
     }
     match x {
-        [a, b.., c] => {
+        [a, b @ .., c] => {
             assert_eq!(a, 1);
             let expected: &[_] = &[2];
             assert_eq!(b, expected);
@@ -50,7 +50,7 @@ fn b() {
 fn b_slice() {
     let x : &[_] = &[1, 2, 3];
     match x {
-        &[a, b, ref c..] => {
+        &[a, b, ref c @ ..] => {
             assert_eq!(a, 1);
             assert_eq!(b, 2);
             let expected: &[_] = &[3];
@@ -59,7 +59,7 @@ fn b_slice() {
         _ => unreachable!()
     }
     match x {
-        &[ref a.., b, c] => {
+        &[ref a @ .., b, c] => {
             let expected: &[_] = &[1];
             assert_eq!(a, expected);
             assert_eq!(b, 2);
@@ -68,7 +68,7 @@ fn b_slice() {
         _ => unreachable!()
     }
     match x {
-        &[a, ref b.., c] => {
+        &[a, ref b @ .., c] => {
             assert_eq!(a, 1);
             let expected: &[_] = &[2];
             assert_eq!(b, expected);
@@ -134,20 +134,6 @@ fn e() {
     assert_eq!(c, 1);
 }
 
-fn f() {
-    let x = &[1, 2, 3, 4, 5];
-    let [a, [b, [c, ..].., d].., e] = *x;
-    assert_eq!((a, b, c, d, e), (1, 2, 3, 4, 5));
-
-    let x: &[isize] = x;
-    let (a, b, c, d, e) = match *x {
-        [a, [b, [c, ..].., d].., e] => (a, b, c, d, e),
-        _ => unimplemented!()
-    };
-
-    assert_eq!((a, b, c, d, e), (1, 2, 3, 4, 5));
-}
-
 pub fn main() {
     a();
     b();
@@ -155,5 +141,4 @@ pub fn main() {
     c();
     d();
     e();
-    f();
 }
index 84d246dff825c2de55bfb3da8001ad0912031849..3c7b160dcc54038a9e218761b84e6c3c86184cac 100644 (file)
@@ -13,14 +13,14 @@ pub fn main() {
         Foo { string: "baz" }
     ];
     match x {
-        [ref first, ref tail..] => {
+        [ref first, ref tail @ ..] => {
             assert_eq!(first.string, "foo");
             assert_eq!(tail.len(), 2);
             assert_eq!(tail[0].string, "bar");
             assert_eq!(tail[1].string, "baz");
 
             match *(tail as &[_]) {
-                [Foo { .. }, _, Foo { .. }, ref _tail..] => {
+                [Foo { .. }, _, Foo { .. }, ref _tail @ ..] => {
                     unreachable!();
                 }
                 [Foo { string: ref a }, Foo { string: ref b }] => {
index d159082ab7ad5d0fcc1c7fdfa79de19268dae686..20a6fd83faa327fa9a6e63d86f7798abbc1337d7 100644 (file)
@@ -5,6 +5,5 @@ fn main() {
     let _ = <<A>::B>::C; //~ ERROR cannot find type `A` in this scope
     let <<A>::B>::C; //~ ERROR cannot find type `A` in this scope
     let 0 ..= <<A>::B>::C; //~ ERROR cannot find type `A` in this scope
-                           //~^ ERROR only char and numeric types are allowed in range patterns
     <<A>::B>::C; //~ ERROR cannot find type `A` in this scope
 }
index 23918ed2e39120e5d6b329e16056af381f3941bf..71ee93f4835fbc92c10e1a7184ee600e34f45e49 100644 (file)
@@ -23,21 +23,11 @@ LL |     let 0 ..= <<A>::B>::C;
    |                 ^ not found in this scope
 
 error[E0412]: cannot find type `A` in this scope
-  --> $DIR/associated-path-shl.rs:9:7
+  --> $DIR/associated-path-shl.rs:8:7
    |
 LL |     <<A>::B>::C;
    |       ^ not found in this scope
 
-error[E0029]: only char and numeric types are allowed in range patterns
-  --> $DIR/associated-path-shl.rs:7:15
-   |
-LL |     let 0 ..= <<A>::B>::C;
-   |               ^^^^^^^^^^^ ranges require char or numeric types
-   |
-   = note: start type: {integer}
-   = note: end type: [type error]
-
-error: aborting due to 6 previous errors
+error: aborting due to 5 previous errors
 
-Some errors have detailed explanations: E0029, E0412.
-For more information about an error, try `rustc --explain E0029`.
+For more information about this error, try `rustc --explain E0412`.
index 69914b6a7910fc42ee9468fc3eee0b9c7cf72c9a..64f6eccd5479a963e34a526eca568e2712b6a4e9 100644 (file)
@@ -1,11 +1,11 @@
-error[E0720]: opaque type expands to a recursive type
+error[E0733]: recursion in an `async fn` requires boxing
   --> $DIR/recursive-async-impl-trait-type.rs:7:40
    |
 LL | async fn recursive_async_function() -> () {
-   |                                        ^^ expands to a recursive type
+   |                                        ^^ an `async fn` cannot invoke itself directly
    |
-   = note: expanded type is `std::future::GenFuture<[static generator@$DIR/recursive-async-impl-trait-type.rs:7:43: 9:2 {impl std::future::Future, ()}]>`
+   = note: a recursive `async fn` must be rewritten to return a boxed future.
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0720`.
+For more information about this error, try `rustc --explain E0733`.
index 733e6b7b57f72ae58dfb012932e5cfa70f3be744..ac733ef6e9c862c7b96628fefb8ad34ecc26072c 100644 (file)
@@ -4,7 +4,7 @@
 #![feature(slice_patterns)]
 
 fn foo(s: &[i32]) -> &[i32] {
-    let &[ref xs..] = s;
+    let &[ref xs @ ..] = s;
     xs
 }
 
index 51e1c024bffff76947524b71773a78e290cd92d5..5326fa612a87bed365fa28a763af3d040a1f3391 100644 (file)
@@ -7,6 +7,6 @@ fn main() {
     // The subslice used to go out of bounds for zero-sized array items, check that this doesn't
     // happen anymore
     match x {
-        [_, ref y..] => assert_eq!(&x[1] as *const (), &y[0] as *const ())
+        [_, ref y @ ..] => assert_eq!(&x[1] as *const (), &y[0] as *const ())
     }
 }
index f1e1ae18839c4ed848c0a4fbdebe33faf8f76b87..20f05353d4633c8f39301f697220c99eadbafeba 100644 (file)
@@ -192,8 +192,8 @@ error[E0503]: cannot use `v[..]` because it was mutably borrowed
 LL |         let x = &mut v;
    |                 ------ borrow of `v` occurs here
 LL |         match v {
-LL |             &[x..] => println!("{:?}", x),
-   |               ^ use of borrowed `v`
+LL |             &[x @ ..] => println!("{:?}", x),
+   |               ^^^^^^ use of borrowed `v`
 ...
 LL |         drop(x);
    |              - borrow later used here
@@ -204,8 +204,8 @@ error[E0503]: cannot use `v[..]` because it was mutably borrowed
 LL |         let x = &mut v;
    |                 ------ borrow of `v` occurs here
 ...
-LL |             &[_, x..] => println!("{:?}", x),
-   |                  ^ use of borrowed `v`
+LL |             &[_, x @ ..] => println!("{:?}", x),
+   |                  ^^^^^^ use of borrowed `v`
 ...
 LL |         drop(x);
    |              - borrow later used here
@@ -216,8 +216,8 @@ error[E0503]: cannot use `v[..]` because it was mutably borrowed
 LL |         let x = &mut v;
    |                 ------ borrow of `v` occurs here
 ...
-LL |             &[x.., _] => println!("{:?}", x),
-   |               ^ use of borrowed `v`
+LL |             &[x @ .., _] => println!("{:?}", x),
+   |               ^^^^^^ use of borrowed `v`
 ...
 LL |         drop(x);
    |              - borrow later used here
@@ -228,8 +228,8 @@ error[E0503]: cannot use `v[..]` because it was mutably borrowed
 LL |         let x = &mut v;
    |                 ------ borrow of `v` occurs here
 ...
-LL |             &[_, x.., _] => println!("{:?}", x),
-   |                  ^ use of borrowed `v`
+LL |             &[_, x @ .., _] => println!("{:?}", x),
+   |                  ^^^^^^ use of borrowed `v`
 ...
 LL |         drop(x);
    |              - borrow later used here
index c8dbf4e6918169bfee9d2c5e9a5b09a9a6bb9a93..c27d9519dc7986f640221273ad467e330e80a21b 100644 (file)
@@ -140,22 +140,22 @@ fn main() {
         let mut v = &[1, 2, 3, 4, 5];
         let x = &mut v;
         match v {
-            &[x..] => println!("{:?}", x),
+            &[x @ ..] => println!("{:?}", x),
                 //~^ ERROR cannot use `v[..]` because it was mutably borrowed
             _ => panic!("other case"),
         }
         match v {
-            &[_, x..] => println!("{:?}", x),
+            &[_, x @ ..] => println!("{:?}", x),
                 //~^ ERROR cannot use `v[..]` because it was mutably borrowed
             _ => panic!("other case"),
         }
         match v {
-            &[x.., _] => println!("{:?}", x),
+            &[x @ .., _] => println!("{:?}", x),
                 //~^ ERROR cannot use `v[..]` because it was mutably borrowed
             _ => panic!("other case"),
         }
         match v {
-            &[_, x.., _] => println!("{:?}", x),
+            &[_, x @ .., _] => println!("{:?}", x),
                 //~^ ERROR cannot use `v[..]` because it was mutably borrowed
             _ => panic!("other case"),
         }
index 14b9b50f0c32a6352eeed0c16209e1aabf13411c..38d847a90ff958b36a864912746323552b9776a8 100644 (file)
@@ -192,8 +192,8 @@ error[E0503]: cannot use `v[..]` because it was mutably borrowed
 LL |         let x = &mut v;
    |                 ------ borrow of `v` occurs here
 LL |         match v {
-LL |             &[x..] => println!("{:?}", x),
-   |               ^ use of borrowed `v`
+LL |             &[x @ ..] => println!("{:?}", x),
+   |               ^^^^^^ use of borrowed `v`
 ...
 LL |         drop(x);
    |              - borrow later used here
@@ -204,8 +204,8 @@ error[E0503]: cannot use `v[..]` because it was mutably borrowed
 LL |         let x = &mut v;
    |                 ------ borrow of `v` occurs here
 ...
-LL |             &[_, x..] => println!("{:?}", x),
-   |                  ^ use of borrowed `v`
+LL |             &[_, x @ ..] => println!("{:?}", x),
+   |                  ^^^^^^ use of borrowed `v`
 ...
 LL |         drop(x);
    |              - borrow later used here
@@ -216,8 +216,8 @@ error[E0503]: cannot use `v[..]` because it was mutably borrowed
 LL |         let x = &mut v;
    |                 ------ borrow of `v` occurs here
 ...
-LL |             &[x.., _] => println!("{:?}", x),
-   |               ^ use of borrowed `v`
+LL |             &[x @ .., _] => println!("{:?}", x),
+   |               ^^^^^^ use of borrowed `v`
 ...
 LL |         drop(x);
    |              - borrow later used here
@@ -228,8 +228,8 @@ error[E0503]: cannot use `v[..]` because it was mutably borrowed
 LL |         let x = &mut v;
    |                 ------ borrow of `v` occurs here
 ...
-LL |             &[_, x.., _] => println!("{:?}", x),
-   |                  ^ use of borrowed `v`
+LL |             &[_, x @ .., _] => println!("{:?}", x),
+   |                  ^^^^^^ use of borrowed `v`
 ...
 LL |         drop(x);
    |              - borrow later used here
index 856b03edd2d7279fe2bbfaeca4972a98d710ac95..ee6abf407a30490afd7acb14ef766ca885a8bb4c 100644 (file)
@@ -10,7 +10,7 @@ fn move_out_from_begin_and_end() {
 fn move_out_by_const_index_and_subslice() {
     let a = [box 1, box 2];
     let [_x, _] = a;
-    let [_y..] = a; //~ ERROR [E0382]
+    let [_y @ ..] = a; //~ ERROR [E0382]
 }
 
 fn main() {}
index 16722a456defa4d54ea5048f5f72620f701fc46d..b34c03e6deff8d54151abb621335e6e47706339e 100644 (file)
@@ -13,8 +13,8 @@ error[E0382]: use of moved value: `a[..]`
    |
 LL |     let [_x, _] = a;
    |          -- value moved here
-LL |     let [_y..] = a;
-   |          ^^ value used here after move
+LL |     let [_y @ ..] = a;
+   |          ^^^^^^^ value used here after move
    |
    = note: move occurs because `a[..]` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
 
index cc524c1ac3e6e1cefbd9451187597e779562e803..fa9a3c217db77ec0eefc88d5128f6e1fcaa2f271 100644 (file)
@@ -15,7 +15,7 @@ pub fn main() {
     ];
     let x: &[Foo] = &x;
     match *x {
-        [_, ref tail..] => {
+        [_, ref tail @ ..] => {
             match tail {
             //~^ ERROR cannot move out of type `[Foo]`
                 &[Foo { string: a },
index 7675147c8ec2aae1cf4701d3992083564c8f246b..048813b2b93e6fd6970eabe2df65509f36217369 100644 (file)
@@ -5,7 +5,7 @@
 
 fn mut_head_tail<'a, A>(v: &'a mut [A]) -> Option<(&'a mut A, &'a mut [A])> {
     match *v {
-        [ref mut head, ref mut tail..] => {
+        [ref mut head, ref mut tail @ ..] => {
             Some((head, tail))
         }
         [] => None
index 5de8dd3305e37ad5353065588260ab20b0531baa..a6b54f9537ddcf5409240dcc08558a6372682eca 100644 (file)
@@ -70,7 +70,7 @@ fn const_index_mixed(s: &mut [i32]) {
 
 fn const_index_and_subslice_ok(s: &mut [i32]) {
     if let [ref first, ref second, ..] = *s {
-        if let [_, _, ref mut tail..] = *s {
+        if let [_, _, ref mut tail @ ..] = *s {
             nop(&[first, second]);
             nop_subslice(tail);
         }
@@ -79,7 +79,7 @@ fn const_index_and_subslice_ok(s: &mut [i32]) {
 
 fn const_index_and_subslice_err(s: &mut [i32]) {
     if let [ref first, ref second, ..] = *s {
-        if let [_, ref mut tail..] = *s { //~ERROR
+        if let [_, ref mut tail @ ..] = *s { //~ERROR
             nop(&[first, second]);
             nop_subslice(tail);
         }
@@ -88,7 +88,7 @@ fn const_index_and_subslice_err(s: &mut [i32]) {
 
 fn const_index_and_subslice_from_end_ok(s: &mut [i32]) {
     if let [.., ref second, ref first] = *s {
-        if let [ref mut tail.., _, _] = *s {
+        if let [ref mut tail @ .., _, _] = *s {
             nop(&[first, second]);
             nop_subslice(tail);
         }
@@ -97,7 +97,7 @@ fn const_index_and_subslice_from_end_ok(s: &mut [i32]) {
 
 fn const_index_and_subslice_from_end_err(s: &mut [i32]) {
     if let [.., ref second, ref first] = *s {
-        if let [ref mut tail.., _] = *s { //~ERROR
+        if let [ref mut tail @ .., _] = *s { //~ERROR
             nop(&[first, second]);
             nop_subslice(tail);
         }
@@ -105,8 +105,8 @@ fn const_index_and_subslice_from_end_err(s: &mut [i32]) {
 }
 
 fn subslices(s: &mut [i32]) {
-    if let [_, _, _, ref s1..] = *s {
-        if let [ref mut s2.., _, _, _] = *s { //~ERROR
+    if let [_, _, _, ref s1 @ ..] = *s {
+        if let [ref mut s2 @ .., _, _, _] = *s { //~ERROR
             nop_subslice(s1);
             nop_subslice(s2);
         }
index f716ee68b00022448de4cf5641e460504e261b6d..2c019f446118208c962f48831809934022a7aa7e 100644 (file)
@@ -89,8 +89,8 @@ error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as im
    |
 LL |     if let [ref first, ref second, ..] = *s {
    |                        ---------- immutable borrow occurs here
-LL |         if let [_, ref mut tail..] = *s {
-   |                    ^^^^^^^^^^^^ mutable borrow occurs here
+LL |         if let [_, ref mut tail @ ..] = *s {
+   |                    ^^^^^^^^^^^^^^^^^ mutable borrow occurs here
 LL |             nop(&[first, second]);
    |                          ------ immutable borrow later used here
 
@@ -99,18 +99,18 @@ error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as im
    |
 LL |     if let [.., ref second, ref first] = *s {
    |                 ---------- immutable borrow occurs here
-LL |         if let [ref mut tail.., _] = *s {
-   |                 ^^^^^^^^^^^^ mutable borrow occurs here
+LL |         if let [ref mut tail @ .., _] = *s {
+   |                 ^^^^^^^^^^^^^^^^^ mutable borrow occurs here
 LL |             nop(&[first, second]);
    |                          ------ immutable borrow later used here
 
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
   --> $DIR/borrowck-slice-pattern-element-loan.rs:109:17
    |
-LL |     if let [_, _, _, ref s1..] = *s {
-   |                      ------ immutable borrow occurs here
-LL |         if let [ref mut s2.., _, _, _] = *s {
-   |                 ^^^^^^^^^^ mutable borrow occurs here
+LL |     if let [_, _, _, ref s1 @ ..] = *s {
+   |                      ----------- immutable borrow occurs here
+LL |         if let [ref mut s2 @ .., _, _, _] = *s {
+   |                 ^^^^^^^^^^^^^^^ mutable borrow occurs here
 LL |             nop_subslice(s1);
    |                          -- immutable borrow later used here
 
index 100384d78c8ea96d79ec7ce663f32b0dbc104620..53a9bcef74a22beb410ed391a74f3b13a5fbd117 100644 (file)
@@ -4,7 +4,7 @@ fn a<'a>() -> &'a [isize] {
     let vec = vec![1, 2, 3, 4];
     let vec: &[isize] = &vec;
     let tail = match vec {
-        &[_, ref tail..] => tail,
+        &[_, ref tail @ ..] => tail,
         _ => panic!("a")
     };
     tail //~ ERROR cannot return value referencing local variable `vec`
@@ -14,7 +14,7 @@ fn b<'a>() -> &'a [isize] {
     let vec = vec![1, 2, 3, 4];
     let vec: &[isize] = &vec;
     let init = match vec {
-        &[ref init.., _] => init,
+        &[ref init @ .., _] => init,
         _ => panic!("b")
     };
     init //~ ERROR cannot return value referencing local variable `vec`
@@ -24,7 +24,7 @@ fn c<'a>() -> &'a [isize] {
     let vec = vec![1, 2, 3, 4];
     let vec: &[isize] = &vec;
     let slice = match vec {
-        &[_, ref slice.., _] => slice,
+        &[_, ref slice @ .., _] => slice,
         _ => panic!("c")
     };
     slice //~ ERROR cannot return value referencing local variable `vec`
index 4d99a92b18ba8ad4b5f9996c33e31cc4f94b4e0a..dd9023f6d9f791846a404f09068cfd0e9d152fa2 100644 (file)
@@ -4,7 +4,7 @@ fn a() {
     let mut v = vec![1, 2, 3];
     let vb: &mut [isize] = &mut v;
     match vb {
-        &mut [_a, ref tail..] => {
+        &mut [_a, ref tail @ ..] => {
             v.push(tail[0] + tail[1]); //~ ERROR cannot borrow
         }
         _ => {}
index efc52530716c8d6225e3b0757ca100ee3003981b..420223009a45b2f0c5624e1ef178921ae4058f96 100644 (file)
@@ -5,7 +5,7 @@
 fn main() {
     let mut a = [1, 2, 3, 4];
     let t = match a {
-        [1, 2, ref tail..] => tail,
+        [1, 2, ref tail @ ..] => tail,
         _ => unreachable!()
     };
     println!("t[0]: {}", t[0]);
index b2f553ba49f70963119bf402b0935d62c9779883..9f8e6fe3b6898dcdbae751c069093f151aee5c94 100644 (file)
@@ -1,8 +1,8 @@
 error[E0506]: cannot assign to `a[_]` because it is borrowed
   --> $DIR/borrowck-vec-pattern-move-tail.rs:12:5
    |
-LL |         [1, 2, ref tail..] => tail,
-   |                -------- borrow of `a[_]` occurs here
+LL |         [1, 2, ref tail @ ..] => tail,
+   |                ------------- borrow of `a[_]` occurs here
 ...
 LL |     a[2] = 0;
    |     ^^^^^^^^ assignment to borrowed `a[_]` occurs here
index 6448149391def94d64693953821c317d3caebe8b..a215305f684dd6aa16efafb0acca652a70a1f5f9 100644 (file)
@@ -19,7 +19,7 @@ fn b() {
     let mut vec = vec![box 1, box 2, box 3];
     let vec: &mut [Box<isize>] = &mut vec;
     match vec {
-        &mut [ref _b..] => {
+        &mut [ref _b @ ..] => {
         //~^ borrow of `vec[_]` occurs here
             vec[0] = box 4; //~ ERROR cannot assign
             //~^ NOTE assignment to borrowed `vec[_]` occurs here
index 072501f23ff840ae2654bc6db5408d290d2cf2f2..f54a3a4072cd215eaa0acea43a7cefd7e0211ec9 100644 (file)
@@ -13,8 +13,8 @@ LL |             _a.use_ref();
 error[E0506]: cannot assign to `vec[_]` because it is borrowed
   --> $DIR/borrowck-vec-pattern-nesting.rs:24:13
    |
-LL |         &mut [ref _b..] => {
-   |               ------ borrow of `vec[_]` occurs here
+LL |         &mut [ref _b @ ..] => {
+   |               ----------- borrow of `vec[_]` occurs here
 LL |
 LL |             vec[0] = box 4;
    |             ^^^^^^ assignment to borrowed `vec[_]` occurs here
index e602e75886d959acc0c9308d4638a86178cba741..c35be2f6be62c02f48a9569aa9d02a7085346122 100644 (file)
@@ -4,7 +4,7 @@ fn a<'a>() -> &'a isize {
     let vec = vec![1, 2, 3, 4];
     let vec: &[isize] = &vec;
     let tail = match vec {
-        &[_a, ref tail..] => &tail[0],
+        &[_a, ref tail @ ..] => &tail[0],
         _ => panic!("foo")
     };
     tail //~ ERROR cannot return value referencing local variable `vec`
diff --git a/src/test/ui/borrowck/return-local-binding-from-desugaring.rs b/src/test/ui/borrowck/return-local-binding-from-desugaring.rs
new file mode 100644 (file)
index 0000000..b2dcd54
--- /dev/null
@@ -0,0 +1,33 @@
+// To avoid leaking the names of local bindings from expressions like for loops, #60984
+// explicitly ignored them, but an assertion that `LocalKind::Var` *must* have a name would
+// trigger an ICE. Before this change, this file's output would be:
+// ```
+// error[E0515]: cannot return value referencing local variable `__next`
+//   --> return-local-binding-from-desugaring.rs:LL:CC
+//    |
+// LL |     for ref x in xs {
+//    |         ----- `__next` is borrowed here
+// ...
+// LL |     result
+//    |     ^^^^^^ returns a value referencing data owned by the current function
+// ```
+// FIXME: ideally `LocalKind` would carry more information to more accurately explain the problem.
+
+use std::collections::HashMap;
+use std::hash::Hash;
+
+fn group_by<I, F, T>(xs: &mut I, f: F) -> HashMap<T, Vec<&I::Item>>
+where
+    I: Iterator,
+    F: Fn(&I::Item) -> T,
+    T: Eq + Hash,
+{
+    let mut result = HashMap::new();
+    for ref x in xs {
+        let key = f(x);
+        result.entry(key).or_insert(Vec::new()).push(x);
+    }
+    result //~ ERROR cannot return value referencing local binding
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/return-local-binding-from-desugaring.stderr b/src/test/ui/borrowck/return-local-binding-from-desugaring.stderr
new file mode 100644 (file)
index 0000000..293dbe6
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0515]: cannot return value referencing local binding
+  --> $DIR/return-local-binding-from-desugaring.rs:30:5
+   |
+LL |     for ref x in xs {
+   |                  -- local binding introduced here
+...
+LL |     result
+   |     ^^^^^^ returns a value referencing data owned by the current function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0515`.
diff --git a/src/test/ui/const-generics/array-impls/alloc-traits-impls-length-32.rs b/src/test/ui/const-generics/array-impls/alloc-traits-impls-length-32.rs
new file mode 100644 (file)
index 0000000..db941a4
--- /dev/null
@@ -0,0 +1,40 @@
+// check-pass
+
+pub fn yes_vec_partial_eq_array<A, B>() -> impl PartialEq<[B; 32]>
+where
+    A: PartialEq<B>,
+{
+    Vec::<A>::new()
+}
+
+pub fn yes_vec_partial_eq_ref_array<'a, A, B>() -> impl PartialEq<&'a [B; 32]>
+where
+    A: PartialEq<B>,
+{
+    Vec::<A>::new()
+}
+
+use std::collections::VecDeque;
+
+pub fn yes_vecdeque_partial_eq_array<A, B>() -> impl PartialEq<[B; 32]>
+where
+    A: PartialEq<B>,
+{
+    VecDeque::<A>::new()
+}
+
+pub fn yes_vecdeque_partial_eq_ref_array<'a, A, B>() -> impl PartialEq<&'a [B; 32]>
+where
+    A: PartialEq<B>,
+{
+    VecDeque::<A>::new()
+}
+
+pub fn yes_vecdeque_partial_eq_ref_mut_array<'a, A, B>() -> impl PartialEq<&'a mut [B; 32]>
+where
+    A: PartialEq<B>,
+{
+    VecDeque::<A>::new()
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/array-impls/alloc-traits-no-impls-length-33.rs b/src/test/ui/const-generics/array-impls/alloc-traits-no-impls-length-33.rs
new file mode 100644 (file)
index 0000000..19107e6
--- /dev/null
@@ -0,0 +1,43 @@
+pub fn no_vec_partial_eq_array<A, B>() -> impl PartialEq<[B; 33]>
+//~^ ERROR arrays only have std trait implementations for lengths 0..=32
+where
+    A: PartialEq<B>,
+{
+    Vec::<A>::new()
+}
+
+pub fn no_vec_partial_eq_ref_array<'a, A, B>() -> impl PartialEq<&'a [B; 33]>
+//~^ ERROR arrays only have std trait implementations for lengths 0..=32
+where
+    A: PartialEq<B>,
+{
+    Vec::<A>::new()
+}
+
+use std::collections::VecDeque;
+
+pub fn no_vecdeque_partial_eq_array<A, B>() -> impl PartialEq<[B; 33]>
+//~^ ERROR arrays only have std trait implementations for lengths 0..=32
+where
+    A: PartialEq<B>,
+{
+    VecDeque::<A>::new()
+}
+
+pub fn no_vecdeque_partial_eq_ref_array<'a, A, B>() -> impl PartialEq<&'a [B; 33]>
+//~^ ERROR arrays only have std trait implementations for lengths 0..=32
+where
+    A: PartialEq<B>,
+{
+    VecDeque::<A>::new()
+}
+
+pub fn no_vecdeque_partial_eq_ref_mut_array<'a, A, B>() -> impl PartialEq<&'a mut [B; 33]>
+//~^ ERROR arrays only have std trait implementations for lengths 0..=32
+where
+    A: PartialEq<B>,
+{
+    VecDeque::<A>::new()
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/array-impls/alloc-traits-no-impls-length-33.stderr b/src/test/ui/const-generics/array-impls/alloc-traits-no-impls-length-33.stderr
new file mode 100644 (file)
index 0000000..5c37468
--- /dev/null
@@ -0,0 +1,48 @@
+error[E0277]: arrays only have std trait implementations for lengths 0..=32
+  --> $DIR/alloc-traits-no-impls-length-33.rs:1:43
+   |
+LL | pub fn no_vec_partial_eq_array<A, B>() -> impl PartialEq<[B; 33]>
+   |                                           ^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[B; 33]`
+   |
+   = note: required because of the requirements on the impl of `std::cmp::PartialEq<[B; 33]>` for `std::vec::Vec<A>`
+   = note: the return type of a function must have a statically known size
+
+error[E0277]: arrays only have std trait implementations for lengths 0..=32
+  --> $DIR/alloc-traits-no-impls-length-33.rs:9:51
+   |
+LL | pub fn no_vec_partial_eq_ref_array<'a, A, B>() -> impl PartialEq<&'a [B; 33]>
+   |                                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[B; 33]`
+   |
+   = note: required because of the requirements on the impl of `std::cmp::PartialEq<&'a [B; 33]>` for `std::vec::Vec<A>`
+   = note: the return type of a function must have a statically known size
+
+error[E0277]: arrays only have std trait implementations for lengths 0..=32
+  --> $DIR/alloc-traits-no-impls-length-33.rs:19:48
+   |
+LL | pub fn no_vecdeque_partial_eq_array<A, B>() -> impl PartialEq<[B; 33]>
+   |                                                ^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[B; 33]`
+   |
+   = note: required because of the requirements on the impl of `std::cmp::PartialEq<[B; 33]>` for `std::collections::VecDeque<A>`
+   = note: the return type of a function must have a statically known size
+
+error[E0277]: arrays only have std trait implementations for lengths 0..=32
+  --> $DIR/alloc-traits-no-impls-length-33.rs:27:56
+   |
+LL | pub fn no_vecdeque_partial_eq_ref_array<'a, A, B>() -> impl PartialEq<&'a [B; 33]>
+   |                                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[B; 33]`
+   |
+   = note: required because of the requirements on the impl of `std::cmp::PartialEq<&'a [B; 33]>` for `std::collections::VecDeque<A>`
+   = note: the return type of a function must have a statically known size
+
+error[E0277]: arrays only have std trait implementations for lengths 0..=32
+  --> $DIR/alloc-traits-no-impls-length-33.rs:35:60
+   |
+LL | pub fn no_vecdeque_partial_eq_ref_mut_array<'a, A, B>() -> impl PartialEq<&'a mut [B; 33]>
+   |                                                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[B; 33]`
+   |
+   = note: required because of the requirements on the impl of `std::cmp::PartialEq<&'a mut [B; 33]>` for `std::collections::VecDeque<A>`
+   = note: the return type of a function must have a statically known size
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
index 9226145d9354de3ee119bb8d159655b7aa63d725..f3f5c382275fe760bd06901237eb2a77810c3f33 100644 (file)
@@ -217,7 +217,7 @@ async fn subslice_pattern_from_end_with_drop(a: Rc<Allocator>, arg: bool, arg2:
     if arg {
         let [.., _x, _] = arr;
     } else {
-        let [_, _y..] = arr;
+        let [_, _y @ ..] = arr;
     }
     a.alloc().await;
 }
@@ -226,7 +226,7 @@ async fn subslice_pattern_reassign(a: Rc<Allocator>) {
     let mut ar = [a.alloc().await, a.alloc().await, a.alloc().await];
     let [_, _, _x] = ar;
     ar = [a.alloc().await, a.alloc().await, a.alloc().await];
-    let [_, _y..] = ar;
+    let [_, _y @ ..] = ar;
     a.alloc().await;
 }
 
index eb1a3f3a9f9cbed7f587c9a1dcfc41f726acf78f..8516bc3d96424cb452adb6ccd7051d11d21728b0 100644 (file)
@@ -237,7 +237,7 @@ fn subslice_pattern_from_end(a: &Allocator, arg: bool) {
     if arg {
         let[.., _x, _] = a;
     } else {
-        let[_, _y..] = a;
+        let[_, _y @ ..] = a;
     }
 }
 
@@ -251,7 +251,7 @@ fn subslice_pattern_from_end_with_drop(a: &Allocator, arg: bool, arg2: bool) {
     if arg {
         let[.., _x, _] = a;
     } else {
-        let[_, _y..] = a;
+        let[_, _y @ ..] = a;
     }
 }
 
@@ -266,7 +266,7 @@ fn subslice_pattern_reassign(a: &Allocator) {
     let mut ar = [a.alloc(), a.alloc(), a.alloc()];
     let[_, _, _x] = ar;
     ar = [a.alloc(), a.alloc(), a.alloc()];
-    let[_, _y..] = ar;
+    let[_, _y @ ..] = ar;
 }
 
 fn panic_after_return(a: &Allocator) -> Ptr<'_> {
index 383c6868ce2fe1d01174b9a08a3a6d4d3966ee64..aa6a973d7bd85709e62bfd02ff55d3a8ebac2b24 100644 (file)
@@ -6,7 +6,6 @@
 #![deny(non_snake_case)] // To trigger a hard error
 
 // Shouldn't generate a warning about unstable features
-#[allow(unused_extern_crates)]
 extern crate stability_cfg2;
 
 pub fn BOGUS() { } //~ ERROR
index 5b6ebc4c0d99025cf1a491ab9ab4d7a949e5452f..d5b8c0efaad37b8c2264c65cfe4f3c352c348053 100644 (file)
@@ -1,5 +1,5 @@
 error: function `BOGUS` should have a snake case name
-  --> $DIR/enable-unstable-lib-feature.rs:12:8
+  --> $DIR/enable-unstable-lib-feature.rs:11:8
    |
 LL | pub fn BOGUS() { }
    |        ^^^^^ help: convert the identifier to snake case: `bogus`
index d166aff56579201bc86a40c047b8a6636fb510eb..e291268be86e56333249110c4e63dcc58a4f1e75 100644 (file)
@@ -1,4 +1,4 @@
-#![allow(unused_extern_crates, non_camel_case_types)]
+#![allow(non_camel_case_types)]
 
 extern crate alloc;
 
index c83561be9c6a5b509cb8a37449924ab240f4cfe6..e7e94d58635c1748b2daaa8ff546edfd47bc6b82 100644 (file)
@@ -1,5 +1,4 @@
 #![feature(rustc_private)]
-#![allow(unused_extern_crates)]
 
 extern crate alloc;
 
index fd6a4087aeca4f9732ce2469a51a06cfd664e4ef..4a48a4d554167021a4ad055080fc13d072b7206a 100644 (file)
@@ -1,5 +1,5 @@
 error[E0259]: the name `alloc` is defined multiple times
-  --> $DIR/E0259.rs:6:1
+  --> $DIR/E0259.rs:5:1
    |
 LL | extern crate alloc;
    | ------------------- previous import of the extern crate `alloc` here
index 73b8934159fcf82384117dcc8ac29f42a7c3d4a0..f7eb220b08f597292433e769aa7adf2e2e1af443 100644 (file)
@@ -1,5 +1,3 @@
-#![allow(unused_extern_crates)]
-
 extern crate alloc;
 
 mod alloc {
index 7d0b3022914d82a887b6d649b4477b526fac79cd..737b20b91ec25af863b76b742f5a4e77e5755f24 100644 (file)
@@ -1,5 +1,5 @@
 error[E0260]: the name `alloc` is defined multiple times
-  --> $DIR/E0260.rs:5:1
+  --> $DIR/E0260.rs:3:1
    |
 LL | extern crate alloc;
    | ------------------- previous import of the extern crate `alloc` here
index f2681fa043dab7bf49d02af6fe68b253509626b4..17d03b14fc6e176487c59800b2d0db61de867108 100644 (file)
@@ -3,7 +3,7 @@
 fn main() {
     let r = &[1, 2];
     match r {
-        &[a, b, c, rest..] => {
+        &[a, b, c, rest @ ..] => {
         //~^ ERROR E0528
         }
     }
index a7205af50542a35b811f3addffb898ca397dbc7c..0f566091145bffaf32458f923677a520690719ea 100644 (file)
@@ -1,8 +1,8 @@
 error[E0528]: pattern requires at least 3 elements but array has 2
   --> $DIR/E0528.rs:6:10
    |
-LL |         &[a, b, c, rest..] => {
-   |          ^^^^^^^^^^^^^^^^^ pattern cannot match array of 2 elements
+LL |         &[a, b, c, rest @ ..] => {
+   |          ^^^^^^^^^^^^^^^^^^^^ pattern cannot match array of 2 elements
 
 error: aborting due to previous error
 
index 4e85bcc4ba623b22555114a7090286984ebb4c55..141f363694ab62201e97d67042781b734f0c0f2e 100644 (file)
@@ -9,7 +9,7 @@ pub trait LolInto<T>: Sized {
 }
 
 pub trait LolFrom<T> {
-    fn from(T) -> Self;
+    fn from(_: T) -> Self;
 }
 
 impl<'a, T: ?Sized, U> LolInto<U> for &'a T where T: LolTo<U> {
index d95c4b09994050b0e9323b1690934d1781efe5ec..d97b693f520983dbc86e9779b2e933a935075926 100644 (file)
@@ -2,7 +2,9 @@
 
 fn main() {
     match [5..4, 99..105, 43..44] {
-        [_, 99.., _] => {}, //~ ERROR unexpected token: `,`
+        [_, 99.., _] => {},
+        //~^ ERROR `X..` range patterns are not supported
+        //~| ERROR mismatched types
         _ => {},
     }
 }
index 359725a41c105892aedde9f8ecdcbc8460050c59..4ecd8515ee164e28016b8131bba4813e4003e660 100644 (file)
@@ -1,8 +1,20 @@
-error: unexpected token: `,`
-  --> $DIR/exclusive_range_pattern_syntax_collision.rs:5:17
+error: `X..` range patterns are not supported
+  --> $DIR/exclusive_range_pattern_syntax_collision.rs:5:13
    |
 LL |         [_, 99.., _] => {},
-   |                 ^
+   |             ^^^^ help: try using the maximum value for the type: `99..MAX`
 
-error: aborting due to previous error
+error[E0308]: mismatched types
+  --> $DIR/exclusive_range_pattern_syntax_collision.rs:5:13
+   |
+LL |     match [5..4, 99..105, 43..44] {
+   |           ----------------------- this match expression has type `std::ops::Range<{integer}>`
+LL |         [_, 99.., _] => {},
+   |             ^^^^ expected struct `std::ops::Range`, found integer
+   |
+   = note: expected type `std::ops::Range<{integer}>`
+              found type `{integer}`
+
+error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0308`.
index 95677e34dd798e55044b74ec3621e35194f951a6..09f459c9862ee03c01008388429b7c8fbae335c7 100644 (file)
@@ -2,7 +2,10 @@
 
 fn main() {
     match [5..4, 99..105, 43..44] {
-        [_, 99..] => {}, //~ ERROR unexpected token: `]`
+        [_, 99..] => {},
+        //~^ ERROR `X..` range patterns are not supported
+        //~| ERROR pattern requires 2 elements but array has 3
+        //~| ERROR mismatched types
         _ => {},
     }
 }
index 8f849d7b3f87c5a53f8af1f5d302b970afe481f0..922d26923158b8580834d6704cc0f3fc26aba190 100644 (file)
@@ -1,8 +1,27 @@
-error: unexpected token: `]`
-  --> $DIR/exclusive_range_pattern_syntax_collision2.rs:5:17
+error: `X..` range patterns are not supported
+  --> $DIR/exclusive_range_pattern_syntax_collision2.rs:5:13
    |
 LL |         [_, 99..] => {},
-   |                 ^
+   |             ^^^^ help: try using the maximum value for the type: `99..MAX`
 
-error: aborting due to previous error
+error[E0527]: pattern requires 2 elements but array has 3
+  --> $DIR/exclusive_range_pattern_syntax_collision2.rs:5:9
+   |
+LL |         [_, 99..] => {},
+   |         ^^^^^^^^^ expected 3 elements
+
+error[E0308]: mismatched types
+  --> $DIR/exclusive_range_pattern_syntax_collision2.rs:5:13
+   |
+LL |     match [5..4, 99..105, 43..44] {
+   |           ----------------------- this match expression has type `std::ops::Range<{integer}>`
+LL |         [_, 99..] => {},
+   |             ^^^^ expected struct `std::ops::Range`, found integer
+   |
+   = note: expected type `std::ops::Range<{integer}>`
+              found type `{integer}`
+
+error: aborting due to 3 previous errors
 
+Some errors have detailed explanations: E0308, E0527.
+For more information about an error, try `rustc --explain E0308`.
index 3bf5da710ef9f9c0ee32b389e7b077a56c093309..95e58b1d48c88cae40440c04b97fc35638e9b074 100644 (file)
@@ -2,7 +2,10 @@
 
 fn main() {
     match [5..4, 99..105, 43..44] {
-        [..9, 99..100, _] => {}, //~ ERROR expected one of `,` or `]`, found `9`
+        [..9, 99..100, _] => {},
+        //~^ ERROR `..X` range patterns are not supported
+        //~| ERROR mismatched types
+        //~| ERROR mismatched types
         _ => {},
     }
 }
index a09ba3562e098050fa296a95689187e2ffcf62fe..8907b875f8e116d4440a6bb988e6ee69acf5e088 100644 (file)
@@ -1,8 +1,31 @@
-error: expected one of `,` or `]`, found `9`
-  --> $DIR/exclusive_range_pattern_syntax_collision3.rs:5:12
+error: `..X` range patterns are not supported
+  --> $DIR/exclusive_range_pattern_syntax_collision3.rs:5:10
    |
 LL |         [..9, 99..100, _] => {},
-   |            ^ expected one of `,` or `]` here
+   |          ^^^ help: try using the minimum value for the type: `MIN..9`
 
-error: aborting due to previous error
+error[E0308]: mismatched types
+  --> $DIR/exclusive_range_pattern_syntax_collision3.rs:5:10
+   |
+LL |     match [5..4, 99..105, 43..44] {
+   |           ----------------------- this match expression has type `std::ops::Range<{integer}>`
+LL |         [..9, 99..100, _] => {},
+   |          ^^^ expected struct `std::ops::Range`, found integer
+   |
+   = note: expected type `std::ops::Range<{integer}>`
+              found type `{integer}`
+
+error[E0308]: mismatched types
+  --> $DIR/exclusive_range_pattern_syntax_collision3.rs:5:15
+   |
+LL |     match [5..4, 99..105, 43..44] {
+   |           ----------------------- this match expression has type `std::ops::Range<{integer}>`
+LL |         [..9, 99..100, _] => {},
+   |               ^^^^^^^ expected struct `std::ops::Range`, found integer
+   |
+   = note: expected type `std::ops::Range<{integer}>`
+              found type `{integer}`
+
+error: aborting due to 3 previous errors
 
+For more information about this error, try `rustc --explain E0308`.
index 0165321debe6b9da4fece575705409c0f6ca62e9..f2a1b135b69cbaab06ce2aeb5e549f4b720b9fca 100644 (file)
@@ -3,15 +3,15 @@
 fn main() {
     let x = [1, 2, 3, 4, 5];
     match x {
-        [1, 2, ..] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized
-        [1, .., 5] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized
-        [.., 4, 5] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized
+        [1, 2, ..] => {} //~ ERROR subslice patterns are unstable
+        [1, .., 5] => {} //~ ERROR subslice patterns are unstable
+        [.., 4, 5] => {} //~ ERROR subslice patterns are unstable
     }
 
     let x = [ 1, 2, 3, 4, 5 ];
     match x {
-        [ xs.., 4, 5 ] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized
-        [ 1, xs.., 5 ] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized
-        [ 1, 2, xs.. ] => {} //~ ERROR syntax for subslices in slice patterns is not yet stabilized
+        [ xs @ .., 4, 5 ] => {} //~ ERROR subslice patterns are unstable
+        [ 1, xs @ .., 5 ] => {} //~ ERROR subslice patterns are unstable
+        [ 1, 2, xs @ .. ] => {} //~ ERROR subslice patterns are unstable
     }
 }
index e88fddaa81fbeabb9c8e4aac3b755af990d51f82..d4946a42b8f3dcc307b9daf569468384de8028c5 100644 (file)
@@ -1,4 +1,4 @@
-error[E0658]: syntax for subslices in slice patterns is not yet stabilized
+error[E0658]: subslice patterns are unstable
   --> $DIR/feature-gate-slice-patterns.rs:6:16
    |
 LL |         [1, 2, ..] => {}
@@ -7,7 +7,7 @@ LL |         [1, 2, ..] => {}
    = note: for more information, see https://github.com/rust-lang/rust/issues/62254
    = help: add `#![feature(slice_patterns)]` to the crate attributes to enable
 
-error[E0658]: syntax for subslices in slice patterns is not yet stabilized
+error[E0658]: subslice patterns are unstable
   --> $DIR/feature-gate-slice-patterns.rs:7:13
    |
 LL |         [1, .., 5] => {}
@@ -16,7 +16,7 @@ LL |         [1, .., 5] => {}
    = note: for more information, see https://github.com/rust-lang/rust/issues/62254
    = help: add `#![feature(slice_patterns)]` to the crate attributes to enable
 
-error[E0658]: syntax for subslices in slice patterns is not yet stabilized
+error[E0658]: subslice patterns are unstable
   --> $DIR/feature-gate-slice-patterns.rs:8:10
    |
 LL |         [.., 4, 5] => {}
@@ -25,29 +25,29 @@ LL |         [.., 4, 5] => {}
    = note: for more information, see https://github.com/rust-lang/rust/issues/62254
    = help: add `#![feature(slice_patterns)]` to the crate attributes to enable
 
-error[E0658]: syntax for subslices in slice patterns is not yet stabilized
+error[E0658]: subslice patterns are unstable
   --> $DIR/feature-gate-slice-patterns.rs:13:11
    |
-LL |         [ xs.., 4, 5 ] => {}
-   |           ^^
+LL |         [ xs @ .., 4, 5 ] => {}
+   |           ^^^^^^^
    |
    = note: for more information, see https://github.com/rust-lang/rust/issues/62254
    = help: add `#![feature(slice_patterns)]` to the crate attributes to enable
 
-error[E0658]: syntax for subslices in slice patterns is not yet stabilized
+error[E0658]: subslice patterns are unstable
   --> $DIR/feature-gate-slice-patterns.rs:14:14
    |
-LL |         [ 1, xs.., 5 ] => {}
-   |              ^^
+LL |         [ 1, xs @ .., 5 ] => {}
+   |              ^^^^^^^
    |
    = note: for more information, see https://github.com/rust-lang/rust/issues/62254
    = help: add `#![feature(slice_patterns)]` to the crate attributes to enable
 
-error[E0658]: syntax for subslices in slice patterns is not yet stabilized
+error[E0658]: subslice patterns are unstable
   --> $DIR/feature-gate-slice-patterns.rs:15:17
    |
-LL |         [ 1, 2, xs.. ] => {}
-   |                 ^^
+LL |         [ 1, 2, xs @ .. ] => {}
+   |                 ^^^^^^^
    |
    = note: for more information, see https://github.com/rust-lang/rust/issues/62254
    = help: add `#![feature(slice_patterns)]` to the crate attributes to enable
index 8df8efefd05ed76fe892de34d8a092f5d10e4294..086613180746362a414dbb7abb33dc348402311c 100644 (file)
@@ -6,7 +6,7 @@ fn main() {
     let v: isize = match &*sl {
         &[] => 0,
         &[a,b,c] => 3,
-        &[a, ref rest..] => a,
-        &[10,a, ref rest..] => 10 //~ ERROR: unreachable pattern
+        &[a, ref rest @ ..] => a,
+        &[10,a, ref rest @ ..] => 10 //~ ERROR: unreachable pattern
     };
 }
index fec9078dc409094cb33b210f7c8b24ce78541567..f27425e28c61d3d9b12af0af8aea6658c8c2ce89 100644 (file)
@@ -1,8 +1,8 @@
 error: unreachable pattern
   --> $DIR/issue-12369.rs:10:9
    |
-LL |         &[10,a, ref rest..] => 10
-   |         ^^^^^^^^^^^^^^^^^^^
+LL |         &[10,a, ref rest @ ..] => 10
+   |         ^^^^^^^^^^^^^^^^^^^^^^
    |
 note: lint level defined here
   --> $DIR/issue-12369.rs:2:9
index 4558118a8091c29d69e85c61a2eb8c9f75462117..b11b1cda38ae127d39b64c94f873227064444b9c 100644 (file)
@@ -7,11 +7,11 @@ fn main() {
     let mut result = vec![];
     loop {
         x = match *x {
-            [1, n, 3, ref rest..] => {
+            [1, n, 3, ref rest @ ..] => {
                 result.push(n);
                 rest
             }
-            [n, ref rest..] => {
+            [n, ref rest @ ..] => {
                 result.push(n);
                 rest
             }
index 3a03a52c32485e3657889b9498c2cdf14894fba2..ee977541137db66e351a7a3e7f004873d0e6d8c1 100644 (file)
@@ -9,6 +9,6 @@ fn count_members(v: &[usize]) -> usize {
     match *v {
         []         => 0,
         [_]        => 1,
-        [_, ref xs..] => 1 + count_members(xs)
+        [_, ref xs @ ..] => 1 + count_members(xs)
     }
 }
index af22b1ad8f0bc3a3bf31d7056a5740d09f720762..fefa3f2f8730465b7bcb9916a2a96c9adca23041 100644 (file)
@@ -7,8 +7,8 @@ fn main() {
     }, 42_usize);
 
     assert_eq!(match [0u8; 1024] {
-        [1, _..] => 0_usize,
-        [0, _..] => 1_usize,
+        [1, ..] => 0_usize,
+        [0, ..] => 1_usize,
         _ => 2_usize
     }, 1_usize);
 }
diff --git a/src/test/ui/issues/issue-26158.rs b/src/test/ui/issues/issue-26158.rs
deleted file mode 100644 (file)
index 11f47b6..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#![feature(slice_patterns)]
-
-fn main() {
-    let x: &[u32] = &[];
-    let &[[ref _a, ref _b..]..] = x; //~ ERROR refutable pattern
-}
diff --git a/src/test/ui/issues/issue-26158.stderr b/src/test/ui/issues/issue-26158.stderr
deleted file mode 100644 (file)
index 3a4dd79..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0005]: refutable pattern in local binding: `&[]` not covered
-  --> $DIR/issue-26158.rs:5:9
-   |
-LL |     let &[[ref _a, ref _b..]..] = x;
-   |         ^^^^^^^^^^^^^^^^^^^^^^^ pattern `&[]` not covered
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0005`.
index 2b0508d08ea67ad1768062dbcba2513ea51b8abb..04313872d27131efce86bd052bc2c194d11addd5 100644 (file)
@@ -1,7 +1,6 @@
 // aux-build:issue-36881-aux.rs
 
 fn main() {
-    #[allow(unused_extern_crates)]
     extern crate issue_36881_aux;
     use issue_36881_aux::Foo; //~ ERROR unresolved import
 }
index 2ec636fde60bf24f183c227ca79859b4c1204668..07d2c99d7d2dec44b6de2648851f0a4a70e8998a 100644 (file)
@@ -1,5 +1,5 @@
 error[E0432]: unresolved import `issue_36881_aux`
-  --> $DIR/issue-36881.rs:6:9
+  --> $DIR/issue-36881.rs:5:9
    |
 LL |     use issue_36881_aux::Foo;
    |         ^^^^^^^^^^^^^^^ maybe a missing `extern crate issue_36881_aux;`?
index 1bec3d340d6653f70625192e1042b2b020b514c1..31b3aba6bc20422b27433e05eec5d5eb2b3cc020 100644 (file)
@@ -1,11 +1,10 @@
-// build-pass (FIXME(62277): could be check-pass?)
-#![allow(dead_code)]
+// check-pass
 #![feature(slice_patterns)]
 
 fn check(list: &[u8]) {
     match list {
         &[] => {},
-        &[_u1, _u2, ref _next..] => {},
+        &[_u1, _u2, ref _next @ ..] => {},
         &[_u1] => {},
     }
 }
index bc14d20b6238824031c2f3849cb3a381a0038ace..c0d4ce1243e015f0dee62a0a8ab701602600286a 100644 (file)
@@ -1,8 +1,8 @@
 error: an inner attribute is not permitted in this context
-  --> $DIR/issue-45296.rs:4:7
+  --> $DIR/issue-45296.rs:4:5
    |
 LL |     #![allow(unused_variables)]
-   |       ^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
index b75e547079ef5b91b01c937244f0dbd69cc3641f..5b70bd6e5ff54923a8ed319fc23d84966d305138 100644 (file)
@@ -24,7 +24,7 @@ fn main() {
     assert_eq!(d, "baz");
 
     let out = bar("baz", "foo");
-    let [a, xs.., d] = out;
+    let [a, xs @ .., d] = out;
     assert_eq!(a, "baz");
     assert_eq!(xs, ["foo", "foo"]);
     assert_eq!(d, "baz");
index 652fd04bdf526edfa2e6df8d2c120adff1521ed1..5e747467a127ed2d182a7052fcff573256c5aea8 100644 (file)
@@ -5,7 +5,6 @@
 // aux-build:stability-cfg2.rs
 // ignore-tidy-linelength
 #![warn(deprecated)]
-#![allow(dead_code, unused_extern_crates)]
 #![feature(staged_api, unstable_test_feature)]
 
 #![stable(feature = "rust1", since = "1.0.0")]
index 811004ee12ccbebecef62a69fe84e5e42dcd1067..8132a66df8a0fa326d0ecdcd2e6b9e7acc46697f 100644 (file)
@@ -1,5 +1,5 @@
 warning: use of deprecated item 'lint_stability::deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:26:9
+  --> $DIR/lint-stability-deprecated.rs:25:9
    |
 LL |         deprecated();
    |         ^^^^^^^^^^
@@ -11,625 +11,625 @@ LL | #![warn(deprecated)]
    |         ^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:31:9
+  --> $DIR/lint-stability-deprecated.rs:30:9
    |
 LL |         Trait::trait_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:33:9
+  --> $DIR/lint-stability-deprecated.rs:32:9
    |
 LL |         <Foo as Trait>::trait_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:35:9
+  --> $DIR/lint-stability-deprecated.rs:34:9
    |
 LL |         deprecated_text();
    |         ^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:40:9
+  --> $DIR/lint-stability-deprecated.rs:39:9
    |
 LL |         Trait::trait_deprecated_text(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:42:9
+  --> $DIR/lint-stability-deprecated.rs:41:9
    |
 LL |         <Foo as Trait>::trait_deprecated_text(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::deprecated_unstable': text
-  --> $DIR/lint-stability-deprecated.rs:44:9
+  --> $DIR/lint-stability-deprecated.rs:43:9
    |
 LL |         deprecated_unstable();
    |         ^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable': text
-  --> $DIR/lint-stability-deprecated.rs:49:9
+  --> $DIR/lint-stability-deprecated.rs:48:9
    |
 LL |         Trait::trait_deprecated_unstable(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable': text
-  --> $DIR/lint-stability-deprecated.rs:51:9
+  --> $DIR/lint-stability-deprecated.rs:50:9
    |
 LL |         <Foo as Trait>::trait_deprecated_unstable(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::deprecated_unstable_text': text
-  --> $DIR/lint-stability-deprecated.rs:53:9
+  --> $DIR/lint-stability-deprecated.rs:52:9
    |
 LL |         deprecated_unstable_text();
    |         ^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
-  --> $DIR/lint-stability-deprecated.rs:58:9
+  --> $DIR/lint-stability-deprecated.rs:57:9
    |
 LL |         Trait::trait_deprecated_unstable_text(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
-  --> $DIR/lint-stability-deprecated.rs:60:9
+  --> $DIR/lint-stability-deprecated.rs:59:9
    |
 LL |         <Foo as Trait>::trait_deprecated_unstable_text(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::DeprecatedStruct': text
-  --> $DIR/lint-stability-deprecated.rs:107:17
+  --> $DIR/lint-stability-deprecated.rs:106:17
    |
 LL |         let _ = DeprecatedStruct {
    |                 ^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::DeprecatedUnstableStruct': text
-  --> $DIR/lint-stability-deprecated.rs:110:17
+  --> $DIR/lint-stability-deprecated.rs:109:17
    |
 LL |         let _ = DeprecatedUnstableStruct {
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::DeprecatedUnitStruct': text
-  --> $DIR/lint-stability-deprecated.rs:117:17
+  --> $DIR/lint-stability-deprecated.rs:116:17
    |
 LL |         let _ = DeprecatedUnitStruct;
    |                 ^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::DeprecatedUnstableUnitStruct': text
-  --> $DIR/lint-stability-deprecated.rs:118:17
+  --> $DIR/lint-stability-deprecated.rs:117:17
    |
 LL |         let _ = DeprecatedUnstableUnitStruct;
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Enum::DeprecatedVariant': text
-  --> $DIR/lint-stability-deprecated.rs:122:17
+  --> $DIR/lint-stability-deprecated.rs:121:17
    |
 LL |         let _ = Enum::DeprecatedVariant;
    |                 ^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Enum::DeprecatedUnstableVariant': text
-  --> $DIR/lint-stability-deprecated.rs:123:17
+  --> $DIR/lint-stability-deprecated.rs:122:17
    |
 LL |         let _ = Enum::DeprecatedUnstableVariant;
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::DeprecatedTupleStruct': text
-  --> $DIR/lint-stability-deprecated.rs:127:17
+  --> $DIR/lint-stability-deprecated.rs:126:17
    |
 LL |         let _ = DeprecatedTupleStruct (1);
    |                 ^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::DeprecatedUnstableTupleStruct': text
-  --> $DIR/lint-stability-deprecated.rs:128:17
+  --> $DIR/lint-stability-deprecated.rs:127:17
    |
 LL |         let _ = DeprecatedUnstableTupleStruct (1);
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:137:25
+  --> $DIR/lint-stability-deprecated.rs:136:25
    |
 LL |         macro_test_arg!(deprecated_text());
    |                         ^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::deprecated_unstable_text': text
-  --> $DIR/lint-stability-deprecated.rs:138:25
+  --> $DIR/lint-stability-deprecated.rs:137:25
    |
 LL |         macro_test_arg!(deprecated_unstable_text());
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:139:41
+  --> $DIR/lint-stability-deprecated.rs:138:41
    |
 LL |         macro_test_arg!(macro_test_arg!(deprecated_text()));
    |                                         ^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:144:9
+  --> $DIR/lint-stability-deprecated.rs:143:9
    |
 LL |         Trait::trait_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:146:9
+  --> $DIR/lint-stability-deprecated.rs:145:9
    |
 LL |         <Foo as Trait>::trait_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:148:9
+  --> $DIR/lint-stability-deprecated.rs:147:9
    |
 LL |         Trait::trait_deprecated_text(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:150:9
+  --> $DIR/lint-stability-deprecated.rs:149:9
    |
 LL |         <Foo as Trait>::trait_deprecated_text(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable': text
-  --> $DIR/lint-stability-deprecated.rs:152:9
+  --> $DIR/lint-stability-deprecated.rs:151:9
    |
 LL |         Trait::trait_deprecated_unstable(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable': text
-  --> $DIR/lint-stability-deprecated.rs:154:9
+  --> $DIR/lint-stability-deprecated.rs:153:9
    |
 LL |         <Foo as Trait>::trait_deprecated_unstable(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
-  --> $DIR/lint-stability-deprecated.rs:156:9
+  --> $DIR/lint-stability-deprecated.rs:155:9
    |
 LL |         Trait::trait_deprecated_unstable_text(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
-  --> $DIR/lint-stability-deprecated.rs:158:9
+  --> $DIR/lint-stability-deprecated.rs:157:9
    |
 LL |         <Foo as Trait>::trait_deprecated_unstable_text(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::DeprecatedTrait': text
-  --> $DIR/lint-stability-deprecated.rs:186:10
+  --> $DIR/lint-stability-deprecated.rs:185:10
    |
 LL |     impl DeprecatedTrait for S {}
    |          ^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::DeprecatedTrait': text
-  --> $DIR/lint-stability-deprecated.rs:188:25
+  --> $DIR/lint-stability-deprecated.rs:187:25
    |
 LL |     trait LocalTrait2 : DeprecatedTrait { }
    |                         ^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'inheritance::inherited_stability::unstable_mod::deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:207:9
+  --> $DIR/lint-stability-deprecated.rs:206:9
    |
 LL |         unstable_mod::deprecated();
    |         ^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:329:9
+  --> $DIR/lint-stability-deprecated.rs:328:9
    |
 LL |         deprecated();
    |         ^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::Trait::trait_deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:334:9
+  --> $DIR/lint-stability-deprecated.rs:333:9
    |
 LL |         Trait::trait_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::Trait::trait_deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:336:9
+  --> $DIR/lint-stability-deprecated.rs:335:9
    |
 LL |         <Foo as Trait>::trait_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:338:9
+  --> $DIR/lint-stability-deprecated.rs:337:9
    |
 LL |         deprecated_text();
    |         ^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:343:9
+  --> $DIR/lint-stability-deprecated.rs:342:9
    |
 LL |         Trait::trait_deprecated_text(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:345:9
+  --> $DIR/lint-stability-deprecated.rs:344:9
    |
 LL |         <Foo as Trait>::trait_deprecated_text(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::DeprecatedStruct': text
-  --> $DIR/lint-stability-deprecated.rs:383:17
+  --> $DIR/lint-stability-deprecated.rs:382:17
    |
 LL |         let _ = DeprecatedStruct {
    |                 ^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::DeprecatedUnitStruct': text
-  --> $DIR/lint-stability-deprecated.rs:390:17
+  --> $DIR/lint-stability-deprecated.rs:389:17
    |
 LL |         let _ = DeprecatedUnitStruct;
    |                 ^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::Enum::DeprecatedVariant': text
-  --> $DIR/lint-stability-deprecated.rs:394:17
+  --> $DIR/lint-stability-deprecated.rs:393:17
    |
 LL |         let _ = Enum::DeprecatedVariant;
    |                 ^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::DeprecatedTupleStruct': text
-  --> $DIR/lint-stability-deprecated.rs:398:17
+  --> $DIR/lint-stability-deprecated.rs:397:17
    |
 LL |         let _ = DeprecatedTupleStruct (1);
    |                 ^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::Trait::trait_deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:405:9
+  --> $DIR/lint-stability-deprecated.rs:404:9
    |
 LL |         Trait::trait_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::Trait::trait_deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:407:9
+  --> $DIR/lint-stability-deprecated.rs:406:9
    |
 LL |         <Foo as Trait>::trait_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:409:9
+  --> $DIR/lint-stability-deprecated.rs:408:9
    |
 LL |         Trait::trait_deprecated_text(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:411:9
+  --> $DIR/lint-stability-deprecated.rs:410:9
    |
 LL |         <Foo as Trait>::trait_deprecated_text(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::test_fn_body::fn_in_body': text
-  --> $DIR/lint-stability-deprecated.rs:438:9
+  --> $DIR/lint-stability-deprecated.rs:437:9
    |
 LL |         fn_in_body();
    |         ^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::DeprecatedTrait': text
-  --> $DIR/lint-stability-deprecated.rs:458:10
+  --> $DIR/lint-stability-deprecated.rs:457:10
    |
 LL |     impl DeprecatedTrait for S { }
    |          ^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::DeprecatedTrait': text
-  --> $DIR/lint-stability-deprecated.rs:460:24
+  --> $DIR/lint-stability-deprecated.rs:459:24
    |
 LL |     trait LocalTrait : DeprecatedTrait { }
    |                        ^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::MethodTester::test_method_body::fn_in_body': text
-  --> $DIR/lint-stability-deprecated.rs:446:13
+  --> $DIR/lint-stability-deprecated.rs:445:13
    |
 LL |             fn_in_body();
    |             ^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::TraitWithAssociatedTypes::TypeDeprecated': text
-  --> $DIR/lint-stability-deprecated.rs:99:48
+  --> $DIR/lint-stability-deprecated.rs:98:48
    |
 LL |         struct S2<T: TraitWithAssociatedTypes>(T::TypeDeprecated);
    |                                                ^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::TraitWithAssociatedTypes::TypeDeprecated': text
-  --> $DIR/lint-stability-deprecated.rs:103:13
+  --> $DIR/lint-stability-deprecated.rs:102:13
    |
 LL |             TypeDeprecated = u16,
    |             ^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::MethodTester::method_deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:27:13
+  --> $DIR/lint-stability-deprecated.rs:26:13
    |
 LL |         foo.method_deprecated();
    |             ^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::MethodTester::method_deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:28:9
+  --> $DIR/lint-stability-deprecated.rs:27:9
    |
 LL |         Foo::method_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::MethodTester::method_deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:29:9
+  --> $DIR/lint-stability-deprecated.rs:28:9
    |
 LL |         <Foo>::method_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:30:13
+  --> $DIR/lint-stability-deprecated.rs:29:13
    |
 LL |         foo.trait_deprecated();
    |             ^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:32:9
+  --> $DIR/lint-stability-deprecated.rs:31:9
    |
 LL |         <Foo>::trait_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::MethodTester::method_deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:36:13
+  --> $DIR/lint-stability-deprecated.rs:35:13
    |
 LL |         foo.method_deprecated_text();
    |             ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::MethodTester::method_deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:37:9
+  --> $DIR/lint-stability-deprecated.rs:36:9
    |
 LL |         Foo::method_deprecated_text(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::MethodTester::method_deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:38:9
+  --> $DIR/lint-stability-deprecated.rs:37:9
    |
 LL |         <Foo>::method_deprecated_text(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:39:13
+  --> $DIR/lint-stability-deprecated.rs:38:13
    |
 LL |         foo.trait_deprecated_text();
    |             ^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:41:9
+  --> $DIR/lint-stability-deprecated.rs:40:9
    |
 LL |         <Foo>::trait_deprecated_text(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::MethodTester::method_deprecated_unstable': text
-  --> $DIR/lint-stability-deprecated.rs:45:13
+  --> $DIR/lint-stability-deprecated.rs:44:13
    |
 LL |         foo.method_deprecated_unstable();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::MethodTester::method_deprecated_unstable': text
-  --> $DIR/lint-stability-deprecated.rs:46:9
+  --> $DIR/lint-stability-deprecated.rs:45:9
    |
 LL |         Foo::method_deprecated_unstable(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::MethodTester::method_deprecated_unstable': text
-  --> $DIR/lint-stability-deprecated.rs:47:9
+  --> $DIR/lint-stability-deprecated.rs:46:9
    |
 LL |         <Foo>::method_deprecated_unstable(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable': text
-  --> $DIR/lint-stability-deprecated.rs:48:13
+  --> $DIR/lint-stability-deprecated.rs:47:13
    |
 LL |         foo.trait_deprecated_unstable();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable': text
-  --> $DIR/lint-stability-deprecated.rs:50:9
+  --> $DIR/lint-stability-deprecated.rs:49:9
    |
 LL |         <Foo>::trait_deprecated_unstable(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::MethodTester::method_deprecated_unstable_text': text
-  --> $DIR/lint-stability-deprecated.rs:54:13
+  --> $DIR/lint-stability-deprecated.rs:53:13
    |
 LL |         foo.method_deprecated_unstable_text();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::MethodTester::method_deprecated_unstable_text': text
-  --> $DIR/lint-stability-deprecated.rs:55:9
+  --> $DIR/lint-stability-deprecated.rs:54:9
    |
 LL |         Foo::method_deprecated_unstable_text(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::MethodTester::method_deprecated_unstable_text': text
-  --> $DIR/lint-stability-deprecated.rs:56:9
+  --> $DIR/lint-stability-deprecated.rs:55:9
    |
 LL |         <Foo>::method_deprecated_unstable_text(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
-  --> $DIR/lint-stability-deprecated.rs:57:13
+  --> $DIR/lint-stability-deprecated.rs:56:13
    |
 LL |         foo.trait_deprecated_unstable_text();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
-  --> $DIR/lint-stability-deprecated.rs:59:9
+  --> $DIR/lint-stability-deprecated.rs:58:9
    |
 LL |         <Foo>::trait_deprecated_unstable_text(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::DeprecatedStruct::i': text
-  --> $DIR/lint-stability-deprecated.rs:108:13
+  --> $DIR/lint-stability-deprecated.rs:107:13
    |
 LL |             i: 0
    |             ^^^^
 
 warning: use of deprecated item 'lint_stability::DeprecatedUnstableStruct::i': text
-  --> $DIR/lint-stability-deprecated.rs:112:13
+  --> $DIR/lint-stability-deprecated.rs:111:13
    |
 LL |             i: 0
    |             ^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:143:13
+  --> $DIR/lint-stability-deprecated.rs:142:13
    |
 LL |         foo.trait_deprecated();
    |             ^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:145:9
+  --> $DIR/lint-stability-deprecated.rs:144:9
    |
 LL |         <Foo>::trait_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:147:13
+  --> $DIR/lint-stability-deprecated.rs:146:13
    |
 LL |         foo.trait_deprecated_text();
    |             ^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:149:9
+  --> $DIR/lint-stability-deprecated.rs:148:9
    |
 LL |         <Foo>::trait_deprecated_text(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable': text
-  --> $DIR/lint-stability-deprecated.rs:151:13
+  --> $DIR/lint-stability-deprecated.rs:150:13
    |
 LL |         foo.trait_deprecated_unstable();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable': text
-  --> $DIR/lint-stability-deprecated.rs:153:9
+  --> $DIR/lint-stability-deprecated.rs:152:9
    |
 LL |         <Foo>::trait_deprecated_unstable(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
-  --> $DIR/lint-stability-deprecated.rs:155:13
+  --> $DIR/lint-stability-deprecated.rs:154:13
    |
 LL |         foo.trait_deprecated_unstable_text();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
-  --> $DIR/lint-stability-deprecated.rs:157:9
+  --> $DIR/lint-stability-deprecated.rs:156:9
    |
 LL |         <Foo>::trait_deprecated_unstable_text(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:174:13
+  --> $DIR/lint-stability-deprecated.rs:173:13
    |
 LL |         foo.trait_deprecated();
    |             ^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:175:13
+  --> $DIR/lint-stability-deprecated.rs:174:13
    |
 LL |         foo.trait_deprecated_text();
    |             ^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable': text
-  --> $DIR/lint-stability-deprecated.rs:176:13
+  --> $DIR/lint-stability-deprecated.rs:175:13
    |
 LL |         foo.trait_deprecated_unstable();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'lint_stability::Trait::trait_deprecated_unstable_text': text
-  --> $DIR/lint-stability-deprecated.rs:177:13
+  --> $DIR/lint-stability-deprecated.rs:176:13
    |
 LL |         foo.trait_deprecated_unstable_text();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::MethodTester::method_deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:330:13
+  --> $DIR/lint-stability-deprecated.rs:329:13
    |
 LL |         foo.method_deprecated();
    |             ^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::MethodTester::method_deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:331:9
+  --> $DIR/lint-stability-deprecated.rs:330:9
    |
 LL |         Foo::method_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::MethodTester::method_deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:332:9
+  --> $DIR/lint-stability-deprecated.rs:331:9
    |
 LL |         <Foo>::method_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::Trait::trait_deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:333:13
+  --> $DIR/lint-stability-deprecated.rs:332:13
    |
 LL |         foo.trait_deprecated();
    |             ^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::Trait::trait_deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:335:9
+  --> $DIR/lint-stability-deprecated.rs:334:9
    |
 LL |         <Foo>::trait_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::MethodTester::method_deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:339:13
+  --> $DIR/lint-stability-deprecated.rs:338:13
    |
 LL |         foo.method_deprecated_text();
    |             ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::MethodTester::method_deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:340:9
+  --> $DIR/lint-stability-deprecated.rs:339:9
    |
 LL |         Foo::method_deprecated_text(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::MethodTester::method_deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:341:9
+  --> $DIR/lint-stability-deprecated.rs:340:9
    |
 LL |         <Foo>::method_deprecated_text(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:342:13
+  --> $DIR/lint-stability-deprecated.rs:341:13
    |
 LL |         foo.trait_deprecated_text();
    |             ^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:344:9
+  --> $DIR/lint-stability-deprecated.rs:343:9
    |
 LL |         <Foo>::trait_deprecated_text(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::DeprecatedStruct::i': text
-  --> $DIR/lint-stability-deprecated.rs:385:13
+  --> $DIR/lint-stability-deprecated.rs:384:13
    |
 LL |             i: 0
    |             ^^^^
 
 warning: use of deprecated item 'this_crate::Trait::trait_deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:404:13
+  --> $DIR/lint-stability-deprecated.rs:403:13
    |
 LL |         foo.trait_deprecated();
    |             ^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::Trait::trait_deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:406:9
+  --> $DIR/lint-stability-deprecated.rs:405:9
    |
 LL |         <Foo>::trait_deprecated(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:408:13
+  --> $DIR/lint-stability-deprecated.rs:407:13
    |
 LL |         foo.trait_deprecated_text();
    |             ^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:410:9
+  --> $DIR/lint-stability-deprecated.rs:409:9
    |
 LL |         <Foo>::trait_deprecated_text(&foo);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::Trait::trait_deprecated': text
-  --> $DIR/lint-stability-deprecated.rs:427:13
+  --> $DIR/lint-stability-deprecated.rs:426:13
    |
 LL |         foo.trait_deprecated();
    |             ^^^^^^^^^^^^^^^^
 
 warning: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text
-  --> $DIR/lint-stability-deprecated.rs:428:13
+  --> $DIR/lint-stability-deprecated.rs:427:13
    |
 LL |         foo.trait_deprecated_text();
    |             ^^^^^^^^^^^^^^^^^^^^^
index 78609a6e24b5eefd783900ca4485d0d4e01c43ed..2957f9311105108ee41e7e029e7ede7b4d582292 100644 (file)
@@ -1,12 +1,70 @@
+// edition:2018
+
 // Exercise the unused_mut attribute in some positive and negative cases
 
-#![allow(unused_assignments)]
-#![allow(unused_variables)]
-#![allow(dead_code)]
 #![deny(unused_mut)]
+#![feature(async_await, async_closure, param_attrs)]
+
+async fn baz_async(
+    mut a: i32,
+    //~^ ERROR: variable does not need to be mutable
+    #[allow(unused_mut)] mut b: i32,
+) {}
+fn baz(
+    mut a: i32,
+    //~^ ERROR: variable does not need to be mutable
+    #[allow(unused_mut)] mut b: i32,
+    #[allow(unused_mut)] (mut c, d): (i32, i32)
+) {}
+
+struct RefStruct {}
+impl RefStruct {
+    async fn baz_async(
+        mut a: i32,
+        //~^ ERROR: variable does not need to be mutable
+        #[allow(unused_mut)] mut b: i32,
+    ) {}
+    fn baz(
+        &self,
+        mut a: i32,
+        //~^ ERROR: variable does not need to be mutable
+        #[allow(unused_mut)] mut b: i32,
+        #[allow(unused_mut)] (mut c, d): (i32, i32)
+    ) {}
+}
 
+trait RefTrait {
+    fn baz(
+        &self,
+        mut a: i32,
+        //~^ ERROR: variable does not need to be mutable
+        #[allow(unused_mut)] mut b: i32,
+        #[allow(unused_mut)] (mut c, d): (i32, i32)
+    ) {}
+}
+impl RefTrait for () {
+    fn baz(
+        &self,
+        mut a: i32,
+        //~^ ERROR: variable does not need to be mutable
+        #[allow(unused_mut)] mut b: i32,
+        #[allow(unused_mut)] (mut c, d): (i32, i32)
+    ) {}
+}
 
 fn main() {
+    let _ = async move |
+        mut a: i32,
+        //~^ ERROR: variable does not need to be mutable
+        #[allow(unused_mut)] mut b: i32,
+    | {};
+    let _ = |
+        mut a: i32,
+        //~^ ERROR: variable does not need to be mutable
+        #[allow(unused_mut)] mut b: i32,
+        #[allow(unused_mut)] (mut c, d): (i32, i32)
+    | {};
+
     // negative cases
     let mut a = 3; //~ ERROR: variable does not need to be mutable
 
index 1a175c9683ec729642b81dae0050c1299e65a14c..92c2b68652dc278c77fc8287a17e9c14e42848ae 100644 (file)
@@ -1,19 +1,83 @@
 error: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:46:14
+  --> $DIR/lint-unused-mut-variables.rs:9:5
    |
-LL |     let x = |mut y: isize| 10;
-   |              ----^
-   |              |
-   |              help: remove this `mut`
+LL |     mut a: i32,
+   |     ----^
+   |     |
+   |     help: remove this `mut`
    |
 note: lint level defined here
-  --> $DIR/lint-unused-mut-variables.rs:6:9
+  --> $DIR/lint-unused-mut-variables.rs:5:9
    |
 LL | #![deny(unused_mut)]
    |         ^^^^^^^^^^
 
 error: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:11:9
+  --> $DIR/lint-unused-mut-variables.rs:14:5
+   |
+LL |     mut a: i32,
+   |     ----^
+   |     |
+   |     help: remove this `mut`
+
+error: variable does not need to be mutable
+  --> $DIR/lint-unused-mut-variables.rs:23:9
+   |
+LL |         mut a: i32,
+   |         ----^
+   |         |
+   |         help: remove this `mut`
+
+error: variable does not need to be mutable
+  --> $DIR/lint-unused-mut-variables.rs:29:9
+   |
+LL |         mut a: i32,
+   |         ----^
+   |         |
+   |         help: remove this `mut`
+
+error: variable does not need to be mutable
+  --> $DIR/lint-unused-mut-variables.rs:39:9
+   |
+LL |         mut a: i32,
+   |         ----^
+   |         |
+   |         help: remove this `mut`
+
+error: variable does not need to be mutable
+  --> $DIR/lint-unused-mut-variables.rs:48:9
+   |
+LL |         mut a: i32,
+   |         ----^
+   |         |
+   |         help: remove this `mut`
+
+error: variable does not need to be mutable
+  --> $DIR/lint-unused-mut-variables.rs:57:9
+   |
+LL |         mut a: i32,
+   |         ----^
+   |         |
+   |         help: remove this `mut`
+
+error: variable does not need to be mutable
+  --> $DIR/lint-unused-mut-variables.rs:62:9
+   |
+LL |         mut a: i32,
+   |         ----^
+   |         |
+   |         help: remove this `mut`
+
+error: variable does not need to be mutable
+  --> $DIR/lint-unused-mut-variables.rs:104:14
+   |
+LL |     let x = |mut y: isize| 10;
+   |              ----^
+   |              |
+   |              help: remove this `mut`
+
+error: variable does not need to be mutable
+  --> $DIR/lint-unused-mut-variables.rs:69:9
    |
 LL |     let mut a = 3;
    |         ----^
@@ -21,7 +85,7 @@ LL |     let mut a = 3;
    |         help: remove this `mut`
 
 error: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:13:9
+  --> $DIR/lint-unused-mut-variables.rs:71:9
    |
 LL |     let mut a = 2;
    |         ----^
@@ -29,7 +93,7 @@ LL |     let mut a = 2;
    |         help: remove this `mut`
 
 error: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:15:9
+  --> $DIR/lint-unused-mut-variables.rs:73:9
    |
 LL |     let mut b = 3;
    |         ----^
@@ -37,7 +101,7 @@ LL |     let mut b = 3;
    |         help: remove this `mut`
 
 error: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:17:9
+  --> $DIR/lint-unused-mut-variables.rs:75:9
    |
 LL |     let mut a = vec![3];
    |         ----^
@@ -45,7 +109,7 @@ LL |     let mut a = vec![3];
    |         help: remove this `mut`
 
 error: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:19:10
+  --> $DIR/lint-unused-mut-variables.rs:77:10
    |
 LL |     let (mut a, b) = (1, 2);
    |          ----^
@@ -53,7 +117,7 @@ LL |     let (mut a, b) = (1, 2);
    |          help: remove this `mut`
 
 error: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:21:9
+  --> $DIR/lint-unused-mut-variables.rs:79:9
    |
 LL |     let mut a;
    |         ----^
@@ -61,7 +125,7 @@ LL |     let mut a;
    |         help: remove this `mut`
 
 error: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:25:9
+  --> $DIR/lint-unused-mut-variables.rs:83:9
    |
 LL |     let mut b;
    |         ----^
@@ -69,7 +133,7 @@ LL |     let mut b;
    |         help: remove this `mut`
 
 error: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:34:9
+  --> $DIR/lint-unused-mut-variables.rs:92:9
    |
 LL |         mut x => {}
    |         ----^
@@ -77,7 +141,7 @@ LL |         mut x => {}
    |         help: remove this `mut`
 
 error: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:38:8
+  --> $DIR/lint-unused-mut-variables.rs:96:8
    |
 LL |       (mut x, 1) |
    |        ----^
@@ -85,7 +149,7 @@ LL |       (mut x, 1) |
    |        help: remove this `mut`
 
 error: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:51:9
+  --> $DIR/lint-unused-mut-variables.rs:109:9
    |
 LL |     let mut a = &mut 5;
    |         ----^
@@ -93,7 +157,7 @@ LL |     let mut a = &mut 5;
    |         help: remove this `mut`
 
 error: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:56:9
+  --> $DIR/lint-unused-mut-variables.rs:114:9
    |
 LL |     let mut b = (&mut a,);
    |         ----^
@@ -101,7 +165,7 @@ LL |     let mut b = (&mut a,);
    |         help: remove this `mut`
 
 error: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:59:9
+  --> $DIR/lint-unused-mut-variables.rs:117:9
    |
 LL |     let mut x = &mut 1;
    |         ----^
@@ -109,7 +173,7 @@ LL |     let mut x = &mut 1;
    |         help: remove this `mut`
 
 error: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:71:9
+  --> $DIR/lint-unused-mut-variables.rs:129:9
    |
 LL |     let mut v : &mut Vec<()> = &mut vec![];
    |         ----^
@@ -117,7 +181,7 @@ LL |     let mut v : &mut Vec<()> = &mut vec![];
    |         help: remove this `mut`
 
 error: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:48:13
+  --> $DIR/lint-unused-mut-variables.rs:106:13
    |
 LL |     fn what(mut foo: isize) {}
    |             ----^^^
@@ -125,7 +189,7 @@ LL |     fn what(mut foo: isize) {}
    |             help: remove this `mut`
 
 error: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:66:20
+  --> $DIR/lint-unused-mut-variables.rs:124:20
    |
 LL |     fn mut_ref_arg(mut arg : &mut [u8]) -> &mut [u8] {
    |                    ----^^^
@@ -133,7 +197,7 @@ LL |     fn mut_ref_arg(mut arg : &mut [u8]) -> &mut [u8] {
    |                    help: remove this `mut`
 
 error: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:138:9
+  --> $DIR/lint-unused-mut-variables.rs:196:9
    |
 LL |     let mut b = vec![2];
    |         ----^
@@ -141,10 +205,10 @@ LL |     let mut b = vec![2];
    |         help: remove this `mut`
    |
 note: lint level defined here
-  --> $DIR/lint-unused-mut-variables.rs:134:8
+  --> $DIR/lint-unused-mut-variables.rs:192:8
    |
 LL | #[deny(unused_mut)]
    |        ^^^^^^^^^^
 
-error: aborting due to 17 previous errors
+error: aborting due to 25 previous errors
 
diff --git a/src/test/ui/lint/lint-unused-variables.rs b/src/test/ui/lint/lint-unused-variables.rs
new file mode 100644 (file)
index 0000000..a1660d2
--- /dev/null
@@ -0,0 +1,64 @@
+// compile-flags: --cfg something
+// edition:2018
+
+#![feature(async_await, async_closure, param_attrs)]
+#![deny(unused_variables)]
+
+async fn foo_async(
+    a: i32,
+    //~^ ERROR unused variable: `a`
+    #[allow(unused_variables)] b: i32,
+) {}
+fn foo(
+    #[allow(unused_variables)] a: i32,
+    b: i32,
+    //~^ ERROR unused variable: `b`
+) {}
+
+struct RefStruct {}
+impl RefStruct {
+    async fn bar_async(
+        &self,
+        a: i32,
+        //~^ ERROR unused variable: `a`
+        #[allow(unused_variables)] b: i32,
+    ) {}
+    fn bar(
+        &self,
+        #[allow(unused_variables)] a: i32,
+        b: i32,
+        //~^ ERROR unused variable: `b`
+    ) {}
+}
+trait RefTrait {
+    fn bar(
+        &self,
+        #[allow(unused_variables)] a: i32,
+        b: i32,
+        //~^ ERROR unused variable: `b`
+    ) {}
+}
+impl RefTrait for RefStruct {
+    fn bar(
+        &self,
+        #[allow(unused_variables)] a: i32,
+        b: i32,
+        //~^ ERROR unused variable: `b`
+    ) {}
+}
+
+fn main() {
+    let _: fn(_, _) = foo;
+    let a = async move |
+        a: i32,
+        //~^ ERROR unused variable: `a`
+        #[allow(unused_variables)] b: i32,
+    | {};
+    let b = |
+        #[allow(unused_variables)] a: i32,
+        b: i32,
+        //~^ ERROR unused variable: `b`
+    | {};
+    let _ = a(1, 2);
+    let _ = b(1, 2);
+}
diff --git a/src/test/ui/lint/lint-unused-variables.stderr b/src/test/ui/lint/lint-unused-variables.stderr
new file mode 100644 (file)
index 0000000..7ed5669
--- /dev/null
@@ -0,0 +1,56 @@
+error: unused variable: `a`
+  --> $DIR/lint-unused-variables.rs:8:5
+   |
+LL |     a: i32,
+   |     ^ help: consider prefixing with an underscore: `_a`
+   |
+note: lint level defined here
+  --> $DIR/lint-unused-variables.rs:5:9
+   |
+LL | #![deny(unused_variables)]
+   |         ^^^^^^^^^^^^^^^^
+
+error: unused variable: `b`
+  --> $DIR/lint-unused-variables.rs:14:5
+   |
+LL |     b: i32,
+   |     ^ help: consider prefixing with an underscore: `_b`
+
+error: unused variable: `a`
+  --> $DIR/lint-unused-variables.rs:53:9
+   |
+LL |         a: i32,
+   |         ^ help: consider prefixing with an underscore: `_a`
+
+error: unused variable: `b`
+  --> $DIR/lint-unused-variables.rs:59:9
+   |
+LL |         b: i32,
+   |         ^ help: consider prefixing with an underscore: `_b`
+
+error: unused variable: `b`
+  --> $DIR/lint-unused-variables.rs:37:9
+   |
+LL |         b: i32,
+   |         ^ help: consider prefixing with an underscore: `_b`
+
+error: unused variable: `a`
+  --> $DIR/lint-unused-variables.rs:22:9
+   |
+LL |         a: i32,
+   |         ^ help: consider prefixing with an underscore: `_a`
+
+error: unused variable: `b`
+  --> $DIR/lint-unused-variables.rs:29:9
+   |
+LL |         b: i32,
+   |         ^ help: consider prefixing with an underscore: `_b`
+
+error: unused variable: `b`
+  --> $DIR/lint-unused-variables.rs:45:9
+   |
+LL |         b: i32,
+   |         ^ help: consider prefixing with an underscore: `_b`
+
+error: aborting due to 8 previous errors
+
index 061c5cc7b3c0e8cc0b617ecfc63ba1523b98cea3..ec0b64a10953fb960ed1afc98c22c64ff3f499f3 100644 (file)
@@ -1,6 +1,5 @@
 #![no_std]
 
-#[allow(unused_extern_crates)]
 #[macro_use(foo(bar))]  //~ ERROR bad macro import
 extern crate std;
 
index f403c8a36608443bc77d513d6e67c8a0312f8943..4e5482a518c9586dc8a803cc9d4e61ea13e708fc 100644 (file)
@@ -1,5 +1,5 @@
 error[E0466]: bad macro import
-  --> $DIR/macro-use-bad-args-1.rs:4:13
+  --> $DIR/macro-use-bad-args-1.rs:3:13
    |
 LL | #[macro_use(foo(bar))]
    |             ^^^^^^^^
index cb231ce292a96b77d9eedf2a25003260c172cddb..c5f8f62c186864a0720b4142fbb28f2160f69d15 100644 (file)
@@ -1,6 +1,5 @@
 #![no_std]
 
-#[allow(unused_extern_crates)]
 #[macro_use(foo="bar")]  //~ ERROR bad macro import
 extern crate std;
 
index 93617edeeaea49020cefd0e926ef9c7f175529fa..c958104eac43bfec5c84e62c89941236404ff94a 100644 (file)
@@ -1,5 +1,5 @@
 error[E0466]: bad macro import
-  --> $DIR/macro-use-bad-args-2.rs:4:13
+  --> $DIR/macro-use-bad-args-2.rs:3:13
    |
 LL | #[macro_use(foo="bar")]
    |             ^^^^^^^^^
diff --git a/src/test/ui/match/issue-50900.rs b/src/test/ui/match/issue-50900.rs
new file mode 100644 (file)
index 0000000..27135af
--- /dev/null
@@ -0,0 +1,19 @@
+#[derive(PartialEq, Eq)]
+pub struct Tag(pub Context, pub u16);
+
+#[derive(PartialEq, Eq)]
+pub enum Context {
+    Tiff,
+    Exif,
+}
+
+impl Tag {
+    const ExifIFDPointer: Tag = Tag(Context::Tiff, 34665);
+}
+
+fn main() {
+    match Tag::ExifIFDPointer {
+    //~^ ERROR: non-exhaustive patterns: `Tag(Exif, _)` not covered
+        Tag::ExifIFDPointer => {}
+    }
+}
diff --git a/src/test/ui/match/issue-50900.stderr b/src/test/ui/match/issue-50900.stderr
new file mode 100644 (file)
index 0000000..7192f11
--- /dev/null
@@ -0,0 +1,14 @@
+error[E0004]: non-exhaustive patterns: `Tag(Exif, _)` not covered
+  --> $DIR/issue-50900.rs:15:11
+   |
+LL | pub struct Tag(pub Context, pub u16);
+   | ------------------------------------- `Tag` defined here
+...
+LL |     match Tag::ExifIFDPointer {
+   |           ^^^^^^^^^^^^^^^^^^^ pattern `Tag(Exif, _)` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
index 5e61c1b22a085f1a0d200644bab318f832879cdd..a0ef92743ac5a775517d94c1a5ba277078da5f61 100644 (file)
@@ -19,10 +19,10 @@ fn main() {
     match [0, 1, 2] {
         [0] => {}, //~ ERROR pattern requires
 
-        [0, 1, x..] => {
+        [0, 1, x @ ..] => {
             let a: [_; 1] = x;
         }
-        [0, 1, 2, 3, x..] => {} //~ ERROR pattern requires
+        [0, 1, 2, 3, x @ ..] => {} //~ ERROR pattern requires
     };
 
     match does_not_exist { //~ ERROR cannot find value `does_not_exist` in this scope
index 47f9d48e26290a32e3ccb63dc286af5b9833cd6e..2f1bbb7621659c6641661486201b0c0f61f6890e 100644 (file)
@@ -19,8 +19,8 @@ LL |         [0] => {},
 error[E0528]: pattern requires at least 4 elements but array has 3
   --> $DIR/match-vec-mismatch.rs:25:9
    |
-LL |         [0, 1, 2, 3, x..] => {}
-   |         ^^^^^^^^^^^^^^^^^ pattern cannot match array of 3 elements
+LL |         [0, 1, 2, 3, x @ ..] => {}
+   |         ^^^^^^^^^^^^^^^^^^^^ pattern cannot match array of 3 elements
 
 error[E0282]: type annotations needed
   --> $DIR/match-vec-mismatch.rs:36:9
index 9e167f37ba9d9712cf05a80af506af80849281ba..78810525bad0f76b4653d3ab4abbf5df382c9f85 100644 (file)
@@ -23,7 +23,7 @@ fn main() {
     let x: Vec<char> = vec!['a', 'b', 'c'];
     let x: &[char] = &x;
     match *x {
-        ['a', 'b', 'c', ref _tail..] => {}
+        ['a', 'b', 'c', ref _tail @ ..] => {}
         ['a', 'b', 'c'] => {} //~ ERROR unreachable pattern
         _ => {}
     }
index a9347926bda0a554ba69bb081e38d75d2b178540..79a0807c3372155efc11f5c55d3bb2862c4d1442 100644 (file)
@@ -2,11 +2,13 @@ error[E0308]: mismatched types
   --> $DIR/issue-38371.rs:4:8
    |
 LL | fn foo(&foo: Foo) {
-   |        ^^^^ expected struct `Foo`, found reference
+   |        ^^^^------
+   |        |
+   |        expected struct `Foo`, found reference
+   |        help: did you mean `foo`: `&Foo`
    |
    = note: expected type `Foo`
               found type `&_`
-   = help: did you mean `foo: &Foo`?
 
 error[E0308]: mismatched types
   --> $DIR/issue-38371.rs:18:9
index 09879c791f89f1ca11c177fc06612df36f4c33a5..e9664a4dd480e950198913fa1bc7e809c17cbb62 100644 (file)
@@ -1,5 +1,4 @@
 #![no_std]
-#![allow(unused_extern_crates)]
 
 extern crate core; //~ ERROR: the name `core` is defined multiple times
 extern crate std;
index 975f5c2f50c5d942f39b4a3495dc98f0a06bcb20..a82931e0fbdd050710e2c795871101bfe920fa99 100644 (file)
@@ -1,5 +1,5 @@
 error[E0259]: the name `core` is defined multiple times
-  --> $DIR/no-std-inject.rs:4:1
+  --> $DIR/no-std-inject.rs:3:1
    |
 LL | extern crate core;
    | ^^^^^^^^^^^^^^^^^^ `core` reimported here
index e888bcf516891554d13d93517bae657ef26ade0e..8cc5f4042cccb1f4ab94b7fef19a7d9b0c1dd9b4 100644 (file)
@@ -32,14 +32,14 @@ fn main() {
     let vec = vec![Some(42), None, Some(21)];
     let vec: &[Option<isize>] = &vec;
     match *vec { //~ ERROR non-exhaustive patterns: `[]` not covered
-        [Some(..), None, ref tail..] => {}
-        [Some(..), Some(..), ref tail..] => {}
+        [Some(..), None, ref tail @ ..] => {}
+        [Some(..), Some(..), ref tail @ ..] => {}
         [None] => {}
     }
     let vec = vec![1];
     let vec: &[isize] = &vec;
     match *vec {
-        [_, ref tail..] => (),
+        [_, ref tail @ ..] => (),
         [] => ()
     }
     let vec = vec![0.5f32];
@@ -53,10 +53,10 @@ fn main() {
     let vec = vec![Some(42), None, Some(21)];
     let vec: &[Option<isize>] = &vec;
     match *vec {
-        [Some(..), None, ref tail..] => {}
-        [Some(..), Some(..), ref tail..] => {}
-        [None, None, ref tail..] => {}
-        [None, Some(..), ref tail..] => {}
+        [Some(..), None, ref tail @ ..] => {}
+        [Some(..), Some(..), ref tail @ ..] => {}
+        [None, None, ref tail @ ..] => {}
+        [None, Some(..), ref tail @ ..] => {}
         [Some(_)] => {}
         [None] => {}
         [] => {}
index 9fcd4bdad7264aea7bbdb4c9a76d317ecbbce6af..4ca1cbcebccf51a94b249e9f5d6dc30535b11137 100644 (file)
@@ -77,7 +77,7 @@ fn vectors_with_nested_enums() {
         [Enum::Second(true), Enum::First] => (),
         [Enum::Second(true), Enum::Second(true)] => (),
         [Enum::Second(false), _] => (),
-        [_, _, ref tail.., _] => ()
+        [_, _, ref tail @ .., _] => ()
     }
 }
 
index 5111b40603c496b4332bdee7e6b04dc38c21d591..400a0276b3b608f8719535175c3ad846dd52b2c4 100644 (file)
@@ -1,8 +1,8 @@
 error: an inner attribute is not permitted in this context
-  --> $DIR/attr.rs:5:3
+  --> $DIR/attr.rs:5:1
    |
 LL | #![lang = "foo"]
-   |   ^
+   | ^^^^^^^^^^^^^^^^
    |
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
index 0dde49a2913f1c4003fc39cde18c28dd23a92a51..b012abc25e7f3bd2b7755ce28798495da3be813a 100644 (file)
@@ -1,8 +1,13 @@
 error: an inner attribute is not permitted following an outer doc comment
-  --> $DIR/inner-attr-after-doc-comment.rs:6:3
+  --> $DIR/inner-attr-after-doc-comment.rs:6:1
    |
-LL | #![recursion_limit="100"]
-   |   ^
+LL | / /**
+LL | |  * My module
+LL | |  */
+   | |___- previous doc comment
+LL | 
+LL |   #![recursion_limit="100"]
+   |   ^^^^^^^^^^^^^^^^^^^^^^^^^ not permitted following an outer attibute
    |
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
index 11a37bc139b3c61cfc71e534a8179a164e657df6..070d9f47d96f925e04bcc7abb412ebb1e06d193f 100644 (file)
@@ -1,8 +1,11 @@
 error: an inner attribute is not permitted following an outer attribute
-  --> $DIR/inner-attr.rs:3:3
+  --> $DIR/inner-attr.rs:3:1
    |
+LL | #[feature(lang_items)]
+   | ---------------------- previous outer attribute
+LL | 
 LL | #![recursion_limit="100"]
-   |   ^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^ not permitted following an outer attibute
    |
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
 
diff --git a/src/test/ui/parser/issue-62973.rs b/src/test/ui/parser/issue-62973.rs
new file mode 100644 (file)
index 0000000..18bc51e
--- /dev/null
@@ -0,0 +1,8 @@
+// ignore-tidy-trailing-newlines
+// error-pattern: aborting due to 6 previous errors
+
+fn main() {}
+
+fn p() { match s { v, E { [) {) }
+
+
diff --git a/src/test/ui/parser/issue-62973.stderr b/src/test/ui/parser/issue-62973.stderr
new file mode 100644 (file)
index 0000000..141076b
--- /dev/null
@@ -0,0 +1,61 @@
+error: this file contains an un-closed delimiter
+  --> $DIR/issue-62973.rs:8:2
+   |
+LL | fn p() { match s { v, E { [) {) }
+   |        -         - un-closed delimiter
+   |        |
+   |        un-closed delimiter
+LL | 
+LL | 
+   |  ^
+
+error: expected one of `,` or `}`, found `{`
+  --> $DIR/issue-62973.rs:6:25
+   |
+LL | fn p() { match s { v, E { [) {) }
+   |                -        ^ expected one of `,` or `}` here
+   |                |
+   |                while parsing this struct
+
+error: struct literals are not allowed here
+  --> $DIR/issue-62973.rs:6:16
+   |
+LL |   fn p() { match s { v, E { [) {) }
+   |  ________________^
+LL | |
+LL | |
+   | |_^
+help: surround the struct literal with parentheses
+   |
+LL | fn p() { match (s { v, E { [) {) }
+LL | 
+LL | )
+   |
+
+error: expected one of `.`, `?`, `{`, or an operator, found `}`
+  --> $DIR/issue-62973.rs:8:1
+   |
+LL | fn p() { match s { v, E { [) {) }
+   |          ----- while parsing this match expression
+LL | 
+LL | 
+   | ^ expected one of `.`, `?`, `{`, or an operator here
+
+error: incorrect close delimiter: `)`
+  --> $DIR/issue-62973.rs:6:28
+   |
+LL | fn p() { match s { v, E { [) {) }
+   |                           -^ incorrect close delimiter
+   |                           |
+   |                           un-closed delimiter
+
+error: incorrect close delimiter: `)`
+  --> $DIR/issue-62973.rs:6:31
+   |
+LL | fn p() { match s { v, E { [) {) }
+   |                              -^ incorrect close delimiter
+   |                              |
+   |                              un-closed delimiter
+
+error: aborting due to 6 previous errors
+
index e5e85ba8ca602c48f3f8ce82d6eb1ba769d8b3fd..00f4374b256d20a115f312bb480cdc6ea5a773d7 100644 (file)
@@ -1,7 +1,13 @@
 fn main() {
-    let a = Vec::new();
+    let a: &[u8] = &[];
     match a {
-        [1, tail.., tail..] => {}, //~ ERROR: expected one of `,` or `@`, found `..`
+        [1, tail @ .., tail @ ..] => {},
+        //~^ ERROR identifier `tail` is bound more than once in the same pattern
+        //~| ERROR subslice patterns are unstable
+        //~| ERROR subslice patterns are unstable
+        //~| ERROR `..` can only be used once per slice pattern
         _ => ()
     }
 }
+
+const RECOVERY_WITNESS: () = 0; //~ ERROR mismatched types
index fee8d248dcf07f68c7a00f72923c047492e2eb8d..0956ac21b7f1e4abecf968a5a21b62a681f5c7dd 100644 (file)
@@ -1,8 +1,45 @@
-error: expected one of `,` or `@`, found `..`
-  --> $DIR/match-vec-invalid.rs:4:25
+error[E0416]: identifier `tail` is bound more than once in the same pattern
+  --> $DIR/match-vec-invalid.rs:4:24
    |
-LL |         [1, tail.., tail..] => {},
-   |                         ^^ expected one of `,` or `@` here
+LL |         [1, tail @ .., tail @ ..] => {},
+   |                        ^^^^ used in a pattern more than once
 
-error: aborting due to previous error
+error[E0658]: subslice patterns are unstable
+  --> $DIR/match-vec-invalid.rs:4:13
+   |
+LL |         [1, tail @ .., tail @ ..] => {},
+   |             ^^^^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/62254
+   = help: add `#![feature(slice_patterns)]` to the crate attributes to enable
+
+error[E0658]: subslice patterns are unstable
+  --> $DIR/match-vec-invalid.rs:4:24
+   |
+LL |         [1, tail @ .., tail @ ..] => {},
+   |                        ^^^^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/62254
+   = help: add `#![feature(slice_patterns)]` to the crate attributes to enable
+
+error: `..` can only be used once per slice pattern
+  --> $DIR/match-vec-invalid.rs:4:31
+   |
+LL |         [1, tail @ .., tail @ ..] => {},
+   |                    --         ^^ can only be used once per slice pattern
+   |                    |
+   |                    previously used here
+
+error[E0308]: mismatched types
+  --> $DIR/match-vec-invalid.rs:13:30
+   |
+LL | const RECOVERY_WITNESS: () = 0;
+   |                              ^ expected (), found integer
+   |
+   = note: expected type `()`
+              found type `{integer}`
+
+error: aborting due to 5 previous errors
 
+Some errors have detailed explanations: E0308, E0416, E0658.
+For more information about an error, try `rustc --explain E0308`.
index 9bad0cb25c1e4151736c89b950f0f0dfde56cbfa..7b9721830993efc2fc1a70f9b299ea86c39bc2cc 100644 (file)
@@ -1,3 +1,9 @@
 fn main() {
+    struct Test(&'static u8, [u8; 0]);
+    let x = Test(&0, []);
+
     let Test(&desc[..]) = x; //~ ERROR: expected one of `)`, `,`, or `@`, found `[`
+    //~^ ERROR subslice patterns are unstable
 }
+
+const RECOVERY_WITNESS: () = 0; //~ ERROR mismatched types
index 2ee4bdb20fe88a8b438167f59d3c5d6562d8c180..201465b2c850c87f13720db143d85e6419b78dc4 100644 (file)
@@ -1,8 +1,28 @@
 error: expected one of `)`, `,`, or `@`, found `[`
-  --> $DIR/pat-lt-bracket-6.rs:2:19
+  --> $DIR/pat-lt-bracket-6.rs:5:19
    |
 LL |     let Test(&desc[..]) = x;
    |                   ^ expected one of `)`, `,`, or `@` here
 
-error: aborting due to previous error
+error[E0658]: subslice patterns are unstable
+  --> $DIR/pat-lt-bracket-6.rs:5:20
+   |
+LL |     let Test(&desc[..]) = x;
+   |                    ^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/62254
+   = help: add `#![feature(slice_patterns)]` to the crate attributes to enable
+
+error[E0308]: mismatched types
+  --> $DIR/pat-lt-bracket-6.rs:9:30
+   |
+LL | const RECOVERY_WITNESS: () = 0;
+   |                              ^ expected (), found integer
+   |
+   = note: expected type `()`
+              found type `{integer}`
+
+error: aborting due to 3 previous errors
 
+Some errors have detailed explanations: E0308, E0658.
+For more information about an error, try `rustc --explain E0308`.
index 36c0d7733733ab2b6501b0aa74976ff8c0d9ddcb..020fdb845e8b5fd4ca73f041532fb0d6cb4dbe3d 100644 (file)
@@ -1,3 +1,8 @@
 fn main() {
-    for thing(x[]) in foo {} //~ ERROR: expected one of `)`, `,`, or `@`, found `[`
+    struct Thing(u8, [u8; 0]);
+    let foo = core::iter::empty();
+
+    for Thing(x[]) in foo {} //~ ERROR: expected one of `)`, `,`, or `@`, found `[`
 }
+
+const RECOVERY_WITNESS: () = 0; //~ ERROR mismatched types
index 5552ea46d9b9d432ca5ca39df9606ce05b4237de..17557efa49e803e70c1369448fc0a183d3c3aaf6 100644 (file)
@@ -1,8 +1,18 @@
 error: expected one of `)`, `,`, or `@`, found `[`
-  --> $DIR/pat-lt-bracket-7.rs:2:16
+  --> $DIR/pat-lt-bracket-7.rs:5:16
    |
-LL |     for thing(x[]) in foo {}
+LL |     for Thing(x[]) in foo {}
    |                ^ expected one of `)`, `,`, or `@` here
 
-error: aborting due to previous error
+error[E0308]: mismatched types
+  --> $DIR/pat-lt-bracket-7.rs:8:30
+   |
+LL | const RECOVERY_WITNESS: () = 0;
+   |                              ^ expected (), found integer
+   |
+   = note: expected type `()`
+              found type `{integer}`
+
+error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0308`.
index fd25499381a2849df1801e7b5733a52ff5bddf86..a8f3debd3d6341a9997272379d24f41ac6ec3b12 100644 (file)
@@ -1,6 +1,7 @@
+// check-pass
+
 fn main() {
     match (0, 1, 2) {
         (pat, ..,) => {}
-        //~^ ERROR trailing comma is not permitted after `..`
     }
 }
diff --git a/src/test/ui/parser/pat-tuple-2.stderr b/src/test/ui/parser/pat-tuple-2.stderr
deleted file mode 100644 (file)
index c3a5c39..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-error: trailing comma is not permitted after `..`
-  --> $DIR/pat-tuple-2.rs:3:17
-   |
-LL |         (pat, ..,) => {}
-   |                 ^ trailing comma is not permitted after `..`
-
-error: aborting due to previous error
-
index e1e975d3c3ea04b3a7d3a42b434d2a9f998ce65e..1486ab231aab4f084fc404433339616c803179c5 100644 (file)
@@ -1,6 +1,6 @@
 fn main() {
     match (0, 1, 2) {
         (.., pat, ..) => {}
-        //~^ ERROR `..` can only be used once per tuple or tuple struct pattern
+        //~^ ERROR `..` can only be used once per tuple pattern
     }
 }
index c9f14bb90429b90e3c0b97cf456bf8aa8760c1b9..9ac0611c5c933230c2d8b82ab9e149babeca997c 100644 (file)
@@ -1,10 +1,10 @@
-error: `..` can only be used once per tuple or tuple struct pattern
+error: `..` can only be used once per tuple pattern
   --> $DIR/pat-tuple-3.rs:3:19
    |
 LL |         (.., pat, ..) => {}
-   |          --       ^^ can only be used once per pattern
+   |          --       ^^ can only be used once per tuple pattern
    |          |
-   |          previously present here
+   |          previously used here
 
 error: aborting due to previous error
 
index 76f60d94bc86ea750c3062e53371b1a59a0825f4..2f03160430a22fa4df6befd3495e0f3a5cab158a 100644 (file)
@@ -1,5 +1,11 @@
 fn main() {
+    const PAT: u8 = 0;
+
     match 0 {
-        (.. pat) => {} //~ ERROR expected one of `)` or `,`, found `pat`
+        (.. PAT) => {}
+        //~^ ERROR `..X` range patterns are not supported
+        //~| ERROR exclusive range pattern syntax is experimental
     }
 }
+
+const RECOVERY_WITNESS: () = 0; //~ ERROR mismatched types
index 26b92fae3139141ffd00e4afe038b0f670955ee8..af3ecce1846497d485d7ad5bf0671d593b79cc9e 100644 (file)
@@ -1,8 +1,28 @@
-error: expected one of `)` or `,`, found `pat`
-  --> $DIR/pat-tuple-4.rs:3:13
+error: `..X` range patterns are not supported
+  --> $DIR/pat-tuple-4.rs:5:10
    |
-LL |         (.. pat) => {}
-   |             ^^^ expected one of `)` or `,` here
+LL |         (.. PAT) => {}
+   |          ^^^^^^ help: try using the minimum value for the type: `MIN..PAT`
 
-error: aborting due to previous error
+error[E0658]: exclusive range pattern syntax is experimental
+  --> $DIR/pat-tuple-4.rs:5:10
+   |
+LL |         (.. PAT) => {}
+   |          ^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/37854
+   = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
+
+error[E0308]: mismatched types
+  --> $DIR/pat-tuple-4.rs:11:30
+   |
+LL | const RECOVERY_WITNESS: () = 0;
+   |                              ^ expected (), found integer
+   |
+   = note: expected type `()`
+              found type `{integer}`
+
+error: aborting due to 3 previous errors
 
+Some errors have detailed explanations: E0308, E0658.
+For more information about an error, try `rustc --explain E0308`.
index d4f05a5eb523ee6053a2b4e3e7ff1d8b6bea8670..5334ef93bb3bd1e6c8be8505893dd3bb1065d7fd 100644 (file)
@@ -1,5 +1,10 @@
 fn main() {
+    const PAT: u8 = 0;
+
     match (0, 1) {
-        (pat ..) => {} //~ ERROR unexpected token: `)`
+        (PAT ..) => {}
+        //~^ ERROR `X..` range patterns are not supported
+        //~| ERROR exclusive range pattern syntax is experimental
+        //~| ERROR mismatched types
     }
 }
index f9832214c6800b4c7ba8fc0012d47ecc78a86b22..09ebdc29a21613cbe0dc25278324d6678f593d2d 100644 (file)
@@ -1,8 +1,30 @@
-error: unexpected token: `)`
-  --> $DIR/pat-tuple-5.rs:3:16
+error: `X..` range patterns are not supported
+  --> $DIR/pat-tuple-5.rs:5:10
    |
-LL |         (pat ..) => {}
-   |                ^
+LL |         (PAT ..) => {}
+   |          ^^^^^^ help: try using the maximum value for the type: `PAT..MAX`
 
-error: aborting due to previous error
+error[E0658]: exclusive range pattern syntax is experimental
+  --> $DIR/pat-tuple-5.rs:5:10
+   |
+LL |         (PAT ..) => {}
+   |          ^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/37854
+   = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
+
+error[E0308]: mismatched types
+  --> $DIR/pat-tuple-5.rs:5:10
+   |
+LL |     match (0, 1) {
+   |           ------ this match expression has type `({integer}, {integer})`
+LL |         (PAT ..) => {}
+   |          ^^^^^^ expected tuple, found u8
+   |
+   = note: expected type `({integer}, {integer})`
+              found type `u8`
+
+error: aborting due to 3 previous errors
 
+Some errors have detailed explanations: E0308, E0658.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/parser/recover-range-pats.rs b/src/test/ui/parser/recover-range-pats.rs
new file mode 100644 (file)
index 0000000..c66652f
--- /dev/null
@@ -0,0 +1,123 @@
+// Here we test all kinds of range patterns in terms of parsing / recovery.
+// We want to ensure that:
+// 1. Things parse as they should.
+// 2. Or at least we have parser recovery if they don't.
+
+#![feature(exclusive_range_pattern)]
+#![deny(ellipsis_inclusive_range_patterns)]
+
+fn main() {}
+
+const X: u8 = 0;
+const Y: u8 = 3;
+
+fn exclusive_from_to() {
+    if let 0..3 = 0 {} // OK.
+    if let 0..Y = 0 {} // OK.
+    if let X..3 = 0 {} // OK.
+    if let X..Y = 0 {} // OK.
+    if let true..Y = 0 {} //~ ERROR only char and numeric types
+    if let X..true = 0 {} //~ ERROR only char and numeric types
+    if let .0..Y = 0 {} //~ ERROR mismatched types
+    //~^ ERROR float literals must have an integer part
+    if let X.. .0 = 0 {} //~ ERROR mismatched types
+    //~^ ERROR float literals must have an integer part
+}
+
+fn inclusive_from_to() {
+    if let 0..=3 = 0 {} // OK.
+    if let 0..=Y = 0 {} // OK.
+    if let X..=3 = 0 {} // OK.
+    if let X..=Y = 0 {} // OK.
+    if let true..=Y = 0 {} //~ ERROR only char and numeric types
+    if let X..=true = 0 {} //~ ERROR only char and numeric types
+    if let .0..=Y = 0 {} //~ ERROR mismatched types
+    //~^ ERROR float literals must have an integer part
+    if let X..=.0 = 0 {} //~ ERROR mismatched types
+    //~^ ERROR float literals must have an integer part
+}
+
+fn inclusive2_from_to() {
+    if let 0...3 = 0 {} //~ ERROR `...` range patterns are deprecated
+    if let 0...Y = 0 {} //~ ERROR `...` range patterns are deprecated
+    if let X...3 = 0 {} //~ ERROR `...` range patterns are deprecated
+    if let X...Y = 0 {} //~ ERROR `...` range patterns are deprecated
+    if let true...Y = 0 {} //~ ERROR only char and numeric types
+    //~^ ERROR `...` range patterns are deprecated
+    if let X...true = 0 {} //~ ERROR only char and numeric types
+    //~^ ERROR `...` range patterns are deprecated
+    if let .0...Y = 0 {} //~ ERROR mismatched types
+    //~^ ERROR float literals must have an integer part
+    //~| ERROR `...` range patterns are deprecated
+    if let X... .0 = 0 {} //~ ERROR mismatched types
+    //~^ ERROR float literals must have an integer part
+    //~| ERROR `...` range patterns are deprecated
+}
+
+fn exclusive_from() {
+    if let 0.. = 0 {} //~ ERROR `X..` range patterns are not supported
+    if let X.. = 0 {} //~ ERROR `X..` range patterns are not supported
+    if let true.. = 0 {} //~ ERROR `X..` range patterns are not supported
+    //~^ ERROR only char and numeric types
+    if let .0.. = 0 {} //~ ERROR `X..` range patterns are not supported
+    //~^ ERROR float literals must have an integer part
+    //~| ERROR mismatched types
+}
+
+fn inclusive_from() {
+    if let 0..= = 0 {} //~ ERROR `X..=` range patterns are not supported
+    if let X..= = 0 {} //~ ERROR `X..=` range patterns are not supported
+    if let true..= = 0 {} //~ ERROR `X..=` range patterns are not supported
+    //~| ERROR only char and numeric types
+    if let .0..= = 0 {} //~ ERROR `X..=` range patterns are not supported
+    //~^ ERROR float literals must have an integer part
+    //~| ERROR mismatched types
+}
+
+fn inclusive2_from() {
+    if let 0... = 0 {} //~ ERROR `X...` range patterns are not supported
+    //~^ ERROR `...` range patterns are deprecated
+    if let X... = 0 {} //~ ERROR `X...` range patterns are not supported
+    //~^ ERROR `...` range patterns are deprecated
+    if let true... = 0 {} //~ ERROR `X...` range patterns are not supported
+    //~^ ERROR `...` range patterns are deprecated
+    //~| ERROR only char and numeric types
+    if let .0... = 0 {} //~ ERROR `X...` range patterns are not supported
+    //~^ ERROR float literals must have an integer part
+    //~| ERROR `...` range patterns are deprecated
+    //~| ERROR mismatched types
+}
+
+fn exclusive_to() {
+    if let ..0 = 0 {} //~ ERROR `..X` range patterns are not supported
+    if let ..Y = 0 {} //~ ERROR `..X` range patterns are not supported
+    if let ..true = 0 {} //~ ERROR `..X` range patterns are not supported
+    //~| ERROR only char and numeric types
+    if let .. .0 = 0 {} //~ ERROR `..X` range patterns are not supported
+    //~^ ERROR float literals must have an integer part
+    //~| ERROR mismatched types
+}
+
+fn inclusive_to() {
+    if let ..=3 = 0 {} //~ ERROR `..=X` range patterns are not supported
+    if let ..=Y = 0 {} //~ ERROR `..=X` range patterns are not supported
+    if let ..=true = 0 {} //~ ERROR `..=X` range patterns are not supported
+    //~| ERROR only char and numeric types
+    if let ..=.0 = 0 {} //~ ERROR `..=X` range patterns are not supported
+    //~^ ERROR float literals must have an integer part
+    //~| ERROR mismatched types
+}
+
+fn inclusive2_to() {
+    if let ...3 = 0 {} //~ ERROR `...X` range patterns are not supported
+    //~^ ERROR `...` range patterns are deprecated
+    if let ...Y = 0 {} //~ ERROR `...X` range patterns are not supported
+    //~^ ERROR `...` range patterns are deprecated
+    if let ...true = 0 {} //~ ERROR `...X` range patterns are not supported
+    //~^ ERROR `...` range patterns are deprecated
+    //~| ERROR only char and numeric types
+    if let ....3 = 0 {} //~ ERROR `...X` range patterns are not supported
+    //~^ ERROR float literals must have an integer part
+    //~| ERROR `...` range patterns are deprecated
+    //~| ERROR mismatched types
+}
diff --git a/src/test/ui/parser/recover-range-pats.stderr b/src/test/ui/parser/recover-range-pats.stderr
new file mode 100644 (file)
index 0000000..c50d5e6
--- /dev/null
@@ -0,0 +1,538 @@
+error: float literals must have an integer part
+  --> $DIR/recover-range-pats.rs:21:12
+   |
+LL |     if let .0..Y = 0 {}
+   |            ^^ help: must have an integer part: `0.0`
+
+error: float literals must have an integer part
+  --> $DIR/recover-range-pats.rs:23:16
+   |
+LL |     if let X.. .0 = 0 {}
+   |                ^^ help: must have an integer part: `0.0`
+
+error: float literals must have an integer part
+  --> $DIR/recover-range-pats.rs:34:12
+   |
+LL |     if let .0..=Y = 0 {}
+   |            ^^ help: must have an integer part: `0.0`
+
+error: float literals must have an integer part
+  --> $DIR/recover-range-pats.rs:36:16
+   |
+LL |     if let X..=.0 = 0 {}
+   |                ^^ help: must have an integer part: `0.0`
+
+error: float literals must have an integer part
+  --> $DIR/recover-range-pats.rs:49:12
+   |
+LL |     if let .0...Y = 0 {}
+   |            ^^ help: must have an integer part: `0.0`
+
+error: float literals must have an integer part
+  --> $DIR/recover-range-pats.rs:52:17
+   |
+LL |     if let X... .0 = 0 {}
+   |                 ^^ help: must have an integer part: `0.0`
+
+error: `X..` range patterns are not supported
+  --> $DIR/recover-range-pats.rs:58:12
+   |
+LL |     if let 0.. = 0 {}
+   |            ^^^ help: try using the maximum value for the type: `0..MAX`
+
+error: `X..` range patterns are not supported
+  --> $DIR/recover-range-pats.rs:59:12
+   |
+LL |     if let X.. = 0 {}
+   |            ^^^ help: try using the maximum value for the type: `X..MAX`
+
+error: `X..` range patterns are not supported
+  --> $DIR/recover-range-pats.rs:60:12
+   |
+LL |     if let true.. = 0 {}
+   |            ^^^^^^ help: try using the maximum value for the type: `true..MAX`
+
+error: float literals must have an integer part
+  --> $DIR/recover-range-pats.rs:62:12
+   |
+LL |     if let .0.. = 0 {}
+   |            ^^ help: must have an integer part: `0.0`
+
+error: `X..` range patterns are not supported
+  --> $DIR/recover-range-pats.rs:62:12
+   |
+LL |     if let .0.. = 0 {}
+   |            ^^^^ help: try using the maximum value for the type: `0.0..MAX`
+
+error: `X..=` range patterns are not supported
+  --> $DIR/recover-range-pats.rs:68:12
+   |
+LL |     if let 0..= = 0 {}
+   |            ^^^^ help: try using the maximum value for the type: `0..=MAX`
+
+error: `X..=` range patterns are not supported
+  --> $DIR/recover-range-pats.rs:69:12
+   |
+LL |     if let X..= = 0 {}
+   |            ^^^^ help: try using the maximum value for the type: `X..=MAX`
+
+error: `X..=` range patterns are not supported
+  --> $DIR/recover-range-pats.rs:70:12
+   |
+LL |     if let true..= = 0 {}
+   |            ^^^^^^^ help: try using the maximum value for the type: `true..=MAX`
+
+error: float literals must have an integer part
+  --> $DIR/recover-range-pats.rs:72:12
+   |
+LL |     if let .0..= = 0 {}
+   |            ^^ help: must have an integer part: `0.0`
+
+error: `X..=` range patterns are not supported
+  --> $DIR/recover-range-pats.rs:72:12
+   |
+LL |     if let .0..= = 0 {}
+   |            ^^^^^ help: try using the maximum value for the type: `0.0..=MAX`
+
+error: `X...` range patterns are not supported
+  --> $DIR/recover-range-pats.rs:78:12
+   |
+LL |     if let 0... = 0 {}
+   |            ^^^^ help: try using the maximum value for the type: `0...MAX`
+
+error: `X...` range patterns are not supported
+  --> $DIR/recover-range-pats.rs:80:12
+   |
+LL |     if let X... = 0 {}
+   |            ^^^^ help: try using the maximum value for the type: `X...MAX`
+
+error: `X...` range patterns are not supported
+  --> $DIR/recover-range-pats.rs:82:12
+   |
+LL |     if let true... = 0 {}
+   |            ^^^^^^^ help: try using the maximum value for the type: `true...MAX`
+
+error: float literals must have an integer part
+  --> $DIR/recover-range-pats.rs:85:12
+   |
+LL |     if let .0... = 0 {}
+   |            ^^ help: must have an integer part: `0.0`
+
+error: `X...` range patterns are not supported
+  --> $DIR/recover-range-pats.rs:85:12
+   |
+LL |     if let .0... = 0 {}
+   |            ^^^^^ help: try using the maximum value for the type: `0.0...MAX`
+
+error: `..X` range patterns are not supported
+  --> $DIR/recover-range-pats.rs:92:12
+   |
+LL |     if let ..0 = 0 {}
+   |            ^^^ help: try using the minimum value for the type: `MIN..0`
+
+error: `..X` range patterns are not supported
+  --> $DIR/recover-range-pats.rs:93:12
+   |
+LL |     if let ..Y = 0 {}
+   |            ^^^ help: try using the minimum value for the type: `MIN..Y`
+
+error: `..X` range patterns are not supported
+  --> $DIR/recover-range-pats.rs:94:12
+   |
+LL |     if let ..true = 0 {}
+   |            ^^^^^^ help: try using the minimum value for the type: `MIN..true`
+
+error: float literals must have an integer part
+  --> $DIR/recover-range-pats.rs:96:15
+   |
+LL |     if let .. .0 = 0 {}
+   |               ^^ help: must have an integer part: `0.0`
+
+error: `..X` range patterns are not supported
+  --> $DIR/recover-range-pats.rs:96:12
+   |
+LL |     if let .. .0 = 0 {}
+   |            ^^^^^ help: try using the minimum value for the type: `MIN..0.0`
+
+error: `..=X` range patterns are not supported
+  --> $DIR/recover-range-pats.rs:102:12
+   |
+LL |     if let ..=3 = 0 {}
+   |            ^^^^ help: try using the minimum value for the type: `MIN..=3`
+
+error: `..=X` range patterns are not supported
+  --> $DIR/recover-range-pats.rs:103:12
+   |
+LL |     if let ..=Y = 0 {}
+   |            ^^^^ help: try using the minimum value for the type: `MIN..=Y`
+
+error: `..=X` range patterns are not supported
+  --> $DIR/recover-range-pats.rs:104:12
+   |
+LL |     if let ..=true = 0 {}
+   |            ^^^^^^^ help: try using the minimum value for the type: `MIN..=true`
+
+error: float literals must have an integer part
+  --> $DIR/recover-range-pats.rs:106:15
+   |
+LL |     if let ..=.0 = 0 {}
+   |               ^^ help: must have an integer part: `0.0`
+
+error: `..=X` range patterns are not supported
+  --> $DIR/recover-range-pats.rs:106:12
+   |
+LL |     if let ..=.0 = 0 {}
+   |            ^^^^^ help: try using the minimum value for the type: `MIN..=0.0`
+
+error: `...X` range patterns are not supported
+  --> $DIR/recover-range-pats.rs:112:12
+   |
+LL |     if let ...3 = 0 {}
+   |            ^^^^ help: try using the minimum value for the type: `MIN...3`
+
+error: `...X` range patterns are not supported
+  --> $DIR/recover-range-pats.rs:114:12
+   |
+LL |     if let ...Y = 0 {}
+   |            ^^^^ help: try using the minimum value for the type: `MIN...Y`
+
+error: `...X` range patterns are not supported
+  --> $DIR/recover-range-pats.rs:116:12
+   |
+LL |     if let ...true = 0 {}
+   |            ^^^^^^^ help: try using the minimum value for the type: `MIN...true`
+
+error: float literals must have an integer part
+  --> $DIR/recover-range-pats.rs:119:15
+   |
+LL |     if let ....3 = 0 {}
+   |               ^^ help: must have an integer part: `0.3`
+
+error: `...X` range patterns are not supported
+  --> $DIR/recover-range-pats.rs:119:12
+   |
+LL |     if let ....3 = 0 {}
+   |            ^^^^^ help: try using the minimum value for the type: `MIN...0.3`
+
+error: `...` range patterns are deprecated
+  --> $DIR/recover-range-pats.rs:41:13
+   |
+LL |     if let 0...3 = 0 {}
+   |             ^^^ help: use `..=` for an inclusive range
+   |
+note: lint level defined here
+  --> $DIR/recover-range-pats.rs:7:9
+   |
+LL | #![deny(ellipsis_inclusive_range_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `...` range patterns are deprecated
+  --> $DIR/recover-range-pats.rs:42:13
+   |
+LL |     if let 0...Y = 0 {}
+   |             ^^^ help: use `..=` for an inclusive range
+
+error: `...` range patterns are deprecated
+  --> $DIR/recover-range-pats.rs:43:13
+   |
+LL |     if let X...3 = 0 {}
+   |             ^^^ help: use `..=` for an inclusive range
+
+error: `...` range patterns are deprecated
+  --> $DIR/recover-range-pats.rs:44:13
+   |
+LL |     if let X...Y = 0 {}
+   |             ^^^ help: use `..=` for an inclusive range
+
+error: `...` range patterns are deprecated
+  --> $DIR/recover-range-pats.rs:45:16
+   |
+LL |     if let true...Y = 0 {}
+   |                ^^^ help: use `..=` for an inclusive range
+
+error: `...` range patterns are deprecated
+  --> $DIR/recover-range-pats.rs:47:13
+   |
+LL |     if let X...true = 0 {}
+   |             ^^^ help: use `..=` for an inclusive range
+
+error: `...` range patterns are deprecated
+  --> $DIR/recover-range-pats.rs:49:14
+   |
+LL |     if let .0...Y = 0 {}
+   |              ^^^ help: use `..=` for an inclusive range
+
+error: `...` range patterns are deprecated
+  --> $DIR/recover-range-pats.rs:52:13
+   |
+LL |     if let X... .0 = 0 {}
+   |             ^^^ help: use `..=` for an inclusive range
+
+error: `...` range patterns are deprecated
+  --> $DIR/recover-range-pats.rs:78:13
+   |
+LL |     if let 0... = 0 {}
+   |             ^^^ help: use `..=` for an inclusive range
+
+error: `...` range patterns are deprecated
+  --> $DIR/recover-range-pats.rs:80:13
+   |
+LL |     if let X... = 0 {}
+   |             ^^^ help: use `..=` for an inclusive range
+
+error: `...` range patterns are deprecated
+  --> $DIR/recover-range-pats.rs:82:16
+   |
+LL |     if let true... = 0 {}
+   |                ^^^ help: use `..=` for an inclusive range
+
+error: `...` range patterns are deprecated
+  --> $DIR/recover-range-pats.rs:85:14
+   |
+LL |     if let .0... = 0 {}
+   |              ^^^ help: use `..=` for an inclusive range
+
+error: `...` range patterns are deprecated
+  --> $DIR/recover-range-pats.rs:112:12
+   |
+LL |     if let ...3 = 0 {}
+   |            ^^^ help: use `..=` for an inclusive range
+
+error: `...` range patterns are deprecated
+  --> $DIR/recover-range-pats.rs:114:12
+   |
+LL |     if let ...Y = 0 {}
+   |            ^^^ help: use `..=` for an inclusive range
+
+error: `...` range patterns are deprecated
+  --> $DIR/recover-range-pats.rs:116:12
+   |
+LL |     if let ...true = 0 {}
+   |            ^^^ help: use `..=` for an inclusive range
+
+error: `...` range patterns are deprecated
+  --> $DIR/recover-range-pats.rs:119:12
+   |
+LL |     if let ....3 = 0 {}
+   |            ^^^ help: use `..=` for an inclusive range
+
+error[E0029]: only char and numeric types are allowed in range patterns
+  --> $DIR/recover-range-pats.rs:19:12
+   |
+LL |     if let true..Y = 0 {}
+   |            ^^^^ ranges require char or numeric types
+   |
+   = note: start type: bool
+   = note: end type: u8
+
+error[E0029]: only char and numeric types are allowed in range patterns
+  --> $DIR/recover-range-pats.rs:20:15
+   |
+LL |     if let X..true = 0 {}
+   |               ^^^^ ranges require char or numeric types
+   |
+   = note: start type: u8
+   = note: end type: bool
+
+error[E0308]: mismatched types
+  --> $DIR/recover-range-pats.rs:21:12
+   |
+LL |     if let .0..Y = 0 {}
+   |            ^^^^^ expected integer, found floating-point number
+   |
+   = note: expected type `{integer}`
+              found type `{float}`
+
+error[E0308]: mismatched types
+  --> $DIR/recover-range-pats.rs:23:12
+   |
+LL |     if let X.. .0 = 0 {}
+   |            ^^^^^^ expected integer, found floating-point number
+   |
+   = note: expected type `u8`
+              found type `{float}`
+
+error[E0029]: only char and numeric types are allowed in range patterns
+  --> $DIR/recover-range-pats.rs:32:12
+   |
+LL |     if let true..=Y = 0 {}
+   |            ^^^^ ranges require char or numeric types
+   |
+   = note: start type: bool
+   = note: end type: u8
+
+error[E0029]: only char and numeric types are allowed in range patterns
+  --> $DIR/recover-range-pats.rs:33:16
+   |
+LL |     if let X..=true = 0 {}
+   |                ^^^^ ranges require char or numeric types
+   |
+   = note: start type: u8
+   = note: end type: bool
+
+error[E0308]: mismatched types
+  --> $DIR/recover-range-pats.rs:34:12
+   |
+LL |     if let .0..=Y = 0 {}
+   |            ^^^^^^ expected integer, found floating-point number
+   |
+   = note: expected type `{integer}`
+              found type `{float}`
+
+error[E0308]: mismatched types
+  --> $DIR/recover-range-pats.rs:36:12
+   |
+LL |     if let X..=.0 = 0 {}
+   |            ^^^^^^ expected integer, found floating-point number
+   |
+   = note: expected type `u8`
+              found type `{float}`
+
+error[E0029]: only char and numeric types are allowed in range patterns
+  --> $DIR/recover-range-pats.rs:45:12
+   |
+LL |     if let true...Y = 0 {}
+   |            ^^^^ ranges require char or numeric types
+   |
+   = note: start type: bool
+   = note: end type: u8
+
+error[E0029]: only char and numeric types are allowed in range patterns
+  --> $DIR/recover-range-pats.rs:47:16
+   |
+LL |     if let X...true = 0 {}
+   |                ^^^^ ranges require char or numeric types
+   |
+   = note: start type: u8
+   = note: end type: bool
+
+error[E0308]: mismatched types
+  --> $DIR/recover-range-pats.rs:49:12
+   |
+LL |     if let .0...Y = 0 {}
+   |            ^^^^^^ expected integer, found floating-point number
+   |
+   = note: expected type `{integer}`
+              found type `{float}`
+
+error[E0308]: mismatched types
+  --> $DIR/recover-range-pats.rs:52:12
+   |
+LL |     if let X... .0 = 0 {}
+   |            ^^^^^^^ expected integer, found floating-point number
+   |
+   = note: expected type `u8`
+              found type `{float}`
+
+error[E0029]: only char and numeric types are allowed in range patterns
+  --> $DIR/recover-range-pats.rs:60:12
+   |
+LL |     if let true.. = 0 {}
+   |            ^^^^ ranges require char or numeric types
+   |
+   = note: start type: bool
+   = note: end type: [type error]
+
+error[E0308]: mismatched types
+  --> $DIR/recover-range-pats.rs:62:12
+   |
+LL |     if let .0.. = 0 {}
+   |            ^^^^ expected integer, found floating-point number
+   |
+   = note: expected type `{integer}`
+              found type `{float}`
+
+error[E0029]: only char and numeric types are allowed in range patterns
+  --> $DIR/recover-range-pats.rs:70:12
+   |
+LL |     if let true..= = 0 {}
+   |            ^^^^ ranges require char or numeric types
+   |
+   = note: start type: bool
+   = note: end type: [type error]
+
+error[E0308]: mismatched types
+  --> $DIR/recover-range-pats.rs:72:12
+   |
+LL |     if let .0..= = 0 {}
+   |            ^^^^^ expected integer, found floating-point number
+   |
+   = note: expected type `{integer}`
+              found type `{float}`
+
+error[E0029]: only char and numeric types are allowed in range patterns
+  --> $DIR/recover-range-pats.rs:82:12
+   |
+LL |     if let true... = 0 {}
+   |            ^^^^ ranges require char or numeric types
+   |
+   = note: start type: bool
+   = note: end type: [type error]
+
+error[E0308]: mismatched types
+  --> $DIR/recover-range-pats.rs:85:12
+   |
+LL |     if let .0... = 0 {}
+   |            ^^^^^ expected integer, found floating-point number
+   |
+   = note: expected type `{integer}`
+              found type `{float}`
+
+error[E0029]: only char and numeric types are allowed in range patterns
+  --> $DIR/recover-range-pats.rs:94:14
+   |
+LL |     if let ..true = 0 {}
+   |              ^^^^ ranges require char or numeric types
+   |
+   = note: start type: [type error]
+   = note: end type: bool
+
+error[E0308]: mismatched types
+  --> $DIR/recover-range-pats.rs:96:12
+   |
+LL |     if let .. .0 = 0 {}
+   |            ^^^^^ expected integer, found floating-point number
+   |
+   = note: expected type `{integer}`
+              found type `{float}`
+
+error[E0029]: only char and numeric types are allowed in range patterns
+  --> $DIR/recover-range-pats.rs:104:15
+   |
+LL |     if let ..=true = 0 {}
+   |               ^^^^ ranges require char or numeric types
+   |
+   = note: start type: [type error]
+   = note: end type: bool
+
+error[E0308]: mismatched types
+  --> $DIR/recover-range-pats.rs:106:12
+   |
+LL |     if let ..=.0 = 0 {}
+   |            ^^^^^ expected integer, found floating-point number
+   |
+   = note: expected type `{integer}`
+              found type `{float}`
+
+error[E0029]: only char and numeric types are allowed in range patterns
+  --> $DIR/recover-range-pats.rs:116:15
+   |
+LL |     if let ...true = 0 {}
+   |               ^^^^ ranges require char or numeric types
+   |
+   = note: start type: [type error]
+   = note: end type: bool
+
+error[E0308]: mismatched types
+  --> $DIR/recover-range-pats.rs:119:12
+   |
+LL |     if let ....3 = 0 {}
+   |            ^^^^^ expected integer, found floating-point number
+   |
+   = note: expected type `{integer}`
+              found type `{float}`
+
+error: aborting due to 76 previous errors
+
+Some errors have detailed explanations: E0029, E0308.
+For more information about an error, try `rustc --explain E0029`.
index 488e8db6b878979e11f42b7c1866f4ae838875d8..7fded752d675e2c005ca6719fa588b94b9d3c84b 100644 (file)
@@ -1,12 +1,12 @@
+// NOTE: This doesn't recover anymore.
+
 fn main() {
     let x = (1, 2, 3, 4);
     match x {
         (1, .., 4) => {}
         (1, .=., 4) => { let _: usize = ""; }
         //~^ ERROR expected pattern, found `.`
-        //~| ERROR mismatched types
         (.=., 4) => {}
-        //~^ ERROR expected pattern, found `.`
         (1, 2, 3, 4) => {}
     }
 }
index 5919aa72355acd43ddea3cdcc5e90f10c1191d6c..93a6a66a63082ca3d2b99950e00447fd3c5f1ef0 100644 (file)
@@ -1,24 +1,8 @@
 error: expected pattern, found `.`
-  --> $DIR/recover-tuple-pat.rs:5:13
+  --> $DIR/recover-tuple-pat.rs:7:13
    |
 LL |         (1, .=., 4) => { let _: usize = ""; }
    |             ^ expected pattern
 
-error: expected pattern, found `.`
-  --> $DIR/recover-tuple-pat.rs:8:10
-   |
-LL |         (.=., 4) => {}
-   |          ^ expected pattern
-
-error[E0308]: mismatched types
-  --> $DIR/recover-tuple-pat.rs:5:41
-   |
-LL |         (1, .=., 4) => { let _: usize = ""; }
-   |                                         ^^ expected usize, found reference
-   |
-   = note: expected type `usize`
-              found type `&'static str`
-
-error: aborting due to 3 previous errors
+error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0308`.
index e4bb0d32942a495c0d2b3d7723530609c488dc41..3cb6ab52e0a2c586eb9acc9b2d2005731cc5114c 100644 (file)
@@ -1,4 +1,3 @@
-#[allow(unused_extern_crates)]
 extern crate std;
 //~^ ERROR the name `std` is defined multiple times
 
index 9e43cd4839f9be44cda0440e46556d604042943a..ea6cb9eb00d8f98e745a5107d76f427ede734716 100644 (file)
@@ -1,8 +1,4 @@
 error[E0259]: the name `std` is defined multiple times
-  --> $DIR/resolve-conflict-extern-crate-vs-extern-crate.rs:2:1
-   |
-LL | extern crate std;
-   | ^^^^^^^^^^^^^^^^^ `std` reimported here
    |
    = note: `std` must be defined only once in the type namespace of this module
 help: you can use `as` to change the binding name of the import
index a9423830d9040509d76ad774f9fb4948ad2a59dc..a14ec5b7290b4762c9296df5bd348a977adae35b 100644 (file)
@@ -1,5 +1,3 @@
-#![allow(unused_extern_crates)]
-
 mod a {
     extern crate alloc;
     use alloc::HashMap;
index 14cdae97d14f3484077694b1c25e53c5a0785eb9..bc862553b5bce15188408298c6f0086f49623a57 100644 (file)
@@ -1,17 +1,17 @@
 error[E0432]: unresolved import `alloc`
-  --> $DIR/resolve_self_super_hint.rs:5:9
+  --> $DIR/resolve_self_super_hint.rs:3:9
    |
 LL |     use alloc::HashMap;
    |         ^^^^^ help: a similar path exists: `self::alloc`
 
 error[E0432]: unresolved import `alloc`
-  --> $DIR/resolve_self_super_hint.rs:10:13
+  --> $DIR/resolve_self_super_hint.rs:8:13
    |
 LL |         use alloc::HashMap;
    |             ^^^^^ help: a similar path exists: `super::alloc`
 
 error[E0432]: unresolved import `alloc`
-  --> $DIR/resolve_self_super_hint.rs:15:17
+  --> $DIR/resolve_self_super_hint.rs:13:17
    |
 LL |             use alloc::HashMap;
    |                 ^^^^^
@@ -20,7 +20,7 @@ LL |             use alloc::HashMap;
    |                 help: a similar path exists: `a::alloc`
 
 error[E0432]: unresolved import `alloc`
-  --> $DIR/resolve_self_super_hint.rs:20:21
+  --> $DIR/resolve_self_super_hint.rs:18:21
    |
 LL |                 use alloc::HashMap;
    |                     ^^^^^
index fd85bf7f16007c9430b52c5b8bcf210756edf41a..1484b8c4a1f13e6f519ce65dee4914826b5925bf 100644 (file)
@@ -4,6 +4,6 @@ pub fn main() {
     let sl: &[u8] = b"foo";
 
     match sl { //~ ERROR non-exhaustive patterns
-        [first, remainder..] => {},
+        [first, remainder @ ..] => {},
     };
 }
index e796e37bbaa4524460f76e36cba87244594ab500..5eeda66173ded56be7b3355b58c54938f12b4ae1 100644 (file)
+// check-pass
 // compile-flags: --cfg something
-// build-pass (FIXME(62277): could be check-pass?)
 
+#![deny(unused_mut)]
 #![feature(param_attrs)]
 
 extern "C" {
     fn ffi(
-        #[allow(C)] a: i32,
+        #[allow(unused_mut)] a: i32,
         #[cfg(something)] b: i32,
         #[cfg_attr(something, cfg(nothing))] c: i32,
-        #[deny(C)] d: i32,
-        #[forbid(C)] #[warn(C)] ...
+        #[deny(unused_mut)] d: i32,
+        #[forbid(unused_mut)] #[warn(unused_mut)] ...
     );
 }
 
 type FnType = fn(
-    #[allow(C)] a: i32,
+    #[allow(unused_mut)] a: i32,
     #[cfg(something)] b: i32,
     #[cfg_attr(something, cfg(nothing))] c: i32,
-    #[deny(C)] d: i32,
-    #[forbid(C)] #[warn(C)] e: i32
+    #[deny(unused_mut)] d: i32,
+    #[forbid(unused_mut)] #[warn(unused_mut)] e: i32
 );
 
 pub fn foo(
-    #[allow(C)] a: i32,
+    #[allow(unused_mut)] a: i32,
     #[cfg(something)] b: i32,
     #[cfg_attr(something, cfg(nothing))] c: i32,
-    #[deny(C)] d: i32,
-    #[forbid(C)] #[warn(C)] e: i32
+    #[deny(unused_mut)] d: i32,
+    #[forbid(unused_mut)] #[warn(unused_mut)] _e: i32
 ) {}
 
-// self, &self and &mut self
+// self
 
 struct SelfStruct {}
 impl SelfStruct {
     fn foo(
-        #[allow(C)] self,
+        #[allow(unused_mut)] self,
         #[cfg(something)] a: i32,
         #[cfg_attr(something, cfg(nothing))]
-        #[deny(C)] b: i32,
+        #[deny(unused_mut)] b: i32,
     ) {}
 }
 
 struct RefStruct {}
 impl RefStruct {
     fn foo(
-        #[allow(C)] &self,
+        #[allow(unused_mut)] &self,
         #[cfg(something)] a: i32,
         #[cfg_attr(something, cfg(nothing))]
-        #[deny(C)] b: i32,
+        #[deny(unused_mut)] b: i32,
     ) {}
 }
 trait RefTrait {
     fn foo(
-        #[forbid(C)] &self,
-        #[warn(C)] a: i32
+        #[forbid(unused_mut)] &self,
+        #[warn(unused_mut)] a: i32
     ) {}
 }
 impl RefTrait for RefStruct {
     fn foo(
-        #[forbid(C)] &self,
-        #[warn(C)] a: i32
-    ) {}
-}
-
-struct MutStruct {}
-impl MutStruct {
-    fn foo(
-        #[allow(C)] &mut self,
-        #[cfg(something)] a: i32,
-        #[cfg_attr(something, cfg(nothing))]
-        #[deny(C)] b: i32,
-    ) {}
-}
-trait MutTrait {
-    fn foo(
-        #[forbid(C)] &mut self,
-        #[warn(C)] a: i32
-    ) {}
-}
-impl MutTrait for MutStruct {
-    fn foo(
-        #[forbid(C)] &mut self,
-        #[warn(C)] a: i32
-    ) {}
-}
-
-// self: Self, self: &Self and self: &mut Self
-
-struct NamedSelfSelfStruct {}
-impl NamedSelfSelfStruct {
-    fn foo(
-        #[allow(C)] self: Self,
-        #[cfg(something)] a: i32,
-        #[cfg_attr(something, cfg(nothing))]
-        #[deny(C)] b: i32,
-    ) {}
-}
-
-struct NamedSelfRefStruct {}
-impl NamedSelfRefStruct {
-    fn foo(
-        #[allow(C)] self: &Self,
-        #[cfg(something)] a: i32,
-        #[cfg_attr(something, cfg(nothing))]
-        #[deny(C)] b: i32,
-    ) {}
-}
-trait NamedSelfRefTrait {
-    fn foo(
-        #[forbid(C)] self: &Self,
-        #[warn(C)] a: i32
-    ) {}
-}
-impl NamedSelfRefTrait for NamedSelfRefStruct {
-    fn foo(
-        #[forbid(C)] self: &Self,
-        #[warn(C)] a: i32
-    ) {}
-}
-
-struct NamedSelfMutStruct {}
-impl NamedSelfMutStruct {
-    fn foo(
-        #[allow(C)] self: &mut Self,
-        #[cfg(something)] a: i32,
-        #[cfg_attr(something, cfg(nothing))]
-        #[deny(C)] b: i32,
-    ) {}
-}
-trait NamedSelfMutTrait {
-    fn foo(
-        #[forbid(C)] self: &mut Self,
-        #[warn(C)] a: i32
-    ) {}
-}
-impl NamedSelfMutTrait for NamedSelfMutStruct {
-    fn foo(
-        #[forbid(C)] self: &mut Self,
-        #[warn(C)] a: i32
-    ) {}
-}
-
-// &'a self and &'a mut self
-
-struct NamedLifetimeRefStruct {}
-impl NamedLifetimeRefStruct {
-    fn foo<'a>(
-        #[allow(C)] self: &'a Self,
-        #[cfg(something)] a: i32,
-        #[cfg_attr(something, cfg(nothing))]
-        #[deny(C)] b: i32,
-    ) {}
-}
-trait NamedLifetimeRefTrait {
-    fn foo<'a>(
-        #[forbid(C)] &'a self,
-        #[warn(C)] a: i32
-    ) {}
-}
-impl NamedLifetimeRefTrait for NamedLifetimeRefStruct {
-    fn foo<'a>(
-        #[forbid(C)] &'a self,
-        #[warn(C)] a: i32
-    ) {}
-}
-
-struct NamedLifetimeMutStruct {}
-impl NamedLifetimeMutStruct {
-    fn foo<'a>(
-        #[allow(C)] self: &'a mut Self,
-        #[cfg(something)] a: i32,
-        #[cfg_attr(something, cfg(nothing))]
-        #[deny(C)] b: i32,
-    ) {}
-}
-trait NamedLifetimeMutTrait {
-    fn foo<'a>(
-        #[forbid(C)] &'a mut self,
-        #[warn(C)] a: i32
-    ) {}
-}
-impl NamedLifetimeMutTrait for NamedLifetimeMutStruct {
-    fn foo<'a>(
-        #[forbid(C)] &'a mut self,
-        #[warn(C)] a: i32
+        #[forbid(unused_mut)] &self,
+        #[warn(unused_mut)] a: i32
     ) {}
 }
 
@@ -192,22 +69,22 @@ fn foo<'a>(
 struct BoxSelfStruct {}
 impl BoxSelfStruct {
     fn foo(
-        #[allow(C)] self: Box<Self>,
+        #[allow(unused_mut)] self: Box<Self>,
         #[cfg(something)] a: i32,
         #[cfg_attr(something, cfg(nothing))]
-        #[deny(C)] b: i32,
+        #[deny(unused_mut)] b: i32,
     ) {}
 }
 trait BoxSelfTrait {
     fn foo(
-        #[forbid(C)] self: Box<Self>,
-        #[warn(C)] a: i32
+        #[forbid(unused_mut)] self: Box<Self>,
+        #[warn(unused_mut)] a: i32
     ) {}
 }
 impl BoxSelfTrait for BoxSelfStruct {
     fn foo(
-        #[forbid(C)] self: Box<Self>,
-        #[warn(C)] a: i32
+        #[forbid(unused_mut)] self: Box<Self>,
+        #[warn(unused_mut)] a: i32
     ) {}
 }
 
@@ -216,10 +93,10 @@ fn main() {
     let _: fn(_, _, _, _) = foo;
     let _: FnType = |_, _, _, _| {};
     let c = |
-        #[allow(C)] a: u32,
+        #[allow(unused_mut)] a: u32,
         #[cfg(something)] b: i32,
         #[cfg_attr(something, cfg(nothing))]
-        #[deny(C)] c: i32,
+        #[deny(unused_mut)] c: i32,
     | {};
     let _ = c(1, 2);
 }
index 977b5d9ce349580a35167269833b1c787b65bac9..069332ffa255f836216a873ab883659a0fbfb66f 100644 (file)
@@ -1,6 +1,7 @@
 // compile-flags: --cfg something
+// edition:2018
 
-#![feature(param_attrs)]
+#![feature(async_await, async_closure, param_attrs)]
 #![deny(unused_variables)]
 
 extern "C" {
@@ -19,24 +20,35 @@ fn ffi(
     #[cfg_attr(something, cfg(nothing))] d: i32,
 );
 
+async fn foo_async(
+    #[cfg(something)] a: i32,
+    //~^ ERROR unused variable: `a`
+    #[cfg(nothing)] b: i32,
+) {}
 fn foo(
     #[cfg(nothing)] a: i32,
     #[cfg(something)] b: i32,
-    //~^ ERROR unused variable: `b` [unused_variables]
+    //~^ ERROR unused variable: `b`
     #[cfg_attr(nothing, cfg(nothing))] c: i32,
-    //~^ ERROR unused variable: `c` [unused_variables]
+    //~^ ERROR unused variable: `c`
     #[cfg_attr(something, cfg(nothing))] d: i32,
 ) {}
 
 struct RefStruct {}
 impl RefStruct {
+    async fn bar_async(
+        &self,
+        #[cfg(something)] a: i32,
+        //~^ ERROR unused variable: `a`
+        #[cfg(nothing)] b: i32,
+    ) {}
     fn bar(
         &self,
         #[cfg(nothing)] a: i32,
         #[cfg(something)] b: i32,
-        //~^ ERROR unused variable: `b` [unused_variables]
+        //~^ ERROR unused variable: `b`
         #[cfg_attr(nothing, cfg(nothing))] c: i32,
-        //~^ ERROR unused variable: `c` [unused_variables]
+        //~^ ERROR unused variable: `c`
         #[cfg_attr(something, cfg(nothing))] d: i32,
     ) {}
 }
@@ -45,9 +57,9 @@ fn bar(
         &self,
         #[cfg(nothing)] a: i32,
         #[cfg(something)] b: i32,
-        //~^ ERROR unused variable: `b` [unused_variables]
+        //~^ ERROR unused variable: `b`
         #[cfg_attr(nothing, cfg(nothing))] c: i32,
-        //~^ ERROR unused variable: `c` [unused_variables]
+        //~^ ERROR unused variable: `c`
         #[cfg_attr(something, cfg(nothing))] d: i32,
     ) {}
 }
@@ -56,9 +68,9 @@ fn bar(
         &self,
         #[cfg(nothing)] a: i32,
         #[cfg(something)] b: i32,
-        //~^ ERROR unused variable: `b` [unused_variables]
+        //~^ ERROR unused variable: `b`
         #[cfg_attr(nothing, cfg(nothing))] c: i32,
-        //~^ ERROR unused variable: `c` [unused_variables]
+        //~^ ERROR unused variable: `c`
         #[cfg_attr(something, cfg(nothing))] d: i32,
     ) {}
 }
@@ -67,13 +79,19 @@ fn main() {
     let _: unsafe extern "C" fn(_, ...) = ffi;
     let _: fn(_, _) = foo;
     let _: FnType = |_, _| {};
+    let a = async move |
+        #[cfg(something)] a: i32,
+        //~^ ERROR unused variable: `a`
+        #[cfg(nothing)] b: i32,
+    | {};
     let c = |
         #[cfg(nothing)] a: i32,
         #[cfg(something)] b: i32,
-        //~^ ERROR unused variable: `b` [unused_variables]
+        //~^ ERROR unused variable: `b`
         #[cfg_attr(nothing, cfg(nothing))] c: i32,
-        //~^ ERROR unused variable: `c` [unused_variables]
+        //~^ ERROR unused variable: `c`
         #[cfg_attr(something, cfg(nothing))] d: i32,
     | {};
+    let _ = a(1);
     let _ = c(1, 2);
 }
index c97190324e5a27081fae882466a2150cb95f0b4c..3232e2a0411a270335498e05ce185bd753808c91 100644 (file)
@@ -1,68 +1,86 @@
-error: unused variable: `b`
+error: unused variable: `a`
   --> $DIR/param-attrs-cfg.rs:24:23
    |
-LL |     #[cfg(something)] b: i32,
-   |                       ^ help: consider prefixing with an underscore: `_b`
+LL |     #[cfg(something)] a: i32,
+   |                       ^ help: consider prefixing with an underscore: `_a`
    |
 note: lint level defined here
-  --> $DIR/param-attrs-cfg.rs:4:9
+  --> $DIR/param-attrs-cfg.rs:5:9
    |
 LL | #![deny(unused_variables)]
    |         ^^^^^^^^^^^^^^^^
 
+error: unused variable: `b`
+  --> $DIR/param-attrs-cfg.rs:30:23
+   |
+LL |     #[cfg(something)] b: i32,
+   |                       ^ help: consider prefixing with an underscore: `_b`
+
 error: unused variable: `c`
-  --> $DIR/param-attrs-cfg.rs:26:40
+  --> $DIR/param-attrs-cfg.rs:32:40
    |
 LL |     #[cfg_attr(nothing, cfg(nothing))] c: i32,
    |                                        ^ help: consider prefixing with an underscore: `_c`
 
+error: unused variable: `a`
+  --> $DIR/param-attrs-cfg.rs:83:27
+   |
+LL |         #[cfg(something)] a: i32,
+   |                           ^ help: consider prefixing with an underscore: `_a`
+
 error: unused variable: `b`
-  --> $DIR/param-attrs-cfg.rs:72:27
+  --> $DIR/param-attrs-cfg.rs:89:27
    |
 LL |         #[cfg(something)] b: i32,
    |                           ^ help: consider prefixing with an underscore: `_b`
 
 error: unused variable: `c`
-  --> $DIR/param-attrs-cfg.rs:74:44
+  --> $DIR/param-attrs-cfg.rs:91:44
    |
 LL |         #[cfg_attr(nothing, cfg(nothing))] c: i32,
    |                                            ^ help: consider prefixing with an underscore: `_c`
 
 error: unused variable: `b`
-  --> $DIR/param-attrs-cfg.rs:47:27
+  --> $DIR/param-attrs-cfg.rs:59:27
    |
 LL |         #[cfg(something)] b: i32,
    |                           ^ help: consider prefixing with an underscore: `_b`
 
 error: unused variable: `c`
-  --> $DIR/param-attrs-cfg.rs:49:44
+  --> $DIR/param-attrs-cfg.rs:61:44
    |
 LL |         #[cfg_attr(nothing, cfg(nothing))] c: i32,
    |                                            ^ help: consider prefixing with an underscore: `_c`
 
+error: unused variable: `a`
+  --> $DIR/param-attrs-cfg.rs:41:27
+   |
+LL |         #[cfg(something)] a: i32,
+   |                           ^ help: consider prefixing with an underscore: `_a`
+
 error: unused variable: `b`
-  --> $DIR/param-attrs-cfg.rs:36:27
+  --> $DIR/param-attrs-cfg.rs:48:27
    |
 LL |         #[cfg(something)] b: i32,
    |                           ^ help: consider prefixing with an underscore: `_b`
 
 error: unused variable: `c`
-  --> $DIR/param-attrs-cfg.rs:38:44
+  --> $DIR/param-attrs-cfg.rs:50:44
    |
 LL |         #[cfg_attr(nothing, cfg(nothing))] c: i32,
    |                                            ^ help: consider prefixing with an underscore: `_c`
 
 error: unused variable: `b`
-  --> $DIR/param-attrs-cfg.rs:58:27
+  --> $DIR/param-attrs-cfg.rs:70:27
    |
 LL |         #[cfg(something)] b: i32,
    |                           ^ help: consider prefixing with an underscore: `_b`
 
 error: unused variable: `c`
-  --> $DIR/param-attrs-cfg.rs:60:44
+  --> $DIR/param-attrs-cfg.rs:72:44
    |
 LL |         #[cfg_attr(nothing, cfg(nothing))] c: i32,
    |                                            ^ help: consider prefixing with an underscore: `_c`
 
-error: aborting due to 10 previous errors
+error: aborting due to 13 previous errors
 
index c5a6514efb0f09528ef42d894022620412640d48..a7f4855915b24f76b70844026cb4580a75c2e13b 100644 (file)
@@ -1,12 +1,14 @@
 // gate-test-param_attrs
 
+#![deny(unused_variables)]
+
 fn foo(
     /// Foo
     //~^ ERROR documentation comments cannot be applied to function parameters
     //~| NOTE doc comments are not allowed here
     //~| ERROR attributes on function parameters are unstable
     //~| NOTE https://github.com/rust-lang/rust/issues/60406
-    #[allow(C)] a: u8
+    #[allow(unused_variables)] a: u8
     //~^ ERROR attributes on function parameters are unstable
     //~| NOTE https://github.com/rust-lang/rust/issues/60406
 ) {}
index 704c41f0fa64165ada8ef3c1656a204392d19561..0bb9d05dca0acad876418cebefe1ba2f40e2fd98 100644 (file)
@@ -1,11 +1,11 @@
 error: documentation comments cannot be applied to function parameters
-  --> $DIR/param-attrs-feature-gate.rs:4:5
+  --> $DIR/param-attrs-feature-gate.rs:6:5
    |
 LL |     /// Foo
    |     ^^^^^^^ doc comments are not allowed here
 
 error[E0658]: attributes on function parameters are unstable
-  --> $DIR/param-attrs-feature-gate.rs:4:5
+  --> $DIR/param-attrs-feature-gate.rs:6:5
    |
 LL |     /// Foo
    |     ^^^^^^^
@@ -14,10 +14,10 @@ LL |     /// Foo
    = help: add `#![feature(param_attrs)]` to the crate attributes to enable
 
 error[E0658]: attributes on function parameters are unstable
-  --> $DIR/param-attrs-feature-gate.rs:9:5
+  --> $DIR/param-attrs-feature-gate.rs:11:5
    |
-LL |     #[allow(C)] a: u8
-   |     ^^^^^^^^^^^
+LL |     #[allow(unused_variables)] a: u8
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: for more information, see https://github.com/rust-lang/rust/issues/60406
    = help: add `#![feature(param_attrs)]` to the crate attributes to enable
index 939a3c4a1fd7a83ddd2eff7d3e24aac7b90f7c52..38b0941aad0a6060a1aea3ee7eb6ab2b68695478 100644 (file)
@@ -5,7 +5,7 @@ fn slice_pat() {
     let sl: &[u8] = b"foo";
 
     match sl {
-        [first, remainder..] => {
+        [first, remainder @ ..] => {
             let _: &u8 = first;
             assert_eq!(first, &b'f');
             assert_eq!(remainder, b"oo");
diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime.rs b/src/test/ui/self/arbitrary_self_types_pin_lifetime.rs
new file mode 100644 (file)
index 0000000..3002013
--- /dev/null
@@ -0,0 +1,60 @@
+// check-pass
+
+use std::pin::Pin;
+use std::task::{Context, Poll};
+
+struct Foo;
+
+impl Foo {
+    fn pin_ref(self: Pin<&Self>) -> Pin<&Self> { self }
+
+    fn pin_mut(self: Pin<&mut Self>) -> Pin<&mut Self> { self }
+
+    fn pin_pin_pin_ref(self: Pin<Pin<Pin<&Self>>>) -> Pin<Pin<Pin<&Self>>> { self }
+
+    fn pin_ref_impl_trait(self: Pin<&Self>) -> impl Clone + '_ { self }
+
+    fn b(self: Pin<&Foo>, f: &Foo) -> Pin<&Foo> { self }
+}
+
+type Alias<T> = Pin<T>;
+impl Foo {
+    fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> Alias<&Self> { self }
+}
+
+struct Bar<T: Unpin, U: Unpin> {
+    field1: T,
+    field2: U,
+}
+
+impl<T: Unpin, U: Unpin> Bar<T, U> {
+    fn fields(self: Pin<&mut Self>) -> (Pin<&mut T>, Pin<&mut U>) {
+        let this = self.get_mut();
+        (Pin::new(&mut this.field1), Pin::new(&mut this.field2))
+    }
+}
+
+trait AsyncBufRead {
+    fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>)
+        -> Poll<std::io::Result<&[u8]>>;
+}
+
+struct Baz(Vec<u8>);
+
+impl AsyncBufRead for Baz {
+    fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>)
+        -> Poll<std::io::Result<&[u8]>>
+    {
+        Poll::Ready(Ok(&self.get_mut().0))
+    }
+}
+
+fn main() {
+    let mut foo = Foo;
+    { Pin::new(&foo).pin_ref() };
+    { Pin::new(&mut foo).pin_mut() };
+    { Pin::new(Pin::new(Pin::new(&foo))).pin_pin_pin_ref() };
+    { Pin::new(&foo).pin_ref_impl_trait() };
+    let mut bar = Bar { field1: 0u8, field2: 1u8 };
+    { Pin::new(&mut bar).fields() };
+}
diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.nll.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.nll.stderr
new file mode 100644 (file)
index 0000000..dcfc9ba
--- /dev/null
@@ -0,0 +1,14 @@
+error: lifetime may not live long enough
+  --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait.rs:8:31
+   |
+LL |     fn f(self: Pin<&Self>) -> impl Clone { self }
+   |                    -          ^^^^^^^^^^ opaque type requires that `'1` must outlive `'static`
+   |                    |
+   |                    let's call the lifetime of this reference `'1`
+help: to allow this `impl Trait` to capture borrowed data with lifetime `'1`, add `'_` as a constraint
+   |
+LL |     fn f(self: Pin<&Self>) -> impl Clone + '_ { self }
+   |                               ^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.rs b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.rs
new file mode 100644 (file)
index 0000000..ad89597
--- /dev/null
@@ -0,0 +1,13 @@
+// compile-fail
+
+use std::pin::Pin;
+
+struct Foo;
+
+impl Foo {
+    fn f(self: Pin<&Self>) -> impl Clone { self } //~ ERROR cannot infer an appropriate lifetime
+}
+
+fn main() {
+    { Pin::new(&Foo).f() };
+}
diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr
new file mode 100644 (file)
index 0000000..5118280
--- /dev/null
@@ -0,0 +1,20 @@
+error: cannot infer an appropriate lifetime
+  --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait.rs:8:44
+   |
+LL |     fn f(self: Pin<&Self>) -> impl Clone { self }
+   |                               ----------   ^^^^ ...but this borrow...
+   |                               |
+   |                               this return type evaluates to the `'static` lifetime...
+   |
+note: ...can't outlive the anonymous lifetime #1 defined on the method body at 8:5
+  --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait.rs:8:5
+   |
+LL |     fn f(self: Pin<&Self>) -> impl Clone { self }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: you can add a constraint to the return type to make it last less than `'static` and match the anonymous lifetime #1 defined on the method body at 8:5
+   |
+LL |     fn f(self: Pin<&Self>) -> impl Clone + '_ { self }
+   |                               ^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.nll.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.nll.stderr
new file mode 100644 (file)
index 0000000..8a0f1a8
--- /dev/null
@@ -0,0 +1,28 @@
+error: lifetime may not live long enough
+  --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:8:46
+   |
+LL |     fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f }
+   |                    -         -               ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |                    |         |
+   |                    |         let's call the lifetime of this reference `'1`
+   |                    let's call the lifetime of this reference `'2`
+
+error: lifetime may not live long enough
+  --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:10:69
+   |
+LL |     fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) }
+   |                    -          -                                     ^^^^^^^^^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |                    |          |
+   |                    |          let's call the lifetime of this reference `'1`
+   |                    let's call the lifetime of this reference `'2`
+
+error: lifetime may not live long enough
+  --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:15:58
+   |
+LL |     fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg }
+   |            --  ---- has type `std::pin::Pin<&'1 Foo>`    ^^^ function was supposed to return data with lifetime `'1` but it is returning data with lifetime `'a`
+   |            |
+   |            lifetime `'a` defined here
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.rs b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.rs
new file mode 100644 (file)
index 0000000..fc5f942
--- /dev/null
@@ -0,0 +1,18 @@
+// compile-fail
+
+use std::pin::Pin;
+
+struct Foo;
+
+impl Foo {
+    fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f } //~ ERROR E0623
+
+    fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) } //~ ERROR E0623
+}
+
+type Alias<T> = Pin<T>;
+impl Foo {
+    fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg } //~ ERROR E0623
+}
+
+fn main() {}
diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.stderr
new file mode 100644 (file)
index 0000000..3296e14
--- /dev/null
@@ -0,0 +1,26 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:8:46
+   |
+LL |     fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f }
+   |                              ----     ----   ^ ...but data from `f` is returned here
+   |                              |
+   |                              this parameter and the return type are declared with different lifetimes...
+
+error[E0623]: lifetime mismatch
+  --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:10:76
+   |
+LL |     fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) }
+   |                               ----              -----------------          ^ ...but data from `f` is returned here
+   |                               |
+   |                               this parameter and the return type are declared with different lifetimes...
+
+error[E0623]: lifetime mismatch
+  --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:15:58
+   |
+LL |     fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg }
+   |                                         ------     ---   ^^^ ...but data from `arg` is returned here
+   |                                         |
+   |                                         this parameter and the return type are declared with different lifetimes...
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/self/elision/README.md b/src/test/ui/self/elision/README.md
new file mode 100644 (file)
index 0000000..7ace2e0
--- /dev/null
@@ -0,0 +1,44 @@
+Test cases intended to document behavior and try to exhaustively
+explore the combinations.
+
+## Confidence
+
+These tests are not yet considered 100% normative, in that some
+aspects of the current behavior are not desirable. This is expressed
+in the "confidence" field in the following table. Values:
+
+| Confidence | Interpretation |
+| --- | --- |
+| 100% | this will remain recommended behavior |
+| 75% | unclear whether we will continue to accept this |
+| 50% | this will likely be deprecated but remain valid |
+| 25% | this could change in the future |
+| 0% | this is definitely bogus and will likely change in the future in *some* way |
+
+## Tests
+
+| Test file | `Self` type | Pattern | Current elision behavior | Confidence |
+| --- | --- | --- | --- | --- |
+| `self.rs` | `Struct` | `Self` | ignore `self` parameter | 100% |
+| `struct.rs` | `Struct` | `Struct` | ignore `self` parameter | 100% |
+| `alias.rs` | `Struct` | `Alias` | ignore `self` parameter | 100% |
+| `ref-self.rs` | `Struct` | `&Self` | take lifetime from `&Self` | 100% |
+| `ref-mut-self.rs` | `Struct` | `&mut Self` | take lifetime from `&mut Self` | 100% |
+| `ref-struct.rs` | `Struct` | `&Struct` | take lifetime from `&Self` | 50% |
+| `ref-mut-struct.rs` | `Struct` | `&mut Struct` | take lifetime from `&mut Self` | 50% |
+| `ref-alias.rs` | `Struct` | `&Alias` | ignore `Alias` | 0% |
+| `ref-mut-alias.rs` | `Struct` | `&mut Alias` | ignore `Alias` | 0% |
+| `lt-self.rs` | `Struct<'a>` | `Self` | ignore `Self` (and hence `'a`) | 25% |
+| `lt-struct.rs` | `Struct<'a>` | `Self` | ignore `Self` (and hence `'a`) | 0% |
+| `lt-alias.rs`   | `Alias<'a>` | `Self` | ignore `Self` (and hence `'a`) | 0% |
+| `lt-ref-self.rs` | `Struct<'a>` | `&Self` | take lifetime from `&Self` | 75% |
+
+In each case, we test the following patterns:
+
+- `self: XXX`
+- `self: Box<XXX>`
+- `self: Pin<XXX>`
+- `self: Box<Box<XXX>>`
+- `self: Box<Pin<XXX>>`
+
+In the non-reference cases, `Pin` causes errors so we substitute `Rc`.
diff --git a/src/test/ui/self/elision/alias.rs b/src/test/ui/self/elision/alias.rs
new file mode 100644 (file)
index 0000000..b5aacfa
--- /dev/null
@@ -0,0 +1,36 @@
+// check-pass
+
+#![feature(arbitrary_self_types)]
+#![allow(non_snake_case)]
+
+use std::rc::Rc;
+
+struct Struct { }
+
+type Alias = Struct;
+
+impl Struct {
+    // Test using an alias for `Struct`:
+
+    fn alias(self: Alias, f: &u32) -> &u32 {
+        f
+    }
+
+    fn box_Alias(self: Box<Alias>, f: &u32) -> &u32 {
+        f
+    }
+
+    fn rc_Alias(self: Rc<Alias>, f: &u32) -> &u32 {
+        f
+    }
+
+    fn box_box_Alias(self: Box<Box<Alias>>, f: &u32) -> &u32 {
+        f
+    }
+
+    fn box_rc_Alias(self: Box<Rc<Alias>>, f: &u32) -> &u32 {
+        f
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/self/elision/assoc.rs b/src/test/ui/self/elision/assoc.rs
new file mode 100644 (file)
index 0000000..163eb49
--- /dev/null
@@ -0,0 +1,40 @@
+// check-pass
+
+#![feature(arbitrary_self_types)]
+#![allow(non_snake_case)]
+
+use std::rc::Rc;
+
+trait Trait {
+    type AssocType;
+}
+
+struct Struct { }
+
+impl Trait for Struct {
+    type AssocType = Self;
+}
+
+impl Struct {
+    fn assoc(self: <Struct as Trait>::AssocType, f: &u32) -> &u32 {
+        f
+    }
+
+    fn box_AssocType(self: Box<<Struct as Trait>::AssocType>, f: &u32) -> &u32 {
+        f
+    }
+
+    fn rc_AssocType(self: Rc<<Struct as Trait>::AssocType>, f: &u32) -> &u32 {
+        f
+    }
+
+    fn box_box_AssocType(self: Box<Box<<Struct as Trait>::AssocType>>, f: &u32) -> &u32 {
+        f
+    }
+
+    fn box_rc_AssocType(self: Box<Rc<<Struct as Trait>::AssocType>>, f: &u32) -> &u32 {
+        f
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/self/elision/lt-alias.rs b/src/test/ui/self/elision/lt-alias.rs
new file mode 100644 (file)
index 0000000..df2300d
--- /dev/null
@@ -0,0 +1,38 @@
+// check-pass
+
+#![feature(arbitrary_self_types)]
+#![allow(non_snake_case)]
+
+use std::rc::Rc;
+
+struct Struct<'a> { x: &'a u32 }
+
+type Alias<'a> = Struct<'a>;
+
+impl<'a> Alias<'a> {
+    fn take_self(self, f: &u32) -> &u32 {
+        f
+    }
+
+    fn take_Alias(self: Alias<'a>, f: &u32) -> &u32 {
+        f
+    }
+
+    fn take_Box_Alias(self: Box<Alias<'a>>, f: &u32) -> &u32 {
+        f
+    }
+
+    fn take_Box_Box_Alias(self: Box<Box<Alias<'a>>>, f: &u32) -> &u32 {
+        f
+    }
+
+    fn take_Rc_Alias(self: Rc<Alias<'a>>, f: &u32) -> &u32 {
+        f
+    }
+
+    fn take_Box_Rc_Alias(self: Box<Rc<Alias<'a>>>, f: &u32) -> &u32 {
+        f
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/self/elision/lt-assoc.rs b/src/test/ui/self/elision/lt-assoc.rs
new file mode 100644 (file)
index 0000000..7057359
--- /dev/null
@@ -0,0 +1,44 @@
+// check-pass
+
+#![feature(arbitrary_self_types)]
+#![allow(non_snake_case)]
+
+use std::rc::Rc;
+
+trait Trait {
+    type AssocType;
+}
+
+struct Struct<'a> { x: &'a u32 }
+
+impl<'a> Trait for Struct<'a> {
+    type AssocType = Self;
+}
+
+impl<'a> Struct<'a> {
+    fn take_self(self, f: &u32) -> &u32 {
+        f
+    }
+
+    fn take_AssocType(self: <Struct<'a> as Trait>::AssocType, f: &u32) -> &u32 {
+        f
+    }
+
+    fn take_Box_AssocType(self: Box<<Struct<'a> as Trait>::AssocType>, f: &u32) -> &u32 {
+        f
+    }
+
+    fn take_Box_Box_AssocType(self: Box<Box<<Struct<'a> as Trait>::AssocType>>, f: &u32) -> &u32 {
+        f
+    }
+
+    fn take_Rc_AssocType(self: Rc<<Struct<'a> as Trait>::AssocType>, f: &u32) -> &u32 {
+        f
+    }
+
+    fn take_Box_Rc_AssocType(self: Box<Rc<<Struct<'a> as Trait>::AssocType>>, f: &u32) -> &u32 {
+        f
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/self/elision/lt-ref-self.nll.stderr b/src/test/ui/self/elision/lt-ref-self.nll.stderr
new file mode 100644 (file)
index 0000000..e97a01e
--- /dev/null
@@ -0,0 +1,62 @@
+error: lifetime may not live long enough
+  --> $DIR/lt-ref-self.rs:12:9
+   |
+LL |     fn ref_self(&self, f: &u32) -> &u32 {
+   |                 -         - let's call the lifetime of this reference `'1`
+   |                 |
+   |                 let's call the lifetime of this reference `'2`
+LL |         f
+   |         ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+
+error: lifetime may not live long enough
+  --> $DIR/lt-ref-self.rs:18:9
+   |
+LL |     fn ref_Self(self: &Self, f: &u32) -> &u32 {
+   |                       -         - let's call the lifetime of this reference `'1`
+   |                       |
+   |                       let's call the lifetime of this reference `'2`
+LL |         f
+   |         ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+
+error: lifetime may not live long enough
+  --> $DIR/lt-ref-self.rs:22:9
+   |
+LL |     fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
+   |                               -          - let's call the lifetime of this reference `'1`
+   |                               |
+   |                               let's call the lifetime of this reference `'2`
+LL |         f
+   |         ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+
+error: lifetime may not live long enough
+  --> $DIR/lt-ref-self.rs:26:9
+   |
+LL |     fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
+   |                               -          - let's call the lifetime of this reference `'1`
+   |                               |
+   |                               let's call the lifetime of this reference `'2`
+LL |         f
+   |         ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+
+error: lifetime may not live long enough
+  --> $DIR/lt-ref-self.rs:30:9
+   |
+LL |     fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
+   |                                       -           - let's call the lifetime of this reference `'1`
+   |                                       |
+   |                                       let's call the lifetime of this reference `'2`
+LL |         f
+   |         ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+
+error: lifetime may not live long enough
+  --> $DIR/lt-ref-self.rs:34:9
+   |
+LL |     fn box_pin_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
+   |                                   -           - let's call the lifetime of this reference `'1`
+   |                                   |
+   |                                   let's call the lifetime of this reference `'2`
+LL |         f
+   |         ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/self/elision/lt-ref-self.rs b/src/test/ui/self/elision/lt-ref-self.rs
new file mode 100644 (file)
index 0000000..8abf287
--- /dev/null
@@ -0,0 +1,38 @@
+#![feature(arbitrary_self_types)]
+#![allow(non_snake_case)]
+
+use std::pin::Pin;
+
+struct Struct<'a> { data: &'a u32 }
+
+impl<'a> Struct<'a> {
+    // Test using `&self` sugar:
+
+    fn ref_self(&self, f: &u32) -> &u32 {
+        f //~ ERROR lifetime mismatch
+    }
+
+    // Test using `&Self` explicitly:
+
+    fn ref_Self(self: &Self, f: &u32) -> &u32 {
+        f //~ ERROR lifetime mismatch
+    }
+
+    fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
+        f //~ ERROR lifetime mismatch
+    }
+
+    fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
+        f //~ ERROR lifetime mismatch
+    }
+
+    fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
+        f //~ ERROR lifetime mismatch
+    }
+
+    fn box_pin_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
+        f //~ ERROR lifetime mismatch
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/self/elision/lt-ref-self.stderr b/src/test/ui/self/elision/lt-ref-self.stderr
new file mode 100644 (file)
index 0000000..f73b3ed
--- /dev/null
@@ -0,0 +1,62 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/lt-ref-self.rs:12:9
+   |
+LL |     fn ref_self(&self, f: &u32) -> &u32 {
+   |                           ----     ----
+   |                           |
+   |                           this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/lt-ref-self.rs:18:9
+   |
+LL |     fn ref_Self(self: &Self, f: &u32) -> &u32 {
+   |                                 ----     ----
+   |                                 |
+   |                                 this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/lt-ref-self.rs:22:9
+   |
+LL |     fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
+   |                                          ----     ----
+   |                                          |
+   |                                          this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/lt-ref-self.rs:26:9
+   |
+LL |     fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
+   |                                          ----     ----
+   |                                          |
+   |                                          this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/lt-ref-self.rs:30:9
+   |
+LL |     fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
+   |                                                   ----     ----
+   |                                                   |
+   |                                                   this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/lt-ref-self.rs:34:9
+   |
+LL |     fn box_pin_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
+   |                                               ----     ----
+   |                                               |
+   |                                               this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/self/elision/lt-self.rs b/src/test/ui/self/elision/lt-self.rs
new file mode 100644 (file)
index 0000000..9b0ee5e
--- /dev/null
@@ -0,0 +1,49 @@
+// check-pass
+
+#![feature(arbitrary_self_types)]
+#![allow(non_snake_case)]
+
+use std::pin::Pin;
+use std::rc::Rc;
+
+struct Struct<'a> {
+    x: &'a u32
+}
+
+impl<'a> Struct<'a> {
+    fn take_self(self, f: &u32) -> &u32 {
+        f
+    }
+
+    fn take_Self(self: Self, f: &u32) -> &u32 {
+        f
+    }
+
+    fn take_Box_Self(self: Box<Self>, f: &u32) -> &u32 {
+        f
+    }
+
+    fn take_Box_Box_Self(self: Box<Box<Self>>, f: &u32) -> &u32 {
+        f
+    }
+
+    fn take_Rc_Self(self: Rc<Self>, f: &u32) -> &u32 {
+        f
+    }
+
+    fn take_Box_Rc_Self(self: Box<Rc<Self>>, f: &u32) -> &u32 {
+        f
+    }
+
+    // N/A
+    //fn take_Pin_Self(self: Pin<Self>, f: &u32) -> &u32 {
+    //    f
+    //}
+
+    // N/A
+    //fn take_Box_Pin_Self(self: Box<Pin<Self>>, f: &u32) -> &u32 {
+    //    f
+    //}
+}
+
+fn main() { }
diff --git a/src/test/ui/self/elision/lt-struct.rs b/src/test/ui/self/elision/lt-struct.rs
new file mode 100644 (file)
index 0000000..e41dfbb
--- /dev/null
@@ -0,0 +1,36 @@
+// check-pass
+
+#![feature(arbitrary_self_types)]
+#![allow(non_snake_case)]
+
+use std::rc::Rc;
+
+struct Struct<'a> { x: &'a u32 }
+
+impl<'a> Struct<'a> {
+    fn take_self(self, f: &u32) -> &u32 {
+        f
+    }
+
+    fn take_Struct(self: Struct<'a>, f: &u32) -> &u32 {
+        f
+    }
+
+    fn take_Box_Struct(self: Box<Struct<'a>>, f: &u32) -> &u32 {
+        f
+    }
+
+    fn take_Box_Box_Struct(self: Box<Box<Struct<'a>>>, f: &u32) -> &u32 {
+        f
+    }
+
+    fn take_Rc_Struct(self: Rc<Struct<'a>>, f: &u32) -> &u32 {
+        f
+    }
+
+    fn take_Box_Rc_Struct(self: Box<Rc<Struct<'a>>>, f: &u32) -> &u32 {
+        f
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/self/elision/multiple-ref-self.rs b/src/test/ui/self/elision/multiple-ref-self.rs
new file mode 100644 (file)
index 0000000..f39613d
--- /dev/null
@@ -0,0 +1,43 @@
+// check-pass
+
+#![feature(arbitrary_self_types)]
+#![allow(non_snake_case)]
+
+use std::marker::PhantomData;
+use std::ops::Deref;
+use std::pin::Pin;
+
+struct Struct { }
+
+struct Wrap<T, P>(T, PhantomData<P>);
+
+impl<T, P> Deref for Wrap<T, P> {
+    type Target = T;
+    fn deref(&self) -> &T { &self.0 }
+}
+
+impl Struct {
+    // Test using multiple `&Self`:
+
+    fn wrap_ref_Self_ref_Self(self: Wrap<&Self, &Self>, f: &u8) -> &u8 {
+        f
+    }
+
+    fn box_wrap_ref_Self_ref_Self(self: Box<Wrap<&Self, &Self>>, f: &u32) -> &u32 {
+        f
+    }
+
+    fn pin_wrap_ref_Self_ref_Self(self: Pin<Wrap<&Self, &Self>>, f: &u32) -> &u32 {
+        f
+    }
+
+    fn box_box_wrap_ref_Self_ref_Self(self: Box<Box<Wrap<&Self, &Self>>>, f: &u32) -> &u32 {
+        f
+    }
+
+    fn box_pin_wrap_ref_Self_ref_Self(self: Box<Pin<Wrap<&Self, &Self>>>, f: &u32) -> &u32 {
+        f
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/self/elision/ref-alias.rs b/src/test/ui/self/elision/ref-alias.rs
new file mode 100644 (file)
index 0000000..d83ac61
--- /dev/null
@@ -0,0 +1,39 @@
+// check-pass
+
+#![feature(arbitrary_self_types)]
+#![allow(non_snake_case)]
+
+use std::pin::Pin;
+
+struct Struct { }
+
+type Alias = Struct;
+
+impl Struct {
+    // Test using an alias for `Struct`:
+    //
+    // FIXME. We currently fail to recognize this as the self type, which
+    // feels like a bug.
+
+    fn ref_Alias(self: &Alias, f: &u32) -> &u32 {
+        f
+    }
+
+    fn box_ref_Alias(self: Box<&Alias>, f: &u32) -> &u32 {
+        f
+    }
+
+    fn pin_ref_Alias(self: Pin<&Alias>, f: &u32) -> &u32 {
+        f
+    }
+
+    fn box_box_ref_Alias(self: Box<Box<&Alias>>, f: &u32) -> &u32 {
+        f
+    }
+
+    fn box_pin_ref_Alias(self: Box<Pin<&Alias>>, f: &u32) -> &u32 {
+        f
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/self/elision/ref-assoc.rs b/src/test/ui/self/elision/ref-assoc.rs
new file mode 100644 (file)
index 0000000..f9354bc
--- /dev/null
@@ -0,0 +1,40 @@
+// check-pass
+
+#![feature(arbitrary_self_types)]
+#![allow(non_snake_case)]
+
+use std::pin::Pin;
+
+trait Trait {
+    type AssocType;
+}
+
+struct Struct { }
+
+impl Trait for Struct {
+    type AssocType = Self;
+}
+
+impl Struct {
+    fn ref_AssocType(self: &<Struct as Trait>::AssocType, f: &u32) -> &u32 {
+        f
+    }
+
+    fn box_ref_AssocType(self: Box<&<Struct as Trait>::AssocType>, f: &u32) -> &u32 {
+        f
+    }
+
+    fn pin_ref_AssocType(self: Pin<&<Struct as Trait>::AssocType>, f: &u32) -> &u32 {
+        f
+    }
+
+    fn box_box_ref_AssocType(self: Box<Box<&<Struct as Trait>::AssocType>>, f: &u32) -> &u32 {
+        f
+    }
+
+    fn box_pin_ref_AssocType(self: Box<Pin<&<Struct as Trait>::AssocType>>, f: &u32) -> &u32 {
+        f
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/self/elision/ref-mut-alias.rs b/src/test/ui/self/elision/ref-mut-alias.rs
new file mode 100644 (file)
index 0000000..395816f
--- /dev/null
@@ -0,0 +1,36 @@
+// check-pass
+
+#![feature(arbitrary_self_types)]
+#![allow(non_snake_case)]
+
+use std::pin::Pin;
+
+struct Struct { }
+
+type Alias = Struct;
+
+impl Struct {
+    // Test using an alias for `Struct`:
+
+    fn ref_Alias(self: &mut Alias, f: &u32) -> &u32 {
+        f
+    }
+
+    fn box_ref_Alias(self: Box<&mut Alias>, f: &u32) -> &u32 {
+        f
+    }
+
+    fn pin_ref_Alias(self: Pin<&mut Alias>, f: &u32) -> &u32 {
+        f
+    }
+
+    fn box_box_ref_Alias(self: Box<Box<&mut Alias>>, f: &u32) -> &u32 {
+        f
+    }
+
+    fn box_pin_ref_Alias(self: Box<Pin<&mut Alias>>, f: &u32) -> &u32 {
+        f
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/self/elision/ref-mut-self.nll.stderr b/src/test/ui/self/elision/ref-mut-self.nll.stderr
new file mode 100644 (file)
index 0000000..3a8ae3f
--- /dev/null
@@ -0,0 +1,62 @@
+error: lifetime may not live long enough
+  --> $DIR/ref-mut-self.rs:12:9
+   |
+LL |     fn ref_self(&mut self, f: &u32) -> &u32 {
+   |                 -             - let's call the lifetime of this reference `'1`
+   |                 |
+   |                 let's call the lifetime of this reference `'2`
+LL |         f
+   |         ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+
+error: lifetime may not live long enough
+  --> $DIR/ref-mut-self.rs:18:9
+   |
+LL |     fn ref_Self(self: &mut Self, f: &u32) -> &u32 {
+   |                       -             - let's call the lifetime of this reference `'1`
+   |                       |
+   |                       let's call the lifetime of this reference `'2`
+LL |         f
+   |         ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+
+error: lifetime may not live long enough
+  --> $DIR/ref-mut-self.rs:22:9
+   |
+LL |     fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 {
+   |                               -              - let's call the lifetime of this reference `'1`
+   |                               |
+   |                               let's call the lifetime of this reference `'2`
+LL |         f
+   |         ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+
+error: lifetime may not live long enough
+  --> $DIR/ref-mut-self.rs:26:9
+   |
+LL |     fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 {
+   |                               -              - let's call the lifetime of this reference `'1`
+   |                               |
+   |                               let's call the lifetime of this reference `'2`
+LL |         f
+   |         ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+
+error: lifetime may not live long enough
+  --> $DIR/ref-mut-self.rs:30:9
+   |
+LL |     fn box_box_ref_Self(self: Box<Box<&mut Self>>, f: &u32) -> &u32 {
+   |                                       -               - let's call the lifetime of this reference `'1`
+   |                                       |
+   |                                       let's call the lifetime of this reference `'2`
+LL |         f
+   |         ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+
+error: lifetime may not live long enough
+  --> $DIR/ref-mut-self.rs:34:9
+   |
+LL |     fn box_pin_ref_Self(self: Box<Pin<&mut Self>>, f: &u32) -> &u32 {
+   |                                       -               - let's call the lifetime of this reference `'1`
+   |                                       |
+   |                                       let's call the lifetime of this reference `'2`
+LL |         f
+   |         ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/self/elision/ref-mut-self.rs b/src/test/ui/self/elision/ref-mut-self.rs
new file mode 100644 (file)
index 0000000..a7ea47b
--- /dev/null
@@ -0,0 +1,38 @@
+#![feature(arbitrary_self_types)]
+#![allow(non_snake_case)]
+
+use std::pin::Pin;
+
+struct Struct { }
+
+impl Struct {
+    // Test using `&mut self` sugar:
+
+    fn ref_self(&mut self, f: &u32) -> &u32 {
+        f //~ ERROR lifetime mismatch
+    }
+
+    // Test using `&mut Self` explicitly:
+
+    fn ref_Self(self: &mut Self, f: &u32) -> &u32 {
+        f //~ ERROR lifetime mismatch
+    }
+
+    fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 {
+        f //~ ERROR lifetime mismatch
+    }
+
+    fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 {
+        f //~ ERROR lifetime mismatch
+    }
+
+    fn box_box_ref_Self(self: Box<Box<&mut Self>>, f: &u32) -> &u32 {
+        f //~ ERROR lifetime mismatch
+    }
+
+    fn box_pin_ref_Self(self: Box<Pin<&mut Self>>, f: &u32) -> &u32 {
+        f //~ ERROR lifetime mismatch
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/self/elision/ref-mut-self.stderr b/src/test/ui/self/elision/ref-mut-self.stderr
new file mode 100644 (file)
index 0000000..37984cd
--- /dev/null
@@ -0,0 +1,62 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-mut-self.rs:12:9
+   |
+LL |     fn ref_self(&mut self, f: &u32) -> &u32 {
+   |                               ----     ----
+   |                               |
+   |                               this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-mut-self.rs:18:9
+   |
+LL |     fn ref_Self(self: &mut Self, f: &u32) -> &u32 {
+   |                                     ----     ----
+   |                                     |
+   |                                     this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-mut-self.rs:22:9
+   |
+LL |     fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 {
+   |                                              ----     ----
+   |                                              |
+   |                                              this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-mut-self.rs:26:9
+   |
+LL |     fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 {
+   |                                              ----     ----
+   |                                              |
+   |                                              this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-mut-self.rs:30:9
+   |
+LL |     fn box_box_ref_Self(self: Box<Box<&mut Self>>, f: &u32) -> &u32 {
+   |                                                       ----     ----
+   |                                                       |
+   |                                                       this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-mut-self.rs:34:9
+   |
+LL |     fn box_pin_ref_Self(self: Box<Pin<&mut Self>>, f: &u32) -> &u32 {
+   |                                                       ----     ----
+   |                                                       |
+   |                                                       this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/self/elision/ref-mut-struct.nll.stderr b/src/test/ui/self/elision/ref-mut-struct.nll.stderr
new file mode 100644 (file)
index 0000000..66152ba
--- /dev/null
@@ -0,0 +1,52 @@
+error: lifetime may not live long enough
+  --> $DIR/ref-mut-struct.rs:12:9
+   |
+LL |     fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 {
+   |                         -               - let's call the lifetime of this reference `'1`
+   |                         |
+   |                         let's call the lifetime of this reference `'2`
+LL |         f
+   |         ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+
+error: lifetime may not live long enough
+  --> $DIR/ref-mut-struct.rs:16:9
+   |
+LL |     fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 {
+   |                                 -                - let's call the lifetime of this reference `'1`
+   |                                 |
+   |                                 let's call the lifetime of this reference `'2`
+LL |         f
+   |         ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+
+error: lifetime may not live long enough
+  --> $DIR/ref-mut-struct.rs:20:9
+   |
+LL |     fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 {
+   |                                 -                - let's call the lifetime of this reference `'1`
+   |                                 |
+   |                                 let's call the lifetime of this reference `'2`
+LL |         f
+   |         ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+
+error: lifetime may not live long enough
+  --> $DIR/ref-mut-struct.rs:24:9
+   |
+LL |     fn box_box_ref_Struct(self: Box<Box<&mut Struct>>, f: &u32) -> &u32 {
+   |                                         -                 - let's call the lifetime of this reference `'1`
+   |                                         |
+   |                                         let's call the lifetime of this reference `'2`
+LL |         f
+   |         ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+
+error: lifetime may not live long enough
+  --> $DIR/ref-mut-struct.rs:28:9
+   |
+LL |     fn box_pin_ref_Struct(self: Box<Pin<&mut Struct>>, f: &u32) -> &u32 {
+   |                                         -                 - let's call the lifetime of this reference `'1`
+   |                                         |
+   |                                         let's call the lifetime of this reference `'2`
+LL |         f
+   |         ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/ui/self/elision/ref-mut-struct.rs b/src/test/ui/self/elision/ref-mut-struct.rs
new file mode 100644 (file)
index 0000000..795ddf8
--- /dev/null
@@ -0,0 +1,32 @@
+#![feature(arbitrary_self_types)]
+#![allow(non_snake_case)]
+
+use std::pin::Pin;
+
+struct Struct { }
+
+impl Struct {
+    // Test using `&mut Struct` explicitly:
+
+    fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 {
+        f //~ ERROR lifetime mismatch
+    }
+
+    fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 {
+        f //~ ERROR lifetime mismatch
+    }
+
+    fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 {
+        f //~ ERROR lifetime mismatch
+    }
+
+    fn box_box_ref_Struct(self: Box<Box<&mut Struct>>, f: &u32) -> &u32 {
+        f //~ ERROR lifetime mismatch
+    }
+
+    fn box_pin_ref_Struct(self: Box<Pin<&mut Struct>>, f: &u32) -> &u32 {
+        f //~ ERROR lifetime mismatch
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/self/elision/ref-mut-struct.stderr b/src/test/ui/self/elision/ref-mut-struct.stderr
new file mode 100644 (file)
index 0000000..2a48269
--- /dev/null
@@ -0,0 +1,52 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-mut-struct.rs:12:9
+   |
+LL |     fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 {
+   |                                         ----     ----
+   |                                         |
+   |                                         this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-mut-struct.rs:16:9
+   |
+LL |     fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 {
+   |                                                  ----     ----
+   |                                                  |
+   |                                                  this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-mut-struct.rs:20:9
+   |
+LL |     fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 {
+   |                                                  ----     ----
+   |                                                  |
+   |                                                  this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-mut-struct.rs:24:9
+   |
+LL |     fn box_box_ref_Struct(self: Box<Box<&mut Struct>>, f: &u32) -> &u32 {
+   |                                                           ----     ----
+   |                                                           |
+   |                                                           this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-mut-struct.rs:28:9
+   |
+LL |     fn box_pin_ref_Struct(self: Box<Pin<&mut Struct>>, f: &u32) -> &u32 {
+   |                                                           ----     ----
+   |                                                           |
+   |                                                           this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/ui/self/elision/ref-self.nll.stderr b/src/test/ui/self/elision/ref-self.nll.stderr
new file mode 100644 (file)
index 0000000..20045be
--- /dev/null
@@ -0,0 +1,72 @@
+error: lifetime may not live long enough
+  --> $DIR/ref-self.rs:21:9
+   |
+LL |     fn ref_self(&self, f: &u32) -> &u32 {
+   |                 -         - let's call the lifetime of this reference `'1`
+   |                 |
+   |                 let's call the lifetime of this reference `'2`
+LL |         f
+   |         ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+
+error: lifetime may not live long enough
+  --> $DIR/ref-self.rs:27:9
+   |
+LL |     fn ref_Self(self: &Self, f: &u32) -> &u32 {
+   |                       -         - let's call the lifetime of this reference `'1`
+   |                       |
+   |                       let's call the lifetime of this reference `'2`
+LL |         f
+   |         ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+
+error: lifetime may not live long enough
+  --> $DIR/ref-self.rs:31:9
+   |
+LL |     fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
+   |                               -          - let's call the lifetime of this reference `'1`
+   |                               |
+   |                               let's call the lifetime of this reference `'2`
+LL |         f
+   |         ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+
+error: lifetime may not live long enough
+  --> $DIR/ref-self.rs:35:9
+   |
+LL |     fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
+   |                               -          - let's call the lifetime of this reference `'1`
+   |                               |
+   |                               let's call the lifetime of this reference `'2`
+LL |         f
+   |         ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+
+error: lifetime may not live long enough
+  --> $DIR/ref-self.rs:39:9
+   |
+LL |     fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
+   |                                       -           - let's call the lifetime of this reference `'1`
+   |                                       |
+   |                                       let's call the lifetime of this reference `'2`
+LL |         f
+   |         ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+
+error: lifetime may not live long enough
+  --> $DIR/ref-self.rs:43:9
+   |
+LL |     fn box_pin_ref_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
+   |                                       -           - let's call the lifetime of this reference `'1`
+   |                                       |
+   |                                       let's call the lifetime of this reference `'2`
+LL |         f
+   |         ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+
+error: lifetime may not live long enough
+  --> $DIR/ref-self.rs:47:9
+   |
+LL |     fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 {
+   |                                      -                - let's call the lifetime of this reference `'1`
+   |                                      |
+   |                                      let's call the lifetime of this reference `'2`
+LL |         f
+   |         ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+
+error: aborting due to 7 previous errors
+
diff --git a/src/test/ui/self/elision/ref-self.rs b/src/test/ui/self/elision/ref-self.rs
new file mode 100644 (file)
index 0000000..e389d85
--- /dev/null
@@ -0,0 +1,51 @@
+#![feature(arbitrary_self_types)]
+#![allow(non_snake_case)]
+
+use std::marker::PhantomData;
+use std::ops::Deref;
+use std::pin::Pin;
+
+struct Struct { }
+
+struct Wrap<T, P>(T, PhantomData<P>);
+
+impl<T, P> Deref for Wrap<T, P> {
+    type Target = T;
+    fn deref(&self) -> &T { &self.0 }
+}
+
+impl Struct {
+    // Test using `&self` sugar:
+
+    fn ref_self(&self, f: &u32) -> &u32 {
+        f //~ ERROR lifetime mismatch
+    }
+
+    // Test using `&Self` explicitly:
+
+    fn ref_Self(self: &Self, f: &u32) -> &u32 {
+        f //~ ERROR lifetime mismatch
+    }
+
+    fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
+        f //~ ERROR lifetime mismatch
+    }
+
+    fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
+        f //~ ERROR lifetime mismatch
+    }
+
+    fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
+        f //~ ERROR lifetime mismatch
+    }
+
+    fn box_pin_ref_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
+        f //~ ERROR lifetime mismatch
+    }
+
+    fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 {
+        f //~ ERROR lifetime mismatch
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/self/elision/ref-self.stderr b/src/test/ui/self/elision/ref-self.stderr
new file mode 100644 (file)
index 0000000..611498f
--- /dev/null
@@ -0,0 +1,72 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-self.rs:21:9
+   |
+LL |     fn ref_self(&self, f: &u32) -> &u32 {
+   |                           ----     ----
+   |                           |
+   |                           this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-self.rs:27:9
+   |
+LL |     fn ref_Self(self: &Self, f: &u32) -> &u32 {
+   |                                 ----     ----
+   |                                 |
+   |                                 this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-self.rs:31:9
+   |
+LL |     fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
+   |                                          ----     ----
+   |                                          |
+   |                                          this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-self.rs:35:9
+   |
+LL |     fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
+   |                                          ----     ----
+   |                                          |
+   |                                          this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-self.rs:39:9
+   |
+LL |     fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
+   |                                                   ----     ----
+   |                                                   |
+   |                                                   this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-self.rs:43:9
+   |
+LL |     fn box_pin_ref_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
+   |                                                   ----     ----
+   |                                                   |
+   |                                                   this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-self.rs:47:9
+   |
+LL |     fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 {
+   |                                                       ---     ---
+   |                                                       |
+   |                                                       this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+
+error: aborting due to 7 previous errors
+
diff --git a/src/test/ui/self/elision/ref-struct.nll.stderr b/src/test/ui/self/elision/ref-struct.nll.stderr
new file mode 100644 (file)
index 0000000..a258bc9
--- /dev/null
@@ -0,0 +1,52 @@
+error: lifetime may not live long enough
+  --> $DIR/ref-struct.rs:12:9
+   |
+LL |     fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
+   |                         -           - let's call the lifetime of this reference `'1`
+   |                         |
+   |                         let's call the lifetime of this reference `'2`
+LL |         f
+   |         ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+
+error: lifetime may not live long enough
+  --> $DIR/ref-struct.rs:16:9
+   |
+LL |     fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 {
+   |                                 -            - let's call the lifetime of this reference `'1`
+   |                                 |
+   |                                 let's call the lifetime of this reference `'2`
+LL |         f
+   |         ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+
+error: lifetime may not live long enough
+  --> $DIR/ref-struct.rs:20:9
+   |
+LL |     fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 {
+   |                                 -            - let's call the lifetime of this reference `'1`
+   |                                 |
+   |                                 let's call the lifetime of this reference `'2`
+LL |         f
+   |         ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+
+error: lifetime may not live long enough
+  --> $DIR/ref-struct.rs:24:9
+   |
+LL |     fn box_box_ref_Struct(self: Box<Box<&Struct>>, f: &u32) -> &u32 {
+   |                                         -             - let's call the lifetime of this reference `'1`
+   |                                         |
+   |                                         let's call the lifetime of this reference `'2`
+LL |         f
+   |         ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+
+error: lifetime may not live long enough
+  --> $DIR/ref-struct.rs:28:9
+   |
+LL |     fn box_pin_Struct(self: Box<Pin<&Struct>>, f: &u32) -> &u32 {
+   |                                     -             - let's call the lifetime of this reference `'1`
+   |                                     |
+   |                                     let's call the lifetime of this reference `'2`
+LL |         f
+   |         ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/ui/self/elision/ref-struct.rs b/src/test/ui/self/elision/ref-struct.rs
new file mode 100644 (file)
index 0000000..342d6d2
--- /dev/null
@@ -0,0 +1,32 @@
+#![feature(arbitrary_self_types)]
+#![allow(non_snake_case)]
+
+use std::pin::Pin;
+
+struct Struct { }
+
+impl Struct {
+    // Test using `&Struct` explicitly:
+
+    fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
+        f //~ ERROR lifetime mismatch
+    }
+
+    fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 {
+        f //~ ERROR lifetime mismatch
+    }
+
+    fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 {
+        f //~ ERROR lifetime mismatch
+    }
+
+    fn box_box_ref_Struct(self: Box<Box<&Struct>>, f: &u32) -> &u32 {
+        f //~ ERROR lifetime mismatch
+    }
+
+    fn box_pin_Struct(self: Box<Pin<&Struct>>, f: &u32) -> &u32 {
+        f //~ ERROR lifetime mismatch
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/self/elision/ref-struct.stderr b/src/test/ui/self/elision/ref-struct.stderr
new file mode 100644 (file)
index 0000000..186e651
--- /dev/null
@@ -0,0 +1,52 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-struct.rs:12:9
+   |
+LL |     fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
+   |                                     ----     ----
+   |                                     |
+   |                                     this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-struct.rs:16:9
+   |
+LL |     fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 {
+   |                                              ----     ----
+   |                                              |
+   |                                              this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-struct.rs:20:9
+   |
+LL |     fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 {
+   |                                              ----     ----
+   |                                              |
+   |                                              this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-struct.rs:24:9
+   |
+LL |     fn box_box_ref_Struct(self: Box<Box<&Struct>>, f: &u32) -> &u32 {
+   |                                                       ----     ----
+   |                                                       |
+   |                                                       this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/ref-struct.rs:28:9
+   |
+LL |     fn box_pin_Struct(self: Box<Pin<&Struct>>, f: &u32) -> &u32 {
+   |                                                   ----     ----
+   |                                                   |
+   |                                                   this parameter and the return type are declared with different lifetimes...
+LL |         f
+   |         ^ ...but data from `f` is returned here
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/ui/self/elision/self.rs b/src/test/ui/self/elision/self.rs
new file mode 100644 (file)
index 0000000..dbcef71
--- /dev/null
@@ -0,0 +1,36 @@
+// check-pass
+
+#![feature(arbitrary_self_types)]
+#![allow(non_snake_case)]
+
+use std::rc::Rc;
+
+struct Struct { }
+
+impl Struct {
+    fn take_self(self, f: &u32) -> &u32 {
+        f
+    }
+
+    fn take_Self(self: Self, f: &u32) -> &u32 {
+        f
+    }
+
+    fn take_Box_Self(self: Box<Self>, f: &u32) -> &u32 {
+        f
+    }
+
+    fn take_Box_Box_Self(self: Box<Box<Self>>, f: &u32) -> &u32 {
+        f
+    }
+
+    fn take_Rc_Self(self: Rc<Self>, f: &u32) -> &u32 {
+        f
+    }
+
+    fn take_Box_Rc_Self(self: Box<Rc<Self>>, f: &u32) -> &u32 {
+        f
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/self/elision/struct.rs b/src/test/ui/self/elision/struct.rs
new file mode 100644 (file)
index 0000000..227e993
--- /dev/null
@@ -0,0 +1,32 @@
+// check-pass
+
+#![feature(arbitrary_self_types)]
+#![allow(non_snake_case)]
+
+use std::rc::Rc;
+
+struct Struct { }
+
+impl Struct {
+    fn ref_Struct(self: Struct, f: &u32) -> &u32 {
+        f
+    }
+
+    fn box_Struct(self: Box<Struct>, f: &u32) -> &u32 {
+        f
+    }
+
+    fn rc_Struct(self: Rc<Struct>, f: &u32) -> &u32 {
+        f
+    }
+
+    fn box_box_Struct(self: Box<Box<Struct>>, f: &u32) -> &u32 {
+        f
+    }
+
+    fn box_rc_Struct(self: Box<Rc<Struct>>, f: &u32) -> &u32 {
+        f
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/self/self_lifetime.rs b/src/test/ui/self/self_lifetime.rs
new file mode 100644 (file)
index 0000000..f04bd83
--- /dev/null
@@ -0,0 +1,15 @@
+// check-pass
+
+// https://github.com/rust-lang/rust/pull/60944#issuecomment-495346120
+
+struct Foo<'a>(&'a ());
+impl<'a> Foo<'a> {
+    fn foo<'b>(self: &'b Foo<'a>) -> &() { self.0 }
+}
+
+type Alias = Foo<'static>;
+impl Alias {
+    fn bar<'a>(self: &Alias, arg: &'a ()) -> &() { arg }
+}
+
+fn main() {}
index f34e6b7606dd75fa7d750024d5a8f08c2cc36f96..929c35a9e1122cbac1f1bac170fa9dff0d19d7cd 100644 (file)
@@ -25,7 +25,7 @@ pub fn main() {
     let (_, _,) = (1, 1,);
     let [_, _,] = [1, 1,];
     let [_, _, .., _,] = [1, 1, 1, 1,];
-    let [_, _, _.., _,] = [1, 1, 1, 1,];
+    let [_, _, _, ..,] = [1, 1, 1, 1,];
 
     let x: Foo<isize,> = Foo::<isize,>(1);
 
index 20176557bcbebecf6b9af3e59968649f0df71551..a935bc6a4ded9b03f54349a9407dcd77ba1eb189 100644 (file)
@@ -1,5 +1,3 @@
-#![deny(rust_2018_idioms)]
-
 use toml;
 use serde::Serialize;
 
index 14035eedbb44b4d15af533dbc03c0e2bcde1fab6..729287faeb628a0a4c3d45bdf8cd9ef781f825bb 100644 (file)
@@ -1,5 +1,3 @@
-#![deny(rust_2018_idioms)]
-
 use std::env;
 use std::process::Command;
 use std::path::{Path, PathBuf};
index 164310dd8d09dd4db4065ee569a70380e793dc72..dc69a5c0b610df452217291db1a0ebc4f76401e3 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 164310dd8d09dd4db4065ee569a70380e793dc72
+Subproject commit dc69a5c0b610df452217291db1a0ebc4f76401e3
index 31360c000ce84d74587e72adfcc94bebf7a5a8a4..d709475541a60696e25227f4e346547fbb4acd7d 100644 (file)
@@ -1,7 +1,6 @@
 #![crate_name = "compiletest"]
 #![feature(test)]
 #![feature(vec_remove_item)]
-#![deny(warnings, rust_2018_idioms)]
 
 extern crate test;
 
index 3e7c7ab6379d8433d983a66232a85b01d9eed841..c31a5069e4673e64b2c4ecb5d03304eec3c3a442 100644 (file)
@@ -1,7 +1,5 @@
 #![feature(rustc_private)]
 
-#![deny(rust_2018_idioms)]
-
 extern crate env_logger;
 extern crate syntax;
 extern crate serialize as rustc_serialize;
index e2bcd4d40af7f371bb5555e7266cf4874d68c348..49c149afe17f901cac9908b018a05465fe119f40 100644 (file)
@@ -14,8 +14,6 @@
 //! A few whitelisted exceptions are allowed as there's known bugs in rustdoc,
 //! but this should catch the majority of "broken link" cases.
 
-#![deny(rust_2018_idioms)]
-
 use std::collections::hash_map::Entry;
 use std::collections::{HashMap, HashSet};
 use std::env;
index 8f9061d7c181111ce22ae11fe5f723fe975e4101..b8dcba3afc3a1624c897c8a27028ebc6dec8d8aa 100755 (executable)
@@ -1,6 +1,12 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
+## This script publishes the new "current" toolstate in the toolstate repo (not to be
+## confused with publishing the test results, which happens in
+## `src/ci/docker/x86_64-gnu-tools/checktools.sh`).
+## It is set as callback for `src/ci/docker/x86_64-gnu-tools/repo.sh` by the CI scripts
+## when a new commit lands on `master` (i.e., after it passed all checks on `auto`).
+
 import sys
 import re
 import os
index f42de44176787b0baca7946af970c9ed53b2688a..a1d52251263d4fe7ee9d3cb6f8ccf5706385e197 100644 (file)
@@ -1,5 +1,3 @@
-#![deny(rust_2018_idioms)]
-
 /// This is a small client program intended to pair with `remote-test-server` in
 /// this repository. This client connects to the server over TCP and is used to
 /// push artifacts and run tests on the server instead of locally.
index e1270489d315fbc9ec8ac0415d17720649892122..d2238730196aa9ce7144d2aa9567e84fb7fc4c47 100644 (file)
@@ -1,5 +1,3 @@
-#![deny(rust_2018_idioms)]
-
 /// This is a small server which is intended to run inside of an emulator or
 /// on a remote test device. This server pairs with the `remote-test-client`
 /// program in this repository. The `remote-test-client` connects to this
index 4689bee3e131933082bea17aa722135ac9cdb8c1..6bce7c3a978eb7f55e8337171798988e5583aad9 100644 (file)
@@ -1,5 +1,3 @@
-#![deny(rust_2018_idioms)]
-
 use clap::{crate_version};
 
 use std::env;
index 99d51bc2d56acaf2ed40878d987120e22947e9eb..143278525616628baf7d95f94e402694cfc82952 100644 (file)
@@ -1,5 +1,4 @@
 #![feature(no_core)]
 #![no_core]
-#![deny(rust_2018_idioms)]
 
 pub use core::*;
index 63432a6585a84d1365e7710206370338fb7f5763..616b5444832c11c56f28ec2ae291b20e4b551ccd 100644 (file)
@@ -1,5 +1,3 @@
-#![deny(rust_2018_idioms)]
-
 use std::env::args;
 use std::fs::read_dir;
 use std::path::Path;
index 8171708e99d004e3bd161007152f0e24588ebbc0..99573cadb95f008db0e51e373ab30f56c23c27ad 100644 (file)
@@ -1,3 +1 @@
-#![deny(rust_2018_idioms)]
-
 fn main() { rustdoc::main() }
index 06c1a8c18bac7b7e323a24754ff154879504a66b..eca8001a9d2a1be40f45cfe6eccae9b9d4d49779 100644 (file)
@@ -38,36 +38,24 @@ macro_rules! tidy_error {
 pub mod deps;
 pub mod extdeps;
 pub mod ui_tests;
+pub mod unit_tests;
 pub mod unstable_book;
-pub mod libcoretest;
 
 fn filter_dirs(path: &Path) -> bool {
     let skip = [
-        "src/llvm",
-        "src/llvm-project",
         "src/llvm-emscripten",
-        "src/libbacktrace",
-        "src/librustc_data_structures/owning_ref",
-        "src/vendor",
+        "src/llvm-project",
+        "src/stdarch",
         "src/tools/cargo",
-        "src/tools/clang",
-        "src/tools/rls",
         "src/tools/clippy",
+        "src/tools/miri",
+        "src/tools/rls",
         "src/tools/rust-installer",
         "src/tools/rustfmt",
-        "src/tools/miri",
-        "src/tools/lld",
-        "src/tools/lldb",
-        "src/target",
-        "src/stdarch",
-        "src/rust-sgx",
-        "target",
-        "vendor",
     ];
     skip.iter().any(|p| path.ends_with(p))
 }
 
-
 fn walk_many(
     paths: &[&Path], skip: &mut dyn FnMut(&Path) -> bool, f: &mut dyn FnMut(&DirEntry, &str)
 ) {
diff --git a/src/tools/tidy/src/libcoretest.rs b/src/tools/tidy/src/libcoretest.rs
deleted file mode 100644 (file)
index 579a20e..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-//! Tidy check to ensure `#[test]` is not used directly inside `libcore`.
-//!
-//! `#![no_core]` libraries cannot be tested directly due to duplicating lang
-//! item. All tests must be written externally in `libcore/tests`.
-
-use std::path::Path;
-
-pub fn check(path: &Path, bad: &mut bool) {
-    let libcore_path = path.join("libcore");
-    super::walk(
-        &libcore_path,
-        &mut |subpath| t!(subpath.strip_prefix(&libcore_path)).starts_with("tests"),
-        &mut |entry, contents| {
-            let subpath = entry.path();
-            if let Some("rs") = subpath.extension().and_then(|e| e.to_str()) {
-                let contents = contents.trim();
-                if !contents.starts_with("//") && contents.contains("#[test]") {
-                    tidy_error!(
-                        bad,
-                        "`{}` contains `#[test]`; libcore tests must be placed inside \
-                        `src/libcore/tests/`",
-                        subpath.display()
-                    );
-                }
-            }
-        },
-    );
-}
index 918762ed6e69a20217fdaae89681d4cc388980ae..3acb50547daf041c818059887a525f76898f1ad0 100644 (file)
@@ -4,8 +4,6 @@
 //! etc. This is run by default on `make check` and as part of the auto
 //! builders.
 
-#![deny(warnings)]
-
 use tidy::*;
 
 use std::process;
@@ -27,7 +25,7 @@ fn main() {
     let collected = features::check(&path, &mut bad, verbose);
     pal::check(&path, &mut bad);
     unstable_book::check(&path, collected, &mut bad);
-    libcoretest::check(&path, &mut bad);
+    unit_tests::check(&path, &mut bad);
     if !args.iter().any(|s| *s == "--no-vendor") {
         deps::check(&path, &mut bad);
     }
index 4a159d926b7cc009c49f678badfd6cffb6023b10..6a0d530e2362a27b55d5b44f8b54928e25945e68 100644 (file)
@@ -152,6 +152,8 @@ pub fn check(path: &Path, bad: &mut bool) {
         let mut skip_file_length = contains_ignore_directive(can_contain, &contents, "filelength");
         let mut skip_end_whitespace =
             contains_ignore_directive(can_contain, &contents, "end-whitespace");
+        let mut skip_trailing_newlines =
+            contains_ignore_directive(can_contain, &contents, "trailing-newlines");
         let mut skip_copyright = contains_ignore_directive(can_contain, &contents, "copyright");
         let mut leading_new_lines = false;
         let mut trailing_new_lines = 0;
@@ -214,10 +216,17 @@ pub fn check(path: &Path, bad: &mut bool) {
         if leading_new_lines {
             tidy_error!(bad, "{}: leading newline", file.display());
         }
+        let mut err = |msg: &str| {
+            tidy_error!(bad, "{}: {}", file.display(), msg);
+        };
         match trailing_new_lines {
-            0 => tidy_error!(bad, "{}: missing trailing newline", file.display()),
+            0 => suppressible_tidy_err!(err, skip_trailing_newlines, "missing trailing newline"),
             1 => {}
-            n => tidy_error!(bad, "{}: too many trailing newlines ({})", file.display(), n),
+            n => suppressible_tidy_err!(
+                err,
+                skip_trailing_newlines,
+                &format!("too many trailing newlines ({})", n)
+            ),
         };
         if lines > LINES {
             let mut err = |_| {
@@ -247,6 +256,9 @@ pub fn check(path: &Path, bad: &mut bool) {
         if let Directive::Ignore(false) = skip_end_whitespace {
             tidy_error!(bad, "{}: ignoring trailing whitespace unnecessarily", file.display());
         }
+        if let Directive::Ignore(false) = skip_trailing_newlines {
+            tidy_error!(bad, "{}: ignoring trailing newlines unnecessarily", file.display());
+        }
         if let Directive::Ignore(false) = skip_copyright {
             tidy_error!(bad, "{}: ignoring copyright unnecessarily", file.display());
         }
diff --git a/src/tools/tidy/src/unit_tests.rs b/src/tools/tidy/src/unit_tests.rs
new file mode 100644 (file)
index 0000000..b789e5c
--- /dev/null
@@ -0,0 +1,95 @@
+//! Tidy check to ensure `#[test]` and `#[bench]` are not used directly inside
+//! `libcore` or `liballoc`.
+//!
+//! `#![no_std]` libraries cannot be tested directly due to duplicating lang
+//! items. All tests and benchmarks must be written externally in `libcore/{tests,benches}`
+//! or `liballoc/{tests,benches}`.
+//!
+//! Outside of libcore and liballoc tests and benchmarks should be outlined into separate files
+//! named `tests.rs` or `benches.rs`, or directories named `tests` or `benches` unconfigured
+//! during normal build.
+
+use std::path::Path;
+
+pub fn check(root_path: &Path, bad: &mut bool) {
+    let libcore = &root_path.join("libcore");
+    let liballoc = &root_path.join("liballoc");
+    let libcore_tests = &root_path.join("libcore/tests");
+    let liballoc_tests = &root_path.join("liballoc/tests");
+    let libcore_benches = &root_path.join("libcore/benches");
+    let liballoc_benches = &root_path.join("liballoc/benches");
+    let is_core_or_alloc = |path: &Path| {
+        let is_core = path.starts_with(libcore) &&
+                      !(path.starts_with(libcore_tests) || path.starts_with(libcore_benches));
+        let is_alloc = path.starts_with(liballoc) &&
+                       !(path.starts_with(liballoc_tests) || path.starts_with(liballoc_benches));
+        is_core || is_alloc
+    };
+    let fixme = [
+        "liballoc",
+        "libpanic_unwind/dwarf",
+        "librustc",
+        "librustc_data_structures",
+        "librustc_incremental/persist",
+        "librustc_lexer/src",
+        "librustc_target/spec",
+        "librustdoc",
+        "libserialize",
+        "libstd",
+        "libsyntax",
+        "libsyntax_pos",
+        "libterm/terminfo",
+        "libtest",
+        "tools/compiletest/src",
+        "tools/tidy/src",
+    ];
+
+    let mut skip = |path: &Path| {
+        let file_name = path.file_name().unwrap_or_default();
+        if path.is_dir() {
+            super::filter_dirs(path) ||
+            path.ends_with("src/test") ||
+            path.ends_with("src/doc") ||
+            (file_name == "tests" || file_name == "benches") && !is_core_or_alloc(path) ||
+            fixme.iter().any(|p| path.ends_with(p))
+        } else {
+            let extension = path.extension().unwrap_or_default();
+            extension != "rs" ||
+            (file_name == "tests.rs" || file_name == "benches.rs") && !is_core_or_alloc(path)
+        }
+    };
+
+    super::walk(
+        root_path,
+        &mut skip,
+        &mut |entry, contents| {
+            let path = entry.path();
+            let is_libcore = path.starts_with(libcore);
+            let is_liballoc = path.starts_with(liballoc);
+            for (i, line) in contents.lines().enumerate() {
+                let line = line.trim();
+                let is_test = || line.contains("#[test]") && !line.contains("`#[test]");
+                let is_bench = || line.contains("#[bench]") && !line.contains("`#[bench]");
+                if !line.starts_with("//") && (is_test() || is_bench()) {
+                    let explanation = if is_libcore {
+                        "libcore unit tests and benchmarks must be placed into \
+                         `libcore/tests` or `libcore/benches`"
+                    } else if is_liballoc {
+                        "liballoc unit tests and benchmarks must be placed into \
+                         `liballoc/tests` or `liballoc/benches`"
+                    } else {
+                        "unit tests and benchmarks must be placed into \
+                         separate files or directories named \
+                         `tests.rs`, `benches.rs`, `tests` or `benches`"
+                    };
+                    let name = if is_test() { "test" } else { "bench" };
+                    tidy_error!(
+                        bad, "`{}:{}` contains `#[{}]`; {}",
+                        path.display(), i + 1, name, explanation,
+                    );
+                    return;
+                }
+            }
+        },
+    );
+}
index e92d174a4e1d45a362be130cc3a05a387b2b6882..036349ea1c82a23f99562125c88c153417efb010 100644 (file)
@@ -1,10 +1,5 @@
 //! Auto-generate stub docs for the unstable book
 
-#![deny(rust_2018_idioms)]
-#![deny(warnings)]
-
-
-
 use tidy::features::{Feature, Features, collect_lib_features, collect_lang_features};
 use tidy::unstable_book::{collect_unstable_feature_names, collect_unstable_book_section_file_names,
                           PATH_STR, LANG_FEATURES_DIR, LIB_FEATURES_DIR};
index 0e703a3ab349d2951a0cc0b914e4499092d0b464..f3509897bdf9c834db18b2bc7cbda5754c9af270 100644 (file)
@@ -1,6 +1,7 @@
 [relabel]
 allow-unauthenticated = [
-    "C-*", "A-*", "E-*", "NLL-*", "O-*", "S-*", "T-*", "WG-*",
+    "C-*", "A-*", "E-*", "NLL-*", "O-*", "S-*", "T-*", "WG-*", "F-*",
+    "requires-nightly",
     # I-* without I-nominated
     "I-compilemem", "I-compiletime", "I-crash", "I-hang", "I-ICE", "I-slow",
 ]