]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #49681 - tmccombs:take-set-limit-stable, r=sfackler
authorbors <bors@rust-lang.org>
Wed, 11 Apr 2018 06:03:46 +0000 (06:03 +0000)
committerbors <bors@rust-lang.org>
Wed, 11 Apr 2018 06:03:46 +0000 (06:03 +0000)
Stabilize take_set_limit

Fixes #42781

357 files changed:
.travis.yml
appveyor.yml
config.toml.example
src/Cargo.lock
src/bootstrap/bin/rustc.rs
src/bootstrap/bootstrap.py
src/bootstrap/builder.rs
src/bootstrap/compile.rs
src/bootstrap/config.rs
src/bootstrap/configure.py
src/bootstrap/dist.rs
src/bootstrap/doc.rs
src/bootstrap/flags.rs
src/bootstrap/install.rs
src/bootstrap/lib.rs
src/bootstrap/sanity.rs
src/bootstrap/tool.rs
src/build_helper/lib.rs
src/ci/docker/dist-various-1/Dockerfile
src/ci/docker/run.sh
src/ci/docker/x86_64-gnu-incremental/Dockerfile [deleted file]
src/ci/run.sh
src/doc/index.md
src/liballoc/Cargo.toml
src/liballoc/benches/lib.rs
src/liballoc/boxed.rs
src/liballoc/lib.rs
src/liballoc/tests/lib.rs
src/liballoc/vec.rs
src/liballoc_jemalloc/Cargo.toml
src/liballoc_jemalloc/lib.rs
src/liballoc_system/Cargo.toml
src/liballoc_system/lib.rs
src/libarena/lib.rs
src/libcore/ascii.rs
src/libcore/benches/lib.rs
src/libcore/cmp.rs
src/libcore/intrinsics.rs
src/libcore/iter/range.rs
src/libcore/lib.rs
src/libcore/macros.rs
src/libcore/mem.rs
src/libcore/panic.rs
src/libcore/panicking.rs
src/libcore/sync/atomic.rs
src/libcore/tests/atomic.rs
src/libcore/tests/lib.rs
src/libfmt_macros/lib.rs
src/libgraphviz/lib.rs
src/libpanic_abort/Cargo.toml
src/libpanic_abort/lib.rs
src/libpanic_unwind/Cargo.toml
src/libpanic_unwind/gcc.rs
src/libpanic_unwind/lib.rs
src/libpanic_unwind/seh64_gnu.rs
src/libpanic_unwind/windows.rs
src/libproc_macro/lib.rs
src/libproc_macro/quote.rs
src/libprofiler_builtins/Cargo.toml
src/librustc/benches/lib.rs
src/librustc/dep_graph/dep_node.rs
src/librustc/diagnostics.rs
src/librustc/hir/check_attr.rs
src/librustc/hir/lowering.rs
src/librustc/hir/map/def_collector.rs
src/librustc/hir/map/mod.rs
src/librustc/ich/impls_hir.rs
src/librustc/ich/impls_syntax.rs
src/librustc/ich/impls_ty.rs
src/librustc/infer/type_variable.rs
src/librustc/lib.rs
src/librustc/lint/context.rs
src/librustc/lint/levels.rs
src/librustc/lint/mod.rs
src/librustc/middle/exported_symbols.rs
src/librustc/middle/mem_categorization.rs
src/librustc/middle/region.rs
src/librustc/middle/weak_lang_items.rs
src/librustc/mir/cache.rs
src/librustc/mir/mod.rs
src/librustc/session/config.rs
src/librustc/traits/error_reporting.rs
src/librustc/traits/mod.rs
src/librustc/traits/on_unimplemented.rs
src/librustc/traits/select.rs
src/librustc/traits/structural_impls.rs
src/librustc/ty/context.rs
src/librustc/ty/maps/config.rs
src/librustc/ty/maps/job.rs [new file with mode: 0644]
src/librustc/ty/maps/mod.rs
src/librustc/ty/maps/on_disk_cache.rs
src/librustc/ty/maps/plumbing.rs
src/librustc/ty/mod.rs
src/librustc/ty/steal.rs
src/librustc/ty/sty.rs
src/librustc/ty/util.rs
src/librustc/util/common.rs
src/librustc_allocator/lib.rs
src/librustc_apfloat/lib.rs
src/librustc_apfloat/tests/ieee.rs
src/librustc_asan/Cargo.toml
src/librustc_back/lib.rs
src/librustc_back/target/apple_base.rs
src/librustc_back/target/mod.rs
src/librustc_back/target/msp430_none_elf.rs
src/librustc_back/target/thumb_base.rs
src/librustc_back/target/windows_base.rs
src/librustc_back/target/windows_msvc_base.rs
src/librustc_borrowck/borrowck/mod.rs
src/librustc_borrowck/lib.rs
src/librustc_const_math/lib.rs
src/librustc_data_structures/lib.rs
src/librustc_data_structures/sync.rs
src/librustc_driver/lib.rs
src/librustc_driver/pretty.rs
src/librustc_driver/test.rs
src/librustc_errors/lib.rs
src/librustc_incremental/assert_dep_graph.rs
src/librustc_incremental/lib.rs
src/librustc_lint/builtin.rs
src/librustc_lint/lib.rs
src/librustc_lint/unused.rs
src/librustc_llvm/lib.rs
src/librustc_lsan/Cargo.toml
src/librustc_metadata/creader.rs
src/librustc_metadata/cstore_impl.rs
src/librustc_metadata/decoder.rs
src/librustc_metadata/encoder.rs
src/librustc_metadata/lib.rs
src/librustc_metadata/locator.rs
src/librustc_metadata/schema.rs
src/librustc_mir/borrow_check/error_reporting.rs
src/librustc_mir/borrow_check/mod.rs
src/librustc_mir/build/mod.rs
src/librustc_mir/dataflow/impls/borrows.rs
src/librustc_mir/dataflow/mod.rs
src/librustc_mir/hair/pattern/mod.rs
src/librustc_mir/interpret/eval_context.rs
src/librustc_mir/lib.rs
src/librustc_mir/monomorphize/collector.rs
src/librustc_mir/monomorphize/partitioning.rs
src/librustc_mir/util/borrowck_errors.rs
src/librustc_mir/util/collect_writes.rs [new file with mode: 0644]
src/librustc_mir/util/mod.rs
src/librustc_msan/Cargo.toml
src/librustc_passes/ast_validation.rs
src/librustc_passes/lib.rs
src/librustc_platform_intrinsics/lib.rs
src/librustc_plugin/lib.rs
src/librustc_privacy/lib.rs
src/librustc_resolve/build_reduced_graph.rs
src/librustc_resolve/lib.rs
src/librustc_resolve/macros.rs
src/librustc_resolve/resolve_imports.rs
src/librustc_save_analysis/dump_visitor.rs
src/librustc_save_analysis/lib.rs
src/librustc_save_analysis/sig.rs
src/librustc_traits/lib.rs
src/librustc_traits/lowering.rs
src/librustc_trans/back/link.rs
src/librustc_trans/back/symbol_export.rs
src/librustc_trans/back/write.rs
src/librustc_trans/base.rs
src/librustc_trans/callee.rs
src/librustc_trans/debuginfo/gdb.rs
src/librustc_trans/debuginfo/mod.rs
src/librustc_trans/lib.rs
src/librustc_trans_utils/lib.rs
src/librustc_trans_utils/symbol_names.rs
src/librustc_tsan/Cargo.toml
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/intrinsic.rs
src/librustc_typeck/check/method/confirm.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/op.rs
src/librustc_typeck/check/regionck.rs
src/librustc_typeck/check/wfcheck.rs
src/librustc_typeck/collect.rs
src/librustc_typeck/diagnostics.rs
src/librustc_typeck/impl_wf_check.rs
src/librustc_typeck/lib.rs
src/librustdoc/clean/auto_trait.rs
src/librustdoc/clean/cfg.rs
src/librustdoc/clean/mod.rs
src/librustdoc/html/render.rs
src/librustdoc/html/static/main.js
src/librustdoc/html/static/rustdoc.css
src/librustdoc/html/static/storage.js
src/librustdoc/html/static/themes/dark.css
src/librustdoc/html/static/themes/light.css
src/librustdoc/lib.rs
src/librustdoc/markdown.rs
src/librustdoc/test.rs
src/libserialize/lib.rs
src/libstd/env.rs
src/libstd/lib.rs
src/libstd/panic.rs
src/libstd/panicking.rs
src/libstd/process.rs
src/libstd/sys/unix/process/process_common.rs
src/libstd/sys/windows/pipe.rs
src/libstd/sys/windows/process.rs
src/libstd_unicode/Cargo.toml
src/libstd_unicode/lib.rs
src/libsyntax/ast.rs
src/libsyntax/attr.rs
src/libsyntax/config.rs
src/libsyntax/ext/base.rs
src/libsyntax/ext/build.rs
src/libsyntax/ext/derive.rs
src/libsyntax/ext/expand.rs
src/libsyntax/ext/placeholders.rs
src/libsyntax/ext/quote.rs
src/libsyntax/ext/tt/macro_parser.rs
src/libsyntax/ext/tt/macro_rules.rs
src/libsyntax/ext/tt/quoted.rs
src/libsyntax/ext/tt/transcribe.rs
src/libsyntax/feature_gate.rs
src/libsyntax/fold.rs
src/libsyntax/lib.rs
src/libsyntax/parse/attr.rs
src/libsyntax/parse/lexer/mod.rs
src/libsyntax/parse/mod.rs
src/libsyntax/parse/parser.rs
src/libsyntax/parse/token.rs
src/libsyntax/print/pprust.rs
src/libsyntax/std_inject.rs
src/libsyntax/test.rs
src/libsyntax/util/node_count.rs
src/libsyntax/visit.rs
src/libsyntax_ext/assert.rs
src/libsyntax_ext/cfg.rs
src/libsyntax_ext/concat.rs
src/libsyntax_ext/concat_idents.rs
src/libsyntax_ext/deriving/clone.rs
src/libsyntax_ext/deriving/custom.rs
src/libsyntax_ext/deriving/debug.rs
src/libsyntax_ext/deriving/encodable.rs
src/libsyntax_ext/deriving/generic/mod.rs
src/libsyntax_ext/deriving/generic/ty.rs
src/libsyntax_ext/env.rs
src/libsyntax_ext/format.rs
src/libsyntax_ext/lib.rs
src/libsyntax_ext/proc_macro_registrar.rs
src/libsyntax_pos/hygiene.rs
src/libsyntax_pos/lib.rs
src/libsyntax_pos/symbol.rs
src/libterm/lib.rs
src/libtest/lib.rs
src/libunwind/Cargo.toml
src/libunwind/lib.rs
src/libunwind/libunwind.rs
src/rustc/compiler_builtins_shim/Cargo.toml
src/rustc/dlmalloc_shim/Cargo.toml
src/rustc/libc_shim/Cargo.toml
src/rustc/rustc.rs
src/stage0.txt
src/test/codegen-units/partitioning/auxiliary/shared_generics_aux.rs [new file with mode: 0644]
src/test/codegen-units/partitioning/extern-generic.rs
src/test/codegen-units/partitioning/shared-generics.rs [new file with mode: 0644]
src/test/codegen/local-generics-in-exe-internalized.rs [new file with mode: 0644]
src/test/compile-fail-fulldeps/auxiliary/macro_crate_test.rs
src/test/compile-fail-fulldeps/proc-macro/auxiliary/attributes-included.rs
src/test/compile-fail-fulldeps/proc-macro/auxiliary/test-macros.rs [new file with mode: 0644]
src/test/compile-fail-fulldeps/proc-macro/macros-in-extern.rs [new file with mode: 0644]
src/test/compile-fail/attrs-with-no-formal-in-generics-1.rs
src/test/compile-fail/attrs-with-no-formal-in-generics-2.rs
src/test/compile-fail/borrowck/borrowck-issue-14498.rs
src/test/compile-fail/borrowck/borrowck-issue-48962.rs [new file with mode: 0644]
src/test/compile-fail/macros-in-extern.rs [new file with mode: 0644]
src/test/compile-fail/rfc-2008-non-exhaustive/invalid-attribute.rs [new file with mode: 0644]
src/test/compile-fail/synthetic-param.rs
src/test/incremental/issue-49595/auxiliary/lit_a.rs [new file with mode: 0644]
src/test/incremental/issue-49595/auxiliary/lit_b.rs [new file with mode: 0644]
src/test/incremental/issue-49595/issue_49595.rs [new file with mode: 0644]
src/test/mir-opt/end_region_destruction_extents_1.rs
src/test/parse-fail/duplicate-visibility.rs
src/test/parse-fail/extern-no-fn.rs
src/test/run-fail/rfc-1937-termination-trait/termination-trait-for-box-dyn-error.rs [new file with mode: 0644]
src/test/run-fail/rfc-1937-termination-trait/termination-trait-for-str.rs [new file with mode: 0644]
src/test/run-make-fulldeps/resolve-rename/Makefile [new file with mode: 0644]
src/test/run-make-fulldeps/resolve-rename/bar.rs [new file with mode: 0644]
src/test/run-make-fulldeps/resolve-rename/baz.rs [new file with mode: 0644]
src/test/run-make-fulldeps/resolve-rename/foo.rs [new file with mode: 0644]
src/test/run-make-fulldeps/std-core-cycle/Makefile
src/test/run-make-fulldeps/symbol-visibility/Makefile
src/test/run-make-fulldeps/symbol-visibility/a_rust_dylib.rs
src/test/run-make-fulldeps/symbol-visibility/an_rlib.rs
src/test/run-pass-fulldeps/auxiliary/cond_plugin.rs
src/test/run-pass-fulldeps/auxiliary/macro_crate_test.rs
src/test/run-pass-fulldeps/auxiliary/proc_macro_def.rs
src/test/run-pass-fulldeps/pprust-expr-roundtrip.rs
src/test/run-pass-fulldeps/proc-macro/auxiliary/count_compound_ops.rs
src/test/run-pass-fulldeps/proc-macro/auxiliary/negative-token.rs
src/test/run-pass-fulldeps/proc-macro/auxiliary/span-api-tests.rs
src/test/run-pass-fulldeps/proc-macro/auxiliary/test-macros.rs [new file with mode: 0644]
src/test/run-pass-fulldeps/proc-macro/macros-in-extern.rs [new file with mode: 0644]
src/test/run-pass/attr-on-generic-formals.rs
src/test/run-pass/auxiliary/dropck_eyepatch_extern_crate.rs
src/test/run-pass/defaults-well-formedness.rs
src/test/run-pass/dropck-eyepatch-reorder.rs
src/test/run-pass/dropck-eyepatch.rs
src/test/run-pass/issue-48962.rs [new file with mode: 0644]
src/test/run-pass/macros-in-extern.rs [new file with mode: 0644]
src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-box-dyn-error.rs [new file with mode: 0644]
src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-str.rs [new file with mode: 0644]
src/test/rustdoc/all.rs [new file with mode: 0644]
src/test/rustdoc/unneeded-trait-implementations-title.rs [new file with mode: 0644]
src/test/ui-fulldeps/proc-macro/auxiliary/parent-source-spans.rs
src/test/ui-fulldeps/proc-macro/auxiliary/three-equals.rs
src/test/ui/borrowck/two-phase-multi-mut.rs [new file with mode: 0644]
src/test/ui/borrowck/two-phase-multi-mut.stderr [new file with mode: 0644]
src/test/ui/borrowck/two-phase-multiple-activations.rs [new file with mode: 0644]
src/test/ui/chalkify/lower_trait.rs
src/test/ui/chalkify/lower_trait.stderr
src/test/ui/chalkify/lower_trait_higher_rank.rs [new file with mode: 0644]
src/test/ui/chalkify/lower_trait_higher_rank.stderr [new file with mode: 0644]
src/test/ui/chalkify/lower_trait_where_clause.rs [new file with mode: 0644]
src/test/ui/chalkify/lower_trait_where_clause.stderr [new file with mode: 0644]
src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.rs [new file with mode: 0644]
src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr [new file with mode: 0644]
src/test/ui/dropck/auxiliary/dropck_eyepatch_extern_crate.rs
src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.rs
src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr
src/test/ui/dropck/dropck-eyepatch-reorder.rs
src/test/ui/dropck/dropck-eyepatch-reorder.stderr
src/test/ui/dropck/dropck-eyepatch.rs
src/test/ui/dropck/dropck-eyepatch.stderr
src/test/ui/feature-gate-custom_attribute2.rs
src/test/ui/feature-gate-custom_attribute2.stderr
src/test/ui/feature-gate-generic_param_attrs.rs [deleted file]
src/test/ui/feature-gate-generic_param_attrs.stderr [deleted file]
src/test/ui/feature-gate-macros_in_extern.rs [new file with mode: 0644]
src/test/ui/feature-gate-macros_in_extern.stderr [new file with mode: 0644]
src/test/ui/feature-gate-may-dangle.rs
src/test/ui/feature-gate-may-dangle.stderr
src/test/ui/feature-gate-non_ascii_idents.stderr
src/test/ui/generic-param-attrs.rs [new file with mode: 0644]
src/test/ui/impl-trait/universal-issue-48703.rs [new file with mode: 0644]
src/test/ui/impl-trait/universal-issue-48703.stderr [new file with mode: 0644]
src/test/ui/issue-48728.rs [new file with mode: 0644]
src/test/ui/issue-48728.stderr [new file with mode: 0644]
src/test/ui/nll/drop-may-dangle.rs
src/test/ui/nll/drop-no-may-dangle.rs
src/test/ui/nll/drop-no-may-dangle.stderr
src/test/ui/nll/issue-47388.rs [new file with mode: 0644]
src/test/ui/nll/issue-47388.stderr [new file with mode: 0644]
src/test/ui/rfc-2005-default-binding-mode/borrowck-issue-49631.rs [new file with mode: 0644]
src/test/ui/rfc-2005-default-binding-mode/borrowck-issue-49631.stderr [new file with mode: 0644]
src/tools/build-manifest/src/main.rs
src/tools/compiletest/src/common.rs
src/tools/compiletest/src/main.rs
src/tools/compiletest/src/runtest.rs
src/tools/rustbook/Cargo.toml
src/tools/rustdoc/main.rs
src/tools/rustfmt
src/tools/tidy/src/lib.rs

index f465ba422817448bcaa8d98efc24c95b5c575a12..f36ad67b111033ba47ae675212622fbc20ad6c31 100644 (file)
@@ -21,7 +21,7 @@ matrix:
     # "alternate" deployments, these are "nightlies" but have LLVM assertions
     # turned on, they're deployed to a different location primarily for
     # additional testing.
-    - env: IMAGE=dist-x86_64-linux DEPLOY_ALT=1
+    - env: IMAGE=dist-x86_64-linux DEPLOY_ALT=1 CI_JOB_NAME=dist-x86_64-linux-alt
       if: branch = try OR branch = auto
 
     - env: >
@@ -33,6 +33,7 @@ matrix:
         MACOSX_DEPLOYMENT_TARGET=10.7
         NO_LLVM_ASSERTIONS=1
         NO_DEBUG_ASSERTIONS=1
+        CI_JOB_NAME=dist-x86_64-apple-alt
       os: osx
       osx_image: xcode9.3-moar
       if: branch = auto
@@ -53,6 +54,7 @@ matrix:
         MACOSX_STD_DEPLOYMENT_TARGET=10.7
         NO_LLVM_ASSERTIONS=1
         NO_DEBUG_ASSERTIONS=1
+        CI_JOB_NAME=x86_64-apple
       os: osx
       osx_image: xcode9.3-moar
       if: branch = auto
@@ -66,6 +68,7 @@ matrix:
         MACOSX_STD_DEPLOYMENT_TARGET=10.7
         NO_LLVM_ASSERTIONS=1
         NO_DEBUG_ASSERTIONS=1
+        CI_JOB_NAME=i686-apple
       os: osx
       osx_image: xcode9.3-moar
       if: branch = auto
@@ -85,6 +88,7 @@ matrix:
         MACOSX_DEPLOYMENT_TARGET=10.7
         NO_LLVM_ASSERTIONS=1
         NO_DEBUG_ASSERTIONS=1
+        CI_JOB_NAME=dist-i686-apple
       os: osx
       osx_image: xcode9.3-moar
       if: branch = auto
@@ -98,6 +102,7 @@ matrix:
         MACOSX_DEPLOYMENT_TARGET=10.7
         NO_LLVM_ASSERTIONS=1
         NO_DEBUG_ASSERTIONS=1
+        CI_JOB_NAME=dist-x86_64-apple
       os: osx
       osx_image: xcode9.3-moar
       if: branch = auto
@@ -171,8 +176,6 @@ matrix:
       if: branch = auto
     - env: IMAGE=x86_64-gnu-distcheck
       if: branch = auto
-    - env: IMAGE=x86_64-gnu-incremental
-      if: branch = auto
 
     - stage: publish toolstate
       if: branch = master AND type = push
index 09c6fca5d02afc8f3f46bf8b4ea46eb5c9f2a958..a15f3dd8d5cac2b957daab5e0ee6fa91a14c9176 100644 (file)
@@ -18,25 +18,31 @@ environment:
   - MSYS_BITS: 64
     RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler
     SCRIPT: python x.py test
+    CI_JOB_NAME: x86_64-msvc
   - MSYS_BITS: 32
     RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc
     SCRIPT: make appveyor-subset-1
+    CI_JOB_NAME: i686-msvc-1
   - MSYS_BITS: 32
     RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc
     SCRIPT: make appveyor-subset-2
+    CI_JOB_NAME: i686-msvc-2
 
   # MSVC aux tests
   - MSYS_BITS: 64
     RUST_CHECK_TARGET: check-aux EXCLUDE_CARGO=1
     RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc
+    CI_JOB_NAME: x86_64-msvc-aux
   - MSYS_BITS: 64
     SCRIPT: python x.py test src/tools/cargotest src/tools/cargo
     RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc
+    CI_JOB_NAME: x86_64-msvc-cargo
 
   # MSVC tools tests
   - MSYS_BITS: 64
     SCRIPT: src/ci/docker/x86_64-gnu-tools/checktools.sh x.py /tmp/toolstates.json windows
     RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --save-toolstates=/tmp/toolstates.json --enable-test-miri
+    CI_JOB_NAME: x86_64-msvc-tools
 
   # 32/64-bit MinGW builds.
   #
@@ -57,18 +63,21 @@ environment:
     MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror
     MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z
     MINGW_DIR: mingw32
+    CI_JOB_NAME: i686-mingw-1
   - MSYS_BITS: 32
     RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu
     SCRIPT: make appveyor-subset-2
     MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror
     MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z
     MINGW_DIR: mingw32
+    CI_JOB_NAME: i686-mingw-2
   - MSYS_BITS: 64
     SCRIPT: python x.py test
     RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu
     MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror
     MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z
     MINGW_DIR: mingw64
+    CI_JOB_NAME: x86_64-mingw
 
   # 32/64 bit MSVC and GNU deployment
   - RUST_CONFIGURE_ARGS: >
@@ -77,6 +86,7 @@ environment:
       --enable-profiler
     SCRIPT: python x.py dist
     DEPLOY: 1
+    CI_JOB_NAME: dist-x86_64-msvc
   - RUST_CONFIGURE_ARGS: >
       --build=i686-pc-windows-msvc
       --target=i586-pc-windows-msvc
@@ -84,6 +94,7 @@ environment:
       --enable-profiler
     SCRIPT: python x.py dist
     DEPLOY: 1
+    CI_JOB_NAME: dist-i686-msvc
   - MSYS_BITS: 32
     RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu --enable-full-tools
     SCRIPT: python x.py dist
@@ -91,6 +102,7 @@ environment:
     MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z
     MINGW_DIR: mingw32
     DEPLOY: 1
+    CI_JOB_NAME: dist-i686-mingw
   - MSYS_BITS: 64
     SCRIPT: python x.py dist
     RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu --enable-full-tools
@@ -98,12 +110,14 @@ environment:
     MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z
     MINGW_DIR: mingw64
     DEPLOY: 1
+    CI_JOB_NAME: dist-x86_64-mingw
 
   # "alternate" deployment, see .travis.yml for more info
   - MSYS_BITS: 64
     RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-extended --enable-profiler
     SCRIPT: python x.py dist
     DEPLOY_ALT: 1
+    CI_JOB_NAME: dist-x86_64-msvc-alt
 
 matrix:
   fast_finish: true
index 9dd3002506e41cbe333d4cc8051dcf9d62071eb7..68bc7dfe720fe11f20313c299b4dc4bc44318b5d 100644 (file)
 # rustc to execute.
 #lld = false
 
+# Whether to deny warnings in crates
+#deny-warnings = true
+
 # =============================================================================
 # Options for specific targets
 #
index 2f77d4125ab0e758cdd34e7e7111debcec200613..e7896d247b4c93cae09f1ad64373590f75bb6ead 100644 (file)
@@ -10,6 +10,7 @@ dependencies = [
 name = "alloc"
 version = "0.0.0"
 dependencies = [
+ "compiler_builtins 0.0.0",
  "core 0.0.0",
  "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "std_unicode 0.0.0",
@@ -23,6 +24,7 @@ dependencies = [
  "alloc_system 0.0.0",
  "build_helper 0.1.0",
  "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "compiler_builtins 0.0.0",
  "core 0.0.0",
  "libc 0.0.0",
 ]
@@ -32,11 +34,25 @@ name = "alloc_system"
 version = "0.0.0"
 dependencies = [
  "alloc 0.0.0",
+ "compiler_builtins 0.0.0",
  "core 0.0.0",
  "dlmalloc 0.0.0",
  "libc 0.0.0",
 ]
 
+[[package]]
+name = "ammonia"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "html5ever 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tendril 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "ansi_term"
 version = "0.11.0"
@@ -491,6 +507,14 @@ dependencies = [
  "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "debug_unreachable"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "deglob"
 version = "0.1.0"
@@ -520,6 +544,7 @@ name = "dlmalloc"
 version = "0.0.0"
 dependencies = [
  "alloc 0.0.0",
+ "compiler_builtins 0.0.0",
  "core 0.0.0",
 ]
 
@@ -533,6 +558,20 @@ name = "either"
 version = "1.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "elasticlunr-rs"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
+ "phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "ena"
 version = "0.9.2"
@@ -681,6 +720,15 @@ name = "fuchsia-zircon-sys"
 version = "0.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "futf"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "debug_unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "futures"
 version = "0.1.20"
@@ -767,6 +815,18 @@ dependencies = [
  "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "html5ever"
+version = "0.22.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "markup5ever 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "humantime"
 version = "1.1.1"
@@ -920,6 +980,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 name = "libc"
 version = "0.0.0"
 dependencies = [
+ "compiler_builtins 0.0.0",
  "core 0.0.0",
 ]
 
@@ -1005,6 +1066,31 @@ dependencies = [
  "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "mac"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "maplit"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "markup5ever"
+version = "0.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
+ "phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "string_cache 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "string_cache_codegen 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tendril 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "matches"
 version = "0.1.6"
@@ -1015,8 +1101,10 @@ name = "mdbook"
 version = "0.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
+ "ammonia 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "chrono 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "elasticlunr-rs 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "handlebars 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1171,6 +1259,7 @@ dependencies = [
 name = "panic_abort"
 version = "0.0.0"
 dependencies = [
+ "compiler_builtins 0.0.0",
  "core 0.0.0",
  "libc 0.0.0",
 ]
@@ -1180,6 +1269,7 @@ name = "panic_unwind"
 version = "0.0.0"
 dependencies = [
  "alloc 0.0.0",
+ "compiler_builtins 0.0.0",
  "core 0.0.0",
  "libc 0.0.0",
  "unwind 0.0.0",
@@ -1234,11 +1324,50 @@ dependencies = [
  "ordermap 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "phf"
+version = "0.7.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "phf_codegen"
+version = "0.7.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "phf_generator 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
+ "phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "phf_generator"
+version = "0.7.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "phf_shared"
+version = "0.7.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "pkg-config"
 version = "0.3.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "precomputed-hash"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "pretty_assertions"
 version = "0.5.1"
@@ -1279,6 +1408,7 @@ name = "profiler_builtins"
 version = "0.0.0"
 dependencies = [
  "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "compiler_builtins 0.0.0",
  "core 0.0.0",
 ]
 
@@ -1345,6 +1475,16 @@ dependencies = [
  "nibble_vec 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "rand"
+version = "0.3.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "rand"
 version = "0.4.2"
@@ -1552,7 +1692,7 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-rustc_cratesio_shim"
-version = "73.0.0"
+version = "91.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1561,7 +1701,7 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-rustc_data_structures"
-version = "73.0.0"
+version = "91.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1569,20 +1709,20 @@ dependencies = [
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot_core 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 73.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 91.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rustc-ap-rustc_errors"
-version = "73.0.0"
+version = "91.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_data_structures 73.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 73.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-syntax_pos 73.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 91.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 91.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax_pos 91.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1590,32 +1730,32 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-serialize"
-version = "73.0.0"
+version = "91.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "rustc-ap-syntax"
-version = "73.0.0"
+version = "91.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_cratesio_shim 73.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_data_structures 73.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_errors 73.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 73.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-syntax_pos 73.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_cratesio_shim 91.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 91.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_errors 91.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 91.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax_pos 91.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rustc-ap-syntax_pos"
-version = "73.0.0"
+version = "91.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "rustc-ap-rustc_data_structures 73.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 73.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 91.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 91.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1665,6 +1805,7 @@ dependencies = [
  "alloc_system 0.0.0",
  "build_helper 0.1.0",
  "cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
+ "compiler_builtins 0.0.0",
  "core 0.0.0",
 ]
 
@@ -1810,6 +1951,7 @@ dependencies = [
  "alloc_system 0.0.0",
  "build_helper 0.1.0",
  "cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
+ "compiler_builtins 0.0.0",
  "core 0.0.0",
 ]
 
@@ -1859,6 +2001,7 @@ dependencies = [
  "alloc_system 0.0.0",
  "build_helper 0.1.0",
  "cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
+ "compiler_builtins 0.0.0",
  "core 0.0.0",
 ]
 
@@ -1998,6 +2141,7 @@ dependencies = [
  "alloc_system 0.0.0",
  "build_helper 0.1.0",
  "cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
+ "compiler_builtins 0.0.0",
  "core 0.0.0",
 ]
 
@@ -2050,7 +2194,7 @@ dependencies = [
  "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-syntax 73.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax 91.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2159,6 +2303,11 @@ name = "shlex"
 version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "siphasher"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "smallvec"
 version = "0.6.0"
@@ -2206,9 +2355,40 @@ dependencies = [
 name = "std_unicode"
 version = "0.0.0"
 dependencies = [
+ "compiler_builtins 0.0.0",
  "core 0.0.0",
 ]
 
+[[package]]
+name = "string_cache"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "debug_unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
+ "precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
+ "string_cache_codegen 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "string_cache_codegen"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "phf_generator 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
+ "phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "string_cache_shared"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "strsim"
 version = "0.7.0"
@@ -2365,6 +2545,16 @@ dependencies = [
  "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "tendril"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "futf 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "utf-8 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "term"
 version = "0.0.0"
@@ -2520,6 +2710,14 @@ name = "unicode-xid"
 version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "unreachable"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "unreachable"
 version = "1.0.0"
@@ -2540,6 +2738,7 @@ dependencies = [
 name = "unwind"
 version = "0.0.0"
 dependencies = [
+ "compiler_builtins 0.0.0",
  "core 0.0.0",
  "libc 0.0.0",
 ]
@@ -2572,6 +2771,11 @@ dependencies = [
  "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "utf-8"
+version = "0.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "utf8-ranges"
 version = "1.0.0"
@@ -2665,6 +2869,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [metadata]
 "checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4"
+"checksum ammonia 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fd4c682378117e4186a492b2252b9537990e1617f44aed9788b9a1149de45477"
 "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
 "checksum ar 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "35c7a5669cb64f085739387e1308b74e6d44022464b7f1b63bbd4ceb6379ec31"
 "checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef"
@@ -2695,11 +2900,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum crypto-hash 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "09de9ee0fc255ace04c7fa0763c9395a945c37c8292bb554f8d48361d1dcf1b4"
 "checksum curl 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b70fd6394677d3c0e239ff4be6f2b3176e171ffd1c23ffdc541e78dea2b8bb5e"
 "checksum curl-sys 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f46e49c7125131f5afaded06944d6888b55cbdf8eba05dae73c954019b907961"
+"checksum debug_unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9a032eac705ca39214d169f83e3d3da290af06d8d1d344d1baad2fd002dca4b3"
 "checksum derive-new 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6fcb923bab47a948f1b01cec2f758fdebba95c9ebc255458654b2b88efe59d71"
 "checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a"
 "checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198"
 "checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab"
 "checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0"
+"checksum elasticlunr-rs 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "19ab5f8db0ffb76b5d87454566ceb502c3650e29057c053f93e884d3b884e344"
 "checksum ena 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f8b449f3b18c89d2dbe40548d2ee4fa58ea0a08b761992da6ecb9788e4688834"
 "checksum endian-type 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d"
 "checksum enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be4551092f4d519593039259a9ed8daedf0da12e5109c5280338073eaeb81180"
@@ -2716,6 +2923,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213"
 "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
 "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
+"checksum futf 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "51f93f3de6ba1794dcd5810b3546d004600a59a98266487c8407bc4b24e398f3"
 "checksum futures 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "0c5a3176836efa0b37f0e321b86672dfada1564aeb516fbed67b7c24050a0263"
 "checksum getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "b900c08c1939860ce8b54dc6a89e26e00c04c380fd0e09796799bd7f12861e05"
 "checksum git2 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f41c0035c37ec11ed3f1e1946a76070b0c740393687e9a9c7612f6a709036b3"
@@ -2725,6 +2933,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum handlebars 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07af2ff31f66f39a5c8b8b8a5dc02734a453110146763e3a2323f4931a915a76"
 "checksum hex 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "459d3cf58137bb02ad4adeef5036377ff59f066dbb82517b7192e3a5462a2abc"
 "checksum home 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8f94f6fbdc000a6eba0c8cf08632b2091bb59141d36ac321a2a96d6365e5e4dc"
+"checksum html5ever 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e579ac8647178ab915d400d7d22938bda5cd351c6c62e1c294d56884ccfc75fe"
 "checksum humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0484fda3e7007f2a4a0d9c3a703ca38c71c54c55602ce4660c419fd32e188c9e"
 "checksum idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "014b298351066f1512874135335d62a789ffe78a9974f94b43ed5621951eaf7d"
 "checksum if_chain 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "61bb90bdd39e3af69b0172dfc6130f6cd6332bf040fbb9bdd4401d37adbd48b8"
@@ -2748,6 +2957,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "89f010e843f2b1a31dbd316b3b8d443758bc634bed37aabade59c686d644e0a2"
 "checksum log_settings 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3d382732ea0fbc09790c4899db3255bdea0fc78b54bf234bd18a63bb603915b6"
 "checksum lzma-sys 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c1b93b78f89e8737dac81837fc8f5521ac162abcba902e1a3db949d55346d1da"
+"checksum mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
+"checksum maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08cbb6b4fef96b6d77bfc40ec491b1690c779e77b05cd9f07f787ed376fd4c43"
+"checksum markup5ever 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfedc97d5a503e96816d10fedcd5b42f760b2e525ce2f7ec71f6a41780548475"
 "checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376"
 "checksum mdbook 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "326d0861da5681a13c19a00952a56c254dd04f00eb944e506fdb36e93ae6f1ca"
 "checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d"
@@ -2772,7 +2984,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum pest 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0fce5d8b5cc33983fc74f78ad552b5522ab41442c4ca91606e4236eb4b5ceefc"
 "checksum pest_derive 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "ab94faafeb93f4c5e3ce81ca0e5a779529a602ad5d09ae6d21996bfb8b6a52bf"
 "checksum petgraph 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "8b30dc85588cd02b9b76f5e386535db546d21dc68506cff2abebee0b6445e8e4"
+"checksum phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "cb325642290f28ee14d8c6201159949a872f220c62af6e110a56ea914fbe42fc"
+"checksum phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "d62594c0bb54c464f633175d502038177e90309daf2e0158be42ed5f023ce88f"
+"checksum phf_generator 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "6b07ffcc532ccc85e3afc45865469bf5d9e4ef5bfcf9622e3cfe80c2d275ec03"
+"checksum phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "07e24b0ca9643bdecd0632f2b3da6b1b89bbb0030e0b992afc1113b23a7bc2f2"
 "checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903"
+"checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
 "checksum pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a029430f0d744bc3d15dd474d591bed2402b645d024583082b9f63bb936dac6"
 "checksum proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cd07deb3c6d1d9ff827999c7f9b04cdfd66b1b17ae508e14fe47b620f2282ae0"
 "checksum proc-macro2 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "388d7ea47318c5ccdeb9ba6312cee7d3f65dd2804be8580a170fce410d50b786"
@@ -2784,6 +3001,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum quote 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7b0ff51282f28dc1b53fd154298feaa2e77c5ea0dba68e1fd8b03b72fbe13d2a"
 "checksum racer 2.0.13 (registry+https://github.com/rust-lang/crates.io-index)" = "40d44bc30fc8d403b665286b2c9a83466ddbf69297668fb02b785c3e58eb8e0d"
 "checksum radix_trie 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "03d0d770481e8af620ca61d3d304bf014f965d7f78e923dc58545e6a545070a9"
+"checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1"
 "checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5"
 "checksum rayon 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80e811e76f1dbf68abf87a759083d34600017fc4e10b6bd5ad84a700f9dba4b1"
 "checksum rayon-core 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9d24ad214285a7729b174ed6d3bcfcb80177807f959d95fafd5bfc5c4f201ac8"
@@ -2798,12 +3016,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum rls-rustc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "885f66b92757420572cbb02e033d4a9558c7413ca9b7ac206f28fd58ffdb44ea"
 "checksum rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d7c7046dc6a92f2ae02ed302746db4382e75131b9ce20ce967259f6b5867a6a"
 "checksum rls-vfs 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "be231e1e559c315bc60ced5ad2cc2d7a9c208ed7d4e2c126500149836fda19bb"
-"checksum rustc-ap-rustc_cratesio_shim 73.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "421262e22426c06306e46057a75048f883dbc43886f78dbe1e750397a9c9b8e6"
-"checksum rustc-ap-rustc_data_structures 73.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8460c1207f9abb48a9720aee8be418bcfac018b6eee7b740b98a410e7799d24a"
-"checksum rustc-ap-rustc_errors 73.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad2077469162e52fcd84543334e18632088b9e342fe54e3b78c37d7077d09714"
-"checksum rustc-ap-serialize 73.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "69943901ae255dca5f63faeae2ff08b402d34a56d1eb50d34fbff6e83e6ace60"
-"checksum rustc-ap-syntax 73.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a44363359a43df753e26a4d4fef72720af183de635ebae8699686cb5d5de813"
-"checksum rustc-ap-syntax_pos 73.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "413f464657e8d5f3864de308dba1867526f21a44809b6f338b34e8c0caf88fb0"
+"checksum rustc-ap-rustc_cratesio_shim 91.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0dd7571780b3232786f538b4e72f4a8d7fcffbb4a951d3861e18142d3cf2f0ac"
+"checksum rustc-ap-rustc_data_structures 91.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ae9ebbcbe26ea53eb0f3162c109892cd69ebb5efc986f3a21bce4891adf628f"
+"checksum rustc-ap-rustc_errors 91.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7c8385e5cf62344a4c6b2446723da0a82dad7ec97b2988b6494a197f231fc4b9"
+"checksum rustc-ap-serialize 91.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d08a7e3ce1d87fda88fdf51bdfec5886f42bfd93ce7fcf1d69fcd0a23d1ab4ea"
+"checksum rustc-ap-syntax 91.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "06b7a6da9b99e9a2e31f9325216dc5d477eb5d9bd88c7bb05b5e97e88d06d675"
+"checksum rustc-ap-syntax_pos 91.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "582d30a1308f6598b3636bc244efacd8551c825ed6be2aa594257fbf772d1161"
 "checksum rustc-demangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11fb43a206a04116ffd7cfcf9bcb941f8eb6cc7ff667272246b0a1c74259a3cb"
 "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
 "checksum same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cfb6eded0b06a0b512c8ddbcf04089138c9b4362c2f696f3c3d76039d68f3637"
@@ -2819,9 +3037,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)" = "5c508584d9913df116b91505eec55610a2f5b16e9ed793c46e4d0152872b3e74"
 "checksum shell-escape 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "170a13e64f2a51b77a45702ba77287f5c6829375b04a69cf2222acd17d0cfab9"
 "checksum shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2"
+"checksum siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0df90a788073e8d0235a67e50441d47db7c8ad9debd91cbf43736a2a92d36537"
 "checksum smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44db0ecb22921ef790d17ae13a3f6d15784183ff5f2a01aa32098c7498d2b4b9"
 "checksum socket2 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "71ebbe82fcdd697244ba7fe6e05e63b5c45910c3927e28469a04947494ff48d8"
 "checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b"
+"checksum string_cache 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39cb4173bcbd1319da31faa5468a7e3870683d7a237150b0b0aaafd546f6ad12"
+"checksum string_cache_codegen 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "479cde50c3539481f33906a387f2bd17c8e87cb848c35b6021d41fb81ff9b4d7"
+"checksum string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1884d1bc09741d466d9b14e6d37ac89d6909cbcac41dd9ae982d4d063bbedfc"
 "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550"
 "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad"
 "checksum syn 0.12.15 (registry+https://github.com/rust-lang/crates.io-index)" = "c97c05b8ebc34ddd6b967994d5c6e9852fa92f8b82b3858c39451f97346dcce5"
@@ -2834,6 +3056,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum tar 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)" = "1605d3388ceb50252952ffebab4b5dc43017ead7e4481b175961c283bb951195"
 "checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8"
 "checksum tempfile 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "439d9a7c00f98b1b5ee730039bf5b1f9203d508690e3c76b509e7ad59f8f7c99"
+"checksum tendril 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9de21546595a0873061940d994bbbc5c35f024ae4fd61ec5c5b159115684f508"
 "checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1"
 "checksum term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5e6b677dd1e8214ea1ef4297f85dbcbed8e8cdddb561040cc998ca2551c37561"
 "checksum termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "adc4587ead41bf016f11af03e55a624c06568b5a19db4e90fde573d805074f83"
@@ -2852,10 +3075,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "36dff09cafb4ec7c8cf0023eb0b686cb6ce65499116a12201c9e11840ca01beb"
 "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
 "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
+"checksum unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f2ae5ddb18e1c92664717616dd9549dde73f539f01bd7b77c2edb2446bdff91"
 "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
 "checksum url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f808aadd8cfec6ef90e4a14eb46f24511824d1ac596b9682703c87056c8678b7"
 "checksum url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "74e7d099f1ee52f823d4bdd60c93c3602043c728f5db3b97bdb548467f7bddea"
 "checksum userenv-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "71d28ea36bbd9192d75bd9fa9b39f96ddb986eaee824adae5d53b6e51919b2f3"
+"checksum utf-8 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f1262dfab4c30d5cb7c07026be00ee343a6cf5027fdc0104a9160f354e5db75c"
 "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122"
 "checksum vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9e0a7d8bed3178a8fb112199d466eeca9ed09a14ba8ad67718179b4fd5487d0b"
 "checksum vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c"
index 6701f58ba8e92593589679caf6772aeb6c1d9395..3dd9b6840591bf8d189b92a5bc37aba94d4b9acd 100644 (file)
@@ -279,6 +279,10 @@ fn main() {
         cmd.arg("--color=always");
     }
 
+    if env::var_os("RUSTC_DENY_WARNINGS").is_some() {
+        cmd.arg("-Dwarnings");
+    }
+
     if verbose > 1 {
         eprintln!("rustc command: {:?}", cmd);
         eprintln!("sysroot: {:?}", sysroot);
index cf54591f25cd576cd62fa204f939a95bfec1d40e..487440becf630de7471c0228bab09c014e33d2ac 100644 (file)
@@ -770,10 +770,7 @@ def bootstrap(help_triggered):
     if 'dev' in data:
         build.set_dev_environment()
 
-    # No help text depends on submodules. This check saves ~1 minute of git commands, even if
-    # all the submodules are present and downloaded!
-    if not help_triggered:
-        build.update_submodules()
+    build.update_submodules()
 
     # Fetch/build the bootstrap
     build.build = args.build or build.build_triple()
index 3f5ec4933d02b23d31469b3ea022b46fb1f0b323..7ff64af919671f977497bff7abf05dfac28e694c 100644 (file)
@@ -698,6 +698,11 @@ pub fn cargo(&self,
 
         cargo.env("RUSTC_VERBOSE", format!("{}", self.verbosity));
 
+        // in std, we want to avoid denying warnings for stage 0 as that makes cfg's painful.
+        if self.config.deny_warnings && !(mode == Mode::Libstd && stage == 0) {
+            cargo.env("RUSTC_DENY_WARNINGS", "1");
+        }
+
         // Throughout the build Cargo can execute a number of build scripts
         // compiling C/C++ code and we need to pass compilers, archivers, flags, etc
         // obtained previously to those build scripts.
index da57881202d17af8b09a92210d2edb3eb1c82ef5..9cc18464fea094668f1c716c74cffe340e233827 100644 (file)
@@ -140,48 +140,58 @@ pub fn std_cargo(build: &Builder,
                  compiler: &Compiler,
                  target: Interned<String>,
                  cargo: &mut Command) {
-    let mut features = build.std_features();
-
     if let Some(target) = env::var_os("MACOSX_STD_DEPLOYMENT_TARGET") {
         cargo.env("MACOSX_DEPLOYMENT_TARGET", target);
     }
 
-    // When doing a local rebuild we tell cargo that we're stage1 rather than
-    // stage0. This works fine if the local rust and being-built rust have the
-    // same view of what the default allocator is, but fails otherwise. Since
-    // we don't have a way to express an allocator preference yet, work
-    // around the issue in the case of a local rebuild with jemalloc disabled.
-    if compiler.stage == 0 && build.local_rebuild && !build.config.use_jemalloc {
-        features.push_str(" force_alloc_system");
-    }
+    if build.no_std(target) == Some(true) {
+        // for no-std targets we only compile a few no_std crates
+        cargo.arg("--features").arg("c mem")
+            .args(&["-p", "alloc"])
+            .args(&["-p", "compiler_builtins"])
+            .args(&["-p", "std_unicode"])
+            .arg("--manifest-path")
+            .arg(build.src.join("src/rustc/compiler_builtins_shim/Cargo.toml"));
+    } else {
+        let mut features = build.std_features();
+
+        // When doing a local rebuild we tell cargo that we're stage1 rather than
+        // stage0. This works fine if the local rust and being-built rust have the
+        // same view of what the default allocator is, but fails otherwise. Since
+        // we don't have a way to express an allocator preference yet, work
+        // around the issue in the case of a local rebuild with jemalloc disabled.
+        if compiler.stage == 0 && build.local_rebuild && !build.config.use_jemalloc {
+            features.push_str(" force_alloc_system");
+        }
 
-    if compiler.stage != 0 && build.config.sanitizers {
-        // This variable is used by the sanitizer runtime crates, e.g.
-        // rustc_lsan, to build the sanitizer runtime from C code
-        // When this variable is missing, those crates won't compile the C code,
-        // so we don't set this variable during stage0 where llvm-config is
-        // missing
-        // We also only build the runtimes when --enable-sanitizers (or its
-        // config.toml equivalent) is used
-        let llvm_config = build.ensure(native::Llvm {
-            target: build.config.build,
-            emscripten: false,
-        });
-        cargo.env("LLVM_CONFIG", llvm_config);
-    }
+        if compiler.stage != 0 && build.config.sanitizers {
+            // This variable is used by the sanitizer runtime crates, e.g.
+            // rustc_lsan, to build the sanitizer runtime from C code
+            // When this variable is missing, those crates won't compile the C code,
+            // so we don't set this variable during stage0 where llvm-config is
+            // missing
+            // We also only build the runtimes when --enable-sanitizers (or its
+            // config.toml equivalent) is used
+            let llvm_config = build.ensure(native::Llvm {
+                target: build.config.build,
+                emscripten: false,
+            });
+            cargo.env("LLVM_CONFIG", llvm_config);
+        }
 
-    cargo.arg("--features").arg(features)
-        .arg("--manifest-path")
-        .arg(build.src.join("src/libstd/Cargo.toml"));
+        cargo.arg("--features").arg(features)
+            .arg("--manifest-path")
+            .arg(build.src.join("src/libstd/Cargo.toml"));
 
-    if let Some(target) = build.config.target_config.get(&target) {
-        if let Some(ref jemalloc) = target.jemalloc {
-            cargo.env("JEMALLOC_OVERRIDE", jemalloc);
+        if let Some(target) = build.config.target_config.get(&target) {
+            if let Some(ref jemalloc) = target.jemalloc {
+                cargo.env("JEMALLOC_OVERRIDE", jemalloc);
+            }
         }
-    }
-    if target.contains("musl") {
-        if let Some(p) = build.musl_root(target) {
-            cargo.env("MUSL_ROOT", p);
+        if target.contains("musl") {
+            if let Some(p) = build.musl_root(target) {
+                cargo.env("MUSL_ROOT", p);
+            }
         }
     }
 }
index 76672df5c570deeeccd747d9c809c56839dabe29..239316d45c49c4067cd3ab74074452e296644f7b 100644 (file)
@@ -71,6 +71,8 @@ pub struct Config {
     pub incremental: bool,
     pub dry_run: bool,
 
+    pub deny_warnings: bool,
+
     // llvm codegen options
     pub llvm_enabled: bool,
     pub llvm_assertions: bool,
@@ -161,6 +163,7 @@ pub struct Target {
     pub crt_static: Option<bool>,
     pub musl_root: Option<PathBuf>,
     pub qemu_rootfs: Option<PathBuf>,
+    pub no_std: bool,
 }
 
 /// Structure of the `config.toml` file that configuration is read from.
@@ -300,6 +303,7 @@ struct Rust {
     codegen_backends_dir: Option<String>,
     wasm_syscall: Option<bool>,
     lld: Option<bool>,
+    deny_warnings: Option<bool>,
 }
 
 /// TOML representation of how each build target is configured.
@@ -339,6 +343,7 @@ pub fn default_opts() -> Config {
         config.test_miri = false;
         config.rust_codegen_backends = vec![INTERNER.intern_str("llvm")];
         config.rust_codegen_backends_dir = "codegen-backends".to_owned();
+        config.deny_warnings = true;
 
         // set by bootstrap.py
         config.src = env::var_os("SRC").map(PathBuf::from).expect("'SRC' to be set");
@@ -365,6 +370,9 @@ pub fn parse(args: &[String]) -> Config {
         config.incremental = flags.incremental;
         config.dry_run = flags.dry_run;
         config.keep_stage = flags.keep_stage;
+        if let Some(value) = flags.warnings {
+            config.deny_warnings = value;
+        }
 
         if config.dry_run {
             let dir = config.out.join("tmp-dry-run");
@@ -510,6 +518,7 @@ pub fn parse(args: &[String]) -> Config {
             config.rustc_default_linker = rust.default_linker.clone();
             config.musl_root = rust.musl_root.clone().map(PathBuf::from);
             config.save_toolstates = rust.save_toolstates.clone().map(PathBuf::from);
+            set(&mut config.deny_warnings, rust.deny_warnings.or(flags.warnings));
 
             if let Some(ref backends) = rust.codegen_backends {
                 config.rust_codegen_backends = backends.iter()
@@ -562,7 +571,7 @@ pub fn parse(args: &[String]) -> Config {
         // default values for all options that we haven't otherwise stored yet.
 
         set(&mut config.initial_rustc, build.rustc.map(PathBuf::from));
-        set(&mut config.initial_rustc, build.cargo.map(PathBuf::from));
+        set(&mut config.initial_cargo, build.cargo.map(PathBuf::from));
 
         let default = false;
         config.llvm_assertions = llvm_assertions.unwrap_or(default);
index a5c373d5d5e7729ad118615fc0395f33641f1e2c..b06968d313ba201b8ed8da8318c323c268088a74 100755 (executable)
@@ -145,7 +145,7 @@ o("jemalloc", "rust.use-jemalloc", "build liballoc with jemalloc")
 o("full-bootstrap", "build.full-bootstrap", "build three compilers instead of two")
 o("extended", "build.extended", "build an extended rust tool set")
 
-v("tools", "build.tools", "List of extended tools will be installed")
+v("tools", None, "List of extended tools will be installed")
 v("build", "build.build", "GNUs ./configure syntax LLVM build triple")
 v("host", None, "GNUs ./configure syntax LLVM host triples")
 v("target", None, "GNUs ./configure syntax LLVM target triples")
@@ -321,6 +321,8 @@ for key in known_args:
         set('target.{}.llvm-config'.format(build()), value + '/bin/llvm-config')
     elif option.name == 'jemalloc-root':
         set('target.{}.jemalloc'.format(build()), value + '/libjemalloc_pic.a')
+    elif option.name == 'tools':
+        set('build.tools', value.split(','))
     elif option.name == 'host':
         set('build.host', value.split(','))
     elif option.name == 'target':
index c9be17ff1ad2d2277049a9dbe1fcd4e6837c801e..e1f5d34bf67235c5e2a58225e4e4903f5b6b55a4 100644 (file)
@@ -642,7 +642,12 @@ fn run(self, builder: &Builder) -> PathBuf {
         if build.hosts.iter().any(|t| t == target) {
             builder.ensure(compile::Rustc { compiler, target });
         } else {
-            builder.ensure(compile::Test { compiler, target });
+            if build.no_std(target) == Some(true) {
+                // the `test` doesn't compile for no-std targets
+                builder.ensure(compile::Std { compiler, target });
+            } else {
+                builder.ensure(compile::Test { compiler, target });
+            }
         }
 
         let image = tmpdir(build).join(format!("{}-{}-image", name, target));
index f07c3e707574b4e4a051fc6e9b1f9e0950b82917..4237ded2215c218e4fd8ed16e4d7d4a795fecc4b 100644 (file)
@@ -698,6 +698,7 @@ fn run(self, builder: &Builder) {
         t!(symlink_dir_force(&builder.config, &out, &out_dir));
 
         let mut cargo = builder.cargo(compiler, Mode::Librustc, target, "doc");
+        cargo.env("RUSTDOCFLAGS", "--document-private-items");
         compile::rustc_cargo(build, &mut cargo);
 
         // Only include compiler crates, no dependencies of those, such as `libc`.
index cd304fb26e0bfcb939cf226951a19c58c170d4f3..3eb9dca2aa835807fc663e85e88f736e4515087d 100644 (file)
@@ -42,6 +42,9 @@ pub struct Flags {
     pub exclude: Vec<PathBuf>,
     pub rustc_error_format: Option<String>,
     pub dry_run: bool,
+
+    // true => deny
+    pub warnings: Option<bool>,
 }
 
 pub enum Subcommand {
@@ -118,6 +121,8 @@ pub fn parse(args: &[String]) -> Flags {
         opts.optopt("", "src", "path to the root of the rust checkout", "DIR");
         opts.optopt("j", "jobs", "number of jobs to run in parallel", "JOBS");
         opts.optflag("h", "help", "print this help message");
+        opts.optopt("", "warnings", "if value is deny, will deny warnings, otherwise use default",
+            "VALUE");
         opts.optopt("", "error-format", "rustc error format", "FORMAT");
 
         // fn usage()
@@ -357,15 +362,9 @@ pub fn parse(args: &[String]) -> Flags {
         };
 
 
-        let mut stage = matches.opt_str("stage").map(|j| j.parse().unwrap());
-
-        if matches.opt_present("incremental") && stage.is_none() {
-            stage = Some(1);
-        }
-
         Flags {
             verbose: matches.opt_count("verbose"),
-            stage,
+            stage: matches.opt_str("stage").map(|j| j.parse().unwrap()),
             dry_run: matches.opt_present("dry-run"),
             on_fail: matches.opt_str("on-fail"),
             rustc_error_format: matches.opt_str("error-format"),
@@ -380,6 +379,7 @@ pub fn parse(args: &[String]) -> Flags {
             incremental: matches.opt_present("incremental"),
             exclude: split(matches.opt_strs("exclude"))
                 .into_iter().map(|p| p.into()).collect::<Vec<_>>(),
+            warnings: matches.opt_str("warnings").map(|v| v == "deny"),
         }
     }
 }
index 4b05cac1ce6979123e0637c5169c9dd2a4b9dff4..d71fdb8a30c70d01be928a1fa2d0e30127b674c5 100644 (file)
@@ -72,7 +72,9 @@ fn install_sh(
     let bindir_default = PathBuf::from("bin");
     let libdir_default = PathBuf::from("lib");
     let mandir_default = datadir_default.join("man");
-    let prefix = build.config.prefix.as_ref().unwrap_or(&prefix_default);
+    let prefix = build.config.prefix.as_ref().map_or(prefix_default, |p| {
+        fs::canonicalize(p).expect(&format!("could not canonicalize {}", p.display()))
+    });
     let sysconfdir = build.config.sysconfdir.as_ref().unwrap_or(&sysconfdir_default);
     let datadir = build.config.datadir.as_ref().unwrap_or(&datadir_default);
     let docdir = build.config.docdir.as_ref().unwrap_or(&docdir_default);
index 2eeb2691eaee45a427f68d944257607d894870ab..0a7f0e5ff4ee25c64116f80a23227dab368bf063 100644 (file)
 //! also check out the `src/bootstrap/README.md` file for more information.
 
 #![deny(warnings)]
-#![feature(conservative_impl_trait, fs_read_write, core_intrinsics)]
-#![feature(slice_concat_ext)]
+#![feature(core_intrinsics)]
 
 #[macro_use]
 extern crate build_helper;
@@ -750,6 +749,12 @@ fn musl_root(&self, target: Interned<String>) -> Option<&Path> {
             .map(|p| &**p)
     }
 
+    /// Returns true if this is a no-std `target`, if defined
+    fn no_std(&self, target: Interned<String>) -> Option<bool> {
+        self.config.target_config.get(&target)
+            .map(|t| t.no_std)
+    }
+
     /// Returns whether the target will be tested using the `remote-test-client`
     /// and `remote-test-server` binaries.
     fn remote_tested(&self, target: Interned<String>) -> bool {
@@ -1149,7 +1154,7 @@ fn create(&self, path: &Path, s: &str) {
 
     fn read(&self, path: &Path) -> String {
         if self.config.dry_run { return String::new(); }
-        t!(fs::read_string(path))
+        t!(fs::read_to_string(path))
     }
 
     fn create_dir(&self, dir: &Path) {
index 5184cca653c4b156b55dded68955fff8921897f4..1b1cec5f18c07d530795f35ee5df4d4faa8145e8 100644 (file)
@@ -169,6 +169,19 @@ pub fn check(build: &mut Build) {
             panic!("the iOS target is only supported on macOS");
         }
 
+        if target.contains("-none-") {
+            if build.no_std(*target).is_none() {
+                let target = build.config.target_config.entry(target.clone())
+                    .or_insert(Default::default());
+
+                target.no_std = true;
+            }
+
+            if build.no_std(*target) == Some(false) {
+                panic!("All the *-none-* targets are no-std targets")
+            }
+        }
+
         // Make sure musl-root is valid
         if target.contains("musl") {
             // If this is a native target (host is also musl) and no musl-root is given,
index 93b6153fcb2f8c58c2758f3a6284e54e5867df83..5fc92611e6529066e3828694740919a4cc9e1c62 100644 (file)
@@ -12,7 +12,6 @@
 use std::env;
 use std::path::PathBuf;
 use std::process::{Command, exit};
-use std::slice::SliceConcatExt;
 
 use Mode;
 use Compiler;
index 5a12afd03e13b820c891aec362d9b6f3c5683f70..e5c85ddb3a9022ae1208a1112b8944a6d22d4084 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![deny(warnings)]
 
 use std::fs::File;
 use std::path::{Path, PathBuf};
index 1b6ee44d87afca025e01d26d8df660ac063061ca..00366301aa17aba600cb8c4f112a220124daab0c 100644 (file)
@@ -20,7 +20,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   bzip2 \
   patch \
   libssl-dev \
-  pkg-config
+  pkg-config \
+  gcc-arm-none-eabi \
+  libnewlib-arm-none-eabi
 
 WORKDIR /build
 
@@ -86,6 +88,10 @@ ENV TARGETS=$TARGETS,armv7-unknown-linux-musleabihf
 ENV TARGETS=$TARGETS,aarch64-unknown-linux-musl
 ENV TARGETS=$TARGETS,sparc64-unknown-linux-gnu
 ENV TARGETS=$TARGETS,x86_64-unknown-redox
+ENV TARGETS=$TARGETS,thumbv6m-none-eabi
+ENV TARGETS=$TARGETS,thumbv7m-none-eabi
+ENV TARGETS=$TARGETS,thumbv7em-none-eabi
+ENV TARGETS=$TARGETS,thumbv7em-none-eabihf
 
 # FIXME: remove armv5te vars after https://github.com/alexcrichton/cc-rs/issues/271
 #        get fixed and cc update
index ea2387b67dbccf9379b5c017e383ef6f61b9c296..c470ae7eb30306cdaa081c06e3c5d79e4d3b90c3 100755 (executable)
@@ -130,6 +130,7 @@ exec docker \
   --env TRAVIS \
   --env TRAVIS_BRANCH \
   --env TOOLSTATE_REPO_ACCESS_TOKEN \
+  --env CI_JOB_NAME="${CI_JOB_NAME-$IMAGE}" \
   --volume "$HOME/.cargo:/cargo" \
   --volume "$HOME/rustsrc:$HOME/rustsrc" \
   --init \
diff --git a/src/ci/docker/x86_64-gnu-incremental/Dockerfile b/src/ci/docker/x86_64-gnu-incremental/Dockerfile
deleted file mode 100644 (file)
index 7304ed6..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-FROM ubuntu:16.04
-
-RUN apt-get update && apt-get install -y --no-install-recommends \
-  g++ \
-  make \
-  file \
-  curl \
-  ca-certificates \
-  python2.7 \
-  git \
-  cmake \
-  sudo \
-  gdb \
-  xz-utils
-
-COPY scripts/sccache.sh /scripts/
-RUN sh /scripts/sccache.sh
-
-ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu
-ENV RUSTFLAGS -Zincremental=/tmp/rust-incr-cache
-ENV RUST_CHECK_TARGET check
-ENV CARGO_INCREMENTAL 0
index 44eae0d1800472eb9eb16a2a979fbafaf8584a92..119b239d6b290177ac4c41b9cb19ab0a9271ef18 100755 (executable)
 
 set -e
 
+if [ -n "$CI_JOB_NAME" ]; then
+  echo "[CI_JOB_NAME=$CI_JOB_NAME]"
+fi
+
 if [ "$NO_CHANGE_USER" = "" ]; then
   if [ "$LOCAL_USER_ID" != "" ]; then
     useradd --shell /bin/bash -u $LOCAL_USER_ID -o -c "" -m user
index 2e36831d7e86f9e7bcb022eb7f5ff0d3d03d0969..2ea889da1fde201aa89bff93f0dd5c9032548759 100644 (file)
@@ -13,65 +13,65 @@ unofficial documentation resources as well!
 Many of these resources take the form of "books"; we collectively call these
 "The Rust Bookshelf." Some are large, some are small.
 
-## Learn Rust
+# Learn Rust
 
 If you'd like to learn Rust, this is the spot for you! All of these resources
 assume that you have programmed before, but not in any specific language:
 
-### The Rust Programming Language
+## The Rust Programming Language
 
 Affectionately nicknamed "the book," [The Rust Programming
 Language](book/index.html) will give you an overview of the language from
 first principles. You'll build a few projects along the way, and by the end,
 you'll have a solid grasp of the language.
 
-### Rust By Example
+## Rust By Example
 
 If reading multiple hundreds of pages about a language isn't your style, then
 [Rust By Example](rust-by-example/index.html) has you covered. While the book talks about code with
 a lot of words, RBE shows off a bunch of code, and keeps the talking to a
 minimum. It also includes exercises!
 
-## Use Rust
+# Use Rust
 
 Once you've gotten familliar with the language, these resources can help you
 when you're actually using it day-to-day.
 
-### The Standard Library
+## The Standard Library
 
 Rust's standard library has [extensive API documentation](std/index.html),
 with explanations of how to use various things, as well as example code for
 accomplishing various tasks.
 
-### The Cargo Book
+## The Cargo Book
 
 [The Cargo Book](cargo/index.html) is a guide to Cargo, Rust's build tool and dependency manager.
 
-### The Rustdoc Book
+## The Rustdoc Book
 
 [The Rustdoc Book](rustdoc/index.html) describes our documentation tool, `rustdoc`.
 
-### Extended Error Listing
+## Extended Error Listing
 
 Many of Rust's errors come with error codes, and you can request extended
 diagnostics from the compiler on those errors. You can also [read them
 here](error-index.html), if you prefer to read them that way.
 
-## Master Rust
+# Master Rust
 
 Once you're quite familiar with the language, you may find these advanced
 resources useful.
 
-### The Reference
+## The Reference
 
 [The Reference](reference/index.html) is not a formal spec, but is more detailed and
 comprehensive than the book.
 
-### The Rustonomicon
+## The Rustonomicon
 
 [The Rustonomicon](nomicon/index.html) is your guidebook to the dark arts of unsafe
 Rust. It's also sometimes called "the 'nomicon."
 
-### The Unstable Book
+## The Unstable Book
 
 [The Unstable Book](unstable-book/index.html) has documentation for unstable features.
index 3bf919b0c0016e3c689b87146e5a0ba30c940f22..2eb8ea1260446a44cfd8fad1f09c91fdfe5ffcec 100644 (file)
@@ -10,6 +10,7 @@ path = "lib.rs"
 [dependencies]
 core = { path = "../libcore" }
 std_unicode = { path = "../libstd_unicode" }
+compiler_builtins = { path = "../rustc/compiler_builtins_shim" }
 
 [dev-dependencies]
 rand = "0.4"
index a43aadfe9a23a72c42b511a8c5a5a3f8add8c015..4f69aa6670b563fa9aced927148d88116446aa88 100644 (file)
@@ -8,9 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![deny(warnings)]
-
-#![cfg_attr(stage0, feature(i128_type))]
 #![feature(rand)]
 #![feature(repr_simd)]
 #![feature(slice_sort_by_cached_key)]
index 4f9dc61ce196be1306884c2afca4c9b71cdabe31..71b53cc88e54dfef3ec2b22ce57a182e265c1067 100644 (file)
@@ -845,3 +845,6 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 
 #[unstable(feature = "pin", issue = "49150")]
 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<PinBox<U>> for PinBox<T> {}
+
+#[unstable(feature = "pin", issue = "49150")]
+unsafe impl<T: ?Sized> Unpin for PinBox<T> {}
index 51a7802540192967d0547ec09e9e7389a6bb6f79..b08bd66b47c5922533f00be05d62ac37e893527b 100644 (file)
@@ -72,7 +72,6 @@
        test(no_crate_inject, attr(allow(unused_variables), deny(warnings))))]
 #![no_std]
 #![needs_allocator]
-#![deny(warnings)]
 #![deny(missing_debug_implementations)]
 
 #![cfg_attr(test, allow(deprecated))] // rand
@@ -97,8 +96,6 @@
 #![feature(fmt_internals)]
 #![feature(from_ref)]
 #![feature(fundamental)]
-#![feature(generic_param_attrs)]
-#![cfg_attr(stage0, feature(i128_type))]
 #![feature(lang_items)]
 #![feature(needs_allocator)]
 #![feature(nonzero)]
 #![feature(exact_chunks)]
 #![feature(pointer_methods)]
 #![feature(inclusive_range_fields)]
+#![cfg_attr(stage0, feature(generic_param_attrs))]
 
 #![cfg_attr(not(test), feature(fn_traits, swap_with_slice, i128))]
 #![cfg_attr(test, feature(test))]
index 1a49fb9964ad727ef7c765c185f8024c35e56764..17f1d0464a5c2d724b7a8a2c935a73622f233370 100644 (file)
@@ -8,13 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![deny(warnings)]
-
 #![feature(allocator_api)]
 #![feature(alloc_system)]
 #![feature(attr_literals)]
 #![feature(box_syntax)]
-#![cfg_attr(stage0, feature(inclusive_range_syntax))]
 #![feature(const_fn)]
 #![feature(drain_filter)]
 #![feature(exact_size_is_empty)]
index 02008310b81613fe0b6e00c29d139e25f1d17315..4b883b5bce79bd48f714b5442340696024eea662 100644 (file)
@@ -1594,40 +1594,69 @@ fn from_elem(elem: u8, n: usize) -> Vec<u8> {
     }
 }
 
-macro_rules! impl_spec_from_elem {
+impl<T: Clone + IsZero> SpecFromElem for T {
+    #[inline]
+    fn from_elem(elem: T, n: usize) -> Vec<T> {
+        if elem.is_zero() {
+            return Vec {
+                buf: RawVec::with_capacity_zeroed(n),
+                len: n,
+            }
+        }
+        let mut v = Vec::with_capacity(n);
+        v.extend_with(n, ExtendElement(elem));
+        v
+    }
+}
+
+unsafe trait IsZero {
+    /// Whether this value is zero
+    fn is_zero(&self) -> bool;
+}
+
+macro_rules! impl_is_zero {
     ($t: ty, $is_zero: expr) => {
-        impl SpecFromElem for $t {
+        unsafe impl IsZero for $t {
             #[inline]
-            fn from_elem(elem: $t, n: usize) -> Vec<$t> {
-                if $is_zero(elem) {
-                    return Vec {
-                        buf: RawVec::with_capacity_zeroed(n),
-                        len: n,
-                    }
-                }
-                let mut v = Vec::with_capacity(n);
-                v.extend_with(n, ExtendElement(elem));
-                v
+            fn is_zero(&self) -> bool {
+                $is_zero(*self)
             }
         }
-    };
+    }
 }
 
-impl_spec_from_elem!(i8, |x| x == 0);
-impl_spec_from_elem!(i16, |x| x == 0);
-impl_spec_from_elem!(i32, |x| x == 0);
-impl_spec_from_elem!(i64, |x| x == 0);
-impl_spec_from_elem!(i128, |x| x == 0);
-impl_spec_from_elem!(isize, |x| x == 0);
+impl_is_zero!(i8, |x| x == 0);
+impl_is_zero!(i16, |x| x == 0);
+impl_is_zero!(i32, |x| x == 0);
+impl_is_zero!(i64, |x| x == 0);
+impl_is_zero!(i128, |x| x == 0);
+impl_is_zero!(isize, |x| x == 0);
+
+impl_is_zero!(u16, |x| x == 0);
+impl_is_zero!(u32, |x| x == 0);
+impl_is_zero!(u64, |x| x == 0);
+impl_is_zero!(u128, |x| x == 0);
+impl_is_zero!(usize, |x| x == 0);
+
+impl_is_zero!(char, |x| x == '\0');
+
+impl_is_zero!(f32, |x: f32| x.to_bits() == 0);
+impl_is_zero!(f64, |x: f64| x.to_bits() == 0);
 
-impl_spec_from_elem!(u16, |x| x == 0);
-impl_spec_from_elem!(u32, |x| x == 0);
-impl_spec_from_elem!(u64, |x| x == 0);
-impl_spec_from_elem!(u128, |x| x == 0);
-impl_spec_from_elem!(usize, |x| x == 0);
+unsafe impl<T: ?Sized> IsZero for *const T {
+    #[inline]
+    fn is_zero(&self) -> bool {
+        (*self).is_null()
+    }
+}
+
+unsafe impl<T: ?Sized> IsZero for *mut T {
+    #[inline]
+    fn is_zero(&self) -> bool {
+        (*self).is_null()
+    }
+}
 
-impl_spec_from_elem!(f32, |x: f32| x.to_bits() == 0);
-impl_spec_from_elem!(f64, |x: f64| x.to_bits() == 0);
 
 ////////////////////////////////////////////////////////////////////////////////
 // Common trait implementations for Vec
index 6d7d83dd99388aa10145a78c4b7b663dd38af802..fd4a45530463df9854455a883061962ba470e8b8 100644 (file)
@@ -16,6 +16,7 @@ alloc = { path = "../liballoc" }
 alloc_system = { path = "../liballoc_system" }
 core = { path = "../libcore" }
 libc = { path = "../rustc/libc_shim" }
+compiler_builtins = { path = "../rustc/compiler_builtins_shim" }
 
 [build-dependencies]
 build_helper = { path = "../build_helper" }
index 7a8d01e4ef8b88f7dddea1adc63f0e1b852baa73..df7e3f61f5f1dc3d7ae3db41839e0177ef8daaca 100644 (file)
@@ -14,7 +14,6 @@
             reason = "this library is unlikely to be stabilized in its current \
                       form or name",
             issue = "27783")]
-#![deny(warnings)]
 #![feature(alloc_system)]
 #![feature(libc)]
 #![feature(linkage)]
index f9a57f7d97a74ea914602769708754e84958d9b4..936e20a32e10e9d064f55f22094052eaafc41455 100644 (file)
@@ -13,6 +13,7 @@ doc = false
 alloc = { path = "../liballoc" }
 core = { path = "../libcore" }
 libc = { path = "../rustc/libc_shim" }
+compiler_builtins = { path = "../rustc/compiler_builtins_shim" }
 
 # See comments in the source for what this dependency is
 [target.'cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))'.dependencies]
index d4404e564e0639960873fbacd4bf616130142a3e..cdcb732f635478bb4f105f7731694cf07b15f608 100644 (file)
@@ -10,7 +10,6 @@
 
 #![no_std]
 #![allow(unused_attributes)]
-#![deny(warnings)]
 #![unstable(feature = "alloc_system",
             reason = "this library is unlikely to be stabilized in its current \
                       form or name",
index 72fa3148fe54aba3563439947fb212864f3d7e3f..b319f333342c1cc11134d98d0881aca582eb7bf8 100644 (file)
        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "https://doc.rust-lang.org/nightly/",
        test(no_crate_inject, attr(deny(warnings))))]
-#![deny(warnings)]
 
 #![feature(alloc)]
 #![feature(core_intrinsics)]
 #![feature(dropck_eyepatch)]
-#![feature(generic_param_attrs)]
+#![cfg_attr(stage0, feature(generic_param_attrs))]
 #![cfg_attr(test, feature(test))]
 
 #![allow(deprecated)]
index 2c4bccebceb95247d45a42ffbba8130acc351df1..e6b0569281f89b219433d3e1826014009edfa268 100644 (file)
@@ -31,7 +31,7 @@
 /// documentation for more.
 ///
 /// [`escape_default`]: fn.escape_default.html
-#[stable(feature = "core_ascii", since = "1.26.0")]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct EscapeDefault {
     range: Range<usize>,
     data: [u8; 4],
@@ -99,7 +99,7 @@ pub struct EscapeDefault {
 /// assert_eq!(b'9', escaped.next().unwrap());
 /// assert_eq!(b'd', escaped.next().unwrap());
 /// ```
-#[stable(feature = "core_ascii", since = "1.26.0")]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub fn escape_default(c: u8) -> EscapeDefault {
     let (data, len) = match c {
         b'\t' => ([b'\\', b't', 0, 0], 2),
index c947b003ccbffaa697586bfb32b5bc528687c142..ced77d779182aaac437bb11645220e418a2741a7 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![deny(warnings)]
-
 #![feature(flt2dec)]
 #![feature(test)]
 
index 67445daa436024b54b0bae004af0c440d7c3fcd2..3ae9b05b865386563ee9e78764e5a7a18fb61ba7 100644 (file)
@@ -427,7 +427,7 @@ fn cmp(&self, other: &Reverse<T>) -> Ordering {
 ///     }
 /// }
 /// ```
-#[cfg_attr(not(stage0), lang = "ord")]
+#[lang = "ord"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Ord: Eq + PartialOrd<Self> {
     /// This method returns an `Ordering` between `self` and `other`.
@@ -597,8 +597,7 @@ fn partial_cmp(&self, other: &Ordering) -> Option<Ordering> {
 /// assert_eq!(x < y, true);
 /// assert_eq!(x.lt(&y), true);
 /// ```
-#[cfg_attr(stage0, lang = "ord")]
-#[cfg_attr(not(stage0), lang = "partial_ord")]
+#[lang = "partial_ord"]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented = "can't compare `{Self}` with `{Rhs}`"]
 pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
index 3b740adc46832d06e0c21c5429d5527542c62a04..83274682250b0911f2e41b61c43894dbe4bed4fd 100644 (file)
@@ -1293,7 +1293,6 @@ pub fn volatile_copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T,
     pub fn bswap<T>(x: T) -> T;
 
     /// Reverses the bits in an integer type `T`.
-    #[cfg(not(stage0))]
     pub fn bitreverse<T>(x: T) -> T;
 
     /// Performs checked integer addition.
@@ -1316,7 +1315,6 @@ pub fn volatile_copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T,
 
     /// Performs an exact division, resulting in undefined behavior where
     /// `x % y != 0` or `y == 0` or `x == T::min_value() && y == -1`
-    #[cfg(not(stage0))]
     pub fn exact_div<T>(x: T, y: T) -> T;
 
     /// Performs an unchecked division, resulting in undefined behavior
@@ -1401,8 +1399,3 @@ pub fn volatile_copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T,
     /// Probably will never become stable.
     pub fn nontemporal_store<T>(ptr: *mut T, val: T);
 }
-
-#[cfg(stage0)]
-pub unsafe fn exact_div<T>(a: T, b: T) -> T {
-    unchecked_div(a, b)
-}
index 5d57207763e47b671306ca3674f20da7cfd7eb14..5896322f111f8e16e494719c0613488a8268efab 100644 (file)
@@ -200,7 +200,7 @@ unsafe impl TrustedLen for ops::Range<$t> { }
 
 macro_rules! range_incl_trusted_len_impl {
     ($($t:ty)*) => ($(
-        #[stable(feature = "inclusive_range", since = "1.26.0")]
+        #[unstable(feature = "trusted_len", issue = "37572")]
         unsafe impl TrustedLen for ops::RangeInclusive<$t> { }
     )*)
 }
index 5a62b8438f93d2a8dccdd5568e36c00427f0dd99..e194b173aa718212c6e073faac006bc3dafa448e 100644 (file)
@@ -63,7 +63,6 @@
 #![no_core]
 #![deny(missing_docs)]
 #![deny(missing_debug_implementations)]
-#![deny(warnings)]
 
 #![feature(allow_internal_unstable)]
 #![feature(asm)]
@@ -78,8 +77,6 @@
 #![feature(doc_spotlight)]
 #![feature(fn_must_use)]
 #![feature(fundamental)]
-#![cfg_attr(stage0, feature(i128_type))]
-#![cfg_attr(stage0, feature(inclusive_range_syntax))]
 #![feature(intrinsics)]
 #![feature(iterator_flatten)]
 #![feature(iterator_repeat_with)]
 #![feature(untagged_unions)]
 #![feature(unwind_attributes)]
 
-#![cfg_attr(stage0, allow(unused_attributes))]
-#![cfg_attr(stage0, feature(never_type))]
-
 #[prelude_import]
 #[allow(unused)]
 use prelude::v1::*;
index 8a87bea71e2530cf9562698aa6650955a854cc33..90a9cb3379b82ed8d8b4da3811df406cf540feef 100644 (file)
@@ -28,71 +28,6 @@ macro_rules! panic {
     });
 }
 
-/// Ensure that a boolean expression is `true` at runtime.
-///
-/// This will invoke the [`panic!`] macro if the provided expression cannot be
-/// evaluated to `true` at runtime.
-///
-/// # Uses
-///
-/// Assertions are always checked in both debug and release builds, and cannot
-/// be disabled. See [`debug_assert!`] for assertions that are not enabled in
-/// release builds by default.
-///
-/// Unsafe code relies on `assert!` to enforce run-time invariants that, if
-/// violated could lead to unsafety.
-///
-/// Other use-cases of `assert!` include [testing] and enforcing run-time
-/// invariants in safe code (whose violation cannot result in unsafety).
-///
-/// # Custom Messages
-///
-/// This macro has a second form, where a custom panic message can
-/// be provided with or without arguments for formatting.  See [`std::fmt`]
-/// for syntax for this form.
-///
-/// [`panic!`]: macro.panic.html
-/// [`debug_assert!`]: macro.debug_assert.html
-/// [testing]: ../book/second-edition/ch11-01-writing-tests.html#checking-results-with-the-assert-macro
-/// [`std::fmt`]: ../std/fmt/index.html
-///
-/// # Examples
-///
-/// ```
-/// // the panic message for these assertions is the stringified value of the
-/// // expression given.
-/// assert!(true);
-///
-/// fn some_computation() -> bool { true } // a very simple function
-///
-/// assert!(some_computation());
-///
-/// // assert with a custom message
-/// let x = true;
-/// assert!(x, "x wasn't true!");
-///
-/// let a = 3; let b = 27;
-/// assert!(a + b == 30, "a = {}, b = {}", a, b);
-/// ```
-#[macro_export]
-#[stable(feature = "rust1", since = "1.0.0")]
-#[cfg(stage0)]
-macro_rules! assert {
-    ($cond:expr) => (
-        if !$cond {
-            panic!(concat!("assertion failed: ", stringify!($cond)))
-        }
-    );
-    ($cond:expr,) => (
-        assert!($cond)
-    );
-    ($cond:expr, $($arg:tt)+) => (
-        if !$cond {
-            panic!($($arg)+)
-        }
-    );
-}
-
 /// Asserts that two expressions are equal to each other (using [`PartialEq`]).
 ///
 /// On panic, this macro will print the values of the expressions with their
index b2467c948b4b156506dabb8c771e73736e6569d0..e3f08926610f69592ecb583a7165b05d5fc0ddad 100644 (file)
@@ -1213,3 +1213,6 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 
 #[unstable(feature = "pin", issue = "49150")]
 impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Pin<'a, U>> for Pin<'a, T> {}
+
+#[unstable(feature = "pin", issue = "49150")]
+unsafe impl<'a, T: ?Sized> Unpin for Pin<'a, T> {}
index 4e72eaa57c73e9c6e3be208fb68f5246cfee6f0c..1720c9d8c60790a9a171f92c467fedbf86ed8dcf 100644 (file)
@@ -120,6 +120,7 @@ pub fn location(&self) -> Option<&Location> {
     }
 }
 
+#[stable(feature = "panic_hook_display", since = "1.26.0")]
 impl<'a> fmt::Display for PanicInfo<'a> {
     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
         formatter.write_str("panicked at ")?;
@@ -244,6 +245,7 @@ pub fn column(&self) -> u32 {
     }
 }
 
+#[stable(feature = "panic_hook_display", since = "1.26.0")]
 impl<'a> fmt::Display for Location<'a> {
     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
         write!(formatter, "{}:{}:{}", self.file, self.line, self.col)
index 94db0baa3f95f883f9eb73855ce0c0ff24b939fa..6b3dc75af46332c29c8da67421cf4fc72c837192 100644 (file)
@@ -64,8 +64,7 @@ pub fn panic_fmt(fmt: fmt::Arguments, file_line_col: &(&'static str, u32, u32))
     #[allow(improper_ctypes)]
     extern {
         #[lang = "panic_fmt"]
-        #[cfg_attr(stage0, unwind)]
-        #[cfg_attr(not(stage0), unwind(allowed))]
+        #[unwind(allowed)]
         fn panic_impl(fmt: fmt::Arguments, file: &'static str, line: u32, col: u32) -> !;
     }
     let (file, line, col) = *file_line_col;
index d934706be67d9337154ae023541880431fae4e38..d336934ec7214ad56668dae5428abfef74ee7514 100644 (file)
@@ -952,6 +952,7 @@ macro_rules! atomic_int {
      $stable_nand:meta,
      $s_int_type:expr, $int_ref:expr,
      $extra_feature:expr,
+     $min_fn:ident, $max_fn:ident,
      $int_type:ident $atomic_type:ident $atomic_init:ident) => {
         /// An integer type which can be safely shared between threads.
         ///
@@ -1421,6 +1422,128 @@ pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
                     unsafe { atomic_xor(self.v.get(), val, order) }
                 }
             }
+
+            doc_comment! {
+                concat!("Fetches the value, and applies a function to it that returns an optional
+new value. Returns a `Result` (`Ok(_)` if the function returned `Some(_)`, else `Err(_)`) of the
+previous value.
+
+Note: This may call the function multiple times if the value has been changed from other threads in
+the meantime, as long as the function returns `Some(_)`, but the function will have been applied
+but once to the stored value.
+
+# Examples
+
+```rust
+#![feature(no_more_cas)]
+", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
+
+let x = ", stringify!($atomic_type), "::new(7);
+assert_eq!(x.fetch_update(|_| None, Ordering::SeqCst, Ordering::SeqCst), Err(7));
+assert_eq!(x.fetch_update(|x| Some(x + 1), Ordering::SeqCst, Ordering::SeqCst), Ok(7));
+assert_eq!(x.fetch_update(|x| Some(x + 1), Ordering::SeqCst, Ordering::SeqCst), Ok(8));
+assert_eq!(x.load(Ordering::SeqCst), 9);
+```"),
+                #[inline]
+                #[unstable(feature = "no_more_cas",
+                       reason = "no more CAS loops in user code",
+                       issue = "48655")]
+                pub fn fetch_update<F>(&self,
+                                       mut f: F,
+                                       fetch_order: Ordering,
+                                       set_order: Ordering) -> Result<$int_type, $int_type>
+                where F: FnMut($int_type) -> Option<$int_type> {
+                    let mut prev = self.load(fetch_order);
+                    while let Some(next) = f(prev) {
+                        match self.compare_exchange_weak(prev, next, set_order, fetch_order) {
+                            x @ Ok(_) => return x,
+                            Err(next_prev) => prev = next_prev
+                        }
+                    }
+                    Err(prev)
+                }
+            }
+
+            doc_comment! {
+                concat!("Maximum with the current value.
+
+Finds the maximum of the current value and the argument `val`, and
+sets the new value to the result.
+
+Returns the previous value.
+
+# Examples
+
+```
+#![feature(atomic_min_max)]
+", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
+
+let foo = ", stringify!($atomic_type), "::new(23);
+assert_eq!(foo.fetch_max(42, Ordering::SeqCst), 23);
+assert_eq!(foo.load(Ordering::SeqCst), 42);
+```
+
+If you want to obtain the maximum value in one step, you can use the following:
+
+```
+#![feature(atomic_min_max)]
+", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
+
+let foo = ", stringify!($atomic_type), "::new(23);
+let bar = 42;
+let max_foo = foo.fetch_max(bar, Ordering::SeqCst).max(bar);
+assert!(max_foo == 42);
+```"),
+                #[inline]
+                #[unstable(feature = "atomic_min_max",
+                       reason = "easier and faster min/max than writing manual CAS loop",
+                       issue = "48655")]
+                pub fn fetch_max(&self, val: $int_type, order: Ordering) -> $int_type {
+                    unsafe { $max_fn(self.v.get(), val, order) }
+                }
+            }
+
+            doc_comment! {
+                concat!("Minimum with the current value.
+
+Finds the minimum of the current value and the argument `val`, and
+sets the new value to the result.
+
+Returns the previous value.
+
+# Examples
+
+```
+#![feature(atomic_min_max)]
+", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
+
+let foo = ", stringify!($atomic_type), "::new(23);
+assert_eq!(foo.fetch_min(42, Ordering::Relaxed), 23);
+assert_eq!(foo.load(Ordering::Relaxed), 23);
+assert_eq!(foo.fetch_min(22, Ordering::Relaxed), 23);
+assert_eq!(foo.load(Ordering::Relaxed), 22);
+```
+
+If you want to obtain the minimum value in one step, you can use the following:
+
+```
+#![feature(atomic_min_max)]
+", $extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};
+
+let foo = ", stringify!($atomic_type), "::new(23);
+let bar = 12;
+let min_foo = foo.fetch_min(bar, Ordering::SeqCst).min(bar);
+assert_eq!(min_foo, 12);
+```"),
+                #[inline]
+                #[unstable(feature = "atomic_min_max",
+                       reason = "easier and faster min/max than writing manual CAS loop",
+                       issue = "48655")]
+                pub fn fetch_min(&self, val: $int_type, order: Ordering) -> $int_type {
+                    unsafe { $min_fn(self.v.get(), val, order) }
+                }
+            }
+
         }
     }
 }
@@ -1435,6 +1558,7 @@ pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
     unstable(feature = "atomic_nand", issue = "13226"),
     "i8", "../../../std/primitive.i8.html",
     "#![feature(integer_atomics)]\n\n",
+    atomic_min, atomic_max,
     i8 AtomicI8 ATOMIC_I8_INIT
 }
 #[cfg(target_has_atomic = "8")]
@@ -1447,6 +1571,7 @@ pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
     unstable(feature = "atomic_nand", issue = "13226"),
     "u8", "../../../std/primitive.u8.html",
     "#![feature(integer_atomics)]\n\n",
+    atomic_umin, atomic_umax,
     u8 AtomicU8 ATOMIC_U8_INIT
 }
 #[cfg(target_has_atomic = "16")]
@@ -1459,6 +1584,7 @@ pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
     unstable(feature = "atomic_nand", issue = "13226"),
     "i16", "../../../std/primitive.i16.html",
     "#![feature(integer_atomics)]\n\n",
+    atomic_min, atomic_max,
     i16 AtomicI16 ATOMIC_I16_INIT
 }
 #[cfg(target_has_atomic = "16")]
@@ -1471,6 +1597,7 @@ pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
     unstable(feature = "atomic_nand", issue = "13226"),
     "u16", "../../../std/primitive.u16.html",
     "#![feature(integer_atomics)]\n\n",
+    atomic_umin, atomic_umax,
     u16 AtomicU16 ATOMIC_U16_INIT
 }
 #[cfg(target_has_atomic = "32")]
@@ -1483,6 +1610,7 @@ pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
     unstable(feature = "atomic_nand", issue = "13226"),
     "i32", "../../../std/primitive.i32.html",
     "#![feature(integer_atomics)]\n\n",
+    atomic_min, atomic_max,
     i32 AtomicI32 ATOMIC_I32_INIT
 }
 #[cfg(target_has_atomic = "32")]
@@ -1495,6 +1623,7 @@ pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
     unstable(feature = "atomic_nand", issue = "13226"),
     "u32", "../../../std/primitive.u32.html",
     "#![feature(integer_atomics)]\n\n",
+    atomic_umin, atomic_umax,
     u32 AtomicU32 ATOMIC_U32_INIT
 }
 #[cfg(target_has_atomic = "64")]
@@ -1507,6 +1636,7 @@ pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
     unstable(feature = "atomic_nand", issue = "13226"),
     "i64", "../../../std/primitive.i64.html",
     "#![feature(integer_atomics)]\n\n",
+    atomic_min, atomic_max,
     i64 AtomicI64 ATOMIC_I64_INIT
 }
 #[cfg(target_has_atomic = "64")]
@@ -1519,6 +1649,7 @@ pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
     unstable(feature = "atomic_nand", issue = "13226"),
     "u64", "../../../std/primitive.u64.html",
     "#![feature(integer_atomics)]\n\n",
+    atomic_umin, atomic_umax,
     u64 AtomicU64 ATOMIC_U64_INIT
 }
 #[cfg(target_has_atomic = "ptr")]
@@ -1531,6 +1662,7 @@ pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
     unstable(feature = "atomic_nand", issue = "13226"),
     "isize", "../../../std/primitive.isize.html",
     "",
+    atomic_min, atomic_max,
     isize AtomicIsize ATOMIC_ISIZE_INIT
 }
 #[cfg(target_has_atomic = "ptr")]
@@ -1543,6 +1675,7 @@ pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
     unstable(feature = "atomic_nand", issue = "13226"),
     "usize", "../../../std/primitive.usize.html",
     "",
+    atomic_umin, atomic_umax,
     usize AtomicUsize ATOMIC_USIZE_INIT
 }
 
@@ -1720,6 +1853,58 @@ unsafe fn atomic_xor<T>(dst: *mut T, val: T, order: Ordering) -> T {
     }
 }
 
+/// returns the max value (signed comparison)
+#[inline]
+unsafe fn atomic_max<T>(dst: *mut T, val: T, order: Ordering) -> T {
+    match order {
+        Acquire => intrinsics::atomic_max_acq(dst, val),
+        Release => intrinsics::atomic_max_rel(dst, val),
+        AcqRel => intrinsics::atomic_max_acqrel(dst, val),
+        Relaxed => intrinsics::atomic_max_relaxed(dst, val),
+        SeqCst => intrinsics::atomic_max(dst, val),
+        __Nonexhaustive => panic!("invalid memory ordering"),
+    }
+}
+
+/// returns the min value (signed comparison)
+#[inline]
+unsafe fn atomic_min<T>(dst: *mut T, val: T, order: Ordering) -> T {
+    match order {
+        Acquire => intrinsics::atomic_min_acq(dst, val),
+        Release => intrinsics::atomic_min_rel(dst, val),
+        AcqRel => intrinsics::atomic_min_acqrel(dst, val),
+        Relaxed => intrinsics::atomic_min_relaxed(dst, val),
+        SeqCst => intrinsics::atomic_min(dst, val),
+        __Nonexhaustive => panic!("invalid memory ordering"),
+    }
+}
+
+/// returns the max value (signed comparison)
+#[inline]
+unsafe fn atomic_umax<T>(dst: *mut T, val: T, order: Ordering) -> T {
+    match order {
+        Acquire => intrinsics::atomic_umax_acq(dst, val),
+        Release => intrinsics::atomic_umax_rel(dst, val),
+        AcqRel => intrinsics::atomic_umax_acqrel(dst, val),
+        Relaxed => intrinsics::atomic_umax_relaxed(dst, val),
+        SeqCst => intrinsics::atomic_umax(dst, val),
+        __Nonexhaustive => panic!("invalid memory ordering"),
+    }
+}
+
+/// returns the min value (signed comparison)
+#[inline]
+unsafe fn atomic_umin<T>(dst: *mut T, val: T, order: Ordering) -> T {
+    match order {
+        Acquire => intrinsics::atomic_umin_acq(dst, val),
+        Release => intrinsics::atomic_umin_rel(dst, val),
+        AcqRel => intrinsics::atomic_umin_acqrel(dst, val),
+        Relaxed => intrinsics::atomic_umin_relaxed(dst, val),
+        SeqCst => intrinsics::atomic_umin(dst, val),
+        __Nonexhaustive => panic!("invalid memory ordering"),
+    }
+}
+
 /// An atomic fence.
 ///
 /// Depending on the specified order, a fence prevents the compiler and CPU from
index f634fabe50399ebb595c00b29d57ec273f4cd6d8..a3667b3f3fee020f9ae973be79e542b1f47f584d 100644 (file)
@@ -104,8 +104,10 @@ fn int_xor() {
 
 #[test]
 fn static_init() {
-    assert!(!S_FALSE.load(SeqCst));
-    assert!(S_TRUE.load(SeqCst));
-    assert!(S_INT.load(SeqCst) == 0);
-    assert!(S_UINT.load(SeqCst) == 0);
+    // Note that we're not really testing the mutability here but it's important
+    // on Android at the moment (#49775)
+    assert!(!S_FALSE.swap(true, SeqCst));
+    assert!(S_TRUE.swap(false, SeqCst));
+    assert!(S_INT.fetch_add(1, SeqCst) == 0);
+    assert!(S_UINT.fetch_add(1, SeqCst) == 0);
 }
index de7211e718c9f20333b33a576cbf019f71cc1389..c3162899bbd0184ffcb21391e105d9de868be915 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![deny(warnings)]
-
 #![feature(ascii_ctype)]
 #![feature(box_syntax)]
 #![feature(core_float)]
 #![feature(fmt_internals)]
 #![feature(hashmap_internals)]
 #![feature(iterator_step_by)]
-#![cfg_attr(stage0, feature(i128_type))]
-#![cfg_attr(stage0, feature(inclusive_range_syntax))]
 #![feature(iterator_flatten)]
-#![cfg_attr(stage0, feature(conservative_impl_trait))]
 #![feature(iterator_repeat_with)]
 #![feature(nonzero)]
 #![feature(pattern)]
index 0f45f965104cadff7b8cce5e168e73a0036cf36b..a551b1b770a68f1b7fa90cdfdf9f20812e6c86da 100644 (file)
@@ -19,7 +19,6 @@
        html_root_url = "https://doc.rust-lang.org/nightly/",
        html_playground_url = "https://play.rust-lang.org/",
        test(attr(deny(warnings))))]
-#![deny(warnings)]
 
 pub use self::Piece::*;
 pub use self::Position::*;
index d8c366d2413d9cf15975eb67bf64feb49b5de58f..158d0101515860af76c7562e987267a7818a2102 100644 (file)
        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "https://doc.rust-lang.org/nightly/",
        test(attr(allow(unused_variables), deny(warnings))))]
-#![deny(warnings)]
 
 #![feature(str_escape)]
 
index e0eac41f49ec92b1ada6f8c0c027e811161fcd2a..633d273b3b93cd49834bd972a5dce5ab106a7ae1 100644 (file)
@@ -12,3 +12,4 @@ doc = false
 [dependencies]
 core = { path = "../libcore" }
 libc = { path = "../rustc/libc_shim" }
+compiler_builtins = { path = "../rustc/compiler_builtins_shim" }
index 5f768ef4399e88fc12771aab5a6f892c263a66be..43c5bbbc618c2954edf7a2580102ad8932acc7ae 100644 (file)
@@ -19,7 +19,6 @@
        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "https://doc.rust-lang.org/nightly/",
        issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/")]
-#![deny(warnings)]
 #![panic_runtime]
 #![allow(unused_features)]
 
index a978ea16e9e74245ecd355fe6dab581c6d005463..74aaa4d5ae3db6bf606fbcad57a1866324826fba 100644 (file)
@@ -14,3 +14,4 @@ alloc = { path = "../liballoc" }
 core = { path = "../libcore" }
 libc = { path = "../rustc/libc_shim" }
 unwind = { path = "../libunwind" }
+compiler_builtins = { path = "../rustc/compiler_builtins_shim" }
index ca2fd561cadcfcc75d9bb719cc5937fee4227b31..eb6dc5b5488694ee05a74e7378e32388674e4131 100644 (file)
@@ -286,8 +286,7 @@ unsafe fn find_eh_action(context: *mut uw::_Unwind_Context)
 // See docs in the `unwind` module.
 #[cfg(all(target_os="windows", target_arch = "x86", target_env="gnu"))]
 #[lang = "eh_unwind_resume"]
-#[cfg_attr(stage0, unwind)]
-#[cfg_attr(not(stage0), unwind(allowed))]
+#[unwind(allowed)]
 unsafe extern "C" fn rust_eh_unwind_resume(panic_ctx: *mut u8) -> ! {
     uw::_Unwind_Resume(panic_ctx as *mut uw::_Unwind_Exception);
 }
index a5cebc3e4d04b6eee6b74854f82d1146508878d9..9321d6917d1566db3ef070a9c35066c0ef8b1007 100644 (file)
@@ -28,7 +28,6 @@
        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "https://doc.rust-lang.org/nightly/",
        issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/")]
-#![deny(warnings)]
 
 #![feature(alloc)]
 #![feature(core_intrinsics)]
 // Entry point for raising an exception, just delegates to the platform-specific
 // implementation.
 #[no_mangle]
-#[cfg_attr(stage0, unwind)]
-#[cfg_attr(not(stage0), unwind(allowed))]
+#[unwind(allowed)]
 pub unsafe extern "C" fn __rust_start_panic(data: usize, vtable: usize) -> u32 {
     imp::panic(mem::transmute(raw::TraitObject {
         data: data as *mut (),
index 090cd095380ee8dfcaffdaeb3600e664130105b3..c3715f96c6482eb7f234a04db1db26eac44d5eeb 100644 (file)
@@ -108,8 +108,7 @@ pub unsafe fn cleanup(ptr: *mut u8) -> Box<Any + Send> {
 }
 
 #[lang = "eh_unwind_resume"]
-#[cfg_attr(stage0, unwind)]
-#[cfg_attr(not(stage0), unwind(allowed))]
+#[unwind(allowed)]
 unsafe extern "C" fn rust_eh_unwind_resume(panic_ctx: c::LPVOID) -> ! {
     let params = [panic_ctx as c::ULONG_PTR];
     c::RaiseException(RUST_PANIC,
index 50fba5faee747facb0f1309ebd900411f912982e..5f1dda36a889ea0aff118b969d5da63d37f9d3ef 100644 (file)
@@ -79,21 +79,18 @@ pub enum EXCEPTION_DISPOSITION {
 pub use self::EXCEPTION_DISPOSITION::*;
 
 extern "system" {
-    #[cfg_attr(stage0, unwind)]
-    #[cfg_attr(not(stage0), unwind(allowed))]
+    #[unwind(allowed)]
     pub fn RaiseException(dwExceptionCode: DWORD,
                           dwExceptionFlags: DWORD,
                           nNumberOfArguments: DWORD,
                           lpArguments: *const ULONG_PTR);
-    #[cfg_attr(stage0, unwind)]
-    #[cfg_attr(not(stage0), unwind(allowed))]
+    #[unwind(allowed)]
     pub fn RtlUnwindEx(TargetFrame: LPVOID,
                        TargetIp: LPVOID,
                        ExceptionRecord: *const EXCEPTION_RECORD,
                        ReturnValue: LPVOID,
                        OriginalContext: *const CONTEXT,
                        HistoryTable: *const UNWIND_HISTORY_TABLE);
-    #[cfg_attr(stage0, unwind)]
-    #[cfg_attr(not(stage0), unwind(allowed))]
+    #[unwind(allowed)]
     pub fn _CxxThrowException(pExceptionObject: *mut c_void, pThrowInfo: *mut u8);
 }
index 007093981d3e19a6ee1ce62557b53627fc50c432..dafdacfdd7247d02d19679d1dd99883fa5d99302 100644 (file)
@@ -24,7 +24,6 @@
 //! See [the book](../book/first-edition/procedural-macros.html) for more.
 
 #![stable(feature = "proc_macro_lib", since = "1.15.0")]
-#![deny(warnings)]
 #![deny(missing_docs)]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
@@ -34,7 +33,6 @@
        test(no_crate_inject, attr(deny(warnings))),
        test(attr(allow(dead_code, deprecated, unused_variables, unused_mut))))]
 
-#![cfg_attr(stage0, feature(i128_type))]
 #![feature(rustc_private)]
 #![feature(staged_api)]
 #![feature(lang_items)]
@@ -59,7 +57,7 @@
 use syntax::parse::{self, token};
 use syntax::symbol::Symbol;
 use syntax::tokenstream;
-use syntax_pos::DUMMY_SP;
+use syntax::parse::lexer::comments;
 use syntax_pos::{FileMap, Pos, SyntaxContext, FileName};
 use syntax_pos::hygiene::Mark;
 
@@ -73,7 +71,7 @@
 /// The API of this type is intentionally bare-bones, but it'll be expanded over
 /// time!
 #[stable(feature = "proc_macro_lib", since = "1.15.0")]
-#[derive(Clone, Debug)]
+#[derive(Clone)]
 pub struct TokenStream(tokenstream::TokenStream);
 
 /// Error returned from `TokenStream::from_str`.
@@ -83,6 +81,20 @@ pub struct LexError {
     _inner: (),
 }
 
+impl TokenStream {
+    /// Returns an empty `TokenStream`.
+    #[unstable(feature = "proc_macro", issue = "38356")]
+    pub fn empty() -> TokenStream {
+        TokenStream(tokenstream::TokenStream::empty())
+    }
+
+    /// Checks if this `TokenStream` is empty.
+    #[unstable(feature = "proc_macro", issue = "38356")]
+    pub fn is_empty(&self) -> bool {
+        self.0.is_empty()
+    }
+}
+
 #[stable(feature = "proc_macro_lib", since = "1.15.0")]
 impl FromStr for TokenStream {
     type Err = LexError;
@@ -110,19 +122,13 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
-/// `quote!(..)` accepts arbitrary tokens and expands into a `TokenStream` describing the input.
-/// For example, `quote!(a + b)` will produce a expression, that, when evaluated, constructs
-/// the `TokenStream` `[Word("a"), Op('+', Alone), Word("b")]`.
-///
-/// Unquoting is done with `$`, and works by taking the single next ident as the unquoted term.
-/// To quote `$` itself, use `$$`.
-#[unstable(feature = "proc_macro", issue = "38356")]
-#[macro_export]
-macro_rules! quote { () => {} }
-
-#[unstable(feature = "proc_macro_internals", issue = "27812")]
-#[doc(hidden)]
-mod quote;
+#[stable(feature = "proc_macro_lib", since = "1.15.0")]
+impl fmt::Debug for TokenStream {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.write_str("TokenStream ")?;
+        f.debug_list().entries(self.clone()).finish()
+    }
+}
 
 #[unstable(feature = "proc_macro", issue = "38356")]
 impl From<TokenTree> for TokenStream {
@@ -132,62 +138,79 @@ fn from(tree: TokenTree) -> TokenStream {
 }
 
 #[unstable(feature = "proc_macro", issue = "38356")]
-impl From<TokenNode> for TokenStream {
-    fn from(kind: TokenNode) -> TokenStream {
-        TokenTree::from(kind).into()
-    }
-}
-
-#[unstable(feature = "proc_macro", issue = "38356")]
-impl<T: Into<TokenStream>> iter::FromIterator<T> for TokenStream {
-    fn from_iter<I: IntoIterator<Item = T>>(streams: I) -> Self {
+impl iter::FromIterator<TokenTree> for TokenStream {
+    fn from_iter<I: IntoIterator<Item = TokenTree>>(trees: I) -> Self {
         let mut builder = tokenstream::TokenStreamBuilder::new();
-        for stream in streams {
-            builder.push(stream.into().0);
+        for tree in trees {
+            builder.push(tree.to_internal());
         }
         TokenStream(builder.build())
     }
 }
 
+/// Implementation details for the `TokenTree` type, such as iterators.
 #[unstable(feature = "proc_macro", issue = "38356")]
-impl IntoIterator for TokenStream {
-    type Item = TokenTree;
-    type IntoIter = TokenTreeIter;
+pub mod token_stream {
+    use syntax::tokenstream;
+    use syntax_pos::DUMMY_SP;
 
-    fn into_iter(self) -> TokenTreeIter {
-        TokenTreeIter { cursor: self.0.trees(), stack: Vec::new() }
+    use {TokenTree, TokenStream, Delimiter};
+
+    /// An iterator over `TokenTree`s.
+    #[derive(Clone)]
+    #[unstable(feature = "proc_macro", issue = "38356")]
+    pub struct IntoIter {
+        cursor: tokenstream::Cursor,
+        stack: Vec<TokenTree>,
     }
-}
 
-impl TokenStream {
-    /// Returns an empty `TokenStream`.
     #[unstable(feature = "proc_macro", issue = "38356")]
-    pub fn empty() -> TokenStream {
-        TokenStream(tokenstream::TokenStream::empty())
+    impl Iterator for IntoIter {
+        type Item = TokenTree;
+
+        fn next(&mut self) -> Option<TokenTree> {
+            loop {
+                let tree = self.stack.pop().or_else(|| {
+                    let next = self.cursor.next_as_stream()?;
+                    Some(TokenTree::from_internal(next, &mut self.stack))
+                })?;
+                if tree.span().0 == DUMMY_SP {
+                    if let TokenTree::Group(ref group) = tree {
+                        if group.delimiter() == Delimiter::None {
+                            self.cursor.insert(group.stream.clone().0);
+                            continue
+                        }
+                    }
+                }
+                return Some(tree);
+            }
+        }
     }
 
-    /// Checks if this `TokenStream` is empty.
     #[unstable(feature = "proc_macro", issue = "38356")]
-    pub fn is_empty(&self) -> bool {
-        self.0.is_empty()
+    impl IntoIterator for TokenStream {
+        type Item = TokenTree;
+        type IntoIter = IntoIter;
+
+        fn into_iter(self) -> IntoIter {
+            IntoIter { cursor: self.0.trees(), stack: Vec::new() }
+        }
     }
 }
 
-/// A region of source code, along with macro expansion information.
+/// `quote!(..)` accepts arbitrary tokens and expands into a `TokenStream` describing the input.
+/// For example, `quote!(a + b)` will produce a expression, that, when evaluated, constructs
+/// the `TokenStream` `[Word("a"), Op('+', Alone), Word("b")]`.
+///
+/// Unquoting is done with `$`, and works by taking the single next ident as the unquoted term.
+/// To quote `$` itself, use `$$`.
 #[unstable(feature = "proc_macro", issue = "38356")]
-#[derive(Copy, Clone, Debug, PartialEq, Eq)]
-pub struct Span(syntax_pos::Span);
+#[macro_export]
+macro_rules! quote { () => {} }
 
-impl Span {
-    /// A span that resolves at the macro definition site.
-    #[unstable(feature = "proc_macro", issue = "38356")]
-    pub fn def_site() -> Span {
-        ::__internal::with_sess(|(_, mark)| {
-            let call_site = mark.expn_info().unwrap().call_site;
-            Span(call_site.with_ctxt(SyntaxContext::empty().apply_mark(mark)))
-        })
-    }
-}
+#[unstable(feature = "proc_macro_internals", issue = "27812")]
+#[doc(hidden)]
+mod quote;
 
 /// Quote a `Span` into a `TokenStream`.
 /// This is needed to implement a custom quoter.
@@ -196,6 +219,11 @@ pub fn quote_span(span: Span) -> TokenStream {
     quote::Quote::quote(span)
 }
 
+/// A region of source code, along with macro expansion information.
+#[unstable(feature = "proc_macro", issue = "38356")]
+#[derive(Copy, Clone)]
+pub struct Span(syntax_pos::Span);
+
 macro_rules! diagnostic_method {
     ($name:ident, $level:expr) => (
         /// Create a new `Diagnostic` with the given `message` at the span
@@ -208,6 +236,15 @@ pub fn $name<T: Into<String>>(self, message: T) -> Diagnostic {
 }
 
 impl Span {
+    /// A span that resolves at the macro definition site.
+    #[unstable(feature = "proc_macro", issue = "38356")]
+    pub fn def_site() -> Span {
+        ::__internal::with_sess(|(_, mark)| {
+            let call_site = mark.expn_info().unwrap().call_site;
+            Span(call_site.with_ctxt(SyntaxContext::empty().apply_mark(mark)))
+        })
+    }
+
     /// The span of the invocation of the current procedural macro.
     #[unstable(feature = "proc_macro", issue = "38356")]
     pub fn call_site() -> Span {
@@ -284,12 +321,28 @@ pub fn located_at(&self, other: Span) -> Span {
         other.resolved_at(*self)
     }
 
+    /// Compares to spans to see if they're equal.
+    #[unstable(feature = "proc_macro", issue = "38356")]
+    pub fn eq(&self, other: &Span) -> bool {
+        self.0 == other.0
+    }
+
     diagnostic_method!(error, Level::Error);
     diagnostic_method!(warning, Level::Warning);
     diagnostic_method!(note, Level::Note);
     diagnostic_method!(help, Level::Help);
 }
 
+#[unstable(feature = "proc_macro", issue = "38356")]
+impl fmt::Debug for Span {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{:?} bytes({}..{})",
+               self.0.ctxt(),
+               self.0.lo().0,
+               self.0.hi().0)
+    }
+}
+
 /// A line-column pair representing the start or end of a `Span`.
 #[unstable(feature = "proc_macro", issue = "38356")]
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
@@ -378,40 +431,112 @@ fn eq(&self, other: &FileName) -> bool {
 
 /// A single token or a delimited sequence of token trees (e.g. `[1, (), ..]`).
 #[unstable(feature = "proc_macro", issue = "38356")]
-#[derive(Clone, Debug)]
-pub struct TokenTree {
-    /// The `TokenTree`'s span
-    pub span: Span,
-    /// Description of the `TokenTree`
-    pub kind: TokenNode,
+#[derive(Clone)]
+pub enum TokenTree {
+    /// A delimited tokenstream
+    Group(Group),
+    /// A unicode identifier
+    Term(Term),
+    /// A punctuation character (`+`, `,`, `$`, etc.).
+    Op(Op),
+    /// A literal character (`'a'`), string (`"hello"`), number (`2.3`), etc.
+    Literal(Literal),
+}
+
+impl TokenTree {
+    /// Returns the span of this token, accessing the `span` method of each of
+    /// the internal tokens.
+    #[unstable(feature = "proc_macro", issue = "38356")]
+    pub fn span(&self) -> Span {
+        match *self {
+            TokenTree::Group(ref t) => t.span(),
+            TokenTree::Term(ref t) => t.span(),
+            TokenTree::Op(ref t) => t.span(),
+            TokenTree::Literal(ref t) => t.span(),
+        }
+    }
+
+    /// Configures the span for *only this token*.
+    ///
+    /// Note that if this token is a `Group` then this method will not configure
+    /// the span of each of the internal tokens, this will simply delegate to
+    /// the `set_span` method of each variant.
+    #[unstable(feature = "proc_macro", issue = "38356")]
+    pub fn set_span(&mut self, span: Span) {
+        match *self {
+            TokenTree::Group(ref mut t) => t.set_span(span),
+            TokenTree::Term(ref mut t) => t.set_span(span),
+            TokenTree::Op(ref mut t) => t.set_span(span),
+            TokenTree::Literal(ref mut t) => t.set_span(span),
+        }
+    }
+}
+
+#[unstable(feature = "proc_macro", issue = "38356")]
+impl fmt::Debug for TokenTree {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        // Each of these has the name in the struct type in the derived debug,
+        // so don't bother with an extra layer of indirection
+        match *self {
+            TokenTree::Group(ref tt) => tt.fmt(f),
+            TokenTree::Term(ref tt) => tt.fmt(f),
+            TokenTree::Op(ref tt) => tt.fmt(f),
+            TokenTree::Literal(ref tt) => tt.fmt(f),
+        }
+    }
+}
+
+#[unstable(feature = "proc_macro", issue = "38356")]
+impl From<Group> for TokenTree {
+    fn from(g: Group) -> TokenTree {
+        TokenTree::Group(g)
+    }
 }
 
 #[unstable(feature = "proc_macro", issue = "38356")]
-impl From<TokenNode> for TokenTree {
-    fn from(kind: TokenNode) -> TokenTree {
-        TokenTree { span: Span::def_site(), kind: kind }
+impl From<Term> for TokenTree {
+    fn from(g: Term) -> TokenTree {
+        TokenTree::Term(g)
+    }
+}
+
+#[unstable(feature = "proc_macro", issue = "38356")]
+impl From<Op> for TokenTree {
+    fn from(g: Op) -> TokenTree {
+        TokenTree::Op(g)
+    }
+}
+
+#[unstable(feature = "proc_macro", issue = "38356")]
+impl From<Literal> for TokenTree {
+    fn from(g: Literal) -> TokenTree {
+        TokenTree::Literal(g)
     }
 }
 
 #[unstable(feature = "proc_macro", issue = "38356")]
 impl fmt::Display for TokenTree {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        TokenStream::from(self.clone()).fmt(f)
+        match *self {
+            TokenTree::Group(ref t) => t.fmt(f),
+            TokenTree::Term(ref t) => t.fmt(f),
+            TokenTree::Op(ref t) => t.fmt(f),
+            TokenTree::Literal(ref t) => t.fmt(f),
+        }
     }
 }
 
-/// Description of a `TokenTree`
+/// A delimited token stream
+///
+/// A `Group` internally contains a `TokenStream` which is delimited by a
+/// `Delimiter`. Groups represent multiple tokens internally and have a `Span`
+/// for the entire stream.
 #[derive(Clone, Debug)]
 #[unstable(feature = "proc_macro", issue = "38356")]
-pub enum TokenNode {
-    /// A delimited tokenstream.
-    Group(Delimiter, TokenStream),
-    /// A unicode identifier.
-    Term(Term),
-    /// A punctuation character (`+`, `,`, `$`, etc.).
-    Op(char, Spacing),
-    /// A literal character (`'a'`), string (`"hello"`), or number (`2.3`).
-    Literal(Literal),
+pub struct Group {
+    delimiter: Delimiter,
+    stream: TokenStream,
+    span: Span,
 }
 
 /// Describes how a sequence of token trees is delimited.
@@ -428,25 +553,74 @@ pub enum Delimiter {
     None,
 }
 
-/// An interned string.
-#[derive(Copy, Clone, Debug)]
-#[unstable(feature = "proc_macro", issue = "38356")]
-pub struct Term(Symbol);
+impl Group {
+    /// Creates a new `group` with the given delimiter and token stream.
+    ///
+    /// This constructor will set the span for this group to
+    /// `Span::call_site()`. To change the span you can use the `set_span`
+    /// method below.
+    #[unstable(feature = "proc_macro", issue = "38356")]
+    pub fn new(delimiter: Delimiter, stream: TokenStream) -> Group {
+        Group {
+            delimiter: delimiter,
+            stream: stream,
+            span: Span::call_site(),
+        }
+    }
 
-impl Term {
-    /// Intern a string into a `Term`.
+    /// Returns the delimiter of this `Group`
     #[unstable(feature = "proc_macro", issue = "38356")]
-    pub fn intern(string: &str) -> Term {
-        Term(Symbol::intern(string))
+    pub fn delimiter(&self) -> Delimiter {
+        self.delimiter
     }
 
-    /// Get a reference to the interned string.
+    /// Returns the `TokenStream` of tokens that are delimited in this `Group`.
+    ///
+    /// Note that the returned token stream does not include the delimiter
+    /// returned above.
     #[unstable(feature = "proc_macro", issue = "38356")]
-    pub fn as_str(&self) -> &str {
-        unsafe { &*(&*self.0.as_str() as *const str) }
+    pub fn stream(&self) -> TokenStream {
+        self.stream.clone()
+    }
+
+    /// Returns the span for the delimiters of this token stream, spanning the
+    /// entire `Group`.
+    #[unstable(feature = "proc_macro", issue = "38356")]
+    pub fn span(&self) -> Span {
+        self.span
+    }
+
+    /// Configures the span for this `Group`'s delimiters, but not its internal
+    /// tokens.
+    ///
+    /// This method will **not** set the span of all the internal tokens spanned
+    /// by this group, but rather it will only set the span of the delimiter
+    /// tokens at the level of the `Group`.
+    #[unstable(feature = "proc_macro", issue = "38356")]
+    pub fn set_span(&mut self, span: Span) {
+        self.span = span;
     }
 }
 
+#[unstable(feature = "proc_macro", issue = "38356")]
+impl fmt::Display for Group {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        TokenStream::from(TokenTree::from(self.clone())).fmt(f)
+    }
+}
+
+/// An `Op` is an operator like `+` or `-`, and only represents one character.
+///
+/// Operators like `+=` are represented as two instance of `Op` with different
+/// forms of `Spacing` returned.
+#[unstable(feature = "proc_macro", issue = "38356")]
+#[derive(Copy, Clone, Debug)]
+pub struct Op {
+    op: char,
+    spacing: Spacing,
+    span: Span,
+}
+
 /// Whether an `Op` is either followed immediately by another `Op` or followed by whitespace.
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
 #[unstable(feature = "proc_macro", issue = "38356")]
@@ -457,68 +631,285 @@ pub enum Spacing {
     Joint,
 }
 
-/// A literal character (`'a'`), string (`"hello"`), or number (`2.3`).
-#[derive(Clone, Debug)]
+impl Op {
+    /// Creates a new `Op` from the given character and spacing.
+    ///
+    /// The returned `Op` will have the default span of `Span::call_site()`
+    /// which can be further configured with the `set_span` method below.
+    #[unstable(feature = "proc_macro", issue = "38356")]
+    pub fn new(op: char, spacing: Spacing) -> Op {
+        Op {
+            op: op,
+            spacing: spacing,
+            span: Span::call_site(),
+        }
+    }
+
+    /// Returns the character this operation represents, for example `'+'`
+    #[unstable(feature = "proc_macro", issue = "38356")]
+    pub fn op(&self) -> char {
+        self.op
+    }
+
+    /// Returns the spacing of this operator, indicating whether it's a joint
+    /// operator with more operators coming next in the token stream or an
+    /// `Alone` meaning that the operator has ended.
+    #[unstable(feature = "proc_macro", issue = "38356")]
+    pub fn spacing(&self) -> Spacing {
+        self.spacing
+    }
+
+    /// Returns the span for this operator character
+    #[unstable(feature = "proc_macro", issue = "38356")]
+    pub fn span(&self) -> Span {
+        self.span
+    }
+
+    /// Configure the span for this operator's character
+    #[unstable(feature = "proc_macro", issue = "38356")]
+    pub fn set_span(&mut self, span: Span) {
+        self.span = span;
+    }
+}
+
 #[unstable(feature = "proc_macro", issue = "38356")]
-pub struct Literal(token::Token);
+impl fmt::Display for Op {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        TokenStream::from(TokenTree::from(self.clone())).fmt(f)
+    }
+}
 
+/// An interned string.
+#[derive(Copy, Clone, Debug)]
 #[unstable(feature = "proc_macro", issue = "38356")]
-impl fmt::Display for Literal {
+pub struct Term {
+    sym: Symbol,
+    span: Span,
+}
+
+impl Term {
+    /// Creates a new `Term` with the given `string` as well as the specified
+    /// `span`.
+    ///
+    /// Note that `span`, currently in rustc, configures the hygiene information
+    /// for this identifier. As of this time `Span::call_site()` explicitly
+    /// opts-in to **non-hygienic** information (aka copy/pasted code) while
+    /// spans like `Span::def_site()` will opt-in to hygienic information,
+    /// meaning that code at the call site of the macro can't access this
+    /// identifier.
+    ///
+    /// Due to the current importance of hygiene this constructor, unlike other
+    /// tokens, requires a `Span` to be specified at construction.
+    #[unstable(feature = "proc_macro", issue = "38356")]
+    pub fn new(string: &str, span: Span) -> Term {
+        Term {
+            sym: Symbol::intern(string),
+            span,
+        }
+    }
+
+    /// Get a reference to the interned string.
+    #[unstable(feature = "proc_macro", issue = "38356")]
+    pub fn as_str(&self) -> &str {
+        unsafe { &*(&*self.sym.as_str() as *const str) }
+    }
+
+    /// Returns the span of this `Term`, encompassing the entire string returned
+    /// by `as_str`.
+    #[unstable(feature = "proc_macro", issue = "38356")]
+    pub fn span(&self) -> Span {
+        self.span
+    }
+
+    /// Configures the span of this `Term`, possibly changing hygiene
+    /// information.
+    #[unstable(feature = "proc_macro", issue = "38356")]
+    pub fn set_span(&mut self, span: Span) {
+        self.span = span;
+    }
+}
+
+#[unstable(feature = "proc_macro", issue = "38356")]
+impl fmt::Display for Term {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        TokenTree { kind: TokenNode::Literal(self.clone()), span: Span(DUMMY_SP) }.fmt(f)
+        self.as_str().fmt(f)
     }
 }
 
-macro_rules! int_literals {
-    ($($int_kind:ident),*) => {$(
-        /// Integer literal.
+/// A literal character (`'a'`), string (`"hello"`), a number (`2.3`), etc.
+#[derive(Clone, Debug)]
+#[unstable(feature = "proc_macro", issue = "38356")]
+pub struct Literal {
+    lit: token::Lit,
+    suffix: Option<ast::Name>,
+    span: Span,
+}
+
+macro_rules! suffixed_int_literals {
+    ($($name:ident => $kind:ident,)*) => ($(
+        /// Creates a new suffixed integer literal with the specified value.
+        ///
+        /// This function will create an integer like `1u32` where the integer
+        /// value specified is the first part of the token and the integral is
+        /// also suffixed at the end.
+        ///
+        /// Literals created through this method have the `Span::call_site()`
+        /// span by default, which can be configured with the `set_span` method
+        /// below.
         #[unstable(feature = "proc_macro", issue = "38356")]
-        pub fn $int_kind(n: $int_kind) -> Literal {
-            Literal::typed_integer(n as i128, stringify!($int_kind))
+        pub fn $name(n: $kind) -> Literal {
+            Literal {
+                lit: token::Lit::Integer(Symbol::intern(&n.to_string())),
+                suffix: Some(Symbol::intern(stringify!($kind))),
+                span: Span::call_site(),
+            }
+        }
+    )*)
+}
+
+macro_rules! unsuffixed_int_literals {
+    ($($name:ident => $kind:ident,)*) => ($(
+        /// Creates a new unsuffixed integer literal with the specified value.
+        ///
+        /// This function will create an integer like `1` where the integer
+        /// value specified is the first part of the token. No suffix is
+        /// specified on this token, meaning that invocations like
+        /// `Literal::i8_unsuffixed(1)` are equivalent to
+        /// `Literal::u32_unsuffixed(1)`.
+        ///
+        /// Literals created through this method have the `Span::call_site()`
+        /// span by default, which can be configured with the `set_span` method
+        /// below.
+        #[unstable(feature = "proc_macro", issue = "38356")]
+        pub fn $name(n: $kind) -> Literal {
+            Literal {
+                lit: token::Lit::Integer(Symbol::intern(&n.to_string())),
+                suffix: None,
+                span: Span::call_site(),
+            }
         }
-    )*}
+    )*)
 }
 
 impl Literal {
-    /// Integer literal
-    #[unstable(feature = "proc_macro", issue = "38356")]
-    pub fn integer(n: i128) -> Literal {
-        Literal(token::Literal(token::Lit::Integer(Symbol::intern(&n.to_string())), None))
+    suffixed_int_literals! {
+        u8_suffixed => u8,
+        u16_suffixed => u16,
+        u32_suffixed => u32,
+        u64_suffixed => u64,
+        u128_suffixed => u128,
+        usize_suffixed => usize,
+        i8_suffixed => i8,
+        i16_suffixed => i16,
+        i32_suffixed => i32,
+        i64_suffixed => i64,
+        i128_suffixed => i128,
+        isize_suffixed => isize,
+    }
+
+    unsuffixed_int_literals! {
+        u8_unsuffixed => u8,
+        u16_unsuffixed => u16,
+        u32_unsuffixed => u32,
+        u64_unsuffixed => u64,
+        u128_unsuffixed => u128,
+        usize_unsuffixed => usize,
+        i8_unsuffixed => i8,
+        i16_unsuffixed => i16,
+        i32_unsuffixed => i32,
+        i64_unsuffixed => i64,
+        i128_unsuffixed => i128,
+        isize_unsuffixed => isize,
     }
 
-    int_literals!(u8, i8, u16, i16, u32, i32, u64, i64, usize, isize);
-    fn typed_integer(n: i128, kind: &'static str) -> Literal {
-        Literal(token::Literal(token::Lit::Integer(Symbol::intern(&n.to_string())),
-                               Some(Symbol::intern(kind))))
+    /// Creates a new unsuffixed floating-point literal.
+    ///
+    /// This constructor is similar to those like `Literal::i8_unsuffixed` where
+    /// the float's value is emitted directly into the token but no suffix is
+    /// used, so it may be inferred to be a `f64` later in the compiler.
+    ///
+    /// # Panics
+    ///
+    /// This function requires that the specified float is finite, for
+    /// example if it is infinity or NaN this function will panic.
+    #[unstable(feature = "proc_macro", issue = "38356")]
+    pub fn f32_unsuffixed(n: f32) -> Literal {
+        if !n.is_finite() {
+            panic!("Invalid float literal {}", n);
+        }
+        Literal {
+            lit: token::Lit::Float(Symbol::intern(&n.to_string())),
+            suffix: None,
+            span: Span::call_site(),
+        }
     }
 
-    /// Floating point literal.
+    /// Creates a new suffixed floating-point literal.
+    ///
+    /// This consturctor will create a literal like `1.0f32` where the value
+    /// specified is the preceding part of the token and `f32` is the suffix of
+    /// the token. This token will always be inferred to be an `f32` in the
+    /// compiler.
+    ///
+    /// # Panics
+    ///
+    /// This function requires that the specified float is finite, for
+    /// example if it is infinity or NaN this function will panic.
     #[unstable(feature = "proc_macro", issue = "38356")]
-    pub fn float(n: f64) -> Literal {
+    pub fn f32_suffixed(n: f32) -> Literal {
         if !n.is_finite() {
             panic!("Invalid float literal {}", n);
         }
-        Literal(token::Literal(token::Lit::Float(Symbol::intern(&n.to_string())), None))
+        Literal {
+            lit: token::Lit::Float(Symbol::intern(&n.to_string())),
+            suffix: Some(Symbol::intern("f32")),
+            span: Span::call_site(),
+        }
     }
 
-    /// Floating point literal.
+    /// Creates a new unsuffixed floating-point literal.
+    ///
+    /// This constructor is similar to those like `Literal::i8_unsuffixed` where
+    /// the float's value is emitted directly into the token but no suffix is
+    /// used, so it may be inferred to be a `f64` later in the compiler.
+    ///
+    /// # Panics
+    ///
+    /// This function requires that the specified float is finite, for
+    /// example if it is infinity or NaN this function will panic.
     #[unstable(feature = "proc_macro", issue = "38356")]
-    pub fn f32(n: f32) -> Literal {
+    pub fn f64_unsuffixed(n: f64) -> Literal {
         if !n.is_finite() {
-            panic!("Invalid f32 literal {}", n);
+            panic!("Invalid float literal {}", n);
+        }
+        Literal {
+            lit: token::Lit::Float(Symbol::intern(&n.to_string())),
+            suffix: None,
+            span: Span::call_site(),
         }
-        Literal(token::Literal(token::Lit::Float(Symbol::intern(&n.to_string())),
-                               Some(Symbol::intern("f32"))))
     }
 
-    /// Floating point literal.
+    /// Creates a new suffixed floating-point literal.
+    ///
+    /// This consturctor will create a literal like `1.0f64` where the value
+    /// specified is the preceding part of the token and `f64` is the suffix of
+    /// the token. This token will always be inferred to be an `f64` in the
+    /// compiler.
+    ///
+    /// # Panics
+    ///
+    /// This function requires that the specified float is finite, for
+    /// example if it is infinity or NaN this function will panic.
     #[unstable(feature = "proc_macro", issue = "38356")]
-    pub fn f64(n: f64) -> Literal {
+    pub fn f64_suffixed(n: f64) -> Literal {
         if !n.is_finite() {
-            panic!("Invalid f64 literal {}", n);
+            panic!("Invalid float literal {}", n);
+        }
+        Literal {
+            lit: token::Lit::Float(Symbol::intern(&n.to_string())),
+            suffix: Some(Symbol::intern("f64")),
+            span: Span::call_site(),
         }
-        Literal(token::Literal(token::Lit::Float(Symbol::intern(&n.to_string())),
-                               Some(Symbol::intern("f64"))))
     }
 
     /// String literal.
@@ -528,7 +919,11 @@ pub fn string(string: &str) -> Literal {
         for ch in string.chars() {
             escaped.extend(ch.escape_debug());
         }
-        Literal(token::Literal(token::Lit::Str_(Symbol::intern(&escaped)), None))
+        Literal {
+            lit: token::Lit::Str_(Symbol::intern(&escaped)),
+            suffix: None,
+            span: Span::call_site(),
+        }
     }
 
     /// Character literal.
@@ -536,7 +931,11 @@ pub fn string(string: &str) -> Literal {
     pub fn character(ch: char) -> Literal {
         let mut escaped = String::new();
         escaped.extend(ch.escape_unicode());
-        Literal(token::Literal(token::Lit::Char(Symbol::intern(&escaped)), None))
+        Literal {
+            lit: token::Lit::Char(Symbol::intern(&escaped)),
+            suffix: None,
+            span: Span::call_site(),
+        }
     }
 
     /// Byte string literal.
@@ -544,36 +943,30 @@ pub fn character(ch: char) -> Literal {
     pub fn byte_string(bytes: &[u8]) -> Literal {
         let string = bytes.iter().cloned().flat_map(ascii::escape_default)
             .map(Into::<char>::into).collect::<String>();
-        Literal(token::Literal(token::Lit::ByteStr(Symbol::intern(&string)), None))
+        Literal {
+            lit: token::Lit::ByteStr(Symbol::intern(&string)),
+            suffix: None,
+            span: Span::call_site(),
+        }
     }
-}
 
-/// An iterator over `TokenTree`s.
-#[derive(Clone)]
-#[unstable(feature = "proc_macro", issue = "38356")]
-pub struct TokenTreeIter {
-    cursor: tokenstream::Cursor,
-    stack: Vec<TokenTree>,
+    /// Returns the span encompassing this literal.
+    #[unstable(feature = "proc_macro", issue = "38356")]
+    pub fn span(&self) -> Span {
+        self.span
+    }
+
+    /// Configures the span associated for this literal.
+    #[unstable(feature = "proc_macro", issue = "38356")]
+    pub fn set_span(&mut self, span: Span) {
+        self.span = span;
+    }
 }
 
 #[unstable(feature = "proc_macro", issue = "38356")]
-impl Iterator for TokenTreeIter {
-    type Item = TokenTree;
-
-    fn next(&mut self) -> Option<TokenTree> {
-        loop {
-            let tree = self.stack.pop().or_else(|| {
-                let next = self.cursor.next_as_stream()?;
-                Some(TokenTree::from_internal(next, &mut self.stack))
-            })?;
-            if tree.span.0 == DUMMY_SP {
-                if let TokenNode::Group(Delimiter::None, stream) = tree.kind {
-                    self.cursor.insert(stream.0);
-                    continue
-                }
-            }
-            return Some(tree);
-        }
+impl fmt::Display for Literal {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        TokenStream::from(TokenTree::from(self.clone())).fmt(f)
     }
 }
 
@@ -607,31 +1000,34 @@ fn from_internal(stream: tokenstream::TokenStream, stack: &mut Vec<TokenTree>)
             tokenstream::TokenTree::Token(span, token) => (span, token),
             tokenstream::TokenTree::Delimited(span, delimed) => {
                 let delimiter = Delimiter::from_internal(delimed.delim);
-                return TokenTree {
-                    span: Span(span),
-                    kind: TokenNode::Group(delimiter, TokenStream(delimed.tts.into())),
-                };
+                let mut g = Group::new(delimiter, TokenStream(delimed.tts.into()));
+                g.set_span(Span(span));
+                return g.into()
             }
         };
 
         let op_kind = if is_joint { Spacing::Joint } else { Spacing::Alone };
         macro_rules! tt {
-            ($e:expr) => (TokenTree { span: Span(span), kind: $e })
+            ($e:expr) => ({
+                let mut x = TokenTree::from($e);
+                x.set_span(Span(span));
+                x
+            })
         }
         macro_rules! op {
-            ($a:expr) => (TokenNode::Op($a, op_kind));
+            ($a:expr) => (tt!(Op::new($a, op_kind)));
             ($a:expr, $b:expr) => ({
-                stack.push(tt!(TokenNode::Op($b, op_kind).into()));
-                TokenNode::Op($a, Spacing::Joint)
+                stack.push(tt!(Op::new($b, op_kind)));
+                tt!(Op::new($a, Spacing::Joint))
             });
             ($a:expr, $b:expr, $c:expr) => ({
-                stack.push(tt!(TokenNode::Op($c, op_kind)));
-                stack.push(tt!(TokenNode::Op($b, Spacing::Joint)));
-                TokenNode::Op($a, Spacing::Joint)
+                stack.push(tt!(Op::new($c, op_kind)));
+                stack.push(tt!(Op::new($b, Spacing::Joint)));
+                tt!(Op::new($a, Spacing::Joint))
             })
         }
 
-        let kind = match token {
+        match token {
             Eq => op!('='),
             Lt => op!('<'),
             Le => op!('<', '='),
@@ -679,80 +1075,98 @@ macro_rules! op {
             Dollar => op!('$'),
             Question => op!('?'),
 
-            Ident(ident, false) | Lifetime(ident) => TokenNode::Term(Term(ident.name)),
-            Ident(ident, true) => TokenNode::Term(Term(Symbol::intern(&format!("r#{}", ident)))),
-            Literal(..) => TokenNode::Literal(self::Literal(token)),
+            Ident(ident, false) | Lifetime(ident) => {
+                tt!(Term::new(&ident.name.as_str(), Span(span)))
+            }
+            Ident(ident, true) => {
+                tt!(Term::new(&format!("r#{}", ident), Span(span)))
+            }
+            Literal(lit, suffix) => tt!(self::Literal { lit, suffix, span: Span(span) }),
             DocComment(c) => {
+                let style = comments::doc_comment_style(&c.as_str());
+                let stripped = comments::strip_doc_comment_decoration(&c.as_str());
                 let stream = vec![
-                    tt!(TokenNode::Term(Term::intern("doc"))),
-                    tt!(op!('=')),
-                    tt!(TokenNode::Literal(self::Literal(Literal(Lit::Str_(c), None)))),
+                    tt!(Term::new("doc", Span(span))),
+                    tt!(Op::new('=', Spacing::Alone)),
+                    tt!(self::Literal::string(&stripped)),
                 ].into_iter().collect();
-                stack.push(tt!(TokenNode::Group(Delimiter::Bracket, stream)));
-                op!('#')
+                stack.push(tt!(Group::new(Delimiter::Bracket, stream)));
+                if style == ast::AttrStyle::Inner {
+                    stack.push(tt!(Op::new('!', Spacing::Alone)));
+                }
+                tt!(Op::new('#', Spacing::Alone))
             }
 
             Interpolated(_) => {
                 __internal::with_sess(|(sess, _)| {
                     let tts = token.interpolated_to_tokenstream(sess, span);
-                    TokenNode::Group(Delimiter::None, TokenStream(tts))
+                    tt!(Group::new(Delimiter::None, TokenStream(tts)))
                 })
             }
 
             DotEq => op!('.', '='),
             OpenDelim(..) | CloseDelim(..) => unreachable!(),
             Whitespace | Comment | Shebang(..) | Eof => unreachable!(),
-        };
-
-        TokenTree { span: Span(span), kind: kind }
+        }
     }
 
     fn to_internal(self) -> tokenstream::TokenStream {
         use syntax::parse::token::*;
         use syntax::tokenstream::{TokenTree, Delimited};
 
-        let (op, kind) = match self.kind {
-            TokenNode::Op(op, kind) => (op, kind),
-            TokenNode::Group(delimiter, tokens) => {
-                return TokenTree::Delimited(self.span.0, Delimited {
-                    delim: delimiter.to_internal(),
-                    tts: tokens.0.into(),
+        let (op, kind, span) = match self {
+            self::TokenTree::Op(tt) => (tt.op(), tt.spacing(), tt.span()),
+            self::TokenTree::Group(tt) => {
+                return TokenTree::Delimited(tt.span.0, Delimited {
+                    delim: tt.delimiter.to_internal(),
+                    tts: tt.stream.0.into(),
                 }).into();
             },
-            TokenNode::Term(symbol) => {
-                let ident = ast::Ident { name: symbol.0, ctxt: self.span.0.ctxt() };
-                let sym_str = symbol.0.as_str();
-                let token =
-                    if sym_str.starts_with("'") { Lifetime(ident) }
-                    else if sym_str.starts_with("r#") {
-                        let name = Symbol::intern(&sym_str[2..]);
-                        let ident = ast::Ident { name, ctxt: self.span.0.ctxt() };
-                        Ident(ident, true)
-                    } else { Ident(ident, false) };
-                return TokenTree::Token(self.span.0, token).into();
+            self::TokenTree::Term(tt) => {
+                let ident = ast::Ident::new(tt.sym, tt.span.0);
+                let sym_str = tt.sym.as_str();
+                let token = if sym_str.starts_with("'") {
+                    Lifetime(ident)
+                } else if sym_str.starts_with("r#") {
+                    let name = Symbol::intern(&sym_str[2..]);
+                    let ident = ast::Ident::new(name, ident.span);
+                    Ident(ident, true)
+                } else {
+                    Ident(ident, false)
+                };
+                return TokenTree::Token(tt.span.0, token).into();
             }
-            TokenNode::Literal(self::Literal(Literal(Lit::Integer(ref a), b)))
+            self::TokenTree::Literal(self::Literal {
+                lit: Lit::Integer(ref a),
+                suffix,
+                span,
+            })
                 if a.as_str().starts_with("-") =>
             {
                 let minus = BinOp(BinOpToken::Minus);
                 let integer = Symbol::intern(&a.as_str()[1..]);
-                let integer = Literal(Lit::Integer(integer), b);
-                let a = TokenTree::Token(self.span.0, minus);
-                let b = TokenTree::Token(self.span.0, integer);
+                let integer = Literal(Lit::Integer(integer), suffix);
+                let a = TokenTree::Token(span.0, minus);
+                let b = TokenTree::Token(span.0, integer);
                 return vec![a, b].into_iter().collect()
             }
-            TokenNode::Literal(self::Literal(Literal(Lit::Float(ref a), b)))
+            self::TokenTree::Literal(self::Literal {
+                lit: Lit::Float(ref a),
+                suffix,
+                span,
+            })
                 if a.as_str().starts_with("-") =>
             {
                 let minus = BinOp(BinOpToken::Minus);
                 let float = Symbol::intern(&a.as_str()[1..]);
-                let float = Literal(Lit::Float(float), b);
-                let a = TokenTree::Token(self.span.0, minus);
-                let b = TokenTree::Token(self.span.0, float);
+                let float = Literal(Lit::Float(float), suffix);
+                let a = TokenTree::Token(span.0, minus);
+                let b = TokenTree::Token(span.0, float);
                 return vec![a, b].into_iter().collect()
             }
-            TokenNode::Literal(token) => {
-                return TokenTree::Token(self.span.0, token.0).into()
+            self::TokenTree::Literal(tt) => {
+                let token = Literal(tt.lit, tt.suffix);
+                return TokenTree::Token(tt.span.0, token).into()
             }
         };
 
@@ -781,7 +1195,7 @@ fn to_internal(self) -> tokenstream::TokenStream {
             _ => panic!("unsupported character {}", op),
         };
 
-        let tree = TokenTree::Token(self.span.0, token);
+        let tree = TokenTree::Token(span.0, token);
         match kind {
             Spacing::Alone => tree.into(),
             Spacing::Joint => tree.joint(),
index 8b5add1a0f0d70744261b96b37dcede510ca91ba..a0ec692809499f47152482115a5ea40ccd791fc9 100644 (file)
@@ -14,7 +14,7 @@
 //! This quasiquoter uses macros 2.0 hygiene to reliably access
 //! items from `proc_macro`, to build a `proc_macro::TokenStream`.
 
-use {Delimiter, Literal, Spacing, Span, Term, TokenNode, TokenStream, TokenTree};
+use {Delimiter, Literal, Spacing, Span, Term, Op, Group, TokenStream, TokenTree};
 
 use syntax::ext::base::{ExtCtxt, ProcMacro};
 use syntax::parse::token;
 pub struct Quoter;
 
 pub fn unquote<T: Into<TokenStream> + Clone>(tokens: &T) -> TokenStream {
-    T::into(tokens.clone())
+    tokens.clone().into()
 }
 
 pub trait Quote {
     fn quote(self) -> TokenStream;
 }
 
+macro_rules! tt2ts {
+    ($e:expr) => (TokenStream::from(TokenTree::from($e)))
+}
+
 macro_rules! quote_tok {
-    (,) => { TokenNode::Op(',', Spacing::Alone) };
-    (.) => { TokenNode::Op('.', Spacing::Alone) };
-    (:) => { TokenNode::Op(':', Spacing::Alone) };
+    (,) => { tt2ts!(Op::new(',', Spacing::Alone)) };
+    (.) => { tt2ts!(Op::new('.', Spacing::Alone)) };
+    (:) => { tt2ts!(Op::new(':', Spacing::Alone)) };
+    (|) => { tt2ts!(Op::new('|', Spacing::Alone)) };
     (::) => {
         [
-            TokenNode::Op(':', Spacing::Joint),
-            TokenNode::Op(':', Spacing::Alone)
-        ].iter().cloned().collect::<TokenStream>()
+            TokenTree::from(Op::new(':', Spacing::Joint)),
+            TokenTree::from(Op::new(':', Spacing::Alone)),
+        ].iter()
+            .cloned()
+            .map(|mut x| {
+                x.set_span(Span::def_site());
+                x
+            })
+            .collect::<TokenStream>()
     };
-    (!) => { TokenNode::Op('!', Spacing::Alone) };
-    (<) => { TokenNode::Op('<', Spacing::Alone) };
-    (>) => { TokenNode::Op('>', Spacing::Alone) };
-    (_) => { TokenNode::Op('_', Spacing::Alone) };
-    (0) => { TokenNode::Literal(::Literal::integer(0)) };
-    (&) => { TokenNode::Op('&', Spacing::Alone) };
-    ($i:ident) => { TokenNode::Term(Term::intern(stringify!($i))) };
+    (!) => { tt2ts!(Op::new('!', Spacing::Alone)) };
+    (<) => { tt2ts!(Op::new('<', Spacing::Alone)) };
+    (>) => { tt2ts!(Op::new('>', Spacing::Alone)) };
+    (_) => { tt2ts!(Op::new('_', Spacing::Alone)) };
+    (0) => { tt2ts!(Literal::i8_unsuffixed(0)) };
+    (&) => { tt2ts!(Op::new('&', Spacing::Alone)) };
+    ($i:ident) => { tt2ts!(Term::new(stringify!($i), Span::def_site())) };
 }
 
 macro_rules! quote_tree {
     ((unquote $($t:tt)*)) => { $($t)* };
     ((quote $($t:tt)*)) => { ($($t)*).quote() };
-    (($($t:tt)*)) => { TokenNode::Group(Delimiter::Parenthesis, quote!($($t)*)) };
-    ([$($t:tt)*]) => { TokenNode::Group(Delimiter::Bracket, quote!($($t)*)) };
-    ({$($t:tt)*}) => { TokenNode::Group(Delimiter::Brace, quote!($($t)*)) };
+    (($($t:tt)*)) => { tt2ts!(Group::new(Delimiter::Parenthesis, quote!($($t)*))) };
+    ([$($t:tt)*]) => { tt2ts!(Group::new(Delimiter::Bracket, quote!($($t)*))) };
+    ({$($t:tt)*}) => { tt2ts!(Group::new(Delimiter::Brace, quote!($($t)*))) };
     ($t:tt) => { quote_tok!($t) };
 }
 
 macro_rules! quote {
     () => { TokenStream::empty() };
     ($($t:tt)*) => {
-        [
-            $(TokenStream::from(quote_tree!($t)),)*
-        ].iter().cloned().collect::<TokenStream>()
+        [$(quote_tree!($t),)*].iter()
+            .cloned()
+            .flat_map(|x| x.into_iter())
+            .collect::<TokenStream>()
     };
 }
 
@@ -97,72 +109,81 @@ fn quote(self) -> TokenStream {
         let tokens = self.into_iter().filter_map(|tree| {
             if after_dollar {
                 after_dollar = false;
-                match tree.kind {
-                    TokenNode::Term(_) => {
+                match tree {
+                    TokenTree::Term(_) => {
+                        let tree = TokenStream::from(tree);
                         return Some(quote!(::__internal::unquote(&(unquote tree)),));
                     }
-                    TokenNode::Op('$', _) => {}
+                    TokenTree::Op(ref tt) if tt.op() == '$' => {}
                     _ => panic!("`$` must be followed by an ident or `$` in `quote!`"),
                 }
-            } else if let TokenNode::Op('$', _) = tree.kind {
-                after_dollar = true;
-                return None;
+            } else if let TokenTree::Op(tt) = tree {
+                if tt.op() == '$' {
+                    after_dollar = true;
+                    return None;
+                }
             }
 
             Some(quote!(::TokenStream::from((quote tree)),))
-        }).collect::<TokenStream>();
+        }).flat_map(|t| t.into_iter()).collect::<TokenStream>();
 
         if after_dollar {
             panic!("unexpected trailing `$` in `quote!`");
         }
 
-        quote!([(unquote tokens)].iter().cloned().collect::<::TokenStream>())
+        quote!(
+            [(unquote tokens)].iter()
+                .cloned()
+                .flat_map(|x| x.into_iter())
+                .collect::<::TokenStream>()
+        )
     }
 }
 
 impl Quote for TokenTree {
     fn quote(self) -> TokenStream {
-        quote!(::TokenTree { span: (quote self.span), kind: (quote self.kind) })
+        match self {
+            TokenTree::Op(tt) => quote!(::TokenTree::Op( (quote tt) )),
+            TokenTree::Group(tt) => quote!(::TokenTree::Group( (quote tt) )),
+            TokenTree::Term(tt) => quote!(::TokenTree::Term( (quote tt) )),
+            TokenTree::Literal(tt) => quote!(::TokenTree::Literal( (quote tt) )),
+        }
     }
 }
 
-impl Quote for TokenNode {
+impl Quote for char {
     fn quote(self) -> TokenStream {
-        macro_rules! gen_match {
-            ($($i:ident($($arg:ident),+)),*) => {
-                match self {
-                    $(TokenNode::$i($($arg),+) => quote! {
-                        ::TokenNode::$i($((quote $arg)),+)
-                    },)*
-                }
-            }
-        }
+        TokenTree::from(Literal::character(self)).into()
+    }
+}
 
-        gen_match! { Op(op, kind), Group(delim, tokens), Term(term), Literal(lit) }
+impl<'a> Quote for &'a str {
+    fn quote(self) -> TokenStream {
+        TokenTree::from(Literal::string(self)).into()
     }
 }
 
-impl Quote for char {
+impl Quote for usize {
     fn quote(self) -> TokenStream {
-        TokenNode::Literal(Literal::character(self)).into()
+        TokenTree::from(Literal::usize_unsuffixed(self)).into()
     }
 }
 
-impl<'a> Quote for &'a str {
+impl Quote for Group {
     fn quote(self) -> TokenStream {
-        TokenNode::Literal(Literal::string(self)).into()
+        quote!(::Group::new((quote self.delimiter()), (quote self.stream())))
     }
 }
 
-impl Quote for usize {
+impl Quote for Op {
     fn quote(self) -> TokenStream {
-        TokenNode::Literal(Literal::integer(self as i128)).into()
+        quote!(::Op::new((quote self.op()), (quote self.spacing())))
     }
 }
 
 impl Quote for Term {
     fn quote(self) -> TokenStream {
-        quote!(::Term::intern((quote self.as_str())))
+        quote!(::Term::new((quote self.as_str()), (quote self.span())))
     }
 }
 
@@ -182,14 +203,22 @@ pub enum LiteralKind {
         impl LiteralKind {
             pub fn with_contents_and_suffix(self, contents: Term, suffix: Option<Term>)
                                             -> Literal {
-                let contents = contents.0;
-                let suffix = suffix.map(|t| t.0);
+                let sym = contents.sym;
+                let suffix = suffix.map(|t| t.sym);
                 match self {
                     $(LiteralKind::$i => {
-                        Literal(token::Literal(token::Lit::$i(contents), suffix))
+                        Literal {
+                            lit: token::Lit::$i(sym),
+                            suffix,
+                            span: contents.span,
+                        }
                     })*
                     $(LiteralKind::$raw(n) => {
-                        Literal(token::Literal(token::Lit::$raw(contents, n), suffix))
+                        Literal {
+                            lit: token::Lit::$raw(sym, n),
+                            suffix,
+                            span: contents.span,
+                        }
                     })*
                 }
             }
@@ -197,16 +226,12 @@ pub fn with_contents_and_suffix(self, contents: Term, suffix: Option<Term>)
 
         impl Literal {
             fn kind_contents_and_suffix(self) -> (LiteralKind, Term, Option<Term>) {
-                let (lit, suffix) = match self.0 {
-                    token::Literal(lit, suffix) => (lit, suffix),
-                    _ => panic!("unsupported literal {:?}", self.0),
-                };
-
-                let (kind, contents) = match lit {
+                let (kind, contents) = match self.lit {
                     $(token::Lit::$i(contents) => (LiteralKind::$i, contents),)*
                     $(token::Lit::$raw(contents, n) => (LiteralKind::$raw(n), contents),)*
                 };
-                (kind, Term(contents), suffix.map(Term))
+                let suffix = self.suffix.map(|sym| Term::new(&sym.as_str(), self.span()));
+                (kind, Term::new(&contents.as_str(), self.span()), suffix)
             }
         }
 
index 04f456917b95703b5eebe33a62e81baa864a36d7..79192fbb6819c4ba09f6822c6bf3515261e31fc3 100644 (file)
@@ -13,6 +13,7 @@ doc = false
 
 [dependencies]
 core = { path = "../libcore" }
+compiler_builtins = { path = "../rustc/compiler_builtins_shim" }
 
 [build-dependencies]
 cc = "1.0.1"
index 278e0f9a26e433d032a5d2c3a4c0ee8142f3c4a9..5496df1342ff41b951b2f79b884b9bc32788de85 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![deny(warnings)]
-
 #![feature(test)]
 
 extern crate test;
index 42cda6a05a1a78e986d94f0af2686982911f721f..7c5318a96f5ac5773422972984e7afd37179579b 100644 (file)
@@ -561,6 +561,7 @@ pub fn fingerprint_needed_for_crate_hash(self) -> bool {
     [] ImplParent(DefId),
     [] TraitOfItem(DefId),
     [] IsReachableNonGeneric(DefId),
+    [] IsUnreachableLocalDefinition(DefId),
     [] IsMirAvailable(DefId),
     [] ItemAttrs(DefId),
     [] TransFnAttrs(DefId),
@@ -589,6 +590,7 @@ pub fn fingerprint_needed_for_crate_hash(self) -> bool {
     [input] CrateDisambiguator(CrateNum),
     [input] CrateHash(CrateNum),
     [input] OriginalCrateName(CrateNum),
+    [input] ExtraFileName(CrateNum),
 
     [] ImplementationsOfTrait { krate: CrateNum, trait_id: DefId },
     [] AllTraitImplementations(CrateNum),
@@ -647,8 +649,6 @@ pub fn fingerprint_needed_for_crate_hash(self) -> bool {
 
     [] InstanceDefSizeEstimate { instance_def: InstanceDef<'tcx> },
 
-    [] GetSymbolExportLevel(DefId),
-
     [] WasmCustomSections(CrateNum),
 
     [input] Features,
@@ -656,6 +656,9 @@ pub fn fingerprint_needed_for_crate_hash(self) -> bool {
     [] ProgramClausesFor(DefId),
     [] WasmImportModuleMap(CrateNum),
     [] ForeignModules(CrateNum),
+
+    [] UpstreamMonomorphizations(CrateNum),
+    [] UpstreamMonomorphizationsFor(DefId),
 );
 
 trait DepNodeParams<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> : fmt::Debug {
index c74ae2343b866b0833154d97fb3457e4a7464276..2662e70999196f458de10c16608a9f55b52e1558 100644 (file)
@@ -2058,6 +2058,33 @@ fn foo<'x, 'y>(x: Cell<&'x u32>) -> impl Trait<'y> + 'x
 ```
 "##,
 
+E0910: r##"
+This error indicates that a `#[non_exhaustive]` attribute was incorrectly placed
+on something other than a struct or enum.
+
+Examples of erroneous code:
+
+```compile_fail,E0910
+# #![feature(non_exhaustive)]
+
+#[non_exhaustive]
+trait Foo { }
+```
+"##,
+
+E0911: r##"
+This error indicates that a `#[non_exhaustive]` attribute had a value. The
+`#[non_exhaustive]` should be empty.
+
+Examples of erroneous code:
+
+```compile_fail,E0911
+# #![feature(non_exhaustive)]
+
+#[non_exhaustive(anything)]
+struct Foo;
+```
+"##,
 
 }
 
index 316ed07ca05d90241d6868d53c5459118c94af6d..956cd17f38f214cd91f47550641f74cdb667742a 100644 (file)
@@ -66,6 +66,8 @@ fn check_attributes(&self, item: &hir::Item, target: Target) {
         for attr in &item.attrs {
             if attr.check_name("inline") {
                 self.check_inline(attr, &item.span, target)
+            } else if attr.check_name("non_exhaustive") {
+                self.check_non_exhaustive(attr, item, target)
             } else if attr.check_name("wasm_import_module") {
                 has_wasm_import_module = true;
                 if attr.value_str().is_none() {
@@ -113,6 +115,31 @@ fn check_inline(&self, attr: &hir::Attribute, span: &Span, target: Target) {
         }
     }
 
+    /// Check if the `#[non_exhaustive]` attribute on an `item` is valid.
+    fn check_non_exhaustive(&self, attr: &hir::Attribute, item: &hir::Item, target: Target) {
+        match target {
+            Target::Struct | Target::Enum => { /* Valid */ },
+            _ => {
+                struct_span_err!(self.tcx.sess,
+                                 attr.span,
+                                 E0910,
+                                 "attribute can only be applied to a struct or enum")
+                    .span_label(item.span, "not a struct or enum")
+                    .emit();
+                return;
+            }
+        }
+
+        if attr.meta_item_list().is_some() || attr.value_str().is_some() {
+            struct_span_err!(self.tcx.sess,
+                             attr.span,
+                             E0911,
+                             "attribute should be empty")
+                .span_label(item.span, "not empty")
+                .emit();
+        }
+    }
+
     /// Check if the `#[repr]` attributes on `item` are valid.
     fn check_repr(&self, item: &hir::Item, target: Target) {
         // Extract the names of all repr hints, e.g., [foo, bar, align] for:
index 5f9f37094f579a5bc01c546dcce43f066ba73de8..b13c289394a7bf92ce83d11a714fcec10425f5a9 100644 (file)
@@ -909,7 +909,7 @@ fn def_key(&mut self, id: DefId) -> DefKey {
 
     fn lower_ident(&mut self, ident: Ident) -> Name {
         let ident = ident.modern();
-        if ident.ctxt == SyntaxContext::empty() {
+        if ident.span.ctxt() == SyntaxContext::empty() {
             return ident.name;
         }
         *self.name_map
@@ -920,7 +920,7 @@ fn lower_ident(&mut self, ident: Ident) -> Name {
     fn lower_label(&mut self, label: Option<Label>) -> Option<hir::Label> {
         label.map(|label| hir::Label {
             name: label.ident.name,
-            span: label.span,
+            span: label.ident.span,
         })
     }
 
@@ -1358,7 +1358,7 @@ fn lower_global_asm(&mut self, ga: &GlobalAsm) -> P<hir::GlobalAsm> {
     fn lower_variant(&mut self, v: &Variant) -> hir::Variant {
         Spanned {
             node: hir::Variant_ {
-                name: v.node.name.name,
+                name: v.node.ident.name,
                 attrs: self.lower_attrs(&v.node.attrs),
                 data: self.lower_variant_data(&v.node.data),
                 disr_expr: v.node
@@ -1607,7 +1607,7 @@ fn lower_path_segment(
         }
 
         hir::PathSegment::new(
-            self.lower_ident(segment.identifier),
+            self.lower_ident(segment.ident),
             parameters,
             infer_types,
         )
@@ -1720,7 +1720,7 @@ fn lower_fn_args_to_names(&mut self, decl: &FnDecl) -> hir::HirVec<Spanned<Name>
         decl.inputs
             .iter()
             .map(|arg| match arg.pat.node {
-                PatKind::Ident(_, ident, None) => respan(ident.span, ident.node.name),
+                PatKind::Ident(_, ident, None) => respan(ident.span, ident.name),
                 _ => respan(arg.pat.span, keywords::Invalid.name()),
             })
             .collect()
@@ -1810,7 +1810,7 @@ fn lower_ty_param(&mut self, tp: &TyParam, add_bounds: &[TyParamBound]) -> hir::
             default: tp.default
                 .as_ref()
                 .map(|x| self.lower_ty(x, ImplTraitContext::Disallowed)),
-            span: tp.span,
+            span: tp.ident.span,
             pure_wrt_drop: attr::contains_name(&tp.attrs, "may_dangle"),
             synthetic: tp.attrs
                 .iter()
@@ -1822,21 +1822,22 @@ fn lower_ty_param(&mut self, tp: &TyParam, add_bounds: &[TyParamBound]) -> hir::
     }
 
     fn lower_lifetime(&mut self, l: &Lifetime) -> hir::Lifetime {
+        let span = l.ident.span;
         match self.lower_ident(l.ident) {
-            x if x == "'static" => self.new_named_lifetime(l.id, l.span, hir::LifetimeName::Static),
+            x if x == "'static" => self.new_named_lifetime(l.id, span, hir::LifetimeName::Static),
             x if x == "'_" => match self.anonymous_lifetime_mode {
                 AnonymousLifetimeMode::CreateParameter => {
-                    let fresh_name = self.collect_fresh_in_band_lifetime(l.span);
-                    self.new_named_lifetime(l.id, l.span, fresh_name)
+                    let fresh_name = self.collect_fresh_in_band_lifetime(span);
+                    self.new_named_lifetime(l.id, span, fresh_name)
                 }
 
                 AnonymousLifetimeMode::PassThrough => {
-                    self.new_named_lifetime(l.id, l.span, hir::LifetimeName::Underscore)
+                    self.new_named_lifetime(l.id, span, hir::LifetimeName::Underscore)
                 }
             },
             name => {
-                self.maybe_collect_in_band_lifetime(l.span, name);
-                self.new_named_lifetime(l.id, l.span, hir::LifetimeName::Name(name))
+                self.maybe_collect_in_band_lifetime(span, name);
+                self.new_named_lifetime(l.id, span, hir::LifetimeName::Name(name))
             }
         }
     }
@@ -2089,10 +2090,7 @@ fn lower_struct_field(&mut self, (index, f): (usize, &StructField)) -> hir::Stru
             name: self.lower_ident(match f.ident {
                 Some(ident) => ident,
                 // FIXME(jseyfried) positional field hygiene
-                None => Ident {
-                    name: Symbol::intern(&index.to_string()),
-                    ctxt: f.span.ctxt(),
-                },
+                None => Ident::new(Symbol::intern(&index.to_string()), f.span),
             }),
             vis: self.lower_visibility(&f.vis, None),
             ty: self.lower_ty(&f.ty, ImplTraitContext::Disallowed),
@@ -2102,7 +2100,7 @@ fn lower_struct_field(&mut self, (index, f): (usize, &StructField)) -> hir::Stru
 
     fn lower_field(&mut self, f: &Field) -> hir::Field {
         hir::Field {
-            name: respan(f.ident.span, self.lower_ident(f.ident.node)),
+            name: respan(f.ident.span, self.lower_ident(f.ident)),
             expr: P(self.lower_expr(&f.expr)),
             span: f.span,
             is_shorthand: f.is_shorthand,
@@ -2359,11 +2357,11 @@ fn lower_use_tree(
 
                 // Correctly resolve `self` imports
                 if path.segments.len() > 1
-                    && path.segments.last().unwrap().identifier.name == keywords::SelfValue.name()
+                    && path.segments.last().unwrap().ident.name == keywords::SelfValue.name()
                 {
                     let _ = path.segments.pop();
                     if rename.is_none() {
-                        *name = path.segments.last().unwrap().identifier.name;
+                        *name = path.segments.last().unwrap().ident.name;
                     }
                 }
 
@@ -2724,6 +2722,7 @@ fn lower_foreign_item(&mut self, i: &ForeignItem) -> hir::ForeignItem {
                         hir::ForeignItemStatic(this.lower_ty(t, ImplTraitContext::Disallowed), m)
                     }
                     ForeignItemKind::Ty => hir::ForeignItemType,
+                    ForeignItemKind::Macro(_) => panic!("shouldn't exist here"),
                 },
                 vis: this.lower_visibility(&i.vis, None),
                 span: i.span,
@@ -2803,7 +2802,7 @@ fn lower_binop(&mut self, b: BinOp) -> hir::BinOp {
     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, pth1, ref sub) => {
+            PatKind::Ident(ref binding_mode, ident, ref sub) => {
                 match self.resolver.get_resolution(p.id).map(|d| d.base_def()) {
                     // `None` can occur in body-less function signatures
                     def @ None | def @ Some(Def::Local(_)) => {
@@ -2814,16 +2813,16 @@ fn lower_pat(&mut self, p: &Pat) -> P<hir::Pat> {
                         hir::PatKind::Binding(
                             self.lower_binding_mode(binding_mode),
                             canonical_id,
-                            respan(pth1.span, pth1.node.name),
+                            respan(ident.span, ident.name),
                             sub.as_ref().map(|x| self.lower_pat(x)),
                         )
                     }
                     Some(def) => hir::PatKind::Path(hir::QPath::Resolved(
                         None,
                         P(hir::Path {
-                            span: pth1.span,
+                            span: ident.span,
                             def,
-                            segments: hir_vec![hir::PathSegment::from_name(pth1.node.name)],
+                            segments: hir_vec![hir::PathSegment::from_name(ident.name)],
                         }),
                     )),
                 }
@@ -2938,7 +2937,7 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
                     ImplTraitContext::Disallowed,
                 );
                 let args = args.iter().map(|x| self.lower_expr(x)).collect();
-                hir::ExprMethodCall(hir_seg, seg.span, args)
+                hir::ExprMethodCall(hir_seg, seg.ident.span, args)
             }
             ExprKind::Binary(binop, ref lhs, ref rhs) => {
                 let binop = self.lower_binop(binop);
@@ -3073,7 +3072,7 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
             ),
             ExprKind::Field(ref el, ident) => hir::ExprField(
                 P(self.lower_expr(el)),
-                respan(ident.span, self.lower_ident(ident.node)),
+                respan(ident.span, self.lower_ident(ident)),
             ),
             ExprKind::TupField(ref el, ident) => hir::ExprTupField(P(self.lower_expr(el)), ident),
             ExprKind::Index(ref el, ref er) => {
@@ -3504,12 +3503,10 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
                 let attr = {
                     // allow(unreachable_code)
                     let allow = {
-                        let allow_ident = self.str_to_ident("allow");
-                        let uc_ident = self.str_to_ident("unreachable_code");
-                        let uc_meta_item = attr::mk_spanned_word_item(e.span, uc_ident);
-                        let uc_nested = NestedMetaItemKind::MetaItem(uc_meta_item);
-                        let uc_spanned = respan(e.span, uc_nested);
-                        attr::mk_spanned_list_item(e.span, allow_ident, vec![uc_spanned])
+                        let allow_ident = Ident::from_str("allow").with_span_pos(e.span);
+                        let uc_ident = Ident::from_str("unreachable_code").with_span_pos(e.span);
+                        let uc_nested = attr::mk_nested_word_item(uc_ident);
+                        attr::mk_list_item(e.span, allow_ident, vec![uc_nested])
                     };
                     attr::mk_spanned_attr_outer(e.span, attr::mk_attr_id(), allow)
                 };
index 3619a7fb0c603288df6a75c2c5b4b8ce74f68a2f..4bd857c73e6cf6d50e73961d5b90542d2028e3d8 100644 (file)
@@ -132,7 +132,7 @@ fn visit_item(&mut self, i: &'a Item) {
                     for v in &enum_definition.variants {
                         let variant_def_index =
                             this.create_def(v.node.data.id(),
-                                            DefPathData::EnumVariant(v.node.name.name.as_str()),
+                                            DefPathData::EnumVariant(v.node.ident.name.as_str()),
                                             REGULAR_SPACE,
                                             v.span);
                         this.with_parent(variant_def_index, |this| {
@@ -181,6 +181,10 @@ fn visit_use_tree(&mut self, use_tree: &'a UseTree, id: NodeId, _nested: bool) {
     }
 
     fn visit_foreign_item(&mut self, foreign_item: &'a ForeignItem) {
+        if let ForeignItemKind::Macro(_) = foreign_item.node {
+            return self.visit_macro_invoc(foreign_item.id, false);
+        }
+
         let def = self.create_def(foreign_item.id,
                                   DefPathData::ValueNs(foreign_item.ident.name.as_str()),
                                   REGULAR_SPACE,
@@ -198,7 +202,7 @@ fn visit_generic_param(&mut self, param: &'a GenericParam) {
                     lifetime_def.lifetime.id,
                     DefPathData::LifetimeDef(lifetime_def.lifetime.ident.name.as_str()),
                     REGULAR_SPACE,
-                    lifetime_def.lifetime.span
+                    lifetime_def.lifetime.ident.span
                 );
             }
             GenericParam::Type(ref ty_param) => {
@@ -206,7 +210,7 @@ fn visit_generic_param(&mut self, param: &'a GenericParam) {
                     ty_param.id,
                     DefPathData::TypeParam(ty_param.ident.name.as_str()),
                     REGULAR_SPACE,
-                    ty_param.span
+                    ty_param.ident.span
                 );
             }
         }
index e8bcbfbb77a1791cb03d6d65352566accc740c8a..1e348e3a31ce215225c4a269e5fa792e235b4439 100644 (file)
 use util::nodemap::{DefIdMap, FxHashMap};
 
 use arena::TypedArena;
-use std::cell::RefCell;
 use std::io;
 use ty::TyCtxt;
 
+use rustc_data_structures::sync::Lock;
+
 pub mod blocks;
 mod collector;
 mod def_collector;
@@ -264,7 +265,7 @@ pub struct Map<'hir> {
     definitions: &'hir Definitions,
 
     /// Bodies inlined from other crates are cached here.
-    inlined_bodies: RefCell<DefIdMap<&'hir Body>>,
+    inlined_bodies: Lock<DefIdMap<&'hir Body>>,
 
     /// The reverse mapping of `node_to_hir_id`.
     hir_to_node_id: FxHashMap<HirId, NodeId>,
@@ -927,8 +928,13 @@ pub fn get_inlined_body_untracked(&self, def_id: DefId) -> Option<&'hir Body> {
     }
 
     pub fn intern_inlined_body(&self, def_id: DefId, body: Body) -> &'hir Body {
+        let mut inlined_bodies = self.inlined_bodies.borrow_mut();
+        if let Some(&b) = inlined_bodies.get(&def_id) {
+            debug_assert_eq!(&body, b);
+            return b;
+        }
         let body = self.forest.inlined_bodies.alloc(body);
-        self.inlined_bodies.borrow_mut().insert(def_id, body);
+        inlined_bodies.insert(def_id, body);
         body
     }
 
@@ -1189,7 +1195,7 @@ pub fn map_crate<'hir>(sess: &::session::Session,
         map,
         hir_to_node_id,
         definitions,
-        inlined_bodies: RefCell::new(DefIdMap()),
+        inlined_bodies: Lock::new(DefIdMap()),
     };
 
     hir_id_validator::check_crate(&map);
index c3b3e10201f9920665028f7a8bb920035a09be43..38b284fd64637025c34cb6acbb741ed5e2aa5570 100644 (file)
@@ -654,11 +654,12 @@ fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         let ast::Ident {
-            ref name,
-            ctxt: _ // Ignore this
+            name,
+            span,
         } = *self;
 
         name.hash_stable(hcx, hasher);
+        span.hash_stable(hcx, hasher);
     }
 }
 
index 425459f448fad32b7fb6ac1ab26460f2a14c0cb9..3bb4c86e7c22ca23578fb58cef8898d38ce5c00b 100644 (file)
@@ -162,7 +162,7 @@ fn hash_stable<W: StableHasherResult>(&self,
 impl_stable_hash_for!(enum ::syntax::ast::Unsafety { Unsafe, Normal });
 impl_stable_hash_for!(enum ::syntax::ast::Constness { Const, NotConst });
 impl_stable_hash_for!(enum ::syntax::ast::Defaultness { Default, Final });
-impl_stable_hash_for!(struct ::syntax::ast::Lifetime { id, span, ident });
+impl_stable_hash_for!(struct ::syntax::ast::Lifetime { id, ident });
 impl_stable_hash_for!(enum ::syntax::ast::StrStyle { Cooked, Raw(pounds) });
 impl_stable_hash_for!(enum ::syntax::ast::AttrStyle { Outer, Inner });
 
@@ -211,7 +211,7 @@ fn hash_stable<W: StableHasherResult>(&self,
         style.hash_stable(hcx, hasher);
         path.segments.len().hash_stable(hcx, hasher);
         for segment in &path.segments {
-            segment.identifier.name.hash_stable(hcx, hasher);
+            segment.ident.name.hash_stable(hcx, hasher);
         }
         for tt in tokens.trees() {
             tt.hash_stable(hcx, hasher);
@@ -341,7 +341,7 @@ fn hash_token<'a, 'gcx, W: StableHasherResult>(
 });
 
 impl_stable_hash_for!(struct ::syntax::ast::MetaItem {
-    name,
+    ident,
     node,
     span
 });
index 340dd32a237c01fa29240d207cd700435e35ebc6..af4d3429bb1d57699210dd13645a0f07598a0e5c 100644 (file)
@@ -53,8 +53,21 @@ fn hash_stable<W: StableHasherResult>(&self,
     }
 }
 
-impl<'a, 'gcx> HashStable<StableHashingContext<'a>>
-for ty::subst::Kind<'gcx> {
+impl<'a, 'gcx, T> ToStableHashKey<StableHashingContext<'a>> for &'gcx ty::Slice<T>
+    where T: HashStable<StableHashingContext<'a>>
+{
+    type KeyType = Fingerprint;
+
+    #[inline]
+    fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> Fingerprint {
+        let mut hasher = StableHasher::new();
+        let mut hcx: StableHashingContext<'a> = hcx.clone();
+        self.hash_stable(&mut hcx, &mut hasher);
+        hasher.finish()
+    }
+}
+
+impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for ty::subst::Kind<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
@@ -67,6 +80,7 @@ impl<'a, 'gcx> HashStable<StableHashingContext<'a>>
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
+        mem::discriminant(self).hash_stable(hcx, hasher);
         match self {
             ty::subst::UnpackedKind::Lifetime(lt) => lt.hash_stable(hcx, hasher),
             ty::subst::UnpackedKind::Type(ty) => ty.hash_stable(hcx, hasher),
@@ -403,7 +417,7 @@ fn hash_stable<W: StableHasherResult>(
             let tcx = tcx.expect("can't hash AllocIds during hir lowering");
             if let Some(alloc) = tcx.interpret_interner.get_alloc(*self) {
                 AllocDiscriminant::Alloc.hash_stable(hcx, hasher);
-                if !hcx.alloc_id_recursion_tracker.insert(*self) {
+                if hcx.alloc_id_recursion_tracker.insert(*self) {
                     tcx
                         .interpret_interner
                         .get_corresponding_static_def_id(*self)
@@ -1392,6 +1406,12 @@ fn hash_stable<W: StableHasherResult>(&self,
     }
 }
 
+impl_stable_hash_for!(
+    impl<'tcx> for struct traits::ProgramClause<'tcx> {
+        goal, hypotheses
+    }
+);
+
 impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for traits::Clause<'tcx> {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a>,
@@ -1400,11 +1420,7 @@ fn hash_stable<W: StableHasherResult>(&self,
 
         mem::discriminant(self).hash_stable(hcx, hasher);
         match self {
-            Implies(hypotheses, goal) => {
-                hypotheses.hash_stable(hcx, hasher);
-                goal.hash_stable(hcx, hasher);
-            }
-            DomainGoal(domain_goal) => domain_goal.hash_stable(hcx, hasher),
+            Implies(clause) => clause.hash_stable(hcx, hasher),
             ForAll(clause) => clause.hash_stable(hcx, hasher),
         }
     }
index 91df6cabf3a8b88c4ae0e5a6a5b947a494638aa7..5e96f4eb576f523e5d20e79454de36ec4f1f95bd 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use syntax::ast;
+use syntax::symbol::InternedString;
 use syntax_pos::Span;
 use ty::{self, Ty};
 
@@ -53,7 +53,7 @@ pub enum TypeVariableOrigin {
     MiscVariable(Span),
     NormalizeProjectionType(Span),
     TypeInference(Span),
-    TypeParameterDefinition(Span, ast::Name),
+    TypeParameterDefinition(Span, InternedString),
 
     /// one of the upvars or closure kind parameters in a `ClosureSubsts`
     /// (before it has been determined)
index dcad8132c2b2478a0b3eac0d0475010b8d647e67..b54699901faf320973b263dc90ca84c3bef7241e 100644 (file)
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "https://doc.rust-lang.org/nightly/")]
-#![deny(warnings)]
 
 #![feature(box_patterns)]
 #![feature(box_syntax)]
-#![cfg_attr(stage0, feature(conservative_impl_trait))]
 #![feature(const_fn)]
-#![cfg_attr(stage0, feature(copy_closures, clone_closures))]
 #![feature(core_intrinsics)]
 #![feature(drain_filter)]
 #![feature(dyn_trait)]
 #![feature(entry_or_default)]
 #![feature(from_ref)]
 #![feature(fs_read_write)]
-#![cfg_attr(stage0, feature(i128_type, i128))]
-#![cfg_attr(stage0, feature(inclusive_range_syntax))]
 #![cfg_attr(windows, feature(libc))]
-#![cfg_attr(stage0, feature(match_default_bindings))]
 #![feature(macro_lifetime_matcher)]
 #![feature(macro_vis_matcher)]
 #![feature(exhaustive_patterns)]
@@ -68,8 +62,6 @@
 #![feature(slice_patterns)]
 #![feature(specialization)]
 #![feature(unboxed_closures)]
-#![cfg_attr(stage0, feature(underscore_lifetimes))]
-#![cfg_attr(stage0, feature(universal_impl_trait))]
 #![feature(trace_macros)]
 #![feature(trusted_len)]
 #![feature(catch_expr)]
index 3c833251f72a78c410b5ab735ced0fb569791bc9..9f8cc2f86992f54ffa5d73f15be5cf2c5a10cab9 100644 (file)
@@ -952,8 +952,8 @@ fn visit_ty(&mut self, t: &'a ast::Ty) {
         ast_visit::walk_ty(self, t);
     }
 
-    fn visit_ident(&mut self, sp: Span, id: ast::Ident) {
-        run_lints!(self, check_ident, early_passes, sp, id);
+    fn visit_ident(&mut self, ident: ast::Ident) {
+        run_lints!(self, check_ident, early_passes, ident);
     }
 
     fn visit_mod(&mut self, m: &'a ast::Mod, s: Span, _a: &[ast::Attribute], n: ast::NodeId) {
index 8a899a35ecb547a7e27e5fc59549a6df067a17f3..e8b536d52676382e356f723d64564451376c2e27 100644 (file)
@@ -221,7 +221,7 @@ pub fn push(&mut self, attrs: &[ast::Attribute]) -> BuilderPush {
                         continue
                     }
                 };
-                let name = word.name();
+                let name = word.ident.name;
                 match store.check_lint_name(&name.as_str()) {
                     CheckLintNameResult::Ok(ids) => {
                         let src = LintSource::Node(name, li.span);
index 1497be2d5ba0d35448feeed03c0ca4dcce1a95fd..0d4fd99995f7ed2d57d4fefe61d16cb20ab4b28f 100644 (file)
@@ -31,7 +31,7 @@
 pub use self::Level::*;
 pub use self::LintSource::*;
 
-use rustc_data_structures::sync::Lrc;
+use rustc_data_structures::sync::{self, Lrc};
 
 use errors::{DiagnosticBuilder, DiagnosticId};
 use hir::def_id::{CrateNum, LOCAL_CRATE};
@@ -236,7 +236,7 @@ fn exit_lint_attrs(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx [ast::Attribut
 }
 
 pub trait EarlyLintPass: LintPass {
-    fn check_ident(&mut self, _: &EarlyContext, _: Span, _: ast::Ident) { }
+    fn check_ident(&mut self, _: &EarlyContext, _: ast::Ident) { }
     fn check_crate(&mut self, _: &EarlyContext, _: &ast::Crate) { }
     fn check_crate_post(&mut self, _: &EarlyContext, _: &ast::Crate) { }
     fn check_mod(&mut self, _: &EarlyContext, _: &ast::Mod, _: Span, _: ast::NodeId) { }
@@ -287,8 +287,9 @@ fn exit_lint_attrs(&mut self, _: &EarlyContext, _: &[ast::Attribute]) { }
 }
 
 /// A lint pass boxed up as a trait object.
-pub type EarlyLintPassObject = Box<dyn EarlyLintPass + 'static>;
-pub type LateLintPassObject = Box<dyn for<'a, 'tcx> LateLintPass<'a, 'tcx> + 'static>;
+pub type EarlyLintPassObject = Box<dyn EarlyLintPass + sync::Send + sync::Sync + 'static>;
+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)]
index b1418792490fcc3d40c832f62aec98ca9c050080..01783eb0ff65f8b90cf561c59d790c5994822d64 100644 (file)
@@ -9,8 +9,13 @@
 // except according to those terms.
 
 use hir::def_id::{DefId, LOCAL_CRATE};
+use ich::StableHashingContext;
+use rustc_data_structures::stable_hasher::{StableHasher, HashStable,
+                                           StableHasherResult};
 use std::cmp;
+use std::mem;
 use ty;
+use ty::subst::Substs;
 
 /// The SymbolExportLevel of a symbols specifies from which kinds of crates
 /// the symbol will be exported. `C` symbols will be exported from any
@@ -40,56 +45,89 @@ pub fn is_below_threshold(self, threshold: SymbolExportLevel) -> bool {
 }
 
 #[derive(Eq, PartialEq, Debug, Copy, Clone, RustcEncodable, RustcDecodable)]
-pub enum ExportedSymbol {
+pub enum ExportedSymbol<'tcx> {
     NonGeneric(DefId),
+    Generic(DefId, &'tcx Substs<'tcx>),
     NoDefId(ty::SymbolName),
 }
 
-impl ExportedSymbol {
-    pub fn symbol_name(&self, tcx: ty::TyCtxt) -> ty::SymbolName {
+impl<'tcx> ExportedSymbol<'tcx> {
+    pub fn symbol_name(&self,
+                       tcx: ty::TyCtxt<'_, 'tcx, '_>)
+                       -> ty::SymbolName {
         match *self {
             ExportedSymbol::NonGeneric(def_id) => {
                 tcx.symbol_name(ty::Instance::mono(tcx, def_id))
             }
+            ExportedSymbol::Generic(def_id, substs) => {
+                tcx.symbol_name(ty::Instance::new(def_id, substs))
+            }
             ExportedSymbol::NoDefId(symbol_name) => {
                 symbol_name
             }
         }
     }
 
-    pub fn compare_stable(&self, tcx: ty::TyCtxt, other: &ExportedSymbol) -> cmp::Ordering {
+    pub fn compare_stable(&self,
+                          tcx: ty::TyCtxt<'_, 'tcx, '_>,
+                          other: &ExportedSymbol<'tcx>)
+                          -> cmp::Ordering {
         match *self {
-            ExportedSymbol::NonGeneric(self_def_id) => {
-                match *other {
-                    ExportedSymbol::NonGeneric(other_def_id) => {
-                        tcx.def_path_hash(self_def_id).cmp(&tcx.def_path_hash(other_def_id))
-                    }
-                    ExportedSymbol::NoDefId(_) => {
-                        cmp::Ordering::Less
-                    }
+            ExportedSymbol::NonGeneric(self_def_id) => match *other {
+                ExportedSymbol::NonGeneric(other_def_id) => {
+                    tcx.def_path_hash(self_def_id).cmp(&tcx.def_path_hash(other_def_id))
+                }
+                ExportedSymbol::Generic(..) |
+                ExportedSymbol::NoDefId(_) => {
+                    cmp::Ordering::Less
+                }
+            }
+            ExportedSymbol::Generic(..) => match *other {
+                ExportedSymbol::NonGeneric(_) => {
+                    cmp::Ordering::Greater
+                }
+                ExportedSymbol::Generic(..) => {
+                    self.symbol_name(tcx).cmp(&other.symbol_name(tcx))
+                }
+                ExportedSymbol::NoDefId(_) => {
+                    cmp::Ordering::Less
                 }
             }
-            ExportedSymbol::NoDefId(self_symbol_name) => {
-                match *other {
-                    ExportedSymbol::NonGeneric(_) => {
-                        cmp::Ordering::Greater
-                    }
-                    ExportedSymbol::NoDefId(ref other_symbol_name) => {
-                        self_symbol_name.cmp(other_symbol_name)
-                    }
+            ExportedSymbol::NoDefId(self_symbol_name) => match *other {
+                ExportedSymbol::NonGeneric(_) |
+                ExportedSymbol::Generic(..) => {
+                    cmp::Ordering::Greater
+                }
+                ExportedSymbol::NoDefId(ref other_symbol_name) => {
+                    self_symbol_name.cmp(other_symbol_name)
                 }
             }
         }
     }
 }
 
-impl_stable_hash_for!(enum self::ExportedSymbol {
-    NonGeneric(def_id),
-    NoDefId(symbol_name)
-});
-
 pub fn metadata_symbol_name(tcx: ty::TyCtxt) -> String {
     format!("rust_metadata_{}_{}",
             tcx.original_crate_name(LOCAL_CRATE),
             tcx.crate_disambiguator(LOCAL_CRATE).to_fingerprint().to_hex())
 }
+
+impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for ExportedSymbol<'gcx> {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a>,
+                                          hasher: &mut StableHasher<W>) {
+        mem::discriminant(self).hash_stable(hcx, hasher);
+        match *self {
+            ExportedSymbol::NonGeneric(def_id) => {
+                def_id.hash_stable(hcx, hasher);
+            }
+            ExportedSymbol::Generic(def_id, substs) => {
+                def_id.hash_stable(hcx, hasher);
+                substs.hash_stable(hcx, hasher);
+            }
+            ExportedSymbol::NoDefId(symbol_name) => {
+                symbol_name.hash_stable(hcx, hasher);
+            }
+        }
+    }
+}
index 6bf0c5d1ba3e39478389c9fa1d60b95fec599f37..5875e5e4097af496036aaa5b221866ffa5fc6e1a 100644 (file)
@@ -503,8 +503,37 @@ pub fn expr_ty_adjusted(&self, expr: &hir::Expr) -> McResult<Ty<'tcx>> {
         self.resolve_type_vars_or_error(expr.hir_id, self.tables.expr_ty_adjusted_opt(expr))
     }
 
+    /// Returns the type of value that this pattern matches against.
+    /// Some non-obvious cases:
+    ///
+    /// - a `ref x` binding matches against a value of type `T` and gives
+    ///   `x` the type `&T`; we return `T`.
+    /// - a pattern with implicit derefs (thanks to default binding
+    ///   modes #42640) may look like `Some(x)` but in fact have
+    ///   implicit deref patterns attached (e.g., it is really
+    ///   `&Some(x)`). In that case, we return the "outermost" type
+    ///   (e.g., `&Option<T>).
     fn pat_ty(&self, pat: &hir::Pat) -> McResult<Ty<'tcx>> {
+        // Check for implicit `&` types wrapping the pattern; note
+        // that these are never attached to binding patterns, so
+        // actually this is somewhat "disjoint" from the code below
+        // that aims to account for `ref x`.
+        if let Some(vec) = self.tables.pat_adjustments().get(pat.hir_id) {
+            if let Some(first_ty) = vec.first() {
+                debug!("pat_ty(pat={:?}) found adjusted ty `{:?}`", pat, first_ty);
+                return Ok(first_ty);
+            }
+        }
+
+        self.pat_ty_unadjusted(pat)
+    }
+
+
+    /// Like `pat_ty`, but ignores implicit `&` patterns.
+    fn pat_ty_unadjusted(&self, pat: &hir::Pat) -> McResult<Ty<'tcx>> {
         let base_ty = self.node_ty(pat.hir_id)?;
+        debug!("pat_ty(pat={:?}) base_ty={:?}", pat, base_ty);
+
         // This code detects whether we are looking at a `ref x`,
         // and if so, figures out what the type *being borrowed* is.
         let ret_ty = match pat.node {
@@ -531,8 +560,8 @@ fn pat_ty(&self, pat: &hir::Pat) -> McResult<Ty<'tcx>> {
             }
             _ => base_ty,
         };
-        debug!("pat_ty(pat={:?}) base_ty={:?} ret_ty={:?}",
-               pat, base_ty, ret_ty);
+        debug!("pat_ty(pat={:?}) ret_ty={:?}", pat, ret_ty);
+
         Ok(ret_ty)
     }
 
@@ -1246,7 +1275,7 @@ fn cat_pattern_<F>(&self, mut cmt: cmt<'tcx>, pat: &hir::Pat, op: &mut F) -> McR
                      self.tcx.adt_def(enum_def).variant_with_id(def_id).fields.len())
                 }
                 Def::StructCtor(_, CtorKind::Fn) => {
-                    match self.pat_ty(&pat)?.sty {
+                    match self.pat_ty_unadjusted(&pat)?.sty {
                         ty::TyAdt(adt_def, _) => {
                             (cmt, adt_def.non_enum_variant().fields.len())
                         }
@@ -1297,7 +1326,7 @@ fn cat_pattern_<F>(&self, mut cmt: cmt<'tcx>, pat: &hir::Pat, op: &mut F) -> McR
 
           PatKind::Tuple(ref subpats, ddpos) => {
             // (p1, ..., pN)
-            let expected_len = match self.pat_ty(&pat)?.sty {
+            let expected_len = match self.pat_ty_unadjusted(&pat)?.sty {
                 ty::TyTuple(ref tys) => tys.len(),
                 ref ty => span_bug!(pat.span, "tuple pattern unexpected type {:?}", ty),
             };
index c7396b34c4689548bd413d4ec8e71b24268105a2..7e1b7c08c3dad99fc22c4566c84cf15a3e78082e 100644 (file)
@@ -353,8 +353,8 @@ pub struct ScopeTree {
     /// the result of `g()` occurs after the yield (and therefore
     /// doesn't). If we want to infer that, we can look at the
     /// postorder traversal:
-    /// ```
-    /// `foo` `f` Call#1 `y` Yield `bar` `g` Call#3 Call#2 Call#0
+    /// ```plain,ignore
+    ///     `foo` `f` Call#1 `y` Yield `bar` `g` Call#3 Call#2 Call#0
     /// ```
     ///
     /// In which we can easily see that `Call#1` occurs before the yield,
index 95e75b4f0646efc42442ce7a60c425aad22fa152..e19f4483f6569f536549ef57501d9bcebe13e025 100644 (file)
@@ -64,6 +64,24 @@ pub fn link_name(attrs: &[ast::Attribute]) -> Option<Symbol> {
     })
 }
 
+/// Returns whether the specified `lang_item` doesn't actually need to be
+/// present for this compilation.
+///
+/// Not all lang items are always required for each compilation, particularly in
+/// the case of panic=abort. In these situations some lang items are injected by
+/// crates and don't actually need to be defined in libstd.
+pub fn whitelisted(tcx: TyCtxt, lang_item: lang_items::LangItem) -> bool {
+    // If we're not compiling with unwinding, we won't actually need these
+    // symbols. Other panic runtimes ensure that the relevant symbols are
+    // available to link things together, but they're never exercised.
+    if tcx.sess.panic_strategy() != PanicStrategy::Unwind {
+        return lang_item == lang_items::EhPersonalityLangItem ||
+            lang_item == lang_items::EhUnwindResumeLangItem
+    }
+
+    false
+}
+
 fn verify<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                     items: &lang_items::LanguageItems) {
     // We only need to check for the presence of weak lang items if we're
@@ -89,18 +107,9 @@ fn verify<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         }
     }
 
-    // If we're not compiling with unwinding, we won't actually need these
-    // symbols. Other panic runtimes ensure that the relevant symbols are
-    // available to link things together, but they're never exercised.
-    let mut whitelisted = HashSet::new();
-    if tcx.sess.panic_strategy() != PanicStrategy::Unwind {
-        whitelisted.insert(lang_items::EhPersonalityLangItem);
-        whitelisted.insert(lang_items::EhUnwindResumeLangItem);
-    }
-
     $(
         if missing.contains(&lang_items::$item) &&
-           !whitelisted.contains(&lang_items::$item) &&
+           !whitelisted(tcx, lang_items::$item) &&
            items.$name().is_none() {
             tcx.sess.err(&format!("language item required, but not found: `{}`",
                                   stringify!($name)));
index 9b75c19a875ebc4ad83ac100ae5f1aa6a78afb92..1ed5a22257c537e53446b2013d1c2e842984c55c 100644 (file)
@@ -8,8 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::cell::{Ref, RefCell};
 use rustc_data_structures::indexed_vec::IndexVec;
+use rustc_data_structures::sync::{RwLock, ReadGuard};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
                                            StableHasherResult};
 use ich::StableHashingContext;
@@ -19,7 +19,7 @@
 
 #[derive(Clone, Debug)]
 pub struct Cache {
-    predecessors: RefCell<Option<IndexVec<BasicBlock, Vec<BasicBlock>>>>
+    predecessors: RwLock<Option<IndexVec<BasicBlock, Vec<BasicBlock>>>>
 }
 
 
@@ -46,7 +46,7 @@ fn hash_stable<W: StableHasherResult>(&self,
 impl Cache {
     pub fn new() -> Self {
         Cache {
-            predecessors: RefCell::new(None)
+            predecessors: RwLock::new(None)
         }
     }
 
@@ -55,12 +55,12 @@ pub fn invalidate(&self) {
         *self.predecessors.borrow_mut() = None;
     }
 
-    pub fn predecessors(&self, mir: &Mir) -> Ref<IndexVec<BasicBlock, Vec<BasicBlock>>> {
+    pub fn predecessors(&self, mir: &Mir) -> ReadGuard<IndexVec<BasicBlock, Vec<BasicBlock>>> {
         if self.predecessors.borrow().is_none() {
             *self.predecessors.borrow_mut() = Some(calculate_predecessors(mir));
         }
 
-        Ref::map(self.predecessors.borrow(), |p| p.as_ref().unwrap())
+        ReadGuard::map(self.predecessors.borrow(), |p| p.as_ref().unwrap())
     }
 }
 
index 9ed4e6a8e00ae5e3c7bc325362c6c9288fe1eedc..33f52ab09c85668b72c9d3a008345fe5394688e6 100644 (file)
@@ -34,7 +34,7 @@
 use std::slice;
 use hir::{self, InlineAsm};
 use std::borrow::{Cow};
-use std::cell::Ref;
+use rustc_data_structures::sync::ReadGuard;
 use std::fmt::{self, Debug, Formatter, Write};
 use std::{iter, mem, u32};
 use std::ops::{Index, IndexMut};
@@ -187,13 +187,13 @@ pub fn basic_blocks_and_local_decls_mut(&mut self) -> (
     }
 
     #[inline]
-    pub fn predecessors(&self) -> Ref<IndexVec<BasicBlock, Vec<BasicBlock>>> {
+    pub fn predecessors(&self) -> ReadGuard<IndexVec<BasicBlock, Vec<BasicBlock>>> {
         self.cache.predecessors(self)
     }
 
     #[inline]
-    pub fn predecessors_for(&self, bb: BasicBlock) -> Ref<Vec<BasicBlock>> {
-        Ref::map(self.predecessors(), |p| &p[bb])
+    pub fn predecessors_for(&self, bb: BasicBlock) -> ReadGuard<Vec<BasicBlock>> {
+        ReadGuard::map(self.predecessors(), |p| &p[bb])
     }
 
     #[inline]
index 59d1a298eaa69ae6fab6d2bd1e173d227724186a..a07370e1e42a7649f53787ab85c38bc2844cfb0c 100644 (file)
@@ -1304,6 +1304,8 @@ fn parse_edition(slot: &mut Edition, v: Option<&str>) -> bool {
           "embed LLVM bitcode in object files"),
     strip_debuginfo_if_disabled: Option<bool> = (None, parse_opt_bool, [TRACKED],
         "tell the linker to strip debuginfo when building without debuginfo enabled."),
+    share_generics: Option<bool> = (None, parse_opt_bool, [TRACKED],
+          "make the current crate share its generic instantiations"),
 }
 
 pub fn default_lib_output() -> CrateType {
@@ -1683,12 +1685,12 @@ pub fn parse_cfgspecs(cfgspecs: Vec<String>) -> ast::CrateConfig {
             } else if meta_item.is_meta_item_list() {
                 let msg = format!(
                     "invalid predicate in --cfg command line argument: `{}`",
-                    meta_item.name()
+                    meta_item.ident
                 );
                 early_error(ErrorOutputType::default(), &msg)
             }
 
-            (meta_item.name(), meta_item.value_str())
+            (meta_item.ident.name, meta_item.value_str())
         })
         .collect::<ast::CrateConfig>()
 }
index d2bde14732bbcdab4eca9a21ea495311826b497d..2af4c3f9fd463ca7adfd651df4750763872a8961 100644 (file)
@@ -378,7 +378,7 @@ fn on_unimplemented_note(
         }
 
         for param in generics.types.iter() {
-            let name = param.name.as_str().to_string();
+            let name = param.name.to_string();
             let ty = trait_ref.substs.type_for_def(param);
             let ty_str = ty.to_string();
             flags.push((name.clone(),
index 2ce1b75e3151fa5e3d86b4393d2e6cdee6fe4202..b30fb2ce016dff62ac902dc6a3ca408d165462cc 100644 (file)
@@ -272,6 +272,8 @@ pub enum DomainGoal<'tcx> {
     TypeOutlives(ty::TypeOutlivesPredicate<'tcx>),
 }
 
+pub type PolyDomainGoal<'tcx> = ty::Binder<DomainGoal<'tcx>>;
+
 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
 pub enum QuantifierKind {
     Universal,
@@ -294,9 +296,15 @@ fn from(domain_goal: DomainGoal<'tcx>) -> Self {
     }
 }
 
-impl<'tcx> From<DomainGoal<'tcx>> for Clause<'tcx> {
-    fn from(domain_goal: DomainGoal<'tcx>) -> Self {
-        Clause::DomainGoal(domain_goal)
+impl<'tcx> From<PolyDomainGoal<'tcx>> for Goal<'tcx> {
+    fn from(domain_goal: PolyDomainGoal<'tcx>) -> Self {
+        match domain_goal.no_late_bound_regions() {
+            Some(p) => p.into(),
+            None => Goal::Quantified(
+                QuantifierKind::Universal,
+                Box::new(domain_goal.map_bound(|p| p.into()))
+            ),
+        }
     }
 }
 
@@ -304,10 +312,23 @@ fn from(domain_goal: DomainGoal<'tcx>) -> Self {
 /// Harrop Formulas".
 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
 pub enum Clause<'tcx> {
-    // FIXME: again, use interned refs instead of `Box`
-    Implies(Vec<Goal<'tcx>>, DomainGoal<'tcx>),
-    DomainGoal(DomainGoal<'tcx>),
-    ForAll(Box<ty::Binder<Clause<'tcx>>>),
+    Implies(ProgramClause<'tcx>),
+    ForAll(ty::Binder<ProgramClause<'tcx>>),
+}
+
+/// A "program clause" has the form `D :- G1, ..., Gn`. It is saying
+/// that the domain goal `D` is true if `G1...Gn` are provable. This
+/// is equivalent to the implication `G1..Gn => D`; we usually write
+/// it with the reverse implication operator `:-` to emphasize the way
+/// that programs are actually solved (via backchaining, which starts
+/// with the goal to solve and proceeds from there).
+#[derive(Clone, PartialEq, Eq, Hash, Debug)]
+pub struct ProgramClause<'tcx> {
+    /// This goal will be considered true...
+    pub goal: DomainGoal<'tcx>,
+
+    /// ...if we can prove these hypotheses (there may be no hypotheses at all):
+    pub hypotheses: Vec<Goal<'tcx>>,
 }
 
 pub type Selection<'tcx> = Vtable<'tcx, PredicateObligation<'tcx>>;
index 8c2c1cfa454729c5cbfcf1593dde5771617b4efa..405dafdff2b3455a511ec6691b4e28eebf7ee728 100644 (file)
@@ -190,7 +190,7 @@ pub fn evaluate(&self,
         for command in self.subcommands.iter().chain(Some(self)).rev() {
             if let Some(ref condition) = command.condition {
                 if !attr::eval_condition(condition, &tcx.sess.parse_sess, &mut |c| {
-                    options.contains(&(c.name().as_str().to_string(),
+                    options.contains(&(c.ident.name.as_str().to_string(),
                                       match c.value_str().map(|s| s.as_str().to_string()) {
                                           Some(s) => Some(s),
                                           None => None
@@ -289,7 +289,7 @@ pub fn format(&self,
         let trait_str = tcx.item_path_str(trait_ref.def_id);
         let generics = tcx.generics_of(trait_ref.def_id);
         let generic_map = generics.types.iter().map(|param| {
-            (param.name.as_str().to_string(),
+            (param.name.to_string(),
              trait_ref.substs.type_for_def(param).to_string())
         }).collect::<FxHashMap<String, String>>();
 
index bbd428611874ae2d994cbcd90ebe1eeb4181023c..58c591bf9351258885ce10111369a488f963ecb1 100644 (file)
@@ -362,7 +362,9 @@ enum EvaluationResult {
     /// When checking `foo`, we have to prove `T: Trait`. This basically
     /// translates into this:
     ///
+    /// ```plain,ignore
     ///     (T: Trait + Sized →_\impl T: Trait), T: Trait ⊢ T: Trait
+    /// ```
     ///
     /// When we try to prove it, we first go the first option, which
     /// recurses. This shows us that the impl is "useless" - it won't
@@ -959,11 +961,21 @@ fn insert_evaluation_cache(&mut self,
         if self.can_use_global_caches(param_env) {
             let mut cache = self.tcx().evaluation_cache.hashmap.borrow_mut();
             if let Some(trait_ref) = self.tcx().lift_to_global(&trait_ref) {
+                debug!(
+                    "insert_evaluation_cache(trait_ref={:?}, candidate={:?}) global",
+                    trait_ref,
+                    result,
+                );
                 cache.insert(trait_ref, WithDepNode::new(dep_node, result));
                 return;
             }
         }
 
+        debug!(
+            "insert_evaluation_cache(trait_ref={:?}, candidate={:?})",
+            trait_ref,
+            result,
+        );
         self.infcx.evaluation_cache.hashmap
                                    .borrow_mut()
                                    .insert(trait_ref, WithDepNode::new(dep_node, result));
@@ -1067,25 +1079,29 @@ fn candidate_from_obligation_no_cache<'o>(&mut self,
                 if self.intercrate_ambiguity_causes.is_some() {
                     debug!("evaluate_stack: intercrate_ambiguity_causes is some");
                     // Heuristics: show the diagnostics when there are no candidates in crate.
-                    let candidate_set = self.assemble_candidates(stack)?;
-                    if !candidate_set.ambiguous && candidate_set.vec.iter().all(|c| {
-                        !self.evaluate_candidate(stack, &c).may_apply()
-                    }) {
-                        let trait_ref = stack.obligation.predicate.skip_binder().trait_ref;
-                        let self_ty = trait_ref.self_ty();
-                        let trait_desc = trait_ref.to_string();
-                        let self_desc = if self_ty.has_concrete_skeleton() {
-                            Some(self_ty.to_string())
-                        } else {
-                            None
-                        };
-                        let cause = if let Conflict::Upstream = conflict {
-                            IntercrateAmbiguityCause::UpstreamCrateUpdate { trait_desc, self_desc }
-                        } else {
-                            IntercrateAmbiguityCause::DownstreamCrate { trait_desc, self_desc }
-                        };
-                        debug!("evaluate_stack: pushing cause = {:?}", cause);
-                        self.intercrate_ambiguity_causes.as_mut().unwrap().push(cause);
+                    if let Ok(candidate_set) = self.assemble_candidates(stack) {
+                        if !candidate_set.ambiguous && candidate_set.vec.iter().all(|c| {
+                            !self.evaluate_candidate(stack, &c).may_apply()
+                        }) {
+                            let trait_ref = stack.obligation.predicate.skip_binder().trait_ref;
+                            let self_ty = trait_ref.self_ty();
+                            let trait_desc = trait_ref.to_string();
+                            let self_desc = if self_ty.has_concrete_skeleton() {
+                                Some(self_ty.to_string())
+                            } else {
+                                None
+                            };
+                            let cause = if let Conflict::Upstream = conflict {
+                                IntercrateAmbiguityCause::UpstreamCrateUpdate {
+                                    trait_desc,
+                                    self_desc,
+                                }
+                            } else {
+                                IntercrateAmbiguityCause::DownstreamCrate { trait_desc, self_desc }
+                            };
+                            debug!("evaluate_stack: pushing cause = {:?}", cause);
+                            self.intercrate_ambiguity_causes.as_mut().unwrap().push(cause);
+                        }
                     }
                 }
                 return Ok(None);
@@ -1283,12 +1299,22 @@ fn insert_candidate_cache(&mut self,
             let mut cache = tcx.selection_cache.hashmap.borrow_mut();
             if let Some(trait_ref) = tcx.lift_to_global(&trait_ref) {
                 if let Some(candidate) = tcx.lift_to_global(&candidate) {
+                    debug!(
+                        "insert_candidate_cache(trait_ref={:?}, candidate={:?}) global",
+                        trait_ref,
+                        candidate,
+                    );
                     cache.insert(trait_ref, WithDepNode::new(dep_node, candidate));
                     return;
                 }
             }
         }
 
+        debug!(
+            "insert_candidate_cache(trait_ref={:?}, candidate={:?}) local",
+            trait_ref,
+            candidate,
+        );
         self.infcx.selection_cache.hashmap
                                   .borrow_mut()
                                   .insert(trait_ref, WithDepNode::new(dep_node, candidate));
index d6e6f0e98adc48afb18f4f61efdae5ac64dec78d..865a9a34aaa25614fa50021f004e7f21f0d4a191 100644 (file)
@@ -493,25 +493,29 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
+impl<'tcx> fmt::Display for traits::ProgramClause<'tcx> {
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+        let traits::ProgramClause { goal, hypotheses } = self;
+        write!(fmt, "{}", goal)?;
+        if !hypotheses.is_empty() {
+            write!(fmt, " :- ")?;
+            for (index, condition) in hypotheses.iter().enumerate() {
+                if index > 0 {
+                    write!(fmt, ", ")?;
+                }
+                write!(fmt, "{}", condition)?;
+            }
+        }
+        write!(fmt, ".")
+    }
+}
+
 impl<'tcx> fmt::Display for traits::Clause<'tcx> {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         use traits::Clause::*;
 
         match self {
-            Implies(hypotheses, goal) => {
-                write!(fmt, "{}", goal)?;
-                if !hypotheses.is_empty() {
-                    write!(fmt, " :- ")?;
-                    for (index, condition) in hypotheses.iter().enumerate() {
-                        if index > 0 {
-                            write!(fmt, ", ")?;
-                        }
-                        write!(fmt, "{}", condition)?;
-                    }
-                }
-                write!(fmt, ".")
-            }
-            DomainGoal(domain_goal) => write!(fmt, "{}.", domain_goal),
+            Implies(clause) => write!(fmt, "{}", clause),
             ForAll(clause) => {
                 // FIXME: appropriate binder names
                 write!(fmt, "forall<> {{ {} }}", clause.skip_binder())
@@ -553,10 +557,16 @@ impl<'tcx> TypeFoldable<'tcx> for traits::Goal<'tcx> {
     }
 }
 
+BraceStructTypeFoldableImpl! {
+    impl<'tcx> TypeFoldable<'tcx> for traits::ProgramClause<'tcx> {
+        goal,
+        hypotheses
+    }
+}
+
 EnumTypeFoldableImpl! {
     impl<'tcx> TypeFoldable<'tcx> for traits::Clause<'tcx> {
-        (traits::Clause::Implies)(hypotheses, goal),
-        (traits::Clause::DomainGoal)(domain_goal),
+        (traits::Clause::Implies)(clause),
         (traits::Clause::ForAll)(clause),
     }
 }
index fdda2286da03b00332fa51d21031581bd16699b9..2713b2d11e0679e67ce3fd93cb8121862ddfe4b3 100644 (file)
@@ -14,7 +14,8 @@
 use dep_graph::{DepNode, DepConstructor};
 use errors::DiagnosticBuilder;
 use session::Session;
-use session::config::{BorrowckMode, OutputFilenames};
+use session::config::{BorrowckMode, OutputFilenames, OptLevel};
+use session::config::CrateType::*;
 use middle;
 use hir::{TraitCandidate, HirId, ItemLocalId};
 use hir::def::{Def, Export};
@@ -57,7 +58,7 @@
                                            StableVec};
 use arena::{TypedArena, DroplessArena};
 use rustc_data_structures::indexed_vec::IndexVec;
-use rustc_data_structures::sync::Lrc;
+use rustc_data_structures::sync::{Lrc, Lock};
 use std::any::Any;
 use std::borrow::Borrow;
 use std::cell::{Cell, RefCell};
 use std::sync::mpsc;
 use std::sync::Arc;
 use syntax::abi;
-use syntax::ast::{self, Name, NodeId};
+use syntax::ast::{self, NodeId};
 use syntax::attr;
 use syntax::codemap::MultiSpan;
 use syntax::feature_gate;
-use syntax::symbol::{Symbol, keywords};
+use syntax::symbol::{Symbol, keywords, InternedString};
 use syntax_pos::Span;
 
 use hir;
@@ -130,28 +131,28 @@ pub struct CtxtInterners<'tcx> {
 
     /// Specifically use a speedy hash algorithm for these hash sets,
     /// they're accessed quite often.
-    type_: RefCell<FxHashSet<Interned<'tcx, TyS<'tcx>>>>,
-    type_list: RefCell<FxHashSet<Interned<'tcx, Slice<Ty<'tcx>>>>>,
-    substs: RefCell<FxHashSet<Interned<'tcx, Substs<'tcx>>>>,
-    canonical_var_infos: RefCell<FxHashSet<Interned<'tcx, Slice<CanonicalVarInfo>>>>,
-    region: RefCell<FxHashSet<Interned<'tcx, RegionKind>>>,
-    existential_predicates: RefCell<FxHashSet<Interned<'tcx, Slice<ExistentialPredicate<'tcx>>>>>,
-    predicates: RefCell<FxHashSet<Interned<'tcx, Slice<Predicate<'tcx>>>>>,
-    const_: RefCell<FxHashSet<Interned<'tcx, Const<'tcx>>>>,
+    type_: Lock<FxHashSet<Interned<'tcx, TyS<'tcx>>>>,
+    type_list: Lock<FxHashSet<Interned<'tcx, Slice<Ty<'tcx>>>>>,
+    substs: Lock<FxHashSet<Interned<'tcx, Substs<'tcx>>>>,
+    canonical_var_infos: Lock<FxHashSet<Interned<'tcx, Slice<CanonicalVarInfo>>>>,
+    region: Lock<FxHashSet<Interned<'tcx, RegionKind>>>,
+    existential_predicates: Lock<FxHashSet<Interned<'tcx, Slice<ExistentialPredicate<'tcx>>>>>,
+    predicates: Lock<FxHashSet<Interned<'tcx, Slice<Predicate<'tcx>>>>>,
+    const_: Lock<FxHashSet<Interned<'tcx, Const<'tcx>>>>,
 }
 
 impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> {
     fn new(arena: &'tcx DroplessArena) -> CtxtInterners<'tcx> {
         CtxtInterners {
-            arena,
-            type_: RefCell::new(FxHashSet()),
-            type_list: RefCell::new(FxHashSet()),
-            substs: RefCell::new(FxHashSet()),
-            region: RefCell::new(FxHashSet()),
-            existential_predicates: RefCell::new(FxHashSet()),
-            canonical_var_infos: RefCell::new(FxHashSet()),
-            predicates: RefCell::new(FxHashSet()),
-            const_: RefCell::new(FxHashSet()),
+            arena: arena,
+            type_: Lock::new(FxHashSet()),
+            type_list: Lock::new(FxHashSet()),
+            substs: Lock::new(FxHashSet()),
+            canonical_var_infos: Lock::new(FxHashSet()),
+            region: Lock::new(FxHashSet()),
+            existential_predicates: Lock::new(FxHashSet()),
+            predicates: Lock::new(FxHashSet()),
+            const_: Lock::new(FxHashSet()),
         }
     }
 
@@ -891,11 +892,11 @@ pub struct GlobalCtxt<'tcx> {
     /// by `proc-macro` crates.
     pub derive_macros: RefCell<NodeMap<Symbol>>,
 
-    stability_interner: RefCell<FxHashSet<&'tcx attr::Stability>>,
+    stability_interner: Lock<FxHashSet<&'tcx attr::Stability>>,
 
     pub interpret_interner: InterpretInterner<'tcx>,
 
-    layout_interner: RefCell<FxHashSet<&'tcx LayoutDetails>>,
+    layout_interner: Lock<FxHashSet<&'tcx LayoutDetails>>,
 
     /// A vector of every trait accessible in the whole crate
     /// (i.e. including those from subcrates). This is used only for
@@ -909,7 +910,7 @@ pub struct GlobalCtxt<'tcx> {
     /// This is intended to only get used during the trans phase of the compiler
     /// when satisfying the query for a particular codegen unit. Internally in
     /// the query it'll send data along this channel to get processed later.
-    pub tx_to_llvm_workers: mpsc::Sender<Box<dyn Any + Send>>,
+    pub tx_to_llvm_workers: Lock<mpsc::Sender<Box<dyn Any + Send>>>,
 
     output_filenames: Arc<OutputFilenames>,
 }
@@ -917,7 +918,7 @@ pub struct GlobalCtxt<'tcx> {
 /// Everything needed to efficiently work with interned allocations
 #[derive(Debug, Default)]
 pub struct InterpretInterner<'tcx> {
-    inner: RefCell<InterpretInternerInner<'tcx>>,
+    inner: Lock<InterpretInternerInner<'tcx>>,
 }
 
 #[derive(Debug, Default)]
@@ -1244,7 +1245,7 @@ pub fn create_and_enter<F, R>(s: &'tcx Session,
                                     Lrc::new(StableVec::new(v)));
         }
 
-        tls::enter_global(GlobalCtxt {
+        let gcx = &GlobalCtxt {
             sess: s,
             cstore,
             global_arenas: &arenas.global,
@@ -1277,15 +1278,17 @@ pub fn create_and_enter<F, R>(s: &'tcx Session,
             evaluation_cache: traits::EvaluationCache::new(),
             crate_name: Symbol::intern(crate_name),
             data_layout,
-            layout_interner: RefCell::new(FxHashSet()),
+            layout_interner: Lock::new(FxHashSet()),
             layout_depth: Cell::new(0),
             derive_macros: RefCell::new(NodeMap()),
-            stability_interner: RefCell::new(FxHashSet()),
+            stability_interner: Lock::new(FxHashSet()),
             interpret_interner: Default::default(),
             all_traits: RefCell::new(None),
-            tx_to_llvm_workers: tx,
+            tx_to_llvm_workers: Lock::new(tx),
             output_filenames: Arc::new(output_filenames.clone()),
-       }, f)
+        };
+
+        tls::enter_global(gcx, f)
     }
 
     pub fn consider_optimizing<T: Fn() -> String>(&self, msg: T) -> bool {
@@ -1497,6 +1500,40 @@ pub fn emit_end_regions(self) -> bool {
             self.sess.opts.debugging_opts.mir_emit_validate > 0 ||
             self.use_mir()
     }
+
+    #[inline]
+    pub fn share_generics(self) -> bool {
+        match self.sess.opts.debugging_opts.share_generics {
+            Some(setting) => setting,
+            None => {
+                self.sess.opts.incremental.is_some() ||
+                match self.sess.opts.optimize {
+                    OptLevel::No   |
+                    OptLevel::Less |
+                    OptLevel::Size |
+                    OptLevel::SizeMin => true,
+                    OptLevel::Default    |
+                    OptLevel::Aggressive => false,
+                }
+            }
+        }
+    }
+
+    #[inline]
+    pub fn local_crate_exports_generics(self) -> bool {
+        debug_assert!(self.share_generics());
+
+        self.sess.crate_types.borrow().iter().any(|crate_type| {
+            match crate_type {
+                CrateTypeExecutable |
+                CrateTypeStaticlib  |
+                CrateTypeProcMacro  |
+                CrateTypeCdylib     => false,
+                CrateTypeRlib       |
+                CrateTypeDylib      => true,
+            }
+        })
+    }
 }
 
 impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
@@ -1509,11 +1546,28 @@ pub fn encode_metadata(self, link_meta: &LinkMeta)
 
 impl<'gcx: 'tcx, 'tcx> GlobalCtxt<'gcx> {
     /// Call the closure with a local `TyCtxt` using the given arena.
-    pub fn enter_local<F, R>(&self, arena: &'tcx DroplessArena, f: F) -> R
-        where F: for<'a> FnOnce(TyCtxt<'a, 'gcx, 'tcx>) -> R
+    pub fn enter_local<F, R>(
+        &self,
+        arena: &'tcx DroplessArena,
+        f: F
+    ) -> R
+    where
+        F: for<'a> FnOnce(TyCtxt<'a, 'gcx, 'tcx>) -> R
     {
         let interners = CtxtInterners::new(arena);
-        tls::enter(self, &interners, f)
+        let tcx = TyCtxt {
+            gcx: self,
+            interners: &interners,
+        };
+        ty::tls::with_related_context(tcx.global_tcx(), |icx| {
+            let new_icx = ty::tls::ImplicitCtxt {
+                tcx,
+                query: icx.query.clone(),
+            };
+            ty::tls::enter_context(&new_icx, |new_icx| {
+                f(new_icx.tcx)
+            })
+        })
     }
 }
 
@@ -1678,83 +1732,196 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lif
 }
 
 pub mod tls {
-    use super::{CtxtInterners, GlobalCtxt, TyCtxt};
+    use super::{GlobalCtxt, TyCtxt};
 
     use std::cell::Cell;
     use std::fmt;
+    use std::mem;
     use syntax_pos;
+    use ty::maps;
+    use errors::{Diagnostic, TRACK_DIAGNOSTICS};
+    use rustc_data_structures::OnDrop;
+    use rustc_data_structures::sync::Lrc;
 
-    /// Marker types used for the scoped TLS slot.
-    /// The type context cannot be used directly because the scoped TLS
-    /// in libstd doesn't allow types generic over lifetimes.
-    enum ThreadLocalGlobalCtxt {}
-    enum ThreadLocalInterners {}
+    /// This is the implicit state of rustc. It contains the current
+    /// TyCtxt and query. It is updated when creating a local interner or
+    /// executing a new query. Whenever there's a TyCtxt value available
+    /// you should also have access to an ImplicitCtxt through the functions
+    /// in this module.
+    #[derive(Clone)]
+    pub struct ImplicitCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
+        /// The current TyCtxt. Initially created by `enter_global` and updated
+        /// by `enter_local` with a new local interner
+        pub tcx: TyCtxt<'a, 'gcx, 'tcx>,
 
-    thread_local! {
-        static TLS_TCX: Cell<Option<(*const ThreadLocalGlobalCtxt,
-                                     *const ThreadLocalInterners)>> = Cell::new(None)
+        /// The current query job, if any. This is updated by start_job in
+        /// ty::maps::plumbing when executing a query
+        pub query: Option<Lrc<maps::QueryJob<'gcx>>>,
     }
 
+    // A thread local value which stores a pointer to the current ImplicitCtxt
+    thread_local!(static TLV: Cell<usize> = Cell::new(0));
+
+    fn set_tlv<F: FnOnce() -> R, R>(value: usize, f: F) -> R {
+        let old = get_tlv();
+        let _reset = OnDrop(move || TLV.with(|tlv| tlv.set(old)));
+        TLV.with(|tlv| tlv.set(value));
+        f()
+    }
+
+    fn get_tlv() -> usize {
+        TLV.with(|tlv| tlv.get())
+    }
+
+    /// This is a callback from libsyntax as it cannot access the implicit state
+    /// in librustc otherwise
     fn span_debug(span: syntax_pos::Span, f: &mut fmt::Formatter) -> fmt::Result {
         with(|tcx| {
             write!(f, "{}", tcx.sess.codemap().span_to_string(span))
         })
     }
 
-    pub fn enter_global<'gcx, F, R>(gcx: GlobalCtxt<'gcx>, f: F) -> R
-        where F: for<'a> FnOnce(TyCtxt<'a, 'gcx, 'gcx>) -> R
+    /// This is a callback from libsyntax as it cannot access the implicit state
+    /// in librustc otherwise. It is used to when diagnostic messages are
+    /// emitted and stores them in the current query, if there is one.
+    fn track_diagnostic(diagnostic: &Diagnostic) {
+        with_context(|context| {
+            if let Some(ref query) = context.query {
+                query.diagnostics.lock().push(diagnostic.clone());
+            }
+        })
+    }
+
+    /// Sets up the callbacks from libsyntax on the current thread
+    pub fn with_thread_locals<F, R>(f: F) -> R
+        where F: FnOnce() -> R
     {
         syntax_pos::SPAN_DEBUG.with(|span_dbg| {
             let original_span_debug = span_dbg.get();
             span_dbg.set(span_debug);
-            let result = enter(&gcx, &gcx.global_interners, f);
-            span_dbg.set(original_span_debug);
-            result
+
+            let _on_drop = OnDrop(move || {
+                span_dbg.set(original_span_debug);
+            });
+
+            TRACK_DIAGNOSTICS.with(|current| {
+                let original = current.get();
+                current.set(track_diagnostic);
+
+                let _on_drop = OnDrop(move || {
+                    current.set(original);
+                });
+
+                f()
+            })
         })
     }
 
-    pub fn enter<'a, 'gcx: 'tcx, 'tcx, F, R>(gcx: &'a GlobalCtxt<'gcx>,
-                                             interners: &'a CtxtInterners<'tcx>,
-                                             f: F) -> R
-        where F: FnOnce(TyCtxt<'a, 'gcx, 'tcx>) -> R
+    /// Sets `context` as the new current ImplicitCtxt for the duration of the function `f`
+    pub fn enter_context<'a, 'gcx: 'tcx, 'tcx, F, R>(context: &ImplicitCtxt<'a, 'gcx, 'tcx>,
+                                                     f: F) -> R
+        where F: FnOnce(&ImplicitCtxt<'a, 'gcx, 'tcx>) -> R
     {
-        let gcx_ptr = gcx as *const _ as *const ThreadLocalGlobalCtxt;
-        let interners_ptr = interners as *const _ as *const ThreadLocalInterners;
-        TLS_TCX.with(|tls| {
-            let prev = tls.get();
-            tls.set(Some((gcx_ptr, interners_ptr)));
-            let ret = f(TyCtxt {
-                gcx,
-                interners,
-            });
-            tls.set(prev);
-            ret
+        set_tlv(context as *const _ as usize, || {
+            f(&context)
         })
     }
 
-    pub fn with<F, R>(f: F) -> R
-        where F: for<'a, 'gcx, 'tcx> FnOnce(TyCtxt<'a, 'gcx, 'tcx>) -> R
+    /// Enters GlobalCtxt by setting up libsyntax callbacks and
+    /// creating a initial TyCtxt and ImplicitCtxt.
+    /// This happens once per rustc session and TyCtxts only exists
+    /// inside the `f` function.
+    pub fn enter_global<'gcx, F, R>(gcx: &GlobalCtxt<'gcx>, f: F) -> R
+        where F: for<'a> FnOnce(TyCtxt<'a, 'gcx, 'gcx>) -> R
     {
-        TLS_TCX.with(|tcx| {
-            let (gcx, interners) = tcx.get().unwrap();
-            let gcx = unsafe { &*(gcx as *const GlobalCtxt) };
-            let interners = unsafe { &*(interners as *const CtxtInterners) };
-            f(TyCtxt {
+        with_thread_locals(|| {
+            let tcx = TyCtxt {
                 gcx,
-                interners,
+                interners: &gcx.global_interners,
+            };
+            let icx = ImplicitCtxt {
+                tcx,
+                query: None,
+            };
+            enter_context(&icx, |_| {
+                f(tcx)
             })
         })
     }
 
-    pub fn with_opt<F, R>(f: F) -> R
-        where F: for<'a, 'gcx, 'tcx> FnOnce(Option<TyCtxt<'a, 'gcx, 'tcx>>) -> R
+    /// Allows access to the current ImplicitCtxt in a closure if one is available
+    pub fn with_context_opt<F, R>(f: F) -> R
+        where F: for<'a, 'gcx, 'tcx> FnOnce(Option<&ImplicitCtxt<'a, 'gcx, 'tcx>>) -> R
     {
-        if TLS_TCX.with(|tcx| tcx.get().is_some()) {
-            with(|v| f(Some(v)))
-        } else {
+        let context = get_tlv();
+        if context == 0 {
             f(None)
+        } else {
+            unsafe { f(Some(&*(context as *const ImplicitCtxt))) }
         }
     }
+
+    /// Allows access to the current ImplicitCtxt.
+    /// Panics if there is no ImplicitCtxt available
+    pub fn with_context<F, R>(f: F) -> R
+        where F: for<'a, 'gcx, 'tcx> FnOnce(&ImplicitCtxt<'a, 'gcx, 'tcx>) -> R
+    {
+        with_context_opt(|opt_context| f(opt_context.expect("no ImplicitCtxt stored in tls")))
+    }
+
+    /// Allows access to the current ImplicitCtxt whose tcx field has the same global
+    /// interner as the tcx argument passed in. This means the closure is given an ImplicitCtxt
+    /// with the same 'gcx lifetime as the TyCtxt passed in.
+    /// This will panic if you pass it a TyCtxt which has a different global interner from
+    /// the current ImplicitCtxt's tcx field.
+    pub fn with_related_context<'a, 'gcx, 'tcx1, F, R>(tcx: TyCtxt<'a, 'gcx, 'tcx1>, f: F) -> R
+        where F: for<'b, 'tcx2> FnOnce(&ImplicitCtxt<'b, 'gcx, 'tcx2>) -> R
+    {
+        with_context(|context| {
+            unsafe {
+                let gcx = tcx.gcx as *const _ as usize;
+                assert!(context.tcx.gcx as *const _ as usize == gcx);
+                let context: &ImplicitCtxt = mem::transmute(context);
+                f(context)
+            }
+        })
+    }
+
+    /// Allows access to the current ImplicitCtxt whose tcx field has the same global
+    /// interner and local interner as the tcx argument passed in. This means the closure
+    /// is given an ImplicitCtxt with the same 'tcx and 'gcx lifetimes as the TyCtxt passed in.
+    /// This will panic if you pass it a TyCtxt which has a different global interner or
+    /// a different local interner from the current ImplicitCtxt's tcx field.
+    pub fn with_fully_related_context<'a, 'gcx, 'tcx, F, R>(tcx: TyCtxt<'a, 'gcx, 'tcx>, f: F) -> R
+        where F: for<'b> FnOnce(&ImplicitCtxt<'b, 'gcx, 'tcx>) -> R
+    {
+        with_context(|context| {
+            unsafe {
+                let gcx = tcx.gcx as *const _ as usize;
+                let interners = tcx.interners as *const _ as usize;
+                assert!(context.tcx.gcx as *const _ as usize == gcx);
+                assert!(context.tcx.interners as *const _ as usize == interners);
+                let context: &ImplicitCtxt = mem::transmute(context);
+                f(context)
+            }
+        })
+    }
+
+    /// Allows access to the TyCtxt in the current ImplicitCtxt.
+    /// Panics if there is no ImplicitCtxt available
+    pub fn with<F, R>(f: F) -> R
+        where F: for<'a, 'gcx, 'tcx> FnOnce(TyCtxt<'a, 'gcx, 'tcx>) -> R
+    {
+        with_context(|context| f(context.tcx))
+    }
+
+    /// Allows access to the TyCtxt in the current ImplicitCtxt.
+    /// The closure is passed None if there is no ImplicitCtxt available
+    pub fn with_opt<F, R>(f: F) -> R
+        where F: for<'a, 'gcx, 'tcx> FnOnce(Option<TyCtxt<'a, 'gcx, 'tcx>>) -> R
+    {
+        with_context_opt(|opt_context| f(opt_context.map(|context| context.tcx)))
+    }
 }
 
 macro_rules! sty_debug_print {
@@ -2263,12 +2430,12 @@ pub fn mk_infer(self, it: InferTy) -> Ty<'tcx> {
 
     pub fn mk_param(self,
                     index: u32,
-                    name: Name) -> Ty<'tcx> {
+                    name: InternedString) -> Ty<'tcx> {
         self.mk_ty(TyParam(ParamTy { idx: index, name: name }))
     }
 
     pub fn mk_self_type(self) -> Ty<'tcx> {
-        self.mk_param(0, keywords::SelfType.name())
+        self.mk_param(0, keywords::SelfType.name().as_str())
     }
 
     pub fn mk_param_from_def(self, def: &ty::TypeParameterDef) -> Ty<'tcx> {
index bb9467305e335ee3e51c5308e570bfd60fece727..16866636cd90aacae94f00970462b272dabc0409 100644 (file)
@@ -131,6 +131,12 @@ fn describe(tcx: TyCtxt, def_id: DefId) -> String {
     }
 }
 
+impl<'tcx> QueryDescription<'tcx> for queries::upstream_monomorphizations<'tcx> {
+    fn describe(_: TyCtxt, k: CrateNum) -> String {
+        format!("collecting available upstream monomorphizations `{:?}`", k)
+    }
+}
+
 impl<'tcx> QueryDescription<'tcx> for queries::crate_inherent_impls<'tcx> {
     fn describe(_: TyCtxt, k: CrateNum) -> String {
         format!("all inherent impls defined in crate `{:?}`", k)
@@ -466,6 +472,12 @@ fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
     }
 }
 
+impl<'tcx> QueryDescription<'tcx> for queries::extra_filename<'tcx> {
+    fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
+        format!("looking up the extra filename for a crate")
+    }
+}
+
 impl<'tcx> QueryDescription<'tcx> for queries::implementations_of_trait<'tcx> {
     fn describe(_tcx: TyCtxt, _: (CrateNum, DefId)) -> String {
         format!("looking up implementations of a trait in a crate")
diff --git a/src/librustc/ty/maps/job.rs b/src/librustc/ty/maps/job.rs
new file mode 100644 (file)
index 0000000..7d756fb
--- /dev/null
@@ -0,0 +1,90 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use rustc_data_structures::sync::{Lock, Lrc};
+use syntax_pos::Span;
+use ty::tls;
+use ty::maps::Query;
+use ty::maps::plumbing::CycleError;
+use ty::context::TyCtxt;
+use errors::Diagnostic;
+
+/// Indicates the state of a query for a given key in a query map
+pub(super) enum QueryResult<'tcx, T> {
+    /// An already executing query. The query job can be used to await for its completion
+    Started(Lrc<QueryJob<'tcx>>),
+
+    /// The query is complete and produced `T`
+    Complete(T),
+
+    /// The query panicked. Queries trying to wait on this will raise a fatal error / silently panic
+    Poisoned,
+}
+
+/// A span and a query key
+#[derive(Clone, Debug)]
+pub struct QueryInfo<'tcx> {
+    pub span: Span,
+    pub query: Query<'tcx>,
+}
+
+/// A object representing an active query job.
+pub struct QueryJob<'tcx> {
+    pub info: QueryInfo<'tcx>,
+
+    /// The parent query job which created this job and is implicitly waiting on it.
+    pub parent: Option<Lrc<QueryJob<'tcx>>>,
+
+    /// Diagnostic messages which are emitted while the query executes
+    pub diagnostics: Lock<Vec<Diagnostic>>,
+}
+
+impl<'tcx> QueryJob<'tcx> {
+    /// Creates a new query job
+    pub fn new(info: QueryInfo<'tcx>, parent: Option<Lrc<QueryJob<'tcx>>>) -> Self {
+        QueryJob {
+            diagnostics: Lock::new(Vec::new()),
+            info,
+            parent,
+        }
+    }
+
+    /// Awaits for the query job to complete.
+    ///
+    /// For single threaded rustc there's no concurrent jobs running, so if we are waiting for any
+    /// query that means that there is a query cycle, thus this always running a cycle error.
+    pub(super) fn await<'lcx>(
+        &self,
+        tcx: TyCtxt<'_, 'tcx, 'lcx>,
+        span: Span,
+    ) -> Result<(), CycleError<'tcx>> {
+        // Get the current executing query (waiter) and find the waitee amongst its parents
+        let mut current_job = tls::with_related_context(tcx, |icx| icx.query.clone());
+        let mut cycle = Vec::new();
+
+        while let Some(job) = current_job {
+            cycle.insert(0, job.info.clone());
+
+            if &*job as *const _ == self as *const _ {
+                break;
+            }
+
+            current_job = job.parent.clone();
+        }
+
+        Err(CycleError { span, cycle })
+    }
+
+    /// Signals to waiters that the query is complete.
+    ///
+    /// This does nothing for single threaded rustc,
+    /// as there are no concurrent jobs which could be waiting on us
+    pub fn signal_complete(&self) {}
+}
index 2bfb68703292382a888e6551b656f5ff007bbe2f..5a23a3b952a423c392f4aa8ce274d965b966285a 100644 (file)
@@ -14,7 +14,7 @@
 use hir::def::{Def, Export};
 use hir::{self, TraitCandidate, ItemLocalId, TransFnAttrs};
 use hir::svh::Svh;
-use infer::canonical::{Canonical, QueryResult};
+use infer::canonical::{self, Canonical};
 use lint;
 use middle::borrowck::BorrowCheckResult;
 use middle::cstore::{ExternCrate, LinkagePreference, NativeLibrary,
 use self::plumbing::*;
 pub use self::plumbing::force_from_dep_node;
 
+mod job;
+pub use self::job::{QueryJob, QueryInfo};
+use self::job::QueryResult;
+
 mod keys;
 pub use self::keys::Key;
 
     //
     // Does not include external symbols that don't have a corresponding DefId,
     // like the compiler-generated `main` function and so on.
-    [] fn reachable_non_generics: ReachableNonGenerics(CrateNum) -> Lrc<DefIdSet>,
+    [] fn reachable_non_generics: ReachableNonGenerics(CrateNum)
+        -> Lrc<DefIdMap<SymbolExportLevel>>,
     [] fn is_reachable_non_generic: IsReachableNonGeneric(DefId) -> bool,
+    [] fn is_unreachable_local_definition: IsUnreachableLocalDefinition(DefId) -> bool,
 
+    [] fn upstream_monomorphizations: UpstreamMonomorphizations(CrateNum)
+        -> Lrc<DefIdMap<Lrc<FxHashMap<&'tcx Substs<'tcx>, CrateNum>>>>,
+    [] fn upstream_monomorphizations_for: UpstreamMonomorphizationsFor(DefId)
+        -> Option<Lrc<FxHashMap<&'tcx Substs<'tcx>, CrateNum>>>,
 
     [] fn native_libraries: NativeLibraries(CrateNum) -> Lrc<Vec<NativeLibrary>>,
 
     [] fn crate_disambiguator: CrateDisambiguator(CrateNum) -> CrateDisambiguator,
     [] fn crate_hash: CrateHash(CrateNum) -> Svh,
     [] fn original_crate_name: OriginalCrateName(CrateNum) -> Symbol,
+    [] fn extra_filename: ExtraFileName(CrateNum) -> String,
 
     [] fn implementations_of_trait: implementations_of_trait_node((CrateNum, DefId))
         -> Lrc<Vec<DefId>>,
     [] fn all_crate_nums: all_crate_nums_node(CrateNum) -> Lrc<Vec<CrateNum>>,
 
     [] fn exported_symbols: ExportedSymbols(CrateNum)
-        -> Arc<Vec<(ExportedSymbol, SymbolExportLevel)>>,
+        -> Arc<Vec<(ExportedSymbol<'tcx>, SymbolExportLevel)>>,
     [] fn collect_and_partition_translation_items:
         collect_and_partition_translation_items_node(CrateNum)
         -> (Arc<DefIdSet>, Arc<Vec<Arc<CodegenUnit<'tcx>>>>),
-    [] fn symbol_export_level: GetSymbolExportLevel(DefId) -> SymbolExportLevel,
     [] fn is_translated_item: IsTranslatedItem(DefId) -> bool,
     [] fn codegen_unit: CodegenUnit(InternedString) -> Arc<CodegenUnit<'tcx>>,
     [] fn compile_codegen_unit: CompileCodegenUnit(InternedString) -> Stats,
     [] fn normalize_projection_ty: NormalizeProjectionTy(
         CanonicalProjectionGoal<'tcx>
     ) -> Result<
-        Lrc<Canonical<'tcx, QueryResult<'tcx, NormalizationResult<'tcx>>>>,
+        Lrc<Canonical<'tcx, canonical::QueryResult<'tcx, NormalizationResult<'tcx>>>>,
         NoSolution,
     >,
 
     [] fn dropck_outlives: DropckOutlives(
         CanonicalTyGoal<'tcx>
     ) -> Result<
-        Lrc<Canonical<'tcx, QueryResult<'tcx, DropckOutlivesResult<'tcx>>>>,
+        Lrc<Canonical<'tcx, canonical::QueryResult<'tcx, DropckOutlivesResult<'tcx>>>>,
         NoSolution,
     >,
 
index c103d6e015aa4c37093a10ed548822dd2804eb5c..4d78703613e9442d6e6e2e6fb1b0431888fe791e 100644 (file)
@@ -30,6 +30,7 @@
 use syntax_pos::{BytePos, Span, DUMMY_SP, FileMap};
 use syntax_pos::hygiene::{Mark, SyntaxContext, ExpnInfo};
 use ty;
+use ty::maps::job::QueryResult;
 use ty::codec::{self as ty_codec, TyDecoder, TyEncoder};
 use ty::context::TyCtxt;
 
@@ -239,6 +240,10 @@ pub fn serialize<'a, 'tcx, E>(&self,
                 for (key, entry) in const_eval::get_cache_internal(tcx).map.iter() {
                     use ty::maps::config::QueryDescription;
                     if const_eval::cache_on_disk(key.clone()) {
+                        let entry = match *entry {
+                            QueryResult::Complete(ref v) => v,
+                            _ => panic!("incomplete query"),
+                        };
                         if let Ok(ref value) = entry.value {
                             let dep_node = SerializedDepNodeIndex::new(entry.index.index());
 
@@ -1109,6 +1114,10 @@ fn encode_query_results<'enc, 'a, 'tcx, Q, E>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 {
     for (key, entry) in Q::get_cache_internal(tcx).map.iter() {
         if Q::cache_on_disk(key.clone()) {
+            let entry = match *entry {
+                QueryResult::Complete(ref v) => v,
+                _ => panic!("incomplete query"),
+            };
             let dep_node = SerializedDepNodeIndex::new(entry.index.index());
 
             // Record position of the cache entry
index 50a19526ba8c4528a74821cf7fc261df50534c14..c04e580a33dedaa1c6f840b3c2cc5f33df9bfd7d 100644 (file)
 
 use dep_graph::{DepNodeIndex, DepNode, DepKind, DepNodeColor};
 use errors::DiagnosticBuilder;
+use errors::Level;
+use ty::tls;
 use ty::{TyCtxt};
-use ty::maps::Query; // NB: actually generated by the macros in this file
 use ty::maps::config::QueryDescription;
+use ty::maps::job::{QueryResult, QueryInfo};
 use ty::item_path;
 
 use rustc_data_structures::fx::{FxHashMap};
-use std::cell::{Ref, RefMut};
+use rustc_data_structures::sync::LockGuard;
 use std::marker::PhantomData;
-use std::mem;
 use syntax_pos::Span;
 
 pub(super) struct QueryMap<'tcx, D: QueryDescription<'tcx>> {
     phantom: PhantomData<(D, &'tcx ())>,
-    pub(super) map: FxHashMap<D::Key, QueryValue<D::Value>>,
+    pub(super) map: FxHashMap<D::Key, QueryResult<'tcx, QueryValue<D::Value>>>,
 }
 
 pub(super) struct QueryValue<T> {
@@ -57,23 +58,30 @@ pub(super) fn new() -> QueryMap<'tcx, M> {
 
 pub(super) trait GetCacheInternal<'tcx>: QueryDescription<'tcx> + Sized {
     fn get_cache_internal<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
-                              -> Ref<'a, QueryMap<'tcx, Self>>;
+                              -> LockGuard<'a, QueryMap<'tcx, Self>>;
 }
 
-pub(super) struct CycleError<'a, 'tcx: 'a> {
-    span: Span,
-    cycle: RefMut<'a, [(Span, Query<'tcx>)]>,
+#[derive(Clone)]
+pub(super) struct CycleError<'tcx> {
+    pub(super) span: Span,
+    pub(super) cycle: Vec<QueryInfo<'tcx>>,
+}
+
+/// The result of `try_get_lock`
+pub(super) enum TryGetLock<'a, 'tcx: 'a, T, D: QueryDescription<'tcx> + 'a> {
+    /// The query is not yet started. Contains a guard to the map eventually used to start it.
+    NotYetStarted(LockGuard<'a, QueryMap<'tcx, D>>),
+
+    /// The query was already completed.
+    /// Returns the result of the query and its dep node index
+    /// if it succeeded or a cycle error if it failed
+    JobCompleted(Result<(T, DepNodeIndex), CycleError<'tcx>>),
 }
 
 impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
-    pub(super) fn report_cycle(self, CycleError { span, cycle }: CycleError)
+    pub(super) fn report_cycle(self, CycleError { span, cycle: stack }: CycleError)
         -> DiagnosticBuilder<'a>
     {
-        // Subtle: release the refcell lock before invoking `describe()`
-        // below by dropping `cycle`.
-        let stack = cycle.to_vec();
-        mem::drop(cycle);
-
         assert!(!stack.is_empty());
 
         // Disable naming impls with types in this path, since that
@@ -87,42 +95,46 @@ pub(super) fn report_cycle(self, CycleError { span, cycle }: CycleError)
                                  "cyclic dependency detected");
             err.span_label(span, "cyclic reference");
 
-            err.span_note(self.sess.codemap().def_span(stack[0].0),
-                          &format!("the cycle begins when {}...", stack[0].1.describe(self)));
+            err.span_note(self.sess.codemap().def_span(stack[0].span),
+                          &format!("the cycle begins when {}...", stack[0].query.describe(self)));
 
-            for &(span, ref query) in &stack[1..] {
+            for &QueryInfo { span, ref query, .. } in &stack[1..] {
                 err.span_note(self.sess.codemap().def_span(span),
                               &format!("...which then requires {}...", query.describe(self)));
             }
 
             err.note(&format!("...which then again requires {}, completing the cycle.",
-                              stack[0].1.describe(self)));
+                              stack[0].query.describe(self)));
 
             return err
         })
     }
 
-    pub(super) fn cycle_check<F, R>(self, span: Span, query: Query<'gcx>, compute: F)
-                                    -> Result<R, CycleError<'a, 'gcx>>
-        where F: FnOnce() -> R
-    {
-        {
-            let mut stack = self.maps.query_stack.borrow_mut();
-            if let Some((i, _)) = stack.iter().enumerate().rev()
-                                       .find(|&(_, &(_, ref q))| *q == query) {
-                return Err(CycleError {
-                    span,
-                    cycle: RefMut::map(stack, |stack| &mut stack[i..])
-                });
+    pub fn try_print_query_stack() {
+        eprintln!("query stack during panic:");
+
+        tls::with_context_opt(|icx| {
+            if let Some(icx) = icx {
+                let mut current_query = icx.query.clone();
+                let mut i = 0;
+
+                while let Some(query) = current_query {
+                    let mut db = DiagnosticBuilder::new(icx.tcx.sess.diagnostic(),
+                        Level::FailureNote,
+                        &format!("#{} [{}] {}",
+                                 i,
+                                 query.info.query.name(),
+                                 query.info.query.describe(icx.tcx)));
+                    db.set_span(icx.tcx.sess.codemap().def_span(query.info.span));
+                    icx.tcx.sess.diagnostic().force_print_db(db);
+
+                    current_query = query.parent.clone();
+                    i += 1;
+                }
             }
-            stack.push((span, query));
-        }
-
-        let result = compute();
-
-        self.maps.query_stack.borrow_mut().pop();
+        });
 
-        Ok(result)
+        eprintln!("end of query stack");
     }
 
     /// Try to read a node index for the node dep_node.
@@ -202,7 +214,11 @@ macro_rules! define_maps {
        [$($modifiers:tt)*] fn $name:ident: $node:ident($K:ty) -> $V:ty,)*) => {
 
         use dep_graph::DepNodeIndex;
-        use std::cell::RefCell;
+        use std::mem;
+        use errors::Diagnostic;
+        use errors::FatalError;
+        use rustc_data_structures::sync::{Lock, LockGuard};
+        use rustc_data_structures::OnDrop;
 
         define_map_struct! {
             tcx: $tcx,
@@ -214,8 +230,7 @@ pub fn new(providers: IndexVec<CrateNum, Providers<$tcx>>)
                        -> Self {
                 Maps {
                     providers,
-                    query_stack: RefCell::new(vec![]),
-                    $($name: RefCell::new(QueryMap::new())),*
+                    $($name: Lock::new(QueryMap::new())),*
                 }
             }
         }
@@ -233,6 +248,12 @@ pub enum QueryMsg {
         }
 
         impl<$tcx> Query<$tcx> {
+            pub fn name(&self) -> &'static str {
+                match *self {
+                    $(Query::$name(_) => stringify!($name),)*
+                }
+            }
+
             pub fn describe(&self, tcx: TyCtxt) -> String {
                 let (r, name) = match *self {
                     $(Query::$name(key) => {
@@ -263,7 +284,7 @@ pub struct $name<$tcx> {
 
         impl<$tcx> GetCacheInternal<$tcx> for queries::$name<$tcx> {
             fn get_cache_internal<'a>(tcx: TyCtxt<'a, $tcx, $tcx>)
-                                      -> ::std::cell::Ref<'a, QueryMap<$tcx, Self>> {
+                                      -> LockGuard<'a, QueryMap<$tcx, Self>> {
                 tcx.maps.$name.borrow()
             }
         }
@@ -277,10 +298,54 @@ fn to_dep_node(tcx: TyCtxt<'a, $tcx, 'lcx>, key: &$K) -> DepNode {
                 DepNode::new(tcx, $node(*key))
             }
 
+            /// Either get the lock of the query map, allowing us to
+            /// start executing the query, or it returns with the result of the query.
+            /// If the query already executed and panicked, this will fatal error / silently panic
+            fn try_get_lock(
+                tcx: TyCtxt<'a, $tcx, 'lcx>,
+                mut span: Span,
+                key: &$K
+            ) -> TryGetLock<'a, $tcx, $V, Self>
+            {
+                loop {
+                    let lock = tcx.maps.$name.borrow_mut();
+                    let job = if let Some(value) = lock.map.get(key) {
+                        match *value {
+                            QueryResult::Started(ref job) => Some(job.clone()),
+                            QueryResult::Complete(ref value) => {
+                                profq_msg!(tcx, ProfileQueriesMsg::CacheHit);
+                                let result = Ok(((&value.value).clone(), value.index));
+                                return TryGetLock::JobCompleted(result);
+                            },
+                            QueryResult::Poisoned => FatalError.raise(),
+                        }
+                    } else {
+                        None
+                    };
+                    let job = if let Some(job) = job {
+                        job
+                    } else {
+                        return TryGetLock::NotYetStarted(lock);
+                    };
+                    mem::drop(lock);
+
+                    // This just matches the behavior of `try_get_with` so the span when
+                    // we await matches the span we would use when executing.
+                    // See the FIXME there.
+                    if span == DUMMY_SP && stringify!($name) != "def_span" {
+                        span = key.default_span(tcx);
+                    }
+
+                    if let Err(cycle) = job.await(tcx, span) {
+                        return TryGetLock::JobCompleted(Err(cycle));
+                    }
+                }
+            }
+
             fn try_get_with(tcx: TyCtxt<'a, $tcx, 'lcx>,
                             mut span: Span,
                             key: $K)
-                            -> Result<$V, CycleError<'a, $tcx>>
+                            -> Result<$V, CycleError<$tcx>>
             {
                 debug!("ty::queries::{}::try_get_with(key={:?}, span={:?})",
                        stringify!($name),
@@ -294,24 +359,41 @@ fn try_get_with(tcx: TyCtxt<'a, $tcx, 'lcx>,
                     )
                 );
 
-                if let Some(value) = tcx.maps.$name.borrow().map.get(&key) {
-                    profq_msg!(tcx, ProfileQueriesMsg::CacheHit);
-                    tcx.dep_graph.read_index(value.index);
-                    return Ok((&value.value).clone());
+                /// Get the lock used to start the query or
+                /// return the result of the completed query
+                macro_rules! get_lock_or_return {
+                    () => {{
+                        match Self::try_get_lock(tcx, span, &key) {
+                            TryGetLock::NotYetStarted(lock) => lock,
+                            TryGetLock::JobCompleted(result) => {
+                                return result.map(|(v, index)| {
+                                    tcx.dep_graph.read_index(index);
+                                    v
+                                })
+                            }
+                        }
+                    }}
                 }
 
+                let mut lock = get_lock_or_return!();
+
                 // FIXME(eddyb) Get more valid Span's on queries.
                 // def_span guard is necessary to prevent a recursive loop,
                 // default_span calls def_span query internally.
                 if span == DUMMY_SP && stringify!($name) != "def_span" {
-                    span = key.default_span(tcx)
+                    // This might deadlock if we hold the map lock since we might be
+                    // waiting for the def_span query and switch to some other fiber
+                    // So we drop the lock here and reacquire it
+                    mem::drop(lock);
+                    span = key.default_span(tcx);
+                    lock = get_lock_or_return!();
                 }
 
                 // Fast path for when incr. comp. is off. `to_dep_node` is
                 // expensive for some DepKinds.
                 if !tcx.dep_graph.is_fully_enabled() {
                     let null_dep_node = DepNode::new_no_params(::dep_graph::DepKind::Null);
-                    return Self::force(tcx, key, span, null_dep_node)
+                    return Self::force_with_lock(tcx, key, span, lock, null_dep_node)
                                 .map(|(v, _)| v);
                 }
 
@@ -320,34 +402,36 @@ fn try_get_with(tcx: TyCtxt<'a, $tcx, 'lcx>,
                 if dep_node.kind.is_anon() {
                     profq_msg!(tcx, ProfileQueriesMsg::ProviderBegin);
 
-                    let res = tcx.cycle_check(span, Query::$name(key), || {
-                        tcx.sess.diagnostic().track_diagnostics(|| {
-                            tcx.dep_graph.with_anon_task(dep_node.kind, || {
-                                Self::compute_result(tcx.global_tcx(), key)
-                            })
+                    let res = Self::start_job(tcx, span, key, lock, |tcx| {
+                        tcx.dep_graph.with_anon_task(dep_node.kind, || {
+                            Self::compute_result(tcx.global_tcx(), key)
                         })
                     })?;
 
                     profq_msg!(tcx, ProfileQueriesMsg::ProviderEnd);
-                    let ((result, dep_node_index), diagnostics) = res;
+                    let (((result, dep_node_index), diagnostics), job) = res;
 
                     tcx.dep_graph.read_index(dep_node_index);
 
                     tcx.on_disk_query_result_cache
                        .store_diagnostics_for_anon_node(dep_node_index, diagnostics);
 
-                    let value = QueryValue::new(result, dep_node_index);
+                    let value = QueryValue::new(Clone::clone(&result), dep_node_index);
 
-                    return Ok((&tcx.maps
-                                    .$name
-                                    .borrow_mut()
-                                    .map
-                                    .entry(key)
-                                    .or_insert(value)
-                                    .value).clone());
+                    tcx.maps
+                       .$name
+                       .borrow_mut()
+                       .map
+                       .insert(key, QueryResult::Complete(value));
+
+                    job.signal_complete();
+
+                    return Ok(result);
                 }
 
                 if !dep_node.kind.is_input() {
+                    // try_mark_green_and_read may force queries. So we must drop our lock here
+                    mem::drop(lock);
                     if let Some(dep_node_index) = tcx.try_mark_green_and_read(&dep_node) {
                         profq_msg!(tcx, ProfileQueriesMsg::CacheHit);
                         return Self::load_from_disk_and_cache_in_memory(tcx,
@@ -356,9 +440,10 @@ fn try_get_with(tcx: TyCtxt<'a, $tcx, 'lcx>,
                                                                         dep_node_index,
                                                                         &dep_node)
                     }
+                    lock = get_lock_or_return!();
                 }
 
-                match Self::force(tcx, key, span, dep_node) {
+                match Self::force_with_lock(tcx, key, span, lock, dep_node) {
                     Ok((result, dep_node_index)) => {
                         tcx.dep_graph.read_index(dep_node_index);
                         Ok(result)
@@ -391,6 +476,73 @@ pub fn ensure(tcx: TyCtxt<'a, $tcx, 'lcx>, key: $K) -> () {
                 }
             }
 
+            /// Creates a job for the query and updates the query map indicating that it started.
+            /// Then it changes ImplicitCtxt to point to the new query job while it executes.
+            /// If the query panics, this updates the query map to indicate so.
+            fn start_job<F, R>(tcx: TyCtxt<'_, $tcx, 'lcx>,
+                               span: Span,
+                               key: $K,
+                               mut map: LockGuard<'_, QueryMap<$tcx, Self>>,
+                               compute: F)
+                -> Result<((R, Vec<Diagnostic>), Lrc<QueryJob<$tcx>>), CycleError<$tcx>>
+                where F: for<'b> FnOnce(TyCtxt<'b, $tcx, 'lcx>) -> R
+            {
+                let query = Query::$name(Clone::clone(&key));
+
+                let entry = QueryInfo {
+                    span,
+                    query,
+                };
+
+                // The TyCtxt stored in TLS has the same global interner lifetime
+                // as `tcx`, so we use `with_related_context` to relate the 'gcx lifetimes
+                // when accessing the ImplicitCtxt
+                let (r, job) = ty::tls::with_related_context(tcx, move |icx| {
+                    let job = Lrc::new(QueryJob::new(entry, icx.query.clone()));
+
+                    // Store the job in the query map and drop the lock to allow
+                    // others to wait it
+                    map.map.entry(key).or_insert(QueryResult::Started(job.clone()));
+                    mem::drop(map);
+
+                    let r = {
+                        let on_drop = OnDrop(|| {
+                            // Poison the query so jobs waiting on it panic
+                            tcx.maps
+                            .$name
+                            .borrow_mut()
+                            .map
+                            .insert(key, QueryResult::Poisoned);
+                            // Also signal the completion of the job, so waiters
+                            // will continue execution
+                            job.signal_complete();
+                        });
+
+                        // Update the ImplicitCtxt to point to our new query job
+                        let icx = ty::tls::ImplicitCtxt {
+                            tcx,
+                            query: Some(job.clone()),
+                        };
+
+                        // Use the ImplicitCtxt while we execute the query
+                        let r = ty::tls::enter_context(&icx, |icx| {
+                            compute(icx.tcx)
+                        });
+
+                        mem::forget(on_drop);
+
+                        r
+                    };
+
+                    (r, job)
+                });
+
+                // Extract the diagnostic from the job
+                let diagnostics: Vec<_> = mem::replace(&mut *job.diagnostics.lock(), Vec::new());
+
+                Ok(((r, diagnostics), job))
+            }
+
             fn compute_result(tcx: TyCtxt<'a, $tcx, 'lcx>, key: $K) -> $V {
                 let provider = tcx.maps.providers[key.map_crate()].$name;
                 provider(tcx.global_tcx(), key)
@@ -401,8 +553,11 @@ fn load_from_disk_and_cache_in_memory(tcx: TyCtxt<'a, $tcx, 'lcx>,
                                                   span: Span,
                                                   dep_node_index: DepNodeIndex,
                                                   dep_node: &DepNode)
-                                                  -> Result<$V, CycleError<'a, $tcx>>
+                                                  -> Result<$V, CycleError<$tcx>>
             {
+                // Note this function can be called concurrently from the same query
+                // We must ensure that this is handled correctly
+
                 debug_assert!(tcx.dep_graph.is_green(dep_node));
 
                 // First we try to load the result from the on-disk cache
@@ -425,24 +580,27 @@ fn load_from_disk_and_cache_in_memory(tcx: TyCtxt<'a, $tcx, 'lcx>,
                     None
                 };
 
-                let result = if let Some(result) = result {
-                    result
+                let (result, job) = if let Some(result) = result {
+                    (result, None)
                 } else {
                     // We could not load a result from the on-disk cache, so
                     // recompute.
-                    let (result, _ ) = tcx.cycle_check(span, Query::$name(key), || {
-                        // The diagnostics for this query have already been
-                        // promoted to the current session during
-                        // try_mark_green(), so we can ignore them here.
-                        tcx.sess.diagnostic().track_diagnostics(|| {
-                            // The dep-graph for this computation is already in
-                            // place
-                            tcx.dep_graph.with_ignore(|| {
-                                Self::compute_result(tcx, key)
-                            })
+
+                    // The diagnostics for this query have already been
+                    // promoted to the current session during
+                    // try_mark_green(), so we can ignore them here.
+                    let ((result, _), job) = Self::start_job(tcx,
+                                                             span,
+                                                             key,
+                                                             tcx.maps.$name.borrow_mut(),
+                                                             |tcx| {
+                        // The dep-graph for this computation is already in
+                        // place
+                        tcx.dep_graph.with_ignore(|| {
+                            Self::compute_result(tcx, key)
                         })
                     })?;
-                    result
+                    (result, Some(job))
                 };
 
                 // If -Zincremental-verify-ich is specified, re-hash results from
@@ -475,43 +633,76 @@ fn load_from_disk_and_cache_in_memory(tcx: TyCtxt<'a, $tcx, 'lcx>,
                     tcx.dep_graph.mark_loaded_from_cache(dep_node_index, true);
                 }
 
-                let value = QueryValue::new(result, dep_node_index);
+                let value = QueryValue::new(Clone::clone(&result), dep_node_index);
+
+                tcx.maps
+                   .$name
+                   .borrow_mut()
+                   .map
+                   .insert(key, QueryResult::Complete(value));
 
-                Ok((&tcx.maps
-                         .$name
-                         .borrow_mut()
-                         .map
-                         .entry(key)
-                         .or_insert(value)
-                         .value).clone())
+                job.map(|j| j.signal_complete());
+
+                Ok(result)
             }
 
+            #[allow(dead_code)]
             fn force(tcx: TyCtxt<'a, $tcx, 'lcx>,
                      key: $K,
                      span: Span,
                      dep_node: DepNode)
-                     -> Result<($V, DepNodeIndex), CycleError<'a, $tcx>> {
-                debug_assert!(!tcx.dep_graph.dep_node_exists(&dep_node));
+                     -> Result<($V, DepNodeIndex), CycleError<$tcx>> {
+                // We may be concurrently trying both execute and force a query
+                // Ensure that only one of them runs the query
+                let lock = match Self::try_get_lock(tcx, span, &key) {
+                    TryGetLock::NotYetStarted(lock) => lock,
+                    TryGetLock::JobCompleted(result) => return result,
+                };
+                Self::force_with_lock(tcx,
+                                      key,
+                                      span,
+                                      lock,
+                                      dep_node)
+            }
+
+            fn force_with_lock(tcx: TyCtxt<'a, $tcx, 'lcx>,
+                               key: $K,
+                               span: Span,
+                               map: LockGuard<'_, QueryMap<$tcx, Self>>,
+                               dep_node: DepNode)
+                               -> Result<($V, DepNodeIndex), CycleError<$tcx>> {
+                // If the following assertion triggers, it can have two reasons:
+                // 1. Something is wrong with DepNode creation, either here or
+                //    in DepGraph::try_mark_green()
+                // 2. Two distinct query keys get mapped to the same DepNode
+                //    (see for example #48923)
+                assert!(!tcx.dep_graph.dep_node_exists(&dep_node),
+                        "Forcing query with already existing DepNode.\n\
+                          - query-key: {:?}\n\
+                          - dep-node: {:?}",
+                        key, dep_node);
 
                 profq_msg!(tcx, ProfileQueriesMsg::ProviderBegin);
-                let res = tcx.cycle_check(span, Query::$name(key), || {
-                    tcx.sess.diagnostic().track_diagnostics(|| {
-                        if dep_node.kind.is_eval_always() {
-                            tcx.dep_graph.with_eval_always_task(dep_node,
-                                                                tcx,
-                                                                key,
-                                                                Self::compute_result)
-                        } else {
-                            tcx.dep_graph.with_task(dep_node,
-                                                    tcx,
-                                                    key,
-                                                    Self::compute_result)
-                        }
-                    })
+                let res = Self::start_job(tcx,
+                                          span,
+                                          key,
+                                          map,
+                                          |tcx| {
+                    if dep_node.kind.is_eval_always() {
+                        tcx.dep_graph.with_eval_always_task(dep_node,
+                                                            tcx,
+                                                            key,
+                                                            Self::compute_result)
+                    } else {
+                        tcx.dep_graph.with_task(dep_node,
+                                                tcx,
+                                                key,
+                                                Self::compute_result)
+                    }
                 })?;
                 profq_msg!(tcx, ProfileQueriesMsg::ProviderEnd);
 
-                let ((result, dep_node_index), diagnostics) = res;
+                let (((result, dep_node_index), diagnostics), job) = res;
 
                 if tcx.sess.opts.debugging_opts.query_dep_graph {
                     tcx.dep_graph.mark_loaded_from_cache(dep_node_index, false);
@@ -522,16 +713,19 @@ fn force(tcx: TyCtxt<'a, $tcx, 'lcx>,
                        .store_diagnostics(dep_node_index, diagnostics);
                 }
 
-                let value = QueryValue::new(result, dep_node_index);
+                let value = QueryValue::new(Clone::clone(&result), dep_node_index);
+
+                tcx.maps
+                   .$name
+                   .borrow_mut()
+                   .map
+                   .insert(key, QueryResult::Complete(value));
 
-                Ok(((&tcx.maps
-                         .$name
-                         .borrow_mut()
-                         .map
-                         .entry(key)
-                         .or_insert(value)
-                         .value).clone(),
-                   dep_node_index))
+                let job: Lrc<QueryJob> = job;
+
+                job.signal_complete();
+
+                Ok((result, dep_node_index))
             }
 
             pub fn try_get(tcx: TyCtxt<'a, $tcx, 'lcx>, span: Span, key: $K)
@@ -599,8 +793,7 @@ macro_rules! define_map_struct {
      input: ($(([$($modifiers:tt)*] [$($attr:tt)*] [$name:ident]))*)) => {
         pub struct Maps<$tcx> {
             providers: IndexVec<CrateNum, Providers<$tcx>>,
-            query_stack: RefCell<Vec<(Span, Query<$tcx>)>>,
-            $($(#[$attr])*  $name: RefCell<QueryMap<$tcx, queries::$name<$tcx>>>,)*
+            $($(#[$attr])*  $name: Lock<QueryMap<$tcx, queries::$name<$tcx>>>,)*
         }
     };
 }
@@ -854,6 +1047,9 @@ macro_rules! force {
         DepKind::ImplParent => { force!(impl_parent, def_id!()); }
         DepKind::TraitOfItem => { force!(trait_of_item, def_id!()); }
         DepKind::IsReachableNonGeneric => { force!(is_reachable_non_generic, def_id!()); }
+        DepKind::IsUnreachableLocalDefinition => {
+            force!(is_unreachable_local_definition, def_id!());
+        }
         DepKind::IsMirAvailable => { force!(is_mir_available, def_id!()); }
         DepKind::ItemAttrs => { force!(item_attrs, def_id!()); }
         DepKind::TransFnAttrs => { force!(trans_fn_attrs, def_id!()); }
@@ -881,6 +1077,7 @@ macro_rules! force {
         DepKind::CrateDisambiguator => { force!(crate_disambiguator, krate!()); }
         DepKind::CrateHash => { force!(crate_hash, krate!()); }
         DepKind::OriginalCrateName => { force!(original_crate_name, krate!()); }
+        DepKind::ExtraFileName => { force!(extra_filename, krate!()); }
 
         DepKind::AllTraitImplementations => {
             force!(all_trait_implementations, krate!());
@@ -937,13 +1134,19 @@ macro_rules! force {
 
         DepKind::TargetFeaturesWhitelist => { force!(target_features_whitelist, LOCAL_CRATE); }
 
-        DepKind::GetSymbolExportLevel => { force!(symbol_export_level, def_id!()); }
         DepKind::Features => { force!(features_query, LOCAL_CRATE); }
 
         DepKind::ProgramClausesFor => { force!(program_clauses_for, def_id!()); }
         DepKind::WasmCustomSections => { force!(wasm_custom_sections, krate!()); }
         DepKind::WasmImportModuleMap => { force!(wasm_import_module_map, krate!()); }
         DepKind::ForeignModules => { force!(foreign_modules, krate!()); }
+
+        DepKind::UpstreamMonomorphizations => {
+            force!(upstream_monomorphizations, krate!());
+        }
+        DepKind::UpstreamMonomorphizationsFor => {
+            force!(upstream_monomorphizations_for, def_id!());
+        }
     }
 
     true
index 72ba199eb24122d38032e4f5717d6b9911a2b240..5b1160f142021a8ca455f860b4af7dd724e92219 100644 (file)
@@ -712,7 +712,7 @@ pub enum IntVarValue {
 
 #[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
 pub struct TypeParameterDef {
-    pub name: Name,
+    pub name: InternedString,
     pub def_id: DefId,
     pub index: u32,
     pub has_default: bool,
@@ -2088,8 +2088,8 @@ pub fn index_of_field_named(&self, name: ast::Name) -> Option<usize> {
             return Some(index);
         }
         let mut ident = name.to_ident();
-        while ident.ctxt != SyntaxContext::empty() {
-            ident.ctxt.remove_mark();
+        while ident.span.ctxt() != SyntaxContext::empty() {
+            ident.span.remove_mark();
             if let Some(field) = self.fields.iter().position(|f| f.name.to_ident() == ident) {
                 return Some(field);
             }
@@ -2558,7 +2558,7 @@ pub fn adjust_ident(self, mut ident: Ident, scope: DefId, block: NodeId) -> (Ide
             LOCAL_CRATE => self.hir.definitions().expansion(scope.index),
             _ => Mark::root(),
         };
-        let scope = match ident.ctxt.adjust(expansion) {
+        let scope = match ident.span.adjust(expansion) {
             Some(macro_def) => self.hir.definitions().macro_def_scope(macro_def),
             None if block == DUMMY_NODE_ID => DefId::local(CRATE_DEF_INDEX), // Dummy DefId
             None => self.hir.get_module_parent(block),
index 0b0818888812f1700db4c8d4caf8b115b1e1ba3d..842c0d6573432fb962057b3432bb4707f75f3048 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::cell::{Ref, RefCell};
+use rustc_data_structures::sync::{RwLock, ReadGuard};
 use std::mem;
 
 /// The `Steal` struct is intended to used as the value for a query.
 ///
 /// FIXME(#41710) -- what is the best way to model linear queries?
 pub struct Steal<T> {
-    value: RefCell<Option<T>>
+    value: RwLock<Option<T>>
 }
 
 impl<T> Steal<T> {
     pub fn new(value: T) -> Self {
         Steal {
-            value: RefCell::new(Some(value))
+            value: RwLock::new(Some(value))
         }
     }
 
-    pub fn borrow(&self) -> Ref<T> {
-        Ref::map(self.value.borrow(), |opt| match *opt {
+    pub fn borrow(&self) -> ReadGuard<T> {
+        ReadGuard::map(self.value.borrow(), |opt| match *opt {
             None => bug!("attempted to read from stolen value"),
             Some(ref v) => v
         })
     }
 
     pub fn steal(&self) -> T {
-        let value_ref = &mut *self.value.borrow_mut();
+        let value_ref = &mut *self.value.try_write().expect("stealing value which is locked");
         let value = mem::replace(value_ref, None);
         value.expect("attempt to read from stolen value")
     }
index ed04d41ba1457fbfddb518db98a4928884b7d4a9..7a9174cbfaf73206619e80f66ffed4ded7a94384 100644 (file)
@@ -24,7 +24,7 @@
 use std::cmp::Ordering;
 use syntax::abi;
 use syntax::ast::{self, Name};
-use syntax::symbol::keywords;
+use syntax::symbol::{keywords, InternedString};
 
 use serialize;
 
@@ -864,16 +864,16 @@ pub fn abi(&self) -> abi::Abi {
 #[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
 pub struct ParamTy {
     pub idx: u32,
-    pub name: Name,
+    pub name: InternedString,
 }
 
 impl<'a, 'gcx, 'tcx> ParamTy {
-    pub fn new(index: u32, name: Name) -> ParamTy {
+    pub fn new(index: u32, name: InternedString) -> ParamTy {
         ParamTy { idx: index, name: name }
     }
 
     pub fn for_self() -> ParamTy {
-        ParamTy::new(0, keywords::SelfType.name())
+        ParamTy::new(0, keywords::SelfType.name().as_str())
     }
 
     pub fn for_def(def: &ty::TypeParameterDef) -> ParamTy {
@@ -885,7 +885,7 @@ pub fn to_ty(self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
     }
 
     pub fn is_self(&self) -> bool {
-        if self.name == keywords::SelfType.name() {
+        if self.name == keywords::SelfType.name().as_str() {
             assert_eq!(self.idx, 0);
             true
         } else {
index 22f851a908b252b5f2046949b4f4fdb74a812876..c170c2a63e82996b697b913e67141dea58fe22bd 100644 (file)
@@ -729,7 +729,7 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
             }
             TyParam(p) => {
                 self.hash(p.idx);
-                self.hash(p.name.as_str());
+                self.hash(p.name);
             }
             TyProjection(ref data) => {
                 self.def_id(data.item_def_id);
index 6b896a889e3003112b33eee21e6ad1ee32afb9c7..32ec837f031bfad02368fdd26831aead7377c46a 100644 (file)
 use std::hash::{Hash, BuildHasher};
 use std::iter::repeat;
 use std::panic;
+use std::env;
 use std::path::Path;
 use std::time::{Duration, Instant};
 
 use std::sync::mpsc::{Sender};
 use syntax_pos::{SpanData};
 use ty::maps::{QueryMsg};
+use ty::TyCtxt;
 use dep_graph::{DepNode};
 use proc_macro;
 use lazy_static;
 
 fn panic_hook(info: &panic::PanicInfo) {
     if !proc_macro::__internal::in_sess() {
-        (*DEFAULT_HOOK)(info)
+        (*DEFAULT_HOOK)(info);
+
+        let backtrace = env::var_os("RUST_BACKTRACE").map(|x| &x != "0").unwrap_or(false);
+
+        if backtrace {
+            TyCtxt::try_print_query_stack();
+        }
     }
 }
 
index e17fce5a2ec0a276d5409af7ecea393a3edd257b..0c7a9a91711b7aac81705e8d635bf6801a6638a4 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![deny(warnings)]
-
 #![feature(rustc_private)]
 
 extern crate rustc;
index 6f08fcf702595eb49957fc70ff8c43516c6925c9..0f051ea5981ca4eefe254c264a179b4343640ad0 100644 (file)
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/")]
-#![deny(warnings)]
 #![forbid(unsafe_code)]
 
-#![cfg_attr(stage0, feature(slice_patterns))]
-#![cfg_attr(stage0, feature(i128_type))]
-#![cfg_attr(stage0, feature(try_from))]
-
 // See librustc_cratesio_shim/Cargo.toml for a comment explaining this.
 #[allow(unused_extern_crates)]
 extern crate rustc_cratesio_shim;
index 627d79724b28a463568723c97dedc96728eaa13d..6e06ea858efad12413fef5d59b75361c56e0344e 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![cfg_attr(stage0, feature(i128_type))]
-
 #[macro_use]
 extern crate rustc_apfloat;
 
index 8f8ef1cc4a0111165ced04bddc19f49a1078fe43..34d8b75a5bfb3476a1f587d33ad663f2d8498f37 100644 (file)
@@ -17,3 +17,4 @@ cmake = "0.1.18"
 alloc = { path = "../liballoc" }
 alloc_system = { path = "../liballoc_system" }
 core = { path = "../libcore" }
+compiler_builtins = { path = "../rustc/compiler_builtins_shim" }
index 9baee26770998a4ffe92f3bb53ad7d4a303134d9..027a9c455553051b7944494b7d8bbeab2868c4f8 100644 (file)
@@ -24,7 +24,6 @@
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/")]
-#![deny(warnings)]
 
 #![feature(box_syntax)]
 #![feature(const_fn)]
index 72173b62594e9658cd77fa4802f6d154d4ccd44d..480de9ff486e5d1e1af6864c3f0a2c0f8d0499bd 100644 (file)
@@ -47,6 +47,7 @@ pub fn opts() -> TargetOptions {
         exe_allocation_crate: super::maybe_jemalloc(),
         has_elf_tls: version >= (10, 7),
         abi_return_struct_as_int: true,
+        emit_debug_gdb_scripts: false,
         .. Default::default()
     }
 }
index 507243a58a5f9506b62c282c7a7c6875e7f470bb..592b27ac641b5204d2af6ec4a16cce4d625e938c 100644 (file)
@@ -478,6 +478,9 @@ pub struct TargetOptions {
 
     /// Whether or not bitcode is embedded in object files
     pub embed_bitcode: bool,
+
+    /// Whether a .debug_gdb_scripts section will be added to the output object file
+    pub emit_debug_gdb_scripts: bool,
 }
 
 impl Default for TargetOptions {
@@ -550,6 +553,7 @@ fn default() -> TargetOptions {
             codegen_backend: "llvm".to_string(),
             default_hidden_visibility: false,
             embed_bitcode: false,
+            emit_debug_gdb_scripts: true,
         }
     }
 }
@@ -799,6 +803,7 @@ macro_rules! key {
         key!(codegen_backend);
         key!(default_hidden_visibility, bool);
         key!(embed_bitcode, bool);
+        key!(emit_debug_gdb_scripts, bool);
 
         if let Some(array) = obj.find("abi-blacklist").and_then(Json::as_array) {
             for name in array.iter().filter_map(|abi| abi.as_string()) {
@@ -1002,6 +1007,7 @@ macro_rules! target_option_val {
         target_option_val!(codegen_backend);
         target_option_val!(default_hidden_visibility);
         target_option_val!(embed_bitcode);
+        target_option_val!(emit_debug_gdb_scripts);
 
         if default.abi_blacklist != self.options.abi_blacklist {
             d.insert("abi-blacklist".to_string(), self.options.abi_blacklist.iter()
index d0f512ae47cd9d02392ad4358bbacdd9f1009fbc..31df9be0bc3f81e7b92f677a5bffa0e6d53f4538 100644 (file)
@@ -59,6 +59,9 @@ pub fn target() -> TargetResult {
             // too much overhead for such small target.
             trap_unreachable: false,
 
+            // See the thumb_base.rs file for an explanation of this value
+            emit_debug_gdb_scripts: false,
+
             .. Default::default( )
         }
     })
index 6a8f52f509310b0cf0a962be74c3f56b1dca7932..bb1fbfad2618f17291ce9fe694b86d7faa3b9699 100644 (file)
@@ -53,6 +53,13 @@ pub fn opts() -> TargetOptions {
         // costs it involves.
         relocation_model: "static".to_string(),
         abi_blacklist: super::arm_base::abi_blacklist(),
+        // When this section is added a volatile load to its start address is also generated. This
+        // volatile load is a footgun as it can end up loading an invalid memory address, depending
+        // on how the user set up their linker scripts. This section adds pretty printer for stuff
+        // like std::Vec, which is not that used in no-std context, so it's best to left it out
+        // until we figure a way to add the pretty printers without requiring a volatile load cf.
+        // rust-lang/rust#44993.
+        emit_debug_gdb_scripts: false,
         .. Default::default()
     }
 }
index 05b6247c9518f040fedda7f653c6346803473732..971b21e062f69415d858743eff0d3187cb86f993 100644 (file)
@@ -102,6 +102,7 @@ pub fn opts() -> TargetOptions {
         ],
         custom_unwind_resume: true,
         abi_return_struct_as_int: true,
+        emit_debug_gdb_scripts: false,
 
         .. Default::default()
     }
index 34aa17267f8bea59e9e6cdf44c0c49591d20f167..06e879bec3492310184cce57472dfef0e0b2e535 100644 (file)
@@ -34,6 +34,7 @@ pub fn opts() -> TargetOptions {
         crt_static_allows_dylibs: true,
         crt_static_respected: true,
         abi_return_struct_as_int: true,
+        emit_debug_gdb_scripts: false,
 
         .. Default::default()
     }
index 93d6247eeae47733af3b4f8833bbb248ceda400c..2049a146a0f02c85bad4d846edeaf3d9e581abcc 100644 (file)
@@ -128,7 +128,7 @@ fn borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, owner_def_id: DefId)
     // Note that `mir_validated` is a "stealable" result; the
     // thief, `optimized_mir()`, forces borrowck, so we know that
     // is not yet stolen.
-    tcx.mir_validated(owner_def_id).borrow();
+    ty::maps::queries::mir_validated::ensure(tcx, owner_def_id);
 
     // option dance because you can't capture an uninitialized variable
     // by mut-ref.
index d54654c60868c26d586907659b1b6a3d3ec1ecff..52a357e1a1d3173c4d7a64327e3efd06af818eef 100644 (file)
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/")]
-#![deny(warnings)]
 
 #![allow(non_camel_case_types)]
 
 #![feature(from_ref)]
-#![cfg_attr(stage0, feature(match_default_bindings))]
 #![feature(quote)]
 
 #[macro_use] extern crate log;
index 7177e2818fbcc8029b98c4d0b95b0f40cb87c0d3..499c330be1da8aca6a0d32483d9d011c2a7bf559 100644 (file)
@@ -17,9 +17,6 @@
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/")]
-#![deny(warnings)]
-
-#![cfg_attr(stage0, feature(i128_type, i128))]
 
 extern crate rustc_apfloat;
 
index 622fb423b51e4450b0b15ea1b36df5c4bde58d13..ba1d73dc268dfa3515b12b93d0621e32910aa09a 100644 (file)
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://www.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/")]
-#![deny(warnings)]
 
 #![feature(collections_range)]
 #![feature(nonzero)]
 #![feature(unboxed_closures)]
 #![feature(fn_traits)]
 #![feature(unsize)]
-#![cfg_attr(stage0, feature(conservative_impl_trait))]
-#![cfg_attr(stage0, feature(i128_type, i128))]
 #![feature(specialization)]
 #![feature(optin_builtin_traits)]
-#![cfg_attr(stage0, feature(underscore_lifetimes))]
 #![feature(macro_vis_matcher)]
 #![feature(allow_internal_unstable)]
-#![cfg_attr(stage0, feature(universal_impl_trait))]
 
 #![cfg_attr(unix, feature(libc))]
 #![cfg_attr(test, feature(test))]
index 184ef1369761cb181501960b2484197037a14d46..0f534f0adec4b919e3dcd5cfe5a533353a9c9462 100644 (file)
@@ -388,6 +388,18 @@ pub fn with_read_lock<F: FnOnce(&T) -> R, R>(&self, f: F) -> R {
         f(&*self.read())
     }
 
+    #[cfg(not(parallel_queries))]
+    #[inline(always)]
+    pub fn try_write(&self) -> Result<WriteGuard<T>, ()> {
+        self.0.try_borrow_mut().map_err(|_| ())
+    }
+
+    #[cfg(parallel_queries)]
+    #[inline(always)]
+    pub fn try_write(&self) -> Result<WriteGuard<T>, ()> {
+        self.0.try_write().ok_or(())
+    }
+
     #[cfg(not(parallel_queries))]
     #[inline(always)]
     pub fn write(&self) -> WriteGuard<T> {
index b461431c7bbbd74b6eb6a8d66f6ccf88910ebd11..f6903d26e701c8f7fea08aad3ea12bb0b4fd7b1c 100644 (file)
@@ -17,7 +17,6 @@
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/")]
-#![deny(warnings)]
 
 #![feature(box_syntax)]
 #![cfg_attr(unix, feature(libc))]
@@ -1045,7 +1044,7 @@ fn print_crate_info(trans: &TransCrate,
                     let mut cfgs = Vec::new();
                     for &(name, ref value) in sess.parse_sess.config.iter() {
                         let gated_cfg = GatedCfg::gate(&ast::MetaItem {
-                            name,
+                            ident: ast::Ident::with_empty_ctxt(name),
                             node: ast::MetaItemKind::Word,
                             span: DUMMY_SP,
                         });
index c5e7fdb30d36ade6dd716322037674395a9fe0d4..70b73ebb8cdeb476f5b978bdf9579a8e017542a7 100644 (file)
@@ -466,11 +466,11 @@ fn pp_ann(&self) -> &pprust::PpAnn {
 impl<'a> pprust::PpAnn for HygieneAnnotation<'a> {
     fn post(&self, s: &mut pprust::State, node: pprust::AnnNode) -> io::Result<()> {
         match node {
-            pprust::NodeIdent(&ast::Ident { name, ctxt }) => {
+            pprust::NodeIdent(&ast::Ident { name, span }) => {
                 s.s.space()?;
                 // FIXME #16420: this doesn't display the connections
                 // between syntax contexts
-                s.synth_comment(format!("{}{:?}", name.as_u32(), ctxt))
+                s.synth_comment(format!("{}{:?}", name.as_u32(), span.ctxt()))
             }
             pprust::NodeName(&name) => {
                 s.s.space()?;
index 9efd8844977f905e7bf41fa15a25dee7e19b367a..971855ee2d007256b58be8846212e5ca1fd1e461 100644 (file)
@@ -303,7 +303,7 @@ pub fn t_pair(&self, ty1: Ty<'tcx>, ty2: Ty<'tcx>) -> Ty<'tcx> {
 
     pub fn t_param(&self, index: u32) -> Ty<'tcx> {
         let name = format!("T{}", index);
-        self.infcx.tcx.mk_param(index, Symbol::intern(&name))
+        self.infcx.tcx.mk_param(index, Symbol::intern(&name).as_str())
     }
 
     pub fn re_early_bound(&self, index: u32, name: &'static str) -> ty::Region<'tcx> {
index 37ae64cef572562f1467ca98c75e93e5de0096e2..8d5f9ac93f0b48e3d5b92f7233715e3f2c1cf7e9 100644 (file)
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/")]
-#![deny(warnings)]
 
 #![feature(custom_attribute)]
 #![allow(unused_attributes)]
 #![feature(range_contains)]
 #![cfg_attr(unix, feature(libc))]
-#![cfg_attr(stage0, feature(conservative_impl_trait))]
-#![cfg_attr(stage0, feature(i128_type))]
 #![feature(optin_builtin_traits)]
 
 extern crate atty;
@@ -42,7 +39,6 @@
 
 use std::borrow::Cow;
 use std::cell::{RefCell, Cell};
-use std::mem;
 use std::{error, fmt};
 use std::sync::atomic::AtomicUsize;
 use std::sync::atomic::Ordering::SeqCst;
@@ -269,7 +265,6 @@ pub struct Handler {
     emitter: RefCell<Box<Emitter>>,
     continue_after_error: Cell<bool>,
     delayed_span_bug: RefCell<Option<Diagnostic>>,
-    tracked_diagnostics: RefCell<Option<Vec<Diagnostic>>>,
 
     // This set contains the `DiagnosticId` of all emitted diagnostics to avoid
     // emitting the same diagnostic with extended help (`--teach`) twice, which
@@ -282,6 +277,11 @@ pub struct Handler {
     emitted_diagnostics: RefCell<FxHashSet<u128>>,
 }
 
+fn default_track_diagnostic(_: &Diagnostic) {}
+
+thread_local!(pub static TRACK_DIAGNOSTICS: Cell<fn(&Diagnostic)> =
+                Cell::new(default_track_diagnostic));
+
 #[derive(Default)]
 pub struct HandlerFlags {
     pub can_emit_warnings: bool,
@@ -333,7 +333,6 @@ pub fn with_emitter_and_flags(e: Box<Emitter>, flags: HandlerFlags) -> Handler {
             emitter: RefCell::new(e),
             continue_after_error: Cell::new(true),
             delayed_span_bug: RefCell::new(None),
-            tracked_diagnostics: RefCell::new(None),
             tracked_diagnostic_codes: RefCell::new(FxHashSet()),
             emitted_diagnostics: RefCell::new(FxHashSet()),
         }
@@ -631,17 +630,6 @@ pub fn emit_with_code(&self, msp: &MultiSpan, msg: &str, code: DiagnosticId, lvl
         }
     }
 
-    pub fn track_diagnostics<F, R>(&self, f: F) -> (R, Vec<Diagnostic>)
-        where F: FnOnce() -> R
-    {
-        let prev = mem::replace(&mut *self.tracked_diagnostics.borrow_mut(),
-                                Some(Vec::new()));
-        let ret = f();
-        let diagnostics = mem::replace(&mut *self.tracked_diagnostics.borrow_mut(), prev)
-            .unwrap();
-        (ret, diagnostics)
-    }
-
     /// `true` if a diagnostic with this code has already been emitted in this handler.
     ///
     /// Used to suppress emitting the same error multiple times with extended explanation when
@@ -650,12 +638,17 @@ pub fn code_emitted(&self, code: &DiagnosticId) -> bool {
         self.tracked_diagnostic_codes.borrow().contains(code)
     }
 
+    pub fn force_print_db(&self, mut db: DiagnosticBuilder) {
+        self.emitter.borrow_mut().emit(&db);
+        db.cancel();
+    }
+
     fn emit_db(&self, db: &DiagnosticBuilder) {
         let diagnostic = &**db;
 
-        if let Some(ref mut list) = *self.tracked_diagnostics.borrow_mut() {
-            list.push(diagnostic.clone());
-        }
+        TRACK_DIAGNOSTICS.with(|track_diagnostics| {
+            track_diagnostics.get()(diagnostic);
+        });
 
         if let Some(ref code) = diagnostic.code {
             self.tracked_diagnostic_codes.borrow_mut().insert(code.clone());
index 17a6176b79e954d4cbb72d2968cb65dff82cf12f..57311a7b588a049fdf3580c25ae63503475fa286 100644 (file)
@@ -110,7 +110,7 @@ fn argument(&self, attr: &ast::Attribute) -> Option<ast::Name> {
         for list_item in attr.meta_item_list().unwrap_or_default() {
             match list_item.word() {
                 Some(word) if value.is_none() =>
-                    value = Some(word.name().clone()),
+                    value = Some(word.ident.name),
                 _ =>
                     // FIXME better-encapsulate meta_item (don't directly access `node`)
                     span_bug!(list_item.span(), "unexpected meta-item {:?}", list_item.node),
index cad72ff778b55155e816b9d78950ad6b5c3e5f3a..a5e07bcec24bb65c242de5765c68c6ad9c3792a9 100644 (file)
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/")]
-#![deny(warnings)]
 
-#![cfg_attr(stage0, feature(conservative_impl_trait))]
 #![feature(fs_read_write)]
-#![cfg_attr(stage0, feature(i128_type))]
-#![cfg_attr(stage0, feature(inclusive_range_syntax))]
 #![feature(specialization)]
 
 extern crate graphviz;
index c0728cb2b6669da1579869acc939e0a1294fe2f0..2cc6708bc034e1dafe570fe975f57f8aee6bac02 100644 (file)
@@ -171,16 +171,16 @@ fn check_pat(&mut self, cx: &LateContext, pat: &hir::Pat) {
                 if fieldpat.node.is_shorthand {
                     continue;
                 }
-                if let PatKind::Binding(_, _, ident, None) = fieldpat.node.pat.node {
-                    if ident.node == fieldpat.node.name {
+                if let PatKind::Binding(_, _, name, None) = fieldpat.node.pat.node {
+                    if name.node == fieldpat.node.name {
                         let mut err = cx.struct_span_lint(NON_SHORTHAND_FIELD_PATTERNS,
                                      fieldpat.span,
                                      &format!("the `{}:` in this pattern is redundant",
-                                              ident.node));
+                                              name.node));
                         let subspan = cx.tcx.sess.codemap().span_through_char(fieldpat.span, ':');
                         err.span_suggestion_short(subspan,
                                                   "remove this",
-                                                  format!("{}", ident.node));
+                                                  format!("{}", name.node));
                         err.emit();
                     }
                 }
@@ -625,7 +625,7 @@ fn check_trait_item(&mut self, cx: &EarlyContext, it: &ast::TraitItem) {
                 for arg in sig.decl.inputs.iter() {
                     match arg.pat.node {
                         ast::PatKind::Ident(_, ident, None) => {
-                            if ident.node.name == keywords::Invalid.name() {
+                            if ident.name == keywords::Invalid.name() {
                                 cx.span_lint(ANONYMOUS_PARAMETERS,
                                              arg.pat.span,
                                              "use of deprecated anonymous parameter");
index d024adad9d0305af87d052541c06f26fd7934a8e..16e8600f2d89bfec62c9bb5eeccdcec779c850fb 100644 (file)
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/")]
-#![deny(warnings)]
 
 #![cfg_attr(test, feature(test))]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
-#![cfg_attr(stage0, feature(i128_type))]
 #![feature(macro_vis_matcher)]
 #![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
-#![cfg_attr(stage0, feature(never_type))]
 
 #[macro_use]
 extern crate syntax;
index aa93b3098e046e8a0d8c0a433c28c50945e37a9c..bf86f6a69522f07492094c0fc81f28fee8646931 100644 (file)
@@ -377,7 +377,7 @@ fn check_use_tree(&self, cx: &EarlyContext, use_tree: &ast::UseTree, item: &ast:
             let node_ident;
             match items[0].0.kind {
                 ast::UseTreeKind::Simple(rename) => {
-                    let orig_ident = items[0].0.prefix.segments.last().unwrap().identifier;
+                    let orig_ident = items[0].0.prefix.segments.last().unwrap().ident;
                     if orig_ident.name == keywords::SelfValue.name() {
                         return;
                     } else {
index 16bee5b987e2d0a6b333745e0289f20597cf9685..bf8a087ab556bd3e4e264dbb208609c64086cf7f 100644 (file)
@@ -16,7 +16,6 @@
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "https://doc.rust-lang.org/nightly/")]
-#![deny(warnings)]
 
 #![feature(box_syntax)]
 #![feature(concat_idents)]
index 087c3162119432a60af7000c58fd7c654dd11c09..9c19b53742654e4c760056a09d1233d25fad7851 100644 (file)
@@ -17,3 +17,4 @@ cmake = "0.1.18"
 alloc = { path = "../liballoc" }
 alloc_system = { path = "../liballoc_system" }
 core = { path = "../libcore" }
+compiler_builtins = { path = "../rustc/compiler_builtins_shim" }
index 13ebb5f61660f981bfc9921e54f2f67a443ac967..86f495c5fac3a2782e245ed06bc2364d0184f2ad 100644 (file)
@@ -262,6 +262,7 @@ fn resolve_crate(&mut self,
                      ident: Symbol,
                      name: Symbol,
                      hash: Option<&Svh>,
+                     extra_filename: Option<&str>,
                      span: Span,
                      path_kind: PathKind,
                      mut dep_kind: DepKind)
@@ -277,6 +278,7 @@ fn resolve_crate(&mut self,
                 ident,
                 crate_name: name,
                 hash: hash.map(|a| &*a),
+                extra_filename: extra_filename,
                 filesearch: self.sess.target_filesearch(path_kind),
                 target: &self.sess.target.target,
                 triple: &self.sess.opts.target_triple,
@@ -409,7 +411,8 @@ fn resolve_crate_deps(&mut self,
         ::std::iter::once(krate).chain(crate_root.crate_deps
                                                  .decode(metadata)
                                                  .map(|dep| {
-            debug!("resolving dep crate {} hash: `{}`", dep.name, dep.hash);
+            info!("resolving dep crate {} hash: `{}` extra filename: `{}`", dep.name, dep.hash,
+                  dep.extra_filename);
             if dep.kind == DepKind::UnexportedMacrosOnly {
                 return krate;
             }
@@ -418,7 +421,8 @@ fn resolve_crate_deps(&mut self,
                 _ => dep.kind,
             };
             let (local_cnum, ..) = self.resolve_crate(
-                root, dep.name, dep.name, Some(&dep.hash), span, PathKind::Dependency, dep_kind,
+                root, dep.name, dep.name, Some(&dep.hash), Some(&dep.extra_filename), span,
+                PathKind::Dependency, dep_kind,
             );
             local_cnum
         })).collect()
@@ -437,6 +441,7 @@ fn read_extension_crate(&mut self, span: Span, orig_name: Symbol, rename: Symbol
             ident: orig_name,
             crate_name: rename,
             hash: None,
+            extra_filename: None,
             filesearch: self.sess.host_filesearch(PathKind::Crate),
             target: &self.sess.host,
             triple: &host_triple,
@@ -664,7 +669,7 @@ fn inject_panic_runtime(&mut self, krate: &ast::Crate) {
 
         let dep_kind = DepKind::Implicit;
         let (cnum, data) =
-            self.resolve_crate(&None, name, name, None, DUMMY_SP, PathKind::Crate, dep_kind);
+            self.resolve_crate(&None, name, name, None, None, DUMMY_SP, PathKind::Crate, dep_kind);
 
         // Sanity check the loaded crate to ensure it is indeed a panic runtime
         // and the panic strategy is indeed what we thought it was.
@@ -771,7 +776,7 @@ fn inject_sanitizer_runtime(&mut self) {
                 let symbol = Symbol::intern(name);
                 let dep_kind = DepKind::Explicit;
                 let (_, data) =
-                    self.resolve_crate(&None, symbol, symbol, None, DUMMY_SP,
+                    self.resolve_crate(&None, symbol, symbol, None, None, DUMMY_SP,
                                        PathKind::Crate, dep_kind);
 
                 // Sanity check the loaded crate to ensure it is indeed a sanitizer runtime
@@ -794,7 +799,7 @@ fn inject_profiler_runtime(&mut self) {
             let symbol = Symbol::intern("profiler_builtins");
             let dep_kind = DepKind::Implicit;
             let (_, data) =
-                self.resolve_crate(&None, symbol, symbol, None, DUMMY_SP,
+                self.resolve_crate(&None, symbol, symbol, None, None, DUMMY_SP,
                                    PathKind::Crate, dep_kind);
 
             // Sanity check the loaded crate to ensure it is indeed a profiler runtime
@@ -909,6 +914,7 @@ fn inject_allocator_crate(&mut self, krate: &ast::Crate) {
                                                               name,
                                                               name,
                                                               None,
+                                                              None,
                                                               DUMMY_SP,
                                                               PathKind::Crate,
                                                               DepKind::Implicit);
@@ -1059,7 +1065,8 @@ fn process_item(&mut self, item: &ast::Item, definitions: &Definitions) {
                 };
 
                 let (cnum, ..) = self.resolve_crate(
-                    &None, item.ident.name, orig_name, None, item.span, PathKind::Crate, dep_kind,
+                    &None, item.ident.name, orig_name, None, None,
+                    item.span, PathKind::Crate, dep_kind,
                 );
 
                 let def_id = definitions.opt_local_def_id(item.id).unwrap();
@@ -1074,6 +1081,7 @@ fn process_item(&mut self, item: &ast::Item, definitions: &Definitions) {
     }
 
     fn resolve_crate_from_path(&mut self, name: Symbol, span: Span) -> CrateNum {
-        self.resolve_crate(&None, name, name, None, span, PathKind::Crate, DepKind::Explicit).0
+        self.resolve_crate(&None, name, name, None, None, span, PathKind::Crate,
+                           DepKind::Explicit).0
     }
 }
index 5fd8ebaa9b4a6d3b4a32b399b61767db816b5b98..2c995d2f5cde637be697c85cc20935ab6fb3eb47 100644 (file)
@@ -163,7 +163,7 @@ fn into_args(self) -> (DefId, DefId) { (self.0.as_def_id(), self.1) }
     fn_arg_names => { cdata.get_fn_arg_names(def_id.index) }
     impl_parent => { cdata.get_parent_impl(def_id.index) }
     trait_of_item => { cdata.get_trait_of_item(def_id.index) }
-    item_body_nested_bodies => { cdata.item_body_nested_bodies(def_id.index) }
+    item_body_nested_bodies => { cdata.item_body_nested_bodies(tcx, def_id.index) }
     const_is_rvalue_promotable_to_static => {
         cdata.const_is_rvalue_promotable_to_static(def_id.index)
     }
@@ -186,9 +186,9 @@ fn into_args(self) -> (DefId, DefId) { (self.0.as_def_id(), self.1) }
         let reachable_non_generics = tcx
             .exported_symbols(cdata.cnum)
             .iter()
-            .filter_map(|&(exported_symbol, _)| {
+            .filter_map(|&(exported_symbol, export_level)| {
                 if let ExportedSymbol::NonGeneric(def_id) = exported_symbol {
-                    return Some(def_id)
+                    return Some((def_id, export_level))
                 } else {
                     None
                 }
@@ -213,6 +213,9 @@ fn into_args(self) -> (DefId, DefId) { (self.0.as_def_id(), self.1) }
     crate_hash => { cdata.hash() }
     original_crate_name => { cdata.name() }
 
+    extra_filename => { cdata.root.extra_filename.clone() }
+
+
     implementations_of_trait => {
         let mut result = vec![];
         let filter = Some(other);
@@ -265,7 +268,7 @@ fn into_args(self) -> (DefId, DefId) { (self.0.as_def_id(), self.1) }
             return Arc::new(Vec::new())
         }
 
-        Arc::new(cdata.exported_symbols())
+        Arc::new(cdata.exported_symbols(tcx))
     }
 
     wasm_custom_sections => { Lrc::new(cdata.wasm_custom_sections()) }
index e938d5c1a97fe4e9d1ff6e0ad4c44e9b448ddd0a..3ea4ddc25226fffe80d39cbeba80b474ea18e2cd 100644 (file)
@@ -818,11 +818,14 @@ pub fn item_body_tables(&self,
         tcx.alloc_tables(ast.tables.decode((self, tcx)))
     }
 
-    pub fn item_body_nested_bodies(&self, id: DefIndex) -> ExternBodyNestedBodies {
+    pub fn item_body_nested_bodies(&self,
+                                   tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                   id: DefIndex)
+                                   -> ExternBodyNestedBodies {
         if let Some(ref ast) = self.entry(id).ast {
-            let ast = ast.decode(self);
+            let mut ast = ast.decode(self);
             let nested_bodies: BTreeMap<_, _> = ast.nested_bodies
-                                                   .decode(self)
+                                                   .decode((self, tcx.sess))
                                                    .map(|body| (body.id(), body))
                                                    .collect();
             ExternBodyNestedBodies {
@@ -1065,11 +1068,13 @@ pub fn get_fn_arg_names(&self, id: DefIndex) -> Vec<ast::Name> {
         arg_names.decode(self).collect()
     }
 
-    pub fn exported_symbols(&self) -> Vec<(ExportedSymbol, SymbolExportLevel)> {
-        self.root
-            .exported_symbols
-            .decode(self)
-            .collect()
+    pub fn exported_symbols(&self,
+                            tcx: TyCtxt<'a, 'tcx, 'tcx>)
+                            -> Vec<(ExportedSymbol<'tcx>, SymbolExportLevel)> {
+        let lazy_seq: LazySeq<(ExportedSymbol<'tcx>, SymbolExportLevel)> =
+            LazySeq::with_position_and_length(self.root.exported_symbols.position,
+                                              self.root.exported_symbols.len);
+        lazy_seq.decode((self, tcx)).collect()
     }
 
     pub fn wasm_custom_sections(&self) -> Vec<DefId> {
index 39de1ec852ec41cf51f7604714ca4107016b9277..1b208a512e2a46c6a977b5c272aef67f8a7e95a7 100644 (file)
@@ -462,6 +462,7 @@ fn encode_crate_root(&mut self) -> Lazy<CrateRoot> {
         let has_global_allocator = tcx.sess.has_global_allocator.get();
         let root = self.lazy(&CrateRoot {
             name: tcx.crate_name(LOCAL_CRATE),
+            extra_filename: tcx.sess.opts.cg.extra_filename.clone(),
             triple: tcx.sess.opts.target_triple.clone(),
             hash: link_meta.crate_hash,
             disambiguator: tcx.sess.local_crate_disambiguator(),
@@ -1357,6 +1358,7 @@ fn encode_crate_deps(&mut self, _: ()) -> LazySeq<CrateDep> {
                     name: self.tcx.original_crate_name(cnum),
                     hash: self.tcx.crate_hash(cnum),
                     kind: self.tcx.dep_kind(cnum),
+                    extra_filename: self.tcx.extra_filename(cnum),
                 };
                 (cnum, dep)
             })
@@ -1442,13 +1444,12 @@ fn encode_impls(&mut self, _: ()) -> LazySeq<TraitImpls> {
     // definition (as that's not defined in this crate).
     fn encode_exported_symbols(&mut self,
                                exported_symbols: &[(ExportedSymbol, SymbolExportLevel)])
-                               -> LazySeq<(ExportedSymbol, SymbolExportLevel)> {
-
+                               -> EncodedExportedSymbols {
         // The metadata symbol name is special. It should not show up in
         // downstream crates.
         let metadata_symbol_name = SymbolName::new(&metadata_symbol_name(self.tcx));
 
-        self.lazy_seq(exported_symbols
+        let lazy_seq = self.lazy_seq(exported_symbols
             .iter()
             .filter(|&&(ref exported_symbol, _)| {
                 match *exported_symbol {
@@ -1458,7 +1459,12 @@ fn encode_exported_symbols(&mut self,
                     _ => true,
                 }
             })
-            .cloned())
+            .cloned());
+
+        EncodedExportedSymbols {
+            len: lazy_seq.len,
+            position: lazy_seq.position,
+        }
     }
 
     fn encode_wasm_custom_sections(&mut self, statics: &[DefId]) -> LazySeq<DefIndex> {
index 4af5ec9ae08ea0d023e23e1516d9f36b5899644b..f02a34c65a94fe0bc218b921496cbc82b9e67349 100644 (file)
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "https://doc.rust-lang.org/nightly/")]
-#![deny(warnings)]
 
 #![feature(box_patterns)]
-#![cfg_attr(stage0, feature(conservative_impl_trait))]
 #![feature(fs_read_write)]
-#![cfg_attr(stage0, feature(i128_type))]
 #![feature(libc)]
 #![feature(macro_lifetime_matcher)]
 #![feature(proc_macro_internals)]
index 41e10b4755d018f3906a2797e44fb1ef483baff5..f553c55ae56fad5cf5ef9f407c6111c56ee47e77 100644 (file)
 //! 1. Does the filename match an rlib/dylib pattern? That is to say, does the
 //!    filename have the right prefix/suffix?
 //! 2. Does the filename have the right prefix for the crate name being queried?
-//!    This is filtering for files like `libfoo*.rlib` and such.
+//!    This is filtering for files like `libfoo*.rlib` and such. If the crate
+//!    we're looking for was originally compiled with -C extra-filename, the
+//!    extra filename will be included in this prefix to reduce reading
+//!    metadata from crates that would otherwise share our prefix.
 //! 3. Is the file an actual rust library? This is done by loading the metadata
 //!    from the library and making sure it's actually there.
 //! 4. Does the name in the metadata agree with the name of the library?
 use rustc_back::target::{Target, TargetTriple};
 
 use std::cmp;
+use std::collections::HashSet;
 use std::fmt;
 use std::fs;
 use std::io::{self, Read};
@@ -256,6 +260,7 @@ pub struct Context<'a> {
     pub ident: Symbol,
     pub crate_name: Symbol,
     pub hash: Option<&'a Svh>,
+    pub extra_filename: Option<&'a str>,
     // points to either self.sess.target.target or self.sess.host, must match triple
     pub target: &'a Target,
     pub triple: &'a TargetTriple,
@@ -303,7 +308,12 @@ fn paths(&self) -> Vec<PathBuf> {
 
 impl<'a> Context<'a> {
     pub fn maybe_load_library_crate(&mut self) -> Option<Library> {
-        self.find_library_crate()
+        let mut seen_paths = HashSet::new();
+        match self.extra_filename {
+            Some(s) => self.find_library_crate(s, &mut seen_paths)
+                .or_else(|| self.find_library_crate("", &mut seen_paths)),
+            None => self.find_library_crate("", &mut seen_paths)
+        }
     }
 
     pub fn report_errs(&mut self) -> ! {
@@ -419,7 +429,10 @@ pub fn report_errs(&mut self) -> ! {
         unreachable!();
     }
 
-    fn find_library_crate(&mut self) -> Option<Library> {
+    fn find_library_crate(&mut self,
+                          extra_prefix: &str,
+                          seen_paths: &mut HashSet<PathBuf>)
+                          -> Option<Library> {
         // If an SVH is specified, then this is a transitive dependency that
         // must be loaded via -L plus some filtering.
         if self.hash.is_none() {
@@ -434,9 +447,9 @@ fn find_library_crate(&mut self) -> Option<Library> {
         let staticpair = self.staticlibname();
 
         // want: crate_name.dir_part() + prefix + crate_name.file_part + "-"
-        let dylib_prefix = format!("{}{}", dypair.0, self.crate_name);
-        let rlib_prefix = format!("lib{}", self.crate_name);
-        let staticlib_prefix = format!("{}{}", staticpair.0, self.crate_name);
+        let dylib_prefix = format!("{}{}{}", dypair.0, self.crate_name, extra_prefix);
+        let rlib_prefix = format!("lib{}{}", self.crate_name, extra_prefix);
+        let staticlib_prefix = format!("{}{}{}", staticpair.0, self.crate_name, extra_prefix);
 
         let mut candidates = FxHashMap();
         let mut staticlibs = vec![];
@@ -476,6 +489,7 @@ fn find_library_crate(&mut self) -> Option<Library> {
                     }
                     return FileDoesntMatch;
                 };
+
             info!("lib candidate: {}", path.display());
 
             let hash_str = hash.to_string();
@@ -484,6 +498,10 @@ fn find_library_crate(&mut self) -> Option<Library> {
             let (ref mut rlibs, ref mut rmetas, ref mut dylibs) = *slot;
             fs::canonicalize(path)
                 .map(|p| {
+                    if seen_paths.contains(&p) {
+                        return FileDoesntMatch
+                    };
+                    seen_paths.insert(p.clone());
                     match found_kind {
                         CrateFlavor::Rlib => { rlibs.insert(p, kind); }
                         CrateFlavor::Rmeta => { rmetas.insert(p, kind); }
index d04a4001c50230ea7e9a6d74f6a1eef22bd39bcb..e3986bb7d91f94c5bdbde85cef7b828b75cf6d58 100644 (file)
@@ -15,7 +15,6 @@
 use rustc::hir::def::{self, CtorKind};
 use rustc::hir::def_id::{DefIndex, DefId, CrateNum};
 use rustc::ich::StableHashingContext;
-use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
 use rustc::middle::cstore::{DepKind, LinkagePreference, NativeLibrary, ForeignModule};
 use rustc::middle::lang_items;
 use rustc::mir;
@@ -188,6 +187,7 @@ pub enum LazyState {
 pub struct CrateRoot {
     pub name: Symbol,
     pub triple: TargetTriple,
+    pub extra_filename: String,
     pub hash: hir::svh::Svh,
     pub disambiguator: CrateDisambiguator,
     pub panic_strategy: PanicStrategy,
@@ -205,7 +205,7 @@ pub struct CrateRoot {
     pub codemap: LazySeq<syntax_pos::FileMap>,
     pub def_path_table: Lazy<hir::map::definitions::DefPathTable>,
     pub impls: LazySeq<TraitImpls>,
-    pub exported_symbols: LazySeq<(ExportedSymbol, SymbolExportLevel)>,
+    pub exported_symbols: EncodedExportedSymbols,
     pub wasm_custom_sections: LazySeq<DefIndex>,
 
     pub index: LazySeq<index::Index>,
@@ -216,12 +216,14 @@ pub struct CrateDep {
     pub name: ast::Name,
     pub hash: hir::svh::Svh,
     pub kind: DepKind,
+    pub extra_filename: String,
 }
 
 impl_stable_hash_for!(struct CrateDep {
     name,
     hash,
-    kind
+    kind,
+    extra_filename
 });
 
 #[derive(RustcEncodable, RustcDecodable)]
@@ -528,3 +530,9 @@ pub struct GeneratorData<'tcx> {
 // Tags used for encoding Spans:
 pub const TAG_VALID_SPAN: u8 = 0;
 pub const TAG_INVALID_SPAN: u8 = 1;
+
+#[derive(RustcEncodable, RustcDecodable)]
+pub struct EncodedExportedSymbols {
+    pub position: usize,
+    pub len: usize,
+}
index 56371d809b26abbd07b09c02c5d7cba64cf056fd..aaed1dd871bac458bff5698002d6c3dea5e5ed50 100644 (file)
@@ -37,6 +37,23 @@ pub(super) fn report_use_of_moved_or_uninitialized(
             .collect::<Vec<_>>();
 
         if mois.is_empty() {
+            let root_place = self.prefixes(&place, PrefixSet::All)
+                .last()
+                .unwrap();
+
+            if self.moved_error_reported
+                .contains(&root_place.clone())
+            {
+                debug!(
+                    "report_use_of_moved_or_uninitialized place: error about {:?} suppressed",
+                    root_place
+                );
+                return;
+            }
+
+            self.moved_error_reported
+                .insert(root_place.clone());
+
             let item_msg = match self.describe_place(place) {
                 Some(name) => format!("`{}`", name),
                 None => "value".to_owned(),
index 305df37466d02a9aa724f8c722012e199dabb231..62acdf76546248cae0733df9959bd93dfc1bd4c3 100644 (file)
@@ -42,6 +42,7 @@
 use dataflow::move_paths::{IllegalMoveOriginKind, MoveError};
 use dataflow::move_paths::{HasMoveData, LookupResult, MoveData, MovePathIndex};
 use util::borrowck_errors::{BorrowckErrors, Origin};
+use util::collect_writes::FindAssignments;
 
 use std::iter;
 
@@ -239,6 +240,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
         },
         access_place_error_reported: FxHashSet(),
         reservation_error_reported: FxHashSet(),
+        moved_error_reported: FxHashSet(),
         nonlexical_regioncx: opt_regioncx,
         nonlexical_cause_info: None,
     };
@@ -285,6 +287,9 @@ pub struct MirBorrowckCtxt<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
     /// but it is currently inconvenient to track down the BorrowIndex
     /// at the time we detect and report a reservation error.
     reservation_error_reported: FxHashSet<Place<'tcx>>,
+    /// This field keeps track of errors reported in the checking of moved variables,
+    /// so that we don't report report seemingly duplicate errors.
+    moved_error_reported: FxHashSet<Place<'tcx>>,
     /// Non-lexical region inference context, if NLL is enabled.  This
     /// contains the results from region inference and lets us e.g.
     /// find out which CFG points are contained in each borrow region.
@@ -368,7 +373,7 @@ fn visit_statement_entry(
                             LocalMutationIsAllowed::No,
                             flow_state,
                         );
-                        self.check_if_path_is_moved(
+                        self.check_if_path_or_subpath_is_moved(
                             context,
                             InitializationRequiringAction::Use,
                             (output, span),
@@ -965,7 +970,7 @@ fn mutate_place(
         // Write of P[i] or *P, or WriteAndRead of any P, requires P init'd.
         match mode {
             MutateMode::WriteAndRead => {
-                self.check_if_path_is_moved(
+                self.check_if_path_or_subpath_is_moved(
                     context,
                     InitializationRequiringAction::Update,
                     place_span,
@@ -1025,7 +1030,7 @@ fn consume_rvalue(
                     flow_state,
                 );
 
-                self.check_if_path_is_moved(
+                self.check_if_path_or_subpath_is_moved(
                     context,
                     InitializationRequiringAction::Borrow,
                     (place, span),
@@ -1053,7 +1058,7 @@ fn consume_rvalue(
                     LocalMutationIsAllowed::No,
                     flow_state,
                 );
-                self.check_if_path_is_moved(
+                self.check_if_path_or_subpath_is_moved(
                     context,
                     InitializationRequiringAction::Use,
                     (place, span),
@@ -1100,7 +1105,7 @@ fn consume_operand(
                 );
 
                 // Finally, check if path was already moved.
-                self.check_if_path_is_moved(
+                self.check_if_path_or_subpath_is_moved(
                     context,
                     InitializationRequiringAction::Use,
                     (place, span),
@@ -1118,7 +1123,7 @@ fn consume_operand(
                 );
 
                 // Finally, check if path was already moved.
-                self.check_if_path_is_moved(
+                self.check_if_path_or_subpath_is_moved(
                     context,
                     InitializationRequiringAction::Use,
                     (place, span),
@@ -1269,7 +1274,7 @@ fn check_activations(
                     LocalMutationIsAllowed::No,
                     flow_state,
                 );
-                // We do not need to call `check_if_path_is_moved`
+                // We do not need to call `check_if_path_or_subpath_is_moved`
                 // again, as we already called it when we made the
                 // initial reservation.
             }
@@ -1304,7 +1309,7 @@ fn check_if_reassignment_to_immutable_state(
         }
     }
 
-    fn check_if_path_is_moved(
+    fn check_if_full_path_is_moved(
         &mut self,
         context: Context,
         desired_action: InitializationRequiringAction,
@@ -1322,18 +1327,17 @@ fn check_if_path_is_moved(
         //
         // 1. Move of `a.b.c`, use of `a.b.c`
         // 2. Move of `a.b.c`, use of `a.b.c.d` (without first reinitializing `a.b.c.d`)
-        // 3. Move of `a.b.c`, use of `a` or `a.b`
-        // 4. Uninitialized `(a.b.c: &_)`, use of `*a.b.c`; note that with
+        // 3. Uninitialized `(a.b.c: &_)`, use of `*a.b.c`; note that with
         //    partial initialization support, one might have `a.x`
         //    initialized but not `a.b`.
         //
         // OK scenarios:
         //
-        // 5. Move of `a.b.c`, use of `a.b.d`
-        // 6. Uninitialized `a.x`, initialized `a.b`, use of `a.b`
-        // 7. Copied `(a.b: &_)`, use of `*(a.b).c`; note that `a.b`
+        // 4. Move of `a.b.c`, use of `a.b.d`
+        // 5. Uninitialized `a.x`, initialized `a.b`, use of `a.b`
+        // 6. Copied `(a.b: &_)`, use of `*(a.b).c`; note that `a.b`
         //    must have been initialized for the use to be sound.
-        // 8. Move of `a.b.c` then reinit of `a.b.c.d`, use of `a.b.c.d`
+        // 7. Move of `a.b.c` then reinit of `a.b.c.d`, use of `a.b.c.d`
 
         // The dataflow tracks shallow prefixes distinctly (that is,
         // field-accesses on P distinctly from P itself), in order to
@@ -1352,9 +1356,9 @@ fn check_if_path_is_moved(
         // have a MovePath, that should capture the initialization
         // state for the place scenario.
         //
-        // This code covers scenarios 1, 2, and 4.
+        // This code covers scenarios 1, 2, and 3.
 
-        debug!("check_if_path_is_moved part1 place: {:?}", place);
+        debug!("check_if_full_path_is_moved place: {:?}", place);
         match self.move_path_closest_to(place) {
             Ok(mpi) => {
                 if maybe_uninits.contains(&mpi) {
@@ -1374,9 +1378,41 @@ fn check_if_path_is_moved(
               // ancestors; dataflow recurs on children when parents
               // move (to support partial (re)inits).
               //
-              // (I.e. querying parents breaks scenario 8; but may want
+              // (I.e. querying parents breaks scenario 7; but may want
               // to do such a query based on partial-init feature-gate.)
         }
+    }
+
+    fn check_if_path_or_subpath_is_moved(
+        &mut self,
+        context: Context,
+        desired_action: InitializationRequiringAction,
+        place_span: (&Place<'tcx>, Span),
+        flow_state: &Flows<'cx, 'gcx, 'tcx>,
+    ) {
+        // FIXME: analogous code in check_loans first maps `place` to
+        // its base_path ... but is that what we want here?
+        let place = self.base_path(place_span.0);
+
+        let maybe_uninits = &flow_state.uninits;
+        let curr_move_outs = &flow_state.move_outs;
+
+        // Bad scenarios:
+        //
+        // 1. Move of `a.b.c`, use of `a` or `a.b`
+        //    partial initialization support, one might have `a.x`
+        //    initialized but not `a.b`.
+        // 2. All bad scenarios from `check_if_full_path_is_moved`
+        //
+        // OK scenarios:
+        //
+        // 3. Move of `a.b.c`, use of `a.b.d`
+        // 4. Uninitialized `a.x`, initialized `a.b`, use of `a.b`
+        // 5. Copied `(a.b: &_)`, use of `*(a.b).c`; note that `a.b`
+        //    must have been initialized for the use to be sound.
+        // 6. Move of `a.b.c` then reinit of `a.b.c.d`, use of `a.b.c.d`
+
+        self.check_if_full_path_is_moved(context, desired_action, place_span, flow_state);
 
         // A move of any shallow suffix of `place` also interferes
         // with an attempt to use `place`. This is scenario 3 above.
@@ -1384,8 +1420,10 @@ fn check_if_path_is_moved(
         // (Distinct from handling of scenarios 1+2+4 above because
         // `place` does not interfere with suffixes of its prefixes,
         // e.g. `a.b.c` does not interfere with `a.b.d`)
+        //
+        // This code covers scenario 1.
 
-        debug!("check_if_path_is_moved part2 place: {:?}", place);
+        debug!("check_if_path_or_subpath_is_moved place: {:?}", place);
         if let Some(mpi) = self.move_path_for_place(place) {
             if let Some(child_mpi) = maybe_uninits.has_any_child_of(mpi) {
                 self.report_use_of_moved_or_uninitialized(
@@ -1445,7 +1483,8 @@ fn check_if_assigned_path_is_moved(
         (place, span): (&Place<'tcx>, Span),
         flow_state: &Flows<'cx, 'gcx, 'tcx>,
     ) {
-        // recur down place; dispatch to check_if_path_is_moved when necessary
+        debug!("check_if_assigned_path_is_moved place: {:?}", place);
+        // recur down place; dispatch to external checks when necessary
         let mut place = place;
         loop {
             match *place {
@@ -1456,17 +1495,25 @@ fn check_if_assigned_path_is_moved(
                 Place::Projection(ref proj) => {
                     let Projection { ref base, ref elem } = **proj;
                     match *elem {
-                        ProjectionElem::Deref |
-                        // assigning to *P requires `P` initialized.
                         ProjectionElem::Index(_/*operand*/) |
                         ProjectionElem::ConstantIndex { .. } |
-                        // assigning to P[i] requires `P` initialized.
+                        // assigning to P[i] requires P to be valid.
                         ProjectionElem::Downcast(_/*adt_def*/, _/*variant_idx*/) =>
                         // assigning to (P->variant) is okay if assigning to `P` is okay
                         //
                         // FIXME: is this true even if P is a adt with a dtor?
                         { }
 
+                        // assigning to (*P) requires P to be initialized
+                        ProjectionElem::Deref => {
+                            self.check_if_full_path_is_moved(
+                                context, InitializationRequiringAction::Use,
+                                (base, span), flow_state);
+                            // (base initialized; no need to
+                            // recur further)
+                            break;
+                        }
+
                         ProjectionElem::Subslice { .. } => {
                             panic!("we don't allow assignments to subslices, context: {:?}",
                                    context);
@@ -1484,7 +1531,7 @@ fn check_if_assigned_path_is_moved(
                                     // check_loans.rs first maps
                                     // `base` to its base_path.
 
-                                    self.check_if_path_is_moved(
+                                    self.check_if_path_or_subpath_is_moved(
                                         context, InitializationRequiringAction::Assignment,
                                         (base, span), flow_state);
 
@@ -1504,6 +1551,36 @@ fn check_if_assigned_path_is_moved(
         }
     }
 
+    fn specialized_description(&self, place:&Place<'tcx>) -> Option<String>{
+        if let Some(_name) = self.describe_place(place) {
+            Some(format!("data in a `&` reference"))
+        } else {
+            None
+        }
+    }
+
+    fn get_default_err_msg(&self, place:&Place<'tcx>) -> String{
+        match self.describe_place(place) {
+            Some(name) => format!("immutable item `{}`", name),
+            None => "immutable item".to_owned(),
+        }
+    }
+
+    fn get_secondary_err_msg(&self, place:&Place<'tcx>) -> String{
+        match self.specialized_description(place) {
+            Some(_) => format!("data in a `&` reference"),
+            None => self.get_default_err_msg(place)
+        }
+    }
+
+    fn get_primary_err_msg(&self, place:&Place<'tcx>) -> String{
+        if let Some(name) = self.describe_place(place) {
+            format!("`{}` is a `&` reference, so the data it refers to cannot be written", name)
+        } else {
+            format!("cannot assign through `&`-reference")
+        }
+    }
+
     /// Check the permissions for the given place and read or write kind
     ///
     /// Returns true if an error is reported, false otherwise.
@@ -1530,43 +1607,70 @@ fn check_access_permissions(
                 self.is_mutable(place, is_local_mutation_allowed)
             {
                 error_reported = true;
-
-                let item_msg = match self.describe_place(place) {
-                    Some(name) => format!("immutable item `{}`", name),
-                    None => "immutable item".to_owned(),
-                };
-
+                let item_msg = self.get_default_err_msg(place);
                 let mut err = self.tcx
                     .cannot_borrow_path_as_mutable(span, &item_msg, Origin::Mir);
                 err.span_label(span, "cannot borrow as mutable");
 
                 if place != place_err {
                     if let Some(name) = self.describe_place(place_err) {
-                        err.note(&format!("Value not mutable causing this error: `{}`", name));
+                        err.note(&format!("the value which is causing this path not to be mutable \
+                                           is...: `{}`", name));
                     }
                 }
 
                 err.emit();
             },
             Reservation(WriteKind::Mutate) | Write(WriteKind::Mutate) => {
+
                 if let Err(place_err) = self.is_mutable(place, is_local_mutation_allowed) {
                     error_reported = true;
+                    let mut err_info = None;
+                    match *place_err {
+
+                        Place::Projection(box Projection {
+                        ref base, elem:ProjectionElem::Deref}) => {
+                            match *base {
+                                Place::Local(local) => {
+                                    let locations = self.mir.find_assignments(local);
+                                        if locations.len() > 0 {
+                                            let item_msg = if error_reported {
+                                                self.get_secondary_err_msg(base)
+                                            } else {
+                                                self.get_default_err_msg(place)
+                                            };
+                                            err_info = Some((
+                                                self.mir.source_info(locations[0]).span,
+                                                    "consider changing this to be a \
+                                                    mutable reference: `&mut`", item_msg,
+                                                    self.get_primary_err_msg(base)));
+                                        }
+                                },
+                            _ => {},
+                            }
+                        },
+                        _ => {},
+                    }
 
-                    let item_msg = match self.describe_place(place) {
-                        Some(name) => format!("immutable item `{}`", name),
-                        None => "immutable item".to_owned(),
-                    };
-
-                    let mut err = self.tcx.cannot_assign(span, &item_msg, Origin::Mir);
-                    err.span_label(span, "cannot mutate");
-
-                    if place != place_err {
-                        if let Some(name) = self.describe_place(place_err) {
-                            err.note(&format!("Value not mutable causing this error: `{}`", name));
+                    if let Some((err_help_span, err_help_stmt, item_msg, sec_span)) = err_info {
+                        let mut err = self.tcx.cannot_assign(span, &item_msg, Origin::Mir);
+                        err.span_suggestion(err_help_span, err_help_stmt, format!(""));
+                        if place != place_err {
+                            err.span_label(span, sec_span);
                         }
+                        err.emit()
+                    } else {
+                        let item_msg_ = self.get_default_err_msg(place);
+                        let mut err = self.tcx.cannot_assign(span, &item_msg_, Origin::Mir);
+                        err.span_label(span, "cannot mutate");
+                        if place != place_err {
+                            if let Some(name) = self.describe_place(place_err) {
+                                err.note(&format!("the value which is causing this path not to be \
+                                                   mutable is...: `{}`", name));
+                            }
+                        }
+                        err.emit();
                     }
-
-                    err.emit();
                 }
             }
             Reservation(WriteKind::Move)
@@ -1585,9 +1689,7 @@ fn check_access_permissions(
                     );
                 }
             }
-
             Activation(..) => {} // permission checks are done at Reservation point.
-
             Read(ReadKind::Borrow(BorrowKind::Unique))
             | Read(ReadKind::Borrow(BorrowKind::Mut { .. }))
             | Read(ReadKind::Borrow(BorrowKind::Shared))
@@ -2209,3 +2311,4 @@ fn new(self, loc: Location) -> Context {
         }
     }
 }
+
index 6f5fcc9e421cc115d780356092c1563455c30201..9b0e4c64171ca59a2dc19c41b2e45a001ffe3b51 100644 (file)
@@ -467,8 +467,8 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
                 mutability: Mutability::Not,
             };
             if let Some(hir::map::NodeBinding(pat)) = tcx.hir.find(var_id) {
-                if let hir::PatKind::Binding(_, _, ref ident, _) = pat.node {
-                    decl.debug_name = ident.node;
+                if let hir::PatKind::Binding(_, _, ref name, _) = pat.node {
+                    decl.debug_name = name.node;
 
                     let bm = *hir.tables.pat_binding_modes()
                                         .get(pat.hir_id)
index fb3042014df6af8e6098a4683a31d14f4fb9dc0d..aa991427be09397b615d9ef466536c7b8afdd5a2 100644 (file)
@@ -64,10 +64,7 @@ pub struct Borrows<'a, 'gcx: 'tcx, 'tcx: 'a> {
     assigned_map: FxHashMap<Place<'tcx>, FxHashSet<BorrowIndex>>,
 
     /// Locations which activate borrows.
-    /// NOTE: A given location may activate more than one borrow in the future
-    /// when more general two-phase borrow support is introduced, but for now we
-    /// only need to store one borrow index
-    activation_map: FxHashMap<Location, BorrowIndex>,
+    activation_map: FxHashMap<Location, FxHashSet<BorrowIndex>>,
 
     /// Every borrow has a region; this maps each such regions back to
     /// its borrow-indexes.
@@ -174,7 +171,7 @@ struct GatherBorrows<'a, 'gcx: 'tcx, 'tcx: 'a> {
             idx_vec: IndexVec<BorrowIndex, BorrowData<'tcx>>,
             location_map: FxHashMap<Location, BorrowIndex>,
             assigned_map: FxHashMap<Place<'tcx>, FxHashSet<BorrowIndex>>,
-            activation_map: FxHashMap<Location, BorrowIndex>,
+            activation_map: FxHashMap<Location, FxHashSet<BorrowIndex>>,
             region_map: FxHashMap<Region<'tcx>, FxHashSet<BorrowIndex>>,
             local_map: FxHashMap<mir::Local, FxHashSet<BorrowIndex>>,
             region_span_map: FxHashMap<RegionKind, Span>,
@@ -211,12 +208,7 @@ fn root_local(mut p: &mir::Place<'_>) -> Option<mir::Local> {
                     let idx = self.idx_vec.push(borrow);
                     self.location_map.insert(location, idx);
 
-                    // This assert is a good sanity check until more general 2-phase borrow
-                    // support is introduced. See NOTE on the activation_map field for more
-                    assert!(!self.activation_map.contains_key(&activate_location),
-                            "More than one activation introduced at the same location.");
-                    self.activation_map.insert(activate_location, idx);
-
+                    insert(&mut self.activation_map, &activate_location, idx);
                     insert(&mut self.assigned_map, assigned_place, idx);
                     insert(&mut self.region_map, &region, idx);
                     if let Some(local) = root_local(borrowed_place) {
@@ -552,9 +544,11 @@ fn perform_activations_at_location(&self,
                                        location: Location) {
         // Handle activations
         match self.activation_map.get(&location) {
-            Some(&activated) => {
-                debug!("activating borrow {:?}", activated);
-                sets.gen(&ReserveOrActivateIndex::active(activated))
+            Some(activations) => {
+                for activated in activations {
+                    debug!("activating borrow {:?}", activated);
+                    sets.gen(&ReserveOrActivateIndex::active(*activated))
+                }
             }
             None => {}
         }
index 74e41ef9c93ee31183973870459c0c3a035e252b..454b6cbd27df1e93b20952c3964b32ef8507d02a 100644 (file)
@@ -152,7 +152,7 @@ pub(crate) fn run<P>(self,
                 } else {
                     sess.span_err(
                         item.span,
-                        &format!("{} attribute requires a path", item.name()));
+                        &format!("{} attribute requires a path", item.ident));
                     return None;
                 }
             }
index 798d635318180937696cddae0546b3e8e2ef7461..c3f41e8ac4827f5970fb9e11dfab2c2f7db695ab 100644 (file)
@@ -466,7 +466,7 @@ fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat) -> Pattern<'tcx> {
                 }
             }
 
-            PatKind::Binding(_, id, ref ident, ref sub) => {
+            PatKind::Binding(_, id, ref name, ref sub) => {
                 let var_ty = self.tables.node_id_to_type(pat.hir_id);
                 let region = match var_ty.sty {
                     ty::TyRef(r, _) => Some(r),
@@ -493,14 +493,14 @@ fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat) -> Pattern<'tcx> {
                     if let ty::TyRef(_, mt) = ty.sty {
                         ty = mt.ty;
                     } else {
-                        bug!("`ref {}` has wrong type {}", ident.node, ty);
+                        bug!("`ref {}` has wrong type {}", name.node, ty);
                     }
                 }
 
                 PatternKind::Binding {
                     mutability,
                     mode,
-                    name: ident.node,
+                    name: name.node,
                     var: id,
                     ty: var_ty,
                     subpattern: self.lower_opt_pattern(sub),
index cf3241fe9be662d6938e7d551020cbee98db5a4d..3220d4d96b36bd1ed7db3a01745156842101d14f 100644 (file)
@@ -893,7 +893,7 @@ pub fn read_discriminant_value(
     }
 
 
-    pub(crate) fn write_discriminant_value(
+    pub fn write_discriminant_value(
         &mut self,
         dest_ty: Ty<'tcx>,
         dest: Place,
index 84baa8c541781f8f21240aa2dd07071f51f51c7c..b1a9d7f295e7a18ae4acf3b3ca2b22c3dfaf33d5 100644 (file)
 
 */
 
-#![deny(warnings)]
-
 #![feature(slice_patterns)]
 #![feature(from_ref)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
 #![feature(catch_expr)]
-#![cfg_attr(stage0, feature(conservative_impl_trait))]
 #![feature(const_fn)]
 #![feature(core_intrinsics)]
 #![feature(decl_macro)]
 #![feature(dyn_trait)]
 #![feature(fs_read_write)]
-#![cfg_attr(stage0, feature(i128_type))]
-#![cfg_attr(stage0, feature(inclusive_range_syntax))]
 #![feature(macro_vis_matcher)]
-#![cfg_attr(stage0, feature(match_default_bindings))]
 #![feature(exhaustive_patterns)]
 #![feature(range_contains)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(nonzero)]
-#![cfg_attr(stage0, feature(underscore_lifetimes))]
-#![cfg_attr(stage0, feature(never_type))]
 #![feature(inclusive_range_fields)]
+#![feature(crate_visibility_modifier)]
 
 extern crate arena;
 #[macro_use]
index 446ef6bd32876b63dce95e1b156cf90a05b5cb54..209f6dbfa485af40d37da07c08f6f34c709fb890 100644 (file)
 
 use rustc_data_structures::bitvec::BitVector;
 
-use std::iter;
-
 #[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)]
 pub enum MonoItemCollectionMode {
     Eager,
@@ -569,7 +567,9 @@ fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'tcx>, location: Location) {
                     ty::TyClosure(def_id, substs) => {
                         let instance = monomorphize::resolve_closure(
                             self.tcx, def_id, substs, ty::ClosureKind::FnOnce);
-                        self.output.push(create_fn_mono_item(instance));
+                        if should_monomorphize_locally(self.tcx, &instance) {
+                            self.output.push(create_fn_mono_item(instance));
+                        }
                     }
                     _ => bug!(),
                 }
@@ -731,14 +731,16 @@ fn should_monomorphize_locally<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance:
         ty::InstanceDef::Intrinsic(_) |
         ty::InstanceDef::CloneShim(..) => return true
     };
-    match tcx.hir.get_if_local(def_id) {
+
+    return match tcx.hir.get_if_local(def_id) {
         Some(hir_map::NodeForeignItem(..)) => {
             false // foreign items are linked against, not translated.
         }
         Some(_) => true,
         None => {
             if tcx.is_reachable_non_generic(def_id) ||
-                tcx.is_foreign_item(def_id)
+                tcx.is_foreign_item(def_id) ||
+                is_available_upstream_generic(tcx, def_id, instance.substs)
             {
                 // We can link to the item in question, no instance needed
                 // in this crate
@@ -750,6 +752,33 @@ fn should_monomorphize_locally<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance:
                 true
             }
         }
+    };
+
+    fn is_available_upstream_generic<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                               def_id: DefId,
+                                               substs: &'tcx Substs<'tcx>)
+                                               -> bool {
+        debug_assert!(!def_id.is_local());
+
+        // If we are not in share generics mode, we don't link to upstream
+        // monomorphizations but always instantiate our own internal versions
+        // instead.
+        if !tcx.share_generics() {
+            return false
+        }
+
+        // If this instance has no type parameters, it cannot be a shared
+        // monomorphization. Non-generic instances are already handled above
+        // by `is_reachable_non_generic()`
+        if substs.types().next().is_none() {
+            return false
+        }
+
+        // Take a look at the available monomorphizations listed in the metadata
+        // of upstream crates.
+        tcx.upstream_monomorphizations_for(def_id)
+           .map(|set| set.contains_key(substs))
+           .unwrap_or(false)
     }
 }
 
@@ -1030,13 +1059,15 @@ fn push_extra_entry_roots(&mut self) {
         // late-bound regions, since late-bound
         // regions must appear in the argument
         // listing.
-        let main_ret_ty = main_ret_ty.no_late_bound_regions().unwrap();
+        let main_ret_ty = self.tcx.erase_regions(
+            &main_ret_ty.no_late_bound_regions().unwrap(),
+        );
 
         let start_instance = Instance::resolve(
             self.tcx,
             ty::ParamEnv::reveal_all(),
             start_def_id,
-            self.tcx.mk_substs(iter::once(Kind::from(main_ret_ty)))
+            self.tcx.intern_substs(&[Kind::from(main_ret_ty)])
         ).unwrap();
 
         self.output.push(create_fn_mono_item(start_instance));
index 3789342b3891dd9b7d0a91b9f12f0f7b61826fb7..da4cb4ec789041d219ce33d3c0084cba30b0a5b0 100644 (file)
@@ -302,6 +302,13 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let is_incremental_build = tcx.sess.opts.incremental.is_some();
     let mut internalization_candidates = FxHashSet();
 
+    // Determine if monomorphizations instantiated in this crate will be made
+    // available to downstream crates. This depends on whether we are in
+    // share-generics mode and whether the current crate can even have
+    // downstream crates.
+    let export_generics = tcx.share_generics() &&
+                          tcx.local_crate_exports_generics();
+
     for trans_item in trans_items {
         match trans_item.instantiation_mode(tcx) {
             InstantiationMode::GloballyShared { .. } => {}
@@ -325,13 +332,27 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                             .or_insert_with(make_codegen_unit);
 
         let mut can_be_internalized = true;
-        let default_visibility = |id: DefId| {
-            if tcx.sess.target.target.options.default_hidden_visibility &&
-                tcx.symbol_export_level(id) != SymbolExportLevel::C
-            {
-                Visibility::Hidden
-            } else {
+        let default_visibility = |id: DefId, is_generic: bool| {
+            if !tcx.sess.target.target.options.default_hidden_visibility {
+                return Visibility::Default
+            }
+
+            // Generic functions never have export level C
+            if is_generic {
+                return Visibility::Hidden
+            }
+
+            // Things with export level C don't get instantiated in downstream
+            // crates
+            if !id.is_local() {
+                return Visibility::Hidden
+            }
+
+            if let Some(&SymbolExportLevel::C) = tcx.reachable_non_generics(id.krate)
+                                                    .get(&id) {
                 Visibility::Default
+            } else {
+                Visibility::Hidden
             }
         };
         let (linkage, mut visibility) = match trans_item.explicit_linkage(tcx) {
@@ -341,6 +362,11 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                     MonoItem::Fn(ref instance) => {
                         let visibility = match instance.def {
                             InstanceDef::Item(def_id) => {
+                                let is_generic = instance.substs
+                                                         .types()
+                                                         .next()
+                                                         .is_some();
+
                                 // The `start_fn` lang item is actually a
                                 // monomorphized instance of a function in the
                                 // standard library, used for the `main`
@@ -363,14 +389,46 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                     can_be_internalized = false;
                                     Visibility::Hidden
                                 } else if def_id.is_local() {
-                                    if tcx.is_reachable_non_generic(def_id) {
+                                    if is_generic {
+                                        if export_generics {
+                                            if tcx.is_unreachable_local_definition(def_id) {
+                                                // This instance cannot be used
+                                                // from another crate.
+                                                Visibility::Hidden
+                                            } else {
+                                                // This instance might be useful in
+                                                // a downstream crate.
+                                                can_be_internalized = false;
+                                                default_visibility(def_id, true)
+                                            }
+                                        } else {
+                                            // We are not exporting generics or
+                                            // the definition is not reachable
+                                            // for downstream crates, we can
+                                            // internalize its instantiations.
+                                            Visibility::Hidden
+                                        }
+                                    } else {
+                                        // This isn't a generic function.
+                                        if tcx.is_reachable_non_generic(def_id) {
+                                            can_be_internalized = false;
+                                            debug_assert!(!is_generic);
+                                            default_visibility(def_id, false)
+                                        } else {
+                                            Visibility::Hidden
+                                        }
+                                    }
+                                } else {
+                                    // This is an upstream DefId.
+                                    if export_generics && is_generic {
+                                        // If it is a upstream monomorphization
+                                        // and we export generics, we must make
+                                        // it available to downstream crates.
                                         can_be_internalized = false;
-                                        default_visibility(def_id)
+                                        default_visibility(def_id, true)
                                     } else {
                                         Visibility::Hidden
                                     }
-                                } else {
-                                    Visibility::Hidden
                                 }
                             }
                             InstanceDef::FnPtrShim(..) |
@@ -387,7 +445,7 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                     MonoItem::Static(def_id) => {
                         let visibility = if tcx.is_reachable_non_generic(def_id) {
                             can_be_internalized = false;
-                            default_visibility(def_id)
+                            default_visibility(def_id, false)
                         } else {
                             Visibility::Hidden
                         };
@@ -397,7 +455,7 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                         let def_id = tcx.hir.local_def_id(node_id);
                         let visibility = if tcx.is_reachable_non_generic(def_id) {
                             can_be_internalized = false;
-                            default_visibility(def_id)
+                            default_visibility(def_id, false)
                         } else {
                             Visibility::Hidden
                         };
index 5e15348de5e718a76632bf2e11c1daeceb341e4b..d6b3e674f8f804878c727db063d25736b3f47ae2 100644 (file)
@@ -284,7 +284,8 @@ fn cannot_reassign_immutable(self, span: Span, desc: &str, is_arg: bool, o: Orig
         self.cancel_if_wrong_origin(err, o)
     }
 
-    fn cannot_assign(self, span: Span, desc: &str, o: Origin) -> DiagnosticBuilder<'cx>
+    fn cannot_assign(self, span: Span, desc: &str, o: Origin)
+                     -> DiagnosticBuilder<'cx>
     {
         let err = struct_span_err!(self, span, E0594,
                                   "cannot assign to {}{OGN}",
diff --git a/src/librustc_mir/util/collect_writes.rs b/src/librustc_mir/util/collect_writes.rs
new file mode 100644 (file)
index 0000000..f04f923
--- /dev/null
@@ -0,0 +1,67 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use rustc::mir::{Local, Location};
+use rustc::mir::Mir;
+use rustc::mir::visit::PlaceContext;
+use rustc::mir::visit::Visitor;
+
+crate trait FindAssignments {
+    // Finds all statements that assign directly to local (i.e., X = ...)
+    // and returns their locations.
+    fn find_assignments(&self, local: Local) -> Vec<Location>;
+}
+
+impl<'tcx> FindAssignments for Mir<'tcx>{
+    fn find_assignments(&self, local: Local) -> Vec<Location>{
+            let mut visitor = FindLocalAssignmentVisitor{ needle: local, locations: vec![]};
+            visitor.visit_mir(self);
+            visitor.locations
+    }
+}
+
+// The Visitor walks the MIR to return the assignment statements corresponding
+// to a Local.
+struct FindLocalAssignmentVisitor {
+    needle: Local,
+    locations: Vec<Location>,
+}
+
+impl<'tcx> Visitor<'tcx> for FindLocalAssignmentVisitor {
+    fn visit_local(&mut self,
+                   local: &Local,
+                   place_context: PlaceContext<'tcx>,
+                   location: Location) {
+        if self.needle != *local {
+            return;
+        }
+
+        match place_context {
+            PlaceContext::Store | PlaceContext::Call => {
+                self.locations.push(location);
+            }
+            PlaceContext::AsmOutput |
+            PlaceContext::Drop |
+            PlaceContext::Inspect |
+            PlaceContext::Borrow { .. } |
+            PlaceContext::Projection(..) |
+            PlaceContext::Copy |
+            PlaceContext::Move |
+            PlaceContext::StorageLive |
+            PlaceContext::StorageDead |
+            PlaceContext::Validate => {
+                // TO-DO
+                // self.super_local(local)
+            }
+        }
+    }
+    // TO-DO
+    // fn super_local()
+}
index eebe5a86018ea6ebb2a8eab45e6441ed48134d8a..19cd376688627de9d3fe4e79272f57b3656700e0 100644 (file)
@@ -17,6 +17,7 @@
 mod graphviz;
 pub(crate) mod pretty;
 pub mod liveness;
+pub mod collect_writes;
 
 pub use self::alignment::is_disaligned;
 pub use self::pretty::{dump_enabled, dump_mir, write_mir_pretty, PassWhere};
index 8d7279b29eb552db3ac95907a5926334d7044e97..17ec2b96438ad02b97746e66de4a6d5a9c7021ad 100644 (file)
@@ -17,3 +17,4 @@ cmake = "0.1.18"
 alloc = { path = "../liballoc" }
 alloc_system = { path = "../liballoc_system" }
 core = { path = "../libcore" }
+compiler_builtins = { path = "../rustc/compiler_builtins_shim" }
index 37274d1fc4479f538185c0288acdcc22229e5004..1866122454c7057cab50c8511a3a1d2775512a0a 100644 (file)
@@ -36,19 +36,20 @@ fn err_handler(&self) -> &errors::Handler {
         &self.session.parse_sess.span_diagnostic
     }
 
-    fn check_lifetime(&self, lifetime: &Lifetime) {
+    fn check_lifetime(&self, ident: Ident) {
         let valid_names = [keywords::UnderscoreLifetime.name(),
                            keywords::StaticLifetime.name(),
                            keywords::Invalid.name()];
-        if !valid_names.contains(&lifetime.ident.name) &&
-            token::is_reserved_ident(lifetime.ident.without_first_quote()) {
-            self.err_handler().span_err(lifetime.span, "lifetimes cannot use keyword names");
+        if !valid_names.contains(&ident.name) &&
+            token::is_reserved_ident(ident.without_first_quote()) {
+            self.err_handler().span_err(ident.span, "lifetimes cannot use keyword names");
         }
     }
 
-    fn check_label(&self, label: Ident, span: Span) {
-        if token::is_reserved_ident(label.without_first_quote()) {
-            self.err_handler().span_err(span, &format!("invalid label name `{}`", label.name));
+    fn check_label(&self, ident: Ident) {
+        if token::is_reserved_ident(ident.without_first_quote()) {
+            self.err_handler()
+                .span_err(ident.span, &format!("invalid label name `{}`", ident.name));
         }
     }
 
@@ -144,7 +145,7 @@ fn check_late_bound_lifetime_defs(&self, params: &Vec<GenericParam>) {
         let non_lifetime_param_spans : Vec<_> = params.iter()
             .filter_map(|param| match *param {
                 GenericParam::Lifetime(_) => None,
-                GenericParam::Type(ref t) => Some(t.span),
+                GenericParam::Type(ref t) => Some(t.ident.span),
             }).collect();
         if !non_lifetime_param_spans.is_empty() {
             self.err_handler().span_err(non_lifetime_param_spans,
@@ -156,7 +157,7 @@ fn check_late_bound_lifetime_defs(&self, params: &Vec<GenericParam>) {
             match *param {
                 GenericParam::Lifetime(ref l) => {
                     if !l.bounds.is_empty() {
-                        let spans : Vec<_> = l.bounds.iter().map(|b| b.span).collect();
+                        let spans: Vec<_> = l.bounds.iter().map(|b| b.ident.span).collect();
                         self.err_handler().span_err(spans,
                             "lifetime bounds cannot be used in this context");
                     }
@@ -193,7 +194,7 @@ fn visit_ty(&mut self, ty: &'a Ty) {
                 for bound in bounds {
                     if let RegionTyParamBound(ref lifetime) = *bound {
                         if any_lifetime_bounds {
-                            span_err!(self.session, lifetime.span, E0226,
+                            span_err!(self.session, lifetime.ident.span, E0226,
                                       "only a single explicit lifetime bound is permitted");
                             break;
                         }
@@ -234,12 +235,12 @@ fn visit_use_tree(&mut self, use_tree: &'a UseTree, id: NodeId, _nested: bool) {
     }
 
     fn visit_label(&mut self, label: &'a Label) {
-        self.check_label(label.ident, label.span);
+        self.check_label(label.ident);
         visit::walk_label(self, label);
     }
 
     fn visit_lifetime(&mut self, lifetime: &'a Lifetime) {
-        self.check_lifetime(lifetime);
+        self.check_lifetime(lifetime.ident);
         visit::walk_lifetime(self, lifetime);
     }
 
@@ -328,19 +329,19 @@ fn visit_item(&mut self, item: &'a Item) {
             ItemKind::TraitAlias(Generics { ref params, .. }, ..) => {
                 for param in params {
                     if let GenericParam::Type(TyParam {
+                        ident,
                         ref bounds,
                         ref default,
-                        span,
                         ..
                     }) = *param
                     {
                         if !bounds.is_empty() {
-                            self.err_handler().span_err(span,
+                            self.err_handler().span_err(ident.span,
                                                         "type parameters on the left side of a \
                                                          trait alias cannot be bounded");
                         }
                         if !default.is_none() {
-                            self.err_handler().span_err(span,
+                            self.err_handler().span_err(ident.span,
                                                         "type parameters on the left side of a \
                                                          trait alias cannot have defaults");
                         }
@@ -381,7 +382,7 @@ fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
                         .span_label(span, "pattern not allowed in foreign function").emit();
                 });
             }
-            ForeignItemKind::Static(..) | ForeignItemKind::Ty => {}
+            ForeignItemKind::Static(..) | ForeignItemKind::Ty | ForeignItemKind::Macro(..) => {}
         }
 
         visit::walk_foreign_item(self, fi)
@@ -408,7 +409,7 @@ fn visit_generics(&mut self, g: &'a Generics) {
             match (param, seen_non_lifetime_param) {
                 (&GenericParam::Lifetime(ref ld), true) => {
                     self.err_handler()
-                        .span_err(ld.lifetime.span, "lifetime parameters must be leading");
+                        .span_err(ld.lifetime.ident.span, "lifetime parameters must be leading");
                 },
                 (&GenericParam::Lifetime(_), false) => {}
                 _ => {
@@ -417,7 +418,7 @@ fn visit_generics(&mut self, g: &'a Generics) {
             }
 
             if let GenericParam::Type(ref ty_param @ TyParam { default: Some(_), .. }) = *param {
-                seen_default = Some(ty_param.span);
+                seen_default = Some(ty_param.ident.span);
             } else if let Some(span) = seen_default {
                 self.err_handler()
                     .span_err(span, "type parameters with a default must be trailing");
@@ -460,6 +461,14 @@ fn visit_poly_trait_ref(&mut self, t: &'a PolyTraitRef, m: &'a TraitBoundModifie
         self.check_late_bound_lifetime_defs(&t.bound_generic_params);
         visit::walk_poly_trait_ref(self, t, m);
     }
+
+    fn visit_mac(&mut self, mac: &Spanned<Mac_>) {
+        // when a new macro kind is added but the author forgets to set it up for expansion
+        // because that's the only part that won't cause a compiler error
+        self.session.diagnostic()
+            .span_bug(mac.span, "macro invocation missed in expansion; did you forget to override \
+                                 the relevant `fold_*()` method in `PlaceholderExpander`?");
+    }
 }
 
 // Bans nested `impl Trait`, e.g. `impl Into<impl Debug>`.
@@ -522,6 +531,10 @@ fn visit_path_parameters(&mut self, _: Span, path_parameters: &'a PathParameters
             }
         }
     }
+
+    fn visit_mac(&mut self, _mac: &Spanned<Mac_>) {
+        // covered in AstValidator
+    }
 }
 
 // Bans `impl Trait` in path projections like `<impl Iterator>::Item` or `Foo::Bar<impl Trait>`.
@@ -583,6 +596,10 @@ fn visit_ty(&mut self, t: &'a Ty) {
             _ => visit::walk_ty(self, t),
         }
     }
+
+    fn visit_mac(&mut self, _mac: &Spanned<Mac_>) {
+        // covered in AstValidator
+    }
 }
 
 pub fn check_crate(session: &Session, krate: &Crate) {
index 1f6cc1f71fc0876c8e198b2bb8ff6327e33ec7af..e65c9de8df1eaf1dbf3277cde693fcf5e5ca79ee 100644 (file)
@@ -17,7 +17,6 @@
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "https://doc.rust-lang.org/nightly/")]
-#![deny(warnings)]
 
 #![feature(rustc_diagnostic_macros)]
 
index 4cc65ee28e89f703d3ebd261907471b7e0e1fe00..b57debdd99486bda802323fe72cbc624d136d530 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![deny(warnings)]
 #![allow(bad_style)]
 
 pub struct Intrinsic {
index c0f830f1fbe2ec2d846f95c2bd30f8e4554e42de..622d8e51a6ca3a2cbcdfb2a960600d16ae66a934 100644 (file)
@@ -63,7 +63,6 @@
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "https://doc.rust-lang.org/nightly/")]
-#![deny(warnings)]
 
 #![feature(rustc_diagnostic_macros)]
 #![feature(staged_api)]
index 95be691b30c791f640b8dc12b926122a8b600388..ef710ff7a7e4b6447775f404c25a39ac7040900d 100644 (file)
@@ -11,7 +11,6 @@
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "https://doc.rust-lang.org/nightly/")]
-#![deny(warnings)]
 
 #![feature(rustc_diagnostic_macros)]
 
@@ -35,7 +34,6 @@
 use syntax::ast::{self, CRATE_NODE_ID, Ident};
 use syntax::symbol::keywords;
 use syntax_pos::Span;
-use syntax_pos::hygiene::SyntaxContext;
 
 use std::cmp;
 use std::mem::replace;
@@ -495,11 +493,11 @@ struct NamePrivacyVisitor<'a, 'tcx: 'a> {
 impl<'a, 'tcx> NamePrivacyVisitor<'a, 'tcx> {
     // Checks that a field in a struct constructor (expression or pattern) is accessible.
     fn check_field(&mut self,
-                   use_ctxt: SyntaxContext, // Syntax context of the field name at the use site
+                   use_ctxt: Span, // Syntax context of the field name at the use site
                    span: Span, // Span of the field pattern, e.g. `x: 0`
                    def: &'tcx ty::AdtDef, // Definition of the struct or enum
                    field: &'tcx ty::FieldDef) { // Definition of the field
-        let ident = Ident { ctxt: use_ctxt.modern(), ..keywords::Invalid.ident() };
+        let ident = Ident::new(keywords::Invalid.name(), use_ctxt.modern());
         let def_id = self.tcx.adjust_ident(ident, def.did, self.current_item).1;
         if !def.is_enum() && !field.vis.is_accessible_from(def_id, self.tcx) {
             struct_span_err!(self.tcx.sess, span, E0451, "field `{}` of {} `{}` is private",
@@ -573,14 +571,14 @@ fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
                     for variant_field in &variant.fields {
                         let field = fields.iter().find(|f| f.name.node == variant_field.name);
                         let (use_ctxt, span) = match field {
-                            Some(field) => (field.name.node.to_ident().ctxt, field.span),
-                            None => (base.span.ctxt(), base.span),
+                            Some(field) => (field.name.node.to_ident().span, field.span),
+                            None => (base.span, base.span),
                         };
                         self.check_field(use_ctxt, span, adt, variant_field);
                     }
                 } else {
                     for field in fields {
-                        let use_ctxt = field.name.node.to_ident().ctxt;
+                        let use_ctxt = field.name.node.to_ident().span;
                         let field_def = variant.field_named(field.name.node);
                         self.check_field(use_ctxt, field.span, adt, field_def);
                     }
@@ -599,7 +597,7 @@ fn visit_pat(&mut self, pat: &'tcx hir::Pat) {
                 let adt = self.tables.pat_ty(pat).ty_adt_def().unwrap();
                 let variant = adt.variant_of_def(def);
                 for field in fields {
-                    let use_ctxt = field.node.name.to_ident().ctxt;
+                    let use_ctxt = field.node.name.to_ident().span;
                     let field_def = variant.field_named(field.node.name);
                     self.check_field(use_ctxt, field.span, adt, field_def);
                 }
index c192f349c2019723f6eb2bba0679db27a4c43220..0542ca6fb24c271c18fa282b459e5a0e6af78140 100644 (file)
@@ -34,7 +34,6 @@
 
 use syntax::ast::{self, Block, ForeignItem, ForeignItemKind, Item, ItemKind, NodeId};
 use syntax::ast::{Mutability, StmtKind, TraitItem, TraitItemKind, Variant};
-use syntax::codemap::respan;
 use syntax::ext::base::SyntaxExtension;
 use syntax::ext::base::Determinacy::Undetermined;
 use syntax::ext::hygiene::Mark;
@@ -115,13 +114,13 @@ fn build_reduced_graph_for_use_tree(&mut self,
 
         let mut module_path: Vec<_> = prefix.segments.iter()
             .chain(path.segments.iter())
-            .map(|seg| respan(seg.span, seg.identifier))
+            .map(|seg| seg.ident)
             .collect();
 
         match use_tree.kind {
             ast::UseTreeKind::Simple(rename) => {
                 let mut ident = use_tree.ident();
-                let mut source = module_path.pop().unwrap().node;
+                let mut source = module_path.pop().unwrap();
                 let mut type_ns_only = false;
 
                 if nested {
@@ -130,7 +129,7 @@ fn build_reduced_graph_for_use_tree(&mut self,
                         type_ns_only = true;
 
                         let last_segment = *module_path.last().unwrap();
-                        if last_segment.node.name == keywords::CrateRoot.name() {
+                        if last_segment.name == keywords::CrateRoot.name() {
                             resolve_error(
                                 self,
                                 use_tree.span,
@@ -142,9 +141,9 @@ fn build_reduced_graph_for_use_tree(&mut self,
 
                         // Replace `use foo::self;` with `use foo;`
                         let _ = module_path.pop();
-                        source = last_segment.node;
+                        source = last_segment;
                         if rename.is_none() {
-                            ident = last_segment.node;
+                            ident = last_segment;
                         }
                     }
                 } else {
@@ -157,7 +156,7 @@ fn build_reduced_graph_for_use_tree(&mut self,
 
                     // Disallow `use $crate;`
                     if source.name == keywords::DollarCrate.name() && path.segments.len() == 1 {
-                        let crate_root = self.resolve_crate_root(source.ctxt, true);
+                        let crate_root = self.resolve_crate_root(source.span.ctxt(), true);
                         let crate_name = match crate_root.kind {
                             ModuleKind::Def(_, name) => name,
                             ModuleKind::Block(..) => unreachable!(),
@@ -195,12 +194,8 @@ fn build_reduced_graph_for_use_tree(&mut self,
             }
             ast::UseTreeKind::Nested(ref items) => {
                 let prefix = ast::Path {
-                    segments: module_path.iter()
-                        .map(|s| ast::PathSegment {
-                            identifier: s.node,
-                            span: s.span,
-                            parameters: None,
-                        })
+                    segments: module_path.into_iter()
+                        .map(|ident| ast::PathSegment::from_ident(ident))
                         .collect(),
                     span: path.span,
                 };
@@ -428,7 +423,7 @@ fn build_reduced_graph_for_variant(&mut self,
                                        parent: Module<'a>,
                                        vis: ty::Visibility,
                                        expansion: Mark) {
-        let ident = variant.node.name;
+        let ident = variant.node.ident;
         let def_id = self.definitions.local_def_id(variant.node.data.id());
 
         // Define a name in the type namespace.
@@ -456,6 +451,7 @@ fn build_reduced_graph_for_foreign_item(&mut self, item: &ForeignItem, expansion
             ForeignItemKind::Ty => {
                 (Def::TyForeign(self.definitions.local_def_id(item.id)), TypeNS)
             }
+            ForeignItemKind::Macro(_) => unreachable!(),
         };
         let parent = self.current_module;
         let vis = self.resolve_visibility(&item.vis);
@@ -721,7 +717,7 @@ fn legacy_macro_imports(&mut self, attrs: &[ast::Attribute]) -> LegacyMacroImpor
                 match attr.meta_item_list() {
                     Some(names) => for attr in names {
                         if let Some(word) = attr.word() {
-                            imports.imports.push((word.name(), attr.span()));
+                            imports.imports.push((word.ident.name, attr.span()));
                         } else {
                             span_err!(self.session, attr.span(), E0466, "bad macro import");
                         }
@@ -735,7 +731,7 @@ fn legacy_macro_imports(&mut self, attrs: &[ast::Attribute]) -> LegacyMacroImpor
                 if let Some(names) = attr.meta_item_list() {
                     for attr in names {
                         if let Some(word) = attr.word() {
-                            imports.reexports.push((word.name(), attr.span()));
+                            imports.reexports.push((word.ident.name, attr.span()));
                         } else {
                             bad_macro_reexport(self, attr.span());
                         }
@@ -816,6 +812,11 @@ fn visit_stmt(&mut self, stmt: &'a ast::Stmt) {
     }
 
     fn visit_foreign_item(&mut self, foreign_item: &'a ForeignItem) {
+        if let ForeignItemKind::Macro(_) = foreign_item.node {
+            self.visit_invoc(foreign_item.id);
+            return;
+        }
+
         self.resolver.build_reduced_graph_for_foreign_item(foreign_item, self.expansion);
         visit::walk_foreign_item(self, foreign_item);
     }
index 97dcf081f8c8d8f85a7626ada6e8260366895a2e..61ff326b2af9662d0168b35b61e987c85219197a 100644 (file)
@@ -11,7 +11,6 @@
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/")]
-#![deny(warnings)]
 
 #![feature(rustc_diagnostic_macros)]
 
@@ -41,9 +40,9 @@
 use rustc::hir::{Freevar, FreevarMap, TraitCandidate, TraitMap, GlobMap};
 use rustc::util::nodemap::{NodeMap, NodeSet, FxHashMap, FxHashSet, DefIdMap};
 
-use syntax::codemap::{dummy_spanned, respan, BytePos, CodeMap};
+use syntax::codemap::{BytePos, CodeMap};
 use syntax::ext::hygiene::{Mark, MarkKind, SyntaxContext};
-use syntax::ast::{self, Name, NodeId, Ident, SpannedIdent, FloatTy, IntTy, UintTy};
+use syntax::ast::{self, Name, NodeId, Ident, FloatTy, IntTy, UintTy};
 use syntax::ext::base::SyntaxExtension;
 use syntax::ext::base::Determinacy::{self, Determined, Undetermined};
 use syntax::ext::base::MacroKind;
@@ -427,14 +426,14 @@ fn generate_fn_name_span(cm: &CodeMap, span: Span) -> Option<Span> {
 /// a new local type parameter.
 ///
 /// For instance:
-/// ```
+/// ```rust,ignore (pseudo-Rust)
 /// // Given span
 /// fn my_function(param: T)
-///                       ^ Original span
+/// //                    ^ Original span
 ///
 /// // Result
 /// fn my_function(param: T)
-///    ^^^^^^^^^^^ Generated span with snippet `my_function<T>`
+/// // ^^^^^^^^^^^ Generated span with snippet `my_function<T>`
 /// ```
 ///
 /// Attention: The method used is very fragile since it essentially duplicates the work of the
@@ -851,7 +850,7 @@ fn visit_variant(&mut self,
 
         // `visit::walk_variant` without the discriminant expression.
         self.visit_variant_data(&variant.node.data,
-                                variant.node.name,
+                                variant.node.ident,
                                 generics,
                                 item_id,
                                 variant.span);
@@ -863,6 +862,7 @@ fn visit_foreign_item(&mut self, foreign_item: &'tcx ForeignItem) {
             }
             ForeignItemKind::Static(..) => NoTypeParameters,
             ForeignItemKind::Ty => NoTypeParameters,
+            ForeignItemKind::Macro(..) => NoTypeParameters,
         };
         self.with_type_parameter_rib(type_parameters, |this| {
             visit::walk_foreign_item(this, foreign_item);
@@ -1653,8 +1653,8 @@ fn resolve_hir_path_cb<F>(&mut self, path: &mut hir::Path, is_value: bool, error
         {
         let namespace = if is_value { ValueNS } else { TypeNS };
         let hir::Path { ref segments, span, ref mut def } = *path;
-        let path: Vec<SpannedIdent> = segments.iter()
-            .map(|seg| respan(span, Ident::with_empty_ctxt(seg.name)))
+        let path: Vec<Ident> = segments.iter()
+            .map(|seg| Ident::new(seg.name, span))
             .collect();
         match self.resolve_path(&path, Some(namespace), true, span) {
             PathResult::Module(module) => *def = module.def().unwrap(),
@@ -1911,10 +1911,11 @@ fn resolve_ident_in_lexical_scope(&mut self,
                                       path_span: Span)
                                       -> Option<LexicalScopeBinding<'a>> {
         if ns == TypeNS {
-            ident.ctxt = if ident.name == keywords::SelfType.name() {
-                SyntaxContext::empty() // FIXME(jseyfried) improve `Self` hygiene
+            ident.span = if ident.name == keywords::SelfType.name() {
+                // FIXME(jseyfried) improve `Self` hygiene
+                ident.span.with_ctxt(SyntaxContext::empty())
             } else {
-                ident.ctxt.modern()
+                ident.span.modern()
             }
         }
 
@@ -1930,10 +1931,10 @@ fn resolve_ident_in_lexical_scope(&mut self,
 
             module = match self.ribs[ns][i].kind {
                 ModuleRibKind(module) => module,
-                MacroDefinition(def) if def == self.macro_def(ident.ctxt) => {
+                MacroDefinition(def) if def == self.macro_def(ident.span.ctxt()) => {
                     // If an invocation of this macro created `ident`, give up on `ident`
                     // and switch to `ident`'s source from the macro definition.
-                    ident.ctxt.remove_mark();
+                    ident.span.remove_mark();
                     continue
                 }
                 _ => continue,
@@ -1953,9 +1954,9 @@ fn resolve_ident_in_lexical_scope(&mut self,
             }
         }
 
-        ident.ctxt = ident.ctxt.modern();
+        ident.span = ident.span.modern();
         loop {
-            module = unwrap_or!(self.hygienic_lexical_parent(module, &mut ident.ctxt), break);
+            module = unwrap_or!(self.hygienic_lexical_parent(module, &mut ident.span), break);
             let orig_current_module = self.current_module;
             self.current_module = module; // Lexical resolutions can never be a privacy error.
             let result = self.resolve_ident_in_module_unadjusted(
@@ -1979,10 +1980,10 @@ fn resolve_ident_in_lexical_scope(&mut self,
         }
     }
 
-    fn hygienic_lexical_parent(&mut self, mut module: Module<'a>, ctxt: &mut SyntaxContext)
+    fn hygienic_lexical_parent(&mut self, mut module: Module<'a>, span: &mut Span)
                                -> Option<Module<'a>> {
-        if !module.expansion.is_descendant_of(ctxt.outer()) {
-            return Some(self.macro_def_scope(ctxt.remove_mark()));
+        if !module.expansion.is_descendant_of(span.ctxt().outer()) {
+            return Some(self.macro_def_scope(span.remove_mark()));
         }
 
         if let ModuleKind::Block(..) = module.kind {
@@ -1994,7 +1995,7 @@ fn hygienic_lexical_parent(&mut self, mut module: Module<'a>, ctxt: &mut SyntaxC
             let parent_expansion = parent.expansion.modern();
             if module_expansion.is_descendant_of(parent_expansion) &&
                parent_expansion != module_expansion {
-                return if parent_expansion.is_descendant_of(ctxt.outer()) {
+                return if parent_expansion.is_descendant_of(span.ctxt().outer()) {
                     Some(parent)
                 } else {
                     None
@@ -2015,9 +2016,9 @@ fn resolve_ident_in_module(&mut self,
                                record_used: bool,
                                span: Span)
                                -> Result<&'a NameBinding<'a>, Determinacy> {
-        ident.ctxt = ident.ctxt.modern();
+        ident.span = ident.span.modern();
         let orig_current_module = self.current_module;
-        if let Some(def) = ident.ctxt.adjust(module.expansion) {
+        if let Some(def) = ident.span.adjust(module.expansion) {
             self.current_module = self.macro_def_scope(def);
         }
         let result = self.resolve_ident_in_module_unadjusted(
@@ -2107,8 +2108,8 @@ fn search_label<P, R>(&self, mut ident: Ident, pred: P) -> Option<R>
                 // If an invocation of this macro created `ident`, give up on `ident`
                 // and switch to `ident`'s source from the macro definition.
                 MacroDefinition(def) => {
-                    if def == self.macro_def(ident.ctxt) {
-                        ident.ctxt.remove_mark();
+                    if def == self.macro_def(ident.span.ctxt()) {
+                        ident.span.remove_mark();
                     }
                 }
                 _ => {
@@ -2279,9 +2280,9 @@ fn with_type_parameter_rib<'b, F>(&'b mut self, type_parameters: TypeParameters<
                                 ident.name,
                                 span,
                             );
-                            resolve_error(self, type_parameter.span, err);
+                            resolve_error(self, type_parameter.ident.span, err);
                         }
-                        seen_bindings.entry(ident).or_insert(type_parameter.span);
+                        seen_bindings.entry(ident).or_insert(type_parameter.ident.span);
 
                         // plain insert (no renaming)
                         let def_id = self.definitions.local_def_id(type_parameter.id);
@@ -2349,7 +2350,7 @@ fn with_optional_trait_ref<T, F>(&mut self, opt_trait_ref: Option<&TraitRef>, f:
         let mut new_id = None;
         if let Some(trait_ref) = opt_trait_ref {
             let path: Vec<_> = trait_ref.path.segments.iter()
-                .map(|seg| respan(seg.span, seg.identifier))
+                .map(|seg| seg.ident)
                 .collect();
             let def = self.smart_resolve_path_fragment(
                 trait_ref.ref_id,
@@ -2498,7 +2499,7 @@ fn binding_mode_map(&mut self, pat: &Pat) -> BindingMap {
                     _ => false,
                 } {
                     let binding_info = BindingInfo { span: ident.span, binding_mode: binding_mode };
-                    binding_map.insert(ident.node, binding_info);
+                    binding_map.insert(ident, binding_info);
                 }
             }
             true
@@ -2638,7 +2639,7 @@ fn resolve_block(&mut self, block: &Block) {
     }
 
     fn fresh_binding(&mut self,
-                     ident: &SpannedIdent,
+                     ident: Ident,
                      pat_id: NodeId,
                      outer_pat_id: NodeId,
                      pat_src: PatternSource,
@@ -2650,14 +2651,14 @@ fn fresh_binding(&mut self,
         // because that breaks the assumptions later
         // passes make about or-patterns.)
         let mut def = Def::Local(pat_id);
-        match bindings.get(&ident.node).cloned() {
+        match bindings.get(&ident).cloned() {
             Some(id) if id == outer_pat_id => {
                 // `Variant(a, a)`, error
                 resolve_error(
                     self,
                     ident.span,
                     ResolutionError::IdentifierBoundMoreThanOnceInSamePattern(
-                        &ident.node.name.as_str())
+                        &ident.name.as_str())
                 );
             }
             Some(..) if pat_src == PatternSource::FnParam => {
@@ -2666,7 +2667,7 @@ fn fresh_binding(&mut self,
                     self,
                     ident.span,
                     ResolutionError::IdentifierBoundMoreThanOnceInParameterList(
-                        &ident.node.name.as_str())
+                        &ident.name.as_str())
                 );
             }
             Some(..) if pat_src == PatternSource::Match ||
@@ -2674,7 +2675,7 @@ fn fresh_binding(&mut self,
                         pat_src == PatternSource::WhileLet => {
                 // `Variant1(a) | Variant2(a)`, ok
                 // Reuse definition from the first `a`.
-                def = self.ribs[ValueNS].last_mut().unwrap().bindings[&ident.node];
+                def = self.ribs[ValueNS].last_mut().unwrap().bindings[&ident];
             }
             Some(..) => {
                 span_bug!(ident.span, "two bindings with the same name from \
@@ -2682,9 +2683,9 @@ fn fresh_binding(&mut self,
             }
             None => {
                 // A completely fresh binding, add to the lists if it's valid.
-                if ident.node.name != keywords::Invalid.name() {
-                    bindings.insert(ident.node, outer_pat_id);
-                    self.ribs[ValueNS].last_mut().unwrap().bindings.insert(ident.node, def);
+                if ident.name != keywords::Invalid.name() {
+                    bindings.insert(ident, outer_pat_id);
+                    self.ribs[ValueNS].last_mut().unwrap().bindings.insert(ident, def);
                 }
             }
         }
@@ -2702,10 +2703,10 @@ fn resolve_pattern(&mut self,
         let outer_pat_id = pat.id;
         pat.walk(&mut |pat| {
             match pat.node {
-                PatKind::Ident(bmode, ref ident, ref opt_pat) => {
+                PatKind::Ident(bmode, ident, ref opt_pat) => {
                     // First try to resolve the identifier as some existing
                     // entity, then fall back to a fresh binding.
-                    let binding = self.resolve_ident_in_lexical_scope(ident.node, ValueNS,
+                    let binding = self.resolve_ident_in_lexical_scope(ident, ValueNS,
                                                                       false, pat.span)
                                       .and_then(LexicalScopeBinding::item);
                     let resolution = binding.map(NameBinding::def).and_then(|def| {
@@ -2717,7 +2718,7 @@ fn resolve_pattern(&mut self,
                             Def::Const(..) if is_syntactic_ambiguity => {
                                 // Disambiguate in favor of a unit struct/variant
                                 // or constant pattern.
-                                self.record_use(ident.node, ValueNS, binding.unwrap(), ident.span);
+                                self.record_use(ident, ValueNS, binding.unwrap(), ident.span);
                                 Some(PathResolution::new(def))
                             }
                             Def::StructCtor(..) | Def::VariantCtor(..) |
@@ -2731,7 +2732,7 @@ fn resolve_pattern(&mut self,
                                     self,
                                     ident.span,
                                     ResolutionError::BindingShadowsSomethingUnacceptable(
-                                        pat_src.descr(), ident.node.name, binding.unwrap())
+                                        pat_src.descr(), ident.name, binding.unwrap())
                                 );
                                 None
                             }
@@ -2784,7 +2785,7 @@ fn smart_resolve_path(&mut self,
                           source: PathSource)
                           -> PathResolution {
         let segments = &path.segments.iter()
-            .map(|seg| respan(seg.span, seg.identifier))
+            .map(|seg| seg.ident)
             .collect::<Vec<_>>();
         self.smart_resolve_path_fragment(id, qself, segments, path.span, source)
     }
@@ -2792,7 +2793,7 @@ fn smart_resolve_path(&mut self,
     fn smart_resolve_path_fragment(&mut self,
                                    id: NodeId,
                                    qself: Option<&QSelf>,
-                                   path: &[SpannedIdent],
+                                   path: &[Ident],
                                    span: Span,
                                    source: PathSource)
                                    -> PathResolution {
@@ -2812,11 +2813,11 @@ fn smart_resolve_path_fragment(&mut self,
                  format!("not a {}", expected),
                  span)
             } else {
-                let item_str = path[path.len() - 1].node;
+                let item_str = path[path.len() - 1];
                 let item_span = path[path.len() - 1].span;
                 let (mod_prefix, mod_str) = if path.len() == 1 {
                     (format!(""), format!("this scope"))
-                } else if path.len() == 2 && path[0].node.name == keywords::CrateRoot.name() {
+                } else if path.len() == 2 && path[0].name == keywords::CrateRoot.name() {
                     (format!(""), format!("the crate root"))
                 } else {
                     let mod_path = &path[..path.len() - 1];
@@ -2850,10 +2851,10 @@ fn smart_resolve_path_fragment(&mut self,
 
             // Try to lookup the name in more relaxed fashion for better error reporting.
             let ident = *path.last().unwrap();
-            let candidates = this.lookup_import_candidates(ident.node.name, ns, is_expected);
+            let candidates = this.lookup_import_candidates(ident.name, ns, is_expected);
             if candidates.is_empty() && is_expected(Def::Enum(DefId::local(CRATE_DEF_INDEX))) {
                 let enum_candidates =
-                    this.lookup_import_candidates(ident.node.name, ns, is_enum_variant);
+                    this.lookup_import_candidates(ident.name, ns, is_enum_variant);
                 let mut enum_candidates = enum_candidates.iter()
                     .map(|suggestion| import_candidate_to_paths(&suggestion)).collect::<Vec<_>>();
                 enum_candidates.sort();
@@ -2871,8 +2872,8 @@ fn smart_resolve_path_fragment(&mut self,
                 }
             }
             if path.len() == 1 && this.self_type_is_available(span) {
-                if let Some(candidate) = this.lookup_assoc_candidate(ident.node, ns, is_expected) {
-                    let self_is_available = this.self_value_is_available(path[0].node.ctxt, span);
+                if let Some(candidate) = this.lookup_assoc_candidate(ident, ns, is_expected) {
+                    let self_is_available = this.self_value_is_available(path[0].span, span);
                     match candidate {
                         AssocSuggestion::Field => {
                             err.span_suggestion(span, "try",
@@ -2917,12 +2918,12 @@ fn smart_resolve_path_fragment(&mut self,
                     (Def::Mod(..), PathSource::Expr(Some(parent))) => match parent.node {
                         ExprKind::Field(_, ident) => {
                             err.span_label(parent.span, format!("did you mean `{}::{}`?",
-                                                                 path_str, ident.node));
+                                                                 path_str, ident));
                             return (err, candidates);
                         }
                         ExprKind::MethodCall(ref segment, ..) => {
                             err.span_label(parent.span, format!("did you mean `{}::{}(...)`?",
-                                                                 path_str, segment.identifier));
+                                                                 path_str, segment.ident));
                             return (err, candidates);
                         }
                         _ => {}
@@ -3026,7 +3027,7 @@ fn smart_resolve_path_fragment(&mut self,
                 // or `<T>::A::B`. If `B` should be resolved in value namespace then
                 // it needs to be added to the trait map.
                 if ns == ValueNS {
-                    let item_name = path.last().unwrap().node;
+                    let item_name = *path.last().unwrap();
                     let traits = self.get_traits_containing_item(item_name, ns);
                     self.trait_map.insert(id, traits);
                 }
@@ -3083,9 +3084,9 @@ fn self_type_is_available(&mut self, span: Span) -> bool {
         if let Some(LexicalScopeBinding::Def(def)) = binding { def != Def::Err } else { false }
     }
 
-    fn self_value_is_available(&mut self, ctxt: SyntaxContext, span: Span) -> bool {
-        let ident = Ident { name: keywords::SelfValue.name(), ctxt: ctxt };
-        let binding = self.resolve_ident_in_lexical_scope(ident, ValueNS, false, span);
+    fn self_value_is_available(&mut self, self_span: Span, path_span: Span) -> bool {
+        let ident = Ident::new(keywords::SelfValue.name(), self_span);
+        let binding = self.resolve_ident_in_lexical_scope(ident, ValueNS, false, path_span);
         if let Some(LexicalScopeBinding::Def(def)) = binding { def != Def::Err } else { false }
     }
 
@@ -3093,7 +3094,7 @@ fn self_value_is_available(&mut self, ctxt: SyntaxContext, span: Span) -> bool {
     fn resolve_qpath_anywhere(&mut self,
                               id: NodeId,
                               qself: Option<&QSelf>,
-                              path: &[SpannedIdent],
+                              path: &[Ident],
                               primary_ns: Namespace,
                               span: Span,
                               defer_to_typeck: bool,
@@ -3113,10 +3114,10 @@ fn resolve_qpath_anywhere(&mut self,
                 };
             }
         }
-        let is_global = self.global_macros.get(&path[0].node.name).cloned()
+        let is_global = self.global_macros.get(&path[0].name).cloned()
             .map(|binding| binding.get_macro(self).kind() == MacroKind::Bang).unwrap_or(false);
         if primary_ns != MacroNS && (is_global ||
-                                     self.macro_names.contains(&path[0].node.modern())) {
+                                     self.macro_names.contains(&path[0].modern())) {
             // Return some dummy definition, it's enough for error reporting.
             return Some(
                 PathResolution::new(Def::Macro(DefId::local(CRATE_DEF_INDEX), MacroKind::Bang))
@@ -3129,7 +3130,7 @@ fn resolve_qpath_anywhere(&mut self,
     fn resolve_qpath(&mut self,
                      id: NodeId,
                      qself: Option<&QSelf>,
-                     path: &[SpannedIdent],
+                     path: &[Ident],
                      ns: Namespace,
                      span: Span,
                      global_by_default: bool)
@@ -3170,8 +3171,8 @@ fn resolve_qpath(&mut self,
             PathResult::Module(..) | PathResult::Failed(..)
                     if (ns == TypeNS || path.len() > 1) &&
                        self.primitive_type_table.primitive_types
-                           .contains_key(&path[0].node.name) => {
-                let prim = self.primitive_type_table.primitive_types[&path[0].node.name];
+                           .contains_key(&path[0].name) => {
+                let prim = self.primitive_type_table.primitive_types[&path[0].name];
                 PathResolution::with_unresolved_segments(Def::PrimTy(prim), path.len() - 1)
             }
             PathResult::Module(module) => PathResolution::new(module.def().unwrap()),
@@ -3184,8 +3185,8 @@ fn resolve_qpath(&mut self,
         };
 
         if path.len() > 1 && !global_by_default && result.base_def() != Def::Err &&
-           path[0].node.name != keywords::CrateRoot.name() &&
-           path[0].node.name != keywords::DollarCrate.name() {
+           path[0].name != keywords::CrateRoot.name() &&
+           path[0].name != keywords::DollarCrate.name() {
             let unqualified_result = {
                 match self.resolve_path(&[*path.last().unwrap()], Some(ns), false, span) {
                     PathResult::NonModule(path_res) => path_res.base_def(),
@@ -3203,7 +3204,7 @@ fn resolve_qpath(&mut self,
     }
 
     fn resolve_path(&mut self,
-                    path: &[SpannedIdent],
+                    path: &[Ident],
                     opt_ns: Option<Namespace>, // `None` indicates a module path
                     record_used: bool,
                     path_span: Span)
@@ -3215,14 +3216,14 @@ fn resolve_path(&mut self,
             debug!("resolve_path ident {} {:?}", i, ident);
             let is_last = i == path.len() - 1;
             let ns = if is_last { opt_ns.unwrap_or(TypeNS) } else { TypeNS };
-            let name = ident.node.name;
+            let name = ident.name;
 
             if i == 0 && ns == TypeNS && name == keywords::SelfValue.name() {
-                let mut ctxt = ident.node.ctxt.modern();
+                let mut ctxt = ident.span.ctxt().modern();
                 module = Some(self.resolve_self(&mut ctxt, self.current_module));
                 continue
             } else if allow_super && ns == TypeNS && name == keywords::Super.name() {
-                let mut ctxt = ident.node.ctxt.modern();
+                let mut ctxt = ident.span.ctxt().modern();
                 let self_module = match i {
                     0 => self.resolve_self(&mut ctxt, self.current_module),
                     _ => module.unwrap(),
@@ -3242,16 +3243,16 @@ fn resolve_path(&mut self,
             if ns == TypeNS {
                 if (i == 0 && name == keywords::CrateRoot.name()) ||
                    (i == 1 && name == keywords::Crate.name() &&
-                              path[0].node.name == keywords::CrateRoot.name()) {
+                              path[0].name == keywords::CrateRoot.name()) {
                     // `::a::b` or `::crate::a::b`
-                    module = Some(self.resolve_crate_root(ident.node.ctxt, false));
+                    module = Some(self.resolve_crate_root(ident.span.ctxt(), false));
                     continue
                 } else if i == 0 && name == keywords::DollarCrate.name() {
                     // `$crate::a::b`
-                    module = Some(self.resolve_crate_root(ident.node.ctxt, true));
+                    module = Some(self.resolve_crate_root(ident.span.ctxt(), true));
                     continue
-                } else if i == 1 && !token::is_path_segment_keyword(ident.node) {
-                    let prev_name = path[0].node.name;
+                } else if i == 1 && !token::is_path_segment_keyword(ident) {
+                    let prev_name = path[0].name;
                     if prev_name == keywords::Extern.name() ||
                        prev_name == keywords::CrateRoot.name() &&
                        self.session.features_untracked().extern_absolute_paths {
@@ -3274,13 +3275,13 @@ fn resolve_path(&mut self,
                name == keywords::Super.name() && i != 0 ||
                name == keywords::Extern.name() && i != 0 ||
                name == keywords::Crate.name() && i != 1 &&
-                    path[0].node.name != keywords::CrateRoot.name() {
+                    path[0].name != keywords::CrateRoot.name() {
                 let name_str = if name == keywords::CrateRoot.name() {
                     format!("crate root")
                 } else {
                     format!("`{}`", name)
                 };
-                let msg = if i == 1 && path[0].node.name == keywords::CrateRoot.name() {
+                let msg = if i == 1 && path[0].name == keywords::CrateRoot.name() {
                     format!("global paths cannot start with {}", name_str)
                 } else if i == 0 && name == keywords::Crate.name() {
                     format!("{} can only be used in absolute paths", name_str)
@@ -3291,12 +3292,12 @@ fn resolve_path(&mut self,
             }
 
             let binding = if let Some(module) = module {
-                self.resolve_ident_in_module(module, ident.node, ns, false, record_used, path_span)
+                self.resolve_ident_in_module(module, ident, ns, false, record_used, path_span)
             } else if opt_ns == Some(MacroNS) {
-                self.resolve_lexical_macro_path_segment(ident.node, ns, record_used, path_span)
+                self.resolve_lexical_macro_path_segment(ident, ns, record_used, path_span)
                     .map(MacroBinding::binding)
             } else {
-                match self.resolve_ident_in_lexical_scope(ident.node, ns, record_used, path_span) {
+                match self.resolve_ident_in_lexical_scope(ident, ns, record_used, path_span) {
                     Some(LexicalScopeBinding::Item(binding)) => Ok(binding),
                     Some(LexicalScopeBinding::Def(def))
                             if opt_ns == Some(TypeNS) || opt_ns == Some(ValueNS) => {
@@ -3322,7 +3323,7 @@ fn resolve_path(&mut self,
                         ));
                     } else {
                         return PathResult::Failed(ident.span,
-                                                  format!("Not a module `{}`", ident.node),
+                                                  format!("Not a module `{}`", ident),
                                                   is_last);
                     }
                 }
@@ -3343,12 +3344,12 @@ fn resolve_path(&mut self,
                         if let Some(candidate) = candidates.get(0) {
                             format!("Did you mean `{}`?", candidate.path)
                         } else {
-                            format!("Maybe a missing `extern crate {};`?", ident.node)
+                            format!("Maybe a missing `extern crate {};`?", ident)
                         }
                     } else if i == 0 {
-                        format!("Use of undeclared type or module `{}`", ident.node)
+                        format!("Use of undeclared type or module `{}`", ident)
                     } else {
-                        format!("Could not find `{}` in `{}`", ident.node, path[i - 1].node)
+                        format!("Could not find `{}` in `{}`", ident, path[i - 1])
                     };
                     return PathResult::Failed(ident.span, msg, is_last);
                 }
@@ -3514,7 +3515,7 @@ fn extract_node_id(t: &Ty) -> Option<NodeId> {
     }
 
     fn lookup_typo_candidate<FilterFn>(&mut self,
-                                       path: &[SpannedIdent],
+                                       path: &[Ident],
                                        ns: Namespace,
                                        filter_fn: FilterFn,
                                        span: Span)
@@ -3575,7 +3576,7 @@ fn lookup_typo_candidate<FilterFn>(&mut self,
             }
         }
 
-        let name = path[path.len() - 1].node.name;
+        let name = path[path.len() - 1].name;
         // Make sure error reporting is deterministic.
         names.sort_by_key(|name| name.as_str());
         match find_best_match_for_name(names.iter(), &name.as_str(), None) {
@@ -3632,7 +3633,7 @@ fn resolve_expr(&mut self, expr: &Expr, parent: Option<&Expr>) {
                         });
                         self.record_def(expr.id, err_path_resolution());
                         resolve_error(self,
-                                      label.span,
+                                      label.ident.span,
                                       ResolutionError::UndeclaredLabel(&label.ident.name.as_str(),
                                                                        close_match));
                     }
@@ -3737,18 +3738,18 @@ fn resolve_expr(&mut self, expr: &Expr, parent: Option<&Expr>) {
 
     fn record_candidate_traits_for_expr_if_necessary(&mut self, expr: &Expr) {
         match expr.node {
-            ExprKind::Field(_, name) => {
+            ExprKind::Field(_, ident) => {
                 // FIXME(#6890): Even though you can't treat a method like a
                 // field, we need to add any trait methods we find that match
                 // the field name so that we can do some nice error reporting
                 // later on in typeck.
-                let traits = self.get_traits_containing_item(name.node, ValueNS);
+                let traits = self.get_traits_containing_item(ident, ValueNS);
                 self.trait_map.insert(expr.id, traits);
             }
             ExprKind::MethodCall(ref segment, ..) => {
                 debug!("(recording candidate traits for expr) recording traits for {}",
                        expr.id);
-                let traits = self.get_traits_containing_item(segment.identifier, ValueNS);
+                let traits = self.get_traits_containing_item(segment.ident, ValueNS);
                 self.trait_map.insert(expr.id, traits);
             }
             _ => {
@@ -3770,12 +3771,12 @@ fn get_traits_containing_item(&mut self, mut ident: Ident, ns: Namespace)
             }
         }
 
-        ident.ctxt = ident.ctxt.modern();
+        ident.span = ident.span.modern();
         let mut search_module = self.current_module;
         loop {
             self.get_traits_in_module_containing_item(ident, ns, search_module, &mut found_traits);
             search_module =
-                unwrap_or!(self.hygienic_lexical_parent(search_module, &mut ident.ctxt), break);
+                unwrap_or!(self.hygienic_lexical_parent(search_module, &mut ident.span), break);
         }
 
         if let Some(prelude) = self.prelude {
@@ -3807,7 +3808,7 @@ fn get_traits_in_module_containing_item(&mut self,
         for &(trait_name, binding) in traits.as_ref().unwrap().iter() {
             let module = binding.module().unwrap();
             let mut ident = ident;
-            if ident.ctxt.glob_adjust(module.expansion, binding.span.ctxt().modern()).is_none() {
+            if ident.span.glob_adjust(module.expansion, binding.span.ctxt().modern()).is_none() {
                 continue
             }
             if self.resolve_ident_in_module_unadjusted(module, ident, ns, false, false, module.span)
@@ -3863,7 +3864,7 @@ fn lookup_import_candidates<FilterFn>(&mut self,
                     if filter_fn(name_binding.def()) {
                         // create the path
                         let mut segms = path_segments.clone();
-                        segms.push(ast::PathSegment::from_ident(ident, name_binding.span));
+                        segms.push(ast::PathSegment::from_ident(ident));
                         let path = Path {
                             span: name_binding.span,
                             segments: segms,
@@ -3885,7 +3886,7 @@ fn lookup_import_candidates<FilterFn>(&mut self,
                 if let Some(module) = name_binding.module() {
                     // form the path
                     let mut path_segments = path_segments.clone();
-                    path_segments.push(ast::PathSegment::from_ident(ident, name_binding.span));
+                    path_segments.push(ast::PathSegment::from_ident(ident));
 
                     if !in_module_is_extern || name_binding.vis == ty::Visibility::Public {
                         // add the module to the lookup
@@ -3924,7 +3925,7 @@ fn find_module(&mut self,
                 if let Some(module) = name_binding.module() {
                     // form the path
                     let mut path_segments = path_segments.clone();
-                    path_segments.push(ast::PathSegment::from_ident(ident, name_binding.span));
+                    path_segments.push(ast::PathSegment::from_ident(ident));
                     if module.def() == Some(module_def) {
                         let path = Path {
                             span: name_binding.span,
@@ -3956,7 +3957,7 @@ fn collect_enum_variants(&mut self, enum_def: Def) -> Option<Vec<Path>> {
             enum_module.for_each_child_stable(|ident, _, name_binding| {
                 if let Def::Variant(..) = name_binding.def() {
                     let mut segms = enum_import_suggestion.path.segments.clone();
-                    segms.push(ast::PathSegment::from_ident(ident, name_binding.span));
+                    segms.push(ast::PathSegment::from_ident(ident));
                     variants.push(Path {
                         span: name_binding.span,
                         segments: segms,
@@ -3986,7 +3987,7 @@ fn resolve_visibility(&mut self, vis: &ast::Visibility) -> ty::Visibility {
             ast::VisibilityKind::Restricted { ref path, id, .. } => {
                 // Visibilities are resolved as global by default, add starting root segment.
                 let segments = path.make_root().iter().chain(path.segments.iter())
-                    .map(|seg| respan(seg.span, seg.identifier))
+                    .map(|seg| seg.ident)
                     .collect::<Vec<_>>();
                 let def = self.smart_resolve_path_fragment(id, None, &segments, path.span,
                                                            PathSource::Visibility).base_def();
@@ -4220,7 +4221,7 @@ fn check_proc_macro_attrs(&mut self, attrs: &[ast::Attribute]) {
             if attr.path.segments.len() > 1 {
                 continue
             }
-            let ident = attr.path.segments[0].identifier;
+            let ident = attr.path.segments[0].ident;
             let result = self.resolve_lexical_macro_path_segment(ident,
                                                                  MacroNS,
                                                                  false,
@@ -4242,30 +4243,30 @@ fn check_proc_macro_attrs(&mut self, attrs: &[ast::Attribute]) {
     }
 }
 
-fn is_self_type(path: &[SpannedIdent], namespace: Namespace) -> bool {
-    namespace == TypeNS && path.len() == 1 && path[0].node.name == keywords::SelfType.name()
+fn is_self_type(path: &[Ident], namespace: Namespace) -> bool {
+    namespace == TypeNS && path.len() == 1 && path[0].name == keywords::SelfType.name()
 }
 
-fn is_self_value(path: &[SpannedIdent], namespace: Namespace) -> bool {
-    namespace == ValueNS && path.len() == 1 && path[0].node.name == keywords::SelfValue.name()
+fn is_self_value(path: &[Ident], namespace: Namespace) -> bool {
+    namespace == ValueNS && path.len() == 1 && path[0].name == keywords::SelfValue.name()
 }
 
-fn names_to_string(idents: &[SpannedIdent]) -> String {
+fn names_to_string(idents: &[Ident]) -> String {
     let mut result = String::new();
     for (i, ident) in idents.iter()
-                            .filter(|i| i.node.name != keywords::CrateRoot.name())
+                            .filter(|ident| ident.name != keywords::CrateRoot.name())
                             .enumerate() {
         if i > 0 {
             result.push_str("::");
         }
-        result.push_str(&ident.node.name.as_str());
+        result.push_str(&ident.name.as_str());
     }
     result
 }
 
 fn path_names_to_string(path: &Path) -> String {
     names_to_string(&path.segments.iter()
-                        .map(|seg| respan(seg.span, seg.identifier))
+                        .map(|seg| seg.ident)
                         .collect::<Vec<_>>())
 }
 
@@ -4354,7 +4355,6 @@ fn collect_mod(names: &mut Vec<Ident>, module: Module) {
     }
     Some(names_to_string(&names.into_iter()
                         .rev()
-                        .map(|n| dummy_spanned(n))
                         .collect::<Vec<_>>()))
 }
 
index 0692a1e0d7f8afbf396dfd48f904db4083cbcd70..0388465b485cb5527727dc50045c16db5ed16351 100644 (file)
@@ -20,7 +20,6 @@
 use rustc::{ty, lint};
 use syntax::ast::{self, Name, Ident};
 use syntax::attr::{self, HasAttrs};
-use syntax::codemap::respan;
 use syntax::errors::DiagnosticBuilder;
 use syntax::ext::base::{self, Annotatable, Determinacy, MultiModifier, MultiDecorator};
 use syntax::ext::base::{MacroKind, SyntaxExtension, Resolver as SyntaxResolver};
@@ -137,15 +136,15 @@ fn eliminate_crate_var(&mut self, item: P<ast::Item>) -> P<ast::Item> {
 
         impl<'a, 'b> Folder for EliminateCrateVar<'a, 'b> {
             fn fold_path(&mut self, mut path: ast::Path) -> ast::Path {
-                let ident = path.segments[0].identifier;
+                let ident = path.segments[0].ident;
                 if ident.name == keywords::DollarCrate.name() {
-                    path.segments[0].identifier.name = keywords::CrateRoot.name();
-                    let module = self.0.resolve_crate_root(ident.ctxt, true);
+                    path.segments[0].ident.name = keywords::CrateRoot.name();
+                    let module = self.0.resolve_crate_root(ident.span.ctxt(), true);
                     if !module.is_local() {
-                        let span = path.segments[0].span;
+                        let span = path.segments[0].ident.span;
                         path.segments.insert(1, match module.kind {
                             ModuleKind::Def(_, name) => ast::PathSegment::from_ident(
-                                ast::Ident::with_empty_ctxt(name), span
+                                ast::Ident::with_empty_ctxt(name).with_span_pos(span)
                             ),
                             _ => unreachable!(),
                         })
@@ -249,7 +248,7 @@ fn find_legacy_attr_invoc(&mut self, attrs: &mut Vec<ast::Attribute>)
                     if traits[j].segments.len() > 1 {
                         continue
                     }
-                    let trait_name = traits[j].segments[0].identifier.name;
+                    let trait_name = traits[j].segments[0].ident.name;
                     let legacy_name = Symbol::intern(&format!("derive_{}", trait_name));
                     if !self.global_macros.contains_key(&legacy_name) {
                         continue
@@ -268,7 +267,7 @@ fn find_legacy_attr_invoc(&mut self, attrs: &mut Vec<ast::Attribute>)
                                 if k > 0 {
                                     tokens.push(TokenTree::Token(path.span, Token::ModSep).into());
                                 }
-                                let tok = Token::from_ast_ident(segment.identifier);
+                                let tok = Token::from_ast_ident(segment.ident);
                                 tokens.push(TokenTree::Token(path.span, tok).into());
                             }
                         }
@@ -278,7 +277,7 @@ fn find_legacy_attr_invoc(&mut self, attrs: &mut Vec<ast::Attribute>)
                         }).into();
                     }
                     return Some(ast::Attribute {
-                        path: ast::Path::from_ident(span, Ident::with_empty_ctxt(legacy_name)),
+                        path: ast::Path::from_ident(Ident::new(legacy_name, span)),
                         tokens: TokenStream::empty(),
                         id: attr::mk_attr_id(),
                         style: ast::AttrStyle::Outer,
@@ -365,7 +364,7 @@ fn resolve_invoc_to_def(&mut self, invoc: &mut Invocation, scope: Mark, force: b
         }
 
         let attr_name = match path.segments.len() {
-            1 => path.segments[0].identifier.name,
+            1 => path.segments[0].ident.name,
             _ => return Err(determinacy),
         };
         for path in traits {
@@ -413,7 +412,7 @@ pub fn resolve_macro_to_def_inner(&mut self, scope: Mark, path: &ast::Path,
                                   kind: MacroKind, force: bool)
                                   -> Result<Def, Determinacy> {
         let ast::Path { ref segments, span } = *path;
-        let path: Vec<_> = segments.iter().map(|seg| respan(seg.span, seg.identifier)).collect();
+        let path: Vec<_> = segments.iter().map(|seg| seg.ident).collect();
         let invocation = self.invocations[&scope];
         let module = invocation.module.get();
         self.current_module = if module.is_trait() { module.parent.unwrap() } else { module };
@@ -447,19 +446,16 @@ pub fn resolve_macro_to_def_inner(&mut self, scope: Mark, path: &ast::Path,
                     Err(Determinacy::Determined)
                 },
             };
-            let path = path.iter().map(|p| p.node).collect::<Vec<_>>();
             self.current_module.nearest_item_scope().macro_resolutions.borrow_mut()
                 .push((path.into_boxed_slice(), span));
             return def;
         }
 
-        let legacy_resolution = self.resolve_legacy_scope(&invocation.legacy_scope,
-                                                          path[0].node,
-                                                          false);
+        let legacy_resolution = self.resolve_legacy_scope(&invocation.legacy_scope, path[0], false);
         let result = if let Some(MacroBinding::Legacy(binding)) = legacy_resolution {
             Ok(Def::Macro(binding.def_id, MacroKind::Bang))
         } else {
-            match self.resolve_lexical_macro_path_segment(path[0].node, MacroNS, false, span) {
+            match self.resolve_lexical_macro_path_segment(path[0], MacroNS, false, span) {
                 Ok(binding) => Ok(binding.binding().def_ignoring_ambiguity()),
                 Err(Determinacy::Undetermined) if !force => return Err(Determinacy::Undetermined),
                 Err(_) => {
@@ -470,7 +466,7 @@ pub fn resolve_macro_to_def_inner(&mut self, scope: Mark, path: &ast::Path,
         };
 
         self.current_module.nearest_item_scope().legacy_macro_resolutions.borrow_mut()
-            .push((scope, path[0].node, span, kind));
+            .push((scope, path[0], span, kind));
 
         result
     }
@@ -534,7 +530,7 @@ pub fn resolve_lexical_macro_path_segment(&mut self,
             }
 
             module = match module {
-                Some(module) => self.hygienic_lexical_parent(module, &mut ident.ctxt),
+                Some(module) => self.hygienic_lexical_parent(module, &mut ident.span),
                 None => return potential_illegal_shadower,
             }
         }
@@ -608,7 +604,6 @@ pub fn resolve_legacy_scope(&mut self,
     pub fn finalize_current_module_macro_resolutions(&mut self) {
         let module = self.current_module;
         for &(ref path, span) in module.macro_resolutions.borrow().iter() {
-            let path = path.iter().map(|p| respan(span, *p)).collect::<Vec<_>>();
             match self.resolve_path(&path, Some(MacroNS), true, span) {
                 PathResult::NonModule(_) => {},
                 PathResult::Failed(span, msg, _) => {
@@ -684,8 +679,8 @@ fn suggest_macro_name(&mut self, name: &str, kind: MacroKind,
                     false
                 }
             };
-            let ident = Ident::from_str(name);
-            self.lookup_typo_candidate(&vec![respan(span, ident)], MacroNS, is_macro, span)
+            let ident = Ident::new(Symbol::intern(name), span);
+            self.lookup_typo_candidate(&vec![ident], MacroNS, is_macro, span)
         });
 
         if let Some(suggestion) = suggestion {
index 7036bdd0e2b07f6edff00b380bca860b6751bc90..87738f7b79be530e6ecb482d10a4a26a5da90ca9 100644 (file)
@@ -24,7 +24,7 @@
 use rustc::session::DiagnosticMessageId;
 use rustc::util::nodemap::{FxHashMap, FxHashSet};
 
-use syntax::ast::{Ident, Name, SpannedIdent, NodeId};
+use syntax::ast::{Ident, Name, NodeId};
 use syntax::ext::base::Determinacy::{self, Determined, Undetermined};
 use syntax::ext::hygiene::Mark;
 use syntax::parse::token;
@@ -58,7 +58,7 @@ pub enum ImportDirectiveSubclass<'a> {
 pub struct ImportDirective<'a> {
     pub id: NodeId,
     pub parent: Module<'a>,
-    pub module_path: Vec<SpannedIdent>,
+    pub module_path: Vec<Ident>,
     pub imported_module: Cell<Option<Module<'a>>>, // the resolution of `module_path`
     pub subclass: ImportDirectiveSubclass<'a>,
     pub span: Span,
@@ -238,7 +238,7 @@ pub fn resolve_ident_in_module_unadjusted(&mut self,
             }
             let module = unwrap_or!(directive.imported_module.get(), return Err(Undetermined));
             let (orig_current_module, mut ident) = (self.current_module, ident.modern());
-            match ident.ctxt.glob_adjust(module.expansion, directive.span.ctxt().modern()) {
+            match ident.span.glob_adjust(module.expansion, directive.span.ctxt().modern()) {
                 Some(Some(def)) => self.current_module = self.macro_def_scope(def),
                 Some(None) => {}
                 None => continue,
@@ -257,7 +257,7 @@ pub fn resolve_ident_in_module_unadjusted(&mut self,
 
     // Add an import directive to the current module.
     pub fn add_import_directive(&mut self,
-                                module_path: Vec<SpannedIdent>,
+                                module_path: Vec<Ident>,
                                 subclass: ImportDirectiveSubclass<'a>,
                                 span: Span,
                                 id: NodeId,
@@ -398,7 +398,7 @@ fn update_resolution<T, F>(&mut self, module: Module<'a>, ident: Ident, ns: Name
         // Define `binding` in `module`s glob importers.
         for directive in module.glob_importers.borrow_mut().iter() {
             let mut ident = ident.modern();
-            let scope = match ident.ctxt.reverse_glob_adjust(module.expansion,
+            let scope = match ident.span.reverse_glob_adjust(module.expansion,
                                                              directive.span.ctxt().modern()) {
                 Some(Some(def)) => self.macro_def_scope(def),
                 Some(None) => directive.parent,
@@ -606,9 +606,9 @@ fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> Option<(Spa
 
         // FIXME: Last path segment is treated specially in import resolution, so extern crate
         // mode for absolute paths needs some special support for single-segment imports.
-        if module_path.len() == 1 && (module_path[0].node.name == keywords::CrateRoot.name() ||
-                                      module_path[0].node.name == keywords::Extern.name()) {
-            let is_extern = module_path[0].node.name == keywords::Extern.name() ||
+        if module_path.len() == 1 && (module_path[0].name == keywords::CrateRoot.name() ||
+                                      module_path[0].name == keywords::Extern.name()) {
+            let is_extern = module_path[0].name == keywords::Extern.name() ||
                             self.session.features_untracked().extern_absolute_paths;
             match directive.subclass {
                 GlobImport { .. } if is_extern => {
@@ -617,13 +617,13 @@ fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> Option<(Spa
                 }
                 SingleImport { source, target, .. } => {
                     let crate_root = if source.name == keywords::Crate.name() &&
-                                        module_path[0].node.name != keywords::Extern.name() {
+                                        module_path[0].name != keywords::Extern.name() {
                         if target.name == keywords::Crate.name() {
                             return Some((directive.span,
                                          "crate root imports need to be explicitly named: \
                                           `use crate as name;`".to_string()));
                         } else {
-                            Some(self.resolve_crate_root(source.ctxt.modern(), false))
+                            Some(self.resolve_crate_root(source.span.ctxt().modern(), false))
                         }
                     } else if is_extern && !token::is_path_segment_keyword(source) {
                         let crate_id =
@@ -669,9 +669,9 @@ fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> Option<(Spa
                 let (mut self_path, mut self_result) = (module_path.clone(), None);
                 let is_special = |ident| token::is_path_segment_keyword(ident) &&
                                          ident.name != keywords::CrateRoot.name();
-                if !self_path.is_empty() && !is_special(self_path[0].node) &&
-                   !(self_path.len() > 1 && is_special(self_path[1].node)) {
-                    self_path[0].node.name = keywords::SelfValue.name();
+                if !self_path.is_empty() && !is_special(self_path[0]) &&
+                   !(self_path.len() > 1 && is_special(self_path[1])) {
+                    self_path[0].name = keywords::SelfValue.name();
                     self_result = Some(self.resolve_path(&self_path, None, false, span));
                 }
                 return if let Some(PathResult::Module(..)) = self_result {
@@ -860,7 +860,7 @@ fn resolve_glob_import(&mut self, directive: &'b ImportDirective<'b>) {
             resolution.borrow().binding().map(|binding| (ident, binding))
         }).collect::<Vec<_>>();
         for ((mut ident, ns), binding) in bindings {
-            let scope = match ident.ctxt.reverse_glob_adjust(module.expansion,
+            let scope = match ident.span.reverse_glob_adjust(module.expansion,
                                                              directive.span.ctxt().modern()) {
                 Some(Some(def)) => self.macro_def_scope(def),
                 Some(None) => self.current_module,
@@ -957,7 +957,7 @@ fn finalize_resolutions_in(&mut self, module: Module<'b>) {
                             let resolutions = imported_module.parent.expect("parent should exist")
                                 .resolutions.borrow();
                             let enum_path_segment_index = directive.module_path.len() - 1;
-                            let enum_ident = directive.module_path[enum_path_segment_index].node;
+                            let enum_ident = directive.module_path[enum_path_segment_index];
 
                             let enum_resolution = resolutions.get(&(enum_ident, TypeNS))
                                 .expect("resolution should exist");
@@ -1011,12 +1011,12 @@ fn finalize_resolutions_in(&mut self, module: Module<'b>) {
     }
 }
 
-fn import_path_to_string(names: &[SpannedIdent],
+fn import_path_to_string(names: &[Ident],
                          subclass: &ImportDirectiveSubclass,
                          span: Span) -> String {
     let pos = names.iter()
-        .position(|p| span == p.span && p.node.name != keywords::CrateRoot.name());
-    let global = !names.is_empty() && names[0].node.name == keywords::CrateRoot.name();
+        .position(|p| span == p.span && p.name != keywords::CrateRoot.name());
+    let global = !names.is_empty() && names[0].name == keywords::CrateRoot.name();
     if let Some(pos) = pos {
         let names = if global { &names[1..pos + 1] } else { &names[..pos + 1] };
         names_to_string(names)
index 3d4d8571c6e4242283bea932777f3e3c30ae9b4a..607701b056bab6ce743ed7fe6d084f58d9f59417 100644 (file)
@@ -20,9 +20,8 @@
 //!
 //! SpanUtils is used to manipulate spans. In particular, to extract sub-spans
 //! from spans (e.g., the span for `bar` from the above example path).
-//! DumpVisitor walks the AST and processes it, and an implementor of Dump
-//! is used for recording the output in a format-agnostic way (see CsvDumper
-//! for an example).
+//! DumpVisitor walks the AST and processes it, and JsonDumper is used for
+//! recording the output.
 
 use rustc::hir::def::Def as HirDef;
 use rustc::hir::def_id::DefId;
@@ -183,7 +182,7 @@ fn process_path_prefixes(&self, path: &ast::Path) -> Vec<(Span, String)> {
         for (i, seg) in segments.iter().enumerate() {
             segs.push(seg.clone());
             let sub_path = ast::Path {
-                span: seg.span, // span for the last segment
+                span: seg.ident.span, // span for the last segment
                 segments: segs,
             };
             let qualname = if i == 0 && path.is_global() {
@@ -191,7 +190,7 @@ fn process_path_prefixes(&self, path: &ast::Path) -> Vec<(Span, String)> {
             } else {
                 path_to_string(&sub_path)
             };
-            result.push((seg.span, qualname));
+            result.push((seg.ident.span, qualname));
             segs = sub_path.segments;
         }
 
@@ -351,14 +350,14 @@ fn process_formals(&mut self, formals: &'l [ast::Arg], qualname: &str) {
             collector.visit_pat(&arg.pat);
             let span_utils = self.span.clone();
 
-            for (id, i, sp, ..) in collector.collected_idents {
+            for (id, ident, ..) in collector.collected_idents {
                 let hir_id = self.tcx.hir.node_to_hir_id(id);
                 let typ = match self.save_ctxt.tables.node_id_to_type_opt(hir_id) {
                     Some(s) => s.to_string(),
                     None => continue,
                 };
-                let sub_span = span_utils.span_for_last_ident(sp);
-                if !self.span.filter_generated(sub_span, sp) {
+                let sub_span = span_utils.span_for_last_ident(ident.span);
+                if !self.span.filter_generated(sub_span, ident.span) {
                     let id = ::id_from_node_id(id, &self.save_ctxt);
                     let span = self.span_from_span(sub_span.expect("No span found for variable"));
 
@@ -371,8 +370,8 @@ fn process_formals(&mut self, formals: &'l [ast::Arg], qualname: &str) {
                             kind: DefKind::Local,
                             id,
                             span,
-                            name: i.to_string(),
-                            qualname: format!("{}::{}", qualname, i.to_string()),
+                            name: ident.to_string(),
+                            qualname: format!("{}::{}", qualname, ident.to_string()),
                             value: typ,
                             parent: None,
                             children: vec![],
@@ -447,7 +446,7 @@ fn process_generic_params(
     ) {
         for param in &generics.params {
             if let ast::GenericParam::Type(ref ty_param) = *param {
-                let param_ss = ty_param.span;
+                let param_ss = ty_param.ident.span;
                 let name = escape(self.span.snippet(param_ss));
                 // Append $id to name to make sure each one is unique
                 let qualname = format!("{}::{}${}", prefix, name, id);
@@ -663,7 +662,7 @@ fn process_enum(
         let access = access_from!(self.save_ctxt, item);
 
         for variant in &enum_definition.variants {
-            let name = variant.node.name.name.to_string();
+            let name = variant.node.ident.name.to_string();
             let mut qualname = enum_data.qualname.clone();
             qualname.push_str("::");
             qualname.push_str(&name);
@@ -1040,11 +1039,11 @@ fn process_var_decl_multi(&mut self, pats: &'l [P<ast::Pat>]) {
         }
 
         // process collected paths
-        for (id, i, sp, immut) in collector.collected_idents {
+        for (id, ident, immut) in collector.collected_idents {
             match self.save_ctxt.get_path_def(id) {
                 HirDef::Local(id) => {
                     let mut value = if immut == ast::Mutability::Immutable {
-                        self.span.snippet(sp).to_string()
+                        self.span.snippet(ident.span).to_string()
                     } else {
                         "<mutable>".to_string()
                     };
@@ -1057,10 +1056,10 @@ fn process_var_decl_multi(&mut self, pats: &'l [P<ast::Pat>]) {
                     value.push_str(": ");
                     value.push_str(&typ);
 
-                    if !self.span.filter_generated(Some(sp), sp) {
-                        let qualname = format!("{}${}", i.to_string(), id);
+                    if !self.span.filter_generated(Some(ident.span), ident.span) {
+                        let qualname = format!("{}${}", ident.to_string(), id);
                         let id = ::id_from_node_id(id, &self.save_ctxt);
-                        let span = self.span_from_span(sp);
+                        let span = self.span_from_span(ident.span);
 
                         self.dumper.dump_def(
                             &Access {
@@ -1071,7 +1070,7 @@ fn process_var_decl_multi(&mut self, pats: &'l [P<ast::Pat>]) {
                                 kind: DefKind::Local,
                                 id,
                                 span,
-                                name: i.to_string(),
+                                name: ident.to_string(),
                                 qualname,
                                 value: typ,
                                 parent: None,
@@ -1093,7 +1092,7 @@ fn process_var_decl_multi(&mut self, pats: &'l [P<ast::Pat>]) {
                 HirDef::TyAlias(..) |
                 HirDef::AssociatedTy(..) |
                 HirDef::SelfTy(..) => {
-                    self.dump_path_ref(id, &ast::Path::from_ident(sp, i));
+                    self.dump_path_ref(id, &ast::Path::from_ident(ident));
                 }
                 def => error!(
                     "unexpected definition kind when processing collected idents: {:?}",
@@ -1114,7 +1113,7 @@ fn process_var_decl(&mut self, p: &'l ast::Pat, value: String) {
         collector.visit_pat(&p);
         self.visit_pat(&p);
 
-        for (id, i, sp, immut) in collector.collected_idents {
+        for (id, ident, immut) in collector.collected_idents {
             let mut value = match immut {
                 ast::Mutability::Immutable => value.to_string(),
                 _ => String::new(),
@@ -1134,10 +1133,10 @@ fn process_var_decl(&mut self, p: &'l ast::Pat, value: String) {
 
             // Get the span only for the name of the variable (I hope the path
             // is only ever a variable name, but who knows?).
-            let sub_span = self.span.span_for_last_ident(sp);
+            let sub_span = self.span.span_for_last_ident(ident.span);
             // Rust uses the id of the pattern for var lookups, so we'll use it too.
-            if !self.span.filter_generated(sub_span, sp) {
-                let qualname = format!("{}${}", i.to_string(), id);
+            if !self.span.filter_generated(sub_span, ident.span) {
+                let qualname = format!("{}${}", ident.to_string(), id);
                 let id = ::id_from_node_id(id, &self.save_ctxt);
                 let span = self.span_from_span(sub_span.expect("No span found for variable"));
 
@@ -1150,7 +1149,7 @@ fn process_var_decl(&mut self, p: &'l ast::Pat, value: String) {
                         kind: DefKind::Local,
                         id,
                         span,
-                        name: i.to_string(),
+                        name: ident.to_string(),
                         qualname,
                         value: typ,
                         parent: None,
@@ -1812,6 +1811,7 @@ fn visit_foreign_item(&mut self, item: &'l ast::ForeignItem) {
                     self.dumper.dump_def(&access, var_data);
                 }
             }
+            ast::ForeignItemKind::Macro(..) => {}
         }
     }
 }
index 953747756517dfb5f3d3bea4df5e5496e12d6f22..fefedd4e1c819112bcf1f7a749830f7976b7d4cf 100644 (file)
@@ -11,7 +11,6 @@
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "https://doc.rust-lang.org/nightly/")]
-#![deny(warnings)]
 #![feature(custom_attribute)]
 #![feature(macro_lifetime_matcher)]
 #![allow(unused_attributes)]
@@ -182,6 +181,7 @@ pub fn get_extern_item_data(&self, item: &ast::ForeignItem) -> Option<Data> {
             }
             // FIXME(plietar): needs a new DefKind in rls-data
             ast::ForeignItemKind::Ty => None,
+            ast::ForeignItemKind::Macro(..) => None,
         }
     }
 
@@ -296,7 +296,7 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
                 filter!(self.span_utils, sub_span, item.span, None);
                 let variants_str = def.variants
                     .iter()
-                    .map(|v| v.node.name.to_string())
+                    .map(|v| v.node.ident.to_string())
                     .collect::<Vec<_>>()
                     .join(", ");
                 let value = format!("{}::{{{}}}", name, variants_str);
@@ -553,7 +553,7 @@ pub fn get_expr_data(&self, expr: &ast::Expr) -> Option<Data> {
                 };
                 match self.tables.expr_ty_adjusted(&hir_node).sty {
                     ty::TyAdt(def, _) if !def.is_enum() => {
-                        let f = def.non_enum_variant().field_named(ident.node.name);
+                        let f = def.non_enum_variant().field_named(ident.name);
                         let sub_span = self.span_utils.span_for_last_ident(expr.span);
                         filter!(self.span_utils, sub_span, expr.span, None);
                         let span = self.span_from_span(sub_span.unwrap());
@@ -602,7 +602,7 @@ pub fn get_expr_data(&self, expr: &ast::Expr) -> Option<Data> {
                     ty::ImplContainer(_) => (Some(method_id), None),
                     ty::TraitContainer(_) => (None, Some(method_id)),
                 };
-                let sub_span = seg.span;
+                let sub_span = seg.ident.span;
                 filter!(self.span_utils, Some(sub_span), expr.span, None);
                 let span = self.span_from_span(sub_span);
                 Some(Data::RefData(Ref {
@@ -706,7 +706,7 @@ fn fn_type(path: &ast::Path) -> bool {
 
         let def = self.get_path_def(id);
         let last_seg = &path.segments[path.segments.len() - 1];
-        let sub_span = last_seg.span;
+        let sub_span = last_seg.ident.span;
         filter!(self.span_utils, Some(sub_span), path.span, None);
         match def {
             HirDef::Upvar(id, ..) | HirDef::Local(id) => {
@@ -816,7 +816,7 @@ pub fn get_field_ref_data(
         field_ref: &ast::Field,
         variant: &ty::VariantDef,
     ) -> Option<Ref> {
-        let f = variant.find_field_named(field_ref.ident.node.name)?;
+        let f = variant.find_field_named(field_ref.ident.name)?;
         // We don't really need a sub-span here, but no harm done
         let sub_span = self.span_utils.span_for_last_ident(field_ref.ident.span);
         filter!(self.span_utils, sub_span, field_ref.ident.span, None);
@@ -960,7 +960,7 @@ fn make_signature(decl: &ast::FnDecl, generics: &ast::Generics) -> String {
 // variables (idents) from patterns.
 struct PathCollector<'l> {
     collected_paths: Vec<(NodeId, &'l ast::Path)>,
-    collected_idents: Vec<(NodeId, ast::Ident, Span, ast::Mutability)>,
+    collected_idents: Vec<(NodeId, ast::Ident, ast::Mutability)>,
 }
 
 impl<'l> PathCollector<'l> {
@@ -981,12 +981,12 @@ fn visit_pat(&mut self, p: &'a ast::Pat) {
             PatKind::TupleStruct(ref path, ..) | PatKind::Path(_, ref path) => {
                 self.collected_paths.push((p.id, path));
             }
-            PatKind::Ident(bm, ref path1, _) => {
+            PatKind::Ident(bm, ident, _) => {
                 debug!(
                     "PathCollector, visit ident in pat {}: {:?} {:?}",
-                    path1.node,
+                    ident,
                     p.span,
-                    path1.span
+                    ident.span
                 );
                 let immut = match bm {
                     // Even if the ref is mut, you can't change the ref, only
@@ -996,7 +996,7 @@ fn visit_pat(&mut self, p: &'a ast::Pat) {
                     ast::BindingMode::ByValue(mt) => mt,
                 };
                 self.collected_idents
-                    .push((p.id, path1.node, path1.span, immut));
+                    .push((p.id, ident, immut));
             }
             _ => {}
         }
index 0c890ce19d0818c605c01e193c06be72d5cf82e6..a9df898efb6350659e4191eaa504539763c20efa 100644 (file)
@@ -671,7 +671,7 @@ impl Sig for ast::StructField {
     fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext) -> Result {
         let mut text = String::new();
         let mut defs = None;
-        if let Some(ref ident) = self.ident {
+        if let Some(ident) = self.ident {
             text.push_str(&ident.to_string());
             defs = Some(SigElement {
                 id: id_from_node_id(self.id, scx),
@@ -692,7 +692,7 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext) ->
 
 impl Sig for ast::Variant_ {
     fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext) -> Result {
-        let mut text = self.name.to_string();
+        let mut text = self.ident.to_string();
         match self.data {
             ast::VariantData::Struct(ref fields, id) => {
                 let name_def = SigElement {
@@ -822,6 +822,7 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext) ->
                     refs: vec![],
                 })
             }
+            ast::ForeignItemKind::Macro(..) => Err("macro"),
         }
     }
 }
index 90f368edeeca664434153c1b5c6f23900fc67b1f..8136f6857a5c62cc8ff1eacd8a1cb371cb9e2a70 100644 (file)
 //! 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(warnings)]
-
 #![feature(crate_visibility_modifier)]
-#![cfg_attr(stage0, feature(match_default_bindings))]
-#![cfg_attr(stage0, feature(underscore_lifetimes))]
 
 #[macro_use]
 extern crate log;
index 1092e826a35f96c643a9c9e25d620d28a08172c1..3d24b087c595834a0af70ccf0ebf5db716fbf6a1 100644 (file)
@@ -13,7 +13,7 @@
 use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc::ty::{self, TyCtxt};
 use rustc::ty::subst::Substs;
-use rustc::traits::{QuantifierKind, Goal, DomainGoal, Clause, WhereClauseAtom};
+use rustc::traits::{WhereClauseAtom, PolyDomainGoal, DomainGoal, ProgramClause, Clause};
 use syntax::ast;
 use rustc_data_structures::sync::Lrc;
 
@@ -61,28 +61,19 @@ fn lower(&self) -> DomainGoal<'tcx> {
 /// `ty::Binder` is used for wrapping a rustc construction possibly containing generic
 /// lifetimes, e.g. `for<'a> T: Fn(&'a i32)`. Instead of representing higher-ranked things
 /// in that leaf-form (i.e. `Holds(Implemented(Binder<TraitPredicate>))` in the previous
-/// example), we model them with quantified goals, e.g. as for the previous example:
+/// example), we model them with quantified domain goals, e.g. as for the previous example:
 /// `forall<'a> { T: Fn(&'a i32) }` which corresponds to something like
 /// `Binder<Holds(Implemented(TraitPredicate))>`.
-///
-/// Also, if `self` does not contain generic lifetimes, we can safely drop the binder and we
-/// can directly lower to a leaf goal instead of a quantified goal.
-impl<'tcx, T> Lower<Goal<'tcx>> for ty::Binder<T>
-    where T: Lower<DomainGoal<'tcx>> + ty::fold::TypeFoldable<'tcx> + Copy
+impl<'tcx, T> Lower<PolyDomainGoal<'tcx>> for ty::Binder<T>
+    where T: Lower<DomainGoal<'tcx>> + ty::fold::TypeFoldable<'tcx>
 {
-    fn lower(&self) -> Goal<'tcx> {
-        match self.no_late_bound_regions() {
-            Some(p) => p.lower().into(),
-            None => Goal::Quantified(
-                QuantifierKind::Universal,
-                Box::new(self.map_bound(|p| p.lower().into()))
-            ),
-        }
+    fn lower(&self) -> PolyDomainGoal<'tcx> {
+        self.map_bound_ref(|p| p.lower())
     }
 }
 
-impl<'tcx> Lower<Goal<'tcx>> for ty::Predicate<'tcx> {
-    fn lower(&self) -> Goal<'tcx> {
+impl<'tcx> Lower<PolyDomainGoal<'tcx>> for ty::Predicate<'tcx> {
+    fn lower(&self) -> PolyDomainGoal<'tcx> {
         use rustc::ty::Predicate::*;
 
         match self {
@@ -90,7 +81,7 @@ fn lower(&self) -> Goal<'tcx> {
             RegionOutlives(predicate) => predicate.lower(),
             TypeOutlives(predicate) => predicate.lower(),
             Projection(predicate) => predicate.lower(),
-            WellFormed(ty) => DomainGoal::WellFormedTy(*ty).into(),
+            WellFormed(ty) => ty::Binder::dummy(DomainGoal::WellFormedTy(*ty)),
             ObjectSafe(..) |
             ClosureKind(..) |
             Subtype(..) |
@@ -99,6 +90,28 @@ fn lower(&self) -> Goal<'tcx> {
     }
 }
 
+/// Transforms an existing goal into a FromEnv goal.
+///
+/// Used for lowered where clauses (see rustc guide).
+trait IntoFromEnvGoal {
+    fn into_from_env_goal(self) -> Self;
+}
+
+impl<'tcx> IntoFromEnvGoal for DomainGoal<'tcx> {
+    fn into_from_env_goal(self) -> DomainGoal<'tcx> {
+        use self::DomainGoal::*;
+        match self {
+            Holds(wc_atom) => FromEnv(wc_atom),
+            WellFormed(..) |
+            FromEnv(..) |
+            WellFormedTy(..) |
+            FromEnvTy(..) |
+            RegionOutlives(..) |
+            TypeOutlives(..) => self,
+        }
+    }
+}
+
 crate fn program_clauses_for<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
     -> Lrc<Vec<Clause<'tcx>>>
 {
@@ -116,9 +129,9 @@ fn lower(&self) -> Goal<'tcx> {
 fn program_clauses_for_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
     -> Lrc<Vec<Clause<'tcx>>>
 {
-    // Rule Implemented-From-Env (see rustc guide)
-    //
     // `trait Trait<P1..Pn> where WC { .. } // P0 == Self`
+
+    // Rule Implemented-From-Env (see rustc guide)
     //
     // ```
     // forall<Self, P1..Pn> {
@@ -134,13 +147,55 @@ fn program_clauses_for_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefI
         }
     };
     // `FromEnv(Self: Trait<P1..Pn>)`
-    let from_env = Goal::DomainGoal(DomainGoal::FromEnv(trait_pred.lower()));
+    let from_env = DomainGoal::FromEnv(trait_pred.lower()).into();
     // `Implemented(Self: Trait<P1..Pn>)`
     let impl_trait = DomainGoal::Holds(WhereClauseAtom::Implemented(trait_pred));
 
     // `Implemented(Self: Trait<P1..Pn>) :- FromEnv(Self: Trait<P1..Pn>)`
-    let clause = Clause::Implies(vec![from_env], impl_trait);
-    Lrc::new(vec![clause])
+    let implemented_from_env = ProgramClause {
+        goal: impl_trait,
+        hypotheses: vec![from_env],
+    };
+    let mut clauses = vec![
+        Clause::ForAll(ty::Binder::dummy(implemented_from_env))
+    ];
+
+    // Rule Implied-Bound-From-Trait
+    //
+    // For each where clause WC:
+    // ```
+    // forall<Self, P1..Pn> {
+    //   FromEnv(WC) :- FromEnv(Self: Trait<P1..Pn)
+    // }
+    // ```
+
+    // `FromEnv(WC) :- FromEnv(Self: Trait<P1..Pn>)`, for each where clause WC
+    // FIXME: Remove the [1..] slice; this is a hack because the query
+    // predicates_of currently includes the trait itself (`Self: Trait<P1..Pn>`).
+    let where_clauses = &tcx.predicates_of(def_id).predicates;
+    let implied_bound_clauses =
+        where_clauses[1..].into_iter()
+        .map(|wc| implied_bound_from_trait(trait_pred, wc));
+    clauses.extend(implied_bound_clauses);
+
+    Lrc::new(clauses)
+}
+
+/// For a given `where_clause`, returns a clause `FromEnv(WC) :- FromEnv(Self: Trait<P1..Pn>)`.
+fn implied_bound_from_trait<'tcx>(
+    trait_pred: ty::TraitPredicate<'tcx>,
+    where_clause: &ty::Predicate<'tcx>,
+) -> Clause<'tcx> {
+    // `FromEnv(Self: Trait<P1..Pn>)`
+    let impl_trait = DomainGoal::FromEnv(WhereClauseAtom::Implemented(trait_pred));
+
+    // `FromEnv(WC) :- FromEnv(Self: Trait<P1..Pn>)`
+    Clause::ForAll(
+        where_clause.lower().map_bound(|goal| ProgramClause {
+            goal: goal.into_from_env_goal(),
+            hypotheses: vec![impl_trait.into()],
+        })
+    )
 }
 
 fn program_clauses_for_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
@@ -167,8 +222,11 @@ fn program_clauses_for_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId
     let where_clauses = tcx.predicates_of(def_id).predicates.lower();
 
      // `Implemented(A0: Trait<A1..An>) :- WC`
-    let clause = Clause::Implies(where_clauses, trait_pred);
-    Lrc::new(vec![clause])
+    let clause = ProgramClause {
+        goal: trait_pred,
+        hypotheses: where_clauses.into_iter().map(|wc| wc.into()).collect()
+    };
+    Lrc::new(vec![Clause::ForAll(ty::Binder::dummy(clause))])
 }
 
 pub fn dump_program_clauses<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
@@ -184,14 +242,19 @@ struct ClauseDumper<'a, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
 }
 
-impl <'a, 'tcx> ClauseDumper<'a, 'tcx > {
+impl<'a, 'tcx> ClauseDumper<'a, 'tcx > {
     fn process_attrs(&mut self, node_id: ast::NodeId, attrs: &[ast::Attribute]) {
         let def_id = self.tcx.hir.local_def_id(node_id);
         for attr in attrs {
             if attr.check_name("rustc_dump_program_clauses") {
                 let clauses = self.tcx.program_clauses_for(def_id);
                 for clause in &*clauses {
-                    self.tcx.sess.struct_span_err(attr.span, &format!("{}", clause)).emit();
+                    // Skip the top-level binder for a less verbose output
+                    let program_clause = match clause {
+                        Clause::Implies(program_clause) => program_clause,
+                        Clause::ForAll(program_clause) => program_clause.skip_binder(),
+                    };
+                    self.tcx.sess.struct_span_err(attr.span, &format!("{}", program_clause)).emit();
                 }
             }
         }
index 6ba3ad879b7d5555435795600df72ba4024639ac..4ffc71ba4703eb268d34619852877f5e47206d0e 100644 (file)
@@ -694,7 +694,7 @@ fn link_natively(sess: &Session,
     loop {
         i += 1;
         prog = time(sess, "running linker", || {
-            exec_linker(sess, &mut cmd, tmpdir)
+            exec_linker(sess, &mut cmd, out_filename, tmpdir)
         });
         let output = match prog {
             Ok(ref output) => output,
@@ -822,7 +822,7 @@ fn escape_string(s: &[u8]) -> String {
     }
 }
 
-fn exec_linker(sess: &Session, cmd: &mut Command, tmpdir: &Path)
+fn exec_linker(sess: &Session, cmd: &mut Command, out_filename: &Path, tmpdir: &Path)
     -> io::Result<Output>
 {
     // When attempting to spawn the linker we run a risk of blowing out the
@@ -836,7 +836,11 @@ fn exec_linker(sess: &Session, cmd: &mut Command, tmpdir: &Path)
     // there instead of looking at the command line.
     if !cmd.very_likely_to_exceed_some_spawn_limit() {
         match cmd.command().stdout(Stdio::piped()).stderr(Stdio::piped()).spawn() {
-            Ok(child) => return child.wait_with_output(),
+            Ok(child) => {
+                let output = child.wait_with_output();
+                flush_linked_file(&output, out_filename)?;
+                return output;
+            }
             Err(ref e) if command_line_too_big(e) => {
                 info!("command line to linker was too big: {}", e);
             }
@@ -870,7 +874,37 @@ fn exec_linker(sess: &Session, cmd: &mut Command, tmpdir: &Path)
     fs::write(&file, &bytes)?;
     cmd2.arg(format!("@{}", file.display()));
     info!("invoking linker {:?}", cmd2);
-    return cmd2.output();
+    let output = cmd2.output();
+    flush_linked_file(&output, out_filename)?;
+    return output;
+
+    #[cfg(unix)]
+    fn flush_linked_file(_: &io::Result<Output>, _: &Path) -> io::Result<()> {
+        Ok(())
+    }
+
+    #[cfg(windows)]
+    fn flush_linked_file(command_output: &io::Result<Output>, out_filename: &Path)
+        -> io::Result<()>
+    {
+        // On Windows, under high I/O load, output buffers are sometimes not flushed,
+        // even long after process exit, causing nasty, non-reproducible output bugs.
+        //
+        // File::sync_all() calls FlushFileBuffers() down the line, which solves the problem.
+        //
+        // А full writeup of the original Chrome bug can be found at
+        // randomascii.wordpress.com/2018/02/25/compiler-bug-linker-bug-windows-kernel-bug/amp
+
+        if let &Ok(ref out) = command_output {
+            if out.status.success() {
+                if let Ok(of) = fs::OpenOptions::new().write(true).open(out_filename) {
+                    of.sync_all()?;
+                }
+            }
+        }
+
+        Ok(())
+    }
 
     #[cfg(unix)]
     fn command_line_too_big(err: &io::Error) -> bool {
index d205e6ca4eda6ed5b78e5afd8cfeeab40af71b07..acd2a7657307c4db2d1a6d2d69c1a53336bcb06c 100644 (file)
 use monomorphize::Instance;
 use rustc::hir;
 use rustc::hir::TransFnAttrFlags;
-use rustc::hir::def_id::CrateNum;
-use rustc::hir::def_id::{DefId, LOCAL_CRATE};
+use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE, CRATE_DEF_INDEX};
+use rustc::ich::Fingerprint;
 use rustc::middle::exported_symbols::{SymbolExportLevel, ExportedSymbol, metadata_symbol_name};
 use rustc::session::config;
 use rustc::ty::{TyCtxt, SymbolName};
 use rustc::ty::maps::Providers;
-use rustc::util::nodemap::{FxHashMap, DefIdSet};
+use rustc::ty::subst::Substs;
+use rustc::util::nodemap::{FxHashMap, DefIdMap};
 use rustc_allocator::ALLOCATOR_METHODS;
+use rustc_data_structures::indexed_vec::IndexVec;
+use std::collections::hash_map::Entry::*;
 
 pub type ExportedSymbols = FxHashMap<
     CrateNum,
@@ -56,51 +59,12 @@ pub fn crates_export_threshold(crate_types: &[config::CrateType])
 
 fn reachable_non_generics_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                              cnum: CrateNum)
-                                             -> Lrc<DefIdSet>
+                                             -> Lrc<DefIdMap<SymbolExportLevel>>
 {
     assert_eq!(cnum, LOCAL_CRATE);
 
     if !tcx.sess.opts.output_types.should_trans() {
-        return Lrc::new(DefIdSet())
-    }
-
-    let export_threshold = threshold(tcx);
-
-    // We already collect all potentially reachable non-generic items for
-    // `exported_symbols`. Now we just filter them down to what is actually
-    // exported for the given crate we are compiling.
-    let reachable_non_generics = tcx
-        .exported_symbols(LOCAL_CRATE)
-        .iter()
-        .filter_map(|&(exported_symbol, level)| {
-            if let ExportedSymbol::NonGeneric(def_id) = exported_symbol {
-                if level.is_below_threshold(export_threshold) {
-                    return Some(def_id)
-                }
-            }
-
-            None
-        })
-        .collect();
-
-    Lrc::new(reachable_non_generics)
-}
-
-fn is_reachable_non_generic_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                               def_id: DefId)
-                                               -> bool {
-    tcx.reachable_non_generics(def_id.krate).contains(&def_id)
-}
-
-fn exported_symbols_provider_local<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                             cnum: CrateNum)
-                                             -> Arc<Vec<(ExportedSymbol,
-                                                         SymbolExportLevel)>>
-{
-    assert_eq!(cnum, LOCAL_CRATE);
-
-    if !tcx.sess.opts.output_types.should_trans() {
-        return Arc::new(vec![])
+        return Lrc::new(DefIdMap())
     }
 
     // Check to see if this crate is a "special runtime crate". These
@@ -113,7 +77,7 @@ fn exported_symbols_provider_local<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let special_runtime_crate = tcx.is_panic_runtime(LOCAL_CRATE) ||
         tcx.is_compiler_builtins(LOCAL_CRATE);
 
-    let reachable_non_generics: DefIdSet = tcx.reachable_set(LOCAL_CRATE).0
+    let mut reachable_non_generics: DefIdMap<_> = tcx.reachable_set(LOCAL_CRATE).0
         .iter()
         .filter_map(|&node_id| {
             // We want to ignore some FFI functions that are not exposed from
@@ -166,11 +130,7 @@ fn exported_symbols_provider_local<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 _ => None
             }
         })
-        .collect();
-
-    let mut symbols: Vec<_> = reachable_non_generics
-        .iter()
-        .map(|&def_id| {
+        .map(|def_id| {
             let export_level = if special_runtime_crate {
                 let name = tcx.symbol_name(Instance::mono(tcx, def_id));
                 // We can probably do better here by just ensuring that
@@ -188,24 +148,63 @@ fn exported_symbols_provider_local<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                     SymbolExportLevel::Rust
                 }
             } else {
-                tcx.symbol_export_level(def_id)
+                symbol_export_level(tcx, def_id)
             };
             debug!("EXPORTED SYMBOL (local): {} ({:?})",
                    tcx.symbol_name(Instance::mono(tcx, def_id)),
                    export_level);
-            (ExportedSymbol::NonGeneric(def_id), export_level)
+            (def_id, export_level)
         })
         .collect();
 
     if let Some(id) = tcx.sess.derive_registrar_fn.get() {
         let def_id = tcx.hir.local_def_id(id);
-        symbols.push((ExportedSymbol::NonGeneric(def_id), SymbolExportLevel::C));
+        reachable_non_generics.insert(def_id, SymbolExportLevel::C);
     }
 
     if let Some(id) = tcx.sess.plugin_registrar_fn.get() {
         let def_id = tcx.hir.local_def_id(id);
-        symbols.push((ExportedSymbol::NonGeneric(def_id), SymbolExportLevel::C));
+        reachable_non_generics.insert(def_id, SymbolExportLevel::C);
+    }
+
+    Lrc::new(reachable_non_generics)
+}
+
+fn is_reachable_non_generic_provider_local<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                                     def_id: DefId)
+                                                     -> bool {
+    let export_threshold = threshold(tcx);
+
+    if let Some(&level) = tcx.reachable_non_generics(def_id.krate).get(&def_id) {
+        level.is_below_threshold(export_threshold)
+    } else {
+        false
     }
+}
+
+fn is_reachable_non_generic_provider_extern<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                                      def_id: DefId)
+                                                      -> bool {
+    tcx.reachable_non_generics(def_id.krate).contains_key(&def_id)
+}
+
+fn exported_symbols_provider_local<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                             cnum: CrateNum)
+                                             -> Arc<Vec<(ExportedSymbol<'tcx>,
+                                                         SymbolExportLevel)>>
+{
+    assert_eq!(cnum, LOCAL_CRATE);
+
+    if !tcx.sess.opts.output_types.should_trans() {
+        return Arc::new(vec![])
+    }
+
+    let mut symbols: Vec<_> = tcx.reachable_non_generics(LOCAL_CRATE)
+                                 .iter()
+                                 .map(|(&def_id, &level)| {
+                                    (ExportedSymbol::NonGeneric(def_id), level)
+                                 })
+                                 .collect();
 
     if let Some(_) = *tcx.sess.entry_fn.borrow() {
         let symbol_name = "main".to_string();
@@ -244,6 +243,46 @@ fn exported_symbols_provider_local<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         symbols.push((exported_symbol, SymbolExportLevel::Rust));
     }
 
+    if tcx.share_generics() && tcx.local_crate_exports_generics() {
+        use rustc::mir::mono::{Linkage, Visibility, MonoItem};
+        use rustc::ty::InstanceDef;
+
+        // Normally, we require that shared monomorphizations are not hidden,
+        // because if we want to re-use a monomorphization from a Rust dylib, it
+        // needs to be exported.
+        // However, on platforms that don't allow for Rust dylibs, having
+        // external linkage is enough for monomorphization to be linked to.
+        let need_visibility = tcx.sess.target.target.options.dynamic_linking &&
+                              !tcx.sess.target.target.options.only_cdylib;
+
+        let (_, cgus) = tcx.collect_and_partition_translation_items(LOCAL_CRATE);
+
+        for (mono_item, &(linkage, visibility)) in cgus.iter()
+                                                       .flat_map(|cgu| cgu.items().iter()) {
+            if linkage != Linkage::External {
+                // We can only re-use things with external linkage, otherwise
+                // we'll get a linker error
+                continue
+            }
+
+            if need_visibility && visibility == Visibility::Hidden {
+                // If we potentially share things from Rust dylibs, they must
+                // not be hidden
+                continue
+            }
+
+            if let &MonoItem::Fn(Instance {
+                def: InstanceDef::Item(def_id),
+                substs,
+            }) = mono_item {
+                if substs.types().next().is_some() {
+                    symbols.push((ExportedSymbol::Generic(def_id, substs),
+                                  SymbolExportLevel::Rust));
+                }
+            }
+        }
+    }
+
     // Sort so we get a stable incr. comp. hash.
     symbols.sort_unstable_by(|&(ref symbol1, ..), &(ref symbol2, ..)| {
         symbol1.compare_stable(tcx, symbol2)
@@ -252,19 +291,93 @@ fn exported_symbols_provider_local<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     Arc::new(symbols)
 }
 
+fn upstream_monomorphizations_provider<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    cnum: CrateNum)
+    -> Lrc<DefIdMap<Lrc<FxHashMap<&'tcx Substs<'tcx>, CrateNum>>>>
+{
+    debug_assert!(cnum == LOCAL_CRATE);
+
+    let cnums = tcx.all_crate_nums(LOCAL_CRATE);
+
+    let mut instances = DefIdMap();
+
+    let cnum_stable_ids: IndexVec<CrateNum, Fingerprint> = {
+        let mut cnum_stable_ids = IndexVec::from_elem_n(Fingerprint::ZERO,
+                                                        cnums.len() + 1);
+
+        for &cnum in cnums.iter() {
+            cnum_stable_ids[cnum] = tcx.def_path_hash(DefId {
+                krate: cnum,
+                index: CRATE_DEF_INDEX,
+            }).0;
+        }
+
+        cnum_stable_ids
+    };
+
+    for &cnum in cnums.iter() {
+        for &(ref exported_symbol, _) in tcx.exported_symbols(cnum).iter() {
+            if let &ExportedSymbol::Generic(def_id, substs) = exported_symbol {
+                let substs_map = instances.entry(def_id)
+                                          .or_insert_with(|| FxHashMap());
+
+                match substs_map.entry(substs) {
+                    Occupied(mut e) => {
+                        // If there are multiple monomorphizations available,
+                        // we select one deterministically.
+                        let other_cnum = *e.get();
+                        if cnum_stable_ids[other_cnum] > cnum_stable_ids[cnum] {
+                            e.insert(cnum);
+                        }
+                    }
+                    Vacant(e) => {
+                        e.insert(cnum);
+                    }
+                }
+            }
+        }
+    }
+
+    Lrc::new(instances.into_iter()
+                      .map(|(key, value)| (key, Lrc::new(value)))
+                      .collect())
+}
+
+fn upstream_monomorphizations_for_provider<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    def_id: DefId)
+    -> Option<Lrc<FxHashMap<&'tcx Substs<'tcx>, CrateNum>>>
+{
+    debug_assert!(!def_id.is_local());
+    tcx.upstream_monomorphizations(LOCAL_CRATE)
+       .get(&def_id)
+       .cloned()
+}
+
+fn is_unreachable_local_definition_provider(tcx: TyCtxt, def_id: DefId) -> bool {
+    if let Some(node_id) = tcx.hir.as_local_node_id(def_id) {
+        !tcx.reachable_set(LOCAL_CRATE).0.contains(&node_id)
+    } else {
+        bug!("is_unreachable_local_definition called with non-local DefId: {:?}",
+              def_id)
+    }
+}
+
 pub fn provide(providers: &mut Providers) {
     providers.reachable_non_generics = reachable_non_generics_provider;
-    providers.is_reachable_non_generic = is_reachable_non_generic_provider;
+    providers.is_reachable_non_generic = is_reachable_non_generic_provider_local;
     providers.exported_symbols = exported_symbols_provider_local;
-    providers.symbol_export_level = symbol_export_level_provider;
+    providers.upstream_monomorphizations = upstream_monomorphizations_provider;
+    providers.is_unreachable_local_definition = is_unreachable_local_definition_provider;
 }
 
 pub fn provide_extern(providers: &mut Providers) {
-    providers.is_reachable_non_generic = is_reachable_non_generic_provider;
-    providers.symbol_export_level = symbol_export_level_provider;
+    providers.is_reachable_non_generic = is_reachable_non_generic_provider_extern;
+    providers.upstream_monomorphizations_for = upstream_monomorphizations_for_provider;
 }
 
-fn symbol_export_level_provider(tcx: TyCtxt, sym_def_id: DefId) -> SymbolExportLevel {
+fn symbol_export_level(tcx: TyCtxt, sym_def_id: DefId) -> SymbolExportLevel {
     // We export anything that's not mangled at the "C" layer as it probably has
     // to do with ABI concerns. We do not, however, apply such treatment to
     // special symbols in the standard library for various plumbing between
index fc699f7569f1c250ce7238c023dd4946384b4ebe..6c7565764119cae8d4150178e6b4a7f2cfd856bc 100644 (file)
@@ -1035,7 +1035,7 @@ pub fn start_async_translation(tcx: TyCtxt,
         crate_info,
 
         time_graph,
-        coordinator_send: tcx.tx_to_llvm_workers.clone(),
+        coordinator_send: tcx.tx_to_llvm_workers.lock().clone(),
         trans_worker_receive,
         shared_emitter_main,
         future: coordinator_thread,
@@ -1428,7 +1428,7 @@ fn start_executing_work(tcx: TyCtxt,
                         metadata_config: Arc<ModuleConfig>,
                         allocator_config: Arc<ModuleConfig>)
                         -> thread::JoinHandle<Result<CompiledModules, ()>> {
-    let coordinator_send = tcx.tx_to_llvm_workers.clone();
+    let coordinator_send = tcx.tx_to_llvm_workers.lock().clone();
     let sess = tcx.sess;
 
     // Compute the set of symbols we need to retain when doing LTO (if we need to)
@@ -2340,7 +2340,7 @@ pub(crate) fn submit_translated_module_to_llvm(tcx: TyCtxt,
                                                mtrans: ModuleTranslation,
                                                cost: u64) {
     let llvm_work_item = WorkItem::Optimize(mtrans);
-    drop(tcx.tx_to_llvm_workers.send(Box::new(Message::TranslationDone {
+    drop(tcx.tx_to_llvm_workers.lock().send(Box::new(Message::TranslationDone {
         llvm_work_item,
         cost,
     })));
index 7ab3499ead3696623d262d0c7608f028ca4f928d..0329264a3125f3467ad30e31e5e509fef7c11d23 100644 (file)
@@ -36,6 +36,7 @@
 use metadata;
 use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use rustc::middle::lang_items::StartFnLangItem;
+use rustc::middle::weak_lang_items;
 use rustc::mir::mono::{Linkage, Visibility, Stats};
 use rustc::middle::cstore::{EncodedMetadata};
 use rustc::ty::{self, Ty, TyCtxt};
@@ -82,7 +83,6 @@
 use std::sync::Arc;
 use std::time::{Instant, Duration};
 use std::{i32, usize};
-use std::iter;
 use std::sync::mpsc;
 use syntax_pos::Span;
 use syntax_pos::symbol::InternedString;
@@ -553,7 +553,9 @@ fn create_entry_fn<'cx>(cx: &'cx CodegenCx,
         // late-bound regions, since late-bound
         // regions must appear in the argument
         // listing.
-        let main_ret_ty = main_ret_ty.no_late_bound_regions().unwrap();
+        let main_ret_ty = cx.tcx.erase_regions(
+            &main_ret_ty.no_late_bound_regions().unwrap(),
+        );
 
         if declare::get_defined_value(cx, "main").is_some() {
             // FIXME: We should be smart and show a better diagnostic here.
@@ -580,8 +582,11 @@ fn create_entry_fn<'cx>(cx: &'cx CodegenCx,
 
         let (start_fn, args) = if use_start_lang_item {
             let start_def_id = cx.tcx.require_lang_item(StartFnLangItem);
-            let start_fn = callee::resolve_and_get_fn(cx, start_def_id, cx.tcx.mk_substs(
-                iter::once(Kind::from(main_ret_ty))));
+            let start_fn = callee::resolve_and_get_fn(
+                cx,
+                start_def_id,
+                cx.tcx.intern_substs(&[Kind::from(main_ret_ty)]),
+            );
             (start_fn, vec![bx.pointercast(rust_main, Type::i8p(cx).ptr_to()),
                             arg_argc, arg_argv])
         } else {
@@ -1137,6 +1142,13 @@ pub fn new(tcx: TyCtxt) -> CrateInfo {
                     info.lang_item_to_crate.insert(item, id.krate);
                 }
             }
+
+            // No need to look for lang items that are whitelisted and don't
+            // actually need to exist.
+            let missing = missing.iter()
+                .cloned()
+                .filter(|&l| !weak_lang_items::whitelisted(tcx, l))
+                .collect();
             info.missing_lang_items.insert(cnum, missing);
         }
 
index 1dcf349e23bd882028b1cd37a63f0828e48c1712..2c503bdab30a9b68745c2641635c3be58bfa2f4a 100644 (file)
@@ -118,44 +118,84 @@ pub fn get_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
         // This is sort of subtle. Inside our codegen unit we started off
         // compilation by predefining all our own `TransItem` instances. That
         // is, everything we're translating ourselves is already defined. That
-        // means that anything we're actually translating ourselves will have
-        // hit the above branch in `get_declared_value`. As a result, we're
-        // guaranteed here that we're declaring a symbol that won't get defined,
-        // or in other words we're referencing a foreign value.
+        // means that anything we're actually translating in this codegen unit
+        // will have hit the above branch in `get_declared_value`. As a result,
+        // we're guaranteed here that we're declaring a symbol that won't get
+        // defined, or in other words we're referencing a value from another
+        // codegen unit or even another crate.
         //
         // So because this is a foreign value we blanket apply an external
         // linkage directive because it's coming from a different object file.
         // The visibility here is where it gets tricky. This symbol could be
         // referencing some foreign crate or foreign library (an `extern`
         // block) in which case we want to leave the default visibility. We may
-        // also, though, have multiple codegen units.
-        //
-        // In the situation of multiple codegen units this function may be
-        // referencing a function from another codegen unit. If we're
-        // indeed referencing a symbol in another codegen unit then we're in one
-        // of two cases:
-        //
-        //  * This is a symbol defined in a foreign crate and we're just
-        //    monomorphizing in another codegen unit. In this case this symbols
-        //    is for sure not exported, so both codegen units will be using
-        //    hidden visibility. Hence, we apply a hidden visibility here.
-        //
-        //  * This is a symbol defined in our local crate. If the symbol in the
-        //    other codegen unit is also not exported then like with the foreign
-        //    case we apply a hidden visibility. If the symbol is exported from
-        //    the foreign object file, however, then we leave this at the
-        //    default visibility as we'll just import it naturally.
+        // also, though, have multiple codegen units. It could be a
+        // monomorphization, in which case its expected visibility depends on
+        // whether we are sharing generics or not. The important thing here is
+        // that the visibility we apply to the declaration is the same one that
+        // has been applied to the definition (wherever that definition may be).
         unsafe {
             llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::ExternalLinkage);
 
-            if cx.tcx.is_translated_item(instance_def_id) {
-                if instance_def_id.is_local() {
-                    if !cx.tcx.is_reachable_non_generic(instance_def_id) {
-                        llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden);
+            let is_generic = instance.substs.types().next().is_some();
+
+            if is_generic {
+                // This is a monomorphization. Its expected visibility depends
+                // on whether we are in share-generics mode.
+
+                if cx.tcx.share_generics() {
+                    // We are in share_generics mode.
+
+                    if instance_def_id.is_local() {
+                        // This is a definition from the current crate. If the
+                        // definition is unreachable for downstream crates or
+                        // the current crate does not re-export generics, the
+                        // definition of the instance will have been declared
+                        // as `hidden`.
+                        if cx.tcx.is_unreachable_local_definition(instance_def_id) ||
+                           !cx.tcx.local_crate_exports_generics() {
+                            llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden);
+                        }
+                    } else {
+                        // This is a monomorphization of a generic function
+                        // defined in an upstream crate.
+                        if cx.tcx.upstream_monomorphizations_for(instance_def_id)
+                                 .map(|set| set.contains_key(instance.substs))
+                                 .unwrap_or(false) {
+                            // This is instantiated in another crate. It cannot
+                            // be `hidden`.
+                        } else {
+                            // This is a local instantiation of an upstream definition.
+                            // If the current crate does not re-export it
+                            // (because it is a C library or an executable), it
+                            // will have been declared `hidden`.
+                            if !cx.tcx.local_crate_exports_generics() {
+                                llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden);
+                            }
+                        }
                     }
                 } else {
+                    // When not sharing generics, all instances are in the same
+                    // crate and have hidden visibility
                     llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden);
                 }
+            } else {
+                // This is a non-generic function
+                if cx.tcx.is_translated_item(instance_def_id) {
+                    // This is a function that is instantiated in the local crate
+
+                    if instance_def_id.is_local() {
+                        // This is function that is defined in the local crate.
+                        // If it is not reachable, it is hidden.
+                        if !cx.tcx.is_reachable_non_generic(instance_def_id) {
+                            llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden);
+                        }
+                    } else {
+                        // This is a function from an upstream crate that has
+                        // been instantiated here. These are always hidden.
+                        llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden);
+                    }
+                }
             }
         }
 
index 03e7c63dbca36a87a2c3a2677ebafc441e524847..0b4858c7ab051085350c48fa95fa01d0e05fd5c3 100644 (file)
@@ -83,7 +83,6 @@ pub fn needs_gdb_debug_scripts_section(cx: &CodegenCx) -> bool {
                             "omit_gdb_pretty_printer_section");
 
     !omit_gdb_pretty_printer_section &&
-    !cx.sess().target.target.options.is_like_osx &&
-    !cx.sess().target.target.options.is_like_windows &&
-    cx.sess().opts.debuginfo != NoDebugInfo
+    cx.sess().opts.debuginfo != NoDebugInfo &&
+    cx.sess().target.target.options.emit_debug_gdb_scripts
 }
index 7664c88679e0e2db53e96489e24e467617bed0c3..87d9623e4003849ae98f67628a40d12090fe155d 100644 (file)
@@ -42,7 +42,7 @@
 
 use syntax_pos::{self, Span, Pos};
 use syntax::ast;
-use syntax::symbol::Symbol;
+use syntax::symbol::{Symbol, InternedString};
 use rustc::ty::layout::{self, LayoutOf};
 
 pub mod gdb;
@@ -393,7 +393,7 @@ fn get_template_parameters<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
             substs.types().zip(names).map(|(ty, name)| {
                 let actual_type = cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty);
                 let actual_type_metadata = type_metadata(cx, actual_type, syntax_pos::DUMMY_SP);
-                let name = CString::new(name.as_str().as_bytes()).unwrap();
+                let name = CString::new(name.as_bytes()).unwrap();
                 unsafe {
                     llvm::LLVMRustDIBuilderCreateTemplateTypeParameter(
                         DIB(cx),
@@ -412,7 +412,7 @@ fn get_template_parameters<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
         return create_DIArray(DIB(cx), &template_params[..]);
     }
 
-    fn get_type_parameter_names(cx: &CodegenCx, generics: &ty::Generics) -> Vec<ast::Name> {
+    fn get_type_parameter_names(cx: &CodegenCx, generics: &ty::Generics) -> Vec<InternedString> {
         let mut names = generics.parent.map_or(vec![], |def_id| {
             get_type_parameter_names(cx, cx.tcx.generics_of(def_id))
         });
index e8a1eb3071a2959b7033c6015b1b10cb04ab500b..b9fa5b1353cee6761f560453fa1501d41c633881 100644 (file)
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/")]
-#![deny(warnings)]
 
 #![feature(box_patterns)]
 #![feature(box_syntax)]
 #![feature(custom_attribute)]
 #![feature(fs_read_write)]
 #![allow(unused_attributes)]
-#![cfg_attr(stage0, feature(i128_type, i128))]
-#![cfg_attr(stage0, feature(inclusive_range_syntax))]
 #![feature(libc)]
 #![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
-#![cfg_attr(stage0, feature(slice_patterns))]
-#![cfg_attr(stage0, feature(conservative_impl_trait))]
 #![feature(optin_builtin_traits)]
 #![feature(inclusive_range_fields)]
+#![feature(underscore_lifetimes)]
 
 use rustc::dep_graph::WorkProduct;
 use syntax_pos::symbol::Symbol;
@@ -407,7 +403,7 @@ struct CrateInfo {
     wasm_custom_sections: BTreeMap<String, Vec<u8>>,
     wasm_imports: FxHashMap<String, String>,
     lang_item_to_crate: FxHashMap<LangItem, CrateNum>,
-    missing_lang_items: FxHashMap<CrateNum, Lrc<Vec<LangItem>>>,
+    missing_lang_items: FxHashMap<CrateNum, Vec<LangItem>>,
 }
 
 __build_diagnostic_array! { librustc_trans, DIAGNOSTICS }
index 99de124c6e1ad7fb510965230fda017e7468f255..b297fd9986501946f99efd2e29979133332406fd 100644 (file)
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/")]
-#![deny(warnings)]
 
 #![feature(box_patterns)]
 #![feature(box_syntax)]
 #![feature(custom_attribute)]
 #![allow(unused_attributes)]
-#![cfg_attr(stage0, feature(i128_type))]
 #![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
-#![cfg_attr(stage0, feature(conservative_impl_trait))]
 
 extern crate ar;
 extern crate flate2;
index f9f93730255e6e302409d59615671653c1030cbf..af174f7ce8516f2eef0b536ce3313951a73ee4f4 100644 (file)
 use rustc::middle::weak_lang_items;
 use rustc_mir::monomorphize::Instance;
 use rustc_mir::monomorphize::item::{MonoItem, MonoItemExt, InstantiationMode};
-use rustc::hir::def_id::DefId;
+use rustc::hir::def_id::{DefId, LOCAL_CRATE};
 use rustc::hir::map as hir_map;
 use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
 use rustc::ty::fold::TypeVisitor;
@@ -170,32 +170,45 @@ fn get_symbol_hash<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         assert!(!substs.needs_subst());
         substs.visit_with(&mut hasher);
 
-        let mut avoid_cross_crate_conflicts = false;
-
-        // If this is an instance of a generic function, we also hash in
-        // the ID of the instantiating crate. This avoids symbol conflicts
-        // in case the same instances is emitted in two crates of the same
-        // project.
-        if substs.types().next().is_some() {
-            avoid_cross_crate_conflicts = true;
-        }
-
-        // If we're dealing with an instance of a function that's inlined from
-        // another crate but we're marking it as globally shared to our
-        // compliation (aka we're not making an internal copy in each of our
-        // codegen units) then this symbol may become an exported (but hidden
-        // visibility) symbol. This means that multiple crates may do the same
-        // and we want to be sure to avoid any symbol conflicts here.
-        match MonoItem::Fn(instance).instantiation_mode(tcx) {
-            InstantiationMode::GloballyShared { may_conflict: true } => {
-                avoid_cross_crate_conflicts = true;
-            }
-            _ => {}
-        }
+        let is_generic = substs.types().next().is_some();
+        let avoid_cross_crate_conflicts =
+            // If this is an instance of a generic function, we also hash in
+            // the ID of the instantiating crate. This avoids symbol conflicts
+            // in case the same instances is emitted in two crates of the same
+            // project.
+            is_generic ||
+
+            // If we're dealing with an instance of a function that's inlined from
+            // another crate but we're marking it as globally shared to our
+            // compliation (aka we're not making an internal copy in each of our
+            // codegen units) then this symbol may become an exported (but hidden
+            // visibility) symbol. This means that multiple crates may do the same
+            // and we want to be sure to avoid any symbol conflicts here.
+            match MonoItem::Fn(instance).instantiation_mode(tcx) {
+                InstantiationMode::GloballyShared { may_conflict: true } => true,
+                _ => false,
+            };
 
         if avoid_cross_crate_conflicts {
-            hasher.hash(tcx.crate_name.as_str());
-            hasher.hash(tcx.sess.local_crate_disambiguator());
+            let instantiating_crate = if is_generic {
+                if !def_id.is_local() && tcx.share_generics() {
+                    // If we are re-using a monomorphization from another crate,
+                    // we have to compute the symbol hash accordingly.
+                    let upstream_monomorphizations =
+                        tcx.upstream_monomorphizations_for(def_id);
+
+                    upstream_monomorphizations.and_then(|monos| monos.get(&substs)
+                                                                     .cloned())
+                                              .unwrap_or(LOCAL_CRATE)
+                } else {
+                    LOCAL_CRATE
+                }
+            } else {
+                LOCAL_CRATE
+            };
+
+            hasher.hash(&tcx.original_crate_name(instantiating_crate).as_str()[..]);
+            hasher.hash(&tcx.crate_disambiguator(instantiating_crate));
         }
     });
 
index 7b83985ba673167370da3e40d6fb8dd6d9ba5e2f..8bb67c0bbac5f4e601154bf939c328550d71cba0 100644 (file)
@@ -17,3 +17,4 @@ cmake = "0.1.18"
 alloc = { path = "../liballoc" }
 alloc_system = { path = "../liballoc_system" }
 core = { path = "../libcore" }
+compiler_builtins = { path = "../rustc/compiler_builtins_shim" }
index 0e93277983f8d9fa8400190d15d8c511cd48069b..c4ea543ab36b6d8cd33cf831b7c2db4b8ec7e0e9 100644 (file)
@@ -979,7 +979,7 @@ pub fn def_to_ty(&self,
                 let item_def_id = tcx.hir.local_def_id(item_id);
                 let generics = tcx.generics_of(item_def_id);
                 let index = generics.type_param_to_index[&tcx.hir.local_def_id(node_id)];
-                tcx.mk_param(index, tcx.hir.name(node_id))
+                tcx.mk_param(index, tcx.hir.name(node_id).as_str())
             }
             Def::SelfTy(_, Some(def_id)) => {
                 // Self in impl (we know the concrete type).
index 377e3a891840f786bb36baed7aa71fdf2d6abf9c..da0d4509353b5652e3a9798e45ea3e513cca9ec6 100644 (file)
@@ -76,7 +76,7 @@ fn equate_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 /// and in libcore/intrinsics.rs
 pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                       it: &hir::ForeignItem) {
-    let param = |n| tcx.mk_param(n, Symbol::intern(&format!("P{}", n)));
+    let param = |n| tcx.mk_param(n, Symbol::intern(&format!("P{}", n)).as_str());
     let name = it.name.as_str();
     let (n_tps, inputs, output) = if name.starts_with("atomic_") {
         let split : Vec<&str> = name.split('_').collect();
@@ -341,7 +341,7 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 pub fn check_platform_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                                it: &hir::ForeignItem) {
     let param = |n| {
-        let name = Symbol::intern(&format!("P{}", n));
+        let name = Symbol::intern(&format!("P{}", n)).as_str();
         tcx.mk_param(n, name)
     };
 
index 19a1efc991d2bff5d968cf76545d2ce8438a4774..3705c53a76fa0ab99562d752c741d16fa8c4f59b 100644 (file)
@@ -310,7 +310,7 @@ fn instantiate_method_substs(&mut self,
         // variables.
         let method_generics = self.tcx.generics_of(pick.item.def_id);
         let mut fn_segment = Some((segment, method_generics));
-        self.fcx.check_path_parameter_count(self.span, &mut fn_segment, true);
+        self.fcx.check_path_parameter_count(self.span, &mut fn_segment, true, false);
 
         // Create subst for early-bound lifetime parameters, combining
         // parameters from the type and those from the method.
index f1896be000f630c22d819aef0d6112699da50871..6c18f8d285d0297d8be2c8c73ea6c4c8ab49dc8b 100644 (file)
@@ -2507,7 +2507,7 @@ fn check_argument_types(&self,
                             sp: Span,
                             expr_sp: Span,
                             fn_inputs: &[Ty<'tcx>],
-                            expected_arg_tys: &[Ty<'tcx>],
+                            mut expected_arg_tys: &[Ty<'tcx>],
                             args: &'gcx [hir::Expr],
                             variadic: bool,
                             tuple_arguments: TupleArgumentsFlag,
@@ -2528,19 +2528,14 @@ fn check_argument_types(&self,
             self.register_wf_obligation(fn_input_ty, sp, traits::MiscObligation);
         }
 
-        let mut expected_arg_tys = expected_arg_tys;
         let expected_arg_count = fn_inputs.len();
 
-        fn parameter_count_error<'tcx>(sess: &Session,
-                                       sp: Span,
-                                       expr_sp: Span,
-                                       expected_count: usize,
-                                       arg_count: usize,
-                                       error_code: &str,
-                                       variadic: bool,
-                                       def_span: Option<Span>,
-                                       sugg_unit: bool) {
-            let mut err = sess.struct_span_err_with_code(sp,
+        let param_count_error = |expected_count: usize,
+                                arg_count: usize,
+                                error_code: &str,
+                                variadic: bool,
+                                sugg_unit: bool| {
+            let mut err = tcx.sess.struct_span_err_with_code(sp,
                 &format!("this function takes {}{} parameter{} but {} parameter{} supplied",
                     if variadic {"at least "} else {""},
                     expected_count,
@@ -2549,11 +2544,11 @@ fn parameter_count_error<'tcx>(sess: &Session,
                     if arg_count == 1 {" was"} else {"s were"}),
                 DiagnosticId::Error(error_code.to_owned()));
 
-            if let Some(def_s) = def_span.map(|sp| sess.codemap().def_span(sp)) {
+            if let Some(def_s) = def_span.map(|sp| tcx.sess.codemap().def_span(sp)) {
                 err.span_label(def_s, "defined here");
             }
             if sugg_unit {
-                let sugg_span = sess.codemap().end_point(expr_sp);
+                let sugg_span = tcx.sess.codemap().end_point(expr_sp);
                 // remove closing `)` from the span
                 let sugg_span = sugg_span.shrink_to_lo();
                 err.span_suggestion(
@@ -2567,14 +2562,13 @@ fn parameter_count_error<'tcx>(sess: &Session,
                                             if expected_count == 1 {""} else {"s"}));
             }
             err.emit();
-        }
+        };
 
         let formal_tys = if tuple_arguments == TupleArguments {
             let tuple_type = self.structurally_resolved_type(sp, fn_inputs[0]);
             match tuple_type.sty {
                 ty::TyTuple(arg_types) if arg_types.len() != args.len() => {
-                    parameter_count_error(tcx.sess, sp, expr_sp, arg_types.len(), args.len(),
-                                          "E0057", false, def_span, false);
+                    param_count_error(arg_types.len(), args.len(), "E0057", false, false);
                     expected_arg_tys = &[];
                     self.err_args(args.len())
                 }
@@ -2602,8 +2596,7 @@ fn parameter_count_error<'tcx>(sess: &Session,
             if supplied_arg_count >= expected_arg_count {
                 fn_inputs.to_vec()
             } else {
-                parameter_count_error(tcx.sess, sp, expr_sp, expected_arg_count,
-                                      supplied_arg_count, "E0060", true, def_span, false);
+                param_count_error(expected_arg_count, supplied_arg_count, "E0060", true, false);
                 expected_arg_tys = &[];
                 self.err_args(supplied_arg_count)
             }
@@ -2616,11 +2609,17 @@ fn parameter_count_error<'tcx>(sess: &Session,
             } else {
                 false
             };
-            parameter_count_error(tcx.sess, sp, expr_sp, expected_arg_count,
-                                  supplied_arg_count, "E0061", false, def_span, sugg_unit);
+            param_count_error(expected_arg_count, supplied_arg_count, "E0061", false, sugg_unit);
+
             expected_arg_tys = &[];
             self.err_args(supplied_arg_count)
         };
+        // If there is no expectation, expect formal_tys.
+        let expected_arg_tys = if !expected_arg_tys.is_empty() {
+            expected_arg_tys
+        } else {
+            &formal_tys
+        };
 
         debug!("check_argument_types: formal_tys={:?}",
                formal_tys.iter().map(|t| self.ty_to_string(*t)).collect::<Vec<String>>());
@@ -2672,28 +2671,21 @@ fn parameter_count_error<'tcx>(sess: &Session,
 
                 // The special-cased logic below has three functions:
                 // 1. Provide as good of an expected type as possible.
-                let expected = expected_arg_tys.get(i).map(|&ty| {
-                    Expectation::rvalue_hint(self, ty)
-                });
+                let expected = Expectation::rvalue_hint(self, expected_arg_tys[i]);
 
-                let checked_ty = self.check_expr_with_expectation(
-                    &arg,
-                    expected.unwrap_or(ExpectHasType(formal_ty)));
+                let checked_ty = self.check_expr_with_expectation(&arg, expected);
 
                 // 2. Coerce to the most detailed type that could be coerced
                 //    to, which is `expected_ty` if `rvalue_hint` returns an
                 //    `ExpectHasType(expected_ty)`, or the `formal_ty` otherwise.
-                let coerce_ty = expected.and_then(|e| e.only_has_type(self));
+                let coerce_ty = expected.only_has_type(self).unwrap_or(formal_ty);
                 // We're processing function arguments so we definitely want to use
                 // two-phase borrows.
-                self.demand_coerce(&arg,
-                                   checked_ty,
-                                   coerce_ty.unwrap_or(formal_ty),
-                                   AllowTwoPhase::Yes);
+                self.demand_coerce(&arg, checked_ty, coerce_ty,  AllowTwoPhase::Yes);
 
                 // 3. Relate the expected type and the formal one,
                 //    if the expected type was used for the coercion.
-                coerce_ty.map(|ty| self.demand_suptype(arg.span, formal_ty, ty));
+                self.demand_suptype(arg.span, formal_ty, coerce_ty);
             }
         }
 
@@ -2839,18 +2831,7 @@ fn check_expr_meets_expectation_or_error(&self,
     fn check_expr_coercable_to_type(&self,
                                     expr: &'gcx hir::Expr,
                                     expected: Ty<'tcx>) -> Ty<'tcx> {
-        self.check_expr_coercable_to_type_with_needs(expr, expected, Needs::None)
-    }
-
-    fn check_expr_coercable_to_type_with_needs(&self,
-                                               expr: &'gcx hir::Expr,
-                                               expected: Ty<'tcx>,
-                                               needs: Needs)
-                                               -> Ty<'tcx> {
-        let ty = self.check_expr_with_expectation_and_needs(
-            expr,
-            ExpectHasType(expected),
-            needs);
+        let ty = self.check_expr_with_hint(expr, expected);
         // checks don't need two phase
         self.demand_coerce(expr, ty, expected, AllowTwoPhase::No)
     }
@@ -2900,45 +2881,47 @@ fn expected_inputs_for_expected_output(&self,
                                            formal_args: &[Ty<'tcx>])
                                            -> Vec<Ty<'tcx>> {
         let formal_ret = self.resolve_type_vars_with_obligations(formal_ret);
-        let expected_args = expected_ret.only_has_type(self).and_then(|ret_ty| {
-            self.fudge_regions_if_ok(&RegionVariableOrigin::Coercion(call_span), || {
-                // Attempt to apply a subtyping relationship between the formal
-                // return type (likely containing type variables if the function
-                // is polymorphic) and the expected return type.
-                // No argument expectations are produced if unification fails.
-                let origin = self.misc(call_span);
-                let ures = self.at(&origin, self.param_env).sup(ret_ty, &formal_ret);
-
-                // FIXME(#27336) can't use ? here, Try::from_error doesn't default
-                // to identity so the resulting type is not constrained.
-                match ures {
-                    Ok(ok) => {
-                        // Process any obligations locally as much as
-                        // we can.  We don't care if some things turn
-                        // out unconstrained or ambiguous, as we're
-                        // just trying to get hints here.
-                        self.save_and_restore_in_snapshot_flag(|_| {
-                            let mut fulfill = TraitEngine::new(self.tcx);
-                            for obligation in ok.obligations {
-                                fulfill.register_predicate_obligation(self, obligation);
-                            }
-                            fulfill.select_where_possible(self)
-                        }).map_err(|_| ())?;
-                    }
-                    Err(_) => return Err(()),
+        let ret_ty = match expected_ret.only_has_type(self) {
+            Some(ret) => ret,
+            None => return Vec::new()
+        };
+        let expect_args = self.fudge_regions_if_ok(&RegionVariableOrigin::Coercion(call_span), || {
+            // Attempt to apply a subtyping relationship between the formal
+            // return type (likely containing type variables if the function
+            // is polymorphic) and the expected return type.
+            // No argument expectations are produced if unification fails.
+            let origin = self.misc(call_span);
+            let ures = self.at(&origin, self.param_env).sup(ret_ty, &formal_ret);
+
+            // FIXME(#27336) can't use ? here, Try::from_error doesn't default
+            // to identity so the resulting type is not constrained.
+            match ures {
+                Ok(ok) => {
+                    // Process any obligations locally as much as
+                    // we can.  We don't care if some things turn
+                    // out unconstrained or ambiguous, as we're
+                    // just trying to get hints here.
+                    self.save_and_restore_in_snapshot_flag(|_| {
+                        let mut fulfill = TraitEngine::new(self.tcx);
+                        for obligation in ok.obligations {
+                            fulfill.register_predicate_obligation(self, obligation);
+                        }
+                        fulfill.select_where_possible(self)
+                    }).map_err(|_| ())?;
                 }
+                Err(_) => return Err(()),
+            }
 
-                // Record all the argument types, with the substitutions
-                // produced from the above subtyping unification.
-                Ok(formal_args.iter().map(|ty| {
-                    self.resolve_type_vars_if_possible(ty)
-                }).collect())
-            }).ok()
-        }).unwrap_or(vec![]);
+            // Record all the argument types, with the substitutions
+            // produced from the above subtyping unification.
+            Ok(formal_args.iter().map(|ty| {
+                self.resolve_type_vars_if_possible(ty)
+            }).collect())
+        }).unwrap_or(Vec::new());
         debug!("expected_inputs_for_expected_output(formal={:?} -> {:?}, expected={:?} -> {:?})",
                formal_args, formal_ret,
-               expected_args, expected_ret);
-        expected_args
+               expect_args, expected_ret);
+        expect_args
     }
 
     // Checks a method call.
@@ -3213,10 +3196,8 @@ fn check_tup_field(&self,
                     if !tuple_like { continue }
 
                     debug!("tuple struct named {:?}",  base_t);
-                    let ident = ast::Ident {
-                        name: Symbol::intern(&idx.node.to_string()),
-                        ctxt: idx.span.ctxt().modern(),
-                    };
+                    let ident =
+                        ast::Ident::new(Symbol::intern(&idx.node.to_string()), idx.span.modern());
                     let (ident, def_scope) =
                         self.tcx.adjust_ident(ident, base_def.did, self.body_id);
                     let fields = &base_def.non_enum_variant().fields;
@@ -4809,9 +4790,9 @@ pub fn instantiate_value_path(&self,
         // variables. If the user provided some types, we may still need
         // to add defaults. If the user provided *too many* types, that's
         // a problem.
-        self.check_path_parameter_count(span, &mut type_segment, false);
-        self.check_path_parameter_count(span, &mut fn_segment, false);
-        self.check_impl_trait(span, &mut fn_segment);
+        let supress_mismatch = self.check_impl_trait(span, &mut fn_segment);
+        self.check_path_parameter_count(span, &mut type_segment, false, supress_mismatch);
+        self.check_path_parameter_count(span, &mut fn_segment, false, supress_mismatch);
 
         let (fn_start, has_self) = match (type_segment, fn_segment) {
             (_, Some((_, generics))) => {
@@ -4964,7 +4945,8 @@ fn check_rustc_args_require_const(&self,
     fn check_path_parameter_count(&self,
                                   span: Span,
                                   segment: &mut Option<(&hir::PathSegment, &ty::Generics)>,
-                                  is_method_call: bool) {
+                                  is_method_call: bool,
+                                  supress_mismatch_error: bool) {
         let (lifetimes, types, infer_types, bindings) = segment.map_or(
             (&[][..], &[][..], true, &[][..]),
             |(s, _)| s.parameters.as_ref().map_or(
@@ -5004,7 +4986,7 @@ fn check_path_parameter_count(&self,
             // type parameters, we force instantiate_value_path to
             // use inference variables instead of the provided types.
             *segment = None;
-        } else if types.len() < required_len && !infer_types {
+        } else if types.len() < required_len && !infer_types && !supress_mismatch_error {
             let expected_text = count_type_params(required_len);
             let actual_text = count_type_params(types.len());
             struct_span_err!(self.tcx.sess, span, E0089,
@@ -5071,10 +5053,11 @@ fn check_path_parameter_count(&self,
     /// Report error if there is an explicit type parameter when using `impl Trait`.
     fn check_impl_trait(&self,
                         span: Span,
-                        segment: &mut Option<(&hir::PathSegment, &ty::Generics)>) {
+                        segment: &mut Option<(&hir::PathSegment, &ty::Generics)>)
+                        -> bool {
         use hir::SyntheticTyParamKind::*;
 
-        segment.map(|(path_segment, generics)| {
+        let segment = segment.map(|(path_segment, generics)| {
             let explicit = !path_segment.infer_types;
             let impl_trait = generics.types.iter()
                                            .any(|ty_param| {
@@ -5095,7 +5078,11 @@ fn check_impl_trait(&self,
 
                 err.emit();
             }
+
+            impl_trait
         });
+
+        segment.unwrap_or(false)
     }
 
     // Resolves `typ` by a single level if `typ` is a type variable.
index efc1e2a80cebef6062806fb667d407a750c1da59..4a175248d74a317533d17bbf39cc0cfbac62659c 100644 (file)
@@ -174,9 +174,9 @@ fn check_overloaded_binop(&self,
         // trait matching creating lifetime constraints that are too strict.
         // E.g. adding `&'a T` and `&'b T`, given `&'x T: Add<&'x T>`, will result
         // in `&'a T <: &'x T` and `&'b T <: &'x T`, instead of `'a = 'b = 'x`.
-        let lhs_ty = self.check_expr_coercable_to_type_with_needs(lhs_expr,
-            self.next_ty_var(TypeVariableOrigin::MiscVariable(lhs_expr.span)),
-            lhs_needs);
+        let lhs_ty = self.check_expr_with_needs(lhs_expr, lhs_needs);
+        let fresh_var = self.next_ty_var(TypeVariableOrigin::MiscVariable(lhs_expr.span));
+        let lhs_ty = self.demand_coerce(lhs_expr, lhs_ty, fresh_var,  AllowTwoPhase::No);
         let lhs_ty = self.resolve_type_vars_with_obligations(lhs_ty);
 
         // NB: As we have not yet type-checked the RHS, we don't have the
index 9ed4ab45a1ba7dd19c22d9a5e3ebd95e76107e9f..b5e862fac958a027089e068924fffdf6440e3a31 100644 (file)
@@ -1164,10 +1164,12 @@ fn link_region(&self,
     /// constraint that `'z <= 'a`. Given this setup, let's clarify the
     /// parameters in (roughly) terms of the example:
     ///
+    /// ```plain,ignore (pseudo-Rust)
     ///     A borrow of: `& 'z bk * r` where `r` has type `& 'a bk T`
     ///     borrow_region   ^~                 ref_region    ^~
     ///     borrow_kind        ^~               ref_kind        ^~
     ///     ref_cmt                 ^
+    /// ```
     ///
     /// Here `bk` stands for some borrow-kind (e.g., `mut`, `uniq`, etc).
     ///
index 406ff9463a03c314f4da185ca068dd0ae2c24a37..6348f3861770ff0065104b1ab6299ea7e8f41a51 100644 (file)
@@ -423,12 +423,18 @@ fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
                     _ => t.super_visit_with(self)
                 }
             }
+
+            fn visit_region(&mut self, _: ty::Region<'tcx>) -> bool {
+                true
+            }
         }
         let mut param_count = CountParams { params: FxHashSet() };
-        pred.visit_with(&mut param_count);
+        let has_region = pred.visit_with(&mut param_count);
         let substituted_pred = pred.subst(fcx.tcx, substs);
-        // Don't check non-defaulted params, dependent defaults or preds with multiple params.
-        if substituted_pred.references_error() || param_count.params.len() > 1 {
+        // Don't check non-defaulted params, dependent defaults (including lifetimes)
+        // or preds with multiple params.
+        if substituted_pred.references_error() || param_count.params.len() > 1
+            || has_region {
             continue;
         }
         // Avoid duplication of predicates that contain no parameters, for example.
@@ -649,7 +655,7 @@ fn reject_shadowing_type_parameters(tcx: TyCtxt, def_id: DefId) {
             // local so it should be okay to just unwrap everything.
             let trait_def_id = impl_params[&method_param.name];
             let trait_decl_span = tcx.def_span(trait_def_id);
-            error_194(tcx, type_span, trait_decl_span, method_param.name);
+            error_194(tcx, type_span, trait_decl_span, &method_param.name[..]);
         }
     }
 }
@@ -753,7 +759,7 @@ fn error_392<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, span: Span, param_name: ast:
     err
 }
 
-fn error_194(tcx: TyCtxt, span: Span, trait_decl_span: Span, name: ast::Name) {
+fn error_194(tcx: TyCtxt, span: Span, trait_decl_span: Span, name: &str) {
     struct_span_err!(tcx.sess, span, E0194,
               "type parameter `{}` shadows another type parameter of the same name",
               name)
index 59156bf0dfeaa0c5a874f381fb41eeb2b8f7f884..a4f820d1fdcf9553488b85b9da013929f9307f47 100644 (file)
@@ -241,7 +241,7 @@ fn type_param_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let param_owner_def_id = tcx.hir.local_def_id(param_owner);
     let generics = tcx.generics_of(param_owner_def_id);
     let index = generics.type_param_to_index[&def_id];
-    let ty = tcx.mk_param(index, tcx.hir.ty_param_name(param_id));
+    let ty = tcx.mk_param(index, tcx.hir.ty_param_name(param_id).as_str());
 
     // Don't look for bounds where the type parameter isn't in scope.
     let parent = if item_def_id == param_owner_def_id {
@@ -839,7 +839,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
                     opt_self = Some(ty::TypeParameterDef {
                         index: 0,
-                        name: keywords::SelfType.name(),
+                        name: keywords::SelfType.name().as_str(),
                         def_id: tcx.hir.local_def_id(param_id),
                         has_default: false,
                         object_lifetime_default: rl::Set1::Empty,
@@ -915,7 +915,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
         ty::TypeParameterDef {
             index: type_start + i as u32,
-            name: p.name,
+            name: p.name.as_str(),
             def_id: tcx.hir.local_def_id(p.id),
             has_default: p.default.is_some(),
             object_lifetime_default:
@@ -934,7 +934,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         // add a dummy parameter for the closure kind
         types.push(ty::TypeParameterDef {
             index: type_start,
-            name: Symbol::intern("<closure_kind>"),
+            name: Symbol::intern("<closure_kind>").as_str(),
             def_id,
             has_default: false,
             object_lifetime_default: rl::Set1::Empty,
@@ -945,7 +945,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         // add a dummy parameter for the closure signature
         types.push(ty::TypeParameterDef {
             index: type_start + 1,
-            name: Symbol::intern("<closure_signature>"),
+            name: Symbol::intern("<closure_signature>").as_str(),
             def_id,
             has_default: false,
             object_lifetime_default: rl::Set1::Empty,
@@ -956,7 +956,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         tcx.with_freevars(node_id, |fv| {
             types.extend(fv.iter().zip(2..).map(|(_, i)| ty::TypeParameterDef {
                 index: type_start + i,
-                name: Symbol::intern("<upvar>"),
+                name: Symbol::intern("<upvar>").as_str(),
                 def_id,
                 has_default: false,
                 object_lifetime_default: rl::Set1::Empty,
@@ -1436,7 +1436,7 @@ fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // Collect the predicates that were written inline by the user on each
     // type parameter (e.g., `<T:Foo>`).
     for param in ast_generics.ty_params() {
-        let param_ty = ty::ParamTy::new(index, param.name).to_ty(tcx);
+        let param_ty = ty::ParamTy::new(index, param.name.as_str()).to_ty(tcx);
         index += 1;
 
         let bounds = compute_bounds(&icx,
index 99726bb65f38557ee75e852833c9b3d0d36db4ec..79d7c8e72821047794c2617e280d0e17413b0df0 100644 (file)
@@ -3784,7 +3784,6 @@ struct Simba {
 Erroneous code example:
 
 ```compile_fail,E0569
-#![feature(generic_param_attrs)]
 #![feature(dropck_eyepatch)]
 
 struct Foo<X>(X);
index 1eed1bf4b71fb58e19496d11e9a15ea555210eba..faf3ccb1133adcb89c9a18a168d0120f8aa5a228 100644 (file)
 ///
 /// Example:
 ///
-/// ```
+/// ```rust,ignore (pseudo-Rust)
 /// impl<T> Trait<Foo> for Bar { ... }
-///      ^ T does not appear in `Foo` or `Bar`, error!
+/// //   ^ T does not appear in `Foo` or `Bar`, error!
 ///
 /// impl<T> Trait<Foo<T>> for Bar { ... }
-///      ^ T appears in `Foo<T>`, ok.
+/// //   ^ T appears in `Foo<T>`, ok.
 ///
 /// impl<T> Trait<Foo> for Bar where Bar: Iterator<Item=T> { ... }
-///      ^ T is bound to `<Bar as Iterator>::Item`, ok.
+/// //   ^ T is bound to `<Bar as Iterator>::Item`, ok.
 ///
 /// impl<'a> Trait<Foo> for Bar { }
-///      ^ 'a is unused, but for back-compat we allow it
+/// //   ^ 'a is unused, but for back-compat we allow it
 ///
 /// impl<'a> Trait<Foo> for Bar { type X = &'a i32; }
-///      ^ 'a is unused and appears in assoc type, error
+/// //   ^ 'a is unused and appears in assoc type, error
 /// ```
 pub fn impl_wf_check<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
     // We will tag this as part of the WF check -- logically, it is,
index 44ecb32a0bf9b1fcbb453a191a962beb9b5e1992..eb9a26855c64917e1c19016926c7857d8adf44cf 100644 (file)
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/")]
-#![deny(warnings)]
 
 #![allow(non_camel_case_types)]
 
-#![cfg_attr(stage0, feature(advanced_slice_patterns))]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
-#![cfg_attr(stage0, feature(conservative_impl_trait))]
-#![cfg_attr(stage0, feature(copy_closures, clone_closures))]
 #![feature(crate_visibility_modifier)]
 #![feature(from_ref)]
-#![cfg_attr(stage0, feature(match_default_bindings))]
 #![feature(exhaustive_patterns)]
 #![feature(option_filter)]
 #![feature(quote)]
 #![feature(refcell_replace_swap)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(slice_patterns)]
-#![cfg_attr(stage0, feature(i128_type))]
-#![cfg_attr(stage0, feature(never_type))]
 #![feature(dyn_trait)]
 
 #[macro_use] extern crate log;
index fe4f785aa915ee9de5795d402b89419b9b8f1d68..561d41087221ebd5936968c014d7a2b1209a3cfb 100644 (file)
@@ -171,7 +171,7 @@ fn get_auto_trait_impl_for(
             let mut segments = path.segments.into_vec();
             let last = segments.pop().unwrap();
 
-            let real_name = name.as_ref().map(|n| Symbol::from(n.as_str()));
+            let real_name = name.map(|name| Symbol::intern(&name));
 
             segments.push(hir::PathSegment::new(
                 real_name.unwrap_or(last.name),
@@ -260,7 +260,9 @@ fn ty_param_to_ty(&self, param: ty::TypeParameterDef) -> hir::Ty {
                 P(hir::Path {
                     span: DUMMY_SP,
                     def: Def::TyParam(param.def_id),
-                    segments: HirVec::from_vec(vec![hir::PathSegment::from_name(param.name)]),
+                    segments: HirVec::from_vec(vec![
+                        hir::PathSegment::from_name(Symbol::intern(&param.name))
+                    ]),
                 }),
             )),
             span: DUMMY_SP,
index c228f54217d34c7f583dff93ef4744cf867d942d..7f89b3e6b3a2aad64c6f3a343f8b8e6bfc2d2532 100644 (file)
@@ -67,7 +67,7 @@ fn parse_nested(nested_cfg: &NestedMetaItem) -> Result<Cfg, InvalidCfgError> {
     /// If the content is not properly formatted, it will return an error indicating what and where
     /// the error is.
     pub fn parse(cfg: &MetaItem) -> Result<Cfg, InvalidCfgError> {
-        let name = cfg.name();
+        let name = cfg.ident.name;
         match cfg.node {
             MetaItemKind::Word => Ok(Cfg::Cfg(name, None)),
             MetaItemKind::NameValue(ref lit) => match lit.node {
@@ -562,14 +562,14 @@ fn test_cfg_or() {
     fn test_parse_ok() {
         with_globals(|| {
             let mi = MetaItem {
-                name: Symbol::intern("all"),
+                ident: Ident::from_str("all"),
                 node: MetaItemKind::Word,
                 span: DUMMY_SP,
             };
             assert_eq!(Cfg::parse(&mi), Ok(word_cfg("all")));
 
             let mi = MetaItem {
-                name: Symbol::intern("all"),
+                ident: Ident::from_str("all"),
                 node: MetaItemKind::NameValue(dummy_spanned(LitKind::Str(
                     Symbol::intern("done"),
                     StrStyle::Cooked,
@@ -579,15 +579,15 @@ fn test_parse_ok() {
             assert_eq!(Cfg::parse(&mi), Ok(name_value_cfg("all", "done")));
 
             let mi = MetaItem {
-                name: Symbol::intern("all"),
+                ident: Ident::from_str("all"),
                 node: MetaItemKind::List(vec![
                     dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem {
-                        name: Symbol::intern("a"),
+                        ident: Ident::from_str("a"),
                         node: MetaItemKind::Word,
                         span: DUMMY_SP,
                     })),
                     dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem {
-                        name: Symbol::intern("b"),
+                        ident: Ident::from_str("b"),
                         node: MetaItemKind::Word,
                         span: DUMMY_SP,
                     })),
@@ -597,15 +597,15 @@ fn test_parse_ok() {
             assert_eq!(Cfg::parse(&mi), Ok(word_cfg("a") & word_cfg("b")));
 
             let mi = MetaItem {
-                name: Symbol::intern("any"),
+                ident: Ident::from_str("any"),
                 node: MetaItemKind::List(vec![
                     dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem {
-                        name: Symbol::intern("a"),
+                        ident: Ident::from_str("a"),
                         node: MetaItemKind::Word,
                         span: DUMMY_SP,
                     })),
                     dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem {
-                        name: Symbol::intern("b"),
+                        ident: Ident::from_str("b"),
                         node: MetaItemKind::Word,
                         span: DUMMY_SP,
                     })),
@@ -615,10 +615,10 @@ fn test_parse_ok() {
             assert_eq!(Cfg::parse(&mi), Ok(word_cfg("a") | word_cfg("b")));
 
             let mi = MetaItem {
-                name: Symbol::intern("not"),
+                ident: Ident::from_str("not"),
                 node: MetaItemKind::List(vec![
                     dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem {
-                        name: Symbol::intern("a"),
+                        ident: Ident::from_str("a"),
                         node: MetaItemKind::Word,
                         span: DUMMY_SP,
                     })),
@@ -628,26 +628,26 @@ fn test_parse_ok() {
             assert_eq!(Cfg::parse(&mi), Ok(!word_cfg("a")));
 
             let mi = MetaItem {
-                name: Symbol::intern("not"),
+                ident: Ident::from_str("not"),
                 node: MetaItemKind::List(vec![
                     dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem {
-                        name: Symbol::intern("any"),
+                        ident: Ident::from_str("any"),
                         node: MetaItemKind::List(vec![
                             dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem {
-                                name: Symbol::intern("a"),
+                                ident: Ident::from_str("a"),
                                 node: MetaItemKind::Word,
                                 span: DUMMY_SP,
                             })),
                             dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem {
-                                name: Symbol::intern("all"),
+                                ident: Ident::from_str("all"),
                                 node: MetaItemKind::List(vec![
                                     dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem {
-                                        name: Symbol::intern("b"),
+                                        ident: Ident::from_str("b"),
                                         node: MetaItemKind::Word,
                                         span: DUMMY_SP,
                                     })),
                                     dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem {
-                                        name: Symbol::intern("c"),
+                                        ident: Ident::from_str("c"),
                                         node: MetaItemKind::Word,
                                         span: DUMMY_SP,
                                     })),
@@ -663,20 +663,20 @@ fn test_parse_ok() {
             assert_eq!(Cfg::parse(&mi), Ok(!(word_cfg("a") | (word_cfg("b") & word_cfg("c")))));
 
             let mi = MetaItem {
-                name: Symbol::intern("all"),
+                ident: Ident::from_str("all"),
                 node: MetaItemKind::List(vec![
                     dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem {
-                        name: Symbol::intern("a"),
+                        ident: Ident::from_str("a"),
                         node: MetaItemKind::Word,
                         span: DUMMY_SP,
                     })),
                     dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem {
-                        name: Symbol::intern("b"),
+                        ident: Ident::from_str("b"),
                         node: MetaItemKind::Word,
                         span: DUMMY_SP,
                     })),
                     dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem {
-                        name: Symbol::intern("c"),
+                        ident: Ident::from_str("c"),
                         node: MetaItemKind::Word,
                         span: DUMMY_SP,
                     })),
@@ -691,22 +691,22 @@ fn test_parse_ok() {
     fn test_parse_err() {
         with_globals(|| {
             let mi = MetaItem {
-                name: Symbol::intern("foo"),
+                ident: Ident::from_str("foo"),
                 node: MetaItemKind::NameValue(dummy_spanned(LitKind::Bool(false))),
                 span: DUMMY_SP,
             };
             assert!(Cfg::parse(&mi).is_err());
 
             let mi = MetaItem {
-                name: Symbol::intern("not"),
+                ident: Ident::from_str("not"),
                 node: MetaItemKind::List(vec![
                     dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem {
-                        name: Symbol::intern("a"),
+                        ident: Ident::from_str("a"),
                         node: MetaItemKind::Word,
                         span: DUMMY_SP,
                     })),
                     dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem {
-                        name: Symbol::intern("b"),
+                        ident: Ident::from_str("b"),
                         node: MetaItemKind::Word,
                         span: DUMMY_SP,
                     })),
@@ -716,17 +716,17 @@ fn test_parse_err() {
             assert!(Cfg::parse(&mi).is_err());
 
             let mi = MetaItem {
-                name: Symbol::intern("not"),
+                ident: Ident::from_str("not"),
                 node: MetaItemKind::List(vec![]),
                 span: DUMMY_SP,
             };
             assert!(Cfg::parse(&mi).is_err());
 
             let mi = MetaItem {
-                name: Symbol::intern("foo"),
+                ident: Ident::from_str("foo"),
                 node: MetaItemKind::List(vec![
                     dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem {
-                        name: Symbol::intern("a"),
+                        ident: Ident::from_str("a"),
                         node: MetaItemKind::Word,
                         span: DUMMY_SP,
                     })),
@@ -736,15 +736,15 @@ fn test_parse_err() {
             assert!(Cfg::parse(&mi).is_err());
 
             let mi = MetaItem {
-                name: Symbol::intern("all"),
+                ident: Ident::from_str("all"),
                 node: MetaItemKind::List(vec![
                     dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem {
-                        name: Symbol::intern("foo"),
+                        ident: Ident::from_str("foo"),
                         node: MetaItemKind::List(vec![]),
                         span: DUMMY_SP,
                     })),
                     dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem {
-                        name: Symbol::intern("b"),
+                        ident: Ident::from_str("b"),
                         node: MetaItemKind::Word,
                         span: DUMMY_SP,
                     })),
@@ -754,15 +754,15 @@ fn test_parse_err() {
             assert!(Cfg::parse(&mi).is_err());
 
             let mi = MetaItem {
-                name: Symbol::intern("any"),
+                ident: Ident::from_str("any"),
                 node: MetaItemKind::List(vec![
                     dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem {
-                        name: Symbol::intern("a"),
+                        ident: Ident::from_str("a"),
                         node: MetaItemKind::Word,
                         span: DUMMY_SP,
                     })),
                     dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem {
-                        name: Symbol::intern("foo"),
+                        ident: Ident::from_str("foo"),
                         node: MetaItemKind::List(vec![]),
                         span: DUMMY_SP,
                     })),
@@ -772,10 +772,10 @@ fn test_parse_err() {
             assert!(Cfg::parse(&mi).is_err());
 
             let mi = MetaItem {
-                name: Symbol::intern("not"),
+                ident: Ident::from_str("not"),
                 node: MetaItemKind::List(vec![
                     dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem {
-                        name: Symbol::intern("foo"),
+                        ident: Ident::from_str("foo"),
                         node: MetaItemKind::List(vec![]),
                         span: DUMMY_SP,
                     })),
index 6ada4ccfbddc265e13728ed41c3cf4882ecb3f2c..da8085d84c3f6729d8cda184f862d1a52b20147b 100644 (file)
 
 use syntax;
 use syntax::abi::Abi;
-use syntax::ast::{self, AttrStyle};
+use syntax::ast::{self, AttrStyle, Ident};
 use syntax::attr;
-use syntax::codemap::Spanned;
+use syntax::codemap::{dummy_spanned, Spanned};
 use syntax::feature_gate::UnstableFeatures;
 use syntax::ptr::P;
 use syntax::symbol::keywords;
-use syntax::symbol::Symbol;
+use syntax::symbol::{Symbol, InternedString};
 use syntax_pos::{self, DUMMY_SP, Pos, FileName};
 
 use rustc::middle::const_val::ConstVal;
@@ -840,7 +840,8 @@ pub fn from_ast(diagnostic: &::errors::Handler,
         for attr in attrs.lists("target_feature") {
             if attr.check_name("enable") {
                 if let Some(feat) = attr.value_str() {
-                    let meta = attr::mk_name_value_item_str("target_feature".into(), feat);
+                    let meta = attr::mk_name_value_item_str(Ident::from_str("target_feature"),
+                                                            dummy_spanned(feat));
                     if let Ok(feat_cfg) = Cfg::parse(&meta) {
                         cfg &= feat_cfg;
                     }
@@ -1146,16 +1147,8 @@ fn resolve(cx: &DocContext, path_str: &str, is_val: bool) -> Result<(Def, Option
 fn macro_resolve(cx: &DocContext, path_str: &str) -> Option<Def> {
     use syntax::ext::base::{MacroKind, SyntaxExtension};
     use syntax::ext::hygiene::Mark;
-    let segment = ast::PathSegment {
-        identifier: ast::Ident::from_str(path_str),
-        span: DUMMY_SP,
-        parameters: None,
-    };
-    let path = ast::Path {
-        span: DUMMY_SP,
-        segments: vec![segment],
-    };
-
+    let segment = ast::PathSegment::from_ident(Ident::from_str(path_str));
+    let path = ast::Path { segments: vec![segment], span: DUMMY_SP };
     let mut resolver = cx.resolver.borrow_mut();
     let mark = Mark::root();
     let res = resolver
@@ -1166,7 +1159,7 @@ fn macro_resolve(cx: &DocContext, path_str: &str) -> Option<Def> {
         } else {
             None
         }
-    } else if let Some(def) = resolver.all_macros.get(&path_str.into()) {
+    } else if let Some(def) = resolver.all_macros.get(&Symbol::intern(path_str)) {
         Some(*def)
     } else {
         None
@@ -1794,7 +1787,7 @@ fn clean(&self, cx: &DocContext) -> Generics {
         // predicates field (see rustc_typeck::collect::ty_generics), so remove
         // them.
         let stripped_typarams = gens.types.iter().filter_map(|tp| {
-            if tp.name == keywords::SelfType.name() {
+            if tp.name == keywords::SelfType.name().as_str() {
                 assert_eq!(tp.index, 0);
                 None
             } else {
@@ -3374,6 +3367,12 @@ fn clean(&self, _: &DocContext) -> String {
     }
 }
 
+impl Clean<String> for InternedString {
+    fn clean(&self, _: &DocContext) -> String {
+        self.to_string()
+    }
+}
+
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct Typedef {
     pub type_: Type,
index 8e6dcf8caf48481fb858d0ddd703612341bbb60d..9e2c7bd7ef1ed6fc808192442760279ac88b7a76 100644 (file)
@@ -1087,7 +1087,8 @@ fn emit_source(&mut self, filename: &FileName) -> io::Result<()> {
             href.push_str(component);
             href.push('/');
         });
-        let mut fname = p.file_name().expect("source has no filename")
+        let mut fname = p.file_name()
+                         .expect("source has no filename")
                          .to_os_string();
         fname.push(".html");
         cur.push(&fname);
@@ -1373,6 +1374,135 @@ fn generics(&mut self, generics: &clean::Generics) {
     }
 }
 
+#[derive(Debug, Eq, PartialEq, Hash)]
+struct ItemEntry {
+    url: String,
+    name: String,
+}
+
+impl ItemEntry {
+    fn new(mut url: String, name: String) -> ItemEntry {
+        while url.starts_with('/') {
+            url.remove(0);
+        }
+        ItemEntry {
+            url,
+            name,
+        }
+    }
+}
+
+impl fmt::Display for ItemEntry {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "<a href='{}'>{}</a>", self.url, Escape(&self.name))
+    }
+}
+
+impl PartialOrd for ItemEntry {
+    fn partial_cmp(&self, other: &ItemEntry) -> Option<::std::cmp::Ordering> {
+        Some(self.cmp(other))
+    }
+}
+
+impl Ord for ItemEntry {
+    fn cmp(&self, other: &ItemEntry) -> ::std::cmp::Ordering {
+        self.name.cmp(&other.name)
+    }
+}
+
+#[derive(Debug)]
+struct AllTypes {
+    structs: HashSet<ItemEntry>,
+    enums: HashSet<ItemEntry>,
+    unions: HashSet<ItemEntry>,
+    primitives: HashSet<ItemEntry>,
+    traits: HashSet<ItemEntry>,
+    macros: HashSet<ItemEntry>,
+    functions: HashSet<ItemEntry>,
+    typedefs: HashSet<ItemEntry>,
+    statics: HashSet<ItemEntry>,
+    constants: HashSet<ItemEntry>,
+}
+
+impl AllTypes {
+    fn new() -> AllTypes {
+        AllTypes {
+            structs: HashSet::with_capacity(100),
+            enums: HashSet::with_capacity(100),
+            unions: HashSet::with_capacity(100),
+            primitives: HashSet::with_capacity(26),
+            traits: HashSet::with_capacity(100),
+            macros: HashSet::with_capacity(100),
+            functions: HashSet::with_capacity(100),
+            typedefs: HashSet::with_capacity(100),
+            statics: HashSet::with_capacity(100),
+            constants: HashSet::with_capacity(100),
+        }
+    }
+
+    fn append(&mut self, item_name: String, item_type: &ItemType) {
+        let mut url: Vec<_> = item_name.split("::").skip(1).collect();
+        if let Some(name) = url.pop() {
+            let new_url = format!("{}/{}.{}.html", url.join("/"), item_type, name);
+            url.push(name);
+            let name = url.join("::");
+            match *item_type {
+                ItemType::Struct => self.structs.insert(ItemEntry::new(new_url, name)),
+                ItemType::Enum => self.enums.insert(ItemEntry::new(new_url, name)),
+                ItemType::Union => self.unions.insert(ItemEntry::new(new_url, name)),
+                ItemType::Primitive => self.primitives.insert(ItemEntry::new(new_url, name)),
+                ItemType::Trait => self.traits.insert(ItemEntry::new(new_url, name)),
+                ItemType::Macro => self.macros.insert(ItemEntry::new(new_url, name)),
+                ItemType::Function => self.functions.insert(ItemEntry::new(new_url, name)),
+                ItemType::Typedef => self.typedefs.insert(ItemEntry::new(new_url, name)),
+                ItemType::Static => self.statics.insert(ItemEntry::new(new_url, name)),
+                ItemType::Constant => self.constants.insert(ItemEntry::new(new_url, name)),
+                _ => true,
+            };
+        }
+    }
+}
+
+fn print_entries(f: &mut fmt::Formatter, e: &HashSet<ItemEntry>, title: &str,
+                 class: &str) -> fmt::Result {
+    if !e.is_empty() {
+        let mut e: Vec<&ItemEntry> = e.iter().collect();
+        e.sort();
+        write!(f, "<h3 id='{}'>{}</h3><ul class='{} docblock'>{}</ul>",
+               title,
+               Escape(title),
+               class,
+               e.iter().map(|s| format!("<li>{}</li>", s)).collect::<String>())?;
+    }
+    Ok(())
+}
+
+impl fmt::Display for AllTypes {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f,
+"<h1 class='fqn'>\
+     <span class='in-band'>List of all items</span>\
+     <span class='out-of-band'>\
+         <span id='render-detail'>\
+             <a id=\"toggle-all-docs\" href=\"javascript:void(0)\" title=\"collapse all docs\">\
+                 [<span class='inner'>&#x2212;</span>]\
+             </a>\
+         </span>
+     </span>
+</h1>")?;
+        print_entries(f, &self.structs, "Structs", "structs")?;
+        print_entries(f, &self.enums, "Enums", "enums")?;
+        print_entries(f, &self.unions, "Unions", "unions")?;
+        print_entries(f, &self.primitives, "Primitives", "primitives")?;
+        print_entries(f, &self.traits, "Traits", "traits")?;
+        print_entries(f, &self.macros, "Macros", "macros")?;
+        print_entries(f, &self.functions, "Functions", "functions")?;
+        print_entries(f, &self.typedefs, "Typedefs", "typedefs")?;
+        print_entries(f, &self.statics, "Statics", "statics")?;
+        print_entries(f, &self.constants, "Constants", "constants")
+    }
+}
+
 impl Context {
     /// String representation of how to get back to the root path of the 'doc/'
     /// folder in terms of a relative URL.
@@ -1414,16 +1544,52 @@ fn krate(self, mut krate: clean::Crate) -> Result<(), Error> {
             Some(i) => i,
             None => return Ok(()),
         };
+        let final_file = self.dst.join(&krate.name)
+                                 .join("all.html");
+        let crate_name = krate.name.clone();
         item.name = Some(krate.name);
 
-        // Render the crate documentation
-        let mut work = vec![(self, item)];
+        let mut all = AllTypes::new();
+
+        {
+            // Render the crate documentation
+            let mut work = vec![(self.clone(), item)];
 
-        while let Some((mut cx, item)) = work.pop() {
-            cx.item(item, |cx, item| {
-                work.push((cx.clone(), item))
-            })?
+            while let Some((mut cx, item)) = work.pop() {
+                cx.item(item, &mut all, |cx, item| {
+                    work.push((cx.clone(), item))
+                })?
+            }
+        }
+
+        let mut w = BufWriter::new(try_err!(File::create(&final_file), &final_file));
+        let mut root_path = self.dst.to_str().expect("invalid path").to_owned();
+        if !root_path.ends_with('/') {
+            root_path.push('/');
         }
+        let page = layout::Page {
+            title: "List of all items in this crate",
+            css_class: "mod",
+            root_path: "../",
+            description: "List of all items in this crate",
+            keywords: BASIC_KEYWORDS,
+            resource_suffix: &self.shared.resource_suffix,
+        };
+        let sidebar = if let Some(ref version) = cache().crate_version {
+            format!("<p class='location'>Crate {}</p>\
+                     <div class='block version'>\
+                         <p>Version {}</p>\
+                     </div>\
+                     <a id='all-types' href='index.html'><p>Back to index</p></a>",
+                    crate_name, version)
+        } else {
+            String::new()
+        };
+        try_err!(layout::render(&mut w, &self.shared.layout,
+                                &page, &sidebar, &all,
+                                self.shared.css_file_extension.is_some(),
+                                &self.shared.themes),
+                 &final_file);
         Ok(())
     }
 
@@ -1496,8 +1662,8 @@ fn render_item(&self,
     /// all sub-items which need to be rendered.
     ///
     /// The rendering driver uses this closure to queue up more work.
-    fn item<F>(&mut self, item: clean::Item, mut f: F) -> Result<(), Error> where
-        F: FnMut(&mut Context, clean::Item),
+    fn item<F>(&mut self, item: clean::Item, all: &mut AllTypes, mut f: F) -> Result<(), Error>
+        where F: FnMut(&mut Context, clean::Item),
     {
         // Stripped modules survive the rustdoc passes (i.e. `strip-private`)
         // if they contain impls for public types. These modules can also
@@ -1544,7 +1710,7 @@ fn item<F>(&mut self, item: clean::Item, mut f: F) -> Result<(), Error> where
                 }
 
                 for item in m.items {
-                    f(this,item);
+                    f(this, item);
                 }
 
                 Ok(())
@@ -1562,13 +1728,14 @@ fn item<F>(&mut self, item: clean::Item, mut f: F) -> Result<(), Error> where
                 let mut dst = try_err!(File::create(&joint_dst), &joint_dst);
                 try_err!(dst.write_all(&buf), &joint_dst);
 
+                all.append(full_path(self, &item), &item_type);
                 // Redirect from a sane URL using the namespace to Rustdoc's
                 // URL for the page.
                 let redir_name = format!("{}.{}.html", name, item_type.name_space());
                 let redir_dst = self.dst.join(redir_name);
                 if let Ok(redirect_out) = OpenOptions::new().create_new(true)
-                                                                .write(true)
-                                                                .open(&redir_dst) {
+                                                            .write(true)
+                                                            .open(&redir_dst) {
                     let mut redirect_out = BufWriter::new(redirect_out);
                     try_err!(layout::redirect(&mut redirect_out, file_name), &redir_dst);
                 }
@@ -1730,11 +1897,12 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
                    version)?;
         }
         write!(fmt,
-               r##"<span id='render-detail'>
-                   <a id="toggle-all-docs" href="javascript:void(0)" title="collapse all docs">
-                       [<span class='inner'>&#x2212;</span>]
-                   </a>
-               </span>"##)?;
+               "<span id='render-detail'>\
+                   <a id=\"toggle-all-docs\" href=\"javascript:void(0)\" \
+                      title=\"collapse all docs\">\
+                       [<span class='inner'>&#x2212;</span>]\
+                   </a>\
+               </span>")?;
 
         // Write `src` tag
         //
@@ -2293,9 +2461,9 @@ fn render_implementor(cx: &Context, implementor: &Impl, w: &mut fmt::Formatter,
 }
 
 fn render_impls(cx: &Context, w: &mut fmt::Formatter,
-                traits: Vec<&&Impl>,
+                traits: &[&&Impl],
                 containing_item: &clean::Item) -> Result<(), fmt::Error> {
-    for i in &traits {
+    for i in traits {
         let did = i.trait_did().unwrap();
         let assoc_link = AssocItemLink::GotoSource(did, &i.inner_impl().provided_trait_methods);
         render_impl(w, cx, i, assoc_link,
@@ -2966,7 +3134,7 @@ fn item_enum(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
 }
 
 fn render_attribute(attr: &ast::MetaItem) -> Option<String> {
-    let name = attr.name();
+    let name = attr.ident.name;
 
     if attr.is_word() {
         Some(format!("{}", name))
@@ -3204,14 +3372,22 @@ fn render_assoc_items(w: &mut fmt::Formatter,
             .iter()
             .partition::<Vec<_>, _>(|t| t.inner_impl().synthetic);
 
-        write!(w, "
-            <h2 id='implementations' class='small-section-header'>
-              Trait Implementations<a href='#implementations' class='anchor'></a>
-            </h2>
-            <div id='implementations-list'>
-        ")?;
-        render_impls(cx, w, concrete, containing_item)?;
-        write!(w, "</div>")?;
+        struct RendererStruct<'a, 'b, 'c>(&'a Context, Vec<&'b &'b Impl>, &'c clean::Item);
+
+        impl<'a, 'b, 'c> fmt::Display for RendererStruct<'a, 'b, 'c> {
+            fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+                render_impls(self.0, fmt, &self.1, self.2)
+            }
+        }
+
+        let impls = format!("{}", RendererStruct(cx, concrete, containing_item));
+        if !impls.is_empty() {
+            write!(w, "
+                <h2 id='implementations' class='small-section-header'>
+                  Trait Implementations<a href='#implementations' class='anchor'></a>
+                </h2>
+                <div id='implementations-list'>{}</div>", impls)?;
+        }
 
         if !synthetic.is_empty() {
             write!(w, "
@@ -3220,7 +3396,7 @@ fn render_assoc_items(w: &mut fmt::Formatter,
                 </h2>
                 <div id='synthetic-implementations-list'>
             ")?;
-            render_impls(cx, w, synthetic, containing_item)?;
+            render_impls(cx, w, &synthetic, containing_item)?;
             write!(w, "</div>")?;
         }
     }
@@ -3559,24 +3735,23 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
 
         if it.is_struct() || it.is_trait() || it.is_primitive() || it.is_union()
             || it.is_enum() || it.is_mod() || it.is_typedef() {
-            write!(fmt, "<p class='location'>")?;
-            match it.inner {
-                clean::StructItem(..) => write!(fmt, "Struct ")?,
-                clean::TraitItem(..) => write!(fmt, "Trait ")?,
-                clean::PrimitiveItem(..) => write!(fmt, "Primitive Type ")?,
-                clean::UnionItem(..) => write!(fmt, "Union ")?,
-                clean::EnumItem(..) => write!(fmt, "Enum ")?,
-                clean::TypedefItem(..) => write!(fmt, "Type Definition ")?,
-                clean::ForeignTypeItem => write!(fmt, "Foreign Type ")?,
-                clean::ModuleItem(..) => if it.is_crate() {
-                    write!(fmt, "Crate ")?;
-                } else {
-                    write!(fmt, "Module ")?;
+            write!(fmt, "<p class='location'>{}{}</p>",
+                match it.inner {
+                    clean::StructItem(..) => "Struct ",
+                    clean::TraitItem(..) => "Trait ",
+                    clean::PrimitiveItem(..) => "Primitive Type ",
+                    clean::UnionItem(..) => "Union ",
+                    clean::EnumItem(..) => "Enum ",
+                    clean::TypedefItem(..) => "Type Definition ",
+                    clean::ForeignTypeItem => "Foreign Type ",
+                    clean::ModuleItem(..) => if it.is_crate() {
+                        "Crate "
+                    } else {
+                        "Module "
+                    },
+                    _ => "",
                 },
-                _ => (),
-            }
-            write!(fmt, "{}", it.name.as_ref().unwrap())?;
-            write!(fmt, "</p>")?;
+                it.name.as_ref().unwrap())?;
         }
 
         if it.is_crate() {
@@ -3584,8 +3759,10 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
                 write!(fmt,
                        "<div class='block version'>\
                         <p>Version {}</p>\
-                        </div>",
-                       version)?;
+                        </div>
+                        <a id='all-types' href='all.html'><p>See all {}'s items</p></a>",
+                       version,
+                       it.name.as_ref().unwrap())?;
             }
         }
 
index 3c115e2b8bacfa8e721334c9c3de554760092485..3a3fa833c238ba569da70ade3fa9444ee0dd9ec0 100644 (file)
         };
     }
 
+    function getPageId() {
+        var id = document.location.href.split('#')[1];
+        if (id) {
+            return id.split('?')[0].split('&')[0];
+        }
+        return null;
+    }
+
     function hasClass(elem, className) {
         if (elem && className && elem.className) {
             var elemClass = elem.className;
         }
     }
 
-    function toggleAllDocs() {
+    function toggleAllDocs(pageId) {
         var toggle = document.getElementById("toggle-all-docs");
         if (hasClass(toggle, "will-expand")) {
             updateLocalStorage("rustdoc-collapse", "false");
             toggle.title = "expand all docs";
 
             onEach(document.getElementsByClassName("collapse-toggle"), function(e) {
-                collapseDocs(e, "hide");
+                collapseDocs(e, "hide", pageId);
             });
         }
     }
 
-    function collapseDocs(toggle, mode) {
+    function collapseDocs(toggle, mode, pageId) {
         if (!toggle || !toggle.parentNode) {
             return;
         }
                 }
             }
 
-            var relatedDoc = toggle.parentNode;
+            var parentElem = toggle.parentNode;
+            var relatedDoc = parentElem;
             var docblock = relatedDoc.nextElementSibling;
 
             while (!hasClass(relatedDoc, "impl-items")) {
                 relatedDoc = relatedDoc.nextElementSibling;
             }
 
-            if (!relatedDoc && !hasClass(docblock, "docblock")) {
+            if ((!relatedDoc && !hasClass(docblock, "docblock")) ||
+                (pageId && onEach(relatedDoc.childNodes, function(e) {
+                    return e.id === pageId;
+                }) === true)) {
                 return;
             }
 
         }
     }
 
-    function autoCollapseAllImpls() {
+    function autoCollapseAllImpls(pageId) {
         // Automatically minimize all non-inherent impls
         onEach(document.getElementsByClassName('impl'), function(n) {
             // inherent impl ids are like 'impl' or impl-<number>'
             if (!inherent) {
                 onEach(n.childNodes, function(m) {
                     if (hasClass(m, "collapse-toggle")) {
-                        collapseDocs(m, "hide");
+                        collapseDocs(m, "hide", pageId);
                     }
                 });
             }
         }
     })
 
-    autoCollapseAllImpls();
+    autoCollapseAllImpls(getPageId());
 
     function createToggleWrapper() {
         var span = document.createElement('span');
     };
 
     if (getCurrentValue("rustdoc-collapse") === "true") {
-        toggleAllDocs();
+        toggleAllDocs(getPageId());
     }
 }());
 
index 31a501d24e7dbb728a53f6b453be59dd3d19ab86..4c6c8dcfddafc033ba00137fa46cb416ac7396a1 100644 (file)
@@ -533,6 +533,9 @@ a {
        left: -5px;
 }
 .small-section-header > .anchor {
+       left: -20px;
+}
+.small-section-header > .anchor:not(.field) {
        left: -28px;
 }
 .anchor:before {
@@ -1291,3 +1294,21 @@ kbd {
        font-size: 19px;
        display: block;
 }
+
+#main > ul {
+       padding-left: 10px;
+}
+#main > ul > li {
+       list-style: none;
+}
+#all-types {
+       text-align: center;
+       border: 1px solid;
+       margin: 0 10px;
+       margin-bottom: 10px;
+       display: block;
+       border-radius: 7px;
+}
+#all-types > p {
+       margin: 5px 0;
+}
\ No newline at end of file
index 2f4e203ebc5c2447e19f33ccf82adec4617dd823..4ef8349fa9ce911a8df2858a74f5446c0fa248ad 100644 (file)
@@ -19,10 +19,11 @@ function onEach(arr, func) {
     if (arr && arr.length > 0 && func) {
         for (var i = 0; i < arr.length; i++) {
             if (func(arr[i]) === true) {
-                break;
+                return true;
             }
         }
     }
+    return false;
 }
 
 function updateLocalStorage(name, value) {
index 09776569f80bf8cee1c4ab432fb598a9b43c44c4..93971a205bf35d71d2730370423d1950efbafd11 100644 (file)
@@ -389,3 +389,10 @@ kbd {
                background: #f0f0f0;
        }
 }
+
+#all-types {
+       background-color: #505050;
+}
+#all-types:hover {
+       background-color: #606060;
+}
index 2334a2728554ea66dd8d345264a59e1e03ce843e..e13818b4bd27867fa9bc05f2ec8651378a6f97bd 100644 (file)
@@ -383,3 +383,10 @@ kbd {
                background: #fff;
        }
 }
+
+#all-types {
+       background-color: #fff;
+}
+#all-types:hover {
+       background-color: #f9f9f9;
+}
\ No newline at end of file
index e31390f59e292cead33782f4d7dac0d2cc4ea70d..730f61e0aa66d2efd5adff88fbce1096b859c716 100644 (file)
@@ -12,7 +12,6 @@
        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "https://doc.rust-lang.org/nightly/",
        html_playground_url = "https://play.rust-lang.org/")]
-#![deny(warnings)]
 
 #![feature(ascii_ctype)]
 #![feature(rustc_private)]
@@ -20,7 +19,6 @@
 #![feature(box_syntax)]
 #![feature(fs_read_write)]
 #![feature(set_stdio)]
-#![cfg_attr(stage0, feature(slice_patterns))]
 #![feature(test)]
 #![feature(unicode)]
 #![feature(vec_remove_item)]
index daa8966b104e8d193c22925b9d426872b4d92eb1..f14d4c602d070f58226be672c1db489ec4604275 100644 (file)
@@ -149,6 +149,7 @@ pub fn test(input: &str, cfgs: Vec<String>, libs: SearchPaths, externs: Externs,
 
     let mut opts = TestOptions::default();
     opts.no_crate_inject = true;
+    opts.display_warnings = display_warnings;
     let mut collector = Collector::new(input.to_owned(), cfgs, libs, externs,
                                        true, opts, maybe_sysroot, None,
                                        Some(PathBuf::from(input)),
index ab11b0d62e9f71055dec5ef63071aadd6ab554a3..cb532276c668310b861e6df58dea027ee405c7fe 100644 (file)
 
 #[derive(Clone, Default)]
 pub struct TestOptions {
+    /// Whether to disable the default `extern crate my_crate;` when creating doctests.
     pub no_crate_inject: bool,
+    /// Whether to emit compilation warnings when compiling doctests. Setting this will suppress
+    /// the default `#![allow(unused)]`.
+    pub display_warnings: bool,
+    /// Additional crate-level attributes to add to doctests.
     pub attrs: Vec<String>,
 }
 
@@ -113,7 +118,8 @@ pub fn run(input_path: &Path,
     let crate_name = crate_name.unwrap_or_else(|| {
         ::rustc_trans_utils::link::find_crate_name(None, &hir_forest.krate().attrs, &input)
     });
-    let opts = scrape_test_config(hir_forest.krate());
+    let mut opts = scrape_test_config(hir_forest.krate());
+    opts.display_warnings |= display_warnings;
     let mut collector = Collector::new(crate_name,
                                        cfgs,
                                        libs,
@@ -153,6 +159,7 @@ fn scrape_test_config(krate: &::rustc::hir::Crate) -> TestOptions {
 
     let mut opts = TestOptions {
         no_crate_inject: false,
+        display_warnings: false,
         attrs: Vec::new(),
     };
 
@@ -357,7 +364,7 @@ pub fn make_test(s: &str,
     let mut line_offset = 0;
     let mut prog = String::new();
 
-    if opts.attrs.is_empty() {
+    if opts.attrs.is_empty() && !opts.display_warnings {
         // If there aren't any attributes supplied by #![doc(test(attr(...)))], then allow some
         // lints that are commonly triggered in doctests. The crate-level test attributes are
         // commonly used to make tests fail in case they trigger warnings, so having this there in
@@ -787,6 +794,7 @@ fn make_test_no_crate_inject() {
         //adding it anyway
         let opts = TestOptions {
             no_crate_inject: true,
+            display_warnings: false,
             attrs: vec![],
         };
         let input =
@@ -957,4 +965,19 @@ fn make_test_dont_insert_main() {
         let output = make_test(input, None, true, &opts);
         assert_eq!(output, (expected.clone(), 1));
     }
+
+    #[test]
+    fn make_test_display_warnings() {
+        //if the user is asking to display doctest warnings, suppress the default allow(unused)
+        let mut opts = TestOptions::default();
+        opts.display_warnings = true;
+        let input =
+"assert_eq!(2+2, 4);";
+        let expected =
+"fn main() {
+assert_eq!(2+2, 4);
+}".to_string();
+        let output = make_test(input, None, false, &opts);
+        assert_eq!(output, (expected.clone(), 1));
+    }
 }
index ee95252346223fa86d2869822a8b2d41b302767d..22d27b6697a7c8973257ba0c4de88528971f82d4 100644 (file)
        html_root_url = "https://doc.rust-lang.org/nightly/",
        html_playground_url = "https://play.rust-lang.org/",
        test(attr(allow(unused_variables), deny(warnings))))]
-#![deny(warnings)]
 
 #![feature(box_syntax)]
 #![feature(core_intrinsics)]
-#![cfg_attr(stage0, feature(i128_type))]
 #![feature(specialization)]
 #![cfg_attr(test, feature(test))]
 
index 320a9f935d45336a8c9f6b90f0ee07428452da54..a103c0bdd598efb06bad612ac870efba86cadad5 100644 (file)
@@ -723,10 +723,10 @@ pub fn args_os() -> ArgsOs {
     ArgsOs { inner: sys::args::args() }
 }
 
-#[stable(feature = "env_unimpl_send_sync", since = "1.25.0")]
+#[stable(feature = "env_unimpl_send_sync", since = "1.26.0")]
 impl !Send for Args {}
 
-#[stable(feature = "env_unimpl_send_sync", since = "1.25.0")]
+#[stable(feature = "env_unimpl_send_sync", since = "1.26.0")]
 impl !Sync for Args {}
 
 #[stable(feature = "env", since = "1.0.0")]
@@ -760,10 +760,10 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
-#[stable(feature = "env_unimpl_send_sync", since = "1.25.0")]
+#[stable(feature = "env_unimpl_send_sync", since = "1.26.0")]
 impl !Send for ArgsOs {}
 
-#[stable(feature = "env_unimpl_send_sync", since = "1.25.0")]
+#[stable(feature = "env_unimpl_send_sync", since = "1.26.0")]
 impl !Sync for ArgsOs {}
 
 #[stable(feature = "env", since = "1.0.0")]
index e18e055654bcb26e855066e5644692fa448361da..672723341eb574a2a63524bf739a41050dfd68cd 100644 (file)
 // Tell the compiler to link to either panic_abort or panic_unwind
 #![needs_panic_runtime]
 
-// Turn warnings into errors, but only after stage0, where it can be useful for
-// code to emit warnings during language transitions
-#![cfg_attr(not(stage0), deny(warnings))]
-
 // std may use features in a platform-specific way
 #![allow(unused_features)]
 
 #![feature(float_from_str_radix)]
 #![feature(fn_traits)]
 #![feature(fnbox)]
-#![feature(generic_param_attrs)]
+#![cfg_attr(stage0, feature(generic_param_attrs))]
 #![feature(hashmap_internals)]
 #![feature(heap_api)]
-#![cfg_attr(stage0, feature(i128_type, i128))]
 #![feature(int_error_internals)]
 #![feature(integer_atomics)]
 #![feature(into_cow)]
 #![feature(doc_spotlight)]
 #![cfg_attr(test, feature(update_panic_count))]
 #![cfg_attr(windows, feature(used))]
-#![cfg_attr(stage0, feature(never_type))]
-#![cfg_attr(stage0, feature(termination_trait))]
 
 #![default_lib_allocator]
 
 // add a new crate name so we can attach the re-exports to it.
 #[macro_reexport(assert_eq, assert_ne, debug_assert, debug_assert_eq,
                  debug_assert_ne, unreachable, unimplemented, write, writeln, try)]
-#[cfg_attr(stage0, macro_reexport(assert))]
 extern crate core as __core;
 
 #[macro_use]
 
 // compiler-rt intrinsics
 #[doc(masked)]
+#[cfg(stage0)]
 extern crate compiler_builtins;
 
 // During testing, this crate is not actually the "real" std library, but rather
 // it links to the real std library, which was compiled from this same source
 // code. So any lang items std defines are conditionally excluded (or else they
-// wolud generate duplicate lang item errors), and any globals it defines are
+// would generate duplicate lang item errors), and any globals it defines are
 // _not_ the globals used by "real" std. So this import, defined only during
 // testing gives test-std access to real-std lang items and globals. See #2912
 #[cfg(test)] extern crate std as realstd;
index 79857104b9b6877bc3f9095d05a9f5707a74355e..28c178307a51049aa413d236a1ccd6d0561440e9 100644 (file)
@@ -188,7 +188,7 @@ pub struct AssertUnwindSafe<T>(
 // * By default everything is unwind safe
 // * pointers T contains mutability of some form are not unwind safe
 // * Unique, an owning pointer, lifts an implementation
-// * Types like Mutex/RwLock which are explicilty poisoned are unwind safe
+// * Types like Mutex/RwLock which are explicitly poisoned are unwind safe
 // * Our custom AssertUnwindSafe wrapper is indeed unwind safe
 
 #[stable(feature = "catch_unwind", since = "1.9.0")]
index 454ac64735c67900e37f40cf5212da99e247d7fe..fba3269204e90e10dbe32bab39be95c5db9d47e2 100644 (file)
@@ -55,8 +55,7 @@ fn __rust_maybe_catch_panic(f: fn(*mut u8),
                                 data: *mut u8,
                                 data_ptr: *mut usize,
                                 vtable_ptr: *mut usize) -> u32;
-    #[cfg_attr(stage0, unwind)]
-    #[cfg_attr(not(stage0), unwind(allowed))]
+    #[unwind(allowed)]
     fn __rust_start_panic(data: usize, vtable: usize) -> u32;
 }
 
@@ -316,8 +315,7 @@ pub fn panicking() -> bool {
 /// Entry point of panic from the libcore crate.
 #[cfg(not(test))]
 #[lang = "panic_fmt"]
-#[cfg_attr(stage0, unwind)]
-#[cfg_attr(not(stage0), unwind(allowed))]
+#[unwind(allowed)]
 pub extern fn rust_begin_panic(msg: fmt::Arguments,
                                file: &'static str,
                                line: u32,
index 40bc84f4bc104a900636a7f0ad5587dcb3cdb269..92f0406c09bb5c752170212e06fe94effebd306a 100644 (file)
@@ -1452,6 +1452,7 @@ pub trait Termination {
 
 #[unstable(feature = "termination_trait_lib", issue = "43301")]
 impl Termination for () {
+    #[inline]
     fn report(self) -> i32 { ExitCode::SUCCESS.report() }
 }
 
@@ -1481,6 +1482,7 @@ fn report(self) -> i32 {
 
 #[unstable(feature = "termination_trait_lib", issue = "43301")]
 impl Termination for ExitCode {
+    #[inline]
     fn report(self) -> i32 {
         self.0.as_i32()
     }
index b7f30600b8a4c7dc3bf63c21a3cb2397510202d4..6396bb3a49e2844c93865187354a0d2338c3b780 100644 (file)
@@ -404,6 +404,7 @@ impl ExitCode {
     pub const SUCCESS: ExitCode = ExitCode(EXIT_SUCCESS as _);
     pub const FAILURE: ExitCode = ExitCode(EXIT_FAILURE as _);
 
+    #[inline]
     pub fn as_i32(&self) -> i32 {
         self.0 as i32
     }
index f3b1185c6ea91d2532b3f88c32257d4afb85ccb5..df1dd7401af619476582db504075646df2ea6109 100644 (file)
@@ -236,7 +236,7 @@ enum State {
 impl<'a> AsyncPipe<'a> {
     fn new(pipe: Handle, dst: &'a mut Vec<u8>) -> io::Result<AsyncPipe<'a>> {
         // Create an event which we'll use to coordinate our overlapped
-        // opreations, this event will be used in WaitForMultipleObjects
+        // operations, this event will be used in WaitForMultipleObjects
         // and passed as part of the OVERLAPPED handle.
         //
         // Note that we do a somewhat clever thing here by flagging the
index afa8e3e1369354f370d5cbf5442b09dd2f3ef53b..bd5507e8f896731aaa68ccad0eb818807f309e0b 100644 (file)
@@ -414,6 +414,7 @@ impl ExitCode {
     pub const SUCCESS: ExitCode = ExitCode(EXIT_SUCCESS as _);
     pub const FAILURE: ExitCode = ExitCode(EXIT_FAILURE as _);
 
+    #[inline]
     pub fn as_i32(&self) -> i32 {
         self.0 as i32
     }
index b3346dbe2fb1240ddd1033907e169134b2ad4442..283070a0e2cf7f42d9a54bd2a8a6a16a46cab8e2 100644 (file)
@@ -15,3 +15,4 @@ path = "tests/lib.rs"
 
 [dependencies]
 core = { path = "../libcore" }
+compiler_builtins = { path = "../rustc/compiler_builtins_shim" }
index c22ea1671fa590131310a79241383043169d31d0..cf8c101a2f91f0dc6c781ceb457910e312eb7c7f 100644 (file)
@@ -27,7 +27,6 @@
        html_playground_url = "https://play.rust-lang.org/",
        issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/",
        test(no_crate_inject, attr(allow(unused_variables), deny(warnings))))]
-#![deny(warnings)]
 #![deny(missing_debug_implementations)]
 #![no_std]
 
index 31bb1c88b8712486b6d7ab00f497198a1801a5d9..e7900af7f121dca4869c8a32cbfb3ca4e9402000 100644 (file)
@@ -36,7 +36,6 @@
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)]
 pub struct Label {
     pub ident: Ident,
-    pub span: Span,
 }
 
 impl fmt::Debug for Label {
@@ -48,7 +47,6 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)]
 pub struct Lifetime {
     pub id: NodeId,
-    pub span: Span,
     pub ident: Ident,
 }
 
@@ -82,7 +80,7 @@ pub struct Path {
 
 impl<'a> PartialEq<&'a str> for Path {
     fn eq(&self, string: &&'a str) -> bool {
-        self.segments.len() == 1 && self.segments[0].identifier.name == *string
+        self.segments.len() == 1 && self.segments[0].ident.name == *string
     }
 }
 
@@ -101,17 +99,14 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 impl Path {
     // convert a span and an identifier to the corresponding
     // 1-segment path
-    pub fn from_ident(s: Span, identifier: Ident) -> Path {
-        Path {
-            span: s,
-            segments: vec![PathSegment::from_ident(identifier, s)],
-        }
+    pub fn from_ident(ident: Ident) -> Path {
+        Path { segments: vec![PathSegment::from_ident(ident)], span: ident.span }
     }
 
     // Make a "crate root" segment for this path unless it already has it
     // or starts with something like `self`/`super`/`$crate`/etc.
     pub fn make_root(&self) -> Option<PathSegment> {
-        if let Some(ident) = self.segments.get(0).map(|seg| seg.identifier) {
+        if let Some(ident) = self.segments.get(0).map(|seg| seg.ident) {
             if ::parse::token::is_path_segment_keyword(ident) &&
                ident.name != keywords::Crate.name() {
                 return None;
@@ -121,7 +116,7 @@ pub fn make_root(&self) -> Option<PathSegment> {
     }
 
     pub fn is_global(&self) -> bool {
-        !self.segments.is_empty() && self.segments[0].identifier.name == keywords::CrateRoot.name()
+        !self.segments.is_empty() && self.segments[0].ident.name == keywords::CrateRoot.name()
     }
 }
 
@@ -131,9 +126,7 @@ pub fn is_global(&self) -> bool {
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct PathSegment {
     /// The identifier portion of this path segment.
-    pub identifier: Ident,
-    /// Span of the segment identifier.
-    pub span: Span,
+    pub ident: Ident,
 
     /// Type/lifetime parameters attached to this path. They come in
     /// two flavors: `Path<A,B,C>` and `Path(A,B) -> C`.
@@ -145,15 +138,11 @@ pub struct PathSegment {
 }
 
 impl PathSegment {
-    pub fn from_ident(ident: Ident, span: Span) -> Self {
-        PathSegment { identifier: ident, span: span, parameters: None }
+    pub fn from_ident(ident: Ident) -> Self {
+        PathSegment { ident, parameters: None }
     }
     pub fn crate_root(span: Span) -> Self {
-        PathSegment {
-            identifier: Ident { ctxt: span.ctxt(), ..keywords::CrateRoot.ident() },
-            span,
-            parameters: None,
-        }
+        PathSegment::from_ident(Ident::new(keywords::CrateRoot.name(), span))
     }
 }
 
@@ -297,7 +286,7 @@ impl TyParamBound {
     pub fn span(&self) -> Span {
         match self {
             &TraitTyParamBound(ref t, ..) => t.span,
-            &RegionTyParamBound(ref l) => l.span,
+            &RegionTyParamBound(ref l) => l.ident.span,
         }
     }
 }
@@ -319,7 +308,6 @@ pub struct TyParam {
     pub id: NodeId,
     pub bounds: TyParamBounds,
     pub default: Option<P<Ty>>,
-    pub span: Span,
 }
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
@@ -370,7 +358,7 @@ pub fn span_for_name(&self, name: &str) -> Option<Span> {
         for param in &self.params {
             if let GenericParam::Type(ref t) = *param {
                 if t.ident.name == name {
-                    return Some(t.span);
+                    return Some(t.ident.span);
                 }
             }
         }
@@ -489,7 +477,7 @@ pub enum NestedMetaItemKind {
 /// E.g. `#[test]`, `#[derive(..)]` or `#[feature = "foo"]`
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct MetaItem {
-    pub name: Name,
+    pub ident: Ident,
     pub node: MetaItemKind,
     pub span: Span,
 }
@@ -545,7 +533,7 @@ pub(super) fn to_ty(&self) -> Option<P<Ty>> {
         let node = match &self.node {
             PatKind::Wild => TyKind::Infer,
             PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), ident, None) =>
-                TyKind::Path(None, Path::from_ident(ident.span, ident.node)),
+                TyKind::Path(None, Path::from_ident(*ident)),
             PatKind::Path(qself, path) => TyKind::Path(qself.clone(), path.clone()),
             PatKind::Mac(mac) => TyKind::Mac(mac.clone()),
             PatKind::Ref(pat, mutbl) =>
@@ -642,7 +630,7 @@ pub enum PatKind {
     /// or a unit struct/variant pattern, or a const pattern (in the last two cases the third
     /// field must be `None`). Disambiguation cannot be done with parser alone, so it happens
     /// during name resolution.
-    Ident(BindingMode, SpannedIdent, Option<P<Pat>>),
+    Ident(BindingMode, Ident, Option<P<Pat>>),
 
     /// A struct or struct variant pattern, e.g. `Variant {x, y, ..}`.
     /// The `bool` is `true` in the presence of a `..`.
@@ -914,15 +902,13 @@ pub struct Arm {
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct Field {
-    pub ident: SpannedIdent,
+    pub ident: Ident,
     pub expr: P<Expr>,
     pub span: Span,
     pub is_shorthand: bool,
     pub attrs: ThinVec<Attribute>,
 }
 
-pub type SpannedIdent = Spanned<Ident>;
-
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
 pub enum BlockCheckMode {
     Default,
@@ -1148,7 +1134,7 @@ pub enum ExprKind {
     /// For example, `a += 1`.
     AssignOp(BinOp, P<Expr>, P<Expr>),
     /// Access of a named struct field (`obj.foo`)
-    Field(P<Expr>, SpannedIdent),
+    Field(P<Expr>, Ident),
     /// Access of an unnamed field of a struct or tuple-struct
     ///
     /// For example, `foo.0`.
@@ -1693,7 +1679,7 @@ pub enum SelfKind {
 impl Arg {
     pub fn to_self(&self) -> Option<ExplicitSelf> {
         if let PatKind::Ident(BindingMode::ByValue(mutbl), ident, _) = self.pat.node {
-            if ident.node.name == keywords::SelfValue.name() {
+            if ident.name == keywords::SelfValue.name() {
                 return match self.ty.node {
                     TyKind::ImplicitSelf => Some(respan(self.pat.span, SelfKind::Value(mutbl))),
                     TyKind::Rptr(lt, MutTy{ref ty, mutbl}) if ty.node == TyKind::ImplicitSelf => {
@@ -1709,13 +1695,13 @@ pub fn to_self(&self) -> Option<ExplicitSelf> {
 
     pub fn is_self(&self) -> bool {
         if let PatKind::Ident(_, ident, _) = self.pat.node {
-            ident.node.name == keywords::SelfValue.name()
+            ident.name == keywords::SelfValue.name()
         } else {
             false
         }
     }
 
-    pub fn from_self(eself: ExplicitSelf, eself_ident: SpannedIdent) -> Arg {
+    pub fn from_self(eself: ExplicitSelf, eself_ident: Ident) -> Arg {
         let span = eself.span.to(eself_ident.span);
         let infer_ty = P(Ty {
             id: DUMMY_NODE_ID,
@@ -1872,7 +1858,7 @@ pub struct EnumDef {
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct Variant_ {
-    pub name: Ident,
+    pub ident: Ident,
     pub attrs: Vec<Attribute>,
     pub data: VariantData,
     /// Explicit discriminant, e.g. `Foo = 1`
@@ -1906,7 +1892,7 @@ pub fn ident(&self) -> Ident {
         match self.kind {
             UseTreeKind::Simple(Some(rename)) => rename,
             UseTreeKind::Simple(None) =>
-                self.prefix.segments.last().expect("empty prefix in a simple import").identifier,
+                self.prefix.segments.last().expect("empty prefix in a simple import").ident,
             _ => panic!("`UseTree::ident` can only be used on a simple import"),
         }
     }
@@ -2192,6 +2178,8 @@ pub enum ForeignItemKind {
     Static(P<Ty>, bool),
     /// A foreign type
     Ty,
+    /// A macro invocation
+    Macro(Mac),
 }
 
 impl ForeignItemKind {
@@ -2200,6 +2188,7 @@ pub fn descriptive_variant(&self) -> &str {
             ForeignItemKind::Fn(..) => "foreign function",
             ForeignItemKind::Static(..) => "foreign static item",
             ForeignItemKind::Ty => "foreign type",
+            ForeignItemKind::Macro(..) => "macro in foreign module",
         }
     }
 }
index 5954b9eb2747552aa323085bcab5222e6375ce27..2812e1238e9a0fd98fb39887879b1752ae33f6a6 100644 (file)
@@ -19,7 +19,7 @@
 use ast::{MetaItem, MetaItemKind, NestedMetaItem, NestedMetaItemKind};
 use ast::{Lit, LitKind, Expr, ExprKind, Item, Local, Stmt, StmtKind};
 use codemap::{Spanned, respan, dummy_spanned};
-use syntax_pos::{Span, DUMMY_SP};
+use syntax_pos::Span;
 use errors::Handler;
 use feature_gate::{Features, GatedCfg};
 use parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration};
@@ -137,7 +137,7 @@ pub fn check_name(&self, name: &str) -> bool {
     /// Returns the name of the meta item, e.g. `foo` in `#[foo]`,
     /// `#[foo="bar"]` and `#[foo(bar)]`, if self is a MetaItem
     pub fn name(&self) -> Option<Name> {
-        self.meta_item().and_then(|meta_item| Some(meta_item.name()))
+        self.meta_item().and_then(|meta_item| Some(meta_item.ident.name))
     }
 
     /// Gets the string value if self is a MetaItem and the MetaItem is a
@@ -154,7 +154,7 @@ pub fn name_value_literal(&self) -> Option<(Name, &Lit)> {
                     if meta_item_list.len() == 1 {
                         let nested_item = &meta_item_list[0];
                         if nested_item.is_literal() {
-                            Some((meta_item.name(), nested_item.literal().unwrap()))
+                            Some((meta_item.ident.name, nested_item.literal().unwrap()))
                         } else {
                             None
                         }
@@ -215,7 +215,7 @@ pub fn check_name(&self, name: &str) -> bool {
 
     pub fn name(&self) -> Option<Name> {
         match self.path.segments.len() {
-            1 => Some(self.path.segments[0].identifier.name),
+            1 => Some(self.path.segments[0].ident.name),
             _ => None,
         }
     }
@@ -250,10 +250,6 @@ pub fn is_value_str(&self) -> bool {
 }
 
 impl MetaItem {
-    pub fn name(&self) -> Name {
-        self.name
-    }
-
     pub fn value_str(&self) -> Option<Symbol> {
         match self.node {
             MetaItemKind::NameValue(ref v) => {
@@ -283,7 +279,7 @@ pub fn is_word(&self) -> bool {
     pub fn span(&self) -> Span { self.span }
 
     pub fn check_name(&self, name: &str) -> bool {
-        self.name() == name
+        self.ident.name == name
     }
 
     pub fn is_value_str(&self) -> bool {
@@ -300,8 +296,8 @@ impl Attribute {
     pub fn meta(&self) -> Option<MetaItem> {
         let mut tokens = self.tokens.trees().peekable();
         Some(MetaItem {
-            name: match self.path.segments.len() {
-                1 => self.path.segments[0].identifier.name,
+            ident: match self.path.segments.len() {
+                1 => self.path.segments[0].ident,
                 _ => return None,
             },
             node: if let Some(node) = MetaItemKind::from_tokens(&mut tokens) {
@@ -353,7 +349,7 @@ pub fn parse_meta<'a>(&self, sess: &'a ParseSess) -> PResult<'a, MetaItem> {
         }
 
         Ok(MetaItem {
-            name: self.path.segments.last().unwrap().identifier.name,
+            ident: self.path.segments.last().unwrap().ident,
             node: self.parse(sess, |parser| parser.parse_meta_item_kind())?,
             span: self.span,
         })
@@ -368,8 +364,8 @@ pub fn with_desugared_doc<T, F>(&self, f: F) -> T where
         if self.is_sugared_doc {
             let comment = self.value_str().unwrap();
             let meta = mk_name_value_item_str(
-                Symbol::intern("doc"),
-                Symbol::intern(&strip_doc_comment_decoration(&comment.as_str())));
+                Ident::from_str("doc"),
+                dummy_spanned(Symbol::intern(&strip_doc_comment_decoration(&comment.as_str()))));
             let mut attr = if self.style == ast::AttrStyle::Outer {
                 mk_attr_outer(self.span, self.id, meta)
             } else {
@@ -385,37 +381,24 @@ pub fn with_desugared_doc<T, F>(&self, f: F) -> T where
 
 /* Constructors */
 
-pub fn mk_name_value_item_str(name: Name, value: Symbol) -> MetaItem {
-    let value_lit = dummy_spanned(LitKind::Str(value, ast::StrStyle::Cooked));
-    mk_spanned_name_value_item(DUMMY_SP, name, value_lit)
+pub fn mk_name_value_item_str(ident: Ident, value: Spanned<Symbol>) -> MetaItem {
+    let value = respan(value.span, LitKind::Str(value.node, ast::StrStyle::Cooked));
+    mk_name_value_item(ident.span.to(value.span), ident, value)
 }
 
-pub fn mk_name_value_item(name: Name, value: ast::Lit) -> MetaItem {
-    mk_spanned_name_value_item(DUMMY_SP, name, value)
+pub fn mk_name_value_item(span: Span, ident: Ident, value: ast::Lit) -> MetaItem {
+    MetaItem { ident, span, node: MetaItemKind::NameValue(value) }
 }
 
-pub fn mk_list_item(name: Name, items: Vec<NestedMetaItem>) -> MetaItem {
-    mk_spanned_list_item(DUMMY_SP, name, items)
+pub fn mk_list_item(span: Span, ident: Ident, items: Vec<NestedMetaItem>) -> MetaItem {
+    MetaItem { ident, span, node: MetaItemKind::List(items) }
 }
 
-pub fn mk_list_word_item(name: Name) -> ast::NestedMetaItem {
-    dummy_spanned(NestedMetaItemKind::MetaItem(mk_spanned_word_item(DUMMY_SP, name)))
+pub fn mk_word_item(ident: Ident) -> MetaItem {
+    MetaItem { ident, span: ident.span, node: MetaItemKind::Word }
 }
-
-pub fn mk_word_item(name: Name) -> MetaItem {
-    mk_spanned_word_item(DUMMY_SP, name)
-}
-
-pub fn mk_spanned_name_value_item(sp: Span, name: Name, value: ast::Lit) -> MetaItem {
-    MetaItem { span: sp, name: name, node: MetaItemKind::NameValue(value) }
-}
-
-pub fn mk_spanned_list_item(sp: Span, name: Name, items: Vec<NestedMetaItem>) -> MetaItem {
-    MetaItem { span: sp, name: name, node: MetaItemKind::List(items) }
-}
-
-pub fn mk_spanned_word_item(sp: Span, name: Name) -> MetaItem {
-    MetaItem { span: sp, name: name, node: MetaItemKind::Word }
+pub fn mk_nested_word_item(ident: Ident) -> NestedMetaItem {
+    respan(ident.span, NestedMetaItemKind::MetaItem(mk_word_item(ident)))
 }
 
 pub fn mk_attr_id() -> AttrId {
@@ -439,7 +422,7 @@ pub fn mk_spanned_attr_inner(sp: Span, id: AttrId, item: MetaItem) -> Attribute
     Attribute {
         id,
         style: ast::AttrStyle::Inner,
-        path: ast::Path::from_ident(item.span, ast::Ident::with_empty_ctxt(item.name)),
+        path: ast::Path::from_ident(item.ident),
         tokens: item.node.tokens(item.span),
         is_sugared_doc: false,
         span: sp,
@@ -457,7 +440,7 @@ pub fn mk_spanned_attr_outer(sp: Span, id: AttrId, item: MetaItem) -> Attribute
     Attribute {
         id,
         style: ast::AttrStyle::Outer,
-        path: ast::Path::from_ident(item.span, ast::Ident::with_empty_ctxt(item.name)),
+        path: ast::Path::from_ident(item.ident),
         tokens: item.node.tokens(item.span),
         is_sugared_doc: false,
         span: sp,
@@ -470,7 +453,7 @@ pub fn mk_sugared_doc_attr(id: AttrId, text: Symbol, span: Span) -> Attribute {
     Attribute {
         id,
         style,
-        path: ast::Path::from_ident(span, ast::Ident::from_str("doc")),
+        path: ast::Path::from_ident(Ident::from_str("doc").with_span_pos(span)),
         tokens: MetaItemKind::NameValue(lit).tokens(span),
         is_sugared_doc: true,
         span,
@@ -506,7 +489,7 @@ pub fn contains_feature_attr(attrs: &[Attribute], feature_name: &str) -> bool {
         item.check_name("feature") &&
         item.meta_item_list().map(|list| {
             list.iter().any(|mi| {
-                mi.word().map(|w| w.name() == feature_name)
+                mi.word().map(|w| w.ident.name == feature_name)
                          .unwrap_or(false)
             })
         }).unwrap_or(false)
@@ -579,7 +562,7 @@ pub fn cfg_matches(cfg: &ast::MetaItem, sess: &ParseSess, features: Option<&Feat
         if let (Some(feats), Some(gated_cfg)) = (features, GatedCfg::gate(cfg)) {
             gated_cfg.check_and_emit(sess, feats);
         }
-        sess.config.contains(&(cfg.name(), cfg.value_str()))
+        sess.config.contains(&(cfg.ident.name, cfg.value_str()))
     })
 }
 
@@ -600,7 +583,7 @@ pub fn eval_condition<F>(cfg: &ast::MetaItem, sess: &ParseSess, eval: &mut F)
 
             // The unwraps below may look dangerous, but we've already asserted
             // that they won't fail with the loop above.
-            match &*cfg.name.as_str() {
+            match &*cfg.ident.name.as_str() {
                 "any" => mis.iter().any(|mi| {
                     eval_condition(mi.meta_item().unwrap(), sess, eval)
                 }),
@@ -693,7 +676,7 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
             let meta = meta.as_ref().unwrap();
             let get = |meta: &MetaItem, item: &mut Option<Symbol>| {
                 if item.is_some() {
-                    handle_errors(diagnostic, meta.span, AttrError::MultipleItem(meta.name()));
+                    handle_errors(diagnostic, meta.span, AttrError::MultipleItem(meta.ident.name));
                     return false
                 }
                 if let Some(v) = meta.value_str() {
@@ -712,14 +695,14 @@ macro_rules! get_meta {
                     )+
                     for meta in metas {
                         if let Some(mi) = meta.meta_item() {
-                            match &*mi.name().as_str() {
+                            match &*mi.ident.name.as_str() {
                                 $(
                                     stringify!($name)
                                         => if !get(mi, &mut $name) { continue 'outer },
                                 )+
                                 _ => {
                                     handle_errors(diagnostic, mi.span,
-                                                  AttrError::UnknownMetaItem(mi.name()));
+                                                  AttrError::UnknownMetaItem(mi.ident.name));
                                     continue 'outer
                                 }
                             }
@@ -731,7 +714,7 @@ macro_rules! get_meta {
                 }
             }
 
-            match &*meta.name.as_str() {
+            match &*meta.ident.name.as_str() {
                 "rustc_deprecated" => {
                     if rustc_depr.is_some() {
                         span_err!(diagnostic, item_sp, E0540,
@@ -786,13 +769,13 @@ macro_rules! get_meta {
                     let mut issue = None;
                     for meta in metas {
                         if let Some(mi) = meta.meta_item() {
-                            match &*mi.name().as_str() {
+                            match &*mi.ident.name.as_str() {
                                 "feature" => if !get(mi, &mut feature) { continue 'outer },
                                 "reason" => if !get(mi, &mut reason) { continue 'outer },
                                 "issue" => if !get(mi, &mut issue) { continue 'outer },
                                 _ => {
                                     handle_errors(diagnostic, meta.span,
-                                                  AttrError::UnknownMetaItem(mi.name()));
+                                                  AttrError::UnknownMetaItem(mi.ident.name));
                                     continue 'outer
                                 }
                             }
@@ -842,12 +825,12 @@ macro_rules! get_meta {
                     let mut since = None;
                     for meta in metas {
                         if let NestedMetaItemKind::MetaItem(ref mi) = meta.node {
-                            match &*mi.name().as_str() {
+                            match &*mi.ident.name.as_str() {
                                 "feature" => if !get(mi, &mut feature) { continue 'outer },
                                 "since" => if !get(mi, &mut since) { continue 'outer },
                                 _ => {
                                     handle_errors(diagnostic, meta.span,
-                                                  AttrError::UnknownMetaItem(mi.name()));
+                                                  AttrError::UnknownMetaItem(mi.ident.name));
                                     continue 'outer
                                 }
                             }
@@ -934,7 +917,7 @@ fn find_deprecation_generic<'a, I>(diagnostic: &Handler,
         depr = if let Some(metas) = attr.meta_item_list() {
             let get = |meta: &MetaItem, item: &mut Option<Symbol>| {
                 if item.is_some() {
-                    handle_errors(diagnostic, meta.span, AttrError::MultipleItem(meta.name()));
+                    handle_errors(diagnostic, meta.span, AttrError::MultipleItem(meta.ident.name));
                     return false
                 }
                 if let Some(v) = meta.value_str() {
@@ -950,12 +933,12 @@ fn find_deprecation_generic<'a, I>(diagnostic: &Handler,
             let mut note = None;
             for meta in metas {
                 if let NestedMetaItemKind::MetaItem(ref mi) = meta.node {
-                    match &*mi.name().as_str() {
+                    match &*mi.ident.name.as_str() {
                         "since" => if !get(mi, &mut since) { continue 'outer },
                         "note" => if !get(mi, &mut note) { continue 'outer },
                         _ => {
                             handle_errors(diagnostic, meta.span,
-                                          AttrError::UnknownMetaItem(mi.name()));
+                                          AttrError::UnknownMetaItem(mi.ident.name));
                             continue 'outer
                         }
                     }
@@ -1007,7 +990,7 @@ pub fn find_repr_attrs(diagnostic: &Handler, attr: &Attribute) -> Vec<ReprAttr>
 
                 let mut recognised = false;
                 if let Some(mi) = item.word() {
-                    let word = &*mi.name().as_str();
+                    let word = &*mi.ident.name.as_str();
                     let hint = match word {
                         "C" => Some(ReprC),
                         "packed" => Some(ReprPacked),
@@ -1106,18 +1089,17 @@ pub fn is_signed(self) -> bool {
 
 impl MetaItem {
     fn tokens(&self) -> TokenStream {
-        let ident = TokenTree::Token(self.span,
-                                     Token::from_ast_ident(Ident::with_empty_ctxt(self.name)));
+        let ident = TokenTree::Token(self.span, Token::from_ast_ident(self.ident));
         TokenStream::concat(vec![ident.into(), self.node.tokens(self.span)])
     }
 
     fn from_tokens<I>(tokens: &mut iter::Peekable<I>) -> Option<MetaItem>
         where I: Iterator<Item = TokenTree>,
     {
-        let (span, name) = match tokens.next() {
-            Some(TokenTree::Token(span, Token::Ident(ident, _))) => (span, ident.name),
+        let (span, ident) = match tokens.next() {
+            Some(TokenTree::Token(span, Token::Ident(ident, _))) => (span, ident),
             Some(TokenTree::Token(_, Token::Interpolated(ref nt))) => match nt.0 {
-                token::Nonterminal::NtIdent(ident, _) => (ident.span, ident.node.name),
+                token::Nonterminal::NtIdent(ident, _) => (ident.span, ident),
                 token::Nonterminal::NtMeta(ref meta) => return Some(meta.clone()),
                 _ => return None,
             },
@@ -1130,7 +1112,7 @@ fn from_tokens<I>(tokens: &mut iter::Peekable<I>) -> Option<MetaItem>
             MetaItemKind::List(..) => list_closing_paren_pos.unwrap_or(span.hi()),
             _ => span.hi(),
         };
-        Some(MetaItem { name, node, span: span.with_hi(hi) })
+        Some(MetaItem { ident, node, span: span.with_hi(hi) })
     }
 }
 
index c0855d470c8bf99f260066b7a151433b352ac577..36911683a0e7785654cd7c88a642cec1c106814f 100644 (file)
@@ -204,7 +204,7 @@ pub fn configure_item_kind(&mut self, item: ast::ItemKind) -> ast::ItemKind {
                     self.configure(v).map(|v| {
                         Spanned {
                             node: ast::Variant_ {
-                                name: v.node.name,
+                                ident: v.node.ident,
                                 attrs: v.node.attrs,
                                 data: self.configure_variant_data(v.node.data),
                                 disr_expr: v.node.disr_expr,
index d3157af984e80534d15424ba4fe7a9251dfad015..c25a7686bead0e8296460215c42d1d199feaa8cc 100644 (file)
@@ -28,7 +28,7 @@
 use std::iter;
 use std::path::PathBuf;
 use std::rc::Rc;
-use rustc_data_structures::sync::Lrc;
+use rustc_data_structures::sync::{self, Lrc};
 use std::default::Default;
 use tokenstream::{self, TokenStream};
 
@@ -38,6 +38,7 @@ pub enum Annotatable {
     Item(P<ast::Item>),
     TraitItem(P<ast::TraitItem>),
     ImplItem(P<ast::ImplItem>),
+    ForeignItem(P<ast::ForeignItem>),
     Stmt(P<ast::Stmt>),
     Expr(P<ast::Expr>),
 }
@@ -48,6 +49,7 @@ fn attrs(&self) -> &[Attribute] {
             Annotatable::Item(ref item) => &item.attrs,
             Annotatable::TraitItem(ref trait_item) => &trait_item.attrs,
             Annotatable::ImplItem(ref impl_item) => &impl_item.attrs,
+            Annotatable::ForeignItem(ref foreign_item) => &foreign_item.attrs,
             Annotatable::Stmt(ref stmt) => stmt.attrs(),
             Annotatable::Expr(ref expr) => &expr.attrs,
         }
@@ -58,6 +60,8 @@ fn map_attrs<F: FnOnce(Vec<Attribute>) -> Vec<Attribute>>(self, f: F) -> Self {
             Annotatable::Item(item) => Annotatable::Item(item.map_attrs(f)),
             Annotatable::TraitItem(trait_item) => Annotatable::TraitItem(trait_item.map_attrs(f)),
             Annotatable::ImplItem(impl_item) => Annotatable::ImplItem(impl_item.map_attrs(f)),
+            Annotatable::ForeignItem(foreign_item) =>
+                Annotatable::ForeignItem(foreign_item.map_attrs(f)),
             Annotatable::Stmt(stmt) => Annotatable::Stmt(stmt.map_attrs(f)),
             Annotatable::Expr(expr) => Annotatable::Expr(expr.map_attrs(f)),
         }
@@ -70,6 +74,7 @@ pub fn span(&self) -> Span {
             Annotatable::Item(ref item) => item.span,
             Annotatable::TraitItem(ref trait_item) => trait_item.span,
             Annotatable::ImplItem(ref impl_item) => impl_item.span,
+            Annotatable::ForeignItem(ref foreign_item) => foreign_item.span,
             Annotatable::Stmt(ref stmt) => stmt.span,
             Annotatable::Expr(ref expr) => expr.span,
         }
@@ -106,6 +111,13 @@ pub fn expect_impl_item(self) -> ast::ImplItem {
         }
     }
 
+    pub fn expect_foreign_item(self) -> ast::ForeignItem {
+        match self {
+            Annotatable::ForeignItem(i) => i.into_inner(),
+            _ => panic!("expected foreign item")
+        }
+    }
+
     pub fn derive_allowed(&self) -> bool {
         match *self {
             Annotatable::Item(ref item) => match item.node {
@@ -239,7 +251,7 @@ fn fold_tt(&mut self, tt: tokenstream::TokenTree) -> tokenstream::TokenTree {
                 if let tokenstream::TokenTree::Token(_, token::Interpolated(ref nt)) = tt {
                     if let token::NtIdent(ident, is_raw) = nt.0 {
                         return tokenstream::TokenTree::Token(ident.span,
-                                                             token::Ident(ident.node, is_raw));
+                                                             token::Ident(ident, is_raw));
                     }
                 }
                 fold::noop_fold_tt(tt, self)
@@ -317,6 +329,9 @@ fn make_trait_items(self: Box<Self>) -> Option<SmallVector<ast::TraitItem>> {
         None
     }
 
+    /// Create zero or more items in an `extern {}` block
+    fn make_foreign_items(self: Box<Self>) -> Option<SmallVector<ast::ForeignItem>> { None }
+
     /// Create a pattern.
     fn make_pat(self: Box<Self>) -> Option<P<ast::Pat>> {
         None
@@ -365,6 +380,7 @@ pub fn $fld(v: $t) -> Box<MacResult> {
     items: SmallVector<P<ast::Item>>,
     impl_items: SmallVector<ast::ImplItem>,
     trait_items: SmallVector<ast::TraitItem>,
+    foreign_items: SmallVector<ast::ForeignItem>,
     stmts: SmallVector<ast::Stmt>,
     ty: P<ast::Ty>,
 }
@@ -386,6 +402,10 @@ fn make_trait_items(self: Box<Self>) -> Option<SmallVector<ast::TraitItem>> {
         self.trait_items
     }
 
+    fn make_foreign_items(self: Box<Self>) -> Option<SmallVector<ast::ForeignItem>> {
+        self.foreign_items
+    }
+
     fn make_stmts(self: Box<Self>) -> Option<SmallVector<ast::Stmt>> {
         match self.stmts.as_ref().map_or(0, |s| s.len()) {
             0 => make_stmts_default!(self),
@@ -502,6 +522,14 @@ fn make_trait_items(self: Box<DummyResult>) -> Option<SmallVector<ast::TraitItem
         }
     }
 
+    fn make_foreign_items(self: Box<Self>) -> Option<SmallVector<ast::ForeignItem>> {
+        if self.expr_only {
+            None
+        } else {
+            Some(SmallVector::new())
+        }
+    }
+
     fn make_stmts(self: Box<DummyResult>) -> Option<SmallVector<ast::Stmt>> {
         Some(SmallVector::one(ast::Stmt {
             id: ast::DUMMY_NODE_ID,
@@ -537,26 +565,26 @@ pub enum SyntaxExtension {
     /// `#[derive(...)]` is a `MultiItemDecorator`.
     ///
     /// Prefer ProcMacro or MultiModifier since they are more flexible.
-    MultiDecorator(Box<MultiItemDecorator>),
+    MultiDecorator(Box<MultiItemDecorator + sync::Sync + sync::Send>),
 
     /// A syntax extension that is attached to an item and modifies it
     /// in-place. Also allows decoration, i.e., creating new items.
-    MultiModifier(Box<MultiItemModifier>),
+    MultiModifier(Box<MultiItemModifier + sync::Sync + sync::Send>),
 
     /// A function-like procedural macro. TokenStream -> TokenStream.
-    ProcMacro(Box<ProcMacro>),
+    ProcMacro(Box<ProcMacro + sync::Sync + sync::Send>),
 
     /// An attribute-like procedural macro. TokenStream, TokenStream -> TokenStream.
     /// The first TokenSteam is the attribute, the second is the annotated item.
     /// Allows modification of the input items and adding new items, similar to
     /// MultiModifier, but uses TokenStreams, rather than AST nodes.
-    AttrProcMacro(Box<AttrProcMacro>),
+    AttrProcMacro(Box<AttrProcMacro + sync::Sync + sync::Send>),
 
     /// A normal, function-like syntax extension.
     ///
     /// `bytes!` is a `NormalTT`.
     NormalTT {
-        expander: Box<TTMacroExpander>,
+        expander: Box<TTMacroExpander + sync::Sync + sync::Send>,
         def_info: Option<(ast::NodeId, Span)>,
         /// Whether the contents of the macro can
         /// directly use `#[unstable]` things (true == yes).
@@ -571,13 +599,15 @@ pub enum SyntaxExtension {
     /// A function-like syntax extension that has an extra ident before
     /// the block.
     ///
-    IdentTT(Box<IdentMacroExpander>, Option<Span>, bool),
+    IdentTT(Box<IdentMacroExpander + sync::Sync + sync::Send>, Option<Span>, bool),
 
     /// An attribute-like procedural macro. TokenStream -> TokenStream.
     /// The input is the annotated item.
     /// Allows generating code to implement a Trait for a given struct
     /// or enum item.
-    ProcMacroDerive(Box<MultiItemModifier>, Vec<Symbol> /* inert attribute names */),
+    ProcMacroDerive(Box<MultiItemModifier +
+                        sync::Sync +
+                        sync::Send>, Vec<Symbol> /* inert attribute names */),
 
     /// An attribute-like procedural macro that derives a builtin trait.
     BuiltinDerive(BuiltinDeriveFn),
@@ -585,7 +615,7 @@ pub enum SyntaxExtension {
     /// A declarative macro, e.g. `macro m() {}`.
     ///
     /// The second element is the definition site span.
-    DeclMacro(Box<TTMacroExpander>, Option<(ast::NodeId, Span)>),
+    DeclMacro(Box<TTMacroExpander + sync::Sync + sync::Send>, Option<(ast::NodeId, Span)>),
 }
 
 impl SyntaxExtension {
@@ -848,8 +878,8 @@ pub fn ident_of(&self, st: &str) -> ast::Ident {
         ast::Ident::from_str(st)
     }
     pub fn std_path(&self, components: &[&str]) -> Vec<ast::Ident> {
-        let def_site = SyntaxContext::empty().apply_mark(self.current_expansion.mark);
-        iter::once(Ident { ctxt: def_site, ..keywords::DollarCrate.ident() })
+        let def_site = DUMMY_SP.apply_mark(self.current_expansion.mark);
+        iter::once(Ident::new(keywords::DollarCrate.name(), def_site))
             .chain(components.iter().map(|s| self.ident_of(s)))
             .collect()
     }
@@ -869,7 +899,7 @@ pub fn expr_to_spanned_string(cx: &mut ExtCtxt, expr: P<ast::Expr>, err_msg: &st
                               -> Option<Spanned<(Symbol, ast::StrStyle)>> {
     // Update `expr.span`'s ctxt now in case expr is an `include!` macro invocation.
     let expr = expr.map(|mut expr| {
-        expr.span = expr.span.with_ctxt(expr.span.ctxt().apply_mark(cx.current_expansion.mark));
+        expr.span = expr.span.apply_mark(cx.current_expansion.mark);
         expr
     });
 
index 269517e998f5b1fe7dfddc9093725555ed289bf1..062f3ce112752cec5d82a474bd0b8aec469f4584 100644 (file)
@@ -38,11 +38,11 @@ fn path_all(&self, sp: Span,
 
     fn qpath(&self, self_type: P<ast::Ty>,
              trait_path: ast::Path,
-             ident: ast::SpannedIdent)
+             ident: ast::Ident)
              -> (ast::QSelf, ast::Path);
     fn qpath_all(&self, self_type: P<ast::Ty>,
                 trait_path: ast::Path,
-                ident: ast::SpannedIdent,
+                ident: ast::Ident,
                 lifetimes: Vec<ast::Lifetime>,
                 types: Vec<P<ast::Ty>>,
                 bindings: Vec<ast::TypeBinding>)
@@ -319,16 +319,18 @@ fn path_all(&self,
                 types: Vec<P<ast::Ty>>,
                 bindings: Vec<ast::TypeBinding> )
                 -> ast::Path {
-        let last_identifier = idents.pop().unwrap();
+        let last_ident = idents.pop().unwrap();
         let mut segments: Vec<ast::PathSegment> = Vec::new();
 
-        segments.extend(idents.into_iter().map(|i| ast::PathSegment::from_ident(i, span)));
+        segments.extend(idents.into_iter().map(|ident| {
+            ast::PathSegment::from_ident(ident.with_span_pos(span))
+        }));
         let parameters = if !lifetimes.is_empty() || !types.is_empty() || !bindings.is_empty() {
             ast::AngleBracketedParameterData { lifetimes, types, bindings, span }.into()
         } else {
             None
         };
-        segments.push(ast::PathSegment { identifier: last_identifier, span, parameters });
+        segments.push(ast::PathSegment { ident: last_ident.with_span_pos(span), parameters });
         let mut path = ast::Path { span, segments };
         if global {
             if let Some(seg) = path.make_root() {
@@ -344,7 +346,7 @@ fn path_all(&self,
     fn qpath(&self,
              self_type: P<ast::Ty>,
              trait_path: ast::Path,
-             ident: ast::SpannedIdent)
+             ident: ast::Ident)
              -> (ast::QSelf, ast::Path) {
         self.qpath_all(self_type, trait_path, ident, vec![], vec![], vec![])
     }
@@ -355,7 +357,7 @@ fn qpath(&self,
     fn qpath_all(&self,
                  self_type: P<ast::Ty>,
                  trait_path: ast::Path,
-                 ident: ast::SpannedIdent,
+                 ident: ast::Ident,
                  lifetimes: Vec<ast::Lifetime>,
                  types: Vec<P<ast::Ty>>,
                  bindings: Vec<ast::TypeBinding>)
@@ -366,11 +368,7 @@ fn qpath_all(&self,
         } else {
             None
         };
-        path.segments.push(ast::PathSegment {
-            identifier: ident.node,
-            span: ident.span,
-            parameters,
-        });
+        path.segments.push(ast::PathSegment { ident, parameters });
 
         (ast::QSelf {
             ty: self_type,
@@ -439,17 +437,16 @@ fn ty_infer(&self, span: Span) -> P<ast::Ty> {
 
     fn typaram(&self,
                span: Span,
-               id: ast::Ident,
+               ident: ast::Ident,
                attrs: Vec<ast::Attribute>,
                bounds: ast::TyParamBounds,
                default: Option<P<ast::Ty>>) -> ast::TyParam {
         ast::TyParam {
-            ident: id,
+            ident: ident.with_span_pos(span),
             id: ast::DUMMY_NODE_ID,
             attrs: attrs.into(),
             bounds,
             default,
-            span,
         }
     }
 
@@ -473,7 +470,7 @@ fn typarambound(&self, path: ast::Path) -> ast::TyParamBound {
     }
 
     fn lifetime(&self, span: Span, ident: ast::Ident) -> ast::Lifetime {
-        ast::Lifetime { id: ast::DUMMY_NODE_ID, span: span, ident: ident }
+        ast::Lifetime { id: ast::DUMMY_NODE_ID, ident: ident.with_span_pos(span) }
     }
 
     fn lifetime_def(&self,
@@ -636,8 +633,7 @@ fn expr_unary(&self, sp: Span, op: ast::UnOp, e: P<ast::Expr>) -> P<ast::Expr> {
     }
 
     fn expr_field_access(&self, sp: Span, expr: P<ast::Expr>, ident: ast::Ident) -> P<ast::Expr> {
-        let id = Spanned { node: ident, span: sp };
-        self.expr(sp, ast::ExprKind::Field(expr, id))
+        self.expr(sp, ast::ExprKind::Field(expr, ident.with_span_pos(sp)))
     }
     fn expr_tup_field_access(&self, sp: Span, expr: P<ast::Expr>, idx: usize) -> P<ast::Expr> {
         let id = Spanned { node: idx, span: sp };
@@ -667,14 +663,15 @@ fn expr_method_call(&self, span: Span,
                         ident: ast::Ident,
                         mut args: Vec<P<ast::Expr>> ) -> P<ast::Expr> {
         args.insert(0, expr);
-        self.expr(span, ast::ExprKind::MethodCall(ast::PathSegment::from_ident(ident, span), args))
+        let segment = ast::PathSegment::from_ident(ident.with_span_pos(span));
+        self.expr(span, ast::ExprKind::MethodCall(segment, args))
     }
     fn expr_block(&self, b: P<ast::Block>) -> P<ast::Expr> {
         self.expr(b.span, ast::ExprKind::Block(b))
     }
-    fn field_imm(&self, span: Span, name: Ident, e: P<ast::Expr>) -> ast::Field {
+    fn field_imm(&self, span: Span, ident: Ident, e: P<ast::Expr>) -> ast::Field {
         ast::Field {
-            ident: respan(span, name),
+            ident: ident.with_span_pos(span),
             expr: e,
             span,
             is_shorthand: false,
@@ -835,7 +832,7 @@ fn pat_ident_binding_mode(&self,
                               span: Span,
                               ident: ast::Ident,
                               bm: ast::BindingMode) -> P<ast::Pat> {
-        let pat = PatKind::Ident(bm, Spanned{span: span, node: ident}, None);
+        let pat = PatKind::Ident(bm, ident.with_span_pos(span), None);
         self.pat(span, pat)
     }
     fn pat_path(&self, span: Span, path: ast::Path) -> P<ast::Pat> {
@@ -1027,7 +1024,7 @@ fn item_fn(&self,
             body)
     }
 
-    fn variant(&self, span: Span, name: Ident, tys: Vec<P<ast::Ty>> ) -> ast::Variant {
+    fn variant(&self, span: Span, ident: Ident, tys: Vec<P<ast::Ty>> ) -> ast::Variant {
         let fields: Vec<_> = tys.into_iter().map(|ty| {
             ast::StructField {
                 span: ty.span,
@@ -1047,7 +1044,7 @@ fn variant(&self, span: Span, name: Ident, tys: Vec<P<ast::Ty>> ) -> ast::Varian
 
         respan(span,
                ast::Variant_ {
-                   name,
+                   ident,
                    attrs: Vec::new(),
                    data: vdata,
                    disr_expr: None,
@@ -1132,21 +1129,22 @@ fn attribute(&self, sp: Span, mi: ast::MetaItem) -> ast::Attribute {
     }
 
     fn meta_word(&self, sp: Span, w: ast::Name) -> ast::MetaItem {
-        attr::mk_spanned_word_item(sp, w)
+        attr::mk_word_item(Ident::with_empty_ctxt(w).with_span_pos(sp))
     }
 
     fn meta_list_item_word(&self, sp: Span, w: ast::Name) -> ast::NestedMetaItem {
-        respan(sp, ast::NestedMetaItemKind::MetaItem(attr::mk_spanned_word_item(sp, w)))
+        attr::mk_nested_word_item(Ident::with_empty_ctxt(w).with_span_pos(sp))
     }
 
     fn meta_list(&self, sp: Span, name: ast::Name, mis: Vec<ast::NestedMetaItem>)
                  -> ast::MetaItem {
-        attr::mk_spanned_list_item(sp, name, mis)
+        attr::mk_list_item(sp, Ident::with_empty_ctxt(name).with_span_pos(sp), mis)
     }
 
     fn meta_name_value(&self, sp: Span, name: ast::Name, value: ast::LitKind)
                        -> ast::MetaItem {
-        attr::mk_spanned_name_value_item(sp, name, respan(sp, value))
+        attr::mk_name_value_item(sp, Ident::with_empty_ctxt(name).with_span_pos(sp),
+                                 respan(sp, value))
     }
 
     fn item_use(&self, sp: Span,
index c7fa0331c1bd5a9dc55c5f9897edf393212432de..6bf166dfe950a84dc3559068d200e132ee4d26e3 100644 (file)
@@ -54,7 +54,7 @@ pub fn add_derived_markers<T>(cx: &mut ExtCtxt, span: Span, traits: &[ast::Path]
             pretty_name.push_str(", ");
         }
         pretty_name.push_str(&path.to_string());
-        names.insert(unwrap_or!(path.segments.get(0), continue).identifier.name);
+        names.insert(unwrap_or!(path.segments.get(0), continue).ident.name);
     }
     pretty_name.push(')');
 
index 864969c40750b5623e8cf51513bbbc98fdb861fe..678c20402d6f47aab78e99f35b0234f61d2846eb 100644 (file)
@@ -133,6 +133,8 @@ impl<'a> MacResult for ::ext::tt::macro_rules::ParserAnyMacro<'a> {
         "trait item", .make_trait_items, lift .fold_trait_item, lift .visit_trait_item;
     ImplItems: SmallVector<ast::ImplItem> [SmallVector, ast::ImplItem],
         "impl item",  .make_impl_items,  lift .fold_impl_item,  lift .visit_impl_item;
+    ForeignItems: SmallVector<ast::ForeignItem> [SmallVector, ast::ForeignItem],
+        "foreign item", .make_foreign_items, lift .fold_foreign_item, lift .visit_foreign_item;
 }
 
 impl ExpansionKind {
@@ -149,6 +151,8 @@ fn expect_from_annotatables<I: IntoIterator<Item = Annotatable>>(self, items: I)
                 Expansion::ImplItems(items.map(Annotatable::expect_impl_item).collect()),
             ExpansionKind::TraitItems =>
                 Expansion::TraitItems(items.map(Annotatable::expect_trait_item).collect()),
+            ExpansionKind::ForeignItems =>
+                Expansion::ForeignItems(items.map(Annotatable::expect_foreign_item).collect()),
             _ => unreachable!(),
         }
     }
@@ -164,10 +168,10 @@ fn macro_bang_format(path: &ast::Path) -> ExpnFormat {
             path_str.push_str("::");
         }
 
-        if segment.identifier.name != keywords::CrateRoot.name() &&
-            segment.identifier.name != keywords::DollarCrate.name()
+        if segment.ident.name != keywords::CrateRoot.name() &&
+            segment.ident.name != keywords::DollarCrate.name()
         {
-            path_str.push_str(&segment.identifier.name.as_str())
+            path_str.push_str(&segment.ident.name.as_str())
         }
     }
 
@@ -435,6 +439,11 @@ fn fully_configure(&mut self, item: Annotatable) -> Annotatable {
             Annotatable::ImplItem(item) => {
                 Annotatable::ImplItem(item.map(|item| cfg.fold_impl_item(item).pop().unwrap()))
             }
+            Annotatable::ForeignItem(item) => {
+                Annotatable::ForeignItem(
+                    item.map(|item| cfg.fold_foreign_item(item).pop().unwrap())
+                )
+            }
             Annotatable::Stmt(stmt) => {
                 Annotatable::Stmt(stmt.map(|stmt| cfg.fold_stmt(stmt).pop().unwrap()))
             }
@@ -509,6 +518,7 @@ fn expand_attr_invoc(&mut self,
                     Annotatable::Item(item) => token::NtItem(item),
                     Annotatable::TraitItem(item) => token::NtTraitItem(item.into_inner()),
                     Annotatable::ImplItem(item) => token::NtImplItem(item.into_inner()),
+                    Annotatable::ForeignItem(item) => token::NtForeignItem(item.into_inner()),
                     Annotatable::Stmt(stmt) => token::NtStmt(stmt.into_inner()),
                     Annotatable::Expr(expr) => token::NtExpr(expr),
                 })).into();
@@ -678,7 +688,7 @@ fn expand_bang_invoc(&mut self,
             opt_expanded
         } else {
             let msg = format!("non-{kind} macro in {kind} position: {name}",
-                              name = path.segments[0].identifier.name, kind = kind.name());
+                              name = path.segments[0].ident.name, kind = kind.name());
             self.cx.span_err(path.span, &msg);
             self.cx.trace_macros_diag();
             kind.dummy(span)
@@ -723,7 +733,7 @@ fn expand_derive_invoc(&mut self,
                 invoc.expansion_data.mark.set_expn_info(expn_info);
                 let span = span.with_ctxt(self.cx.backtrace());
                 let dummy = ast::MetaItem { // FIXME(jseyfried) avoid this
-                    name: keywords::Invalid.name(),
+                    ident: keywords::Invalid.ident(),
                     span: DUMMY_SP,
                     node: ast::MetaItemKind::Word,
                 };
@@ -793,6 +803,15 @@ pub fn parse_expansion(&mut self, kind: ExpansionKind, macro_legacy_warnings: bo
                 }
                 Expansion::ImplItems(items)
             }
+            ExpansionKind::ForeignItems => {
+                let mut items = SmallVector::new();
+                while self.token != token::Eof {
+                    if let Some(item) = self.parse_foreign_item()? {
+                        items.push(item);
+                    }
+                }
+                Expansion::ForeignItems(items)
+            }
             ExpansionKind::Stmts => {
                 let mut stmts = SmallVector::new();
                 while self.token != token::Eof &&
@@ -1166,6 +1185,44 @@ fn fold_foreign_mod(&mut self, foreign_mod: ast::ForeignMod) -> ast::ForeignMod
         noop_fold_foreign_mod(self.cfg.configure_foreign_mod(foreign_mod), self)
     }
 
+    fn fold_foreign_item(&mut self,
+                         foreign_item: ast::ForeignItem) -> SmallVector<ast::ForeignItem> {
+        let (attr, traits, foreign_item) = self.classify_item(foreign_item);
+
+        let explain = if self.cx.ecfg.proc_macro_enabled() {
+            feature_gate::EXPLAIN_PROC_MACROS_IN_EXTERN
+        } else {
+            feature_gate::EXPLAIN_MACROS_IN_EXTERN
+        };
+
+        if attr.is_some() || !traits.is_empty()  {
+            if !self.cx.ecfg.macros_in_extern_enabled() {
+                if let Some(ref attr) = attr {
+                    emit_feature_err(&self.cx.parse_sess, "macros_in_extern", attr.span,
+                                     GateIssue::Language, explain);
+                }
+            }
+
+            let item = Annotatable::ForeignItem(P(foreign_item));
+            return self.collect_attr(attr, traits, item, ExpansionKind::ForeignItems)
+                .make_foreign_items();
+        }
+
+        if let ast::ForeignItemKind::Macro(mac) = foreign_item.node {
+            self.check_attributes(&foreign_item.attrs);
+
+            if !self.cx.ecfg.macros_in_extern_enabled() {
+                emit_feature_err(&self.cx.parse_sess, "macros_in_extern", foreign_item.span,
+                                 GateIssue::Language, explain);
+            }
+
+            return self.collect_bang(mac, foreign_item.span, ExpansionKind::ForeignItems)
+                .make_foreign_items();
+        }
+
+        noop_fold_foreign_item(foreign_item, self)
+    }
+
     fn fold_item_kind(&mut self, item: ast::ItemKind) -> ast::ItemKind {
         match item {
             ast::ItemKind::MacroDef(..) => item,
@@ -1222,15 +1279,16 @@ fn fold_attribute(&mut self, at: ast::Attribute) -> Option<ast::Attribute> {
 
                             let include_info = vec![
                                 dummy_spanned(ast::NestedMetaItemKind::MetaItem(
-                                        attr::mk_name_value_item_str("file".into(),
-                                                                     file))),
+                                        attr::mk_name_value_item_str(Ident::from_str("file"),
+                                                                     dummy_spanned(file)))),
                                 dummy_spanned(ast::NestedMetaItemKind::MetaItem(
-                                        attr::mk_name_value_item_str("contents".into(),
-                                                                     (&*src).into()))),
+                                        attr::mk_name_value_item_str(Ident::from_str("contents"),
+                                                            dummy_spanned(Symbol::intern(&src))))),
                             ];
 
-                            items.push(dummy_spanned(ast::NestedMetaItemKind::MetaItem(
-                                        attr::mk_list_item("include".into(), include_info))));
+                            let include_ident = Ident::from_str("include");
+                            let item = attr::mk_list_item(DUMMY_SP, include_ident, include_info);
+                            items.push(dummy_spanned(ast::NestedMetaItemKind::MetaItem(item)));
                         }
                         Err(_) => {
                             self.cx.span_err(at.span,
@@ -1243,7 +1301,7 @@ fn fold_attribute(&mut self, at: ast::Attribute) -> Option<ast::Attribute> {
                 }
             }
 
-            let meta = attr::mk_list_item("doc".into(), items);
+            let meta = attr::mk_list_item(DUMMY_SP, Ident::from_str("doc"), items);
             match at.style {
                 ast::AttrStyle::Inner =>
                     Some(attr::mk_spanned_attr_inner(at.span, at.id, meta)),
@@ -1311,6 +1369,7 @@ fn enable_trace_macros = trace_macros,
         fn enable_allow_internal_unstable = allow_internal_unstable,
         fn enable_custom_derive = custom_derive,
         fn proc_macro_enabled = proc_macro,
+        fn macros_in_extern_enabled = macros_in_extern,
     }
 }
 
@@ -1320,12 +1379,12 @@ fn proc_macro_enabled = proc_macro,
 
 impl Folder for Marker {
     fn fold_ident(&mut self, mut ident: Ident) -> Ident {
-        ident.ctxt = ident.ctxt.apply_mark(self.0);
+        ident.span = ident.span.apply_mark(self.0);
         ident
     }
 
     fn new_span(&mut self, span: Span) -> Span {
-        span.with_ctxt(span.ctxt().apply_mark(self.0))
+        span.apply_mark(self.0)
     }
 
     fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac {
index 9c2c22476e9d9f598edf2e6358f134cdaeb661a7..9f60882ca29fc408224b388e1de08f181847cda3 100644 (file)
@@ -60,6 +60,10 @@ fn mac_placeholder() -> ast::Mac {
             defaultness: ast::Defaultness::Final,
             tokens: None,
         })),
+        ExpansionKind::ForeignItems => Expansion::ForeignItems(SmallVector::one(ast::ForeignItem {
+            id, span, ident, vis, attrs,
+            node: ast::ForeignItemKind::Macro(mac_placeholder()),
+        })),
         ExpansionKind::Pat => Expansion::Pat(P(ast::Pat {
             id, span, node: ast::PatKind::Mac(mac_placeholder()),
         })),
@@ -132,6 +136,13 @@ fn fold_impl_item(&mut self, item: ast::ImplItem) -> SmallVector<ast::ImplItem>
         }
     }
 
+    fn fold_foreign_item(&mut self, item: ast::ForeignItem) -> SmallVector<ast::ForeignItem> {
+        match item.node {
+            ast::ForeignItemKind::Macro(_) => self.remove(item.id).make_foreign_items(),
+            _ => noop_fold_foreign_item(item, self),
+        }
+    }
+
     fn fold_expr(&mut self, expr: P<ast::Expr>) -> P<ast::Expr> {
         match expr.node {
             ast::ExprKind::Mac(_) => self.remove(expr.id).make_expr(),
index 540a03ff032ffef2527e5395d99cad058fb08975..3303955d398a64375035a3223ace0c1ba6347e1f 100644 (file)
@@ -75,7 +75,7 @@ fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
 
     impl ToTokens for ast::Ident {
         fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
-            vec![TokenTree::Token(DUMMY_SP, Token::from_ast_ident(*self))]
+            vec![TokenTree::Token(self.span, Token::from_ast_ident(*self))]
         }
     }
 
@@ -193,7 +193,7 @@ fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
 
     impl ToTokens for ast::Lifetime {
         fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
-            vec![TokenTree::Token(DUMMY_SP, token::Lifetime(self.ident))]
+            vec![TokenTree::Token(self.ident.span, token::Lifetime(self.ident))]
         }
     }
 
@@ -239,7 +239,7 @@ fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
                     inner.push(TokenTree::Token(self.span, token::Colon).into());
                 }
                 inner.push(TokenTree::Token(
-                    self.span, token::Token::from_ast_ident(segment.identifier)
+                    self.span, token::Token::from_ast_ident(segment.ident)
                 ).into());
             }
             inner.push(self.tokens.clone());
index 8cb331c65da2871c5ffca5f7a7d178bff1a08c0b..d9c3deb30da30a8b6107bbafb181e7e6c90adf84 100644 (file)
@@ -86,7 +86,6 @@
 
 use ast::Ident;
 use syntax_pos::{self, BytePos, Span};
-use codemap::respan;
 use errors::FatalError;
 use ext::tt::quoted::{self, TokenTree};
 use parse::{Directory, ParseSess};
@@ -366,7 +365,7 @@ pub fn parse_failure_msg(tok: Token) -> String {
 fn token_name_eq(t1: &Token, t2: &Token) -> bool {
     if let (Some((id1, is_raw1)), Some((id2, is_raw2))) = (t1.ident(), t2.ident()) {
         id1.name == id2.name && is_raw1 == is_raw2
-    } else if let (&token::Lifetime(id1), &token::Lifetime(id2)) = (t1, t2) {
+    } else if let (Some(id1), Some(id2)) = (t1.lifetime(), t2.lifetime()) {
         id1.name == id2.name
     } else {
         *t1 == *t2
@@ -825,8 +824,9 @@ fn parse_nt<'a>(p: &mut Parser<'a>, sp: Span, name: &str) -> Nonterminal {
         "ty" => token::NtTy(panictry!(p.parse_ty())),
         // this could be handled like a token, since it is one
         "ident" => if let Some((ident, is_raw)) = get_macro_ident(&p.token) {
+            let span = p.span;
             p.bump();
-            token::NtIdent(respan(p.prev_span, ident), is_raw)
+            token::NtIdent(Ident::new(ident.name, span), is_raw)
         } else {
             let token_str = pprust::token_to_string(&p.token);
             p.fatal(&format!("expected ident, found {}", &token_str)).emit();
@@ -835,7 +835,7 @@ fn parse_nt<'a>(p: &mut Parser<'a>, sp: Span, name: &str) -> Nonterminal {
         "path" => token::NtPath(panictry!(p.parse_path_common(PathStyle::Type, false))),
         "meta" => token::NtMeta(panictry!(p.parse_meta_item())),
         "vis" => token::NtVis(panictry!(p.parse_visibility(true))),
-        "lifetime" => token::NtLifetime(p.expect_lifetime()),
+        "lifetime" => token::NtLifetime(p.expect_lifetime().ident),
         // this is not supposed to happen, since it has been checked
         // when compiling the macro.
         _ => p.span_bug(sp, "invalid fragment specifier"),
index 10e5926eb9e36d45667f31fcb038d5e610873419..ffe68289d5224be79aa5cb086791919d07b08abc 100644 (file)
@@ -53,7 +53,7 @@ pub fn make(mut self: Box<ParserAnyMacro<'a>>, kind: ExpansionKind) -> Expansion
         }
 
         // Make sure we don't have any tokens left to parse so we don't silently drop anything.
-        let path = ast::Path::from_ident(site_span, macro_ident);
+        let path = ast::Path::from_ident(macro_ident.with_span_pos(site_span));
         parser.ensure_complete_parse(&path, kind.name(), site_span);
         expansion
     }
index f324edeb1178ad49db4d4fc6e9f9cda20dc56be6..01b971976a763c3d49bf72f5283e2303e52f0442 100644 (file)
@@ -289,14 +289,11 @@ fn parse_tree<I>(
             // `tree` is followed by an `ident`. This could be `$meta_var` or the `$crate` special
             // metavariable that names the crate of the invokation.
             Some(tokenstream::TokenTree::Token(ident_span, ref token)) if token.is_ident() => {
-                let (ident, _) = token.ident().unwrap();
+                let (ident, is_raw) = token.ident().unwrap();
                 let span = ident_span.with_lo(span.lo());
-                if ident.name == keywords::Crate.name() {
-                    let ident = ast::Ident {
-                        name: keywords::DollarCrate.name(),
-                        ..ident
-                    };
-                    TokenTree::Token(span, token::Ident(ident, false))
+                if ident.name == keywords::Crate.name() && !is_raw {
+                    let ident = ast::Ident::new(keywords::DollarCrate.name(), ident.span);
+                    TokenTree::Token(span, token::Ident(ident, is_raw))
                 } else {
                     TokenTree::MetaVar(span, ident)
                 }
index 3f01d5ec6dd876e1117ea9c030206968d1f3ffbc..1cdb6b0e5c902692f8130ce6f6839ca301cc6ce7 100644 (file)
@@ -156,7 +156,7 @@ pub fn transcribe(cx: &ExtCtxt,
                         if let NtTT(ref tt) = **nt {
                             result.push(tt.clone().into());
                         } else {
-                            sp = sp.with_ctxt(sp.ctxt().apply_mark(cx.current_expansion.mark));
+                            sp = sp.apply_mark(cx.current_expansion.mark);
                             let token = TokenTree::Token(sp, Token::interpolated((**nt).clone()));
                             result.push(token.into());
                         }
@@ -166,14 +166,14 @@ pub fn transcribe(cx: &ExtCtxt,
                     }
                 } else {
                     let ident =
-                        Ident { ctxt: ident.ctxt.apply_mark(cx.current_expansion.mark), ..ident };
-                    sp = sp.with_ctxt(sp.ctxt().apply_mark(cx.current_expansion.mark));
+                        Ident::new(ident.name, ident.span.apply_mark(cx.current_expansion.mark));
+                    sp = sp.apply_mark(cx.current_expansion.mark);
                     result.push(TokenTree::Token(sp, token::Dollar).into());
                     result.push(TokenTree::Token(sp, token::Token::from_ast_ident(ident)).into());
                 }
             }
             quoted::TokenTree::Delimited(mut span, delimited) => {
-                span = span.with_ctxt(span.ctxt().apply_mark(cx.current_expansion.mark));
+                span = span.apply_mark(cx.current_expansion.mark);
                 stack.push(Frame::Delimited { forest: delimited, idx: 0, span: span });
                 result_stack.push(mem::replace(&mut result, Vec::new()));
             }
index e734a4e3735342ff5895290d14780c16a7e1885f..0a3cd66d89717635ecfe56b67d6b607f652be996 100644 (file)
@@ -193,7 +193,7 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
     (active, rustc_attrs, "1.0.0", Some(29642), None),
 
     // Allows the use of non lexical lifetimes; RFC 2094
-    (active, nll, "1.0.0", Some(43234), None),
+    (active, nll, "1.0.0", Some(43234), Some(Edition::Edition2018)),
 
     // Allows the use of #[allow_internal_unstable]. This is an
     // attribute on macro_rules! and can't use the attribute handling
@@ -288,9 +288,6 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
     // rustc internal
     (active, compiler_builtins, "1.13.0", None, None),
 
-    // Allows attributes on lifetime/type formal parameters in generics (RFC 1327)
-    (active, generic_param_attrs, "1.11.0", Some(34761), None),
-
     // Allows #[link(..., cfg(..))]
     (active, link_cfg, "1.14.0", Some(37406), None),
 
@@ -391,7 +388,7 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
     (active, dyn_trait, "1.22.0", Some(44662), Some(Edition::Edition2018)),
 
     // `crate` as visibility modifier, synonymous to `pub(crate)`
-    (active, crate_visibility_modifier, "1.23.0", Some(45388), None),
+    (active, crate_visibility_modifier, "1.23.0", Some(45388), Some(Edition::Edition2018)),
 
     // extern types
     (active, extern_types, "1.23.0", Some(43467), None),
@@ -400,10 +397,10 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
     (active, arbitrary_self_types, "1.23.0", Some(44874), None),
 
     // `crate` in paths
-    (active, crate_in_paths, "1.23.0", Some(45477), None),
+    (active, crate_in_paths, "1.23.0", Some(45477), Some(Edition::Edition2018)),
 
     // In-band lifetime bindings (e.g. `fn foo(x: &'a u8) -> &'a u8`)
-    (active, in_band_lifetimes, "1.23.0", Some(44524), None),
+    (active, in_band_lifetimes, "1.23.0", Some(44524), Some(Edition::Edition2018)),
 
     // generic associated types (RFC 1598)
     (active, generic_associated_types, "1.23.0", Some(44265), None),
@@ -412,10 +409,10 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
     (active, extern_absolute_paths, "1.24.0", Some(44660), None),
 
     // `foo.rs` as an alternative to `foo/mod.rs`
-    (active, non_modrs_mods, "1.24.0", Some(44660), None),
+    (active, non_modrs_mods, "1.24.0", Some(44660), Some(Edition::Edition2018)),
 
     // Termination trait in tests (RFC 1937)
-    (active, termination_trait_test, "1.24.0", Some(48854), None),
+    (active, termination_trait_test, "1.24.0", Some(48854), Some(Edition::Edition2018)),
 
     // Allows use of the :lifetime macro fragment specifier
     (active, macro_lifetime_matcher, "1.24.0", Some(46895), None),
@@ -446,6 +443,9 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
 
     // Allows keywords to be escaped for use as identifiers
     (active, raw_identifiers, "1.26.0", Some(48589), None),
+
+    // Allows macro invocations in `extern {}` blocks
+    (active, macros_in_extern, "1.27.0", Some(49476), None),
 );
 
 declare_features! (
@@ -483,7 +483,7 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
     // allow empty structs and enum variants with braces
     (accepted, braced_empty_structs, "1.8.0", Some(29720), None),
     // Allows indexing into constant arrays.
-    (accepted, const_indexing, "1.24.0", Some(29947), None),
+    (accepted, const_indexing, "1.26.0", Some(29947), None),
     (accepted, default_type_params, "1.0.0", None, None),
     (accepted, globs, "1.0.0", None, None),
     (accepted, if_let, "1.0.0", None, None),
@@ -566,6 +566,8 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
     (accepted, match_default_bindings, "1.26.0", Some(42640), None),
     // allow `'_` placeholder lifetimes
     (accepted, underscore_lifetimes, "1.26.0", Some(44524), None),
+    // Allows attributes on lifetime/type formal parameters in generics (RFC 1327)
+    (accepted, generic_param_attrs, "1.26.0", Some(48848), None),
 );
 
 // If you change this, please modify src/doc/unstable-book as well. You must
@@ -1052,7 +1054,7 @@ pub struct GatedCfg {
 
 impl GatedCfg {
     pub fn gate(cfg: &ast::MetaItem) -> Option<GatedCfg> {
-        let name = cfg.name().as_str();
+        let name = cfg.ident.name.as_str();
         GATED_CFGS.iter()
                   .position(|info| info.0 == name)
                   .map(|idx| {
@@ -1292,6 +1294,13 @@ fn leveled_feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue
 pub const EXPLAIN_MACRO_AT_MOST_ONCE_REP: &'static str =
     "Using the `?` macro Kleene operator for \"at most one\" repetition is unstable";
 
+pub const EXPLAIN_MACROS_IN_EXTERN: &'static str =
+    "Macro invocations in `extern {}` blocks are experimental.";
+
+// mention proc-macros when enabled
+pub const EXPLAIN_PROC_MACROS_IN_EXTERN: &'static str =
+    "Macro and proc-macro invocations in `extern {}` blocks are experimental.";
+
 struct PostExpansionVisitor<'a> {
     context: &'a Context<'a>,
 }
@@ -1596,6 +1605,7 @@ fn visit_foreign_item(&mut self, i: &'a ast::ForeignItem) {
                     gate_feature_post!(&self, extern_types, i.span,
                                        "extern types are experimental");
             }
+            ast::ForeignItemKind::Macro(..) => {}
         }
 
         visit::walk_foreign_item(self, i)
@@ -1756,11 +1766,19 @@ fn visit_impl_item(&mut self, ii: &'a ast::ImplItem) {
 
     fn visit_path(&mut self, path: &'a ast::Path, _id: NodeId) {
         for segment in &path.segments {
-            if segment.identifier.name == keywords::Crate.name() {
-                gate_feature_post!(&self, crate_in_paths, segment.span,
+            // Identifiers we are going to check could come from a legacy macro (e.g. `#[test]`).
+            // For such macros identifiers must have empty context, because this context is
+            // used during name resolution and produced names must be unhygienic for compatibility.
+            // On the other hand, we need the actual non-empty context for feature gate checking
+            // because it's hygienic even for legacy macros. As previously stated, such context
+            // cannot be kept in identifiers, so it's kept in paths instead and we take it from
+            // there while keeping location info from the ident span.
+            let span = segment.ident.span.with_ctxt(path.span.ctxt());
+            if segment.ident.name == keywords::Crate.name() {
+                gate_feature_post!(&self, crate_in_paths, span,
                                    "`crate` in paths is experimental");
-            } else if segment.identifier.name == keywords::Extern.name() {
-                gate_feature_post!(&self, extern_in_paths, segment.span,
+            } else if segment.ident.name == keywords::Extern.name() {
+                gate_feature_post!(&self, extern_in_paths, span,
                                    "`extern` in paths is experimental");
             }
         }
@@ -1775,21 +1793,6 @@ fn visit_vis(&mut self, vis: &'a ast::Visibility) {
         }
         visit::walk_vis(self, vis);
     }
-
-    fn visit_generic_param(&mut self, param: &'a ast::GenericParam) {
-        let (attrs, explain) = match *param {
-            ast::GenericParam::Lifetime(ref ld) =>
-                (&ld.attrs, "attributes on lifetime bindings are experimental"),
-            ast::GenericParam::Type(ref t) =>
-                (&t.attrs, "attributes on type parameter bindings are experimental"),
-        };
-
-        if !attrs.is_empty() {
-            gate_feature_post!(&self, generic_param_attrs, attrs[0].span, explain);
-        }
-
-        visit::walk_generic_param(self, param)
-    }
 }
 
 pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute],
@@ -1816,7 +1819,7 @@ fn feature_removed(span_handler: &Handler, span: Span) {
                 for mi in list {
 
                     let name = if let Some(word) = mi.word() {
-                        word.name()
+                        word.ident.name
                     } else {
                         span_err!(span_handler, mi.span, E0556,
                                   "malformed feature, expected just one word");
index e702bf56e7f83faf69b0cbcfbcfcf52faf1169ca..ba6703b9c74406ee24db0cc8b83e24074e47520f 100644 (file)
@@ -60,10 +60,14 @@ fn fold_use_tree(&mut self, use_tree: UseTree) -> UseTree {
         noop_fold_use_tree(use_tree, self)
     }
 
-    fn fold_foreign_item(&mut self, ni: ForeignItem) -> ForeignItem {
+    fn fold_foreign_item(&mut self, ni: ForeignItem) -> SmallVector<ForeignItem> {
         noop_fold_foreign_item(ni, self)
     }
 
+    fn fold_foreign_item_simple(&mut self, ni: ForeignItem) -> ForeignItem {
+        noop_fold_foreign_item_simple(ni, self)
+    }
+
     fn fold_item(&mut self, i: P<Item>) -> SmallVector<P<Item>> {
         noop_fold_item(i, self)
     }
@@ -414,7 +418,7 @@ pub fn noop_fold_foreign_mod<T: Folder>(ForeignMod {abi, items}: ForeignMod,
                                         fld: &mut T) -> ForeignMod {
     ForeignMod {
         abi,
-        items: items.move_map(|x| fld.fold_foreign_item(x)),
+        items: items.move_flat_map(|x| fld.fold_foreign_item(x)),
     }
 }
 
@@ -426,7 +430,7 @@ pub fn noop_fold_global_asm<T: Folder>(ga: P<GlobalAsm>,
 pub fn noop_fold_variant<T: Folder>(v: Variant, fld: &mut T) -> Variant {
     Spanned {
         node: Variant_ {
-            name: fld.fold_ident(v.node.name),
+            ident: fld.fold_ident(v.node.ident),
             attrs: fold_attrs(v.node.attrs, fld),
             data: fld.fold_variant_data(v.node.data),
             disr_expr: v.node.disr_expr.map(|e| fld.fold_expr(e)),
@@ -435,8 +439,8 @@ pub fn noop_fold_variant<T: Folder>(v: Variant, fld: &mut T) -> Variant {
     }
 }
 
-pub fn noop_fold_ident<T: Folder>(i: Ident, _: &mut T) -> Ident {
-    i
+pub fn noop_fold_ident<T: Folder>(ident: Ident, fld: &mut T) -> Ident {
+    Ident::new(ident.name, fld.new_span(ident.span))
 }
 
 pub fn noop_fold_usize<T: Folder>(i: usize, _: &mut T) -> usize {
@@ -445,9 +449,8 @@ pub fn noop_fold_usize<T: Folder>(i: usize, _: &mut T) -> usize {
 
 pub fn noop_fold_path<T: Folder>(Path { segments, span }: Path, fld: &mut T) -> Path {
     Path {
-        segments: segments.move_map(|PathSegment {identifier, span, parameters}| PathSegment {
-            identifier: fld.fold_ident(identifier),
-            span: fld.new_span(span),
+        segments: segments.move_map(|PathSegment {ident, parameters}| PathSegment {
+            ident: fld.fold_ident(ident),
             parameters: parameters.map(|ps| ps.map(|ps| fld.fold_path_parameters(ps))),
         }),
         span: fld.new_span(span)
@@ -540,7 +543,7 @@ pub fn noop_fold_meta_list_item<T: Folder>(li: NestedMetaItem, fld: &mut T)
 
 pub fn noop_fold_meta_item<T: Folder>(mi: MetaItem, fld: &mut T) -> MetaItem {
     MetaItem {
-        name: mi.name,
+        ident: mi.ident,
         node: match mi.node {
             MetaItemKind::Word => MetaItemKind::Word,
             MetaItemKind::List(mis) => {
@@ -630,8 +633,8 @@ pub fn noop_fold_interpolated<T: Folder>(nt: token::Nonterminal, fld: &mut T)
         token::NtPat(pat) => token::NtPat(fld.fold_pat(pat)),
         token::NtExpr(expr) => token::NtExpr(fld.fold_expr(expr)),
         token::NtTy(ty) => token::NtTy(fld.fold_ty(ty)),
-        token::NtIdent(id, is_raw) =>
-            token::NtIdent(Spanned::<Ident>{node: fld.fold_ident(id.node), ..id}, is_raw),
+        token::NtIdent(ident, is_raw) => token::NtIdent(fld.fold_ident(ident), is_raw),
+        token::NtLifetime(ident) => token::NtLifetime(fld.fold_ident(ident)),
         token::NtMeta(meta) => token::NtMeta(fld.fold_meta_item(meta)),
         token::NtPath(path) => token::NtPath(fld.fold_path(path)),
         token::NtTT(tt) => token::NtTT(fld.fold_tt(tt)),
@@ -647,7 +650,10 @@ pub fn noop_fold_interpolated<T: Folder>(nt: token::Nonterminal, fld: &mut T)
             token::NtWhereClause(fld.fold_where_clause(where_clause)),
         token::NtArg(arg) => token::NtArg(fld.fold_arg(arg)),
         token::NtVis(vis) => token::NtVis(fld.fold_vis(vis)),
-        token::NtLifetime(lifetime) => token::NtLifetime(fld.fold_lifetime(lifetime)),
+        token::NtForeignItem(ni) =>
+            token::NtForeignItem(fld.fold_foreign_item(ni)
+                                 // see reasoning above
+                                 .expect_one("expected fold to produce exactly one item")),
     }
 }
 
@@ -672,7 +678,7 @@ pub fn noop_fold_ty_param_bound<T>(tpb: TyParamBound, fld: &mut T)
 }
 
 pub fn noop_fold_ty_param<T: Folder>(tp: TyParam, fld: &mut T) -> TyParam {
-    let TyParam {attrs, id, ident, bounds, default, span} = tp;
+    let TyParam {attrs, id, ident, bounds, default} = tp;
     let attrs: Vec<_> = attrs.into();
     TyParam {
         attrs: attrs.into_iter()
@@ -683,7 +689,6 @@ pub fn noop_fold_ty_param<T: Folder>(tp: TyParam, fld: &mut T) -> TyParam {
         ident: fld.fold_ident(ident),
         bounds: fld.fold_bounds(bounds),
         default: default.map(|x| fld.fold_ty(x)),
-        span: fld.new_span(span),
     }
 }
 
@@ -704,7 +709,6 @@ pub fn noop_fold_generic_params<T: Folder>(
 pub fn noop_fold_label<T: Folder>(label: Label, fld: &mut T) -> Label {
     Label {
         ident: fld.fold_ident(label.ident),
-        span: fld.new_span(label.span),
     }
 }
 
@@ -712,7 +716,6 @@ pub fn noop_fold_lifetime<T: Folder>(l: Lifetime, fld: &mut T) -> Lifetime {
     Lifetime {
         id: fld.new_id(l.id),
         ident: fld.fold_ident(l.ident),
-        span: fld.new_span(l.span)
     }
 }
 
@@ -851,7 +854,7 @@ pub fn noop_fold_struct_field<T: Folder>(f: StructField, fld: &mut T) -> StructF
 
 pub fn noop_fold_field<T: Folder>(f: Field, folder: &mut T) -> Field {
     Field {
-        ident: respan(f.ident.span, folder.fold_ident(f.ident.node)),
+        ident: folder.fold_ident(f.ident),
         expr: folder.fold_expr(f.expr),
         span: folder.new_span(f.span),
         is_shorthand: f.is_shorthand,
@@ -1072,7 +1075,12 @@ pub fn noop_fold_item_simple<T: Folder>(Item {id, ident, attrs, node, vis, span,
     }
 }
 
-pub fn noop_fold_foreign_item<T: Folder>(ni: ForeignItem, folder: &mut T) -> ForeignItem {
+pub fn noop_fold_foreign_item<T: Folder>(ni: ForeignItem, folder: &mut T)
+-> SmallVector<ForeignItem> {
+    SmallVector::one(folder.fold_foreign_item_simple(ni))
+}
+
+pub fn noop_fold_foreign_item_simple<T: Folder>(ni: ForeignItem, folder: &mut T) -> ForeignItem {
     ForeignItem {
         id: folder.new_id(ni.id),
         vis: folder.fold_vis(ni.vis),
@@ -1086,6 +1094,7 @@ pub fn noop_fold_foreign_item<T: Folder>(ni: ForeignItem, folder: &mut T) -> For
                 ForeignItemKind::Static(folder.fold_ty(t), m)
             }
             ForeignItemKind::Ty => ForeignItemKind::Ty,
+            ForeignItemKind::Macro(mac) => ForeignItemKind::Macro(folder.fold_mac(mac)),
         },
         span: folder.new_span(ni.span)
     }
@@ -1105,11 +1114,10 @@ pub fn noop_fold_pat<T: Folder>(p: P<Pat>, folder: &mut T) -> P<Pat> {
         id: folder.new_id(id),
         node: match node {
             PatKind::Wild => PatKind::Wild,
-            PatKind::Ident(binding_mode, pth1, sub) => {
+            PatKind::Ident(binding_mode, ident, sub) => {
                 PatKind::Ident(binding_mode,
-                        Spanned{span: folder.new_span(pth1.span),
-                                node: folder.fold_ident(pth1.node)},
-                        sub.map(|x| folder.fold_pat(x)))
+                               folder.fold_ident(ident),
+                               sub.map(|x| folder.fold_pat(x)))
             }
             PatKind::Lit(e) => PatKind::Lit(folder.fold_expr(e)),
             PatKind::TupleStruct(pth, pats, ddpos) => {
@@ -1181,8 +1189,7 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span, attrs}: Expr, folder: &mu
             ExprKind::MethodCall(seg, args) => {
                 ExprKind::MethodCall(
                     PathSegment {
-                        identifier: folder.fold_ident(seg.identifier),
-                        span: folder.new_span(seg.span),
+                        ident: folder.fold_ident(seg.ident),
                         parameters: seg.parameters.map(|ps| {
                             ps.map(|ps| folder.fold_path_parameters(ps))
                         }),
@@ -1258,14 +1265,12 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span, attrs}: Expr, folder: &mu
                             folder.fold_expr(er))
             }
             ExprKind::Field(el, ident) => {
-                ExprKind::Field(folder.fold_expr(el),
-                          respan(folder.new_span(ident.span),
-                                 folder.fold_ident(ident.node)))
+                ExprKind::Field(folder.fold_expr(el), folder.fold_ident(ident))
             }
-            ExprKind::TupField(el, ident) => {
+            ExprKind::TupField(el, index) => {
                 ExprKind::TupField(folder.fold_expr(el),
-                             respan(folder.new_span(ident.span),
-                                    folder.fold_usize(ident.node)))
+                             respan(folder.new_span(index.span),
+                                    folder.fold_usize(index.node)))
             }
             ExprKind::Index(el, er) => {
                 ExprKind::Index(folder.fold_expr(el), folder.fold_expr(er))
index dc349c1a3e6a12f51b728a4b16111d085a12b9d0..d80430f609b3a069a78e2f970230e89c0387d7f1 100644 (file)
        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "https://doc.rust-lang.org/nightly/",
        test(attr(deny(warnings))))]
-#![deny(warnings)]
 
 #![feature(unicode)]
 #![feature(rustc_diagnostic_macros)]
-#![cfg_attr(stage0, feature(match_default_bindings))]
 #![feature(non_exhaustive)]
-#![cfg_attr(stage0, feature(i128_type))]
 #![feature(const_atomic_usize_new)]
 #![feature(rustc_attrs)]
 
+#![recursion_limit="256"]
+
 // See librustc_cratesio_shim/Cargo.toml for a comment explaining this.
 #[allow(unused_extern_crates)]
 extern crate rustc_cratesio_shim;
index 4c3f42d9c6b7d4c2f94406de5f05ed0e6e7843e9..90f08ab1468e212ca37cce4df7ae0f7bf6e669c0 100644 (file)
@@ -149,8 +149,7 @@ pub fn parse_path_and_tokens(&mut self) -> PResult<'a, (ast::Path, TokenStream)>
         };
         Ok(if let Some(meta) = meta {
             self.bump();
-            (ast::Path::from_ident(meta.span, ast::Ident::with_empty_ctxt(meta.name)),
-             meta.node.tokens(meta.span))
+            (ast::Path::from_ident(meta.ident), meta.node.tokens(meta.span))
         } else {
             (self.parse_path(PathStyle::Mod)?, self.parse_tokens())
         })
@@ -228,7 +227,7 @@ pub fn parse_meta_item(&mut self) -> PResult<'a, ast::MetaItem> {
         let lo = self.span;
         let ident = self.parse_ident()?;
         let node = self.parse_meta_item_kind()?;
-        Ok(ast::MetaItem { name: ident.name, node: node, span: lo.to(self.prev_span) })
+        Ok(ast::MetaItem { ident, node: node, span: lo.to(self.prev_span) })
     }
 
     pub fn parse_meta_item_kind(&mut self) -> PResult<'a, ast::MetaItemKind> {
index 068929c8948df983ef3eb17bc2573922bebab8d1..39b2f77f2305e717d62216d22a8b53c3cfee0059 100644 (file)
@@ -76,7 +76,7 @@ fn mk_sp(&self, lo: BytePos, hi: BytePos) -> Span {
     fn mk_ident(&self, string: &str) -> Ident {
         let mut ident = Ident::from_str(string);
         if let Some(span) = self.override_span {
-            ident.ctxt = span.ctxt();
+            ident.span = span;
         }
         ident
     }
@@ -1781,7 +1781,6 @@ mod tests {
     use errors;
     use feature_gate::UnstableFeatures;
     use parse::token;
-    use std::cell::RefCell;
     use std::collections::HashSet;
     use std::io;
     use std::path::PathBuf;
@@ -1797,12 +1796,12 @@ fn mk_sess(cm: Lrc<CodeMap>) -> ParseSess {
             span_diagnostic: errors::Handler::with_emitter(true, false, Box::new(emitter)),
             unstable_features: UnstableFeatures::from_environment(),
             config: CrateConfig::new(),
-            included_mod_stack: RefCell::new(Vec::new()),
+            included_mod_stack: Lock::new(Vec::new()),
             code_map: cm,
-            missing_fragment_specifiers: RefCell::new(HashSet::new()),
-            raw_identifier_spans: RefCell::new(Vec::new()),
+            missing_fragment_specifiers: Lock::new(HashSet::new()),
+            raw_identifier_spans: Lock::new(Vec::new()),
             registered_diagnostics: Lock::new(ErrorMap::new()),
-            non_modrs_mods: RefCell::new(vec![]),
+            non_modrs_mods: Lock::new(vec![]),
         }
     }
 
index 1483691a1eaee04a88886ad1ea484376f9ba4d6b..ff63c9a5c6d539ac1614011b5096a6aff631cc53 100644 (file)
@@ -23,7 +23,6 @@
 use tokenstream::{TokenStream, TokenTree};
 use diagnostics::plugin::ErrorMap;
 
-use std::cell::RefCell;
 use std::collections::HashSet;
 use std::iter;
 use std::path::{Path, PathBuf};
@@ -46,17 +45,17 @@ pub struct ParseSess {
     pub span_diagnostic: Handler,
     pub unstable_features: UnstableFeatures,
     pub config: CrateConfig,
-    pub missing_fragment_specifiers: RefCell<HashSet<Span>>,
+    pub missing_fragment_specifiers: Lock<HashSet<Span>>,
     /// Places where raw identifiers were used. This is used for feature gating
     /// raw identifiers
-    pub raw_identifier_spans: RefCell<Vec<Span>>,
+    pub raw_identifier_spans: Lock<Vec<Span>>,
     /// The registered diagnostics codes
     pub registered_diagnostics: Lock<ErrorMap>,
     // Spans where a `mod foo;` statement was included in a non-mod.rs file.
     // These are used to issue errors if the non_modrs_mods feature is not enabled.
-    pub non_modrs_mods: RefCell<Vec<(ast::Ident, Span)>>,
+    pub non_modrs_mods: Lock<Vec<(ast::Ident, Span)>>,
     /// Used to determine and report recursive mod inclusions
-    included_mod_stack: RefCell<Vec<PathBuf>>,
+    included_mod_stack: Lock<Vec<PathBuf>>,
     code_map: Lrc<CodeMap>,
 }
 
@@ -75,12 +74,12 @@ pub fn with_span_handler(handler: Handler, code_map: Lrc<CodeMap>) -> ParseSess
             span_diagnostic: handler,
             unstable_features: UnstableFeatures::from_environment(),
             config: HashSet::new(),
-            missing_fragment_specifiers: RefCell::new(HashSet::new()),
-            raw_identifier_spans: RefCell::new(Vec::new()),
+            missing_fragment_specifiers: Lock::new(HashSet::new()),
+            raw_identifier_spans: Lock::new(Vec::new()),
             registered_diagnostics: Lock::new(ErrorMap::new()),
-            included_mod_stack: RefCell::new(vec![]),
+            included_mod_stack: Lock::new(vec![]),
             code_map,
-            non_modrs_mods: RefCell::new(vec![]),
+            non_modrs_mods: Lock::new(vec![]),
         }
     }
 
@@ -689,7 +688,7 @@ fn sp(a: u32, b: u32) -> Span {
     }
 
     fn str2seg(s: &str, lo: u32, hi: u32) -> ast::PathSegment {
-        ast::PathSegment::from_ident(Ident::from_str(s), sp(lo, hi))
+        ast::PathSegment::from_ident(Ident::new(Symbol::intern(s), sp(lo, hi)))
     }
 
     #[test] fn path_exprs_1() {
@@ -873,10 +872,8 @@ fn parser_done(p: Parser){
                     == P(ast::Pat{
                     id: ast::DUMMY_NODE_ID,
                     node: PatKind::Ident(ast::BindingMode::ByValue(ast::Mutability::Immutable),
-                                        Spanned{ span:sp(0, 1),
-                                                node: Ident::from_str("b")
-                        },
-                                        None),
+                                         Ident::new(Symbol::intern("b"), sp(0, 1)),
+                                         None),
                     span: sp(0,1)}));
             parser_done(parser);
         })
@@ -912,9 +909,7 @@ fn parser_done(p: Parser){
                                             node: PatKind::Ident(
                                                 ast::BindingMode::ByValue(
                                                     ast::Mutability::Immutable),
-                                                Spanned{
-                                                    span: sp(6,7),
-                                                    node: Ident::from_str("b")},
+                                                Ident::new(Symbol::intern("b"), sp(6, 7)),
                                                 None
                                             ),
                                             span: sp(6,7)
index f5ab023b30e8f0fa4ff8cf12163c43b09dce6c7b..61de50e8e6affa53e3a7b37cf69cb835c709969b 100644 (file)
@@ -26,7 +26,7 @@
 use ast::{Label, Lifetime, LifetimeDef, Lit, LitKind, UintTy};
 use ast::Local;
 use ast::MacStmtStyle;
-use ast::Mac_;
+use ast::{Mac, Mac_};
 use ast::{MutTy, Mutability};
 use ast::{Pat, PatKind, PathSegment};
 use ast::{PolyTraitRef, QSelf};
@@ -512,13 +512,10 @@ fn from(expr: P<Expr>) -> Self {
 
 /// Create a placeholder argument.
 fn dummy_arg(span: Span) -> Arg {
-    let spanned = Spanned {
-        span,
-        node: keywords::Invalid.ident()
-    };
+    let ident = Ident::new(keywords::Invalid.name(), span);
     let pat = P(Pat {
         id: ast::DUMMY_NODE_ID,
-        node: PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), spanned, None),
+        node: PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), ident, None),
         span,
     });
     let ty = Ty {
@@ -778,7 +775,7 @@ pub fn parse_ident(&mut self) -> PResult<'a, ast::Ident> {
 
     fn parse_ident_common(&mut self, recover: bool) -> PResult<'a, ast::Ident> {
         match self.token {
-            token::Ident(i, _) => {
+            token::Ident(ident, _) => {
                 if self.token.is_reserved_ident() {
                     let mut err = self.expected_ident_found();
                     if recover {
@@ -787,8 +784,9 @@ fn parse_ident_common(&mut self, recover: bool) -> PResult<'a, ast::Ident> {
                         return Err(err);
                     }
                 }
+                let span = self.span;
                 self.bump();
-                Ok(i)
+                Ok(Ident::new(ident.name, span))
             }
             _ => {
                 Err(if self.prev_token_kind == PrevTokenKind::DocComment {
@@ -1319,19 +1317,6 @@ pub fn token_is_bare_fn_keyword(&mut self) -> bool {
             self.check_keyword(keywords::Extern) && self.is_extern_non_path()
     }
 
-    fn eat_label(&mut self) -> Option<Label> {
-        let ident = match self.token {
-            token::Lifetime(ref ident) => *ident,
-            token::Interpolated(ref nt) => match nt.0 {
-                token::NtLifetime(lifetime) => lifetime.ident,
-                _ => return None,
-            },
-            _ => return None,
-        };
-        self.bump();
-        Some(Label { ident, span: self.prev_span })
-    }
-
     /// parse a TyKind::BareFn type:
     pub fn parse_ty_bare_fn(&mut self, generic_params: Vec<GenericParam>)
                             -> PResult<'a, TyKind> {
@@ -1417,28 +1402,8 @@ fn parse_trait_item_(&mut self,
                 None
             };
             (ident, TraitItemKind::Const(ty, default), ast::Generics::default())
-        } else if self.token.is_path_start() && !self.is_extern_non_path() {
+        } else if let Some(mac) = self.parse_assoc_macro_invoc("trait", None, &mut false)? {
             // trait item macro.
-            // code copied from parse_macro_use_or_failure... abstraction!
-            let prev_span = self.prev_span;
-            let lo = self.span;
-            let pth = self.parse_path(PathStyle::Mod)?;
-
-            if pth.segments.len() == 1 {
-                if !self.eat(&token::Not) {
-                    return Err(self.missing_assoc_item_kind_err("trait", prev_span));
-                }
-            } else {
-                self.expect(&token::Not)?;
-            }
-
-            // eat a matched-delimiter token tree:
-            let (delim, tts) = self.expect_delimited_token_tree()?;
-            if delim != token::Brace {
-                self.expect(&token::Semi)?
-            }
-
-            let mac = respan(lo.to(self.prev_span), Mac_ { path: pth, tts: tts });
             (keywords::Invalid.ident(), ast::TraitItemKind::Macro(mac), ast::Generics::default())
         } else {
             let (constness, unsafety, abi) = self.parse_fn_front_matter()?;
@@ -1804,13 +1769,11 @@ pub fn parse_arg_general(&mut self, require_name: bool) -> PResult<'a, Arg> {
             pat
         } else {
             debug!("parse_arg_general ident_to_pat");
-            let sp = self.prev_span;
-            let spanned = Spanned { span: sp, node: keywords::Invalid.ident() };
+            let ident = Ident::new(keywords::Invalid.name(), self.prev_span);
             P(Pat {
                 id: ast::DUMMY_NODE_ID,
-                node: PatKind::Ident(BindingMode::ByValue(Mutability::Immutable),
-                                     spanned, None),
-                span: sp
+                node: PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), ident, None),
+                span: ident.span,
             })
         };
 
@@ -1919,13 +1882,14 @@ pub fn parse_pat_literal_maybe_minus(&mut self) -> PResult<'a, P<Expr>> {
 
     pub fn parse_path_segment_ident(&mut self) -> PResult<'a, ast::Ident> {
         match self.token {
-            token::Ident(sid, _) if self.token.is_path_segment_keyword() => {
+            token::Ident(ident, _) if self.token.is_path_segment_keyword() => {
+                let span = self.span;
                 self.bump();
-                Ok(sid)
+                Ok(Ident::new(ident.name, span))
             }
             _ => self.parse_ident(),
-         }
-     }
+        }
+    }
 
     /// Parses qualified path.
     /// Assumes that the leading `<` has been parsed already.
@@ -1993,7 +1957,7 @@ pub fn parse_path_allowing_meta(&mut self, style: PathStyle) -> PResult<'a, ast:
         let meta_ident = match self.token {
             token::Interpolated(ref nt) => match nt.0 {
                 token::NtMeta(ref meta) => match meta.node {
-                    ast::MetaItemKind::Word => Some(ast::Ident::with_empty_ctxt(meta.name)),
+                    ast::MetaItemKind::Word => Some(meta.ident),
                     _ => None,
                 },
                 _ => None,
@@ -2002,7 +1966,7 @@ pub fn parse_path_allowing_meta(&mut self, style: PathStyle) -> PResult<'a, ast:
         };
         if let Some(ident) = meta_ident {
             self.bump();
-            return Ok(ast::Path::from_ident(self.prev_span, ident));
+            return Ok(ast::Path::from_ident(ident));
         }
         self.parse_path(style)
     }
@@ -2023,7 +1987,6 @@ fn parse_path_segments(&mut self,
 
     fn parse_path_segment(&mut self, style: PathStyle, enable_warning: bool)
                           -> PResult<'a, PathSegment> {
-        let ident_span = self.span;
         let ident = self.parse_path_segment_ident()?;
 
         let is_args_start = |token: &token::Token| match *token {
@@ -2071,10 +2034,10 @@ fn parse_path_segment(&mut self, style: PathStyle, enable_warning: bool)
                 ParenthesizedParameterData { inputs, output, span }.into()
             };
 
-            PathSegment { identifier: ident, span: ident_span, parameters }
+            PathSegment { ident, parameters }
         } else {
             // Generic arguments are not found.
-            PathSegment::from_ident(ident, ident_span)
+            PathSegment::from_ident(ident)
         })
     }
 
@@ -2085,14 +2048,25 @@ fn check_lifetime(&mut self) -> bool {
 
     /// Parse single lifetime 'a or panic.
     pub fn expect_lifetime(&mut self) -> Lifetime {
-        if let Some(lifetime) = self.token.lifetime(self.span) {
+        if let Some(ident) = self.token.lifetime() {
+            let span = self.span;
             self.bump();
-            lifetime
+            Lifetime { ident: Ident::new(ident.name, span), id: ast::DUMMY_NODE_ID }
         } else {
             self.span_bug(self.span, "not a lifetime")
         }
     }
 
+    fn eat_label(&mut self) -> Option<Label> {
+        if let Some(ident) = self.token.lifetime() {
+            let span = self.span;
+            self.bump();
+            Some(Label { ident: Ident::new(ident.name, span) })
+        } else {
+            None
+        }
+    }
+
     /// Parse mutability (`mut` or nothing).
     fn parse_mutability(&mut self) -> Mutability {
         if self.eat_keyword(keywords::Mut) {
@@ -2105,7 +2079,7 @@ fn parse_mutability(&mut self) -> Mutability {
     pub fn parse_field_name(&mut self) -> PResult<'a, Ident> {
         if let token::Literal(token::Integer(name), None) = self.token {
             self.bump();
-            Ok(Ident::with_empty_ctxt(name))
+            Ok(Ident::new(name, self.prev_span))
         } else {
             self.parse_ident_common(false)
         }
@@ -2115,24 +2089,22 @@ pub fn parse_field_name(&mut self) -> PResult<'a, Ident> {
     pub fn parse_field(&mut self) -> PResult<'a, Field> {
         let attrs = self.parse_outer_attributes()?;
         let lo = self.span;
-        let hi;
 
         // Check if a colon exists one ahead. This means we're parsing a fieldname.
         let (fieldname, expr, is_shorthand) = if self.look_ahead(1, |t| t == &token::Colon) {
             let fieldname = self.parse_field_name()?;
-            hi = self.prev_span;
-            self.bump();
+            self.bump(); // `:`
             (fieldname, self.parse_expr()?, false)
         } else {
             let fieldname = self.parse_ident_common(false)?;
-            hi = self.prev_span;
 
             // Mimic `x: x` for the `x` field shorthand.
-            let path = ast::Path::from_ident(lo.to(hi), fieldname);
-            (fieldname, self.mk_expr(lo.to(hi), ExprKind::Path(None, path), ThinVec::new()), true)
+            let path = ast::Path::from_ident(fieldname);
+            let expr = self.mk_expr(fieldname.span, ExprKind::Path(None, path), ThinVec::new());
+            (fieldname, expr, true)
         };
         Ok(ast::Field {
-            ident: respan(lo.to(hi), fieldname),
+            ident: fieldname,
             span: lo.to(expr.span),
             expr,
             is_shorthand,
@@ -2338,7 +2310,7 @@ fn parse_bottom_expr(&mut self) -> PResult<'a, P<Expr>> {
                     return self.parse_while_expr(None, lo, attrs);
                 }
                 if let Some(label) = self.eat_label() {
-                    let lo = label.span;
+                    let lo = label.ident.span;
                     self.expect(&token::Colon)?;
                     if self.eat_keyword(keywords::While) {
                         return self.parse_while_expr(Some(label), lo, attrs)
@@ -2612,8 +2584,7 @@ fn parse_dot_suffix(&mut self, self_arg: P<Expr>, lo: Span) -> PResult<'a, P<Exp
                 }
 
                 let span = lo.to(self.prev_span);
-                let ident = respan(segment.span, segment.identifier);
-                self.mk_expr(span, ExprKind::Field(self_arg, ident), ThinVec::new())
+                self.mk_expr(span, ExprKind::Field(self_arg, segment.ident), ThinVec::new())
             }
         })
     }
@@ -2734,7 +2705,7 @@ fn parse_dot_or_call_expr_with_(&mut self, e0: P<Expr>, lo: Span) -> PResult<'a,
     }
 
     pub fn process_potential_macro_variable(&mut self) {
-        let (ident, is_raw) = match self.token {
+        let (token, span) = match self.token {
             token::Dollar if self.span.ctxt() != syntax_pos::hygiene::SyntaxContext::empty() &&
                              self.look_ahead(1, |t| t.is_ident()) => {
                 self.bump();
@@ -2749,15 +2720,18 @@ pub fn process_potential_macro_variable(&mut self) {
             }
             token::Interpolated(ref nt) => {
                 self.meta_var_span = Some(self.span);
+                // Interpolated identifier and lifetime tokens are replaced with usual identifier
+                // and lifetime tokens, so the former are never encountered during normal parsing.
                 match nt.0 {
-                    token::NtIdent(ident, is_raw) => (ident, is_raw),
+                    token::NtIdent(ident, is_raw) => (token::Ident(ident, is_raw), ident.span),
+                    token::NtLifetime(ident) => (token::Lifetime(ident), ident.span),
                     _ => return,
                 }
             }
             _ => return,
         };
-        self.token = token::Ident(ident.node, is_raw);
-        self.span = ident.span;
+        self.token = token;
+        self.span = span;
     }
 
     /// parse a single token tree from the input.
@@ -2856,7 +2830,48 @@ pub fn parse_prefix_expr(&mut self,
                 let (span, e) = self.interpolated_or_expr_span(e)?;
                 (lo.to(span), ExprKind::Box(e))
             }
-            _ => return self.parse_dot_or_call_expr(Some(attrs))
+            token::Ident(..) if self.token.is_ident_named("not") => {
+                // `not` is just an ordinary identifier in Rust-the-language,
+                // but as `rustc`-the-compiler, we can issue clever diagnostics
+                // for confused users who really want to say `!`
+                let token_cannot_continue_expr = |t: &token::Token| match *t {
+                    // These tokens can start an expression after `!`, but
+                    // can't continue an expression after an ident
+                    token::Ident(ident, is_raw) => token::ident_can_begin_expr(ident, is_raw),
+                    token::Literal(..) | token::Pound => true,
+                    token::Interpolated(ref nt) => match nt.0 {
+                        token::NtIdent(..) | token::NtExpr(..) |
+                        token::NtBlock(..) | token::NtPath(..) => true,
+                        _ => false,
+                    },
+                    _ => false
+                };
+                let cannot_continue_expr = self.look_ahead(1, token_cannot_continue_expr);
+                if cannot_continue_expr {
+                    self.bump();
+                    // Emit the error ...
+                    let mut err = self.diagnostic()
+                        .struct_span_err(self.span,
+                                         &format!("unexpected {} after identifier",
+                                                  self.this_token_descr()));
+                    // span the `not` plus trailing whitespace to avoid
+                    // trailing whitespace after the `!` in our suggestion
+                    let to_replace = self.sess.codemap()
+                        .span_until_non_whitespace(lo.to(self.span));
+                    err.span_suggestion_short(to_replace,
+                                              "use `!` to perform logical negation",
+                                              "!".to_owned());
+                    err.emit();
+                    // —and recover! (just as if we were in the block
+                    // for the `token::Not` arm)
+                    let e = self.parse_prefix_expr(None);
+                    let (span, e) = self.interpolated_or_expr_span(e)?;
+                    (lo.to(span), self.mk_unary(UnOp::Not, e))
+                } else {
+                    return self.parse_dot_or_call_expr(Some(attrs));
+                }
+            }
+            _ => { return self.parse_dot_or_call_expr(Some(attrs)); }
         };
         return Ok(self.mk_expr(lo.to(hi), ex, attrs));
     }
@@ -3692,10 +3707,9 @@ fn parse_pat_fields(&mut self) -> PResult<'a, (Vec<codemap::Spanned<ast::FieldPa
                     (false, true) => BindingMode::ByValue(Mutability::Mutable),
                     (false, false) => BindingMode::ByValue(Mutability::Immutable),
                 };
-                let fieldpath = codemap::Spanned{span:self.prev_span, node:fieldname};
                 let fieldpat = P(Pat {
                     id: ast::DUMMY_NODE_ID,
-                    node: PatKind::Ident(bind_type, fieldpath, None),
+                    node: PatKind::Ident(bind_type, fieldname, None),
                     span: boxed_span.to(hi),
                 });
 
@@ -3986,9 +4000,7 @@ fn parse_pat_with_range_pat(&mut self, allow_range_pat: bool) -> PResult<'a, P<P
     fn parse_pat_ident(&mut self,
                        binding_mode: ast::BindingMode)
                        -> PResult<'a, PatKind> {
-        let ident_span = self.span;
         let ident = self.parse_ident()?;
-        let name = codemap::Spanned{span: ident_span, node: ident};
         let sub = if self.eat(&token::At) {
             Some(self.parse_pat()?)
         } else {
@@ -4007,7 +4019,7 @@ fn parse_pat_ident(&mut self,
                 "expected identifier, found enum pattern"))
         }
 
-        Ok(PatKind::Ident(binding_mode, name, sub))
+        Ok(PatKind::Ident(binding_mode, ident, sub))
     }
 
     /// Parse a local variable declaration
@@ -4515,6 +4527,11 @@ pub fn parse_block(&mut self) -> PResult<'a, P<Block>> {
             // Which is valid in other languages, but not Rust.
             match self.parse_stmt_without_recovery(false) {
                 Ok(Some(stmt)) => {
+                    if self.look_ahead(1, |t| t == &token::OpenDelim(token::Brace)) {
+                        // if the next token is an open brace (e.g., `if a b {`), the place-
+                        // inside-a-block suggestion would be more likely wrong than right
+                        return Err(e);
+                    }
                     let mut stmt_span = stmt.span;
                     // expand the span to include the semicolon, if it exists
                     if self.eat(&token::Semi) {
@@ -4719,7 +4736,6 @@ fn parse_lt_param_bounds(&mut self) -> Vec<Lifetime> {
 
     /// Matches typaram = IDENT (`?` unbound)? optbounds ( EQ ty )?
     fn parse_ty_param(&mut self, preceding_attrs: Vec<Attribute>) -> PResult<'a, TyParam> {
-        let span = self.span;
         let ident = self.parse_ident()?;
 
         // Parse optional colon and param bounds.
@@ -4741,7 +4757,6 @@ fn parse_ty_param(&mut self, preceding_attrs: Vec<Attribute>) -> PResult<'a, TyP
             id: ast::DUMMY_NODE_ID,
             bounds,
             default,
-            span,
         })
     }
 
@@ -4749,7 +4764,6 @@ fn parse_ty_param(&mut self, preceding_attrs: Vec<Attribute>) -> PResult<'a, TyP
     ///     TraitItemAssocTy = Ident ["<"...">"] [":" [TyParamBounds]] ["where" ...] ["=" Ty]
     fn parse_trait_item_assoc_ty(&mut self, preceding_attrs: Vec<Attribute>)
         -> PResult<'a, (ast::Generics, TyParam)> {
-        let span = self.span;
         let ident = self.parse_ident()?;
         let mut generics = self.parse_generics()?;
 
@@ -4774,7 +4788,6 @@ fn parse_trait_item_assoc_ty(&mut self, preceding_attrs: Vec<Attribute>)
             id: ast::DUMMY_NODE_ID,
             bounds,
             default,
-            span,
         }))
     }
 
@@ -5071,9 +5084,8 @@ pub fn parse_fn_decl(&mut self, allow_variadic: bool) -> PResult<'a, P<FnDecl>>
     fn parse_self_arg(&mut self) -> PResult<'a, Option<Arg>> {
         let expect_ident = |this: &mut Self| match this.token {
             // Preserve hygienic context.
-            token::Ident(ident, _) => {
-                let sp = this.span; this.bump(); codemap::respan(sp, ident)
-            }
+            token::Ident(ident, _) =>
+                { let span = this.span; this.bump(); Ident::new(ident.name, span) }
             _ => unreachable!()
         };
         let isolated_self = |this: &mut Self, n| {
@@ -5393,6 +5405,12 @@ fn complain_if_pub_macro_diag(&mut self, vis: &VisibilityKind, sp: Span) -> PRes
     fn missing_assoc_item_kind_err(&mut self, item_type: &str, prev_span: Span)
                                    -> DiagnosticBuilder<'a>
     {
+        let expected_kinds = if item_type == "extern" {
+            "missing `fn`, `type`, or `static`"
+        } else {
+            "missing `fn`, `type`, or `const`"
+        };
+
         // Given this code `path(`, it seems like this is not
         // setting the visibility of a macro invocation, but rather
         // a mistyped method declaration.
@@ -5405,9 +5423,9 @@ fn missing_assoc_item_kind_err(&mut self, item_type: &str, prev_span: Span)
         let sp = prev_span.between(self.prev_span);
         let mut err = self.diagnostic().struct_span_err(
             sp,
-            &format!("missing `fn`, `type`, or `const` for {}-item declaration",
-                     item_type));
-        err.span_label(sp, "missing `fn`, `type`, or `const`");
+            &format!("{} for {}-item declaration",
+                     expected_kinds, item_type));
+        err.span_label(sp, expected_kinds);
         err
     }
 
@@ -5416,31 +5434,8 @@ fn parse_impl_method(&mut self, vis: &Visibility, at_end: &mut bool)
                          -> PResult<'a, (Ident, Vec<Attribute>, ast::Generics,
                              ast::ImplItemKind)> {
         // code copied from parse_macro_use_or_failure... abstraction!
-        if self.token.is_path_start() && !self.is_extern_non_path() {
+        if let Some(mac) = self.parse_assoc_macro_invoc("impl", Some(vis), at_end)? {
             // Method macro.
-
-            let prev_span = self.prev_span;
-
-            let lo = self.span;
-            let pth = self.parse_path(PathStyle::Mod)?;
-            if pth.segments.len() == 1 {
-                if !self.eat(&token::Not) {
-                    return Err(self.missing_assoc_item_kind_err("impl", prev_span));
-                }
-            } else {
-                self.expect(&token::Not)?;
-            }
-
-            self.complain_if_pub_macro(&vis.node, prev_span);
-
-            // eat a matched-delimiter token tree:
-            *at_end = true;
-            let (delim, tts) = self.expect_delimited_token_tree()?;
-            if delim != token::Brace {
-                self.expect(&token::Semi)?
-            }
-
-            let mac = respan(lo.to(self.prev_span), Mac_ { path: pth, tts: tts });
             Ok((keywords::Invalid.ident(), vec![], ast::Generics::default(),
                 ast::ImplItemKind::Macro(mac)))
         } else {
@@ -5603,7 +5598,7 @@ fn parse_item_impl(&mut self, unsafety: Unsafety, defaultness: Defaultness)
                     TyKind::Path(None, path) => path,
                     _ => {
                         self.span_err(ty_first.span, "expected a trait, found type");
-                        ast::Path::from_ident(ty_first.span, keywords::Invalid.ident())
+                        ast::Path::from_ident(Ident::new(keywords::Invalid.name(), ty_first.span))
                     }
                 };
                 let trait_ref = TraitRef { path, ref_id: ty_first.id };
@@ -5988,8 +5983,7 @@ fn parse_item_mod(&mut self, outer_attrs: &[Attribute]) -> PResult<'a, ItemInfo>
                     let attr = Attribute {
                         id: attr::mk_attr_id(),
                         style: ast::AttrStyle::Outer,
-                        path: ast::Path::from_ident(syntax_pos::DUMMY_SP,
-                                                    Ident::from_str("warn_directory_ownership")),
+                        path: ast::Path::from_ident(Ident::from_str("warn_directory_ownership")),
                         tokens: TokenStream::empty(),
                         is_sugared_doc: false,
                         span: syntax_pos::DUMMY_SP,
@@ -6371,7 +6365,7 @@ fn parse_enum_def(&mut self, _generics: &ast::Generics) -> PResult<'a, EnumDef>
             }
 
             let vr = ast::Variant_ {
-                name: ident,
+                ident,
                 attrs: variant_attrs,
                 data: struct_def,
                 disr_expr,
@@ -6786,7 +6780,9 @@ fn parse_item_(&mut self, attrs: Vec<Attribute>,
     }
 
     /// Parse a foreign item.
-    fn parse_foreign_item(&mut self) -> PResult<'a, Option<ForeignItem>> {
+    pub fn parse_foreign_item(&mut self) -> PResult<'a, Option<ForeignItem>> {
+        maybe_whole!(self, NtForeignItem, |ni| Some(ni));
+
         let attrs = self.parse_outer_attributes()?;
         let lo = self.span;
         let visibility = self.parse_visibility(false)?;
@@ -6812,12 +6808,26 @@ fn parse_foreign_item(&mut self) -> PResult<'a, Option<ForeignItem>> {
             return Ok(Some(self.parse_item_foreign_type(visibility, lo, attrs)?));
         }
 
-        // FIXME #5668: this will occur for a macro invocation:
-        match self.parse_macro_use_or_failure(attrs, true, false, lo, visibility)? {
-            Some(item) => {
-                return Err(self.span_fatal(item.span, "macros cannot expand to foreign items"));
+        match self.parse_assoc_macro_invoc("extern", Some(&visibility), &mut false)? {
+            Some(mac) => {
+                Ok(Some(
+                    ForeignItem {
+                        ident: keywords::Invalid.ident(),
+                        span: lo.to(self.prev_span),
+                        id: ast::DUMMY_NODE_ID,
+                        attrs,
+                        vis: visibility,
+                        node: ForeignItemKind::Macro(mac),
+                    }
+                ))
+            }
+            None => {
+                if !attrs.is_empty() {
+                    self.expected_item_err(&attrs);
+                }
+
+                Ok(None)
             }
-            None => Ok(None)
         }
     }
 
@@ -6881,6 +6891,41 @@ fn parse_macro_use_or_failure(
         Ok(None)
     }
 
+    /// Parse a macro invocation inside a `trait`, `impl` or `extern` block
+    fn parse_assoc_macro_invoc(&mut self, item_kind: &str, vis: Option<&Visibility>,
+                               at_end: &mut bool) -> PResult<'a, Option<Mac>>
+    {
+        if self.token.is_path_start() && !self.is_extern_non_path() {
+            let prev_span = self.prev_span;
+            let lo = self.span;
+            let pth = self.parse_path(PathStyle::Mod)?;
+
+            if pth.segments.len() == 1 {
+                if !self.eat(&token::Not) {
+                    return Err(self.missing_assoc_item_kind_err(item_kind, prev_span));
+                }
+            } else {
+                self.expect(&token::Not)?;
+            }
+
+            if let Some(vis) = vis {
+                self.complain_if_pub_macro(&vis.node, prev_span);
+            }
+
+            *at_end = true;
+
+            // eat a matched-delimiter token tree:
+            let (delim, tts) = self.expect_delimited_token_tree()?;
+            if delim != token::Brace {
+                self.expect(&token::Semi)?
+            }
+
+            Ok(Some(respan(lo.to(self.prev_span), Mac_ { path: pth, tts: tts })))
+        } else {
+            Ok(None)
+        }
+    }
+
     fn collect_tokens<F, R>(&mut self, f: F) -> PResult<'a, (R, TokenStream)>
         where F: FnOnce(&mut Self) -> PResult<'a, R>
     {
index e2dfca5d10a3c51a189718372b95bb076f6acd35..8da79f92768a1c31e3658f7a6b4654301f2ebada 100644 (file)
@@ -25,9 +25,8 @@
 use tokenstream::{TokenStream, TokenTree};
 use tokenstream;
 
-use std::cell::Cell;
 use std::{cmp, fmt};
-use rustc_data_structures::sync::Lrc;
+use rustc_data_structures::sync::{Lrc, Lock};
 
 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug, Copy)]
 pub enum BinOpToken {
@@ -91,7 +90,7 @@ pub fn short_name(&self) -> &'static str {
     }
 }
 
-fn ident_can_begin_expr(ident: ast::Ident, is_raw: bool) -> bool {
+pub(crate) fn ident_can_begin_expr(ident: ast::Ident, is_raw: bool) -> bool {
     let ident_token: Token = Ident(ident, is_raw);
 
     !ident_token.is_reserved_ident() ||
@@ -317,21 +316,45 @@ pub fn is_lit(&self) -> bool {
         }
     }
 
-    pub fn ident(&self) -> Option<(ast::Ident, bool)> {
+    /// Returns an identifier if this token is an identifier.
+    pub fn ident(&self) -> Option<(ast::Ident, /* is_raw */ bool)> {
         match *self {
             Ident(ident, is_raw) => Some((ident, is_raw)),
             Interpolated(ref nt) => match nt.0 {
-                NtIdent(ident, is_raw) => Some((ident.node, is_raw)),
+                NtIdent(ident, is_raw) => Some((ident, is_raw)),
+                _ => None,
+            },
+            _ => None,
+        }
+    }
+    /// Returns a lifetime identifier if this token is a lifetime.
+    pub fn lifetime(&self) -> Option<ast::Ident> {
+        match *self {
+            Lifetime(ident) => Some(ident),
+            Interpolated(ref nt) => match nt.0 {
+                NtLifetime(ident) => Some(ident),
                 _ => None,
             },
             _ => None,
         }
     }
-
     /// Returns `true` if the token is an identifier.
     pub fn is_ident(&self) -> bool {
         self.ident().is_some()
     }
+    /// Returns `true` if the token is a lifetime.
+    pub fn is_lifetime(&self) -> bool {
+        self.lifetime().is_some()
+    }
+
+    /// Returns `true` if the token is a identifier whose name is the given
+    /// string slice.
+    pub fn is_ident_named(&self, name: &str) -> bool {
+        match self.ident() {
+            Some((ident, _)) => ident.name.as_str() == name,
+            None => false
+        }
+    }
 
     /// Returns `true` if the token is a documentation comment.
     pub fn is_doc_comment(&self) -> bool {
@@ -359,26 +382,6 @@ pub fn is_path(&self) -> bool {
         false
     }
 
-    /// Returns a lifetime with the span and a dummy id if it is a lifetime,
-    /// or the original lifetime if it is an interpolated lifetime, ignoring
-    /// the span.
-    pub fn lifetime(&self, span: Span) -> Option<ast::Lifetime> {
-        match *self {
-            Lifetime(ident) =>
-                Some(ast::Lifetime { ident: ident, span: span, id: ast::DUMMY_NODE_ID }),
-            Interpolated(ref nt) => match nt.0 {
-                NtLifetime(lifetime) => Some(lifetime),
-                _ => None,
-            },
-            _ => None,
-        }
-    }
-
-    /// Returns `true` if the token is a lifetime.
-    pub fn is_lifetime(&self) -> bool {
-        self.lifetime(syntax_pos::DUMMY_SP).is_some()
-    }
-
     /// Returns `true` if the token is either the `mut` or `const` keyword.
     pub fn is_mutability(&self) -> bool {
         self.is_keyword(keywords::Mut) ||
@@ -431,6 +434,14 @@ pub fn is_unused_keyword(&self) -> bool {
         }
     }
 
+    /// Returns `true` if the token is either a special identifier or a keyword.
+    pub fn is_reserved_ident(&self) -> bool {
+        match self.ident() {
+            Some((id, false)) => is_reserved_ident(id),
+            _ => false,
+        }
+    }
+
     pub fn glue(self, joint: Token) -> Option<Token> {
         Some(match self {
             Eq => match joint {
@@ -497,14 +508,6 @@ pub fn similar_tokens(&self) -> Option<Vec<Token>> {
         }
     }
 
-    /// Returns `true` if the token is either a special identifier or a keyword.
-    pub fn is_reserved_ident(&self) -> bool {
-        match self.ident() {
-            Some((id, false)) => is_reserved_ident(id),
-            _ => false,
-        }
-    }
-
     pub fn interpolated_to_tokenstream(&self, sess: &ParseSess, span: Span)
         -> TokenStream
     {
@@ -539,12 +542,12 @@ pub fn interpolated_to_tokenstream(&self, sess: &ParseSess, span: Span)
                 tokens = prepend_attrs(sess, &item.attrs, item.tokens.as_ref(), span);
             }
             Nonterminal::NtIdent(ident, is_raw) => {
-                let token = Token::Ident(ident.node, is_raw);
+                let token = Token::Ident(ident, is_raw);
                 tokens = Some(TokenTree::Token(ident.span, token).into());
             }
-            Nonterminal::NtLifetime(lifetime) => {
-                let token = Token::Lifetime(lifetime.ident);
-                tokens = Some(TokenTree::Token(lifetime.span, token).into());
+            Nonterminal::NtLifetime(ident) => {
+                let token = Token::Lifetime(ident);
+                tokens = Some(TokenTree::Token(ident.span, token).into());
             }
             Nonterminal::NtTT(ref tt) => {
                 tokens = Some(tt.clone().into());
@@ -571,7 +574,8 @@ pub enum Nonterminal {
     NtPat(P<ast::Pat>),
     NtExpr(P<ast::Expr>),
     NtTy(P<ast::Ty>),
-    NtIdent(ast::SpannedIdent, /* is_raw */ bool),
+    NtIdent(ast::Ident, /* is_raw */ bool),
+    NtLifetime(ast::Ident),
     /// Stuff inside brackets for attributes
     NtMeta(ast::MetaItem),
     NtPath(ast::Path),
@@ -581,10 +585,10 @@ pub enum Nonterminal {
     NtArm(ast::Arm),
     NtImplItem(ast::ImplItem),
     NtTraitItem(ast::TraitItem),
+    NtForeignItem(ast::ForeignItem),
     NtGenerics(ast::Generics),
     NtWhereClause(ast::WhereClause),
     NtArg(ast::Arg),
-    NtLifetime(ast::Lifetime),
 }
 
 impl fmt::Debug for Nonterminal {
@@ -603,6 +607,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
             NtArm(..) => f.pad("NtArm(..)"),
             NtImplItem(..) => f.pad("NtImplItem(..)"),
             NtTraitItem(..) => f.pad("NtTraitItem(..)"),
+            NtForeignItem(..) => f.pad("NtForeignItem(..)"),
             NtGenerics(..) => f.pad("NtGenerics(..)"),
             NtWhereClause(..) => f.pad("NtWhereClause(..)"),
             NtArg(..) => f.pad("NtArg(..)"),
@@ -621,15 +626,8 @@ pub fn is_op(tok: &Token) -> bool {
     }
 }
 
-pub struct LazyTokenStream(Cell<Option<TokenStream>>);
-
-impl Clone for LazyTokenStream {
-    fn clone(&self) -> Self {
-        let opt_stream = self.0.take();
-        self.0.set(opt_stream.clone());
-        LazyTokenStream(Cell::new(opt_stream))
-    }
-}
+#[derive(Clone)]
+pub struct LazyTokenStream(Lock<Option<TokenStream>>);
 
 impl cmp::Eq for LazyTokenStream {}
 impl PartialEq for LazyTokenStream {
@@ -646,15 +644,14 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 
 impl LazyTokenStream {
     pub fn new() -> Self {
-        LazyTokenStream(Cell::new(None))
+        LazyTokenStream(Lock::new(None))
     }
 
     pub fn force<F: FnOnce() -> TokenStream>(&self, f: F) -> TokenStream {
-        let mut opt_stream = self.0.take();
+        let mut opt_stream = self.0.lock();
         if opt_stream.is_none() {
-            opt_stream = Some(f());
+            *opt_stream = Some(f());
         }
-        self.0.set(opt_stream.clone());
         opt_stream.clone().unwrap()
     }
 }
index c3785c10f6905bd6f941284ebd3a416e1998b8df..8168db19058764f0585f148769062c1ffd917510 100644 (file)
@@ -26,7 +26,7 @@
 use print::pp::Breaks::{Consistent, Inconsistent};
 use ptr::P;
 use std_inject;
-use symbol::{Symbol, keywords};
+use symbol::keywords;
 use syntax_pos::{DUMMY_SP, FileName};
 use tokenstream::{self, TokenStream, TokenTree};
 
@@ -94,20 +94,20 @@ pub fn print_crate<'a>(cm: &'a CodeMap,
                        is_expanded: bool) -> io::Result<()> {
     let mut s = State::new_from_input(cm, sess, filename, input, out, ann, is_expanded);
 
-    if is_expanded && !std_inject::injected_crate_name().is_none() {
+    if is_expanded && std_inject::injected_crate_name().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
         // of the feature gate, so we fake them up here.
 
         // #![feature(prelude_import)]
-        let prelude_import_meta = attr::mk_list_word_item(Symbol::intern("prelude_import"));
-        let list = attr::mk_list_item(Symbol::intern("feature"), vec![prelude_import_meta]);
+        let pi_nested = attr::mk_nested_word_item(ast::Ident::from_str("prelude_import"));
+        let list = attr::mk_list_item(DUMMY_SP, ast::Ident::from_str("feature"), vec![pi_nested]);
         let fake_attr = attr::mk_attr_inner(DUMMY_SP, attr::mk_attr_id(), list);
         s.print_attribute(&fake_attr)?;
 
         // #![no_std]
-        let no_std_meta = attr::mk_word_item(Symbol::intern("no_std"));
+        let no_std_meta = attr::mk_word_item(ast::Ident::from_str("no_std"));
         let fake_attr = attr::mk_attr_inner(DUMMY_SP, attr::mk_attr_id(), no_std_meta);
         s.print_attribute(&fake_attr)?;
     }
@@ -262,25 +262,26 @@ pub fn token_to_string(tok: &Token) -> String {
         token::Shebang(s)           => format!("/* shebang: {}*/", s),
 
         token::Interpolated(ref nt) => match nt.0 {
-            token::NtExpr(ref e)         => expr_to_string(e),
-            token::NtMeta(ref e)         => meta_item_to_string(e),
-            token::NtTy(ref e)           => ty_to_string(e),
-            token::NtPath(ref e)         => path_to_string(e),
-            token::NtItem(ref e)         => item_to_string(e),
-            token::NtBlock(ref e)        => block_to_string(e),
-            token::NtStmt(ref e)         => stmt_to_string(e),
-            token::NtPat(ref e)          => pat_to_string(e),
-            token::NtIdent(ref e, false) => ident_to_string(e.node),
-            token::NtIdent(ref e, true)  => format!("r#{}", ident_to_string(e.node)),
-            token::NtTT(ref tree)        => tt_to_string(tree.clone()),
-            token::NtArm(ref e)          => arm_to_string(e),
-            token::NtImplItem(ref e)     => impl_item_to_string(e),
-            token::NtTraitItem(ref e)    => trait_item_to_string(e),
-            token::NtGenerics(ref e)     => generic_params_to_string(&e.params),
-            token::NtWhereClause(ref e)  => where_clause_to_string(e),
-            token::NtArg(ref e)          => arg_to_string(e),
-            token::NtVis(ref e)          => vis_to_string(e),
-            token::NtLifetime(ref e)     => lifetime_to_string(e),
+            token::NtExpr(ref e)        => expr_to_string(e),
+            token::NtMeta(ref e)        => meta_item_to_string(e),
+            token::NtTy(ref e)          => ty_to_string(e),
+            token::NtPath(ref e)        => path_to_string(e),
+            token::NtItem(ref e)        => item_to_string(e),
+            token::NtBlock(ref e)       => block_to_string(e),
+            token::NtStmt(ref e)        => stmt_to_string(e),
+            token::NtPat(ref e)         => pat_to_string(e),
+            token::NtIdent(e, false)    => ident_to_string(e),
+            token::NtIdent(e, true)     => format!("r#{}", ident_to_string(e)),
+            token::NtLifetime(e)        => ident_to_string(e),
+            token::NtTT(ref tree)       => tt_to_string(tree.clone()),
+            token::NtArm(ref e)         => arm_to_string(e),
+            token::NtImplItem(ref e)    => impl_item_to_string(e),
+            token::NtTraitItem(ref e)   => trait_item_to_string(e),
+            token::NtGenerics(ref e)    => generic_params_to_string(&e.params),
+            token::NtWhereClause(ref e) => where_clause_to_string(e),
+            token::NtArg(ref e)         => arg_to_string(e),
+            token::NtVis(ref e)         => vis_to_string(e),
+            token::NtForeignItem(ref e) => foreign_item_to_string(e),
         }
     }
 }
@@ -422,6 +423,10 @@ pub fn mac_to_string(arg: &ast::Mac) -> String {
     to_string(|s| s.print_mac(arg, ::parse::token::Paren))
 }
 
+pub fn foreign_item_to_string(arg: &ast::ForeignItem) -> String {
+    to_string(|s| s.print_foreign_item(arg))
+}
+
 pub fn visibility_qualified(vis: &ast::Visibility, s: &str) -> String {
     format!("{}{}", to_string(|s| s.print_visibility(vis)), s)
 }
@@ -734,11 +739,11 @@ fn print_attribute_inline(&mut self, attr: &ast::Attribute,
                     if i > 0 {
                         self.writer().word("::")?
                     }
-                    if segment.identifier.name != keywords::CrateRoot.name() &&
-                       segment.identifier.name != keywords::DollarCrate.name() {
-                        self.writer().word(&segment.identifier.name.as_str())?;
-                    } else if segment.identifier.name == keywords::DollarCrate.name() {
-                        self.print_dollar_crate(segment.identifier.ctxt)?;
+                    if segment.ident.name != keywords::CrateRoot.name() &&
+                       segment.ident.name != keywords::DollarCrate.name() {
+                        self.writer().word(&segment.ident.name.as_str())?;
+                    } else if segment.ident.name == keywords::DollarCrate.name() {
+                        self.print_dollar_crate(segment.ident.span.ctxt())?;
                     }
                 }
                 self.writer().space()?;
@@ -763,15 +768,15 @@ fn print_meta_item(&mut self, item: &ast::MetaItem) -> io::Result<()> {
         self.ibox(INDENT_UNIT)?;
         match item.node {
             ast::MetaItemKind::Word => {
-                self.writer().word(&item.name.as_str())?;
+                self.writer().word(&item.ident.name.as_str())?;
             }
             ast::MetaItemKind::NameValue(ref value) => {
-                self.word_space(&item.name.as_str())?;
+                self.word_space(&item.ident.name.as_str())?;
                 self.word_space("=")?;
                 self.print_literal(value)?;
             }
             ast::MetaItemKind::List(ref items) => {
-                self.writer().word(&item.name.as_str())?;
+                self.writer().word(&item.ident.name.as_str())?;
                 self.popen()?;
                 self.commasep(Consistent,
                               &items[..],
@@ -1127,6 +1132,10 @@ pub fn print_foreign_item(&mut self,
                 self.end()?; // end the head-ibox
                 self.end() // end the outer cbox
             }
+            ast::ForeignItemKind::Macro(ref m) => {
+                self.print_mac(m, token::Paren)?;
+                self.s.word(";")
+            }
         }
     }
 
@@ -1531,7 +1540,7 @@ pub fn print_struct(&mut self,
     pub fn print_variant(&mut self, v: &ast::Variant) -> io::Result<()> {
         self.head("")?;
         let generics = ast::Generics::default();
-        self.print_struct(&v.node.data, &generics, v.node.name, v.span, false)?;
+        self.print_struct(&v.node.data, &generics, v.node.ident, v.span, false)?;
         match v.node.disr_expr {
             Some(ref d) => {
                 self.s.space()?;
@@ -1915,7 +1924,7 @@ fn print_expr_struct(&mut self,
             |s, field| {
                 s.ibox(INDENT_UNIT)?;
                 if !field.is_shorthand {
-                    s.print_ident(field.ident.node)?;
+                    s.print_ident(field.ident)?;
                     s.word_space(":")?;
                 }
                 s.print_expr(&field.expr)?;
@@ -1972,7 +1981,7 @@ fn print_expr_method_call(&mut self,
         let base_args = &args[1..];
         self.print_expr_maybe_paren(&args[0], parser::PREC_POSTFIX)?;
         self.s.word(".")?;
-        self.print_ident(segment.identifier)?;
+        self.print_ident(segment.ident)?;
         if let Some(ref parameters) = segment.parameters {
             self.print_path_parameters(parameters, true)?;
         }
@@ -2189,10 +2198,10 @@ fn print_expr_outer_attr_style(&mut self,
                 self.word_space("=")?;
                 self.print_expr_maybe_paren(rhs, prec)?;
             }
-            ast::ExprKind::Field(ref expr, id) => {
+            ast::ExprKind::Field(ref expr, ident) => {
                 self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX)?;
                 self.s.word(".")?;
-                self.print_ident(id.node)?;
+                self.print_ident(ident)?;
             }
             ast::ExprKind::TupField(ref expr, id) => {
                 self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX)?;
@@ -2408,14 +2417,14 @@ fn print_path_segment(&mut self,
                           colons_before_params: bool)
                           -> io::Result<()>
     {
-        if segment.identifier.name != keywords::CrateRoot.name() &&
-           segment.identifier.name != keywords::DollarCrate.name() {
-            self.print_ident(segment.identifier)?;
+        if segment.ident.name != keywords::CrateRoot.name() &&
+           segment.ident.name != keywords::DollarCrate.name() {
+            self.print_ident(segment.ident)?;
             if let Some(ref parameters) = segment.parameters {
                 self.print_path_parameters(parameters, colons_before_params)?;
             }
-        } else if segment.identifier.name == keywords::DollarCrate.name() {
-            self.print_dollar_crate(segment.identifier.ctxt)?;
+        } else if segment.ident.name == keywords::DollarCrate.name() {
+            self.print_dollar_crate(segment.ident.span.ctxt())?;
         }
         Ok(())
     }
@@ -2437,7 +2446,7 @@ fn print_qpath(&mut self,
         self.s.word(">")?;
         self.s.word("::")?;
         let item_segment = path.segments.last().unwrap();
-        self.print_ident(item_segment.identifier)?;
+        self.print_ident(item_segment.ident)?;
         match item_segment.parameters {
             Some(ref parameters) => self.print_path_parameters(parameters, colons_before_params),
             None => Ok(()),
@@ -2517,7 +2526,7 @@ pub fn print_pat(&mut self, pat: &ast::Pat) -> io::Result<()> {
          is that it doesn't matter */
         match pat.node {
             PatKind::Wild => self.s.word("_")?,
-            PatKind::Ident(binding_mode, ref path1, ref sub) => {
+            PatKind::Ident(binding_mode, ident, ref sub) => {
                 match binding_mode {
                     ast::BindingMode::ByRef(mutbl) => {
                         self.word_nbsp("ref")?;
@@ -2528,7 +2537,7 @@ pub fn print_pat(&mut self, pat: &ast::Pat) -> io::Result<()> {
                         self.word_nbsp("mut")?;
                     }
                 }
-                self.print_ident(path1.node)?;
+                self.print_ident(ident)?;
                 if let Some(ref p) = *sub {
                     self.s.word("@")?;
                     self.print_pat(p)?;
@@ -2990,7 +2999,7 @@ pub fn print_arg(&mut self, input: &ast::Arg, is_closure: bool) -> io::Result<()
                     self.print_explicit_self(&eself)?;
                 } else {
                     let invalid = if let PatKind::Ident(_, ident, _) = input.pat.node {
-                        ident.node.name == keywords::Invalid.name()
+                        ident.name == keywords::Invalid.name()
                     } else {
                         false
                     };
@@ -3185,7 +3194,7 @@ fn test_variant_to_string() {
             let ident = ast::Ident::from_str("principal_skinner");
 
             let var = codemap::respan(syntax_pos::DUMMY_SP, ast::Variant_ {
-                name: ident,
+                ident,
                 attrs: Vec::new(),
                 // making this up as I go.... ?
                 data: ast::VariantData::Unit(ast::DUMMY_NODE_ID),
index fdbc795b2d365500e81ac29da08ba6733008de8f..bba7a2d73773646d5db9df809836d6645e811177 100644 (file)
@@ -44,33 +44,44 @@ pub fn injected_crate_name() -> Option<&'static str> {
 }
 
 pub fn maybe_inject_crates_ref(mut krate: ast::Crate, alt_std_name: Option<&str>) -> ast::Crate {
-    let name = if attr::contains_name(&krate.attrs, "no_core") {
+    // 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, "no_core") {
         return krate;
     } else if attr::contains_name(&krate.attrs, "no_std") {
-        "core"
+        if attr::contains_name(&krate.attrs, "compiler_builtins") {
+            &["core"]
+        } else {
+            &["core", "compiler_builtins"]
+        }
     } else {
-        "std"
+        &["std"]
     };
 
-    INJECTED_CRATE_NAME.with(|opt_name| opt_name.set(Some(name)));
+    for name in names {
+        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::from_str("macro_use")))],
+            vis: dummy_spanned(ast::VisibilityKind::Inherited),
+            node: ast::ItemKind::ExternCrate(alt_std_name.map(Symbol::intern)),
+            ident: ast::Ident::from_str(name),
+            id: ast::DUMMY_NODE_ID,
+            span: DUMMY_SP,
+            tokens: 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(Symbol::intern("macro_use")))],
-        vis: dummy_spanned(ast::VisibilityKind::Inherited),
-        node: ast::ItemKind::ExternCrate(alt_std_name.map(Symbol::intern)),
-        ident: ast::Ident::from_str(name),
-        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 = ignored_span(DUMMY_SP);
     krate.module.items.insert(0, P(ast::Item {
         attrs: vec![ast::Attribute {
             style: ast::AttrStyle::Outer,
-            path: ast::Path::from_ident(span, ast::Ident::from_str("prelude_import")),
+            path: ast::Path::from_ident(ast::Ident::new(Symbol::intern("prelude_import"), span)),
             tokens: TokenStream::empty(),
             id: attr::mk_attr_id(),
             is_sugared_doc: false,
@@ -80,7 +91,7 @@ pub fn maybe_inject_crates_ref(mut krate: ast::Crate, alt_std_name: Option<&str>
         node: ast::ItemKind::Use(P(ast::UseTree {
             prefix: ast::Path {
                 segments: [name, "prelude", "v1"].into_iter().map(|name| {
-                    ast::PathSegment::from_ident(ast::Ident::from_str(name), DUMMY_SP)
+                    ast::PathSegment::from_ident(ast::Ident::from_str(name))
                 }).collect(),
                 span,
             },
index 67a822e4e02af052a7db504dd50db193b33f3778..fd2e760e9bee0ab5108d76eb779735280dcf909b 100644 (file)
@@ -195,10 +195,10 @@ fn fold_item(&mut self, i: P<ast::Item>) -> SmallVector<P<ast::Item>> {
             EntryPointType::MainAttr |
             EntryPointType::Start =>
                 folded.map(|ast::Item {id, ident, attrs, node, vis, span, tokens}| {
-                    let allow_str = Symbol::intern("allow");
-                    let dead_code_str = Symbol::intern("dead_code");
-                    let word_vec = vec![attr::mk_list_word_item(dead_code_str)];
-                    let allow_dead_code_item = attr::mk_list_item(allow_str, word_vec);
+                    let allow_ident = Ident::from_str("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);
@@ -623,7 +623,7 @@ fn nospan<T>(t: T) -> codemap::Spanned<T> {
 fn path_node(ids: Vec<Ident>) -> ast::Path {
     ast::Path {
         span: DUMMY_SP,
-        segments: ids.into_iter().map(|id| ast::PathSegment::from_ident(id, DUMMY_SP)).collect(),
+        segments: ids.into_iter().map(|id| ast::PathSegment::from_ident(id)).collect(),
     }
 }
 
index da238be85e0e2dee751e34a4c6f30bc89835c189..d4c6b4b158b25dc2590063e1e04d6e0cced892c7 100644 (file)
@@ -27,9 +27,9 @@ pub fn new() -> NodeCounter {
 }
 
 impl<'ast> Visitor<'ast> for NodeCounter {
-    fn visit_ident(&mut self, span: Span, ident: Ident) {
+    fn visit_ident(&mut self, ident: Ident) {
         self.count += 1;
-        walk_ident(self, span, ident);
+        walk_ident(self, ident);
     }
     fn visit_mod(&mut self, m: &Mod, _s: Span, _a: &[Attribute], _n: NodeId) {
         self.count += 1;
index d8de78054ab6f4ecce75f663503a2572abb5489f..fdb3e2c5f31db138e55b23eeda7c4500df1a23f7 100644 (file)
@@ -55,8 +55,8 @@ pub trait Visitor<'ast>: Sized {
     fn visit_name(&mut self, _span: Span, _name: Name) {
         // Nothing to do.
     }
-    fn visit_ident(&mut self, span: Span, ident: Ident) {
-        walk_ident(self, span, ident);
+    fn visit_ident(&mut self, ident: Ident) {
+        walk_ident(self, ident);
     }
     fn visit_mod(&mut self, m: &'ast Mod, _s: Span, _attrs: &[Attribute], _n: NodeId) {
         walk_mod(self, m);
@@ -166,8 +166,8 @@ macro_rules! walk_list {
     }
 }
 
-pub fn walk_ident<'a, V: Visitor<'a>>(visitor: &mut V, span: Span, ident: Ident) {
-    visitor.visit_name(span, ident.name);
+pub fn walk_ident<'a, V: Visitor<'a>>(visitor: &mut V, ident: Ident) {
+    visitor.visit_name(ident.span, ident.name);
 }
 
 pub fn walk_crate<'a, V: Visitor<'a>>(visitor: &mut V, krate: &'a Crate) {
@@ -189,11 +189,11 @@ pub fn walk_local<'a, V: Visitor<'a>>(visitor: &mut V, local: &'a Local) {
 }
 
 pub fn walk_label<'a, V: Visitor<'a>>(visitor: &mut V, label: &'a Label) {
-    visitor.visit_ident(label.span, label.ident);
+    visitor.visit_ident(label.ident);
 }
 
 pub fn walk_lifetime<'a, V: Visitor<'a>>(visitor: &mut V, lifetime: &'a Lifetime) {
-    visitor.visit_ident(lifetime.span, lifetime.ident);
+    visitor.visit_ident(lifetime.ident);
 }
 
 pub fn walk_poly_trait_ref<'a, V>(visitor: &mut V,
@@ -211,7 +211,7 @@ pub fn walk_trait_ref<'a, V: Visitor<'a>>(visitor: &mut V, trait_ref: &'a TraitR
 
 pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
     visitor.visit_vis(&item.vis);
-    visitor.visit_ident(item.span, item.ident);
+    visitor.visit_ident(item.ident);
     match item.node {
         ItemKind::ExternCrate(orig_name) => {
             if let Some(orig_name) = orig_name {
@@ -293,8 +293,8 @@ pub fn walk_variant<'a, V>(visitor: &mut V,
                            item_id: NodeId)
     where V: Visitor<'a>,
 {
-    visitor.visit_ident(variant.span, variant.node.name);
-    visitor.visit_variant_data(&variant.node.data, variant.node.name,
+    visitor.visit_ident(variant.node.ident);
+    visitor.visit_variant_data(&variant.node.data, variant.node.ident,
                              generics, item_id, variant.span);
     walk_list!(visitor, visit_expr, &variant.node.disr_expr);
     walk_list!(visitor, visit_attribute, &variant.node.attrs);
@@ -357,7 +357,7 @@ pub fn walk_use_tree<'a, V: Visitor<'a>>(
     match use_tree.kind {
         UseTreeKind::Simple(rename) => {
             if let Some(rename) = rename {
-                visitor.visit_ident(use_tree.span, rename);
+                visitor.visit_ident(rename);
             }
         }
         UseTreeKind::Glob => {},
@@ -372,7 +372,7 @@ pub fn walk_use_tree<'a, V: Visitor<'a>>(
 pub fn walk_path_segment<'a, V: Visitor<'a>>(visitor: &mut V,
                                              path_span: Span,
                                              segment: &'a PathSegment) {
-    visitor.visit_ident(path_span, segment.identifier);
+    visitor.visit_ident(segment.ident);
     if let Some(ref parameters) = segment.parameters {
         visitor.visit_path_parameters(path_span, parameters);
     }
@@ -398,7 +398,7 @@ pub fn walk_path_parameters<'a, V>(visitor: &mut V,
 
 pub fn walk_assoc_type_binding<'a, V: Visitor<'a>>(visitor: &mut V,
                                                    type_binding: &'a TypeBinding) {
-    visitor.visit_ident(type_binding.span, type_binding.ident);
+    visitor.visit_ident(type_binding.ident);
     visitor.visit_ty(&type_binding.ty);
 }
 
@@ -418,7 +418,7 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) {
             visitor.visit_path(path, pattern.id);
             for field in fields {
                 walk_list!(visitor, visit_attribute, field.node.attrs.iter());
-                visitor.visit_ident(field.span, field.node.ident);
+                visitor.visit_ident(field.node.ident);
                 visitor.visit_pat(&field.node.pat)
             }
         }
@@ -430,8 +430,8 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) {
         PatKind::Paren(ref subpattern) => {
             visitor.visit_pat(subpattern)
         }
-        PatKind::Ident(_, ref pth1, ref optional_subpattern) => {
-            visitor.visit_ident(pth1.span, pth1.node);
+        PatKind::Ident(_, ident, ref optional_subpattern) => {
+            visitor.visit_ident(ident);
             walk_list!(visitor, visit_pat, optional_subpattern);
         }
         PatKind::Lit(ref expression) => visitor.visit_expr(expression),
@@ -451,7 +451,7 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) {
 
 pub fn walk_foreign_item<'a, V: Visitor<'a>>(visitor: &mut V, foreign_item: &'a ForeignItem) {
     visitor.visit_vis(&foreign_item.vis);
-    visitor.visit_ident(foreign_item.span, foreign_item.ident);
+    visitor.visit_ident(foreign_item.ident);
 
     match foreign_item.node {
         ForeignItemKind::Fn(ref function_declaration, ref generics) => {
@@ -460,6 +460,7 @@ pub fn walk_foreign_item<'a, V: Visitor<'a>>(visitor: &mut V, foreign_item: &'a
         }
         ForeignItemKind::Static(ref typ, _) => visitor.visit_ty(typ),
         ForeignItemKind::Ty => (),
+        ForeignItemKind::Macro(ref mac) => visitor.visit_mac(mac),
     }
 
     walk_list!(visitor, visit_attribute, &foreign_item.attrs);
@@ -488,7 +489,7 @@ pub fn walk_generic_param<'a, V: Visitor<'a>>(visitor: &mut V, param: &'a Generi
             walk_list!(visitor, visit_attribute, &*l.attrs);
         }
         GenericParam::Type(ref t) => {
-            visitor.visit_ident(t.span, t.ident);
+            visitor.visit_ident(t.ident);
             walk_list!(visitor, visit_ty_param_bound, &t.bounds);
             walk_list!(visitor, visit_ty, &t.default);
             walk_list!(visitor, visit_attribute, &*t.attrs);
@@ -560,7 +561,7 @@ pub fn walk_fn<'a, V>(visitor: &mut V, kind: FnKind<'a>, declaration: &'a FnDecl
 }
 
 pub fn walk_trait_item<'a, V: Visitor<'a>>(visitor: &mut V, trait_item: &'a TraitItem) {
-    visitor.visit_ident(trait_item.span, trait_item.ident);
+    visitor.visit_ident(trait_item.ident);
     walk_list!(visitor, visit_attribute, &trait_item.attrs);
     visitor.visit_generics(&trait_item.generics);
     match trait_item.node {
@@ -587,7 +588,7 @@ pub fn walk_trait_item<'a, V: Visitor<'a>>(visitor: &mut V, trait_item: &'a Trai
 
 pub fn walk_impl_item<'a, V: Visitor<'a>>(visitor: &mut V, impl_item: &'a ImplItem) {
     visitor.visit_vis(&impl_item.vis);
-    visitor.visit_ident(impl_item.span, impl_item.ident);
+    visitor.visit_ident(impl_item.ident);
     walk_list!(visitor, visit_attribute, &impl_item.attrs);
     visitor.visit_generics(&impl_item.generics);
     match impl_item.node {
@@ -615,7 +616,7 @@ pub fn walk_struct_def<'a, V: Visitor<'a>>(visitor: &mut V, struct_definition: &
 pub fn walk_struct_field<'a, V: Visitor<'a>>(visitor: &mut V, struct_field: &'a StructField) {
     visitor.visit_vis(&struct_field.vis);
     if let Some(ident) = struct_field.ident {
-        visitor.visit_ident(struct_field.span, ident);
+        visitor.visit_ident(ident);
     }
     visitor.visit_ty(&struct_field.ty);
     walk_list!(visitor, visit_attribute, &struct_field.attrs);
@@ -665,7 +666,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
             visitor.visit_path(path, expression.id);
             for field in fields {
                 walk_list!(visitor, visit_attribute, field.attrs.iter());
-                visitor.visit_ident(field.ident.span, field.ident.node);
+                visitor.visit_ident(field.ident);
                 visitor.visit_expr(&field.expr)
             }
             walk_list!(visitor, visit_expr, optional_base);
@@ -744,9 +745,9 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
             visitor.visit_expr(left_expression);
             visitor.visit_expr(right_expression);
         }
-        ExprKind::Field(ref subexpression, ref ident) => {
+        ExprKind::Field(ref subexpression, ident) => {
             visitor.visit_expr(subexpression);
-            visitor.visit_ident(ident.span, ident.node);
+            visitor.visit_ident(ident);
         }
         ExprKind::TupField(ref subexpression, _) => {
             visitor.visit_expr(subexpression);
index 8b29e6adeb9eb9ba2231e7175e2dc56a042d9df0..7352c494a426cf3c8468d1ee7c55861b5f45e32c 100644 (file)
@@ -14,6 +14,7 @@
 use syntax::ext::build::AstBuilder;
 use syntax::parse::token;
 use syntax::print::pprust;
+use syntax::symbol::Symbol;
 use syntax::tokenstream::{TokenStream, TokenTree};
 use syntax_pos::{Span, DUMMY_SP};
 
@@ -35,9 +36,9 @@ pub fn expand_assert<'cx>(
         None
     };
 
-    let sp = sp.with_ctxt(sp.ctxt().apply_mark(cx.current_expansion.mark));
+    let sp = sp.apply_mark(cx.current_expansion.mark);
     let panic_call = Mac_ {
-        path: Path::from_ident(sp, Ident::from_str("panic")),
+        path: Path::from_ident(Ident::new(Symbol::intern("panic"), sp)),
         tts: if let Some(ts) = custom_msg_args {
             ts.into()
         } else {
index 1eeba9b30b8e24f5a481a2fd3011c47d10e22d77..6acc578d07e783040ba0aec680b6b242f4d008c0 100644 (file)
@@ -24,7 +24,7 @@ pub fn expand_cfg<'cx>(cx: &mut ExtCtxt,
                        sp: Span,
                        tts: &[tokenstream::TokenTree])
                        -> Box<base::MacResult + 'static> {
-    let sp = sp.with_ctxt(sp.ctxt().apply_mark(cx.current_expansion.mark));
+    let sp = sp.apply_mark(cx.current_expansion.mark);
     let mut p = cx.new_parser_from_tts(tts);
     let cfg = panictry!(p.parse_meta_item());
 
index c79e7867c5f5ef8602bdd2defde8642ba5b8b0cb..6c085528a6632e4ac17091a68399dab6d1c79928 100644 (file)
@@ -57,6 +57,6 @@ pub fn expand_syntax_ext(cx: &mut base::ExtCtxt,
             }
         }
     }
-    let sp = sp.with_ctxt(sp.ctxt().apply_mark(cx.current_expansion.mark));
+    let sp = sp.apply_mark(cx.current_expansion.mark);
     base::MacEager::expr(cx.expr_str(sp, Symbol::intern(&accumulator)))
 }
index d513008f0e2d388a92aad7c1da6989b8b2cd67ff..544b1410d3d912135d8550c01d5345635ebb40d6 100644 (file)
@@ -16,7 +16,6 @@
 use syntax::ptr::P;
 use syntax_pos::Span;
 use syntax_pos::symbol::Symbol;
-use syntax_pos::hygiene::SyntaxContext;
 use syntax::tokenstream::TokenTree;
 
 pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt,
@@ -53,31 +52,17 @@ pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt,
             }
         }
     }
-    let res = ast::Ident {
-        name: Symbol::intern(&res_str),
-        ctxt: SyntaxContext::empty().apply_mark(cx.current_expansion.mark),
-    };
 
-    struct Result {
-        ident: ast::Ident,
-        span: Span,
-    };
+    let ident = ast::Ident::new(Symbol::intern(&res_str), sp.apply_mark(cx.current_expansion.mark));
 
-    impl Result {
-        fn path(&self) -> ast::Path {
-            ast::Path {
-                span: self.span,
-                segments: vec![ast::PathSegment::from_ident(self.ident, self.span)],
-            }
-        }
-    }
+    struct ConcatIdentsResult { ident: ast::Ident }
 
-    impl base::MacResult for Result {
+    impl base::MacResult for ConcatIdentsResult {
         fn make_expr(self: Box<Self>) -> Option<P<ast::Expr>> {
             Some(P(ast::Expr {
                 id: ast::DUMMY_NODE_ID,
-                node: ast::ExprKind::Path(None, self.path()),
-                span: self.span,
+                node: ast::ExprKind::Path(None, ast::Path::from_ident(self.ident)),
+                span: self.ident.span,
                 attrs: ast::ThinVec::new(),
             }))
         }
@@ -85,14 +70,11 @@ fn make_expr(self: Box<Self>) -> Option<P<ast::Expr>> {
         fn make_ty(self: Box<Self>) -> Option<P<ast::Ty>> {
             Some(P(ast::Ty {
                 id: ast::DUMMY_NODE_ID,
-                node: ast::TyKind::Path(None, self.path()),
-                span: self.span,
+                node: ast::TyKind::Path(None, ast::Path::from_ident(self.ident)),
+                span: self.ident.span,
             }))
         }
     }
 
-    Box::new(Result {
-        ident: res,
-        span: sp.with_ctxt(sp.ctxt().apply_mark(cx.current_expansion.mark)),
-    })
+    Box::new(ConcatIdentsResult { ident })
 }
index f23d22b0c365f4b82b9b2b17f46be4511137d204..dec24d13c9b493fd766013b773c612a14f966f0a 100644 (file)
@@ -177,7 +177,7 @@ fn cs_clone(name: &str,
             vdata = vdata_;
         }
         EnumMatching(.., variant, ref af) => {
-            ctor_path = cx.path(trait_span, vec![substr.type_ident, variant.node.name]);
+            ctor_path = cx.path(trait_span, vec![substr.type_ident, variant.node.ident]);
             all_fields = af;
             vdata = &variant.node.data;
         }
index 80557078d5463da4f9c1c87f8edf59c2f359a031..5fd5e29948852589b585a25df482ee72b82509a6 100644 (file)
@@ -55,6 +55,7 @@ fn expand(&self,
             Annotatable::Item(item) => item,
             Annotatable::ImplItem(_) |
             Annotatable::TraitItem(_) |
+            Annotatable::ForeignItem(_) |
             Annotatable::Stmt(_) |
             Annotatable::Expr(_) => {
                 ecx.span_err(span, "proc-macro derives may only be \
index 7b23de582a79aa74415c3234a23183128697654f..c007285cd85191afdf4eaa0037e3cd5cf7035de1 100644 (file)
@@ -61,7 +61,7 @@ fn show_substructure(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<E
     // based on the "shape".
     let (ident, is_struct) = match *substr.fields {
         Struct(vdata, _) => (substr.type_ident, vdata.is_struct()),
-        EnumMatching(_, _, v, _) => (v.node.name, v.node.data.is_struct()),
+        EnumMatching(_, _, v, _) => (v.node.ident, v.node.data.is_struct()),
         EnumNonMatchingCollapsed(..) |
         StaticStruct(..) |
         StaticEnum(..) => cx.span_bug(span, "nonsensical .fields in `#[derive(Debug)]`"),
index 88baa22e7fa1160561b664e82bb4f4a1437447b4..d579b3abd45a902b39a947ddc480975717fddcd1 100644 (file)
@@ -277,7 +277,7 @@ fn encodable_substructure(cx: &mut ExtCtxt,
             }
 
             let blk = cx.lambda_stmts_1(trait_span, stmts, blkarg);
-            let name = cx.expr_str(trait_span, variant.node.name.name);
+            let name = cx.expr_str(trait_span, variant.node.ident.name);
             let call = cx.expr_method_call(trait_span,
                                            blkencoder,
                                            cx.ident_of("emit_enum_variant"),
index 3935f1722b61525670885e978fa53a15f36b02da..4126ce79f355517d8e8502796727378adc4f73f2 100644 (file)
 use syntax::ast::{
     self, BinOpKind, EnumDef, Expr, GenericParam, Generics, Ident, PatKind, VariantData
 };
+
 use syntax::attr;
 use syntax::ext::base::{Annotatable, ExtCtxt};
 use syntax::ext::build::AstBuilder;
@@ -367,7 +368,7 @@ impl<'a, 'b> visit::Visitor<'a> for Visitor<'a, 'b> {
         fn visit_ty(&mut self, ty: &'a ast::Ty) {
             if let ast::TyKind::Path(_, ref path) = ty.node {
                 if let Some(segment) = path.segments.first() {
-                    if self.ty_param_names.contains(&segment.identifier.name) {
+                    if self.ty_param_names.contains(&segment.ident.name) {
                         self.types.push(P(ty.clone()));
                     }
                 }
@@ -622,7 +623,7 @@ fn create_derived_impl(&self,
                         // if we have already handled this type, skip it
                         if let ast::TyKind::Path(_, ref p) = ty.node {
                             if p.segments.len() == 1 &&
-                            ty_param_names.contains(&p.segments[0].identifier.name) ||
+                            ty_param_names.contains(&p.segments[0].ident.name) ||
                             processed_field_types.contains(&p.segments) {
                                 continue;
                             };
@@ -952,7 +953,7 @@ fn create_method(&self,
         let args = {
             let self_args = explicit_self.map(|explicit_self| {
                 ast::Arg::from_self(explicit_self,
-                                    respan(trait_.span, keywords::SelfValue.ident()))
+                                    keywords::SelfValue.ident().with_span_pos(trait_.span))
             });
             let nonself_args = arg_types.into_iter()
                 .map(|(name, ty)| cx.arg(trait_.span, name, ty));
@@ -1537,10 +1538,9 @@ fn expand_static_enum_method_body(&self,
         let summary = enum_def.variants
             .iter()
             .map(|v| {
-                let ident = v.node.name;
                 let sp = v.span.with_ctxt(trait_.span.ctxt());
                 let summary = trait_.summarise_struct(cx, &v.node.data);
-                (ident, sp, summary)
+                (v.node.ident, sp, summary)
             })
             .collect();
         self.call_substructure_method(cx,
@@ -1581,7 +1581,7 @@ fn summarise_struct(&self, cx: &mut ExtCtxt, struct_def: &VariantData) -> Static
 
     fn create_subpatterns(&self,
                           cx: &mut ExtCtxt,
-                          field_paths: Vec<ast::SpannedIdent>,
+                          field_paths: Vec<ast::Ident>,
                           mutbl: ast::Mutability,
                           use_temporaries: bool)
                           -> Vec<P<ast::Pat>> {
@@ -1613,10 +1613,7 @@ fn create_struct_pattern
         for (i, struct_field) in struct_def.fields().iter().enumerate() {
             let sp = struct_field.span.with_ctxt(self.span.ctxt());
             let ident = cx.ident_of(&format!("{}_{}", prefix, i));
-            paths.push(codemap::Spanned {
-                span: sp,
-                node: ident,
-            });
+            paths.push(ident.with_span_pos(sp));
             let val = cx.expr_path(cx.path_ident(sp, ident));
             let val = if use_temporaries {
                 val
@@ -1669,9 +1666,8 @@ fn create_enum_variant_pattern
          prefix: &str,
          mutbl: ast::Mutability)
          -> (P<ast::Pat>, Vec<(Span, Option<Ident>, P<Expr>, &'a [ast::Attribute])>) {
-        let variant_ident = variant.node.name;
         let sp = variant.span.with_ctxt(self.span.ctxt());
-        let variant_path = cx.path(sp, vec![enum_ident, variant_ident]);
+        let variant_path = cx.path(sp, vec![enum_ident, variant.node.ident]);
         let use_temporaries = false; // enums can't be repr(packed)
         self.create_struct_pattern(cx, variant_path, &variant.node.data, prefix, mutbl,
                                    use_temporaries)
index cc3e8b6e6b7c09276d0e723c8ab6453d49e4f2d6..25a2969448835dca4ba648e9be841b01dd61ee0f 100644 (file)
 use syntax::ast::{Expr, GenericParam, Generics, Ident, SelfKind};
 use syntax::ext::base::ExtCtxt;
 use syntax::ext::build::AstBuilder;
-use syntax::codemap::respan;
+use syntax::codemap::{respan, DUMMY_SP};
 use syntax::ptr::P;
 use syntax_pos::Span;
-use syntax_pos::hygiene::SyntaxContext;
 use syntax_pos::symbol::keywords;
 
 /// The types of pointers
@@ -93,8 +92,8 @@ pub fn to_path(&self,
             PathKind::Global => cx.path_all(span, true, idents, lt, tys, Vec::new()),
             PathKind::Local => cx.path_all(span, false, idents, lt, tys, Vec::new()),
             PathKind::Std => {
-                let def_site = SyntaxContext::empty().apply_mark(cx.current_expansion.mark);
-                idents.insert(0, Ident { ctxt: def_site, ..keywords::DollarCrate.ident() });
+                let def_site = DUMMY_SP.apply_mark(cx.current_expansion.mark);
+                idents.insert(0, Ident::new(keywords::DollarCrate.name(), def_site));
                 cx.path_all(span, false, idents, lt, tys, Vec::new())
             }
         }
index ba6d25f7a60a4bf8647d0f22608cec67ba868b3d..4e1af108ab4fa038765d01da23b0977a3d5922ce 100644 (file)
@@ -32,7 +32,7 @@ pub fn expand_option_env<'cx>(cx: &'cx mut ExtCtxt,
         Some(v) => v,
     };
 
-    let sp = sp.with_ctxt(sp.ctxt().apply_mark(cx.current_expansion.mark));
+    let sp = sp.apply_mark(cx.current_expansion.mark);
     let e = match env::var(&*var.as_str()) {
         Err(..) => {
             let lt = cx.lifetime(sp, keywords::StaticLifetime.ident());
index d9c68e3167bd68cc3f983d72b4899ff55f5bdf02..c78decb1eb9d0bc2983a94c75974fe9c8e4a0a22 100644 (file)
@@ -641,7 +641,7 @@ fn format_arg(ecx: &ExtCtxt,
                   ty: &ArgumentType,
                   arg: ast::Ident)
                   -> P<ast::Expr> {
-        sp = sp.with_ctxt(sp.ctxt().apply_mark(ecx.current_expansion.mark));
+        sp = sp.apply_mark(ecx.current_expansion.mark);
         let arg = ecx.expr_ident(sp, arg);
         let trait_ = match *ty {
             Placeholder(ref tyname) => {
@@ -678,7 +678,7 @@ pub fn expand_format_args<'cx>(ecx: &'cx mut ExtCtxt,
                                mut sp: Span,
                                tts: &[tokenstream::TokenTree])
                                -> Box<base::MacResult + 'cx> {
-    sp = sp.with_ctxt(sp.ctxt().apply_mark(ecx.current_expansion.mark));
+    sp = sp.apply_mark(ecx.current_expansion.mark);
     match parse_args(ecx, sp, tts) {
         Some((efmt, args, names)) => {
             MacEager::expr(expand_preparsed_format_args(ecx, sp, efmt, args, names))
@@ -700,7 +700,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
     let arg_types: Vec<_> = (0..args.len()).map(|_| Vec::new()).collect();
     let arg_unique_types: Vec<_> = (0..args.len()).map(|_| Vec::new()).collect();
     let mut macsp = ecx.call_site();
-    macsp = macsp.with_ctxt(macsp.ctxt().apply_mark(ecx.current_expansion.mark));
+    macsp = macsp.apply_mark(ecx.current_expansion.mark);
     let msg = "format argument must be a string literal.";
     let fmt = match expr_to_spanned_string(ecx, efmt, msg) {
         Some(fmt) => fmt,
index 249a64b353f5912f981425e92c1b94b7c3f7e928..97e34c554d116f66fa8ab262381df5cf48f1c4b3 100644 (file)
@@ -13,7 +13,6 @@
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "https://doc.rust-lang.org/nightly/")]
-#![deny(warnings)]
 
 #![feature(proc_macro_internals)]
 #![feature(decl_macro)]
index e623779ce63ba732eade30cca564e192939fd63c..d684e8b4ffea5a4894428fa73f587199863b905e 100644 (file)
@@ -18,7 +18,7 @@
 use syntax::ext::base::ExtCtxt;
 use syntax::ext::build::AstBuilder;
 use syntax::ext::expand::ExpansionConfig;
-use syntax::ext::hygiene::{Mark, SyntaxContext};
+use syntax::ext::hygiene::Mark;
 use syntax::fold::Folder;
 use syntax::parse::ParseSess;
 use syntax::ptr::P;
@@ -371,7 +371,7 @@ fn mk_registrar(cx: &mut ExtCtxt,
             allow_internal_unsafe: false,
         }
     });
-    let span = DUMMY_SP.with_ctxt(SyntaxContext::empty().apply_mark(mark));
+    let span = DUMMY_SP.apply_mark(mark);
 
     let proc_macro = Ident::from_str("proc_macro");
     let krate = cx.item(span,
index aba71bd0468311cb67c2aa99db7f47052ed0287e..c180563450f83ebf712ea05dda99a1aeba64d2ff 100644 (file)
@@ -123,7 +123,7 @@ pub struct HygieneData {
     marks: Vec<MarkData>,
     syntax_contexts: Vec<SyntaxContextData>,
     markings: HashMap<(SyntaxContext, Mark), SyntaxContext>,
-    gensym_to_ctxt: HashMap<Symbol, SyntaxContext>,
+    gensym_to_ctxt: HashMap<Symbol, Span>,
 }
 
 impl HygieneData {
@@ -461,7 +461,7 @@ impl Symbol {
     pub fn from_ident(ident: Ident) -> Symbol {
         HygieneData::with(|data| {
             let gensym = ident.name.gensymed();
-            data.gensym_to_ctxt.insert(gensym, ident.ctxt);
+            data.gensym_to_ctxt.insert(gensym, ident.span);
             gensym
         })
     }
@@ -469,7 +469,7 @@ pub fn from_ident(ident: Ident) -> Symbol {
     pub fn to_ident(self) -> Ident {
         HygieneData::with(|data| {
             match data.gensym_to_ctxt.get(&self) {
-                Some(&ctxt) => Ident { name: self.interned(), ctxt: ctxt },
+                Some(&span) => Ident::new(self.interned(), span),
                 None => Ident::with_empty_ctxt(self),
             }
         })
index eb345200f413db0ce24ee7ae43521d58f9098484..9a7d1fd8ee6cb9a508579a3029cfe09d449b6860 100644 (file)
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/")]
-#![deny(warnings)]
 
 #![feature(const_fn)]
 #![feature(custom_attribute)]
-#![cfg_attr(stage0, feature(i128_type))]
 #![feature(optin_builtin_traits)]
 #![allow(unused_attributes)]
 #![feature(specialization)]
@@ -50,7 +48,7 @@
 extern crate unicode_width;
 
 pub mod hygiene;
-pub use hygiene::{SyntaxContext, ExpnInfo, ExpnFormat, NameAndSpan, CompilerDesugaringKind};
+pub use hygiene::{Mark, SyntaxContext, ExpnInfo, ExpnFormat, NameAndSpan, CompilerDesugaringKind};
 
 mod span_encoding;
 pub use span_encoding::{Span, DUMMY_SP};
@@ -422,6 +420,52 @@ pub fn until(self, end: Span) -> Span {
             if end.ctxt == SyntaxContext::empty() { end.ctxt } else { span.ctxt },
         )
     }
+
+    #[inline]
+    pub fn apply_mark(self, mark: Mark) -> Span {
+        let span = self.data();
+        span.with_ctxt(span.ctxt.apply_mark(mark))
+    }
+
+    #[inline]
+    pub fn remove_mark(&mut self) -> Mark {
+        let mut span = self.data();
+        let mark = span.ctxt.remove_mark();
+        *self = Span::new(span.lo, span.hi, span.ctxt);
+        mark
+    }
+
+    #[inline]
+    pub fn adjust(&mut self, expansion: Mark) -> Option<Mark> {
+        let mut span = self.data();
+        let mark = span.ctxt.adjust(expansion);
+        *self = Span::new(span.lo, span.hi, span.ctxt);
+        mark
+    }
+
+    #[inline]
+    pub fn glob_adjust(&mut self, expansion: Mark, glob_ctxt: SyntaxContext)
+                       -> Option<Option<Mark>> {
+        let mut span = self.data();
+        let mark = span.ctxt.glob_adjust(expansion, glob_ctxt);
+        *self = Span::new(span.lo, span.hi, span.ctxt);
+        mark
+    }
+
+    #[inline]
+    pub fn reverse_glob_adjust(&mut self, expansion: Mark, glob_ctxt: SyntaxContext)
+                               -> Option<Option<Mark>> {
+        let mut span = self.data();
+        let mark = span.ctxt.reverse_glob_adjust(expansion, glob_ctxt);
+        *self = Span::new(span.lo, span.hi, span.ctxt);
+        mark
+    }
+
+    #[inline]
+    pub fn modern(self) -> Span {
+        let span = self.data();
+        span.with_ctxt(span.ctxt.modern())
+    }
 }
 
 #[derive(Clone, Debug)]
index 098eafef2585c146a751ce2fb9c382d4466d52f1..331b0fe5481d5c0d0593626b21dcce8288b241e3 100644 (file)
 //! type, and vice versa.
 
 use hygiene::SyntaxContext;
-use GLOBALS;
+use {Span, DUMMY_SP, GLOBALS};
 
 use serialize::{Decodable, Decoder, Encodable, Encoder};
 use std::collections::HashMap;
 use std::fmt;
+use std::hash::{Hash, Hasher};
 
-#[derive(Copy, Clone, PartialEq, Eq, Hash)]
+#[derive(Copy, Clone, Eq)]
 pub struct Ident {
     pub name: Symbol,
-    pub ctxt: SyntaxContext,
+    pub span: Span,
 }
 
 impl Ident {
+    #[inline]
+    pub const fn new(name: Symbol, span: Span) -> Ident {
+        Ident { name, span }
+    }
+    #[inline]
     pub const fn with_empty_ctxt(name: Symbol) -> Ident {
-        Ident { name: name, ctxt: SyntaxContext::empty() }
+        Ident::new(name, DUMMY_SP)
     }
 
     /// Maps a string to an identifier with an empty syntax context.
@@ -35,18 +41,36 @@ pub fn from_str(string: &str) -> Ident {
         Ident::with_empty_ctxt(Symbol::intern(string))
     }
 
-    pub fn without_first_quote(&self) -> Ident {
-        Ident { name: Symbol::from(self.name.as_str().trim_left_matches('\'')), ctxt: self.ctxt }
+    /// Replace `lo` and `hi` with those from `span`, but keep hygiene context.
+    pub fn with_span_pos(self, span: Span) -> Ident {
+        Ident::new(self.name, span.with_ctxt(self.span.ctxt()))
+    }
+
+    pub fn without_first_quote(self) -> Ident {
+        Ident::new(Symbol::intern(self.name.as_str().trim_left_matches('\'')), self.span)
     }
 
     pub fn modern(self) -> Ident {
-        Ident { name: self.name, ctxt: self.ctxt.modern() }
+        Ident::new(self.name, self.span.modern())
+    }
+}
+
+impl PartialEq for Ident {
+    fn eq(&self, rhs: &Self) -> bool {
+        self.name == rhs.name && self.span.ctxt() == rhs.span.ctxt()
+    }
+}
+
+impl Hash for Ident {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        self.name.hash(state);
+        self.span.ctxt().hash(state);
     }
 }
 
 impl fmt::Debug for Ident {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "{}{:?}", self.name, self.ctxt)
+        write!(f, "{}{:?}", self.name, self.span.ctxt())
     }
 }
 
@@ -58,7 +82,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 
 impl Encodable for Ident {
     fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
-        if self.ctxt.modern() == SyntaxContext::empty() {
+        if self.span.ctxt().modern() == SyntaxContext::empty() {
             s.emit_str(&self.name.as_str())
         } else { // FIXME(jseyfried) intercrate hygiene
             let mut string = "#".to_owned();
@@ -123,12 +147,6 @@ pub fn as_u32(self) -> u32 {
     }
 }
 
-impl<'a> From<&'a str> for Symbol {
-    fn from(string: &'a str) -> Symbol {
-        Symbol::intern(string)
-    }
-}
-
 impl fmt::Debug for Symbol {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         let is_gensymed = with_interner(|interner| interner.is_gensymed(*self));
index ad0e582b1c324e4ef38ab460476c2b19e7696037..a012f4e776fb21b69ed8ddbd10ae4bad44f43372 100644 (file)
@@ -46,7 +46,6 @@
        html_playground_url = "https://play.rust-lang.org/",
        test(attr(deny(warnings))))]
 #![deny(missing_docs)]
-#![deny(warnings)]
 
 #![cfg_attr(windows, feature(libc))]
 // Handle rustfmt skips
index b8be1aeff174278244bca9fcfebc509c1fecb3f7..9291eaa910bd744d745935eb295fc6efac275f3b 100644 (file)
@@ -31,7 +31,6 @@
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "https://doc.rust-lang.org/nightly/", test(attr(deny(warnings))))]
-#![deny(warnings)]
 #![feature(asm)]
 #![feature(fnbox)]
 #![cfg_attr(any(unix, target_os = "cloudabi"), feature(libc))]
index fbd9789d2f52d16c98aa91319664b707cb9c2ad8..4760461df64e3895e73561fccd66785dedc6ff92 100644 (file)
@@ -14,3 +14,4 @@ doc = false
 [dependencies]
 core = { path = "../libcore" }
 libc = { path = "../rustc/libc_shim" }
+compiler_builtins = { path = "../rustc/compiler_builtins_shim" }
index 5347c781218ce4b947f10a3d2e11529a686abf04..2b3c19c067ed4258de5a3da04fc6ae1b754a2168 100644 (file)
@@ -10,7 +10,6 @@
 
 #![no_std]
 #![unstable(feature = "panic_unwind", issue = "32837")]
-#![deny(warnings)]
 
 #![feature(cfg_target_vendor)]
 #![feature(link_cfg)]
index aa73b11fb3813683534bc7286c502c13d36bfd54..a640a2b777537decc21d176cfe144a934501ef59 100644 (file)
@@ -83,8 +83,7 @@ pub enum _Unwind_Context {}
 pub type _Unwind_Exception_Cleanup_Fn = extern "C" fn(unwind_code: _Unwind_Reason_Code,
                                                       exception: *mut _Unwind_Exception);
 extern "C" {
-    #[cfg_attr(stage0, unwind)]
-    #[cfg_attr(not(stage0), unwind(allowed))]
+    #[unwind(allowed)]
     pub fn _Unwind_Resume(exception: *mut _Unwind_Exception) -> !;
     pub fn _Unwind_DeleteException(exception: *mut _Unwind_Exception);
     pub fn _Unwind_GetLanguageSpecificData(ctx: *mut _Unwind_Context) -> *mut c_void;
@@ -221,8 +220,7 @@ pub unsafe fn _Unwind_FindEnclosingFunction(pc: *mut c_void) -> *mut c_void {
 if #[cfg(not(all(target_os = "ios", target_arch = "arm")))] {
     // Not 32-bit iOS
     extern "C" {
-        #[cfg_attr(stage0, unwind)]
-        #[cfg_attr(not(stage0), unwind(allowed))]
+        #[unwind(allowed)]
         pub fn _Unwind_RaiseException(exception: *mut _Unwind_Exception) -> _Unwind_Reason_Code;
         pub fn _Unwind_Backtrace(trace: _Unwind_Trace_Fn,
                                  trace_argument: *mut c_void)
@@ -231,8 +229,7 @@ pub fn _Unwind_Backtrace(trace: _Unwind_Trace_Fn,
 } else {
     // 32-bit iOS uses SjLj and does not provide _Unwind_Backtrace()
     extern "C" {
-        #[cfg_attr(stage0, unwind)]
-        #[cfg_attr(not(stage0), unwind(allowed))]
+        #[unwind(allowed)]
         pub fn _Unwind_SjLj_RaiseException(e: *mut _Unwind_Exception) -> _Unwind_Reason_Code;
     }
 
index 608e5f5f36d02eb3b6d5ae7eaa8e8a77077beb7f..7d8423ca84eb41622f382652c0adb2641ea0fcbd 100644 (file)
@@ -35,5 +35,6 @@ cc = "1.0.1"
 [features]
 c = []
 default = ["c", "rustbuild", "compiler-builtins"]
+mem = []
 rustbuild = []
 compiler-builtins = []
index cf8440c40da1aaa8736f3467b950895abdec649c..d2fe159d80673d54dbdb48a6fd0affacfc3665d4 100644 (file)
@@ -11,4 +11,5 @@ doc = false
 
 [dependencies]
 core = { path = "../../libcore" }
+compiler_builtins = { path = "../../rustc/compiler_builtins_shim" }
 alloc = { path = "../../liballoc" }
index 0c04402124a2de290c13d4c2f3b47c9083da6ea7..e77897d6433136603451492472ebd6834a1fd561 100644 (file)
@@ -29,6 +29,8 @@ doc = false
 #
 # See https://github.com/rust-lang/rfcs/pull/1133.
 core = { path = "../../libcore" }
+compiler_builtins = { path = "../compiler_builtins_shim" }
+
 
 [features]
 # Certain parts of libc are conditionally compiled differently than when used
index 9fa33f911a1686f8118a3f31bbf6dde38578d653..a888838ce432cb1fa44e8f738406961ede720674 100644 (file)
@@ -13,6 +13,7 @@
 
 // Set the stack size at link time on Windows. See rustc_driver::in_rustc_thread
 // for the rationale.
+#[allow(unused_attributes)]
 #[cfg_attr(all(windows, target_env = "msvc"), link_args = "/STACK:16777216")]
 // We only build for msvc and gnu now, but we use a exhaustive condition here
 // so we can expect either the stack size to be set or the build fails.
index 96ec1e6834dff30aa0c129f31b3af9a41349369b..e8db3358cf076b49d5c7054a073fa372db534bde 100644 (file)
@@ -12,7 +12,7 @@
 # source tarball for a stable release you'll likely see `1.x.0` for rustc and
 # `0.x.0` for Cargo where they were released on `date`.
 
-date: 2018-03-18
+date: 2018-04-04
 rustc: beta
 cargo: beta
 
diff --git a/src/test/codegen-units/partitioning/auxiliary/shared_generics_aux.rs b/src/test/codegen-units/partitioning/auxiliary/shared_generics_aux.rs
new file mode 100644 (file)
index 0000000..b742da8
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags:-Zshare-generics=yes
+
+#![crate_type="rlib"]
+
+pub fn generic_fn<T>(x: T, y: T) -> (T, T) {
+    (x, y)
+}
+
+pub fn use_generic_fn_f32() -> (f32, f32) {
+    generic_fn(0.0f32, 1.0f32)
+}
index bdb31265e2fb2e14692fad0d841def04eaac321e..140b43c85d548d93d61cbedfb7b8e156cbd5c0f3 100644 (file)
@@ -11,7 +11,7 @@
 // ignore-tidy-linelength
 // We specify -Z incremental here because we want to test the partitioning for
 // incremental compilation
-// compile-flags:-Zprint-trans-items=eager -Zincremental=tmp/partitioning-tests/extern-generic
+// compile-flags:-Zprint-trans-items=eager -Zincremental=tmp/partitioning-tests/extern-generic -Zshare-generics=y
 
 #![allow(dead_code)]
 #![crate_type="lib"]
@@ -59,4 +59,4 @@ fn non_user() {}
 // Make sure the two generic functions from the extern crate get instantiated
 // once for the current crate
 //~ TRANS_ITEM fn cgu_generic_function::foo[0]<&str> @@ cgu_generic_function.volatile[External]
-//~ TRANS_ITEM fn cgu_generic_function::bar[0]<&str> @@ cgu_generic_function.volatile[Internal]
+//~ TRANS_ITEM fn cgu_generic_function::bar[0]<&str> @@ cgu_generic_function.volatile[External]
diff --git a/src/test/codegen-units/partitioning/shared-generics.rs b/src/test/codegen-units/partitioning/shared-generics.rs
new file mode 100644 (file)
index 0000000..d352609
--- /dev/null
@@ -0,0 +1,30 @@
+// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-tidy-linelength
+// compile-flags:-Zprint-trans-items=eager -Zshare-generics=yes -Zincremental=tmp/partitioning-tests/shared-generics-exe
+
+#![crate_type="rlib"]
+
+// aux-build:shared_generics_aux.rs
+extern crate shared_generics_aux;
+
+//~ TRANS_ITEM fn shared_generics::foo[0]
+pub fn foo() {
+
+    //~ TRANS_ITEM fn shared_generics_aux::generic_fn[0]<u16> @@ shared_generics_aux.volatile[External]
+    let _ = shared_generics_aux::generic_fn(0u16, 1u16);
+
+    // This should not generate a monomorphization because it's already
+    // available in `shared_generics_aux`.
+    let _ = shared_generics_aux::generic_fn(0.0f32, 3.0f32);
+}
+
+// TRANS_ITEM drop-glue i8
diff --git a/src/test/codegen/local-generics-in-exe-internalized.rs b/src/test/codegen/local-generics-in-exe-internalized.rs
new file mode 100644 (file)
index 0000000..162a025
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: -C no-prepopulate-passes -Zshare-generics=yes
+
+// Check that local generics are internalized if they are in the same CGU
+
+// CHECK: define internal {{.*}} @_ZN34local_generics_in_exe_internalized3foo{{.*}}
+pub fn foo<T>(x: T, y: T) -> (T, T) {
+    (x, y)
+}
+
+fn main() {
+    let _ = foo(0u8, 1u8);
+}
index 77ea3019419387df239a147e4c13757e844058db..040f0b661be14fab1b21698a682b0e837f29dad7 100644 (file)
@@ -93,7 +93,9 @@ fn expand_into_foo_multi(cx: &mut ExtCtxt,
                 }
             })
         }
-        // these are covered in proc_macro/attr-stmt-expr.rs
+        // covered in proc_macro/macros-in-extern.rs
+        Annotatable::ForeignItem(_) => unimplemented!(),
+        // covered in proc_macro/attr-stmt-expr.rs
         Annotatable::Stmt(_) | Annotatable::Expr(_) => panic!("expected item")
     }
 }
@@ -115,7 +117,7 @@ fn expand_duplicate(cx: &mut ExtCtxt,
     let copy_name = match mi.node {
         ast::MetaItemKind::List(ref xs) => {
             if let Some(word) = xs[0].word() {
-                ast::Ident::with_empty_ctxt(word.name())
+                word.ident
             } else {
                 cx.span_err(mi.span, "Expected word");
                 return;
@@ -147,6 +149,8 @@ fn expand_duplicate(cx: &mut ExtCtxt,
             new_it.ident = copy_name;
             push(Annotatable::TraitItem(P(new_it)));
         }
+        // covered in proc_macro/macros-in-extern.rs
+        Annotatable::ForeignItem(_) => unimplemented!(),
         // covered in proc_macro/attr-stmt-expr.rs
         Annotatable::Stmt(_) | Annotatable::Expr(_) => panic!("expected item")
     }
index d725adfec7544a6950ea29a1a7b13b71c902fcc1..bbfec5815ba5c17262c9c7fe12864b9b58358c6b 100644 (file)
@@ -16,7 +16,7 @@
 
 extern crate proc_macro;
 
-use proc_macro::{TokenStream, TokenTree, TokenNode, Delimiter, Literal, Spacing};
+use proc_macro::{TokenStream, TokenTree, Delimiter, Literal, Spacing, Group};
 
 #[proc_macro_attribute]
 pub fn foo(attr: TokenStream, input: TokenStream) -> TokenStream {
@@ -52,24 +52,30 @@ pub fn bar(attr: TokenStream, input: TokenStream) -> TokenStream {
 }
 
 fn assert_inline(slice: &mut &[TokenTree]) {
-    match slice[0].kind {
-        TokenNode::Op('#', _) => {}
+    match &slice[0] {
+        TokenTree::Op(tt) => assert_eq!(tt.op(), '#'),
         _ => panic!("expected '#' char"),
     }
-    match slice[1].kind {
-        TokenNode::Group(Delimiter::Bracket, _) => {}
+    match &slice[1] {
+        TokenTree::Group(tt) => assert_eq!(tt.delimiter(), Delimiter::Bracket),
         _ => panic!("expected brackets"),
     }
     *slice = &slice[2..];
 }
 
 fn assert_doc(slice: &mut &[TokenTree]) {
-    match slice[0].kind {
-        TokenNode::Op('#', Spacing::Alone) => {}
+    match &slice[0] {
+        TokenTree::Op(tt) => {
+            assert_eq!(tt.op(), '#');
+            assert_eq!(tt.spacing(), Spacing::Alone);
+        }
         _ => panic!("expected #"),
     }
-    let inner = match slice[1].kind {
-        TokenNode::Group(Delimiter::Bracket, ref s) => s.clone(),
+    let inner = match &slice[1] {
+        TokenTree::Group(tt) => {
+            assert_eq!(tt.delimiter(), Delimiter::Bracket);
+            tt.stream()
+        }
         _ => panic!("expected brackets"),
     };
     let tokens = inner.into_iter().collect::<Vec<_>>();
@@ -79,16 +85,19 @@ fn assert_doc(slice: &mut &[TokenTree]) {
         panic!("expected three tokens in doc")
     }
 
-    match tokens[0].kind {
-        TokenNode::Term(ref t) => assert_eq!("doc", t.as_str()),
+    match &tokens[0] {
+        TokenTree::Term(tt) => assert_eq!("doc", tt.as_str()),
         _ => panic!("expected `doc`"),
     }
-    match tokens[1].kind {
-        TokenNode::Op('=', Spacing::Alone) => {}
+    match &tokens[1] {
+        TokenTree::Op(tt) => {
+            assert_eq!(tt.op(), '=');
+            assert_eq!(tt.spacing(), Spacing::Alone);
+        }
         _ => panic!("expected equals"),
     }
-    match tokens[2].kind {
-        TokenNode::Literal(_) => {}
+    match tokens[2] {
+        TokenTree::Literal(_) => {}
         _ => panic!("expected literal"),
     }
 
@@ -96,32 +105,35 @@ fn assert_doc(slice: &mut &[TokenTree]) {
 }
 
 fn assert_invoc(slice: &mut &[TokenTree]) {
-    match slice[0].kind {
-        TokenNode::Op('#', _) => {}
+    match &slice[0] {
+        TokenTree::Op(tt) => assert_eq!(tt.op(), '#'),
         _ => panic!("expected '#' char"),
     }
-    match slice[1].kind {
-        TokenNode::Group(Delimiter::Bracket, _) => {}
+    match &slice[1] {
+        TokenTree::Group(tt) => assert_eq!(tt.delimiter(), Delimiter::Bracket),
         _ => panic!("expected brackets"),
     }
     *slice = &slice[2..];
 }
 
 fn assert_foo(slice: &mut &[TokenTree]) {
-    match slice[0].kind {
-        TokenNode::Term(ref name) => assert_eq!(name.as_str(), "fn"),
+    match &slice[0] {
+        TokenTree::Term(tt) => assert_eq!(tt.as_str(), "fn"),
         _ => panic!("expected fn"),
     }
-    match slice[1].kind {
-        TokenNode::Term(ref name) => assert_eq!(name.as_str(), "foo"),
+    match &slice[1] {
+        TokenTree::Term(tt) => assert_eq!(tt.as_str(), "foo"),
         _ => panic!("expected foo"),
     }
-    match slice[2].kind {
-        TokenNode::Group(Delimiter::Parenthesis, ref s) => assert!(s.is_empty()),
+    match &slice[2] {
+        TokenTree::Group(tt) => {
+            assert_eq!(tt.delimiter(), Delimiter::Parenthesis);
+            assert!(tt.stream().is_empty());
+        }
         _ => panic!("expected parens"),
     }
-    match slice[3].kind {
-        TokenNode::Group(Delimiter::Brace, _) => {}
+    match &slice[3] {
+        TokenTree::Group(tt) => assert_eq!(tt.delimiter(), Delimiter::Brace),
         _ => panic!("expected braces"),
     }
     *slice = &slice[4..];
@@ -132,22 +144,17 @@ fn fold_stream(input: TokenStream) -> TokenStream {
 }
 
 fn fold_tree(input: TokenTree) -> TokenTree {
-    TokenTree {
-        span: input.span,
-        kind: fold_node(input.kind),
-    }
-}
-
-fn fold_node(input: TokenNode) -> TokenNode {
     match input {
-        TokenNode::Group(a, b) => TokenNode::Group(a, fold_stream(b)),
-        TokenNode::Op(a, b) => TokenNode::Op(a, b),
-        TokenNode::Term(a) => TokenNode::Term(a),
-        TokenNode::Literal(a) => {
+        TokenTree::Group(b) => {
+            TokenTree::Group(Group::new(b.delimiter(), fold_stream(b.stream())))
+        }
+        TokenTree::Op(b) => TokenTree::Op(b),
+        TokenTree::Term(a) => TokenTree::Term(a),
+        TokenTree::Literal(a) => {
             if a.to_string() != "\"foo\"" {
-                TokenNode::Literal(a)
+                TokenTree::Literal(a)
             } else {
-                TokenNode::Literal(Literal::integer(3))
+                TokenTree::Literal(Literal::i32_unsuffixed(3))
             }
         }
     }
diff --git a/src/test/compile-fail-fulldeps/proc-macro/auxiliary/test-macros.rs b/src/test/compile-fail-fulldeps/proc-macro/auxiliary/test-macros.rs
new file mode 100644 (file)
index 0000000..d1c5b90
--- /dev/null
@@ -0,0 +1,36 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+#![feature(proc_macro)]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_attribute]
+pub fn nop_attr(_attr: TokenStream, input: TokenStream) -> TokenStream {
+    assert!(_attr.to_string().is_empty());
+    input
+}
+
+#[proc_macro_attribute]
+pub fn no_output(_attr: TokenStream, _input: TokenStream) -> TokenStream {
+    assert!(_attr.to_string().is_empty());
+    assert!(!_input.to_string().is_empty());
+    "".parse().unwrap()
+}
+
+#[proc_macro]
+pub fn emit_input(input: TokenStream) -> TokenStream {
+    input
+}
diff --git a/src/test/compile-fail-fulldeps/proc-macro/macros-in-extern.rs b/src/test/compile-fail-fulldeps/proc-macro/macros-in-extern.rs
new file mode 100644 (file)
index 0000000..4c88df3
--- /dev/null
@@ -0,0 +1,38 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:test-macros.rs
+// ignore-stage1
+// ignore-wasm32
+
+#![feature(proc_macro)]
+
+extern crate test_macros;
+
+use test_macros::{nop_attr, no_output, emit_input};
+
+fn main() {
+    assert_eq!(unsafe { rust_get_test_int() }, 0isize);
+    assert_eq!(unsafe { rust_dbg_extern_identity_u32(0xDEADBEEF) }, 0xDEADBEEF);
+}
+
+#[link(name = "rust_test_helpers", kind = "static")]
+extern {
+    #[no_output]
+    //~^ ERROR Macro and proc-macro invocations in `extern {}` blocks are experimental.
+    fn some_definitely_unknown_symbol_which_should_be_removed();
+
+    #[nop_attr]
+    //~^ ERROR Macro and proc-macro invocations in `extern {}` blocks are experimental.
+    fn rust_get_test_int() -> isize;
+
+    emit_input!(fn rust_dbg_extern_identity_u32(arg: u32) -> u32;);
+    //~^ ERROR Macro and proc-macro invocations in `extern {}` blocks are experimental.
+}
index 53e287cda208adbcee9881156b28a584350d9816..ec7885f1f44f97c68bfcd6ac3ad04b757eae9e2b 100644 (file)
@@ -12,8 +12,7 @@
 // `#[oops]` is left dangling (that is, it is unattached, with no
 // formal binding following it).
 
-#![feature(generic_param_attrs, rustc_attrs)]
-#![allow(dead_code)]
+#![feature(rustc_attrs)]
 
 struct RefIntPair<'a, 'b>(&'a u32, &'b u32);
 
index 5e09473ab77da9ee2987123bc7c740a158247908..efe2d5561a832b5acedfb04da1a94035104faf4d 100644 (file)
@@ -12,8 +12,7 @@
 // `#[oops]` is left dangling (that is, it is unattached, with no
 // formal binding following it).
 
-#![feature(generic_param_attrs, rustc_attrs)]
-#![allow(dead_code)]
+#![feature(rustc_attrs)]
 
 struct RefAny<'a, T>(&'a T);
 
index 8a09ab3fd06c8e1ffa7f5dce75db2ecf07dbf57e..fbdd013024db56d5663960ffada8f7ca5e4d50e7 100644 (file)
@@ -27,7 +27,7 @@ fn indirect_write_to_imm_box() {
     let y: Box<_> = box &mut x;
     let p = &y;
     ***p = 2; //[ast]~ ERROR cannot assign to data in a `&` reference
-              //[mir]~^ ERROR cannot assign to immutable item `***p`
+              //[mir]~^ ERROR cannot assign to data in a `&` reference
     drop(p);
 }
 
diff --git a/src/test/compile-fail/borrowck/borrowck-issue-48962.rs b/src/test/compile-fail/borrowck/borrowck-issue-48962.rs
new file mode 100644 (file)
index 0000000..e3bbfd9
--- /dev/null
@@ -0,0 +1,38 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(nll)]
+
+struct Node {
+    elem: i32,
+    next: Option<Box<Node>>,
+}
+
+fn a() {
+    let mut node = Node {
+        elem: 5,
+        next: None,
+    };
+
+    let mut src = &mut node;
+    {src};
+    src.next = None; //~ ERROR use of moved value: `src` [E0382]
+}
+
+fn b() {
+    let mut src = &mut (22, 44);
+    {src};
+    src.0 = 66; //~ ERROR use of moved value: `src` [E0382]
+}
+
+fn main() {
+    a();
+    b();
+}
diff --git a/src/test/compile-fail/macros-in-extern.rs b/src/test/compile-fail/macros-in-extern.rs
new file mode 100644 (file)
index 0000000..7d7f95c
--- /dev/null
@@ -0,0 +1,42 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-wasm32
+
+#![feature(decl_macro)]
+
+macro_rules! returns_isize(
+    ($ident:ident) => (
+        fn $ident() -> isize;
+    )
+);
+
+macro takes_u32_returns_u32($ident:ident) {
+    fn $ident (arg: u32) -> u32;
+}
+
+macro_rules! emits_nothing(
+    () => ()
+);
+
+fn main() {
+    assert_eq!(unsafe { rust_get_test_int() }, 0isize);
+    assert_eq!(unsafe { rust_dbg_extern_identity_u32(0xDEADBEEF) }, 0xDEADBEEFu32);
+}
+
+#[link(name = "rust_test_helpers", kind = "static")]
+extern {
+    returns_isize!(rust_get_test_int);
+    //~^ ERROR Macro invocations in `extern {}` blocks are experimental.
+    takes_u32_returns_u32!(rust_dbg_extern_identity_u32);
+    //~^ ERROR Macro invocations in `extern {}` blocks are experimental.
+    emits_nothing!();
+    //~^ ERROR Macro invocations in `extern {}` blocks are experimental.
+}
diff --git a/src/test/compile-fail/rfc-2008-non-exhaustive/invalid-attribute.rs b/src/test/compile-fail/rfc-2008-non-exhaustive/invalid-attribute.rs
new file mode 100644 (file)
index 0000000..e48d989
--- /dev/null
@@ -0,0 +1,28 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(non_exhaustive)]
+
+#[non_exhaustive(anything)]
+//~^ ERROR attribute should be empty [E0911]
+struct Foo;
+
+#[non_exhaustive]
+//~^ ERROR attribute can only be applied to a struct or enum [E0910]
+trait Bar { }
+
+#[non_exhaustive]
+//~^ ERROR attribute can only be applied to a struct or enum [E0910]
+union Baz {
+    f1: u16,
+    f2: u16
+}
+
+fn main() { }
index a9762e383fe4e52e41dd3ea179f06c3e01e11975..337cae1369ee27c1928ac27eaed9bca959cc192b 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(generic_param_attrs, rustc_attrs)]
+#![feature(rustc_attrs)]
 
 fn func<#[rustc_synthetic] T>(_: T) {}
 
diff --git a/src/test/incremental/issue-49595/auxiliary/lit_a.rs b/src/test/incremental/issue-49595/auxiliary/lit_a.rs
new file mode 100644 (file)
index 0000000..f36baa0
--- /dev/null
@@ -0,0 +1,11 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub const A: &str = "hello";
diff --git a/src/test/incremental/issue-49595/auxiliary/lit_b.rs b/src/test/incremental/issue-49595/auxiliary/lit_b.rs
new file mode 100644 (file)
index 0000000..2252437
--- /dev/null
@@ -0,0 +1,11 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub const A: &str = "xxxxx";
diff --git a/src/test/incremental/issue-49595/issue_49595.rs b/src/test/incremental/issue-49595/issue_49595.rs
new file mode 100644 (file)
index 0000000..b899e02
--- /dev/null
@@ -0,0 +1,42 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// revisions:cfail1 cfail2 cfail3
+// compile-flags: -Z query-dep-graph --test
+// must-compile-successfully
+
+#![feature(rustc_attrs)]
+#![crate_type = "rlib"]
+
+#![rustc_partition_translated(module="issue_49595-tests", cfg="cfail2")]
+#![rustc_partition_translated(module="issue_49595-lit_test", cfg="cfail3")]
+
+mod tests {
+    #[cfg_attr(not(cfail1), ignore)]
+    #[test]
+    fn test() {
+    }
+}
+
+
+// Checks that changing a string literal without changing its span
+// takes effect.
+
+// replacing a module to have a stable span
+#[cfg_attr(not(cfail3), path = "auxiliary/lit_a.rs")]
+#[cfg_attr(cfail3, path = "auxiliary/lit_b.rs")]
+mod lit;
+
+pub mod lit_test {
+    #[test]
+    fn lit_test() {
+        println!("{}", ::lit::A);
+    }
+}
index 69c5cdccf49d7627e122d846f6195771b70fcf7f..e189f2e3b34a304a67cd0b810ff427d4ea8601f5 100644 (file)
@@ -14,7 +14,6 @@
 // A scenario with significant destruction code extents (which have
 // suffix "dce" in current `-Z identify_regions` rendering).
 
-#![feature(generic_param_attrs)]
 #![feature(dropck_eyepatch)]
 
 fn main() {
index 5ee84cd5543ba2854f4b7c4cacf31efe9a69403e..6899caa7153bb57c091ec13be5d5cec186b76c72 100644 (file)
@@ -10,7 +10,7 @@
 
 // compile-flags: -Z parse-only
 
-// error-pattern:unmatched visibility `pub`
+// error-pattern:expected one of `(`, `fn`, `static`, `type`, or `}` here
 extern {
     pub pub fn foo();
 }
index ff3fefde40ece69c6005601d7fd513b09afba3f8..aa0dbd4d4fc1b35957bbbd3f2399370215e0ae09 100644 (file)
@@ -10,8 +10,8 @@
 
 // compile-flags: -Z parse-only
 
-extern {
-    f(); //~ ERROR expected one of `!` or `::`, found `(`
+extern { //~ ERROR missing `fn`, `type`, or `static` for extern-item declaration
+    f();
 }
 
 fn main() {
diff --git a/src/test/run-fail/rfc-1937-termination-trait/termination-trait-for-box-dyn-error.rs b/src/test/run-fail/rfc-1937-termination-trait/termination-trait-for-box-dyn-error.rs
new file mode 100644 (file)
index 0000000..bd6bcf8
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// must-compile-successfully
+// failure-status: 1
+
+#![feature(dyn_trait)]
+
+use std::error::Error;
+use std::io;
+
+fn main() -> Result<(), Box<dyn Error>> {
+    Err(Box::new(io::Error::new(io::ErrorKind::Other, "returned Box<dyn Error> from main()")))
+}
diff --git a/src/test/run-fail/rfc-1937-termination-trait/termination-trait-for-str.rs b/src/test/run-fail/rfc-1937-termination-trait/termination-trait-for-str.rs
new file mode 100644 (file)
index 0000000..9f01b0b
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// error-pattern: An error message for you
+// failure-status: 1
+
+fn main() -> Result<(), &'static str> {
+    Err("An error message for you")
+}
diff --git a/src/test/run-make-fulldeps/resolve-rename/Makefile b/src/test/run-make-fulldeps/resolve-rename/Makefile
new file mode 100644 (file)
index 0000000..4b0c36d
--- /dev/null
@@ -0,0 +1,7 @@
+-include ../tools.mk
+
+all:
+       $(RUSTC) -C extra-filename=-hash foo.rs
+       $(RUSTC) bar.rs
+       mv $(TMPDIR)/libfoo-hash.rlib $(TMPDIR)/libfoo-another-hash.rlib
+       $(RUSTC) baz.rs
diff --git a/src/test/run-make-fulldeps/resolve-rename/bar.rs b/src/test/run-make-fulldeps/resolve-rename/bar.rs
new file mode 100644 (file)
index 0000000..1552b45
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_type = "rlib"]
+
+extern crate foo;
+
+pub fn bar() { foo::foo() }
diff --git a/src/test/run-make-fulldeps/resolve-rename/baz.rs b/src/test/run-make-fulldeps/resolve-rename/baz.rs
new file mode 100644 (file)
index 0000000..27d8014
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_type = "rlib"]
+
+extern crate bar;
+
+pub fn baz() { bar::bar() }
diff --git a/src/test/run-make-fulldeps/resolve-rename/foo.rs b/src/test/run-make-fulldeps/resolve-rename/foo.rs
new file mode 100644 (file)
index 0000000..830c289
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_type = "rlib"]
+
+pub fn foo() {}
index adc5be8016cf447ca614a1ac3af2a4ddf3375cd7..ce3b2d46bbc7b99dffa493e96554995ef49c7a0b 100644 (file)
@@ -13,3 +13,4 @@ endif
 all:
        $(RUSTC) bar.rs
        $(RUSTC) foo.rs $(FLAGS)
+       $(RUSTC) foo.rs $(FLAGS) -C panic=abort
index f1ada814bdb804648c8e3d40a279d844ef4673b1..17d470063fc934f6ce8fb418f00adf9863e4f1e5 100644 (file)
@@ -23,11 +23,11 @@ COMBINED_CDYLIB_NAME=libcombined_rlib_dylib.dylib
 endif
 
 all:
-       $(RUSTC) an_rlib.rs
-       $(RUSTC) a_cdylib.rs
-       $(RUSTC) a_rust_dylib.rs
-       $(RUSTC) an_executable.rs
-       $(RUSTC) a_cdylib.rs --crate-name combined_rlib_dylib --crate-type=rlib,cdylib
+       $(RUSTC) -Zshare-generics=no an_rlib.rs
+       $(RUSTC) -Zshare-generics=no a_cdylib.rs
+       $(RUSTC) -Zshare-generics=no a_rust_dylib.rs
+       $(RUSTC) -Zshare-generics=no an_executable.rs
+       $(RUSTC) -Zshare-generics=no a_cdylib.rs --crate-name combined_rlib_dylib --crate-type=rlib,cdylib
 
        # Check that a cdylib exports its public #[no_mangle] functions
        [ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -c public_c_function_from_cdylib)" -eq "1" ]
@@ -39,10 +39,15 @@ all:
        # Check that a Rust dylib exports its monomorphic functions
        [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c public_c_function_from_rust_dylib)" -eq "1" ]
        [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c _ZN.*public_rust_function_from_rust_dylib.*E)" -eq "1" ]
+       # Check that a Rust dylib does not export generics if -Zshare-generics=no
+       [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c _ZN.*public_generic_function_from_rust_dylib.*E)" -eq "0" ]
+
 
        # Check that a Rust dylib exports the monomorphic functions from its dependencies
        [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c public_c_function_from_rlib)" -eq "1" ]
        [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c public_rust_function_from_rlib)" -eq "1" ]
+       # Check that a Rust dylib does not export generics if -Zshare-generics=no
+       [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c _ZN.*public_generic_function_from_rlib.*E)" -eq "0" ]
 
        # Check that an executable does not export any dynamic symbols
        [ "$$($(NM) $(TMPDIR)/$(EXE_NAME) | grep -c public_c_function_from_rlib)" -eq "0" ]
@@ -57,4 +62,31 @@ all:
        [ "$$($(NM) $(TMPDIR)/$(COMBINED_CDYLIB_NAME) | grep -c public_c_function_from_rlib)" -eq "1" ]
        # Check that a cdylib DOES NOT export any public Rust functions
        [ "$$($(NM) $(TMPDIR)/$(COMBINED_CDYLIB_NAME) | grep -c _ZN.*h.*E)" -eq "0" ]
+
+
+       $(RUSTC) -Zshare-generics=yes an_rlib.rs
+       $(RUSTC) -Zshare-generics=yes a_cdylib.rs
+       $(RUSTC) -Zshare-generics=yes a_rust_dylib.rs
+       $(RUSTC) -Zshare-generics=yes an_executable.rs
+
+       # Check that a cdylib exports its public #[no_mangle] functions
+       [ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -c public_c_function_from_cdylib)" -eq "1" ]
+       # Check that a cdylib exports the public #[no_mangle] functions of dependencies
+       [ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -c public_c_function_from_rlib)" -eq "1" ]
+       # Check that a cdylib DOES NOT export any public Rust functions
+       [ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -c _ZN.*h.*E)" -eq "0" ]
+
+       # Check that a Rust dylib exports its monomorphic functions, including generics this time
+       [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c public_c_function_from_rust_dylib)" -eq "1" ]
+       [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c _ZN.*public_rust_function_from_rust_dylib.*E)" -eq "1" ]
+       [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c _ZN.*public_generic_function_from_rust_dylib.*E)" -eq "1" ]
+
+       # Check that a Rust dylib exports the monomorphic functions from its dependencies
+       [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c public_c_function_from_rlib)" -eq "1" ]
+       [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c public_rust_function_from_rlib)" -eq "1" ]
+       [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c _ZN.*public_generic_function_from_rlib.*E)" -eq "1" ]
+
+       # Check that an executable does not export any dynamic symbols
+       [ "$$($(NM) $(TMPDIR)/$(EXE_NAME) | grep -c public_c_function_from_rlib)" -eq "0" ]
+       [ "$$($(NM) $(TMPDIR)/$(EXE_NAME) | grep -c public_rust_function_from_exe)" -eq "0" ]
 endif
index b826211c9a42afab0b1aefc0161b1e37ace56d88..99e748ec2efc88e8659f64ed2eb97ef08c52efe1 100644 (file)
@@ -17,4 +17,9 @@ pub fn public_rust_function_from_rust_dylib() {}
 
 // This should be exported
 #[no_mangle]
-pub extern "C" fn public_c_function_from_rust_dylib() {}
+pub extern "C" fn public_c_function_from_rust_dylib() {
+    let _ = public_generic_function_from_rust_dylib(1u16);
+}
+
+// This should be exported if -Zshare-generics=yes
+pub fn public_generic_function_from_rust_dylib<T>(x: T) -> T { x }
index cd19500d14021f0e253fb75067c5caf4b20084a0..a1d73afd30b110684d51086d761cfa619e6d9665 100644 (file)
 pub fn public_rust_function_from_rlib() {}
 
 #[no_mangle]
-pub extern "C" fn public_c_function_from_rlib() {}
+pub extern "C" fn public_c_function_from_rlib() {
+    let _ = public_generic_function_from_rlib(0u64);
+}
+
+pub fn public_generic_function_from_rlib<T>(x: T) -> T {
+    x
+}
index e2c68a626f91e9b87d478a935cde7541ec7fe314..281ee70815e11c80442dfce57c8735435ef49c9a 100644 (file)
 
 extern crate proc_macro;
 
-use proc_macro::{TokenStream, TokenNode, quote};
+use proc_macro::*;
 
 #[proc_macro]
 pub fn cond(input: TokenStream) -> TokenStream {
     let mut conds = Vec::new();
     let mut input = input.into_iter().peekable();
     while let Some(tree) = input.next() {
-        let cond = match tree.kind {
-            TokenNode::Group(_, cond) => cond,
+        let cond = match tree {
+            TokenTree::Group(tt) => tt.stream(),
             _ => panic!("Invalid input"),
         };
         let mut cond_trees = cond.clone().into_iter();
@@ -32,8 +32,8 @@ pub fn cond(input: TokenStream) -> TokenStream {
         if rhs.is_empty() {
             panic!("Invalid macro usage in cond: {}", cond);
         }
-        let is_else = match test.kind {
-            TokenNode::Term(word) => word.as_str() == "else",
+        let is_else = match test {
+            TokenTree::Term(word) => word.as_str() == "else",
             _ => false,
         };
         conds.push(if is_else || input.peek().is_none() {
@@ -43,5 +43,5 @@ pub fn cond(input: TokenStream) -> TokenStream {
         });
     }
 
-    conds.into_iter().collect()
+    conds.into_iter().flat_map(|x| x.into_iter()).collect()
 }
index 5ebd32921329de2bf5efb4a25491e103b34e971b..2f80408ac1ce98833c65cefe424f84039810e961 100644 (file)
@@ -96,7 +96,9 @@ fn expand_into_foo_multi(cx: &mut ExtCtxt,
                 }
             })
         ],
-        // these are covered in proc_macro/attr-stmt-expr.rs
+        // covered in proc_macro/macros-in-extern.rs
+        Annotatable::ForeignItem(..) => unimplemented!(),
+        // covered in proc_macro/attr-stmt-expr.rs
         Annotatable::Stmt(_) | Annotatable::Expr(_) => panic!("expected item"),
     }
 }
@@ -110,7 +112,7 @@ fn expand_duplicate(cx: &mut ExtCtxt,
     let copy_name = match mi.node {
         ast::MetaItemKind::List(ref xs) => {
             if let Some(word) = xs[0].word() {
-                ast::Ident::with_empty_ctxt(word.name())
+                word.ident
             } else {
                 cx.span_err(mi.span, "Expected word");
                 return;
@@ -142,7 +144,9 @@ fn expand_duplicate(cx: &mut ExtCtxt,
             new_it.ident = copy_name;
             push(Annotatable::TraitItem(P(new_it)));
         }
-        // these are covered in proc_macro/attr-stmt-expr.rs
+        // covered in proc_macro/macros-in-extern.rs
+        Annotatable::ForeignItem(..) => unimplemented!(),
+        // covered in proc_macro/attr-stmt-expr.rs
         Annotatable::Stmt(_) | Annotatable::Expr(_) => panic!("expected item")
     }
 }
index 1b47043884844b49409b550d4356e09efed08785..d3670ae66feedf01ba43f5870b6b5131d3375afd 100644 (file)
@@ -15,7 +15,7 @@
 
 extern crate proc_macro;
 
-use proc_macro::{TokenStream, quote};
+use proc_macro::*;
 
 #[proc_macro_attribute]
 pub fn attr_tru(_attr: TokenStream, item: TokenStream) -> TokenStream {
index 920760cd34ac8d0ecd3eb1ad6f94ed6a1ae38b6c..3a848a31c4dd7671e712322a322d1132168f15fa 100644 (file)
@@ -61,15 +61,8 @@ fn expr(kind: ExprKind) -> P<Expr> {
 }
 
 fn make_x() -> P<Expr> {
-    let seg = PathSegment {
-        identifier: Ident::from_str("x"),
-        span: DUMMY_SP,
-        parameters: None,
-    };
-    let path = Path {
-        span: DUMMY_SP,
-        segments: vec![seg],
-    };
+    let seg = PathSegment::from_ident(Ident::from_str("x"));
+    let path = Path { segments: vec![seg], span: DUMMY_SP };
     expr(ExprKind::Path(None, path))
 }
 
@@ -89,12 +82,7 @@ fn iter_exprs(depth: usize, f: &mut FnMut(P<Expr>)) {
             0 => iter_exprs(depth - 1, &mut |e| g(ExprKind::Box(e))),
             1 => iter_exprs(depth - 1, &mut |e| g(ExprKind::Call(e, vec![]))),
             2 => {
-                let seg = PathSegment {
-                    identifier: Ident::from_str("x"),
-                    span: DUMMY_SP,
-                    parameters: None,
-                };
-
+                let seg = PathSegment::from_ident(Ident::from_str("x"));
                 iter_exprs(depth - 1, &mut |e| g(ExprKind::MethodCall(
                             seg.clone(), vec![e, make_x()])));
                 iter_exprs(depth - 1, &mut |e| g(ExprKind::MethodCall(
@@ -146,8 +134,7 @@ fn iter_exprs(depth: usize, f: &mut FnMut(P<Expr>)) {
                 iter_exprs(depth - 1, &mut |e| g(ExprKind::Assign(make_x(), e)));
             },
             10 => {
-                let ident = Spanned { span: DUMMY_SP, node: Ident::from_str("f") };
-                iter_exprs(depth - 1, &mut |e| g(ExprKind::Field(e, ident)));
+                iter_exprs(depth - 1, &mut |e| g(ExprKind::Field(e, Ident::from_str("f"))));
             },
             11 => {
                 iter_exprs(depth - 1, &mut |e| g(ExprKind::Range(
@@ -163,15 +150,7 @@ fn iter_exprs(depth: usize, f: &mut FnMut(P<Expr>)) {
                 iter_exprs(depth - 1, &mut |e| g(ExprKind::Ret(Some(e))));
             },
             14 => {
-                let seg = PathSegment {
-                    identifier: Ident::from_str("S"),
-                    span: DUMMY_SP,
-                    parameters: None,
-                };
-                let path = Path {
-                    span: DUMMY_SP,
-                    segments: vec![seg],
-                };
+                let path = Path::from_ident(Ident::from_str("S"));
                 g(ExprKind::Struct(path, vec![], Some(make_x())));
             },
             15 => {
index ec2ff0d1e2b8c81769fd777fa2ff9cfa7d243014..063d8dc40536dc5a737ca96020bafc1d8af0e2a9 100644 (file)
 
 extern crate proc_macro;
 
-use proc_macro::{TokenStream, TokenNode, Spacing, Literal, quote};
+use proc_macro::{TokenStream, TokenTree, Spacing, Literal, quote};
 
 #[proc_macro]
 pub fn count_compound_ops(input: TokenStream) -> TokenStream {
     assert_eq!(count_compound_ops_helper(quote!(++ (&&) 4@a)), 3);
-    TokenNode::Literal(Literal::u32(count_compound_ops_helper(input))).into()
+    let l = Literal::u32_suffixed(count_compound_ops_helper(input));
+    TokenTree::from(l).into()
 }
 
 fn count_compound_ops_helper(input: TokenStream) -> u32 {
     let mut count = 0;
     for token in input {
-        match token.kind {
-            TokenNode::Op(c, Spacing::Alone) => count += 1,
-            TokenNode::Group(_, tokens) => count += count_compound_ops_helper(tokens),
+        match &token {
+            TokenTree::Op(tt) if tt.spacing() == Spacing::Alone => {
+                count += 1;
+            }
+            TokenTree::Group(tt) => {
+                count += count_compound_ops_helper(tt.stream());
+            }
             _ => {}
         }
     }
index e5ebb7c2e41b3fa53f224c6a690a4885cfeb484e..e76e4d585f497562691d16094397c253923e04e1 100644 (file)
 
 #[proc_macro]
 pub fn neg_one(_input: TokenStream) -> TokenStream {
-    TokenTree {
-        span: Span::call_site(),
-        kind: TokenNode::Literal(Literal::i32(-1)),
-    }.into()
+    TokenTree::Literal(Literal::i32_suffixed(-1)).into()
 }
 
 #[proc_macro]
 pub fn neg_one_float(_input: TokenStream) -> TokenStream {
-    TokenTree {
-        span: Span::call_site(),
-        kind: TokenNode::Literal(Literal::f32(-1.0)),
-    }.into()
+    TokenTree::Literal(Literal::f32_suffixed(-1.0)).into()
 }
index ce6ffcc3cb03d5abac7fe90bcee65dd82c5ce9f0..6ab9d6d0b8a7ce1dc688b54a6ce7161ee02f6c2c 100644 (file)
@@ -27,7 +27,7 @@ pub fn reemit(input: TokenStream) -> TokenStream {
 #[proc_macro]
 pub fn assert_fake_source_file(input: TokenStream) -> TokenStream {
     for tk in input {
-        let source_file = tk.span.source_file();
+        let source_file = tk.span().source_file();
         assert!(!source_file.is_real(), "Source file is real: {:?}", source_file);
     }
 
@@ -37,7 +37,7 @@ pub fn assert_fake_source_file(input: TokenStream) -> TokenStream {
 #[proc_macro]
 pub fn assert_source_file(input: TokenStream) -> TokenStream {
     for tk in input {
-        let source_file = tk.span.source_file();
+        let source_file = tk.span().source_file();
         assert!(source_file.is_real(), "Source file is not real: {:?}", source_file);
     }
 
diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/test-macros.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/test-macros.rs
new file mode 100644 (file)
index 0000000..d1c5b90
--- /dev/null
@@ -0,0 +1,36 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+#![feature(proc_macro)]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_attribute]
+pub fn nop_attr(_attr: TokenStream, input: TokenStream) -> TokenStream {
+    assert!(_attr.to_string().is_empty());
+    input
+}
+
+#[proc_macro_attribute]
+pub fn no_output(_attr: TokenStream, _input: TokenStream) -> TokenStream {
+    assert!(_attr.to_string().is_empty());
+    assert!(!_input.to_string().is_empty());
+    "".parse().unwrap()
+}
+
+#[proc_macro]
+pub fn emit_input(input: TokenStream) -> TokenStream {
+    input
+}
diff --git a/src/test/run-pass-fulldeps/proc-macro/macros-in-extern.rs b/src/test/run-pass-fulldeps/proc-macro/macros-in-extern.rs
new file mode 100644 (file)
index 0000000..59b9b0b
--- /dev/null
@@ -0,0 +1,35 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:test-macros.rs
+// ignore-stage1
+// ignore-wasm32
+
+#![feature(proc_macro, macros_in_extern)]
+
+extern crate test_macros;
+
+use test_macros::{nop_attr, no_output, emit_input};
+
+fn main() {
+    assert_eq!(unsafe { rust_get_test_int() }, 1isize);
+    assert_eq!(unsafe { rust_dbg_extern_identity_u32(0xDEADBEEF) }, 0xDEADBEEF);
+}
+
+#[link(name = "rust_test_helpers", kind = "static")]
+extern {
+    #[no_output]
+    fn some_definitely_unknown_symbol_which_should_be_removed();
+
+    #[nop_attr]
+    fn rust_get_test_int() -> isize;
+
+    emit_input!(fn rust_dbg_extern_identity_u32(arg: u32) -> u32;);
+}
index 5985284d8496b83676a84daf4cc5116554800705..e87b9e3d82a24ae3fba6d98647dbf8b93d4d6ba6 100644 (file)
@@ -17,7 +17,7 @@
 // using `rustc_attrs` feature. There is a separate compile-fail/ test
 // ensuring that the attribute feature-gating works in this context.)
 
-#![feature(generic_param_attrs, rustc_attrs)]
+#![feature(rustc_attrs)]
 #![allow(dead_code)]
 
 struct StLt<#[rustc_lt_struct] 'a>(&'a u32);
index 1266e589b127e54b62928fade13422c992ada1dd..d89129434411520827d2c7896b199d090b712b67 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(generic_param_attrs)]
 #![feature(dropck_eyepatch)]
 
 // The point of this test is to illustrate that the `#[may_dangle]`
index f35946790955360be57bf8f2e09c009ef82c6670..9b06bf837ae0ccf266e24f63ce341dfb7cf1afc1 100644 (file)
@@ -27,4 +27,8 @@ trait SelfBound<T: Copy=Self> {}
 // Not even for well-formedness.
 struct WellFormedProjection<A, T=<A as Iterator>::Item>(A, T);
 
+// Issue #49344, predicates with lifetimes should not be checked.
+trait Scope<'a> {}
+struct Request<'a, S: Scope<'a> = i32>(S, &'a ());
+
 fn main() {}
index bbf8bb8c352389f2c246b5ea44b3c0f7c5930645..a99a7232e9ebc6d51b67d43870358822a0d40810 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(generic_param_attrs)]
 #![feature(dropck_eyepatch)]
 
 // The point of this test is to test uses of `#[may_dangle]` attribute
index 4a09ba05dff5eec3af108c0cbc21d759d4655f34..c0c091d78eb16dd688aba30a7f9bcc9bbf7ea786 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(generic_param_attrs)]
 #![feature(dropck_eyepatch)]
 
 // The point of this test is to illustrate that the `#[may_dangle]`
diff --git a/src/test/run-pass/issue-48962.rs b/src/test/run-pass/issue-48962.rs
new file mode 100644 (file)
index 0000000..a603dfb
--- /dev/null
@@ -0,0 +1,43 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that we are able to reinitilize box with moved referent
+#![feature(nll)]
+static mut ORDER: [usize; 3] = [0, 0, 0];
+static mut INDEX: usize = 0;
+
+struct Dropee (usize);
+
+impl Drop for Dropee {
+    fn drop(&mut self) {
+        unsafe {
+            ORDER[INDEX] = self.0;
+            INDEX = INDEX + 1;
+        }
+    }
+}
+
+fn add_sentintel() {
+    unsafe {
+        ORDER[INDEX] = 2;
+        INDEX = INDEX + 1;
+    }
+}
+
+fn main() {
+    let mut x = Box::new(Dropee(1));
+    *x;  // move out from `*x`
+    add_sentintel();
+    *x = Dropee(3); // re-initialize `*x`
+    {x}; // drop value
+    unsafe {
+        assert_eq!(ORDER, [1, 2, 3]);
+    }
+}
diff --git a/src/test/run-pass/macros-in-extern.rs b/src/test/run-pass/macros-in-extern.rs
new file mode 100644 (file)
index 0000000..d909493
--- /dev/null
@@ -0,0 +1,39 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-wasm32
+
+#![feature(decl_macro, macros_in_extern)]
+
+macro_rules! returns_isize(
+    ($ident:ident) => (
+        fn $ident() -> isize;
+    )
+);
+
+macro takes_u32_returns_u32($ident:ident) {
+    fn $ident (arg: u32) -> u32;
+}
+
+macro_rules! emits_nothing(
+    () => ()
+);
+
+fn main() {
+    assert_eq!(unsafe { rust_get_test_int() }, 1isize);
+    assert_eq!(unsafe { rust_dbg_extern_identity_u32(0xDEADBEEF) }, 0xDEADBEEFu32);
+}
+
+#[link(name = "rust_test_helpers", kind = "static")]
+extern {
+    returns_isize!(rust_get_test_int);
+    takes_u32_returns_u32!(rust_dbg_extern_identity_u32);
+    emits_nothing!();
+}
diff --git a/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-box-dyn-error.rs b/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-box-dyn-error.rs
new file mode 100644 (file)
index 0000000..24c30a5
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(dyn_trait)]
+
+use std::error::Error;
+
+fn main() -> Result<(), Box<dyn Error>> {
+    Ok(())
+}
diff --git a/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-str.rs b/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-str.rs
new file mode 100644 (file)
index 0000000..2023ff7
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() -> Result<(), &'static str> {
+    Ok(())
+}
diff --git a/src/test/rustdoc/all.rs b/src/test/rustdoc/all.rs
new file mode 100644 (file)
index 0000000..ec39131
--- /dev/null
@@ -0,0 +1,30 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_name = "foo"]
+
+// @has foo/all.html '//a[@href="struct.Struct.html"]' 'Struct'
+// @has foo/all.html '//a[@href="enum.Enum.html"]' 'Enum'
+// @has foo/all.html '//a[@href="union.Union.html"]' 'Union'
+// @has foo/all.html '//a[@href="constant.CONST.html"]' 'CONST'
+// @has foo/all.html '//a[@href="static.STATIC.html"]' 'STATIC'
+// @has foo/all.html '//a[@href="fn.function.html"]' 'function'
+
+pub struct Struct;
+pub enum Enum {
+    X,
+    Y,
+}
+pub union Union {
+    x: u32,
+}
+pub const CONST: u32 = 0;
+pub static STATIC: &str = "baguette";
+pub fn function() {}
diff --git a/src/test/rustdoc/unneeded-trait-implementations-title.rs b/src/test/rustdoc/unneeded-trait-implementations-title.rs
new file mode 100644 (file)
index 0000000..2c07417
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_name = "foo"]
+
+pub struct Bar;
+
+// @!has foo/struct.Bar.html '//*[@id="implementations"]'
index 3eb96c2ab9622d71846942bb389b4552f7e9c6ff..ed11b2db2f5ffb235eaecd81e7a1d621642eb1f5 100644 (file)
 
 extern crate proc_macro;
 
-use proc_macro::{TokenStream, TokenTree, TokenNode, Span};
+use proc_macro::{TokenStream, TokenTree, Span};
 
 fn lit_span(tt: TokenTree) -> (Span, String) {
-    use TokenNode::*;
-    match tt.kind {
-        Literal(..) | Group(..) => (tt.span, tt.to_string().trim().into()),
+    match tt {
+        TokenTree::Literal(..) |
+        TokenTree::Group(..) => (tt.span(), tt.to_string().trim().into()),
         _ => panic!("expected a literal in token tree, got: {:?}", tt)
     }
 }
index 2381c61b87bd0ab939a7e4d128a9efd5ceec9f86..fda0e28891f26b0712f7b264f3b8070a8348e100 100644 (file)
 
 extern crate proc_macro;
 
-use proc_macro::{TokenStream, TokenNode, Span, Diagnostic};
+use proc_macro::{TokenStream, TokenTree, Span, Diagnostic};
 
 fn parse(input: TokenStream) -> Result<(), Diagnostic> {
     let mut count = 0;
     let mut last_span = Span::def_site();
     for tree in input {
-        let span = tree.span;
+        let span = tree.span();
         if count >= 3 {
             return Err(span.error(format!("expected EOF, found `{}`.", tree))
                            .span_note(last_span, "last good input was here")
                            .help("input must be: `===`"))
         }
 
-        if let TokenNode::Op('=', _) = tree.kind {
-            count += 1;
-        } else {
-            return Err(span.error(format!("expected `=`, found `{}`.", tree)));
+        if let TokenTree::Op(tt) = tree {
+            if tt.op() == '=' {
+                count += 1;
+                last_span = span;
+                continue
+            }
         }
-
-        last_span = span;
+        return Err(span.error(format!("expected `=`, found `{}`.", tree)));
     }
 
     if count < 3 {
diff --git a/src/test/ui/borrowck/two-phase-multi-mut.rs b/src/test/ui/borrowck/two-phase-multi-mut.rs
new file mode 100644 (file)
index 0000000..2b82362
--- /dev/null
@@ -0,0 +1,26 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(nll)]
+
+struct Foo {
+}
+
+impl Foo {
+    fn method(&mut self, foo: &mut Foo) {
+    }
+}
+
+fn main() {
+    let mut foo = Foo { };
+    foo.method(&mut foo);
+    //~^     cannot borrow `foo` as mutable more than once at a time
+    //~^^    cannot borrow `foo` as mutable more than once at a time
+}
diff --git a/src/test/ui/borrowck/two-phase-multi-mut.stderr b/src/test/ui/borrowck/two-phase-multi-mut.stderr
new file mode 100644 (file)
index 0000000..0c02acf
--- /dev/null
@@ -0,0 +1,23 @@
+error[E0499]: cannot borrow `foo` as mutable more than once at a time
+  --> $DIR/two-phase-multi-mut.rs:23:16
+   |
+LL |     foo.method(&mut foo);
+   |     -----------^^^^^^^^-
+   |     |          |
+   |     |          second mutable borrow occurs here
+   |     first mutable borrow occurs here
+   |     borrow later used here
+
+error[E0499]: cannot borrow `foo` as mutable more than once at a time
+  --> $DIR/two-phase-multi-mut.rs:23:5
+   |
+LL |     foo.method(&mut foo);
+   |     ^^^^^^^^^^^--------^
+   |     |          |
+   |     |          first mutable borrow occurs here
+   |     second mutable borrow occurs here
+   |     borrow later used here
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/src/test/ui/borrowck/two-phase-multiple-activations.rs b/src/test/ui/borrowck/two-phase-multiple-activations.rs
new file mode 100644 (file)
index 0000000..e1ed41b
--- /dev/null
@@ -0,0 +1,35 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// revisions: lxl nll
+//[lxl]compile-flags: -Z borrowck=mir -Z two-phase-borrows
+//[nll]compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z nll
+
+// run-pass
+
+use std::io::Result;
+
+struct Foo {}
+
+pub trait FakeRead {
+    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize>;
+}
+
+impl FakeRead for Foo {
+    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize> {
+        Ok(4)
+    }
+}
+
+fn main() {
+    let mut a = Foo {};
+    let mut v = Vec::new();
+    a.read_to_end(&mut v);
+}
index 010cb77edc3f10e87c2ad921edde77d4e93042f2..74feb0105ccf1ced50accc11a62f8a6c53180a92 100644 (file)
@@ -11,6 +11,9 @@
 #![feature(rustc_attrs)]
 
 #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<S, T, U>) :-
+                              //~| ERROR FromEnv
+                              //~| ERROR FromEnv
+                              //~| ERROR FromEnv
 trait Foo<S, T, U> {
     fn s(S) -> S;
     fn t(T) -> T;
index 6da1e2fd8edd8f810a1b858fc32c970536286fcd..45753c3bb90c2977a6b88e17e9fe1d1c43b8d3b2 100644 (file)
@@ -4,5 +4,23 @@ error: Implemented(Self: Foo<S, T, U>) :- FromEnv(Self: Foo<S, T, U>).
 LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<S, T, U>) :-
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error
+error: FromEnv(S: std::marker::Sized) :- FromEnv(Self: Foo<S, T, U>).
+  --> $DIR/lower_trait.rs:13:1
+   |
+LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<S, T, U>) :-
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: FromEnv(T: std::marker::Sized) :- FromEnv(Self: Foo<S, T, U>).
+  --> $DIR/lower_trait.rs:13:1
+   |
+LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<S, T, U>) :-
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: FromEnv(U: std::marker::Sized) :- FromEnv(Self: Foo<S, T, U>).
+  --> $DIR/lower_trait.rs:13:1
+   |
+LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<S, T, U>) :-
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/chalkify/lower_trait_higher_rank.rs b/src/test/ui/chalkify/lower_trait_higher_rank.rs
new file mode 100644 (file)
index 0000000..e5eaf45
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(rustc_attrs)]
+
+#[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<F>) :-
+                              //~| ERROR FromEnv
+                              //~| ERROR FromEnv
+                              //~| ERROR FromEnv
+trait Foo<F> where for<'a> F: Fn(&'a (u8, u16)) -> &'a u8
+{
+    fn s(F) -> F;
+}
+
+fn main() {
+    println!("hello");
+}
diff --git a/src/test/ui/chalkify/lower_trait_higher_rank.stderr b/src/test/ui/chalkify/lower_trait_higher_rank.stderr
new file mode 100644 (file)
index 0000000..9aed0c0
--- /dev/null
@@ -0,0 +1,26 @@
+error: Implemented(Self: Foo<F>) :- FromEnv(Self: Foo<F>).
+  --> $DIR/lower_trait_higher_rank.rs:13:1
+   |
+LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<F>) :-
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: FromEnv(F: std::marker::Sized) :- FromEnv(Self: Foo<F>).
+  --> $DIR/lower_trait_higher_rank.rs:13:1
+   |
+LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<F>) :-
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: FromEnv(F: std::ops::Fn<(&'a (u8, u16),)>) :- FromEnv(Self: Foo<F>).
+  --> $DIR/lower_trait_higher_rank.rs:13:1
+   |
+LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<F>) :-
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: FromEnv(<F as std::ops::FnOnce<(&'a (u8, u16),)>>::Output == &'a u8) :- FromEnv(Self: Foo<F>).
+  --> $DIR/lower_trait_higher_rank.rs:13:1
+   |
+LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<F>) :-
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/chalkify/lower_trait_where_clause.rs b/src/test/ui/chalkify/lower_trait_where_clause.rs
new file mode 100644 (file)
index 0000000..b2ce3ca
--- /dev/null
@@ -0,0 +1,31 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(rustc_attrs)]
+
+use std::fmt::{Debug, Display};
+use std::borrow::Borrow;
+
+#[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<'a, 'b, S, T, U>) :-
+                              //~| ERROR FromEnv
+                              //~| ERROR FromEnv
+                              //~| ERROR FromEnv
+                              //~| ERROR FromEnv
+                              //~| ERROR RegionOutlives
+                              //~| ERROR TypeOutlives
+trait Foo<'a, 'b, S, T, U> where S: Debug, T: Borrow<U>, U: ?Sized, 'a: 'b, U: 'b {
+    fn s(S) -> S;
+    fn t(T) -> T;
+    fn u(U) -> U;
+}
+
+fn main() {
+    println!("hello");
+}
diff --git a/src/test/ui/chalkify/lower_trait_where_clause.stderr b/src/test/ui/chalkify/lower_trait_where_clause.stderr
new file mode 100644 (file)
index 0000000..a9ecaec
--- /dev/null
@@ -0,0 +1,44 @@
+error: Implemented(Self: Foo<'a, 'b, S, T, U>) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
+  --> $DIR/lower_trait_where_clause.rs:16:1
+   |
+LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<'a, 'b, S, T, U>) :-
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: FromEnv(S: std::marker::Sized) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
+  --> $DIR/lower_trait_where_clause.rs:16:1
+   |
+LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<'a, 'b, S, T, U>) :-
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: FromEnv(T: std::marker::Sized) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
+  --> $DIR/lower_trait_where_clause.rs:16:1
+   |
+LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<'a, 'b, S, T, U>) :-
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: FromEnv(S: std::fmt::Debug) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
+  --> $DIR/lower_trait_where_clause.rs:16:1
+   |
+LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<'a, 'b, S, T, U>) :-
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: FromEnv(T: std::borrow::Borrow<U>) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
+  --> $DIR/lower_trait_where_clause.rs:16:1
+   |
+LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<'a, 'b, S, T, U>) :-
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: RegionOutlives('a : 'b) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
+  --> $DIR/lower_trait_where_clause.rs:16:1
+   |
+LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<'a, 'b, S, T, U>) :-
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: TypeOutlives(U : 'b) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
+  --> $DIR/lower_trait_where_clause.rs:16:1
+   |
+LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<'a, 'b, S, T, U>) :-
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 7 previous errors
+
diff --git a/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.rs b/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.rs
new file mode 100644 (file)
index 0000000..4526517
--- /dev/null
@@ -0,0 +1,44 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn gratitude() {
+    let for_you = false;
+    if not for_you {
+        //~^ ERROR unexpected `for_you` after identifier
+        println!("I couldn't");
+    }
+}
+
+fn qualification() {
+    let the_worst = true;
+    while not the_worst {
+        //~^ ERROR unexpected `the_worst` after identifier
+        println!("still pretty bad");
+    }
+}
+
+fn should_we() {
+    let not = true;
+    if not  // lack of braces is [sic]
+        println!("Then when?");
+    //~^ ERROR expected `{`, found `;
+    //~| ERROR unexpected `println` after identifier
+}
+
+fn sleepy() {
+    let resource = not 2;
+    //~^ ERROR unexpected `2` after identifier
+}
+
+fn main() {
+    let be_smothered_out_before = true;
+    let young_souls = not be_smothered_out_before;
+    //~^ ERROR unexpected `be_smothered_out_before` after identifier
+}
diff --git a/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr b/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr
new file mode 100644 (file)
index 0000000..db34781
--- /dev/null
@@ -0,0 +1,50 @@
+error: unexpected `for_you` after identifier
+  --> $DIR/issue-46836-identifier-not-instead-of-negation.rs:13:12
+   |
+LL |     if not for_you {
+   |        ----^^^^^^^
+   |        |
+   |        help: use `!` to perform logical negation
+
+error: unexpected `the_worst` after identifier
+  --> $DIR/issue-46836-identifier-not-instead-of-negation.rs:21:15
+   |
+LL |     while not the_worst {
+   |           ----^^^^^^^^^
+   |           |
+   |           help: use `!` to perform logical negation
+
+error: unexpected `println` after identifier
+  --> $DIR/issue-46836-identifier-not-instead-of-negation.rs:30:9
+   |
+LL |     if not  // lack of braces is [sic]
+   |        ----- help: use `!` to perform logical negation
+LL |         println!("Then when?");
+   |         ^^^^^^^
+
+error: expected `{`, found `;`
+  --> $DIR/issue-46836-identifier-not-instead-of-negation.rs:30:31
+   |
+LL |     if not  // lack of braces is [sic]
+   |     -- this `if` statement has a condition, but no block
+LL |         println!("Then when?");
+   |                               ^
+
+error: unexpected `2` after identifier
+  --> $DIR/issue-46836-identifier-not-instead-of-negation.rs:36:24
+   |
+LL |     let resource = not 2;
+   |                    ----^
+   |                    |
+   |                    help: use `!` to perform logical negation
+
+error: unexpected `be_smothered_out_before` after identifier
+  --> $DIR/issue-46836-identifier-not-instead-of-negation.rs:42:27
+   |
+LL |     let young_souls = not be_smothered_out_before;
+   |                       ----^^^^^^^^^^^^^^^^^^^^^^^
+   |                       |
+   |                       help: use `!` to perform logical negation
+
+error: aborting due to 6 previous errors
+
index 1b00d88dcb3dfd78d9fba23aab85499ff10d220b..08722ca62ac4197eaffec3b378048dfc1e4e1349 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(generic_param_attrs)]
 #![feature(dropck_eyepatch)]
 
 // This is a support file for ../dropck-eyepatch-extern-crate.rs
index f92c8703dc9273b9ddb3055db23b98aab705ae43..cba438b02a922f529bca5448df040ee01130d5c4 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(generic_param_attrs)]
 #![feature(dropck_eyepatch)]
 
 // This test ensures that a use of `#[may_dangle]` is rejected if
index f4ea7f1bc50987ea50e10d356cedca93899fdcb3..9d68ff13ef343db88c04d7a449c7bed4631d892d 100644 (file)
@@ -1,5 +1,5 @@
 error[E0569]: requires an `unsafe impl` declaration due to `#[may_dangle]` attribute
-  --> $DIR/dropck-eyepatch-implies-unsafe-impl.rs:32:1
+  --> $DIR/dropck-eyepatch-implies-unsafe-impl.rs:31:1
    |
 LL | / impl<#[may_dangle] A, B: fmt::Debug> Drop for Pt<A, B> {
 LL | |     //~^ ERROR requires an `unsafe impl` declaration due to `#[may_dangle]` attribute
@@ -10,7 +10,7 @@ LL | | }
    | |_^
 
 error[E0569]: requires an `unsafe impl` declaration due to `#[may_dangle]` attribute
-  --> $DIR/dropck-eyepatch-implies-unsafe-impl.rs:38:1
+  --> $DIR/dropck-eyepatch-implies-unsafe-impl.rs:37:1
    |
 LL | / impl<#[may_dangle] 'a, 'b, B: fmt::Debug> Drop for Pr<'a, 'b, B> {
 LL | |     //~^ ERROR requires an `unsafe impl` declaration due to `#[may_dangle]` attribute
index 3bd9efb32b3b4fba046645a2072e66375638b1fc..eda8d85f6ec952c4a38f28126b0e3d7d5d7ff52b 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(generic_param_attrs)]
 #![feature(dropck_eyepatch)]
 
 // The point of this test is to test uses of `#[may_dangle]` attribute
index e6ce53402f4f36e722e40e02e2d837758bca149a..1a35996a0cadb57917dbfbedc8211a773bf1df6d 100644 (file)
@@ -1,5 +1,5 @@
 error[E0597]: `c` does not live long enough
-  --> $DIR/dropck-eyepatch-reorder.rs:57:20
+  --> $DIR/dropck-eyepatch-reorder.rs:56:20
    |
 LL |     dt = Dt("dt", &c);
    |                    ^ borrowed value does not live long enough
@@ -10,7 +10,7 @@ LL | }
    = note: values in a scope are dropped in the opposite order they are created
 
 error[E0597]: `c` does not live long enough
-  --> $DIR/dropck-eyepatch-reorder.rs:59:20
+  --> $DIR/dropck-eyepatch-reorder.rs:58:20
    |
 LL |     dr = Dr("dr", &c);
    |                    ^ borrowed value does not live long enough
@@ -21,7 +21,7 @@ LL | }
    = note: values in a scope are dropped in the opposite order they are created
 
 error[E0597]: `c` does not live long enough
-  --> $DIR/dropck-eyepatch-reorder.rs:67:29
+  --> $DIR/dropck-eyepatch-reorder.rs:66:29
    |
 LL |     pt = Pt("pt", &c_long, &c);
    |                             ^ borrowed value does not live long enough
@@ -32,7 +32,7 @@ LL | }
    = note: values in a scope are dropped in the opposite order they are created
 
 error[E0597]: `c` does not live long enough
-  --> $DIR/dropck-eyepatch-reorder.rs:69:29
+  --> $DIR/dropck-eyepatch-reorder.rs:68:29
    |
 LL |     pr = Pr("pr", &c_long, &c);
    |                             ^ borrowed value does not live long enough
index abaae47189f8bf77703a1b1c8a25b44a80a4a17b..af173a2e97916610e34298331856ae9bb8e34440 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(generic_param_attrs)]
 #![feature(dropck_eyepatch)]
 
 // The point of this test is to illustrate that the `#[may_dangle]`
index 5e0a4a744212def606da4f1753f228c5ad5fa668..4d291642022939b5d5e531b65547202b81742117 100644 (file)
@@ -1,5 +1,5 @@
 error[E0597]: `c` does not live long enough
-  --> $DIR/dropck-eyepatch.rs:80:20
+  --> $DIR/dropck-eyepatch.rs:79:20
    |
 LL |     dt = Dt("dt", &c);
    |                    ^ borrowed value does not live long enough
@@ -10,7 +10,7 @@ LL | }
    = note: values in a scope are dropped in the opposite order they are created
 
 error[E0597]: `c` does not live long enough
-  --> $DIR/dropck-eyepatch.rs:82:20
+  --> $DIR/dropck-eyepatch.rs:81:20
    |
 LL |     dr = Dr("dr", &c);
    |                    ^ borrowed value does not live long enough
@@ -21,7 +21,7 @@ LL | }
    = note: values in a scope are dropped in the opposite order they are created
 
 error[E0597]: `c` does not live long enough
-  --> $DIR/dropck-eyepatch.rs:90:29
+  --> $DIR/dropck-eyepatch.rs:89:29
    |
 LL |     pt = Pt("pt", &c_long, &c);
    |                             ^ borrowed value does not live long enough
@@ -32,7 +32,7 @@ LL | }
    = note: values in a scope are dropped in the opposite order they are created
 
 error[E0597]: `c` does not live long enough
-  --> $DIR/dropck-eyepatch.rs:92:29
+  --> $DIR/dropck-eyepatch.rs:91:29
    |
 LL |     pr = Pr("pr", &c_long, &c);
    |                             ^ borrowed value does not live long enough
index 0d89c52d885f9022a85dfffaddd905ddd7914263..30fd89f091b47443164f956bb93f54eadef3e7d4 100644 (file)
 
 // This test ensures that attributes on formals in generic parameter
 // lists are included when we are checking for unstable attributes.
-//
-// Note that feature(generic_param_attrs) *is* enabled here. We are
-// checking feature-gating of the attributes themselves, not the
-// capability to parse such attributes in that context.
 
 // gate-test-custom_attribute
 
-#![feature(generic_param_attrs)]
-#![allow(dead_code)]
-
 struct StLt<#[lt_struct] 'a>(&'a u32);
 //~^ ERROR The attribute `lt_struct` is currently unknown to the compiler
 struct StTy<#[ty_struct] I>(I);
index 90be45a33eacbacdfd7b10c245be519b1e40debd..1c1f50366d64c8c81d4fa1f9c17411fe43036b1b 100644 (file)
@@ -1,5 +1,5 @@
 error[E0658]: The attribute `lt_struct` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
-  --> $DIR/feature-gate-custom_attribute2.rs:23:13
+  --> $DIR/feature-gate-custom_attribute2.rs:16:13
    |
 LL | struct StLt<#[lt_struct] 'a>(&'a u32);
    |             ^^^^^^^^^^^^
@@ -7,7 +7,7 @@ LL | struct StLt<#[lt_struct] 'a>(&'a u32);
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
 error[E0658]: The attribute `ty_struct` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
-  --> $DIR/feature-gate-custom_attribute2.rs:25:13
+  --> $DIR/feature-gate-custom_attribute2.rs:18:13
    |
 LL | struct StTy<#[ty_struct] I>(I);
    |             ^^^^^^^^^^^^
@@ -15,7 +15,7 @@ LL | struct StTy<#[ty_struct] I>(I);
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
 error[E0658]: The attribute `lt_enum` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
-  --> $DIR/feature-gate-custom_attribute2.rs:28:11
+  --> $DIR/feature-gate-custom_attribute2.rs:21:11
    |
 LL | enum EnLt<#[lt_enum] 'b> { A(&'b u32), B }
    |           ^^^^^^^^^^
@@ -23,7 +23,7 @@ LL | enum EnLt<#[lt_enum] 'b> { A(&'b u32), B }
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
 error[E0658]: The attribute `ty_enum` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
-  --> $DIR/feature-gate-custom_attribute2.rs:30:11
+  --> $DIR/feature-gate-custom_attribute2.rs:23:11
    |
 LL | enum EnTy<#[ty_enum] J> { A(J), B }
    |           ^^^^^^^^^^
@@ -31,7 +31,7 @@ LL | enum EnTy<#[ty_enum] J> { A(J), B }
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
 error[E0658]: The attribute `lt_trait` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
-  --> $DIR/feature-gate-custom_attribute2.rs:33:12
+  --> $DIR/feature-gate-custom_attribute2.rs:26:12
    |
 LL | trait TrLt<#[lt_trait] 'c> { fn foo(&self, _: &'c [u32]) -> &'c u32; }
    |            ^^^^^^^^^^^
@@ -39,7 +39,7 @@ LL | trait TrLt<#[lt_trait] 'c> { fn foo(&self, _: &'c [u32]) -> &'c u32; }
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
 error[E0658]: The attribute `ty_trait` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
-  --> $DIR/feature-gate-custom_attribute2.rs:35:12
+  --> $DIR/feature-gate-custom_attribute2.rs:28:12
    |
 LL | trait TrTy<#[ty_trait] K> { fn foo(&self, _: K); }
    |            ^^^^^^^^^^^
@@ -47,7 +47,7 @@ LL | trait TrTy<#[ty_trait] K> { fn foo(&self, _: K); }
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
 error[E0658]: The attribute `lt_type` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
-  --> $DIR/feature-gate-custom_attribute2.rs:38:11
+  --> $DIR/feature-gate-custom_attribute2.rs:31:11
    |
 LL | type TyLt<#[lt_type] 'd> = &'d u32;
    |           ^^^^^^^^^^
@@ -55,7 +55,7 @@ LL | type TyLt<#[lt_type] 'd> = &'d u32;
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
 error[E0658]: The attribute `ty_type` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
-  --> $DIR/feature-gate-custom_attribute2.rs:40:11
+  --> $DIR/feature-gate-custom_attribute2.rs:33:11
    |
 LL | type TyTy<#[ty_type] L> = (L, );
    |           ^^^^^^^^^^
@@ -63,7 +63,7 @@ LL | type TyTy<#[ty_type] L> = (L, );
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
 error[E0658]: The attribute `lt_inherent` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
-  --> $DIR/feature-gate-custom_attribute2.rs:43:6
+  --> $DIR/feature-gate-custom_attribute2.rs:36:6
    |
 LL | impl<#[lt_inherent] 'e> StLt<'e> { }
    |      ^^^^^^^^^^^^^^
@@ -71,7 +71,7 @@ LL | impl<#[lt_inherent] 'e> StLt<'e> { }
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
 error[E0658]: The attribute `ty_inherent` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
-  --> $DIR/feature-gate-custom_attribute2.rs:45:6
+  --> $DIR/feature-gate-custom_attribute2.rs:38:6
    |
 LL | impl<#[ty_inherent] M> StTy<M> { }
    |      ^^^^^^^^^^^^^^
@@ -79,7 +79,7 @@ LL | impl<#[ty_inherent] M> StTy<M> { }
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
 error[E0658]: The attribute `lt_impl_for` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
-  --> $DIR/feature-gate-custom_attribute2.rs:48:6
+  --> $DIR/feature-gate-custom_attribute2.rs:41:6
    |
 LL | impl<#[lt_impl_for] 'f> TrLt<'f> for StLt<'f> {
    |      ^^^^^^^^^^^^^^
@@ -87,7 +87,7 @@ LL | impl<#[lt_impl_for] 'f> TrLt<'f> for StLt<'f> {
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
 error[E0658]: The attribute `ty_impl_for` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
-  --> $DIR/feature-gate-custom_attribute2.rs:52:6
+  --> $DIR/feature-gate-custom_attribute2.rs:45:6
    |
 LL | impl<#[ty_impl_for] N> TrTy<N> for StTy<N> {
    |      ^^^^^^^^^^^^^^
@@ -95,7 +95,7 @@ LL | impl<#[ty_impl_for] N> TrTy<N> for StTy<N> {
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
 error[E0658]: The attribute `lt_fn` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
-  --> $DIR/feature-gate-custom_attribute2.rs:57:9
+  --> $DIR/feature-gate-custom_attribute2.rs:50:9
    |
 LL | fn f_lt<#[lt_fn] 'g>(_: &'g [u32]) -> &'g u32 { loop { } }
    |         ^^^^^^^^
@@ -103,7 +103,7 @@ LL | fn f_lt<#[lt_fn] 'g>(_: &'g [u32]) -> &'g u32 { loop { } }
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
 error[E0658]: The attribute `ty_fn` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
-  --> $DIR/feature-gate-custom_attribute2.rs:59:9
+  --> $DIR/feature-gate-custom_attribute2.rs:52:9
    |
 LL | fn f_ty<#[ty_fn] O>(_: O) { }
    |         ^^^^^^^^
@@ -111,7 +111,7 @@ LL | fn f_ty<#[ty_fn] O>(_: O) { }
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
 error[E0658]: The attribute `lt_meth` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
-  --> $DIR/feature-gate-custom_attribute2.rs:63:13
+  --> $DIR/feature-gate-custom_attribute2.rs:56:13
    |
 LL |     fn m_lt<#[lt_meth] 'h>(_: &'h [u32]) -> &'h u32 { loop { } }
    |             ^^^^^^^^^^
@@ -119,7 +119,7 @@ LL |     fn m_lt<#[lt_meth] 'h>(_: &'h [u32]) -> &'h u32 { loop { } }
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
 error[E0658]: The attribute `ty_meth` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
-  --> $DIR/feature-gate-custom_attribute2.rs:65:13
+  --> $DIR/feature-gate-custom_attribute2.rs:58:13
    |
 LL |     fn m_ty<#[ty_meth] P>(_: P) { }
    |             ^^^^^^^^^^
@@ -127,7 +127,7 @@ LL |     fn m_ty<#[ty_meth] P>(_: P) { }
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
 error[E0658]: The attribute `lt_hof` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
-  --> $DIR/feature-gate-custom_attribute2.rs:70:19
+  --> $DIR/feature-gate-custom_attribute2.rs:63:19
    |
 LL |     where Q: for <#[lt_hof] 'i> Fn(&'i [u32]) -> &'i u32
    |                   ^^^^^^^^^
diff --git a/src/test/ui/feature-gate-generic_param_attrs.rs b/src/test/ui/feature-gate-generic_param_attrs.rs
deleted file mode 100644 (file)
index 944802f..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// This test ensures that attributes on formals in generic parameter
-// lists are rejected if feature(generic_param_attrs) is not enabled.
-//
-// (We are prefixing all tested features with `rustc_`, to ensure that
-// the attributes themselves won't be rejected by the compiler when
-// using `rustc_attrs` feature. There is a separate compile-fail/ test
-// ensuring that the attribute feature-gating works in this context.)
-
-#![feature(rustc_attrs)]
-#![allow(dead_code)]
-
-struct StLt<#[rustc_lt_struct] 'a>(&'a u32);
-//~^ ERROR attributes on lifetime bindings are experimental (see issue #34761)
-struct StTy<#[rustc_ty_struct] I>(I);
-//~^ ERROR attributes on type parameter bindings are experimental (see issue #34761)
-
-enum EnLt<#[rustc_lt_enum] 'b> { A(&'b u32), B }
-//~^ ERROR attributes on lifetime bindings are experimental (see issue #34761)
-enum EnTy<#[rustc_ty_enum] J> { A(J), B }
-//~^ ERROR attributes on type parameter bindings are experimental (see issue #34761)
-
-trait TrLt<#[rustc_lt_trait] 'c> { fn foo(&self, _: &'c [u32]) -> &'c u32; }
-//~^ ERROR attributes on lifetime bindings are experimental (see issue #34761)
-trait TrTy<#[rustc_ty_trait] K> { fn foo(&self, _: K); }
-//~^ ERROR attributes on type parameter bindings are experimental (see issue #34761)
-
-type TyLt<#[rustc_lt_type] 'd> = &'d u32;
-//~^ ERROR attributes on lifetime bindings are experimental (see issue #34761)
-type TyTy<#[rustc_ty_type] L> = (L, );
-//~^ ERROR attributes on type parameter bindings are experimental (see issue #34761)
-
-impl<#[rustc_lt_inherent] 'e> StLt<'e> { }
-//~^ ERROR attributes on lifetime bindings are experimental (see issue #34761)
-impl<#[rustc_ty_inherent] M> StTy<M> { }
-//~^ ERROR attributes on type parameter bindings are experimental (see issue #34761)
-
-impl<#[rustc_lt_impl_for] 'f> TrLt<'f> for StLt<'f> {
-    //~^ ERROR attributes on lifetime bindings are experimental (see issue #34761)
-    fn foo(&self, _: &'f [u32]) -> &'f u32 { loop { } }
-}
-impl<#[rustc_ty_impl_for] N> TrTy<N> for StTy<N> {
-    //~^ ERROR attributes on type parameter bindings are experimental (see issue #34761)
-    fn foo(&self, _: N) { }
-}
-
-fn f_lt<#[rustc_lt_fn] 'g>(_: &'g [u32]) -> &'g u32 { loop { } }
-//~^ ERROR attributes on lifetime bindings are experimental (see issue #34761)
-fn f_ty<#[rustc_ty_fn] O>(_: O) { }
-//~^ ERROR attributes on type parameter bindings are experimental (see issue #34761)
-
-impl<I> StTy<I> {
-    fn m_lt<#[rustc_lt_meth] 'h>(_: &'h [u32]) -> &'h u32 { loop { } }
-    //~^ ERROR attributes on lifetime bindings are experimental (see issue #34761)
-    fn m_ty<#[rustc_ty_meth] P>(_: P) { }
-    //~^ ERROR attributes on type parameter bindings are experimental (see issue #34761)
-}
-
-fn hof_lt<Q>(_: Q)
-    where Q: for <#[rustc_lt_hof] 'i> Fn(&'i [u32]) -> &'i u32
-    //~^ ERROR attributes on lifetime bindings are experimental (see issue #34761)
-{
-}
-
-fn main() {
-
-}
diff --git a/src/test/ui/feature-gate-generic_param_attrs.stderr b/src/test/ui/feature-gate-generic_param_attrs.stderr
deleted file mode 100644 (file)
index 7b44924..0000000
+++ /dev/null
@@ -1,139 +0,0 @@
-error[E0658]: attributes on lifetime bindings are experimental (see issue #34761)
-  --> $DIR/feature-gate-generic_param_attrs.rs:22:13
-   |
-LL | struct StLt<#[rustc_lt_struct] 'a>(&'a u32);
-   |             ^^^^^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(generic_param_attrs)] to the crate attributes to enable
-
-error[E0658]: attributes on type parameter bindings are experimental (see issue #34761)
-  --> $DIR/feature-gate-generic_param_attrs.rs:24:13
-   |
-LL | struct StTy<#[rustc_ty_struct] I>(I);
-   |             ^^^^^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(generic_param_attrs)] to the crate attributes to enable
-
-error[E0658]: attributes on lifetime bindings are experimental (see issue #34761)
-  --> $DIR/feature-gate-generic_param_attrs.rs:27:11
-   |
-LL | enum EnLt<#[rustc_lt_enum] 'b> { A(&'b u32), B }
-   |           ^^^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(generic_param_attrs)] to the crate attributes to enable
-
-error[E0658]: attributes on type parameter bindings are experimental (see issue #34761)
-  --> $DIR/feature-gate-generic_param_attrs.rs:29:11
-   |
-LL | enum EnTy<#[rustc_ty_enum] J> { A(J), B }
-   |           ^^^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(generic_param_attrs)] to the crate attributes to enable
-
-error[E0658]: attributes on lifetime bindings are experimental (see issue #34761)
-  --> $DIR/feature-gate-generic_param_attrs.rs:32:12
-   |
-LL | trait TrLt<#[rustc_lt_trait] 'c> { fn foo(&self, _: &'c [u32]) -> &'c u32; }
-   |            ^^^^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(generic_param_attrs)] to the crate attributes to enable
-
-error[E0658]: attributes on type parameter bindings are experimental (see issue #34761)
-  --> $DIR/feature-gate-generic_param_attrs.rs:34:12
-   |
-LL | trait TrTy<#[rustc_ty_trait] K> { fn foo(&self, _: K); }
-   |            ^^^^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(generic_param_attrs)] to the crate attributes to enable
-
-error[E0658]: attributes on lifetime bindings are experimental (see issue #34761)
-  --> $DIR/feature-gate-generic_param_attrs.rs:37:11
-   |
-LL | type TyLt<#[rustc_lt_type] 'd> = &'d u32;
-   |           ^^^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(generic_param_attrs)] to the crate attributes to enable
-
-error[E0658]: attributes on type parameter bindings are experimental (see issue #34761)
-  --> $DIR/feature-gate-generic_param_attrs.rs:39:11
-   |
-LL | type TyTy<#[rustc_ty_type] L> = (L, );
-   |           ^^^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(generic_param_attrs)] to the crate attributes to enable
-
-error[E0658]: attributes on lifetime bindings are experimental (see issue #34761)
-  --> $DIR/feature-gate-generic_param_attrs.rs:42:6
-   |
-LL | impl<#[rustc_lt_inherent] 'e> StLt<'e> { }
-   |      ^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(generic_param_attrs)] to the crate attributes to enable
-
-error[E0658]: attributes on type parameter bindings are experimental (see issue #34761)
-  --> $DIR/feature-gate-generic_param_attrs.rs:44:6
-   |
-LL | impl<#[rustc_ty_inherent] M> StTy<M> { }
-   |      ^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(generic_param_attrs)] to the crate attributes to enable
-
-error[E0658]: attributes on lifetime bindings are experimental (see issue #34761)
-  --> $DIR/feature-gate-generic_param_attrs.rs:47:6
-   |
-LL | impl<#[rustc_lt_impl_for] 'f> TrLt<'f> for StLt<'f> {
-   |      ^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(generic_param_attrs)] to the crate attributes to enable
-
-error[E0658]: attributes on type parameter bindings are experimental (see issue #34761)
-  --> $DIR/feature-gate-generic_param_attrs.rs:51:6
-   |
-LL | impl<#[rustc_ty_impl_for] N> TrTy<N> for StTy<N> {
-   |      ^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(generic_param_attrs)] to the crate attributes to enable
-
-error[E0658]: attributes on lifetime bindings are experimental (see issue #34761)
-  --> $DIR/feature-gate-generic_param_attrs.rs:56:9
-   |
-LL | fn f_lt<#[rustc_lt_fn] 'g>(_: &'g [u32]) -> &'g u32 { loop { } }
-   |         ^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(generic_param_attrs)] to the crate attributes to enable
-
-error[E0658]: attributes on type parameter bindings are experimental (see issue #34761)
-  --> $DIR/feature-gate-generic_param_attrs.rs:58:9
-   |
-LL | fn f_ty<#[rustc_ty_fn] O>(_: O) { }
-   |         ^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(generic_param_attrs)] to the crate attributes to enable
-
-error[E0658]: attributes on lifetime bindings are experimental (see issue #34761)
-  --> $DIR/feature-gate-generic_param_attrs.rs:62:13
-   |
-LL |     fn m_lt<#[rustc_lt_meth] 'h>(_: &'h [u32]) -> &'h u32 { loop { } }
-   |             ^^^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(generic_param_attrs)] to the crate attributes to enable
-
-error[E0658]: attributes on type parameter bindings are experimental (see issue #34761)
-  --> $DIR/feature-gate-generic_param_attrs.rs:64:13
-   |
-LL |     fn m_ty<#[rustc_ty_meth] P>(_: P) { }
-   |             ^^^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(generic_param_attrs)] to the crate attributes to enable
-
-error[E0658]: attributes on lifetime bindings are experimental (see issue #34761)
-  --> $DIR/feature-gate-generic_param_attrs.rs:69:19
-   |
-LL |     where Q: for <#[rustc_lt_hof] 'i> Fn(&'i [u32]) -> &'i u32
-   |                   ^^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(generic_param_attrs)] to the crate attributes to enable
-
-error: aborting due to 17 previous errors
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gate-macros_in_extern.rs b/src/test/ui/feature-gate-macros_in_extern.rs
new file mode 100644 (file)
index 0000000..9c75824
--- /dev/null
@@ -0,0 +1,35 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(decl_macro)]
+
+macro_rules! returns_isize(
+    ($ident:ident) => (
+        fn $ident() -> isize;
+    )
+);
+
+macro takes_u32_returns_u32($ident:ident) {
+    fn $ident (arg: u32) -> u32;
+}
+
+macro_rules! emits_nothing(
+    () => ()
+);
+
+#[link(name = "rust_test_helpers", kind = "static")]
+extern {
+    returns_isize!(rust_get_test_int);
+    //~^ ERROR Macro invocations in `extern {}` blocks are experimental.
+    takes_u32_returns_u32!(rust_dbg_extern_identity_u32);
+    //~^ ERROR Macro invocations in `extern {}` blocks are experimental.
+    emits_nothing!();
+    //~^ ERROR Macro invocations in `extern {}` blocks are experimental.
+}
diff --git a/src/test/ui/feature-gate-macros_in_extern.stderr b/src/test/ui/feature-gate-macros_in_extern.stderr
new file mode 100644 (file)
index 0000000..49aca0d
--- /dev/null
@@ -0,0 +1,27 @@
+error[E0658]: Macro invocations in `extern {}` blocks are experimental. (see issue #49476)
+  --> $DIR/feature-gate-macros_in_extern.rs:29:5
+   |
+LL |     returns_isize!(rust_get_test_int);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(macros_in_extern)] to the crate attributes to enable
+
+error[E0658]: Macro invocations in `extern {}` blocks are experimental. (see issue #49476)
+  --> $DIR/feature-gate-macros_in_extern.rs:31:5
+   |
+LL |     takes_u32_returns_u32!(rust_dbg_extern_identity_u32);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(macros_in_extern)] to the crate attributes to enable
+
+error[E0658]: Macro invocations in `extern {}` blocks are experimental. (see issue #49476)
+  --> $DIR/feature-gate-macros_in_extern.rs:33:5
+   |
+LL |     emits_nothing!();
+   |     ^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(macros_in_extern)] to the crate attributes to enable
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
index ace9fe9ab2759154178ebca58c182d15902947a1..a67ece0448838291e91225b420a6b3c995e2c40b 100644 (file)
@@ -12,8 +12,6 @@
 
 // Check that `may_dangle` is rejected if `dropck_eyepatch` feature gate is absent.
 
-#![feature(generic_param_attrs)]
-
 struct Pt<A>(A);
 impl<#[may_dangle] A> Drop for Pt<A> {
     //~^ ERROR may_dangle has unstable semantics and may be removed in the future
index 85707f6e92127aecc6a1ba1f4d4aca118d3a684a..aad725dfe65ec974e137a0b71ef9bb9dd19a6e9c 100644 (file)
@@ -1,5 +1,5 @@
 error[E0658]: may_dangle has unstable semantics and may be removed in the future (see issue #34761)
-  --> $DIR/feature-gate-may-dangle.rs:18:6
+  --> $DIR/feature-gate-may-dangle.rs:16:6
    |
 LL | impl<#[may_dangle] A> Drop for Pt<A> {
    |      ^^^^^^^^^^^^^
index 69d7e38d431f4d89723a5bf2b4082ff49a57f5f0..a2853570d6d3fa1a04f11b6246d1ef723f829122 100644 (file)
@@ -1,8 +1,8 @@
 error[E0658]: non-ascii idents are not fully supported. (see issue #28979)
-  --> $DIR/feature-gate-non_ascii_idents.rs:11:1
+  --> $DIR/feature-gate-non_ascii_idents.rs:11:22
    |
 LL | extern crate core as bäz; //~ ERROR non-ascii idents
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                      ^^^
    |
    = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
 
@@ -10,29 +10,23 @@ error[E0658]: non-ascii idents are not fully supported. (see issue #28979)
   --> $DIR/feature-gate-non_ascii_idents.rs:13:5
    |
 LL | use föö::bar; //~ ERROR non-ascii idents
-   |     ^^^^^^^^
+   |     ^^^
    |
    = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
 
 error[E0658]: non-ascii idents are not fully supported. (see issue #28979)
-  --> $DIR/feature-gate-non_ascii_idents.rs:15:1
+  --> $DIR/feature-gate-non_ascii_idents.rs:15:5
    |
 LL | mod föö { //~ ERROR non-ascii idents
-   | ^^^^^^^
+   |     ^^^
    |
    = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
 
 error[E0658]: non-ascii idents are not fully supported. (see issue #28979)
-  --> $DIR/feature-gate-non_ascii_idents.rs:19:1
+  --> $DIR/feature-gate-non_ascii_idents.rs:19:4
    |
-LL | / fn bär( //~ ERROR non-ascii idents
-LL | |     bäz: isize //~ ERROR non-ascii idents
-LL | |     ) {
-LL | |     let _ö: isize; //~ ERROR non-ascii idents
-...  |
-LL | |     }
-LL | | }
-   | |_^
+LL | fn bär( //~ ERROR non-ascii idents
+   |    ^^^
    |
    = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
 
@@ -61,10 +55,10 @@ LL |         (_ä, _) => {} //~ ERROR non-ascii idents
    = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
 
 error[E0658]: non-ascii idents are not fully supported. (see issue #28979)
-  --> $DIR/feature-gate-non_ascii_idents.rs:29:1
+  --> $DIR/feature-gate-non_ascii_idents.rs:29:8
    |
 LL | struct Föö { //~ ERROR non-ascii idents
-   | ^^^^^^^^^^
+   |        ^^^
    |
    = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
 
@@ -72,15 +66,15 @@ error[E0658]: non-ascii idents are not fully supported. (see issue #28979)
   --> $DIR/feature-gate-non_ascii_idents.rs:30:5
    |
 LL |     föö: isize //~ ERROR non-ascii idents
-   |     ^^^^^^^^^^
+   |     ^^^
    |
    = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
 
 error[E0658]: non-ascii idents are not fully supported. (see issue #28979)
-  --> $DIR/feature-gate-non_ascii_idents.rs:33:1
+  --> $DIR/feature-gate-non_ascii_idents.rs:33:6
    |
 LL | enum Bär { //~ ERROR non-ascii idents
-   | ^^^^^^^^
+   |      ^^^
    |
    = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
 
@@ -96,15 +90,15 @@ error[E0658]: non-ascii idents are not fully supported. (see issue #28979)
   --> $DIR/feature-gate-non_ascii_idents.rs:35:9
    |
 LL |         qüx: isize //~ ERROR non-ascii idents
-   |         ^^^^^^^^^^
+   |         ^^^
    |
    = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
 
 error[E0658]: non-ascii idents are not fully supported. (see issue #28979)
-  --> $DIR/feature-gate-non_ascii_idents.rs:40:5
+  --> $DIR/feature-gate-non_ascii_idents.rs:40:8
    |
 LL |     fn qüx();  //~ ERROR non-ascii idents
-   |     ^^^^^^^^^
+   |        ^^^
    |
    = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
 
diff --git a/src/test/ui/generic-param-attrs.rs b/src/test/ui/generic-param-attrs.rs
new file mode 100644 (file)
index 0000000..37fabcd
--- /dev/null
@@ -0,0 +1,54 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// This test previously ensured that attributes on formals in generic parameter
+// lists are rejected without a feature gate.
+//
+// (We are prefixing all tested features with `rustc_`, to ensure that
+// the attributes themselves won't be rejected by the compiler when
+// using `rustc_attrs` feature. There is a separate compile-fail/ test
+// ensuring that the attribute feature-gating works in this context.)
+
+// must-compile-successfully
+
+#![feature(rustc_attrs)]
+#![allow(dead_code)]
+
+struct StLt<#[rustc_lt_struct] 'a>(&'a u32);
+struct StTy<#[rustc_ty_struct] I>(I);
+enum EnLt<#[rustc_lt_enum] 'b> { A(&'b u32), B }
+enum EnTy<#[rustc_ty_enum] J> { A(J), B }
+trait TrLt<#[rustc_lt_trait] 'c> { fn foo(&self, _: &'c [u32]) -> &'c u32; }
+trait TrTy<#[rustc_ty_trait] K> { fn foo(&self, _: K); }
+type TyLt<#[rustc_lt_type] 'd> = &'d u32;
+type TyTy<#[rustc_ty_type] L> = (L, );
+
+impl<#[rustc_lt_inherent] 'e> StLt<'e> { }
+impl<#[rustc_ty_inherent] M> StTy<M> { }
+impl<#[rustc_lt_impl_for] 'f> TrLt<'f> for StLt<'f> {
+    fn foo(&self, _: &'f [u32]) -> &'f u32 { loop { } }
+}
+impl<#[rustc_ty_impl_for] N> TrTy<N> for StTy<N> {
+    fn foo(&self, _: N) { }
+}
+
+fn f_lt<#[rustc_lt_fn] 'g>(_: &'g [u32]) -> &'g u32 { loop { } }
+fn f_ty<#[rustc_ty_fn] O>(_: O) { }
+
+impl<I> StTy<I> {
+    fn m_lt<#[rustc_lt_meth] 'h>(_: &'h [u32]) -> &'h u32 { loop { } }
+    fn m_ty<#[rustc_ty_meth] P>(_: P) { }
+}
+
+fn hof_lt<Q>(_: Q)
+    where Q: for <#[rustc_lt_hof] 'i> Fn(&'i [u32]) -> &'i u32
+{}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/universal-issue-48703.rs b/src/test/ui/impl-trait/universal-issue-48703.rs
new file mode 100644 (file)
index 0000000..e017b37
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(universal_impl_trait)]
+
+use std::fmt::Debug;
+
+fn foo<T>(x: impl Debug) { }
+
+fn main() {
+    foo::<String>('a'); //~ ERROR cannot provide explicit type parameters
+}
diff --git a/src/test/ui/impl-trait/universal-issue-48703.stderr b/src/test/ui/impl-trait/universal-issue-48703.stderr
new file mode 100644 (file)
index 0000000..ea50968
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0632]: cannot provide explicit type parameters when `impl Trait` is used in argument position.
+  --> $DIR/universal-issue-48703.rs:18:5
+   |
+LL |     foo::<String>('a'); //~ ERROR cannot provide explicit type parameters
+   |     ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0632`.
diff --git a/src/test/ui/issue-48728.rs b/src/test/ui/issue-48728.rs
new file mode 100644 (file)
index 0000000..251ebf5
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Regression test for #48728, an ICE that occurred computing
+// coherence "help" information.
+
+#[derive(Clone)] //~ ERROR conflicting implementations of trait `std::clone::Clone`
+struct Node<T: ?Sized>(Box<T>);
+
+impl<T: Clone + ?Sized> Clone for Node<[T]> {
+    fn clone(&self) -> Self {
+        Node(Box::clone(&self.0))
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issue-48728.stderr b/src/test/ui/issue-48728.stderr
new file mode 100644 (file)
index 0000000..05c87fe
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0119]: conflicting implementations of trait `std::clone::Clone` for type `Node<[_]>`:
+  --> $DIR/issue-48728.rs:14:10
+   |
+LL | #[derive(Clone)] //~ ERROR conflicting implementations of trait `std::clone::Clone`
+   |          ^^^^^ conflicting implementation for `Node<[_]>`
+...
+LL | impl<T: Clone + ?Sized> Clone for Node<[T]> {
+   | ------------------------------------------- first implementation here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
index 2780b34746378ac33b4736c8a856aad4bfe97621..55c9f5de302052df25abb0c5891170e737a0d94f 100644 (file)
@@ -17,7 +17,6 @@
 
 #![allow(warnings)]
 #![feature(dropck_eyepatch)]
-#![feature(generic_param_attrs)]
 
 fn use_x(_: usize) -> bool { true }
 
index 3d9a5456cbb3666972e79e19cbda3513f513b9ec..e5478e39fecca9e3dddf2a394371d48ea55d8237 100644 (file)
@@ -17,7 +17,6 @@
 
 #![allow(warnings)]
 #![feature(dropck_eyepatch)]
-#![feature(generic_param_attrs)]
 
 fn use_x(_: usize) -> bool { true }
 
index 6454413901bec8f63003303e9d7832403ca186c1..a35271bdcfeff81c5b66b4e748f10f4e8e889a22 100644 (file)
@@ -1,5 +1,5 @@
 error[E0506]: cannot assign to `v[..]` because it is borrowed
-  --> $DIR/drop-no-may-dangle.rs:31:9
+  --> $DIR/drop-no-may-dangle.rs:30:9
    |
 LL |     let p: WrapMayNotDangle<&usize> = WrapMayNotDangle { value: &v[0] };
    |                                                                 ----- borrow of `v[..]` occurs here
@@ -11,7 +11,7 @@ LL | }
    | - borrow later used here, when `p` is dropped
 
 error[E0506]: cannot assign to `v[..]` because it is borrowed
-  --> $DIR/drop-no-may-dangle.rs:34:5
+  --> $DIR/drop-no-may-dangle.rs:33:5
    |
 LL |     let p: WrapMayNotDangle<&usize> = WrapMayNotDangle { value: &v[0] };
    |                                                                 ----- borrow of `v[..]` occurs here
diff --git a/src/test/ui/nll/issue-47388.rs b/src/test/ui/nll/issue-47388.rs
new file mode 100644 (file)
index 0000000..39feea0
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+#![feature(nll)]
+struct FancyNum {
+    num: u8,
+}
+
+fn main() {
+    let mut fancy = FancyNum{ num: 5 };
+    let fancy_ref = &(&mut fancy);
+    fancy_ref.num = 6; //~ ERROR E0594
+    println!("{}", fancy_ref.num);
+}
diff --git a/src/test/ui/nll/issue-47388.stderr b/src/test/ui/nll/issue-47388.stderr
new file mode 100644 (file)
index 0000000..272cb65
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0594]: cannot assign to data in a `&` reference
+  --> $DIR/issue-47388.rs:18:5
+   |
+LL |     let fancy_ref = &(&mut fancy);
+   |                     ------------- help: consider changing this to be a mutable reference: `&mut`
+LL |     fancy_ref.num = 6; //~ ERROR E0594
+   |     ^^^^^^^^^^^^^^^^^ `fancy_ref` is a `&` reference, so the data it refers to cannot be written
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/rfc-2005-default-binding-mode/borrowck-issue-49631.rs b/src/test/ui/rfc-2005-default-binding-mode/borrowck-issue-49631.rs
new file mode 100644 (file)
index 0000000..8dc1627
--- /dev/null
@@ -0,0 +1,34 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+pub struct Foo {
+}
+
+impl Foo {
+    fn get(&self) -> Option<&Result<String, String>> {
+        None
+    }
+
+    fn mutate(&mut self) { }
+}
+
+fn main() {
+    let mut foo = Foo { };
+
+    // foo.get() returns type Option<&Result<String, String>>, so
+    // using `string` keeps borrow of `foo` alive. Hence calling
+    // `foo.mutate()` should be an error.
+    while let Some(Ok(string)) = foo.get() {
+        foo.mutate();
+        //~^ ERROR cannot borrow `foo` as mutable
+        println!("foo={:?}", *string);
+    }
+}
diff --git a/src/test/ui/rfc-2005-default-binding-mode/borrowck-issue-49631.stderr b/src/test/ui/rfc-2005-default-binding-mode/borrowck-issue-49631.stderr
new file mode 100644 (file)
index 0000000..2da5ac8
--- /dev/null
@@ -0,0 +1,13 @@
+error[E0502]: cannot borrow `foo` as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-issue-49631.rs:30:9
+   |
+LL |     while let Some(Ok(string)) = foo.get() {
+   |                                  ---     - immutable borrow ends here
+   |                                  |
+   |                                  immutable borrow occurs here
+LL |         foo.mutate();
+   |         ^^^ mutable borrow occurs here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0502`.
index 49b054f8b9e504c1cddc00dacde3cf5554dde7d3..9f2389292158b8070fe6eb8da4d942ebe9b3e349 100644 (file)
     "sparc-unknown-linux-gnu",
     "sparc64-unknown-linux-gnu",
     "sparcv9-sun-solaris",
+    "thumbv6m-none-eabi",
+    "thumbv7em-none-eabi",
+    "thumbv7em-none-eabihf",
+    "thumbv7m-none-eabi",
     "wasm32-unknown-emscripten",
     "wasm32-unknown-unknown",
     "x86_64-apple-darwin",
@@ -356,6 +360,28 @@ fn build_manifest(&mut self) -> Manifest {
                 target: "*".to_string(),
             });
 
+            // If the components/extensions don't actually exist for this
+            // particular host/target combination then nix it entirely from our
+            // lists.
+            {
+                let has_component = |c: &Component| {
+                    if c.target == "*" {
+                        return true
+                    }
+                    let pkg = match manifest.pkg.get(&c.pkg) {
+                        Some(p) => p,
+                        None => return false,
+                    };
+                    let target = match pkg.target.get(&c.target) {
+                        Some(t) => t,
+                        None => return false,
+                    };
+                    target.available
+                };
+                extensions.retain(&has_component);
+                components.retain(&has_component);
+            }
+
             pkg.target.insert(host.to_string(), Target {
                 available: true,
                 url: Some(self.url(&filename)),
index 1d8cef05b7dd3408f0e330c0cd529d8f49a89faf..41fc67a66f47df828fd6f380c9c8e8607a78f57e 100644 (file)
@@ -95,6 +95,26 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
+#[derive(Clone)]
+pub enum CompareMode {
+    Nll
+}
+
+impl CompareMode {
+    fn to_str(&self) -> &'static str {
+        match *self {
+            CompareMode::Nll => "nll"
+        }
+    }
+
+    pub fn parse(s: String) -> CompareMode {
+        match s.as_str() {
+            "nll" => CompareMode::Nll,
+            x => panic!("unknown --compare-mode option: {}", x),
+        }
+    }
+}
+
 #[derive(Clone)]
 pub struct Config {
     /// The library paths required for running the compiler
@@ -210,6 +230,9 @@ pub struct Config {
     /// where to find the remote test client process, if we're using it
     pub remote_test_client: Option<PathBuf>,
 
+    /// mode describing what file the actual ui output will be compared to
+    pub compare_mode: Option<CompareMode>,
+
     // Configuration for various run-make tests frobbing things like C compilers
     // or querying about various LLVM component information.
     pub cc: String,
@@ -230,12 +253,19 @@ pub struct TestPaths {
 }
 
 /// Used by `ui` tests to generate things like `foo.stderr` from `foo.rs`.
-pub fn expected_output_path(testpaths: &TestPaths, revision: Option<&str>, kind: &str) -> PathBuf {
+pub fn expected_output_path(testpaths: &TestPaths,
+                            revision: Option<&str>,
+                            compare_mode: &Option<CompareMode>,
+                            kind: &str) -> PathBuf {
+
     assert!(UI_EXTENSIONS.contains(&kind));
-    let extension = match revision {
-        Some(r) => format!("{}.{}", r, kind),
-        None => kind.to_string(),
-    };
+    let mut parts = Vec::new();
+
+    if let Some(x) = revision { parts.push(x); }
+    if let Some(ref x) = *compare_mode { parts.push(x.to_str()); }
+    parts.push(kind);
+
+    let extension = parts.join(".");
     testpaths.file.with_extension(extension)
 }
 
index e65c03a6e571c1adbc39237ac4ffaa4bb963184d..80cab96434ba784fa2679228d56a0c6d390b54e0 100644 (file)
@@ -38,6 +38,7 @@
 use common::{Config, TestPaths};
 use common::{DebugInfoGdb, DebugInfoLldb, Mode, Pretty};
 use common::{expected_output_path, UI_EXTENSIONS};
+use common::CompareMode;
 use test::ColorConfig;
 use util::logv;
 
@@ -227,6 +228,12 @@ pub fn parse_config(args: Vec<String>) -> Config {
             "path to the remote test client",
             "PATH",
         )
+        .optopt(
+            "",
+            "compare-mode",
+            "mode describing what file the actual ui output will be compared to",
+            "COMPARE MODE"
+        )
         .optflag("h", "help", "show this message");
 
     let (argv0, args_) = args.split_first().unwrap();
@@ -320,6 +327,7 @@ fn make_absolute(path: PathBuf) -> PathBuf {
         quiet: matches.opt_present("quiet"),
         color,
         remote_test_client: matches.opt_str("remote-test-client").map(PathBuf::from),
+        compare_mode: matches.opt_str("compare-mode").map(CompareMode::parse),
 
         cc: matches.opt_str("cc").unwrap(),
         cxx: matches.opt_str("cxx").unwrap(),
@@ -615,7 +623,8 @@ pub fn make_test(config: &Config, testpaths: &TestPaths) -> test::TestDescAndFn
     };
 
     // Debugging emscripten code doesn't make sense today
-    let ignore = early_props.ignore || !up_to_date(config, testpaths, &early_props)
+    let ignore = early_props.ignore
+        || (!up_to_date(config, testpaths, &early_props) && config.compare_mode.is_none())
         || (config.mode == DebugInfoGdb || config.mode == DebugInfoLldb)
             && config.target.contains("emscripten");
 
@@ -688,12 +697,15 @@ fn up_to_date(config: &Config, testpaths: &TestPaths, props: &EarlyProps) -> boo
     // UI test files.
     for extension in UI_EXTENSIONS {
         for revision in &props.revisions {
-            let path = &expected_output_path(testpaths, Some(revision), extension);
+            let path = &expected_output_path(testpaths,
+                                             Some(revision),
+                                             &config.compare_mode,
+                                             extension);
             inputs.push(mtime(path));
         }
 
         if props.revisions.is_empty() {
-            let path = &expected_output_path(testpaths, None, extension);
+            let path = &expected_output_path(testpaths, None, &config.compare_mode, extension);
             inputs.push(mtime(path));
         }
     }
index e826c5366a81f736828b5f12496815e130eb4fb4..0081c0ae69d6762dfa95971de225c82989dd6184 100644 (file)
@@ -13,6 +13,7 @@
 use common::{Codegen, CodegenUnits, DebugInfoGdb, DebugInfoLldb, Rustdoc};
 use common::{Incremental, MirOpt, RunMake, Ui};
 use common::{expected_output_path, UI_STDERR, UI_STDOUT};
+use common::CompareMode;
 use diff;
 use errors::{self, Error, ErrorKind};
 use filetime::FileTime;
@@ -1683,6 +1684,13 @@ fn make_compile_args(&self, input_file: &Path, output_file: TargetLocation) -> C
             }
         }
 
+        match self.config.compare_mode {
+            Some(CompareMode::Nll) => {
+                rustc.args(&["-Znll", "-Zborrowck=mir", "-Ztwo-phase-borrows"]);
+            },
+            None => {},
+        }
+
         if self.props.force_host {
             rustc.args(self.split_maybe_args(&self.config.host_rustcflags));
         } else {
@@ -2505,11 +2513,8 @@ fn run_ui_test(&self) {
         let proc_res = self.compile_test();
         self.check_if_test_should_compile(&proc_res);
 
-        let expected_stderr_path = self.expected_output_path(UI_STDERR);
-        let expected_stderr = self.load_expected_output(&expected_stderr_path);
-
-        let expected_stdout_path = self.expected_output_path(UI_STDOUT);
-        let expected_stdout = self.load_expected_output(&expected_stdout_path);
+        let expected_stderr = self.load_expected_output(UI_STDERR);
+        let expected_stdout = self.load_expected_output(UI_STDOUT);
 
         let normalized_stdout =
             self.normalize_output(&proc_res.stdout, &self.props.normalize_stdout);
@@ -2552,7 +2557,7 @@ fn run_ui_test(&self) {
                 self.fatal_proc_rec("test run failed!", &proc_res);
             }
         }
-        if !explicit {
+        if !explicit && self.config.compare_mode.is_none() {
             if !expected_errors.is_empty() || !proc_res.status.success() {
                 // "// error-pattern" comments
                 self.check_expected_errors(expected_errors, &proc_res);
@@ -2795,19 +2800,32 @@ fn normalize_output(&self, output: &str, custom_rules: &[(String, String)]) -> S
         normalized
     }
 
-    fn expected_output_path(&self, kind: &str) -> PathBuf {
-        expected_output_path(&self.testpaths, self.revision, kind)
-    }
+    fn load_expected_output(&self, kind: &str) -> String {
+        let mut path = expected_output_path(&self.testpaths,
+                                            self.revision,
+                                            &self.config.compare_mode,
+                                            kind);
 
-    fn load_expected_output(&self, path: &Path) -> String {
-        if !path.exists() {
-            return String::new();
+        if !path.exists() && self.config.compare_mode.is_some() {
+            // fallback!
+            path = expected_output_path(&self.testpaths, self.revision, &None, kind);
         }
 
+        if path.exists() {
+            match self.load_expected_output_from_path(&path) {
+                Ok(x) => x,
+                Err(x) => self.fatal(&x),
+            }
+        } else {
+            String::new()
+        }
+    }
+
+    fn load_expected_output_from_path(&self, path: &Path) -> Result<String, String> {
         let mut result = String::new();
         match File::open(path).and_then(|mut f| f.read_to_string(&mut result)) {
-            Ok(_) => result,
-            Err(e) => self.fatal(&format!(
+            Ok(_) => Ok(result),
+            Err(e) => Err(format!(
                 "failed to load expected output from `{}`: {}",
                 path.display(),
                 e
index 539b434e9eca554c9dc9d52a130e4d3dfbde28ef..554e3c0cd5f0bbd4771d57a69295829fbaba6bb5 100644 (file)
@@ -8,5 +8,6 @@ license = "MIT/Apache-2.0"
 clap = "2.25.0"
 
 [dependencies.mdbook]
-version = "0.1.2"
+version = "0.1.5"
 default-features = false
+features = ["search"]
index e726dea84f103d65d97e0f8503abde4a0111e1ab..7aca765cead8c48f8794901cf33813ba199e9fca 100644 (file)
@@ -9,6 +9,8 @@
 // except according to those terms.
 
 #![feature(link_args)]
+
+#[allow(unused_attributes)]
 // Set the stack size at link time on Windows. See rustc_driver::in_rustc_thread
 // for the rationale.
 #[cfg_attr(all(windows, target_env = "msvc"), link_args = "/STACK:16777216")]
index a4462d18bf6b92aaec1eeb1c30d5ddf94a3ca987..e784712f09d4978b5331ceaf96476bcf4b1b0b1b 160000 (submodule)
@@ -1 +1 @@
-Subproject commit a4462d18bf6b92aaec1eeb1c30d5ddf94a3ca987
+Subproject commit e784712f09d4978b5331ceaf96476bcf4b1b0b1b
index 06eb055f68e060e179014984c78e68bcaa011bbf..fa2274366401445737932941c876e0df8b26232d 100644 (file)
@@ -13,8 +13,6 @@
 //! This library contains the tidy lints and exposes it
 //! to be used by tools.
 
-#![deny(warnings)]
-
 extern crate serde;
 extern crate serde_json;
 #[macro_use]